Делаем телеграм-бот для сохранения сообщений в блокчейн

от автора

Привет, я Дмитрий и хочу поделиться с вами как я делал свой телеграм-бот для сохранения сообщений из чатов в блокчейн на языке java. Вообще идея была в том, чтобы научиться быстро и удобно увековечивать некоторые особо важные сообщения, так чтобы они оставались без изменений и вне зависимости от того, что будет с чатом где они были размещены или даже с самим Телеграмом.

Чему мы научимся:

  1. (1-я часть) писать предупреждающее сообщение когда бот добавляют в чат

  2. посылать в чат приветственное сообщение когда боту дают права админа и он начинает работать

  3. читать сообщения из чатов или приватных бесед

  4. (2-я часть) обрабатывать сообщения из чатов, к которым он подключен или из приватных бесед

  5. обрабатывать команды

  6. (3-я часть) делать транзакцию для блокчейн и писать ответ на сообщение, что транзакция создана

  7. проверять подтверждение транзакции в блокчейн и изменять ранее посланный ответ на новое сообщение

Во-первых, что такое блокчейн? Представьте что есть такая волшебная книга-летопись, и волшебник летописец, который может вносить в нее записи. И что таких летописей множество и у каждой свой летописец. И волшебство в том, что если в одну из них внесена запись, то она магическим образом появляется во всех летописях и ее оттуда уже нельзя удалить или изменить. И все видят эту запись и всегда могут найти ее на заданной странице. К примеру, вы приходите к летописцу и говорите — “у меня есть мое стихотворение, которое я хочу увековечить и подарить миру, но так, чтобы мое авторство было учтено!” Волшебник, говорит — “добро, а сколько строк в твоем стихотворении?” — “100!” — отвечаете вы. “Тогда это будет стоить 5 волшебных монет”, — говорит он. “По рукам!”. Вы отдаете ему монетки, и волшебник вносит ваше стихотворения в волшебную летопись и она сразу появляется во всех волшебных летописях разом на текущей странице — с подписью внесшего её волшебника и с вашей подписью как автора.

Во-вторых, зачем нужно сообщения из чата сохранять в блокчейне? В первую очередь чтобы не зависеть от изменений в чате телеграм — сообщение уже записанное в блокчейн нельзя удалить или изменить. Например (кейс 1), как вы знаете, накануне задержали Павла Дурова во Франции с целью получить доступы к чатам телеграм. А что если к вашему чату будет получен доступ извне и все сообщения будут удалены или искажены? В свою защиту, Вы всегда сможете получить изначальные сообщения, если они сохранялись в блокчейн. Второй момент (кейс 2) — чтобы сохранить для истории, чтобы можно было через года знать что данные остались неизменны.

С блокчейном разобрались, идем дальше…

Сперва создаем учетную запись для своего бота, в которой задаем его имена и получаем ключи доступа. Это можно сделать вызвав официальный менеджер ботов Телеграм — @BotFather.

Теперь начинаем писать код

Для работы с ботом я использовал библиотеку com.pengrad.telegrambot https://github.com/pengrad/java-telegram-bot-api?tab=readme-ov-file#creating-your-bot

Создаем экземпляр бота так:

import com.pengrad.telegrambot.TelegramBot; …        TelegramBot bot = new TelegramBot(botToken);        // Спросить бота о его настройках:        System.out.println(bot.execute(new GetMe())); 

где botToken — это ключ доступа, полученный от @BotFather.

Пересылка сообщений в чат

Бот может отсылать сообщения в чат по его уникальному номеру, как простые текстовые, так и красиво отформатированные (например по Markdown). Код такой:

    protected BaseResponse sendSimpleText(long chatId, String textToSend) {         SendMessage message = new SendMessage(chatId, textToSend);         return sendMessage(message);     }      protected BaseResponse sendMarkdown(long chatId, String textToSend) {         SendMessage message = new SendMessage(chatId, textToSend);         message.parseMode(ParseMode.Markdown);         return sendMessage(message);     } 

Получение событий из чата

Для того чтобы не заморачиваться с доменным именем, мы будем использовать режим опроса телеграм-сервиса, получая с него все обновления и события из мира телеграм-чатов:

       // Подписка на обновления         bot.setUpdatesListener(updates -> {             // Обработка обновлений             try {                 updates.forEach(update -> onUpdateReceived(update));                 // return id of last processed update or confirm them all                 // Создание Обработчика ошибок             } catch (Exception e) {                 log.error("On TELEGRAM Updates error {}", e.toString());             }             return UpdatesListener.CONFIRMED_UPDATES_ALL;         }, e -> {             if (e.response() != null) {                 // Ошибка из Телеграма                 log.warn("TELEGRAM ERR: " + e.response().errorCode() + " - " + e.response().description());             } else {                 // Как видно проблема сети                 e.printStackTrace();             }         }); 

Теперь нам нужно задать обработку в функции onUpdateReceived и дело в шляпе!

Давайте сделаем простой обработчик вида:

   protected void onUpdateReceived(Update update) {          try {              Chat chat;             Chat origMessageChat;             User from;             User user;             Long chatId;             Long userId;             String text;              Integer updateId = update.updateId();             String lang = "ru";              ////////// MESSAGE             Message message = update.message();             String userName;            if (message != null) {                 // сюда приходит если:                 // или прямой чат пользователя с ботом                 // или в чате группы/супергруппы (не канал) бот добавлен администратором                  chat = message.chat();                 chatId = chat.id();                 chatErrorId = chatId;                 System.out.println(message.text());  …            }         }     } 

Теперь, для того чтобы бот смог читать сообщения в каком-либо чате — его нужно пригласить в этот чат и сделать администратором — только тогда он сможет получать уведомления о событиях и сообщениях в данном чате. Также можно писать команды боту напрямую через приватный чат с этим ботом.

Если мы запустим данную программу и пригласим бота в какой-либо чат и сделаем его админом, то все сообщения из этого чата будут печататься и в системный лог.

Кроме сообщений из чата, вы сможете получать события, такие как наделение правами пользователя, приглашения в чат и т.д.

Давайте теперь научим нашего бота определять — пригласили ли его в чат и наделили ли правами администратора. Для этого в код обработчика вставим:

            // приглашения и удаления из групп             ChatMemberUpdated myChatMember = update.myChatMember();             if (myChatMember != null) {                 chat = myChatMember.chat(); // в каком чате действие произошло                 chatId = chat.id();                 chatErrorId = chat.id();                 from = myChatMember.from(); // кто это сделал                  log.warn("User from: " + GSON.toJson(from).toString());                  ChatMember newChatMember = myChatMember.newChatMember();                 user = newChatMember.user();                 ChatMember.Status oldStatus = myChatMember.oldChatMember().status();                 ChatMember.Status newStatus = newChatMember.status();                 if (oldStatus.equals(newStatus))                     return;                  if (user.username().equals(botUserName)) {                      if (newStatus.equals(ChatMember.Status.kicked) || newStatus.equals(ChatMember.Status.left)) {                         // нас удалили из группы                         Integer untilDate = newChatMember.untilDate(); // 0 - просто удалили                         log.error("kicked from " + chat.title() + " by User " + from.username());                          // Конкретный пользователь известен только когда удаляют администратора! Иначе бот кикает и не понятно кто тебя кикнул                         if (!from.isBot())                             sendSimpleText(from.id(), from.username() + ", спасибо за использование наших услуг в чате \"" + chat.title() + "\". Надеемся на продолжение сотрудничества в будущем.");                      } else if (newStatus.equals(ChatMember.Status.administrator)) {                         // нас сделали администратором                         // Тут известен конкретный пользователь кто пригласил                         if (!from.isBot())                             sendSimpleText(from.id(), from.username() + ", спасибо за допуск меня к работе в чате \"" + chat.title() + "\". Надеюсь быть полезным...");                      } else if (newStatus.equals(ChatMember.Status.member)) {                         // нас внесли в группу или понизили из админа до обычного пользователя                         if (!from.isBot())                             sendSimpleText(from.id(), from.username() + ", моя работа в чате \"" + chat.title() + "\" прекращена. Жду назначения администраторам снова...");                      }                      log.info("status:" +  newStatus.name());                  } else {                     // Это не про меня                 }              } 

Приватный чат с ботом

Так же можно понять что кто-то общается с ботом в приватной беседе (когда кто-то общается напрямую с ботом). Приватный чат можно определить так:

if (chat.type().equals(Chat.Type.Private))

Обработка пересланных сообщений из каналов

Интересный режим, когда связаны чат для обсуждения и новостной канал. Тогда сообщения из канала автоматически падают в чат обсуждений. Поймать их можно так:

                if (Boolean.TRUE.equals(message.isAutomaticForward())) {                     // это сообщение пришло из канала к которому привязан данный чат (супергруппа)                     // это основной чат откуда пришло сообщение - с именем и правильным UserName                     origMessageChat = message.senderChat(); 

Итак, в первой части статьи мы разобрались как посылать сообщения в чаты, как их читать и как определять что бот добавили в чат и наделили правами администратора.

Полный код телеграм-бота (супер-класс и подкласс, реализующий посылку транзакций в блокчейн) расположен в Gillab репозитории проекта Erachain — внутри ноды блокчейн. Вызвать бот в телеграм-мессенджере можно по имени @blockchain_storage_bot — вы можете посмотреть как он работает, чтобы лучше понять код бота.

В комментах пишите вопросы — будем делать вторую часть статьи


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


Комментарии

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

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