Наш канал в telegram

Инструкция по созданию Telegram ботов. Часть 4. Прикручиваем MySQL к чат-боту для Telegram на php (webhook)

  1. Часть 1. Что такое Telegram боты и как они работают
  2. Часть 2. Регистрация аккаунтов Telegram ботов в картинках
  3. Часть 3. Пишем простого чат-бота для Telegram на чистом php (webhook)
  4. Часть 4. Прикручиваем MySQL к чат-боту для Telegram на php (webhook)
  5. Часть 5. Пишем Telegram бота для работы через long polling

Итак, сегодня мы попробуем несколько увеличить функционал нашего простейшего чат-бота, а именно: прикрутим к нему базу данных MySQL, в которой будем хранить список подключавшихся к боту пользователей и информацию о них, а так же добавим возможность этих пользователей забанивать и разбанивать.

Первым делом создаём базу данных (пусть она называется, скажем, MYBASE) и дописываем в наш файл config.php данные для доступа к этой БД:

$dbhost = 'MYHOST'    // адрес сервера БД
$dbname = 'MYBASE'    // имя БД
$dbuser = 'username'  // имя пользователя для доступа к БД
$dbpwd = 'password'   // пароль для доступа к БД

Теперь нужно определиться со структурой нашей БД. Пусть в ней будет всего одна таблица, назовём её, скажем, MYTABLE, которая будет содержать следующие поля:

  • user_id — уникальный идентификатор пользователя в Telegram, varchar(32)
  • first_name — имя пользователя в Telegram, varchar(1024)
  • last_name — фамилия пользователя в Telegram, varchar(1024)
  • nick_name — ник пользователя в Telegram, varchar(1024)
  • registered — время первого подключения юзера (timestamp)
  • lastvisit — время последнего общения юзера с ботом (timestamp)
  • status — статус пользователя (забанен/не забанен), uint(8)

Поле user_id нужно пометить как уникальное, для поля status установить значение по умолчанию 1 (у незабаненых юзеров будет status=1, а у забаненых status=0), для полей registered и lastvisit — установить значение по умолчанию «CURRENT_TIMESTAMP», а также дополнительно установить опцию «on update CURRENT_TIMESTAMP» для поля lastvisit (чтобы каждый раз при обновлении записи значение этого поля автоматически обновлялось).

Два небольших замечания:

  • Обычно все любят заводить в таблице первичный ключ id с автоинкрементом, однако нам он не нужен, поскольку user_id и так будут уникальные (это обеспечивает сам Telegram), без всякого автоинкремента, а использовать значение последнего элемента этого поля для подсчёта количества пользователей в таблице — вообще дурь, так как при удалении или обновлении записей в таблице всё сдвинется в любом случае (при обновлении записей в таблицах (запросом UPDATE) автоинкремент выполняется даже если поля реально не обновлялись).
  • Почему-то во всех экспериментах с ботами Telegram, в любом апдейте и с любыми ботами, я наблюдал одну и ту же картину, — chat_id и user_id у одного и того же пользователя всегда совпадают. Причём, я считаю, что получаемое в полях chat_id и user_id значение — это именно user_id, поскольку он одинаковый при общении юзера с любым другим ботом, а значения chat_id должны в этом случае быть разными по определению, — разные боты — разные чаты.

Последнее замечание не очень похоже на ошибку (как если бы нам просто отдавали не то поле), поскольку отправка сообщений методом sendMessage при использовании этого идентификатора (user_id) работает нормально, хотя в описании сказано, что здесь должен быть chat_id. Техподдержка Telegram мой вопрос на эту тему проигнорировала. В общем, либо нам чего-то не договаривают, либо я что-то, где-то не дочитал.

Мой товарищ, Virtual, вообще считает, что так и должно быть, а chat_id юзеров «A» и «B» Telegram получает сложением двух уникальных строк: user_id юзера «A» и user_id юзера «B». Полученный таким сложением идентификатор был бы уникальным (поскольку состоял бы из двух уникальных частей) и однозначно идентифицировал бы кто с кем чатится. Это было бы логично, хотя в доке, в любом случае, написано по-другому.

Ладно, хватит лирических отступлений, идём дальше (но если кто разберётся в чём тут подвох — отпишитесь в коментах или на форуме).

Нам нужно добавлять в БД данные о пользователях и читать данные о пользователях из БД.

Вместо того, чтобы для каждого юзера выяснять, есть ли он в БД, и далее добавлять его данные в базу, если его там нет (это очень долгий путь), просто будем каждый раз пытаться добавить его в базу (если он там уже есть — запрос просто не выполнится). Одновременно с попыткой добавления будем пытаться обновить данные о юзере, записанные в БД, и пытаться прочитать его статус (забанен или нет).

Всё это мы будем делать в одном мультизапросе, а чтобы его выполнение не прекращалось из-за невозможности выполнить какой-то из подзапросов, — воспользуемся директивой IGNORE.

Для реализации всех вышеперечисленных идей дописываем в файле bot.php, перед строкой

// начинаем распарсивать полученное сообщение

следующий код:

Код под катом

if(($chat_id == $admin_chat_id) && ($command === '/send') && ($user_text_length!=0)){

[свернуть]

Теперь нам нужно добавить две новые команды: /ban и /unban. Это делается следующим образом:

  • Во-первых, научим нашего бота выделять адресата (user_id) для этих новых команд. Для этого заменяем в файле bot.php вот такую строку кода:
  • if(($chat_id == $admin_chat_id) && (($command === '/send') || ($command === '/ban') || ($command === '/unban')) && ($user_text_length!=0)){

    на вот такую:

    /send <i>chat_id</i> <i>message</i> - послать <i>message</i> в указанный чат');
  • Во-вторых, внесём их в список, выдаваемый командами /start и /help. Для этого в том же файле заменяем строку
  • /send <i>chat_id</i> <i>message</i> - послать <i>message</i> в указанный чат
    /ban <i>user_id</i> - забанить пользователя с указанным user_id
    /unban <i>user_id</i> - разбанить пользователя с указанным user_id');

    на вот такие:

    default:
  • Ну и, наконец, нужно написать для новых команд обработчики. В файл bot.php, перед строкой
  • $uname = $input_array['message']['chat']['username']; // выделяем ник собеседника

    дописываем следующий код:

    Код под катом

    // обрабатываем принятое сообщение для защиты и удобства
    $message = trim($message);                         // удаляем пробелы
    $message = htmlspecialchars($message, ENT_QUOTES); // преобразуем спецсимволы (&, ", ', <, >) в html-сущности

    [свернуть]

    Загружаем к себе на сервер (в папку MYBOT) исправленные файлы bot.php и config.php и смотрим, что получилось. На этом этапе у нас уже всё должно работать. Остаётся, как обычно, хоть чуть-чуть озаботится вопросами безопасности.

    Поскольку мы добавили код, который позволяет вводить что-то, что в дальнейшем участвует в формировании SQL-запросов, то защищаться нам придётся от возможных SQL-инъекций. Соответственно, нам нужно добавить какую-то обработку вводимой информации. Самое простое, что мы можем в данном случае сделать, — это заменять спецсимволы на их html-коды (например, > на &gt; и так далее). Открываем файл bot.php и дописываем после строки

    $uname = $input_array['message']['chat']['username']; // выделяем ник собеседника

    следующий код:

    // обрабатываем принятое сообщение для защиты и удобства
    $message = trim($message);                         // удаляем пробелы
    $message = htmlspecialchars($message, ENT_QUOTES); // преобразуем спецсимволы (&, ", ', <, >) в html-сущности

    Снова перезаливаем исправленный файл bot.php на сервак и наслаждаемся результатом, — у нас есть организованный через бота Telegram-чат с регистрацией юзеров и возможностью из забанить или разбанить.

    Что ещё можно добавить? Да много чего. Например:

    • возможность существования нескольких админов, которым бот будет присылать сообщения от юзеров
    • возможность добавления/удаления админов
    • возможность админам включать режим «не беспокоить», для временной приостановки получения сообщений
    • возможность сохранения переписки

    Однако, всё это вы можете сделать самостоятельно, а я на этом закончу (и так уже слишком много букв). Лучше начну писать про long polling.

    1. Часть 1. Что такое Telegram боты и как они работают
    2. Часть 2. Регистрация аккаунтов Telegram ботов в картинках
    3. Часть 3. Пишем простого чат-бота для Telegram на чистом php (webhook)
    4. Часть 4. Прикручиваем MySQL к чат-боту для Telegram на php (webhook)
    5. Часть 5. Пишем Telegram бота для работы через long polling

    Добавить комментарий