First working version.
This commit is contained in:
87
src/salvium_tipbot_commands.php
Normal file
87
src/salvium_tipbot_commands.php
Normal file
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
use Salvium\SalviumTipBotDB;
|
||||
use Salvium\SalviumWallet;
|
||||
|
||||
class SalviumTipBotCommands {
|
||||
private SalviumTipBotDB $db;
|
||||
private SalviumWallet $wallet;
|
||||
|
||||
public function __construct(SalviumTipBotDB $db, SalviumWallet $wallet) {
|
||||
$this->db = $db;
|
||||
$this->wallet = $wallet;
|
||||
}
|
||||
|
||||
public function handle(string $command, array $args, array $context): void {
|
||||
$method = 'cmd_' . ltrim($command, '/');
|
||||
if (method_exists($this, $method)) {
|
||||
$response = $this->$method($args, $context);
|
||||
} else {
|
||||
//$response = "Unknown command.";
|
||||
$response = "";
|
||||
}
|
||||
|
||||
sendMessage($context['chat_id'], $response);
|
||||
$this->db->logMessage($context['chat_id'], $context['chat_name'], $context['username'], $context['raw'], $response);
|
||||
}
|
||||
|
||||
private function cmd_start(array $args, array $ctx): string {
|
||||
if (!empty($ctx['username'])) {
|
||||
$this->db->updateUsername($ctx['user_id'], $ctx['username']);
|
||||
}
|
||||
return "Welcome to the Salvium Tip Bot! Use /deposit to get started.";
|
||||
}
|
||||
|
||||
private function cmd_deposit(array $args, array $ctx): string {
|
||||
$user = $this->db->getUserByTelegramId($ctx['user_id']);
|
||||
if (!$user) {
|
||||
$sub = $this->wallet->getNewSubaddress();
|
||||
if (!$sub) return "Error generating subaddress.";
|
||||
$this->db->createUser($ctx['user_id'], $sub);
|
||||
if (!empty($ctx['username'])) {
|
||||
$this->db->updateUsername($ctx['user_id'], $ctx['username']);
|
||||
}
|
||||
return "Your deposit address: $sub";
|
||||
}
|
||||
return "Your deposit address: {$user['salvium_subaddress']}";
|
||||
}
|
||||
|
||||
private function cmd_balance(array $args, array $ctx): string {
|
||||
$user = $this->db->getUserByTelegramId($ctx['user_id']);
|
||||
return $user ? "Your balance: {$user['tip_balance']} SAL" : "No account found. Use /deposit first.";
|
||||
}
|
||||
|
||||
private function cmd_withdraw(array $args, array $ctx): string {
|
||||
if (count($args) < 3) return "Usage: /withdraw <address> <amount>";
|
||||
|
||||
list(, $address, $amount) = $args;
|
||||
$amount = (float) $amount;
|
||||
$user = $this->db->getUserByTelegramId($ctx['user_id']);
|
||||
|
||||
if (!$user || $user['tip_balance'] < $amount) return "Insufficient balance or invalid account.";
|
||||
if (!isValidSalviumAddress($address)) return "Invalid SAL address format.";
|
||||
|
||||
$this->db->updateUserTipBalance($user['id'], $amount, 'subtract');
|
||||
$this->db->logWithdrawal($user['id'], $address, $amount);
|
||||
return "Withdrawal request submitted. Processing soon.";
|
||||
}
|
||||
|
||||
|
||||
private function cmd_tip(array $args, array $ctx): string {
|
||||
if (count($args) < 3) return "Usage: /tip <username> <amount>";
|
||||
|
||||
list(, $targetUsername, $amount) = $args;
|
||||
$amount = (float)$amount;
|
||||
$sender = $this->db->getUserByTelegramId($ctx['user_id']);
|
||||
$recipient = $this->db->getUserByUsername(ltrim($targetUsername, '@'));
|
||||
|
||||
if (!$sender || $sender['tip_balance'] < $amount) return "Insufficient funds or invalid sender.";
|
||||
if (!$recipient) return "Recipient not found. Ask them to run /start first.";
|
||||
|
||||
$this->db->updateUserTipBalance($sender['id'], $amount, 'subtract');
|
||||
$this->db->addTip($sender['id'], $recipient['id'], $amount, $ctx['chat_id']);
|
||||
sendMessage($recipient['telegram_user_id'], "You received a tip of {$amount} SAL! Use /balance to check.");
|
||||
|
||||
return "Tipped {$targetUsername} {$amount} SAL successfully!";
|
||||
}
|
||||
}
|
||||
?>
|
||||
24
src/salvium_tipbot_common.php
Normal file
24
src/salvium_tipbot_common.php
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
function sendMessage(int $chatId, string $text, array $options = []): void {
|
||||
global $config;
|
||||
$url = "https://api.telegram.org/bot{$config['TELEGRAM_BOT_TOKEN']}/sendMessage";
|
||||
$payload = array_merge(['chat_id' => $chatId, 'text' => $text], $options);
|
||||
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($payload));
|
||||
if (!empty($config['IPV4_ONLY'])) {
|
||||
curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
|
||||
}
|
||||
curl_exec($ch);
|
||||
curl_close($ch);
|
||||
}
|
||||
|
||||
function isValidSalviumAddress(string $address): bool {
|
||||
// Accepts standard and subaddress prefixes for Salvium (e.g. SaLvd, SaLvs)
|
||||
return preg_match('/^SaLv[a-zA-Z0-9]{95}$/', $address) === 1;
|
||||
}
|
||||
|
||||
?>
|
||||
44
src/salvium_tipbot_db.php
Normal file → Executable file
44
src/salvium_tipbot_db.php
Normal file → Executable file
@@ -63,6 +63,17 @@ class SalviumTipBotDB {
|
||||
FOREIGN KEY (sender_user_id) REFERENCES users(id),
|
||||
FOREIGN KEY (recipient_user_id) REFERENCES users(id)
|
||||
);
|
||||
|
||||
CREATE TABLE bot_log (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
chat_id BIGINT NOT NULL,
|
||||
chat_name VARCHAR(255),
|
||||
username VARCHAR(255),
|
||||
message TEXT,
|
||||
response TEXT,
|
||||
logged_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
*/
|
||||
|
||||
public function getUserByTelegramId(int $telegramUserId): array|false {
|
||||
@@ -71,6 +82,17 @@ class SalviumTipBotDB {
|
||||
return $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
public function getUserByUsername(string $username): array|false {
|
||||
$stmt = $this->pdo->prepare("SELECT * FROM users WHERE username = ?");
|
||||
$stmt->execute([$username]);
|
||||
return $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
public function updateUsername(int $telegramUserId, string $username): void {
|
||||
$stmt = $this->pdo->prepare("UPDATE users SET username = ? WHERE telegram_user_id = ?");
|
||||
$stmt->execute([$username, $telegramUserId]);
|
||||
}
|
||||
|
||||
public function getUserBySubaddress(string $subaddress): array|false {
|
||||
$stmt = $this->pdo->prepare("SELECT * FROM users WHERE salvium_subaddress = ?");
|
||||
$stmt->execute([$subaddress]);
|
||||
@@ -127,6 +149,11 @@ class SalviumTipBotDB {
|
||||
return $stmt->execute([$senderUserId, $recipientUserId, $amount, $channelId]);
|
||||
}
|
||||
|
||||
public function getAllPendingTips(): array {
|
||||
$stmt = $this->pdo->query("SELECT * FROM tips WHERE status = 'pending'");
|
||||
return $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
public function getPendingTipsForUser(int $recipientUserId): array {
|
||||
$stmt = $this->pdo->prepare("SELECT * FROM tips WHERE recipient_user_id = ? AND status = 'pending'");
|
||||
$stmt->execute([$recipientUserId]);
|
||||
@@ -143,5 +170,22 @@ class SalviumTipBotDB {
|
||||
$stmt = $this->pdo->query("SELECT * FROM withdrawals WHERE status = 'pending'");
|
||||
return $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
public function logMessage(int $chatId, string $chatName, string $username, string $message, string $response): void {
|
||||
try {
|
||||
$sql = "INSERT INTO bot_log (chat_id, chat_name, username, message, response) VALUES (:chat_id, :chat_name, :username, :message, :response)";
|
||||
$stmt = $this->pdo->prepare($sql);
|
||||
$stmt->execute([
|
||||
':chat_id' => $chatId,
|
||||
':chat_name' => $chatName,
|
||||
':username' => $username,
|
||||
':message' => $message,
|
||||
':response' => $response,
|
||||
]);
|
||||
} catch (PDOException $e) {
|
||||
error_log("Error logging message: " . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
||||
|
||||
23
src/salvium_tipbot_wallet.php
Normal file → Executable file
23
src/salvium_tipbot_wallet.php
Normal file → Executable file
@@ -68,14 +68,25 @@ class SalviumWallet {
|
||||
return $result['addresses'] ?? false;
|
||||
}
|
||||
|
||||
public function transfer(array $destinations, int $mixin = 11, int $unlockTime = 0, bool $getTxKey = false, bool $doNotRelay = false): array|false {
|
||||
public function transfer(array $destinations, int $accountIndex = 0, array $subaddrIndices = [0], int $priority = 0, int $ringSize = 16, bool $getTxKey = true): array|false {
|
||||
$params = [
|
||||
'destinations' => $destinations,
|
||||
'mixin' => $mixin,
|
||||
'unlock_time' => $unlockTime,
|
||||
'get_tx_key' => $getTxKey,
|
||||
'do_not_relay' => $doNotRelay
|
||||
'destinations' => array_map(function ($dest) {
|
||||
return [
|
||||
'address' => $dest['address'],
|
||||
'amount' => (int)($dest['amount']), // already in atomic units
|
||||
'asset_type' => 'SAL1'
|
||||
];
|
||||
}, $destinations),
|
||||
'source_asset' => 'SAL1',
|
||||
'dest_asset' => 'SAL1',
|
||||
'tx_type' => 3,
|
||||
'account_index' => $accountIndex,
|
||||
// 'subaddr_indices' => $subaddrIndices,
|
||||
'priority' => $priority,
|
||||
'ring_size' => $ringSize,
|
||||
'get_tx_key' => $getTxKey
|
||||
];
|
||||
|
||||
return $this->_callRpc('transfer', $params);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user