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()