improved user recognition, commands handler fix

This commit is contained in:
t1amak
2025-05-30 21:21:35 +00:00
parent 02dce3692e
commit cc8fbe2487
3 changed files with 105 additions and 73 deletions
+15 -2
View File
@@ -21,8 +21,21 @@ $update = json_decode(file_get_contents("php://input"), true);
if (!$update || !isset($update['message'])) exit;
$message = $update['message'];
$args = explode(' ', trim($message['text'] ?? ''));
$command = strtolower($args[0] ?? '');
//$args = explode(' ', trim($message['text'] ?? ''));
//$command = strtolower($args[0] ?? '');
$text = trim($message['text'] ?? '');
if (!str_starts_with($text, '/')) exit; // Only react to messages that start with '/'
$args = explode(' ', $text);
$command = strtolower($args[0]);
// Strip optional @BotUsername (Telegram adds this in groups)
if (str_contains($command, '@')) {
$command = explode('@', $command)[0];
}
$context = [
'chat_id' => $message['chat']['id'],
+27 -71
View File
@@ -45,18 +45,12 @@ class SalviumTipBotCommands {
}
private function cmd_start(array $args, array $ctx): string {
$user = $this->db->getUserByTelegramId($ctx['user_id']);
if (!$user) {
$sub = $this->wallet->getNewSubaddress();
if ($sub) {
$this->db->createUser($ctx['user_id'], $sub);
if (!empty($ctx['username'])) {
$this->db->updateUsername($ctx['user_id'], $ctx['username']);
}
}
}
$this->db->ensureUserExists(
$ctx['user_id'],
$ctx['username'] ?? null,
fn() => $this->wallet->getNewSubaddress(),
false
);
return "👋 Welcome to the Salvium Tip Bot!\n\n"
. "You can use the following commands:\n"
@@ -69,33 +63,12 @@ class SalviumTipBotCommands {
}
private function cmd_deposit(array $args, array $ctx): string {
$user = $this->db->getUserByTelegramId($ctx['user_id']);
// If no exact match, attempt upgrade by matching username with placeholder
if (!$user && !empty($ctx['username'])) {
$user = $this->db->getUserByUsername($ctx['username']);
// Check if it's a placeholder user (telegram_user_id is synthetic)
if ($user && $user['telegram_user_id'] < 1000000) {
// Upgrade the telegram_user_id to the real one
$this->db->upgradeTelegramUserId($user['telegram_user_id'], $ctx['user_id']);
// Refresh user
$user = $this->db->getUserByTelegramId($ctx['user_id']);
}
}
// If still not found, create new user
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";
}
$user = $this->db->ensureUserExists(
$ctx['user_id'],
$ctx['username'] ?? null,
fn() => $this->wallet->getNewSubaddress(),
false
);
return "Your deposit address: {$user['salvium_subaddress']}";
}
@@ -143,32 +116,24 @@ class SalviumTipBotCommands {
}
$cleanUsername = ltrim($targetUsername, '@');
$recipient = $this->db->getUserByUsername($cleanUsername);
// If recipient not known, create placeholder
$recipient = $this->db->ensureUserExists(
0,
$cleanUsername,
fn() => $this->wallet->getNewSubaddress(),
true
);
if (!$recipient) {
$syntheticId = 100000 + (crc32($cleanUsername) % 900000);
$subaddress = $this->wallet->getNewSubaddress();
if (!$subaddress) {
return "Failed to create deposit address for {$cleanUsername}.";
}
return "Failed to ensure recipient exists.";
}
$existing = $this->db->getUserByTelegramId($syntheticId);
$this->db->updateUserTipBalance($sender['id'], $amount, 'subtract');
$this->db->addTip($sender['id'], $recipient['id'], $amount, $ctx['chat_id']);
if (!$existing) {
if (!$this->db->createUser($syntheticId, $subaddress)) {
return "Failed to create recipient account for {$cleanUsername}.";
}
}
// Ensure username is correct (could be NULL in DB even if user exists)
$this->db->updateUsername($syntheticId, $cleanUsername);
// Now safely fetch the recipient
$recipient = $this->db->getUserByUsername($cleanUsername);
// Notify group
if (!empty($recipient['telegram_user_id']) && $recipient['telegram_user_id'] > 0 && $recipient['telegram_user_id'] !== (100_000 + (crc32($cleanUsername) % 900_000))) {
sendMessage($recipient['telegram_user_id'], "You received a tip of {$amount} SAL! Use /balance to check.");
} else {
sendMessage($ctx['chat_id'], "Hey @$cleanUsername, you just got a tip from @$ctx[username]!");
sendGif(
$ctx['chat_id'],
@@ -177,30 +142,21 @@ class SalviumTipBotCommands {
);
}
$this->db->updateUserTipBalance($sender['id'], $amount, 'subtract');
$this->db->addTip($sender['id'], $recipient['id'], $amount, $ctx['chat_id']);
if (!empty($recipient['telegram_user_id']) && $recipient['telegram_user_id'] > 0 && $recipient['telegram_user_id'] != crc32($cleanUsername)) {
sendMessage($recipient['telegram_user_id'], "You received a tip of {$amount} SAL! Use /balance to check.");
}
return "Tipped {$targetUsername} {$amount} SAL successfully!";
}
private function cmd_claim(array $args, array $ctx): string {
$user = $this->db->getUserByUsername($ctx['username']);
if (!$user || $user['telegram_user_id'] > 1000000) {
if (!$user || $user['telegram_user_id'] > 1_000_000) {
return "Nothing to claim or already claimed.";
}
// Upgrade placeholder to real user ID
$this->db->upgradeTelegramUserId($user['telegram_user_id'], $ctx['user_id']);
return "Welcome @{$ctx['username']}, your account has been activated. You can now check your balance and receive tips!";
}
}
?>
+63
View File
@@ -89,10 +89,22 @@ class SalviumTipBotDB {
}
public function updateUsername(int $telegramUserId, string $username): void {
// First, check if the username is already used by a different user
$stmt = $this->pdo->prepare("SELECT telegram_user_id FROM users WHERE username = ?");
$stmt->execute([$username]);
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if ($row && (int)$row['telegram_user_id'] !== $telegramUserId) {
// Username is used by another user, don't overwrite
return;
}
// Safe to update
$stmt = $this->pdo->prepare("UPDATE users SET username = ? WHERE telegram_user_id = ?");
$stmt->execute([$username, $telegramUserId]);
}
public function upgradeTelegramUserId(int $oldId, int $newId): bool {
$stmt = $this->pdo->prepare("UPDATE users SET telegram_user_id = ? WHERE telegram_user_id = ?");
return $stmt->execute([$newId, $oldId]);
@@ -109,6 +121,57 @@ class SalviumTipBotDB {
return $stmt->execute([$telegramUserId, $subaddress]);
}
public function ensureUserExists(
int $telegramId,
?string $username,
callable $subaddressGenerator,
bool $allowSynthetic = false
): array {
// 1. Try exact match by Telegram ID
$user = $this->getUserByTelegramId($telegramId);
// 2. Try upgrade from placeholder if matching username
if (!$user && $username) {
$placeholder = $this->getUserByUsername($username);
if ($placeholder && $placeholder['telegram_user_id'] < 1_000_000 && $telegramId !== 0) {
$this->upgradeTelegramUserId($placeholder['telegram_user_id'], $telegramId);
$user = $this->getUserByTelegramId($telegramId);
}
else if ($placeholder && $placeholder['telegram_user_id'] >= 1_000_000 && $telegramId === 0) {
$user = $this->getUserByTelegramId($placeholder['telegram_user_id']);
}
}
// 3. Still not found? Possibly create new user
if (!$user) {
$idToUse = $telegramId;
if ($telegramId === 0 && $username && $allowSynthetic) {
// Create synthetic ID
$clean = ltrim($username, '@');
$idToUse = 100_000 + (crc32($clean) % 900_000);
}
$existing = $this->getUserByTelegramId($idToUse);
if (!$existing) {
$sub = $subaddressGenerator();
if (!$sub) throw new RuntimeException("Failed to generate subaddress");
$this->createUser($idToUse, $sub);
}
if ($username) {
$this->updateUsername($idToUse, $username);
}
$user = $this->getUserByTelegramId($idToUse);
}
return $user;
}
public function updateUserTipBalance(int $userId, float $amount, string $operation = 'add'): bool {
$sql = $operation === 'add' ? "UPDATE users SET tip_balance = tip_balance + ? WHERE id = ?" : "UPDATE users SET tip_balance = tip_balance - ? WHERE id = ?";
$stmt = $this->pdo->prepare($sql);