Гайд: создаем функционального Telegram-бота на Dart

от автора

Привет! Я Саша Омельяненко, тимлид в отделе Flutter в AGIMA. На одном из наших проектов мне нужно было сделать бота для Telegram. Я нашел инструкции, как создать только базового бота. Но как оформить его, добавить кнопки и повесить на них Listener, я не нашел.

Пришлось разбираться с документацией Telegram, а это занятие не из приятных. Чтобы избавить вас от этого удовольствия, я решил написать гайд по разработке функционального Telegram-бота на Dart. Мы пройдем весь процесс от регистрации бота до его развертывания на удаленном сервере. Эта инструкция будет полезна Flutter-разработчикам уровня Junior и Middle.

Что будет уметь наш бот

Мы разработаем бота, который будет имитировать регистрацию пользователя и отдавать токен.

  1. При выполнении команды /start бот будет проверять, зарегистрирован пользователь или нет.

  2. Если пользователь не зарегистрирован, бот будет отправлять текст приветствия и выводить кнопки «Регистрация» и «Инструкция».

  3. Если пользователь нажимает кнопку «Регистрация», бот отправит запрос на бэк и получит токен.

  4. Если пользователь нажимает кнопку «Инструкция», бот покажет сообщение с инструкцией.

  5. Если пользователь зарегистрирован, то бот покажет текст и кнопку с инструкцией.

Теперь, когда мы определили функциональность нашего бота, приступим к его созданию.

1. Регистрация нового бота в Telegram

Для начала нужно зарегистрировать нового бота в Telegram. Для этого:

  1. Откройте Telegram и найдите бота BotFather.

  2. Напишите команду /newbot.

  3. Следуйте инструкциям BotFather для создания нового бота. Укажите имя бота и его Username.

  4. После успешной регистрации 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

Архитектура

Здесь определим, из каких частей будет состоять бот.

  1. Инициализация.

  2. Оформление.

  3. Стартовые команды.

  4. Listener.

  5. Список команд.

Инициализация 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. Через бота.

Добавим описание бота:

  1. Откройте BotFather и выберите команду /setdescription.

  2. Следуйте инструкциям для добавления описания вашему боту.

Добавим меню. Для этого используем команду /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-контейнера

  1. Скопируйте ваш проект на сервер.

  2. Перейдите в директорию проекта.

  3. Соберите Docker-образ:
    docker build -t my_telegram_bot .

  4. Запустите Docker-контейнер:
    docker run -d my_telegram_bot

Теперь ваш Telegram-бот должен запуститься и работать на удаленном сервере.

Заключение

Вот и всё! Вы создали и развернули Telegram бота на Dart. Надеюсь, этот гайд был полезен. Если у вас есть вопросы или предложения, пишите в комментариях.

Спасибо, что прочитали.

P. S. Интересные штуки по Flutter постит у себя в канале наш руководитель Саша Ворожищев. Из последнего — серия постов про Rive-анимации. Загляните!

Что еще почитать


ссылка на оригинал статьи https://habr.com/ru/articles/837618/


Комментарии

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *