Russian (Pусский) translation by Sergey Zhuk (you can also view the original English article)
Если вы читаете это, то скорее всего понимаете, что боты для чатов является популярным трендом в 2016 году.
Эволюция ботов заключается не только в искусственном интеллекте. Ботом может быть инструмент в вашем мессенджере с простым интерфейсом, который может быть использован для расширения функционала сайта или сервиса, или использован как отдельное приложение. Боты легки в разработке и установке, и еще один плюс заключается в том, что мессенджеры могут использоваться на любом устройстве: ноутбуках, смартфонах и планшетах. Вот почему все сходят с ума по ботам.
И наиболее популярным мессенджером с открытым API для ботов является Telegram.
Что мы собираемся делать
В этой статье мы создадим простой бот-секундомер для Telegram. Я покажу вам как создавать собственного бота, связываться с аналитикой, напишем немножко кода и в конце добавим своего бота в магазин ботов.
Кстати я заранее приготовил демо, так что вы можете протестировать бота, просто добавив @stopwatchbot в свой контакт лист в Telegram.
Создаем бота с помощью BotFather
Первым шагом при создании бота нужно зарегистрировать аккаунт для своего бота в Telegram. И для этого есть собственный бот, который называется BotFather. Просто добавьте его в свой контакт лист и вы сможете создавать и настраивать ботов Telegram, просто напечатав команду /newbot и следуя инструкциям от BotFather.



После регистрации вашего нового бота, вы получите сообщение с поздравлением и токен для авторизации. Мы скоро будем использовать этот токен для авторизации бота и отправки запросов к Bot API.
Позднее вы сможете использовать BotFather для добавления описаний и фото к профилям ваших ботов, регенерации токенов, задания списка доступных боту команд, удаления аккаунтов и прочее. Чтобы получить полный список команд, просто напечатайте /help в чате с BotFather.
Соединяемся с Botan Analytics
Не существует никакой встроенной аналитики в Telegrem Bots API, но все равно важно знать, сколько пользователей у вас есть, как они себя ведут и какие команды используют чаще других. Конечно можно собрать такую информацию, используя собственный движок, но если мы собираемся сфокусироваться на функционале самого бота, а не метриках, то нужно использовать решение из коробки.
И для этого уже есть простой инструмент, который называется Botan. Он основан на Yandex AppMetric и абсолютно бесплатный. Используя Botan, можно сегментировать вашу аудиторию, получать информацию о профилях пользователей, получить наиболее часто используемые команды, а так же получить красивые графики прямо в вашем мессенджере:



Для того чтобы начать, нужно зарегистрировать ваше бота в Botan и получить свой токен. И опять же это можно сделать в боте, используя BotanioBot:



Просто нажмите на "Add bot" на вашей клавиатуре в диалоговом окне, введите ник вашего бота, и получите ваш токен для трекинга. Теперь Botanio готов регистрировать события вашего бота, а вы можете получать статистику по пользователям, сессиям и событиям прямо в вашем мессенджере.
Создание и регистрация SSL Webhook
В Telegram есть два способа получения сообщений от пользователей: длинный опрос и webhooks.



Обычно с долгим опросом, вам необходимо запрашивать новые сообщения из API, а с webhooks вы устанавливаете свой обратный вызов, который будет вызван API Telegram, если появится новое сообщение от пользователя. Я предпочитаю использовать webhooks потому что это больше похоже на взаимодействие в реальном времени, так что в этой статье мы так же будем использовать этот способ. Теперь нам нужно выбрать URL для обратного вызова нашего webhook, который будет вызван по HTTPS протоколу, и нужно установить его достаточно безопасным, и расположить свой скрипт в безопасной директории как сказано в руководстве:
Если вы хотите убедится что запрос Webhook действительно исходит от Telegream, мы рекомендуем использовать секретный путь в URL, например:https://www.example.com/<token>. Так как никто больше не знает токена для вашего бота, то вы можете быть уверены, что запрос идет от нас.
Если у вас подтвержденный SSL сертификат, то все что вам нужно, это открыть ваш URL в браузере:
1 |
https://api.telegram.org:443/bot[token]/setwebhook?url=[webhook] |
Иначе необходимо сгенерировать самоподписанный сертификат. Вот пример команды в Linux для этого:
1 |
openssl req -newkey rsa:2048 -sha256 -nodes -keyout /path/to/certificate.key -x509 -days 365 -out /path/to/certificate.crt -subj "/C=IT/ST=state/L=location/O=description/CN=yourdomain.com" |
И не забудьте открыть SSL порт:
1 |
sudo ufw allow 443/tcp |
Чтобы подтвердить ваш сертификат и сделать ваш домен для webhook доверительным, необходимо загрузить свой публичный ключ:
1 |
curl \ |
2 |
-F "url=https://yourdomain.com/path/to/script.php" \ |
3 |
-F "certificate=/path/to/certificate.key" \ |
4 |
"https://api.telegram.org/bot[token]/setwebhook" |
В итоге вы получите следующий JSON ответ:
1 |
{"ok":true,"result":true,"description":"Webhook was set"} |
В нем сказано что webhook был установлен и мы готовы начать работу с ботом.
Создаем базу данных
Теперь нам нужно создать базу данных для наших таймеров. Что мы собираемся в ней хранить? Когда пользователь дает команду секундомеру начать отсчет, мы будем брать ID чата и сохранять строку с ID чата и текущим временем Unix. Следовательно мы сохраним строку с отметкой времени и ID чата.
Чтобы показывать текущее время секундомера, мы будем брать сохраненную метку времени и сравнивать ее с текущим временем. Разница и будет текущее время в секундах. Если пользователь останавливает секундомер, то мы просто удаляем строчку с данным ID чата.
Итак давайте создадим базу данных и таблицу для хранения информации для секундомера:
1 |
CREATE TABLE IF NOT EXISTS `stopwatch` ( |
2 |
`chat_id` int(10) unsigned NOT NULL, |
3 |
`timestamp` int(10) unsigned NOT NULL, |
4 |
PRIMARY KEY (`chat_id`) |
5 |
) ENGINE=InnoDB DEFAULT CHARSET=utf8; |
Создание класса Stopwatch
Наконец мы готовы начать писать код. Создадим класс для работы с базой данных в файле stopwatch.php и начнем с конструктора, который устанавливает два приватных свойства, где мы будем хранить ID чата и соединение с MySQL:
1 |
class Stopwatch |
2 |
{
|
3 |
/** @var mysqli */
|
4 |
private $mysqli; |
5 |
/** @var int */
|
6 |
private $stopwatch_id; |
7 |
/**
|
8 |
* Stopwatch constructor
|
9 |
* @param mysqli $mysqli
|
10 |
* @param $stopwatch_id
|
11 |
*/
|
12 |
public function __construct(\mysqli $mysqli, $stopwatch_id) |
13 |
{
|
14 |
$this->mysqli = $mysqli; |
15 |
$this->stopwatch_id = intval($stopwatch_id); |
16 |
}
|
17 |
}
|
Когда пользователь запускает таймер, мы берем текущую временную метку Unix и сохраняем ее вместе с ID чата в методе start():
1 |
public function start() |
2 |
{
|
3 |
$timestamp = time(); |
4 |
$query = " |
5 |
INSERT INTO `stopwatch` (`chat_id`, `timestamp`)
|
6 |
VALUES ('$this->stopwatch_id', '$timestamp') |
7 |
ON DUPLICATE KEY UPDATE timestamp = '$timestamp' |
8 |
"; |
9 |
return $this->mysqli->query($query); |
10 |
}
|
Если таймер останавливается, то нам нужно удалить строку из базы данных:
1 |
/**
|
2 |
* Delete row with stopwatch id
|
3 |
* @return bool|mysqli_result
|
4 |
*/
|
5 |
public function stop() |
6 |
{
|
7 |
$query = " |
8 |
DELETE FROM `stopwatch`
|
9 |
WHERE `chat_id` = $this->stopwatch_id |
10 |
"; |
11 |
return $this->mysqli->query($query); |
12 |
}
|
И вот главная часть нашего класса. Когда пользователь запрашивает статус нашего таймера, нам нужно найти строку с секундомером из текущей беседы и подсчитать разницу в секундах между сохраненной временной меткой и текущим временем. К счастью временная метка Unix является целым числом, так что мы просто можем вычесть одно из другого. Чтобы отформатировать результирующее значение в виде времени, мы используем функцию gmdate.
1 |
/**
|
2 |
* Find row with stopwatch id and return difference in seconds from saved Unix time and current time
|
3 |
* @return string
|
4 |
*/
|
5 |
public function status() |
6 |
{
|
7 |
$query = " |
8 |
SELECT `timestamp` FROM `stopwatch`
|
9 |
WHERE `chat_id` = $this->stopwatch_id |
10 |
"; |
11 |
$timestamp = $this->mysqli->query($query)->fetch_row(); |
12 |
if (!empty($timestamp)) { |
13 |
return gmdate("H:i:s", time() - reset($timestamp)); |
14 |
}
|
15 |
}
|
Как видите, если в базе данных нет значения, то метод status() ничего не вернет, и мы обработаем значение null как остановленный таймер.
Выбор библиотеки PHP
Есть много PHP библиотек для работы с Telegram API, но на момент написания этой статьи лишь одна поддерживала одновременно Telegram Bot API и трекинг Botan. Она называется PHP Telegram Bot API.
Для установки библиотеки используем Composer:
1 |
composer require telegram-bot/api |
Если вам не нужна аналитика, то попробуйте Bot API PHP SDK с интеграцией в Laravel или PHP Telegram Bot.
Запуск Webhook скрипта
И вот мы переходим к главной части - мы создаем скрипт для обработки обратных вызовов от Telegram Bot API. Создадим файл index.php и включим в него автозагрузчик Composer и новый класс Stopwatch. Откроем соединение MySQL, создадим нового клиента Telegram API и запустим его:
1 |
require_once 'vendor/autoload.php'; |
2 |
require_once 'stopwatch.php'; |
3 |
|
4 |
// connect to database
|
5 |
$mysqli = new mysqli('database_host', 'database_user', 'database_password', 'database_name'); |
6 |
if (!empty($mysqli->connect_errno)) { |
7 |
throw new \Exception($mysqli->connect_error, $mysqli->connect_errno); |
8 |
}
|
9 |
|
10 |
// create a bot
|
11 |
$bot = new \TelegramBot\Api\Client('bot_token', 'botanio_token'); |
12 |
// run, bot, run!
|
13 |
$bot->run(); |
Создание команд
Теперь нужно настроить ответ бота на команду /start. Эта команда используется для старта всех ботов Telegram, и пользователям будет показано наше сообщение с приветствием.
1 |
$bot->command('start', function ($message) use ($bot) { |
2 |
$answer = 'Howdy! Welcome to the stopwatch. Use bot commands or keyboard to control your time.'; |
3 |
$bot->sendMessage($message->getChat()->getId(), $answer); |
4 |
});
|
Здесь в методе command() мы определим замыкание для получения команды. Замыкание получает ID текущего чата и отправляет сообщение с приветствием. Так же все зарегистрированные команды автоматически по имени команды.
Для запуска секундомера, мы определим команду /go:
1 |
$bot->command('go', function ($message) use ($bot, $mysqli) { |
2 |
$stopwatch = new Stopwatch($mysqli, $message->getChat()->getId()); |
3 |
$stopwatch->start(); |
4 |
$bot->sendMessage($message->getChat()->getId(), 'Stopwatch started. Go!'); |
5 |
});
|
Она создаст объект класса Stopwatch и запустит таймер, вызывав метод start(), который мы определили ранее.
Чтобы определить команду /status, делаем аналогично. Просто вызываем метод status() и возврашаем результат. Если метод вернул null, сообщаем пользователю, что таймер не был запущен.
1 |
$bot->command('status', function ($message) use ($bot, $mysqli) { |
2 |
$stopwatch = new Stopwatch($mysqli, $message->getChat()->getId()); |
3 |
$answer = $stopwatch->status(); |
4 |
if (empty($answer)) { |
5 |
$answer = 'Timer is not started.'; |
6 |
}
|
7 |
$bot->sendMessage($message->getChat()->getId(), $answer); |
8 |
});
|
А если пользователь останавливает таймер, то нам нужно сначала получить статус, показать результирующее время, а затем остановить таймер, используя метод stop().
1 |
$bot->command('stop', function ($message) use ($bot, $mysqli) { |
2 |
$stopwatch = new Stopwatch($mysqli, $message->getChat()->getId()); |
3 |
$answer = $stopwatch->status(); |
4 |
if (!empty($answer)) { |
5 |
$answer = 'Your time is ' . $answer . PHP_EOL; |
6 |
}
|
7 |
$stopwatch->stop(); |
8 |
$bot->sendMessage($message->getChat()->getId(), $answer . 'Stopwatch stopped. Enjoy your time!'); |
9 |
});
|
И это все! Теперь вы можете загрузить все необходимые файлы в вашу директорию для webhook и протестировать своего бота.
Добавление клавиатуры
Чтобы предложить пользователю, какие команды он может выполнять, мы можем к сообщению добавить клавиатуру. Наш таймер может быть в двух состояниях: запущен или остановлен. Для того чтобы показать пользователю клавиатуру, нам нужно просто переопределить метод sendMessage():
1 |
$keyboard = new \TelegramBot\Api\Types\ReplyKeyboardMarkup([['/go', '/status']], null, true); |
2 |
|
3 |
$bot->sendMessage($message->getChat()->getId(), $answer, false, null, null, $keyboards); |
4 |
});
|
Теперь мы может добавлять клавиатуру к любой команде нашего бота. Я не стал включать здесь полный пример, но вы можете его увидеть в репозитории.
Добавление бота в Store
Хорошо, теперь у нас есть работающий бот, и мы хотим показать его миру. Лучшим способом будет зарегистрировать бота в каталоге ботов. Сейчас у Telegram нет официального каталога, но есть несколько неофициальных, и самый большой из них - Storebot.me, в котором уже зарегистрированы тысячи ботов.
И в нем есть бот... для регистрации бота в каталоге ботов! Добавляем @storebot в свой контакт лист, пишем команду /add и следуем инструкциям. Вас попросят ввести имя бота, описание, выбрать одну из стандартных категорий, и подтвердить права на бота отправкой токена.



Через некоторое время ваш бот пройдет процесс подтверждения я появится в чартах Storebot. Теперь вы и ваши пользователи могу голосовать, находить и оценивать вашего бота в store, чтобы помочь ему подняться в каталоге.
Заключение
Мы прошли длинный путь, от создания простого бота до регистрации его в store, сделав его доступным для реальных пользователей. Как вы могли убедиться, существует много инструментов, которые сделают вашу жизнь проще при создании собственного бота, и не нужно писать много кода для создания простого бота. Теперь вы готовы к созданию собственного бота!
Если у вас есть какие-либо вопросы, не стесняйтесь задавать их в комментариях под статьей.



