From b6f20524647db3b76a509e8f6e702ad7fe3291bf Mon Sep 17 00:00:00 2001 From: Egor Date: Sun, 18 Jan 2026 23:33:45 +0300 Subject: [PATCH 1/2] Update auth.py --- app/middlewares/auth.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/app/middlewares/auth.py b/app/middlewares/auth.py index a3261b49..56e3ccdf 100644 --- a/app/middlewares/auth.py +++ b/app/middlewares/auth.py @@ -44,13 +44,10 @@ class AuthMiddleware(BaseMiddleware): data: Dict[str, Any] ) -> Any: - # Глобальная проверка: если callback с недоступным сообщением — игнорируем - if isinstance(event, CallbackQuery) and isinstance(event.message, InaccessibleMessage): - try: - await event.answer() - except Exception: - pass - return None + # Callback с недоступным сообщением (>48ч) — пропускаем к хендлерам, + # они сами отправят новое сообщение через edit_or_answer_photo + # if isinstance(event, CallbackQuery) and isinstance(event.message, InaccessibleMessage): + # pass # Раньше здесь был return None, теперь пропускаем дальше user: TgUser = None if isinstance(event, (Message, CallbackQuery)): From 346806bce03ff771e09edaad82eb8b57ac989fbb Mon Sep 17 00:00:00 2001 From: PEDZEO Date: Mon, 19 Jan 2026 00:28:57 +0300 Subject: [PATCH 2/2] feat(notifications): integrate WebSocket notifications for ticket replies and new tickets - Added WebSocket notifications for admins on new ticket creation and user replies. - Implemented notification handling in the ticket management routes. - Enhanced error logging for notification failures. --- app/cabinet/routes/__init__.py | 8 ++++++++ app/cabinet/routes/admin_tickets.py | 12 ++++++++++++ app/cabinet/routes/tickets.py | 24 ++++++++++++++++++++++-- requirements.txt | 1 + 4 files changed, 43 insertions(+), 2 deletions(-) diff --git a/app/cabinet/routes/__init__.py b/app/cabinet/routes/__init__.py index 035ca3d2..a26fb6ba 100644 --- a/app/cabinet/routes/__init__.py +++ b/app/cabinet/routes/__init__.py @@ -32,6 +32,9 @@ from .admin_payments import router as admin_payments_router from .admin_promo_offers import router as admin_promo_offers_router from .admin_remnawave import router as admin_remnawave_router from .media import router as media_router +from .websocket import router as websocket_router +from .ticket_notifications import router as ticket_notifications_router +from .ticket_notifications import admin_router as admin_ticket_notifications_router # Main cabinet router router = APIRouter(prefix="/cabinet", tags=["Cabinet"]) @@ -71,5 +74,10 @@ router.include_router(admin_users_router) router.include_router(admin_payments_router) router.include_router(admin_promo_offers_router) router.include_router(admin_remnawave_router) +router.include_router(ticket_notifications_router) +router.include_router(admin_ticket_notifications_router) + +# WebSocket route +router.include_router(websocket_router) __all__ = ["router"] diff --git a/app/cabinet/routes/admin_tickets.py b/app/cabinet/routes/admin_tickets.py index cfef4544..0fcc2dd4 100644 --- a/app/cabinet/routes/admin_tickets.py +++ b/app/cabinet/routes/admin_tickets.py @@ -13,7 +13,9 @@ from pydantic import BaseModel, Field from app.database.models import User, Ticket, TicketMessage from app.database.crud.ticket import TicketCRUD, TicketMessageCRUD +from app.database.crud.ticket_notification import TicketNotificationCRUD from app.config import settings +from app.cabinet.routes.websocket import notify_user_ticket_reply from ..dependencies import get_cabinet_db, get_current_admin_user from ..schemas.tickets import TicketMessageResponse @@ -348,6 +350,16 @@ async def reply_to_ticket( except Exception as e: logger.warning(f"Failed to send Telegram notification: {e}") + # Уведомить пользователя в кабинете (WebSocket) + try: + notification = await TicketNotificationCRUD.create_user_notification_for_admin_reply( + db, ticket, request.message + ) + if notification: + await notify_user_ticket_reply(ticket.user_id, ticket.id, (request.message or "")[:100]) + except Exception as e: + logger.warning(f"Failed to create cabinet notification for admin reply: {e}") + return _message_to_response(message) diff --git a/app/cabinet/routes/tickets.py b/app/cabinet/routes/tickets.py index 448c870f..500f7001 100644 --- a/app/cabinet/routes/tickets.py +++ b/app/cabinet/routes/tickets.py @@ -13,6 +13,8 @@ from sqlalchemy.orm import selectinload from app.database.models import User, Ticket, TicketMessage from app.config import settings from app.handlers.tickets import notify_admins_about_new_ticket, notify_admins_about_ticket_reply +from app.database.crud.ticket_notification import TicketNotificationCRUD +from app.cabinet.routes.websocket import notify_admins_new_ticket, notify_admins_ticket_reply from ..dependencies import get_cabinet_db, get_current_cabinet_user from ..schemas.tickets import ( @@ -162,12 +164,20 @@ async def create_ticket( # Refresh to get relationships await db.refresh(ticket, ["messages"]) - # Уведомить админов о новом тикете + # Уведомить админов о новом тикете (Telegram) try: await notify_admins_about_new_ticket(ticket, db) except Exception as e: logger.error(f"Error notifying admins about new ticket from cabinet: {e}") + # Уведомить админов в кабинете (WebSocket) + try: + notification = await TicketNotificationCRUD.create_admin_notification_for_new_ticket(db, ticket) + if notification: + await notify_admins_new_ticket(ticket.id, ticket.title, user.id) + except Exception as e: + logger.error(f"Error creating cabinet notification for new ticket: {e}") + messages = [_message_to_response(m) for m in ticket.messages] return TicketDetailResponse( @@ -275,10 +285,20 @@ async def add_ticket_message( await db.commit() await db.refresh(message) - # Уведомить админов об ответе пользователя + # Уведомить админов об ответе пользователя (Telegram) try: await notify_admins_about_ticket_reply(ticket, request.message, db) except Exception as e: logger.error(f"Error notifying admins about ticket reply from cabinet: {e}") + # Уведомить админов в кабинете (WebSocket) + try: + notification = await TicketNotificationCRUD.create_admin_notification_for_user_reply( + db, ticket, request.message + ) + if notification: + await notify_admins_ticket_reply(ticket.id, (request.message or "")[:100], user.id) + except Exception as e: + logger.error(f"Error creating cabinet notification for user reply: {e}") + return _message_to_response(message) diff --git a/requirements.txt b/requirements.txt index bc256ffb..579a18bc 100644 --- a/requirements.txt +++ b/requirements.txt @@ -14,6 +14,7 @@ redis==5.0.1 PyYAML==6.0.2 fastapi==0.115.6 uvicorn==0.32.1 +websockets>=12.0 python-multipart==0.0.9 # YooKassa SDK