Здравствуйте формучане! Сегодня я бы хотел обсудить с вами довольно важную и в то же время интересную тему насчет телеграм ботов:-)
Начнем пожалуй вообще с конструкции самого простого бота на Python:
Python:
from aiogram import Bot, types
from aiogram.dispatcher import Dispatcher
from aiogram.utils import executor
#=============Модули для работы==================#
from config import TOKEN
bot = Bot(token=TOKEN)
dp = Dispatcher(bot)
@dp.message_handler(commands=['start'])
async def process_start_command(message: types.Message):
await message.reply("Привет!\nНапиши мне что-нибудь!")
if __name__ == '__main__':
executor.start_polling(dp)
Это простой бот ,который пишет вам "Привет! Напиши мне что-нибудь!" при команде "/start". Обратите внимание на последнюю строку :
Python:
executor.start_polling(dp)
Ошибка 504 gateway timeout – это код состояния HTTP, который появляется, когда один сервер не получает своевременный ответ от другого сервера, который действует как шлюз или прокси. Проще говоря, это означает, что сервер не смог выполнить ваш запрос в течение заданного периода времени.
И ваш бот/боты просто крашнутся
Давайте вообще разберем, чем отличается метод Polling от метода WebHook.
Polling - это метод ,при котором ваш телеграм бот делает постоянные запросы к серверу телеграм, и из-за этого часто возникают ошибки с timeout
WebHook - это метод,при котором не мы отправляем запросы к серверу в ,а сервер Telegram оповещает нас ,если произошло что-то новое. Для этого метода нужен будет свой сервер!(но мы его напишем чуть позже)
Если вообще простым языком,то допустим ,что почта это Telegram ,а мы с вами Polling . Мы постоянно будем бегать на почту ,чтобы спросить ,не пришло ли нам новое письмо,а если мы будем в качестве WebHook'а, то мы будем сидеть на попе ровно и ждать,пока почта сама нас уведомит о новом письме. Думаю,что так понятней! Но как же работать через вебхуки?
Начинаем работу с сервером и SSL-сертификатами!
Для начала,небольшое отступление:
-При работе с webhook ,нам будет нужен SSL сертификат,иначе telegram просто не примет наш сервер на которой он должен будет отправлять запросы!
Начнем!
Создаем сертификат
Повторюсь: я не считаю себя супер-мега-крутым специалистом в айти, возможно, я что-то делаю неправильно, тем не менее, это работает и выглядит вполне прилично. Ладно, приступим.
Для начала, установим пакет openssl:
sudo apt-get install openssl
Затем сгенерируем приватный ключ:
openssl genrsa -out webhook_pkey.pem 2048
Теперь, внимание, генерируем самоподписанный сертификат вот этой вот длинной командой:
openssl req -new -x509 -days 3650 -key webhook_pkey.pem -out webhook_cert.pem
Нам предложат ввести некоторую информацию о себе: двухбуквенный код страны, имя организации и т.д. Если не хотите ничего вводить, ставьте точку. НО! ВАЖНО! Когда дойдете до предложения ввести Common Name, следует написать IP адрес сервера, на котором будет запущен бот.
В результате получим файлы webhook_cert.pem и webhook_pkey.pem
Далее нужно написать сам сервер и подключить SSL. Устанавливаем вишню:
Python:
python3 -m pip install cherrypy
Python:
import telebot
import cherrypy
WEBHOOK_HOST = 'IP-адрес сервера, на котором запущен бот'
WEBHOOK_PORT = 443 # 443, 80, 88 или 8443 (порт должен быть открыт!)
WEBHOOK_LISTEN = '0.0.0.0' # На некоторых серверах придется указывать такой же IP, что и выше
WEBHOOK_SSL_CERT = './webhook_cert.pem' # Путь к сертификату
WEBHOOK_SSL_PRIV = './webhook_pkey.pem' # Путь к приватному ключу
WEBHOOK_URL_BASE = "https://%s:%s" % (WEBHOOK_HOST, WEBHOOK_PORT)
WEBHOOK_URL_PATH = "/%s/" % (token)
bot = telebot.TeleBot(token)
Далее создадим класс, реализующий экземпляр веб-сервера:
Python:
class WebhookServer(object):
@cherrypy.expose
def index(self):
if 'content-length' in cherrypy.request.headers and \
'content-type' in cherrypy.request.headers and \
cherrypy.request.headers['content-type'] == 'application/json':
length = int(cherrypy.request.headers['content-length'])
json_string = cherrypy.request.body.read(length).decode("utf-8")
update = telebot.types.Update.de_json(json_string)
# Эта функция обеспечивает проверку входящего сообщения
bot.process_new_updates([update])
return ' '
else:
raise cherrypy.HTTPError(403)
Python:
@bot.message_handler(func=lambda message: True, content_types=['text'])
def echo_message(message): #Вернет то,что мы написали
bot.reply_to(message, message.text)
Код:
# Снимаем вебхук перед повторной установкой (избавляет от некоторых проблем)
bot.remove_webhook()
# Ставим заново вебхук
bot.set_webhook(url=WEBHOOK_URL_BASE + WEBHOOK_URL_PATH,
certificate=open(WEBHOOK_SSL_CERT, 'r'))
Python:
cherrypy.config.update({
'server.socket_host': WEBHOOK_LISTEN,
'server.socket_port': WEBHOOK_PORT,
'server.ssl_module': 'builtin',
'server.ssl_certificate': WEBHOOK_SSL_CERT,
'server.ssl_private_key': WEBHOOK_SSL_PRIV
})
# Собственно, запуск!
cherrypy.quickstart(WebhookServer(), WEBHOOK_URL_PATH, {'/': {}})
Обратите внимание на последнюю строку. Наш сервер в качестве “корня” будет прослушивать адрес вида “ip-адрес/токен_бота”, относительно которого index - это и есть этот адрес. Может, немного криво пояснил, но позднее вам всё станет предельно ясно, сейчас не нужно загромождать голову лишней информацией.
Запустим бота и напишем ему парочку сообщений. Затем посмотрим в окно терминала:
Если 200,то все хорошо)
Спасибо за прочтение!