Телеграмм-бот на python

Как настроить бот, чтобы работать непрерывно

Если вы запустите свой бот в REPL.IT, а затем закройте вкладку, он работает, ваш бот будет прекратить работу.

Но есть два способа постоянно поддержания бота, даже после закрытия веб-бауза.

Первый путь и простейший способ – подписаться на оплаченный план в REPL.IT. Их самый дешевый платный план называется планом хакера, и он включает в себя пять всегда на рентам.

Вы можете получить три месяца бесплатно, используя эту ссылку (ограничена первыми 1000 человек):

После того, как вы подписались на этот план, откройте refl и щелкните по названию вверху. Затем выберите опцию «Всегда на».

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

Вот что за reft.it docs говорят:

Чтобы постоянно поддерживать бот, мы будем использовать другой бесплатный сервис, называемый Robot Womptime At https://uptimerobot.com/ Отказ

Робот безотказной работы может быть установлен на веб-сервер Bot на REPL.IT каждые 5 минут. С постоянными звонками, бот никогда не войдет на сцену сна и будет просто продолжать работать.

Поэтому мы должны сделать еще две вещи, чтобы наш бот постоянно работать:

  1. Создайте веб-сервер в REPL.IT и
  2. Установите Robot Roomtime, чтобы непрерывно пинговать веб-сервер.

Как создать веб-сервер в REPL.IT

Создание веб-сервера проще, чем вы можете подумать.

Чтобы сделать это, создайте новый файл в вашем проекте под названием Отказ

Затем добавьте следующий код:

from flask import Flask
from threading import Thread

app = Flask('')

@app.route('/')
def home():
    return "Hello. I am alive!"

def run():
  app.run(host='0.0.0.0',port=8080)

def keep_alive():
    t = Thread(target=run)
    t.start()

В этом коде мы используем колбу для запуска веб-сервера. Сервер возвращает «Привет. Я жив». всем, кто его посещает. Сервер будет работать на отдельной резьбе с нашего бота. Мы не будем обсуждать все здесь, так как остальные не имеют права актуальны для нашего бота.

Теперь нам просто нужен бот для запуска этого веб-сервера.

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

from keep_alive import keep_alive

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

stear_alive ()

Когда вы запускаете BOT на REPL.IT После добавления этого кода, откроется новое окно веб-сервера. Для веб-сервера, показанного URL. Скопируйте URL, чтобы вы могли использовать его в следующем разделе.

Как настроить робот времени безотказной работы

Теперь нам нужно настроить робот безотказной работы для Ping на веб-сервере каждые пять минут. Это заставит бот постоянно работать.

Создайте бесплатный аккаунт на https://uptimerobot.com/ Отказ

Как только вы вошли в свою учетную запись, нажмите «Добавить новый монитор».

Для нового монитора выберите «HTTP (S)» в качестве типа монитора и назовите его, что вам нравится. Затем вставьте в URL-адрес вашего веб-сервера от REPL.IT. Наконец, нажмите «Создать монитор».

Были сделаны! Теперь бот будет работать непрерывно, чтобы люди всегда могли взаимодействовать с ним на REPL.IT.

Часть 2 Написание кода

sudo apt-get install python python-pip

Далее воспользуемся системой управления пакетами PIP, которая используется для установки и управления программными пакетами, и установим библиотеку PyTelegramBotAPI (Telebot):

Создадим логику работы нашего бота. Используя полноценный IDE или простой текстовый редактор создадим файл ourbot.py и заполним его необходимой логикой.

import telebot 

bot = telebot.TeleBot(‘851216368:AAG6_JHHsIqAK-lX2CxOWQHTAM109zdrcZM’)

Теперь создадим метод, для получения сообщений.

Возможности PyTelegramBotAPI позволяют отправлять боту аудио (content_types=[‘audio’), видео (content_types=[‘video’), документы (content_types=[‘document’), текст (content_types=[‘text’), географический адрес (content_types=[‘location’), данные контакта (content_types=[‘contact’) и стикеры (content_types=[‘sticker’).  Мы, для простоты опыта, будем общаться с ботом только текстом:

@bot.message_handler(content_types=)
def handle_text_messages(message):

Теперь рассмотрим логику обработки наших текстовых сообщений. Мы хотим захардкодить простое общение бота с пользователем: бот должен уметь здороваться, когда с ним здороваются, уметь отвечать на вопросы «Кто ты?», «Как тебя зовут?» и «Что ты умеешь?».

Видео курсы по схожей тематике:

UX/UI Design Стартовый

Артур Рыгус

UX/UI Design мобильных приложений

Владислав Шевченко

Создаем игру типа “Pokémon Go“

Роман Самчук

    if message.text == «Привет»:
        bot.send_message(message.from_user.id, «Привет»)
    elif message.text == «Кто ты?»:
        bot.send_message(message.from_user.id, «Я тестовый чатбот для учебного примера.»)
    elif message.text == «Как тебя зовут?»:
        bot.send_message(message.from_user.id, «Меня зовут MyFirstTestBot.»)
    elif message.text == «Что ты умеешь?»:
        bot.send_message(message.from_user.id, «Я умею отвечать на несколько простых вопросов — кто я, как меня зовут и что я умею делать.»)
    else:
        bot.send_message(message.from_user.id, «Я тебя не понимаю. Напиши что-то другое.»)

После тела метода, обрабатывающего наши запросы к боту, добавим вызов метода:

bot.polling(none_stop=True, interval=0)

Задачей этого метода является создание потока, в котором бот отправляет запросы на сервер, уточняя таким способом, не писал ли ему кто-то сообщение. Параметр none_stop: False означает, что наша программа будет продолжать отправлять запросы на сервер после получения сообщения об ошибке от сервера Telegram.

Сохраним наш код:

Мы можем протестировать работу нашего бота, запустив его код в той IDE, в которой мы писали. И написав нашему боту в мессенджере.

Все работает.

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

Вопросы заливки нашего простого бота на сервер мы рассмотрим в следующей статье.

Плацдарм для бота

Напишем элементарного эхо-бота на aiogram с поллингом, чтобы бегло ознакомиться с фреймворком. Прежде всего, добавим нужные импорты (предполагается, что мы используем Virtual Environment, подробнее о нём – в уроке №0):

Теперь создадим объект бота. А за хэндлеры здесь отвечает специальный Диспетчер:

Далее напишем простейший хэндлер, повторяющий текстовые сообщения:

Началась магия.Во-первых, как я написал чуть выше, за хэндлеры отвечает диспетчер (dp).Во-вторых, подхэндлерные функции в aiogram асинхронные (async def), вызовы Bot API тоже асинхронные, поэтому необходимо использовать ключевое слово .В-третьих, вместо можно для удобства использовать без указания и , чтобы бот сделал «ответ» (reply), либо аналог , чтобы просто отправить в тот же чат, не создавая «ответ». Само выражение в хэндлере пустое, т.к. нас устроят любые текстовые сообщения.

Наконец, запуск!

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

Коэффициент Отиаи

TF-IDF — это преобразование, применяемое к текстам для получения двух вещественных векторов в векторном пространстве. Тогда мы можем получить коэффициент Отиаи любой пары векторов, вычислив их поэлементное произведение и разделив его на произведение их норм. Таким образом, получается косинус угла между векторами. Коэффициент Отиаи является мерой сходства между двумя ненулевыми векторами. Используя эту формулу, можно вычислить схожесть между любыми двумя текстами d1 и d2.

Cosine Similarity (d1, d2) =  Dot product(d1, d2) / ||d1|| * ||d2||

Здесь d1, d2 — два ненулевых вектора.

Пришло время перейти к решению нашей задачи, то есть созданию чат-бота. Назовем его «ROBO».

Почему Django?

Многие скажут: ведь Django — очень большой фреймворк! Зачем забивать гвозди микроскопом? У меня на это есть несколько аргументов:

  1. В Django есть поддержка баз данных, встроенная админка и огромная библиотека плагинов на все случаи жизни. Теория от YCombinator учит использовать готовые компоненты вместо написания своих с нуля, так как это позволит сильно сэкономить время на старте и не придется наступать на грабли, на которые уже кто-то наступал.

  2. Если какие-то модули не нужны сейчас, то они могут пригодится в будущем. Например, ваш бот стал популярным и появились фродеры: админка сильно упростит анализ данных системы и позволит расширить вашу команду «не программистами».

  3. Django проверена миллионами разработчиков. Написаны тысячи сайтов с документацией и примерами. Понятно как ее правильно деплоить в продакшн и масштабировать.

Каждый раз, разрабатывая Телеграм бота сложнее, чем hello-world, нужна база данных как минимум, чтобы хранить информацию о всех пользователях, которые пользуются ботом (да, на данный момент Telegram Bot API не выдает даже такую базовую статистику). Как только ботом начинают пользоваться десятки тысячи людей, понадобится как-то масштабировать систему — возможно, одного сервера не хватит.

Если логика вашего Телеграм бота сложна, вам понадобятся background tasks. Например, чтобы разослать тысячам пользователей сообщение с рекламой анонсом новых возможностей бота. В экосистеме Django такие задачи легко реализуются с помощью модуля Celery. В качестве его брокера я люблю использовать Redis, а для периодических задач модуль Django-celery-beat (появляется возможность через админку просто накликать, какую функцию по какому крону вызывать).

Телеграм бот в продакшене: особенности

  1. База данных должна быть нормальная (не текстовый фай, не sqlite, не in memory). Например, Postgres.

    1. Это обеспечит стабильность и уменьшит шансы, что все данные внезапно потеряются.

  2. Если что-то упало, чтобы поднялось само.

    1. Желательно при этом собирать ошибки, например, через Sentry.

  3. Настроен CI, который автоматизирует превращение нового кода в рабочий сервис.

    1. Я использую GitHub Actions, который заставляет Dokku сделать git pull и начать собирать проект, когда кто-то закоммитил в мастер. Подробнее об этом в конце статьи.

  4. Есть возможность легко масштабировать проект по необходимости. В частности — обработчики сообщений пользователей.

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

Вебхуки

Существуют два способа работать с Telegram Bot API (да и вообще со всеми микросервисами): пулинг и вебхуки.

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

  2. Webhook — это когда вы говорите серверам Телеги: присылай мне на мой URL события сам.

Первый способ сильно упрощает разработку ботов, в то время как второй требует поднятого веб-сервера, который будет слушать входящие сообщения и засовывать из в handlers, которые вы описали. Более того, серверы Телеграмма требуют настроенного HTTPS шифрования, поэтому, например, настроить вебхуки на ваш домашний IP без настроенного DNS вряд ли получится. Решение с ngrok поможет лишь протестировать работу бота через вебхуки, в продакшене его, конечно же, не надо использовать.

Если polling — отлично помогает при разработке телеграм бота, то Webhook отлично подходит для продакшена: в случаях наплыва пользователей, можно запустить два инстанса с вашими хендлерами, а заранее настроенный load balancer сам будет параллелить между ними входящие события по вебхуку (такая функция есть как в docker-compose, так и в большинстве современных облачных PaaS, таких как Heroku, Google App Engine или Digital Ocean App Platform).

Как скрестить Django и Telegram bot

Как работать с вебхуками в случае с Django? Просто создать view (), который получит входящий ивент от Телеграмма и отправит его в ваш обработчик событий (куда вы вешали handlers — логику реакций бота на разные действия пользователей) ().

Стоит создать Django Model для . И заполнять ее как минимум каждый раз, когда кто-то нажимает команду /start. В этом случае, все пользователи вашего бота будут аккуратно складываться в базу данных, и вы сможете как минимум их посчитать. Для этого рекомендую создать , который будет создавать либо возвращать существующий объект класса User .

Функционал для логирования

Согласно тексту справки, бот должен уметь делать две вещи:

  1. Если вы отправляете сообщение боту, он должен где-то его сохранить.
  2. При отправке боту команды он должен отправить вам последнее сообщение.

Для этого мы будем использовать встроенную в Replit базу данных ключ-значение. Начнем с импорта API:

from replit import db

Модуль db — это объект, который ведет себя как словарь, но сохраняет свое содержимое между запусками. Он также сериализует свои ключи в виде строк.

Мы хотим хранить зарегистрированные сообщения в определенном порядке, но объект по своей сути не упорядочен (будучи словарем). Поэтому мы создадим вспомогательную функцию, которая может получать самый большой ключ (при условии, что мы будем использовать только числовые индексы). Добавим эту функцию перед определением функции :

def latest_key():
    ks = db.keys()
    if len(ks):
        return max(map(int, ks))
    else:
        return -1 

Функция получает все ключи из нашей базы данных (модуль ). Если в ней есть ключи, они преобразуются в целые числа и возвращается максимальное из них. Если ключей нет, то возвращается .

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

def log(update: Update, context: CallbackContext) -> None:
    db = update.message.text 

Этот обработчик получает последний ключ из базы данных, увеличивает его на единицу и создает новую пару ключ — сообщение.

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

dispatcher.add_handler(MessageHandler(Filters.text & ~Filters.command, log))

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

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

def fetch(update: Update, context: CallbackContext) -> None:
    update.message.reply_text(db.get(str(latest_key()), 'No Messages yet.'))

Мы можем зарегистрировать его вместе с обработчиками остальных команд. Добавьте данную строку после уже существующих строк :

dispatcher.add_handler(CommandHandler("fetch", fetch))

Polling vs Webhook

Если бы не противостояние polling vs webhook и некоторые сложности (отчасти надуманные) с webhook’ом, в этой статье не было бы необходимости. Раз это имеет принципиальное значение, давайте разберемся подробнее.

Что такое бот и как он общается с Телеграмом? Очевидно, бот это программа, которая работает на вашем компьютере или сервере. А общение с Телеграмом происходит методами отправки и получения сообщений. И если с отправкой сообщений примерно все ясно, вариант один — послать (адрес “куда” мы знаем). То вариантов получения ботом сообщений от Телеграма два.

Первый — это опрос (буквальный перевод слова polling) сервера Телеграма на наличие сообщений для бота. Второй — это “почтовый ящик” с ip-адресом (webhook — можно перевести как веб-ловушка), на который приходят сообщения от сервера Телеграма.

Самая простая аналогия с реальной почтой. Пусть почта (почтовое отделение) — это сервер Телеграма, а вы — это ваш бот. Тогда, в первом случае (polling) вам приходится ходить на почту за корреспонденцией. И если хотите получать сообщения без задержек, то придется не ходить, а буквально бегать без передышек взад и вперед. Как понимаем, жить на почте в ожидании сообщений запрещено! Во втором случае вы сообщаете почтовому отделению свой домашний адрес и ждете корреспонденцию спокойно дома, попивая чай или покуривая бамбук.

Конечно, для человека первый вариант кажется самым суровым. Но, говоря между нами, если бегать за сообщениями мы посылаем железку с кодом, то нам должно быть все равно. И так бы и было, если бы не одна проблема. Время от времени, почта (сервер Телеграма) то закрывается на обед, то переезжает. И у вас в первом варианте (polling) происходит трагедия, которая в реальном мире ботов заканчивается их зависанием и сбоем.

Во втором же случае “почтового ящика” с адресом (webhook’ом) такого не происходит. Потому что ни вы, ни ваш бот, никуда не ходите, а просто ждете. И вам все равно, куда переехало почтовое отделение, потому что почту вам приносит почтальон.

Таким образом, по объему кода (см. ссылку выше) первый вариант кажется проще. А второй логичнее, но тяжелее. Для его реализации нужно завести адрес, подтвердить его достоверность и поднять веб-сервер, на который и будут приходить сообщения от Телеграма.

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

Я сначала не поверил, что проблема настолько серьезна. И сделал вариант с polling’ом, предполагая, что как-нибудь позже перепишу на webhook’и. Но это не сработало. На моем домашнем компе с macOS бот работал без проблем и час и два (конечно, с VPN) и не падал. Но стоило мне перенести его на облачный сервер на Linux’е он не мог проработать и 20 минут. Я пытался решить эту проблему разными путями и настройками, но получал лишь разный код ошибок. Селяви, это Телеграм. Потеряв день, пришлось взяться за webhook’и, не откладывая на потом. В конце концов, я же хотел запустить бот на сервере сейчас, а не через год.

Итак, что такое чат-бот?

Чат-бот — это программа, которая выясняет потребности пользователей, а затем помогает удовлетворить их (денежная транзакция, бронирование отелей, составление документов). Сегодня почти каждая компания имеет чат-бота для взаимодействия с пользователями. Некоторые способы использования чат-ботов:

  • предоставление информации о рейсе;
  • предоставление пользователям доступа к информации об их финансах;
  • служба поддержки.

Возможности безграничны.

История чат-ботов восходит к 1966 году, когда Джозеф Вейценбаум разработал компьютерную программу ELIZA. Программа подражает манере речи психотерапевта и состоит лишь из 200 строк кода. Пообщаться с Элизой можно до сих пор на сайте.

Создание скелета бота

Теперь, когда все настроено, мы можем приступить к программированию! Начнем с нашего файла :

import os

from telegram import Update #upm package(python-telegram-bot)
from telegram.ext import Updater, CommandHandler, MessageHandler, Filters, CallbackContext  #upm package(python-telegram-bot)


def help_command(update: Update, context: CallbackContext) -> None:
    htext = '''
Welcome
Send a message to store it.
Send /fetch to retrieve the most recent message'''
    update.message.reply_text(htext)


def main():
    updater = Updater(os.getenv("TOKEN"))

    dispatcher = updater.dispatcher
    dispatcher.add_handler(CommandHandler("start", help_command))
    dispatcher.add_handler(CommandHandler("help", help_command))

    updater.start_polling()

    updater.idle()


if __name__ == '__main__':
    main() 

Сначала мы импортируем модуль , чтобы получить доступ к токену как переменной окружения.

Затем мы импортируем некоторые классы из библиотеки Telegram.

Комментарии, начинающиеся с , не являются обязательными. Они используются Replit для загрузки правильного пакета. В общем случае это не нужно, но здесь необходимо, потому что подобных библиотек Telegram очень много.

Функция запускается всякий раз, когда пользователь отправляет нам команду или . Команда также выполняется автоматически, когда новый пользователь запускает ваш бот (как мы ранее запускали ). Бот будет знать, как использовать эту функцию, потому что мы сообщим ему об этом позже в теле функции .

В функции main мы инициализируем экземпляр класса , который использует наш токен.

updater = Updater(os.getenv("TOKEN"))

— это класс, который будет постоянно проверять Telegram на наличие новых сообщений в нашем боте.

Когда получает новое сообщение, он передает его в класс . Тот проверяет, есть ли у нас подходящий обработчик для данного сообщения. Как уже упоминалось выше, нужно задать обработчик для команд и . Мы cделаем это при помощи функции , например:

dispatcher.add_handler(CommandHandler("start", help_command))

и

dispatcher.add_handler(CommandHandler("help", help_command))

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

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

updater.start_polling()

Важно знать, что — это неблокирующая функция. Это означает, что код в ней не прекращает выполнение

Он будет исполняться, пока программа не завершится.

Другими словами, если мы оставим это в качестве последней строки функции , код будет выполнен, а затем немедленно завершится, потому что больше ничего не блокирует его. Поэтому, чтобы наш бот не прекращал прослушку, мы используем строку , чтобы заблокировать скрипт, пока мы слушаем.

Получение самоподписанного сертификата SSL для IP

Надо сказать, что в интернете вокруг темы ssl сертификатов для Телеграма сплошной хоррор. Как сказал Михаил Лермонтов на этот счет:

“Смешались в кучу кони, люди,
И залпы тысячи орудий
Слились в протяжный вой…”

Если почитать, что пишут в интернете, то получится, что если бот на webhook’ах не работает, то во всем виноваты неправильно полученные сертификаты. А еще, их нельзя регистрировать на ip. И вообще самоподписанные сертификаты Телеграм не принимает. И даже, если он примет сертификат, то это не значит, что ваш бот будет работать, и Телеграм даже ошибку не пришлет.

Вот такие страшилки. К чему я это пишу? К тому, что эти страшилки обошлись мне в еще одни потерянные сутки, даже пришлось пропустить просмотр “Хоббита”. Мой бот первоначально отказывался работать на webhook’ах. Это произошло из-за моих ошибок при его размещении на сервере (тогда я этого не знал). Но из-за страшилок выше я искал проблему не там, сосредоточившись на решении проблем с ssl-сертификатами, которых не было. Зато я приобрел бесценный опыт. Я нарегистрировался сертификатов на годы вперед как на доменные имена, так и на ip, как самоподписанные, так и платные, как в виде двух файлов, так и в виде четырех. Я узнал, какие бывают сертификаты и как делать из них цепочки. Надеюсь, мне это когда-нибудь пригодится.

Одно хорошо, вам на эти грабли наступать не надо, я это уже сделал за вас. Вполне допускаю, что как не бывает “дыма без огня”, так и для таких страшилок был повод. Но на текущий день ситуация похоже устаканилась.

Прямо сейчас мы с вами получим ssl-сертификат самым удобным для нас путем, а именно на ip (а не на доменное имя), самоподписанные (т.е. бесплатно) и обойдясь всего одной строчкой без всяких сайтов.

В терминале (который мы еще не закрыли) подготовьте отдельный каталог, в который мы сохраним файл сертификата и приватный ключ. Зайдите в этот каталог и из него вызовите следующую команду.

В итоге вы получите два файла в каталоге, из которого запустили эту команду. Один файл url_cert.pem и есть ваш сертификат, а второй приватный ключ url_private.key. В коде бота для них выделены переменные WEBHOOK_SSL_CERT и WEBHOOK_SSL_PRIV соответственно. Не забудьте вписать пути доступа к этим файлам вместе с наименованиями. Скачайте копии и сохраните их у себя на будущее.

Не закрывайте терминал.

Эпилог

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

Приведу пример, цифра 10 000 сама по себе не страшна, но что будет если мы приправим ее небольшим контекстом, 10 000 смертей, выглядит страшнее, не правда ли? Если дальше продолжить эксперимент с добавлением контекста то можно дойти до ужасающих результатов, допустим “10000 новых смертей от коронавируса в России в день” и тогда мы получим то, что называется паника, которое настолько сильна, что подавляет развитие разума и логического мышления, заменяя его подавляющим чувством тревоги и неистового возбуждения, совместимого с животной реакцией «дерись или беги».
Именно поэтому стоит критически анализировать информацию, особенно в наше время.

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

Спасибо тем кто дочитал до конца за внимание. Приятного кодинга!

Признавая сообщения, которые мы уже видели

Вместо того, чтобы просить телеграммы для всех наших недавних сообщений с каждым вызовом, а затем пытаться понять, какие из них нас интересуют, мы можем сказать телеграмме, что мы уже обработали определенные сообщения, и что мы хотим прекратить получать их как часть звонки. Каждое обновление имеет поле, и это инкрементные (более поздние сообщения имеют более высокие числа). Когда мы делаем API Call, мы можем необязательно пройти аргумент и дать как значение. Это говорит о телеграмме, которую мы уже видели и обработали это сообщение и что мы не хотим этого снова. Это также означает, что телеграмма никогда не отправит нам никаких предыдущих сообщений (сообщения с более низким ), поэтому мы должны убедиться, что мы действительно закончили всеми сообщениями, прежде чем делать это.

Измените наш бот следующим образом:

Добавьте дополнительное Смещение Параметр на нашу функцию getupdate. Если это указано, мы передадим его на API Telegram, чтобы указать, что мы не хотим получать сообщения с меньшими идентификаторами, чем это. Модифицированная функция должна выглядеть так:

def get_updates(offset=None):
    url = URL + "getUpdates"
    if offset:
        url += "?offset={}".format(offset)
    js = get_json_from_url(url)
    return js

Добавьте функцию, которая рассчитывает наивысший идентификатор всех обновлений, которые мы получаем от GetUpDates. Это должно выглядеть следующим образом.

def get_last_update_id(updates):
    update_ids = []
    for update in updates:
        update_ids.append(int(update))
    return max(update_ids)

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

Добавьте функцию, чтобы отправить ответ Echo для каждого сообщения, которое мы получаем. Это должно выглядеть следующим образом:

def echo_all(updates):
    for update in updates:
        try:
            text = update
            chat = update
            send_message(text, chat)
        except Exception as e:
            print(e)

Обновите код в Главная () Так что это выглядит так:

def main():
    last_update_id = None
    while True:
        updates = get_updates(last_update_id)
        if len(updates) > 0:
            last_update_id = get_last_update_id(updates) + 1
            echo_all(updates)
        time.sleep(0.5)

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

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

Попробуйте изменения, перезапустив скрипт Python и отправку некоторых сообщений на свой бот – вы должны увидеть, что он работает как раньше, но теперь это не имеет значения, если вы отправляете дубликаты сообщений или отправляете сообщения слишком быстро, оба из которых являются большие улучшения Отказ

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

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

Adblock
detector