uchill/backend/apps/notifications/telegram_views.py

139 lines
5.2 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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