Введение
В рамках этой статьи мы создадим своего бота, способного переотправлять отправленные пользователем сообщения с учётом форматирования и медиа.
Тема ботов была изъезжена до дыр уже многими блогами, постами, блогпостами и прочими кодерами. Однако в большинстве своём это боты на условных Python/JS/PHP, в которых обычно можно сделать как получится и всё вроде как даже заработает. Я же в своё время (почти) ушел из этих языков в мир строгой типизации и объектной ориентированности Java, а позже и в Kotlin. На момент, когда мне было интересно написать своего первого бота, на рынке github из интересных присутствовала только библиотека pengrad/java-telegram-bot-api, однако лично для меня она имела один фатальный недостаток: она на тот момент полностью дублировала Telegram Bot API, то есть фактически являлась прокладкой, которая кроме взаимодействия через Java классы больше ничего не давала.
Так я пришел к идее написать свою библиотеку для Telegram Bot API. Первая покрывающая основной API версия заняла у меня месяц, но выходили обновления, пользователи предлагали идеи по улучшению, да и мне часто не нравилось делать какие-то вещи руками на постоянной основе. В итоге, библиотека развивается по сей день, там есть удобный API, свой DSL, но что главное — она не утратила свою исходную идею о том, чтобы строго типизировать работу с Telegram Bot API.
Как вообще работают боты в Telegram
У ботов в телеграме есть масса ограничений. На красивые циферки очень часто можно посмотреть тут, но если вкратце (ссылка на BotFather, чтобы дальше не повторяться) (скорее всего, будет пополняться для расширения кругозора):
-
По-умолчанию бот не видит сообщения других пользователей в группах до прямого обращения к боту командой (это можно поменять через group privacy настройку в BotFather)
-
По-умолчанию боты не инлайновые. Инлайновые боты — это как бот для гифок, то есть когда вы вводите ник бота, добавляете пробел и он вам предлагает варианты. После нажатия на вариант отправляется сообщение в чат с контентом, предложенным ботом (тоже включается через настройку в BotFather)
-
Кроме того, после включения инлайн-режима для бота, нужно будет отдельно включить поддержку инлайн-режима для локаций, когда бот может выдать результаты на основе геолокации пользователя
-
-
В API сейчас нет способа получить историю чата. Никакого. Вообще. Можно разве что кешировать сообщения
В среднем же пайплайн разработки бота выглядит следующим образом:
-
Идея
-
Создание тестового бота через BotFather с помощью
/newbot -
Кодинг, исправление ошибок
-
Хостинг
Итак, бот
-
Топаем к BotFather и создаём бота через
/newbot -
Для простоты открываем этот шаблон на гитхабе и создаём из него свой проект
Далее можно проследовать в Readme шаблона и настроить проект, а можно просто начать кодить в вашем файле App.kt. Итак, что же у нас есть из коробки:
suspend fun main(args: Array<String>) { val bot = telegramBot(args.first()) // 1 val scope = CoroutineScope(Dispatchers.Default) // 2 bot.buildBehaviour(scope) { // 3 val me = getMe() onCommand("start", requireOnlyCommandInMessage = true) { reply(it, "Hello, I am ${me.firstName}") } }.join() // 4 }
-
Создаём бота. Можно заменить
args.first()на явную передачу вашего токена, полученного при создании бота через BotFather -
Создание
CoroutineScope. Почитать о корутинах в котлине можно тут, но если вкратце — они позволяют производить работу с ботом асинхронно -
Начало самого интересного. В коллбэке для
buildBehaviourмы будем составлять логику нашего бота в этом туториале -
Заставляем нашу программу не заканчиваться после составления логики бота и его запуска
Теперь давайте заменим код в логике бота на следующий:
onContentMessage { // 1 execute( // 2 it.content.createResend(it.chat.id) // 3 ) }
Готово ? Давайте теперь разберёмся, что же тут происходит:
-
Данный метод позволяет нам отдельно получать сообщения с некоторым контентом: медиа, локации, текст и т.д.
-
execute— основной метод всей библиотеки. Этот метод отправляет запрос в систему телеграма. Скорее всего, напрямую вы будете использовать его очень редко, но знать о нём полезно -
Магия с createResend заключается в том, что практически любой контент в телеграме может быть переотправлен. По этой причине в библиотеке были сделаны методы переотправки контента — они автоматически формируют запрос на отправку сообщения с тем же контентом
Теперь можно сделать что-то по-интересней. Давайте научимся реагировать на команды:
onCommand("start") { // 1 reply(it, "Привет, я пока что умею не так много, но скоро всему научусь!") // 2 } onCommand("help") { reply(it, "Отправьте мне любое сообщение, и я отвечу вам тем же?") }
-
Этот коллбэк будет вызываться каждый раз при отправке
/start, но важно знать, что он будет вызываться при наличии в сообщении только этой команды -
Отвечаем текстовым сообщением.
itтут обозначает само сообщение
Ну и напоследок давайте попробуем переписать часть с onContentMessage так, чтобы попутно сохранять части текстовых сообщений:
fun save(sources: List<TextSource>) { // работа с сохранением частей текста println(sources.makeString()) // 3 } onContentMessage { it.content.asTextContent() ?.let { content -> // 1 save(content.textSources) // 2 } execute(it.content.createResend(it.chat.id)) }
-
asTextContent()проверяет, является ли контент сообщения текстом и вызываетlet, если да -
content.textSourcesсоздаст списокTextSourceобъектов, с этим списком потенциально можно:-
Сохранять (у
TextSourceесть сериализатор дляkotlinx.serialization) -
Копировать, перемещать, модифицировать
-
Использовать для форматирования — сурсы могут быть превращены в стандартные текстовые части телеграма
-
-
makeStringсоздаст из спискаTextSourceтекст, который будет виден пользователю без учета форматирования
Заключение
Итак, мы создали бота, который:
-
Умеет отвечать на простые команды
/startи/help -
Умеет переотправлять полученные сообщения отправителю
-
Отбирает текстовые сообщения и производит операции с их контентом
Далее остаётся только развивать бота насколько хватит фантазии. Например, можно выделить модули в функции/плагины, как я это сделал в своём PlaguBotе.
Для более подробной информации о проекте можно посмотреть его основную страницу, вики, проект с примерами и заглянуть в наш телеграм канал.
ссылка на оригинал статьи https://habr.com/ru/post/553784/
Добавить комментарий