42 lines
1.5 KiB
Python
42 lines
1.5 KiB
Python
import logging
|
|
|
|
from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseForbidden
|
|
from django.utils.crypto import constant_time_compare
|
|
from django.views.decorators.csrf import csrf_exempt
|
|
from django.views.decorators.http import require_POST
|
|
from telebot import types
|
|
|
|
from .dispatcher import handle_update
|
|
from .models import Bot
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
SECRET_HEADER = 'X-Telegram-Bot-Api-Secret-Token'
|
|
|
|
|
|
@csrf_exempt
|
|
@require_POST
|
|
def webhook(request, bot_id: int):
|
|
"""Принимает обновление от Bot API сервера.
|
|
|
|
Бот читается из базы на каждое обновление, поэтому смена интерфейса в админке применяется сразу.
|
|
Ошибка обработчика не возвращается телеграму: иначе он будет повторять то же обновление.
|
|
"""
|
|
bot = Bot.objects.find_published(bot_id)
|
|
if bot is None or not constant_time_compare(request.headers.get(SECRET_HEADER, ''), bot.webhook_secret):
|
|
return HttpResponseForbidden()
|
|
try:
|
|
update = types.Update.de_json(request.body.decode())
|
|
except ValueError:
|
|
return HttpResponseBadRequest()
|
|
|
|
try:
|
|
handle_update(bot.api(), bot, update)
|
|
except Exception as error:
|
|
logger.exception('Bot %s failed to handle update %s', bot_id, update.update_id)
|
|
Bot.objects.filter(pk=bot_id).update(last_error=str(error))
|
|
else:
|
|
if bot.last_error:
|
|
Bot.objects.filter(pk=bot_id).update(last_error='')
|
|
return HttpResponse()
|