139 lines
5.2 KiB
Python
139 lines
5.2 KiB
Python
"""
|
||
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)
|
||
|