Постановка задачи

Как известно, бот это программа на компьютере, которая взаимодействует с https://api.telegram.org и притворяется человеком. Разумеется, у неё есть данные в своей собственной базе данных или типа того. Если этот компьютер внезапно исчезнет, то хотелось бы, чтобы верные друзья в другом месте и с другим компьютером «засунули флешку» и запустили этого же бота из другого места. И, разумеется, для этого нужно передать актуальные данные из старого места в новое. Разумеется, для этого существуют какие-нибудь проверенные временем дорогостоящие решения, но это всё можно организовать прямо через Телеграм. И не спрашивайте, зачем это нужно лично вам.

Файлы

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

Первый способ. Через сообщения

Команда sendMessage не только посылает сообщение. Она еще и возвращает номер этого сообщения. И по паре чисел (Id чата, номер сообщения) это самое сообщение можно регулярно изменять (например, записывая туда file_id резервной копии данных) посредством editMessageText, и потом прочитать из нового экземпляра бота посредством forwardMessage (да, эта команда ещё и возвращает текст передаваемого сообщения). Так вот, эта пара (Id чата, номер сообщения) не меняется, и это значит, что можно сначала запустить бота, он сделает сообщения (в какой-нибудь приватный канал) для хранения file_id резервной копии и покажет пару чисел (Id чата, номер сообщения). Затем следует вписать эту пару чисел в «бот на флешке» и раздать её своим верным друзьям. Это вполне работающий метод, но вот это вот: «сначала запустить потом изменить код бота» – несколько неудобно. Но есть и

Второй способ. Через меню

Как известно, у бота есть меню. Когда-то давно его можно было делать только через @BotFather, но, потом появилась setMyCommands, чтобы установить меню прямо из бота, и getMyCommands, чтобы прочитать то, что было в это самое меню установлено. Итак: бот делает резервную копию и записывает file_id этой копии в какой-нибудь приватный канал. Потом узнает пару чисел (Id чата, номер сообщения) и записывает их в меню в виде как бы пояснения к команде.

При запуске бота с другого компьютера, бот сначала сделает getMyCommands, узнает ту самую пару чисел, сделает forwardMessage, узнает file_id, скачает данные, и как будто ничего и не случилось.

Понятно, что эта пара чисел будет болтаться перед глазами всех пользователей и вызывать ненужные вопросы, но в июне 2021 года у setMyCommand появилось поле language_code и возможность делать разные меню для разных пользователей с разным языком в системных настройках. Экспериментально установлено, что в качестве языкового кода можно указывать несуществующие языки типа «xy» и это значит, что пользователи ничего лишнего не увидят и вопросов не зададут.

Более того. Можно организовать автозапуск запасных ботов и обойтись без верных друзей. Итак: Основной бот запущен в рабочем режиме и, кроме прочего, регулярно пишет что-нибудь меняющееся в меню или в сообщение с известным номером. Например, текущее время. Запасные боты (запущенные в других местах) находятся в спящем режиме, они ничего не делают но регулярно (но через случайные промежутки времени) смотрят это «текущее время». Если они замечают, что оно давно не обновлялось, то первый обнаруживший это бот запустится в рабочем режиме. И как будто ничего и не случилось...

И не спрашивайте, зачем это может понадобиться лично вам.

Комментарии (16)


  1. vvzvlad
    19.01.2023 02:11

    Я бы хотел где-нибудь держать простую бд ключ-значение, чтобы бот на сервере не хранил состояние, а был чистым кодом. Может, в каком-нибудь сообщении? Жалко у ботов нет saved messages.


    1. Hungryee
      19.01.2023 03:22

      В обертках вокруг телеграмм апи, по крайней мере на питоне, есть встроенная база данных in-memory с сохранением в файл

      Про какой saved messages может идти речь если нужное сообщение можно просто сохранить в виде айди


      1. vvzvlad
        19.01.2023 03:36

        В обертках вокруг телеграмм апи, по крайней мере на питоне, есть встроенная база данных in-memory с сохранением в файл

        Это где такая? В telebot не нашел. Ну и она опять же, сохраняет на своем сервере, и кроме кода и токена бота надо еще и файл с бд хранить, заботиться об актуальности и все такое.

        Про какой saved messages может идти речь если нужное сообщение можно просто сохранить в виде айди

        Куда сохранить?


        1. maksiplus19
          20.01.2023 14:39

          python-telegram-bot иммет отдельные объекты для данных бота, чата и юзера и может сохранять их в pickle-файл


    1. ZeroDX
      19.01.2023 05:15

      А нельзя сделать для бота отдельный кпнал, в который он бы и писал свою базу в виде сообщений?


      1. aafin Автор
        19.01.2023 08:09

        Писать то он может, а вот как доставать.. Номера сообщений мало предсказуемы.


        1. PrinceKorwin
          19.01.2023 10:46

          Можно сделать одно pinned сообщение для этого


        1. souls_arch
          20.01.2023 11:43

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


          1. aafin Автор
            20.01.2023 12:00

            Боты не умеют искать. Могут только прочитать сообщение с заранее известным номером. Да и то не совсем прочитать. Чтение это побочный эффект от fodwardMessage и делать это слишком часть бот тоже не может.


    1. art_sd
      19.01.2023 05:16

      Можно попробовать сделать что-то на основе google script apps. Оно позволяет сделать и выставить в мир АПИ, а также в разумных пределах к нему обращаться. Сам скрипт в процессе обработки запроса может ходить в ваши spreadsheets, что-то оттуда выбирать, что-то туда дописывать или логировать.


      1. BasiC2k
        19.01.2023 17:23

        Для получения от ТГ сообщений (updates), есть три варианта и все они не подходят в случае Apps Script:

        1. webhook - не подходит, т.к. у вас нет public key certificate Google;

        2. long polling - упрётся в квоты для выполнения скриптов;

        3. регулярные запросы - возможно выполнение по триггеру. Минимальное время проверки - раз в минуту, что не очень оперативно. Также упрётся в дневные квоты для запуска триггеров.


        1. aafin Автор
          19.01.2023 19:05

          Много лет назад через вебхуки оно таки работало. Не знаю как сейчас. https://youtu.be/mKSXd_od4Lg


        1. art_sd
          19.01.2023 19:48

          Насколько я понял, речь была не об обработке каждого сообщения, а о разовой втяжке какого-то конфига ботом при инициализации. Здесь вполне может получиться не упереться в квоты.


  1. kaskar2008
    19.01.2023 05:16
    +2

    Очень много вопросов...

    Но подсвечу то, что первым пришло в голову:

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

    Если бот падает из-за потери связи с бд/сервисом/сокетом, то нужно зеркалить именно их, а не бота. Это всего лишь клиент. Все равно, что в браузере запускать сразу 2 сайта в разных вкладках и если на одной вкладке на сайте упало соединение с бэком, то закрыть вкладку и переключиться на вторую. Бессмысленно :)

    Если бот падает, потому что сам сервер работает коряво или на нем падает инет - тут лучше поменять сервак и выбрать тот, у которого аптайм ближе всего к 100. В ситуации с падающим сервером, конечно, можно притянуть варик поднимать "теневых" ботов на других серверах, но тогда вместо 3-4 оплаченных серверов лучше взять только 2, но с высоким аптаймом и при падении пойти смотреть, что там опять случилось (если сервак дома, например). Вероятность падения одновременно 2х серверов, никак не связанных друг с другом, как говориться "крайне мала".

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

    В остальном идея с файлом имеет место быть. Спасибо за инфу по некоторым командам и что куда можно передавать и за описание собственного опыта, кому-то точно это пригодится.


  1. iWeezy
    19.01.2023 05:16

    У ботов как и у пользователей не хватает автоматической архивации, у пользователей хотябы есть сама функция... Которая сохраняет не только данные но и составляет из них html страницу повторяющую мессенджер.


  1. nfirex
    19.01.2023 05:17
    -1

    Не знаю зачем это мне лично может понадобиться, но интересный хак!

    Я как понимаю, боты основаны на поллинге, и тем самым просто решается проблема отсутствия общей базы данных?

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