Привет! Я Саша Омельяненко, тимлид в отделе Flutter в AGIMA. На одном из наших проектов мне нужно было сделать бота для Telegram. Я нашел инструкции, как создать только базового бота. Но как оформить его, добавить кнопки и повесить на них Listener, я не нашел.
Пришлось разбираться с документацией Telegram, а это занятие не из приятных. Чтобы избавить вас от этого удовольствия, я решил написать гайд по разработке функционального Telegram-бота на Dart. Мы пройдем весь процесс от регистрации бота до его развертывания на удаленном сервере. Эта инструкция будет полезна Flutter-разработчикам уровня Junior и Middle.
Что будет уметь наш бот
Мы разработаем бота, который будет имитировать регистрацию пользователя и отдавать токен.
-
При выполнении команды /start бот будет проверять, зарегистрирован пользователь или нет.
-
Если пользователь не зарегистрирован, бот будет отправлять текст приветствия и выводить кнопки «Регистрация» и «Инструкция».
-
Если пользователь нажимает кнопку «Регистрация», бот отправит запрос на бэк и получит токен.
-
Если пользователь нажимает кнопку «Инструкция», бот покажет сообщение с инструкцией.
-
Если пользователь зарегистрирован, то бот покажет текст и кнопку с инструкцией.
Теперь, когда мы определили функциональность нашего бота, приступим к его созданию.
1. Регистрация нового бота в Telegram
Для начала нужно зарегистрировать нового бота в Telegram. Для этого:
-
Откройте Telegram и найдите бота BotFather.
-
Напишите команду /newbot.
-
Следуйте инструкциям BotFather для создания нового бота. Укажите имя бота и его Username.
-
После успешной регистрации BotFather выдаст вам токен доступа (API Token). Сохраните его, он понадобится для взаимодействия с Telegram API.
2. Разработка бота
Теперь, когда у нас есть токен, можно приступить к написанию кода. Мы будем использовать библиотеку teledart для взаимодействия с Telegram API.
Создаем новый Dart-проект
dart create -t console-full dart_test_habr_bot
Устанавливаем зависимости
Добавьте зависимость teledart
в ваш pubspec.yaml
:
dependencies: teledart: ^0.6.1
Архитектура
Здесь определим, из каких частей будет состоять бот.
-
Инициализация.
-
Оформление.
-
Стартовые команды.
-
Listener.
-
Список команд.
Инициализация bin/dart_test_habr_bot.dart
late TeleDart _teleDart; final telegram = Telegram(YOUR_BOT_TOKEN_FROM_BOT_FATHER); final username = (await telegram.getMe()).username; _teleDart = TeleDart(YOUR_BOT_TOKEN_FROM_BOT_FATHER, Event(username!)); final repository = Repository(); _teleDart.start();
Оформление
Тут мы можем пойти двумя путями. Оформить бота в проекте или использовать BotFather.
1. Через бота.
Добавим описание бота:
-
Откройте BotFather и выберите команду
/setdescription
. -
Следуйте инструкциям для добавления описания вашему боту.
Добавим меню. Для этого используем команду /setcommands
в BotFather. Укажите команды и их описания.
2. В проекте.
Добавим описание бота:
_teleDart.setMyShortDescription( 'Это бот для регистрации и управления аккаунтом', 'ru');
Добавление меню:
_teleDart.setMyCommands([ BotCommand(command: '/start', description: '🚀 Начать'), BotCommand(command: '/information', description: '🛠Инструкция'), ]);
Стартовые команды
Как я уже писал выше, у бота будет 2 стартовые команды — «Старт» и «Инструкция». Создаем отдельный файл lib/start_bot/start_bot.dart и добавляем туда 2 команды и Listener. Для команд и лисенера я создал mixin lib/start_bot/start_bot_mixin.dar
late TeleDart _teleDart; _teleDart = teleDart; //Кнопка старт tabStart(teleDart: _teleDart); //Кнопка Инструкция tabInstruction(teleDart: _teleDart); //Слушатель listener(teleDart: _teleDart);
Для корректной работы в mixin я добавил 4 переменных, позже мы их инициализируем:
var msgId = 0; var userName = ''; var telegramTag = ''; var token = '';
Кнопка «Старт»
void tabStart({ required TeleDart teleDart, }) { teleDart.onCommand('start').listen( (message) async { msgId = message.chat.id; userName = message.chat.firstName!; final Map<String, dynamic> response = await repository.checkUser(chatId: msgId); final isRegist = response['isRegist']; if (!isRegist) { final button1 = InlineKeyboardButton( text: '🚀Регистрация', callbackData: 'regist', ); final button2 = InlineKeyboardButton( text: '🛠Инструкция', callbackData: 'instruction', ); teleDart.sendMessage( msgId, 'Рады приветствовать вас $userName!👋\n\nВы еще не зарегистрированны\n\n👇Хотите зарегистрироваться? Жмите👇', replyMarkup: InlineKeyboardMarkup( inlineKeyboard: [ [button1], [button2], ], ), ); } else { final button1 = InlineKeyboardButton( text: '🛠Инструкция', callbackData: 'instruction', ); teleDart.sendMessage( msgId, 'Привет, $userName!👋\n\nВы уже проходили регистрацию\n\n👇Хотите ознакомиться с инструкцией? Жмите👇', replyMarkup: InlineKeyboardMarkup( inlineKeyboard: [ [button1], ], ), ); } }, ); }
Кнопка «Инструкция»
void tabInstruction({ required TeleDart teleDart, }) { final button1 = InlineKeyboardButton( text: '🚀Регистрация', callbackData: 'regist', ); teleDart.sendMessage( msgId, 'Кажется Вам нужна помощь!\n\nВсе просто\n\nЕсли Вы не зарегистрованны, для регистрации нажмите кнопку "Зарегистрироваться"', replyMarkup: InlineKeyboardMarkup( inlineKeyboard: [ [button1], ], ), ); }
Listener
Теперь давайте добавим Listenеr, чтобы понимать, куда нажимает пользователь.
void listener({ required TeleDart teleDart, }) => teleDart.onCallbackQuery().listen( (onData) async { final data = onData.data!; switch (data) { case 'regist': _handleRegist( teleDart: teleDart, onData: onData, ); break; case 'instruction': _handleInstruction( teleDart: teleDart, onData: onData, ); break; default: break; } }, );
Список команд
Теперь давайте реализуем две наши команды.
// Кнопка регистрации void _handleRegist({ required TeleDart teleDart, required TeleDartCallbackQuery onData, }) { final Map<String, dynamic> response = await repository.registUser(chatId: msgId); final token = response['token']; teleDart.sendMessage( onData.message!.chat.id, '🥳Вы активировали аккаунт\n\n👇Вот Ваш токен👇\n\n$token', ); } // Кнопка инструкция void _handleInstruction({ required TeleDart teleDart, required TeleDartCallbackQuery onData, }) { final button1 = InlineKeyboardButton( text: '🚀Регистрация', callbackData: 'regist', ); teleDart.sendMessage( msgId, 'Кажется Вам нужна помощь!\n\nВсе просто\n\nЕсли Вы не зарегистрованны, для регистрации нажмите кнопку "Зарегистрироваться"', replyMarkup: InlineKeyboardMarkup( inlineKeyboard: [ [button1], ], ), ); }
На этом этап разработки закончен. Я не стал описывать методы работы с сетью, т. к. это база. Теперь нам осталось упаковать всё в Docker и выложить наш проект на сервер.
3. Docker
Создайте файл Dockerfile
в корне вашего проекта:
# Use the official Dart image from the Docker Hub FROM google/dart:latest # Set the working directory WORKDIR /app # Copy the pubspec.* files to the working directory COPY pubspec.* ./ # Install the dependencies RUN dart pub get # Copy the rest of the application code to the working directory COPY . . # Build the application RUN dart compile exe bin/main.dart -o bin/main # Command to run the application CMD ["bin/main"]
4. Подключение к удаленному VDS-серверу
Для подключения к удаленному серверу используйте SSH. Например, для подключения к серверу с IP-адресом 123.45.67.89
и пользователем user
выполните команду:
ssh user@123.45.67.89
5. Запуск проекта на сервере
Сборка и запуск Docker-контейнера
-
Скопируйте ваш проект на сервер.
-
Перейдите в директорию проекта.
-
Соберите Docker-образ:
docker build -t my_telegram_bot .
-
Запустите Docker-контейнер:
docker run -d my_telegram_bot
Теперь ваш Telegram-бот должен запуститься и работать на удаленном сервере.
Заключение
Вот и всё! Вы создали и развернули Telegram бота на Dart. Надеюсь, этот гайд был полезен. Если у вас есть вопросы или предложения, пишите в комментариях.
Спасибо, что прочитали.
P. S. Интересные штуки по Flutter постит у себя в канале наш руководитель Саша Ворожищев. Из последнего — серия постов про Rive-анимации. Загляните!
Что еще почитать
ссылка на оригинал статьи https://habr.com/ru/articles/837618/
Добавить комментарий