""" Views для обработки Telegram webhook. """ import json import logging from django.http import JsonResponse, HttpResponse from django.views.decorators.csrf import csrf_exempt from django.views.decorators.http import require_http_methods from django.conf import settings from telegram import Update from telegram.ext import ContextTypes logger = logging.getLogger(__name__) @csrf_exempt @require_http_methods(["POST"]) def telegram_webhook(request): """ Обработчик webhook от Telegram. POST /api/notifications/telegram/webhook/ """ try: # Проверяем secret token если указан webhook_secret_token = getattr(settings, 'TELEGRAM_WEBHOOK_SECRET_TOKEN', None) if webhook_secret_token: received_token = request.headers.get('X-Telegram-Bot-Api-Secret-Token') if received_token != webhook_secret_token: logger.warning("Invalid webhook secret token") return HttpResponse(status=403) # Получаем данные из запроса body = request.body.decode('utf-8') data = json.loads(body) # Создаем Update объект update = Update.de_json(data, None) if not update: logger.warning("Empty update received") return JsonResponse({'ok': True}) # Получаем экземпляр бота from .telegram_bot import TelegramBot # Создаем или получаем экземпляр бота bot = TelegramBot() # Обрабатываем update асинхронно import asyncio async def process_update(): """Обработка update в асинхронном контексте.""" try: # Обрабатываем update через метод бота success = await bot.process_webhook_update(update) return success except Exception as e: logger.error(f"Error processing update: {e}", exc_info=True) return False # Запускаем обработку try: loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) success = loop.run_until_complete(process_update()) loop.close() if success: return JsonResponse({'ok': True}) else: return JsonResponse({'ok': False, 'error': 'Processing failed'}, status=500) except Exception as e: logger.error(f"Error in webhook processing: {e}", exc_info=True) return JsonResponse({'ok': False, 'error': str(e)}, status=500) except json.JSONDecodeError: logger.error("Invalid JSON in webhook request") return JsonResponse({'ok': False, 'error': 'Invalid JSON'}, status=400) except Exception as e: logger.error(f"Unexpected error in webhook: {e}", exc_info=True) return JsonResponse({'ok': False, 'error': str(e)}, status=500) @require_http_methods(["GET", "POST"]) def telegram_webhook_info(request): """ Получить информацию о webhook или управлять им. GET /api/notifications/telegram/webhook/info/ - получить информацию POST /api/notifications/telegram/webhook/setup/ - установить webhook POST /api/notifications/telegram/webhook/remove/ - удалить webhook """ from telegram import Bot from telegram.error import TelegramError from django.conf import settings import asyncio token = getattr(settings, 'TELEGRAM_BOT_TOKEN', None) if not token: return JsonResponse({'error': 'TELEGRAM_BOT_TOKEN not set'}, status=500) try: bot = Bot(token=token) async def get_info(): """Получить информацию о webhook.""" try: info = await bot.get_webhook_info() await bot.close() return { 'url': info.url or None, 'has_custom_certificate': info.has_custom_certificate, 'pending_update_count': info.pending_update_count, 'last_error_date': info.last_error_date.isoformat() if info.last_error_date else None, 'last_error_message': info.last_error_message, 'max_connections': info.max_connections, 'allowed_updates': info.allowed_updates, } except TelegramError as e: await bot.close() raise loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) info = loop.run_until_complete(get_info()) loop.close() return JsonResponse({'ok': True, 'data': info}) except TelegramError as e: logger.error(f"Telegram API error: {e}") return JsonResponse({'ok': False, 'error': str(e)}, status=500) except Exception as e: logger.error(f"Error getting webhook info: {e}", exc_info=True) return JsonResponse({'ok': False, 'error': str(e)}, status=500)