Какой язык выбрать для программирования бота? Есть ли преимущества одного перед другим? Минимальный код? Отладка и k-версия Web Telegram
На первый вопрос можно ответить так: какой язык знаете, тот и используйте. Логично. Если человек изучал Python, а не С#, то он выберет первое.
Если пользователь имеет только начальные навыки программирования, то проще выбрать скриптовый движок, а не Java, при всём уважении.
Если в рюкзаке знания нескольких языков, то отталкиваются от своих предпочтений и задач. К моим предпочтениям относятся web-технологии с готовкой на PHP.
Дают ли знания web-технологий какие-то преимущества при разработке ботов? Если для ТГ требуется создать мини-приложение и игры на HTML5, то дают. В остальном случаях исходят из задач и наличия необходимых библиотек.
Боты - это программы (скрипты), которые взаимодействуют с серверами ТГ. Боты выполняют какие-то функции, но для этого им необходимы данные для работы. Для получения данных (обновлений) от сервера доступно два взаимоисключающих способа - опрос и вебхук (автоматически сформированный запрос).
В первом случае для получения обновлений бот должен регулярно (по таймеру) отправлять запросы на сервер методом getUpdates, а во втором случае при появлении обновления сервер направляет данные на указанный при регистрации вебхука адрес, что в нашем случае является скрипт бота.
Второй вариант удобнее в работе и на нём мы остановимся, хотя никто не запрещает зарегистрировать ещё бота без привязки к вебхуку.
Создадим простой скрипт с минимальным кодом bot.php.
Для вызова этого скрипта его нужно разместить на сервере с поддержкой https. Здесь можно долго не думать и зарегистрировать на месяц бесплатный хостинг, например, на Beget, если вообще не хочется платить за "попробовать ботостроительство".
После размещения скрипта указываем его адрес в методе установки вебхука
https://api.telegram.org/bot{{TOKEN}}/setWebhook?url=https://{{DOMEN}}/bot.php
{{TOKEN}} и {{DOMEN}} - это обозначение переменных в Postman, которым нужно присвоить соответствующие значения на вкладке окружения (Environment в левой части интерфейса).
В случае успешного выполнения запроса получим ответ {"ok":true,"result":true,"description":"Webhook was set"}
Если теперь ввести в поле чата ТГ текст "Сообщение", то после его отправки в файл message.txt запишутся данные:
Array ( [update_id] => 883574836 [message] => Array ( [message_id] => 8160 [from] => Array ( [id] => 525... [is_bot] => [first_name] => А [username] => m [language_code] => ru ) [chat] => Array ( [id] => 525... [first_name] => А [username] => m [type] => private ) [date] => 1734004957 [text] => Сообщение ) )
Для получения значения поля из этих данных нужно указать путь к нему. Это можно делать двумя способами - от поля или от корня структуры.
От поля путь выписывается так:
При движении от корня выписываем поля в обратную сторону
На практике не всегда требуется видеть и сохранять все полученные ботом данные. Например, для рассылки сообщений нужно знать только chat_id получателей. При регистрации в ТГ необходимо указать имя (first_name), но часто пользователи вбивают туда всё, что стукнет в голову - ники и др. Например, под именем "Наташа" может скрываться брутальный мужик (и наоборот). Username есть не у всех, да и его можно изменить. Учёт пользователей по сhat_id - самый надёжный вариант.
Сохранять необходимые данные нужно самостоятельно и заранее. Иначе получится так, что нужно сделать рассылку по подписчикам бота, а где взять адреса подписчиков, если их не сохраняли? Это я к тому, что при разработке бота нужно сразу определиться с тем, какие данные и где будут храниться.
Если сообщение большое, то оно может не поместиться даже на одном экране и каждый раз выискивать нужные поля в нём утомительно. Можно выводить в чат контрольные сообщения. Недостаток этого способа в том, что для вывода лога в чат необходимо в коде бота отправить сообщение. Код программы должен выполниться, но этого не произойдёт, если в нём есть ошибки. В процессе программирования бота неплохо было бы оперативно видеть на экране информацию о том, что скрипт бота работает.
Для решения этой задачи можно использовать AutoHotKey и создать скрипт, который будет обновлять страницу бота в браузере после сохранения кода по сочетанию клавиш Ctrl+S.
Скрипт AutoHotkey для обновления страницы в Firefox
В начале кода бота можно включить отображение всех ошибок и предупреждений или просто выводить какую-нибудь надпись, например:
echo "Start";
Если надпись исчезла после обновления страницы, то в коде синтаксическая ошибка.
При желании можно реализовать такой механизм - имитацию отправки сообщения от пользователя в чат и удаление его. Если в чате есть сообщения, значит где-то ошибка. Для этого также можно использовать скрипт автоматизации и web версию Telegram.
Браузерный скрипт напишем с использованием уже знакомого нам плагина Tampermonkey. Разные версии ТГ могут потребовать разный код. Для k-версии Web Telegram он пока такой:
Это всё хорошо, но где брать код для обработки сообщений ботом? Если вы создавали запросы в программе Postman, то у неё есть функция генерации кода запросов в разных форматах.
Если оформлять каждый запрос запрос в виде отдельной функции, - для метода sendMessage своя, для sendPhoto - своя и т.д., то, с одной стороны, это упростит вызов методов, а с другой приведёт к дублированию кода запросов и ограничению функциональности. Закладывать в виде параметров все необязательные параметры методов Bot Api утомительно. Можно использовать универсальную функцию и передавать ей название метода Bot Api и данные, как показано ниже.
function call($methodName, $data){ $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => "https://api.telegram.org/bot".TOKEN."/$methodName", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => '', CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 0, CURLOPT_FOLLOWLOCATION => true, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => 'POST', CURLOPT_POSTFIELDS => $data, CURLOPT_HTTPHEADER => array( 'Content-Type: application/json' ), )); $response = curl_exec($curl); curl_close($curl); }
Недостаток этой функции в том, что для её вызова каждый раз придётся выписывать структуру данных. Наилучший результат даст комбинированный подход, при котором можно использовать как отдельные функции с основными и часто используемыми дополнительными параметрами, так и универсальную функцию, если требуется вызов большого количества необязательных параметров.