Merge pull request #2511 from BEDOLAGA-DEV/dev

Dev
This commit is contained in:
Egor
2026-02-03 03:17:18 +03:00
committed by GitHub
3 changed files with 92 additions and 17 deletions
+17 -2
View File
@@ -7,6 +7,7 @@ from typing import Any
from aiogram import BaseMiddleware
from aiogram.fsm.context import FSMContext
from aiogram.types import CallbackQuery, Message, TelegramObject, User as TgUser
from sqlalchemy.exc import InterfaceError, OperationalError
from app.config import settings
from app.database.crud.user import get_user_by_telegram_id
@@ -204,13 +205,27 @@ class AuthMiddleware(BaseMiddleware):
data['is_admin'] = settings.is_admin(user.id)
result = await handler(event, data)
await db.commit()
try:
await db.commit()
except (InterfaceError, OperationalError) as conn_err:
# Соединение закрылось (таймаут после долгой операции) - просто логируем
logger.warning(f'⚠️ Соединение с БД закрыто после обработки, пропускаем commit: {conn_err}')
return result
except (InterfaceError, OperationalError) as conn_err:
# Соединение с БД закрылось - не пытаемся rollback
logger.error(f'Ошибка соединения с БД в AuthMiddleware: {conn_err}')
logger.error(f'Event type: {type(event)}')
if hasattr(event, 'data'):
logger.error(f'Callback data: {event.data}')
raise
except Exception as e:
logger.error(f'Ошибка в AuthMiddleware: {e}')
logger.error(f'Event type: {type(event)}')
if hasattr(event, 'data'):
logger.error(f'Callback data: {event.data}')
await db.rollback()
try:
await db.rollback()
except (InterfaceError, OperationalError):
pass # Соединение уже закрыто
raise
+21 -4
View File
@@ -9,6 +9,7 @@ from aiogram import BaseMiddleware, Bot
from aiogram.enums import ParseMode
from aiogram.exceptions import TelegramBadRequest
from aiogram.types import BufferedInputFile, CallbackQuery, InlineKeyboardButton, InlineKeyboardMarkup, TelegramObject
from sqlalchemy.exc import InterfaceError, OperationalError
from app.config import settings
from app.services.startup_notification_service import _get_error_recommendations
@@ -67,6 +68,10 @@ class GlobalErrorMiddleware(BaseMiddleware):
return await handler(event, data)
except TelegramBadRequest as e:
return await self._handle_telegram_error(event, e, data)
except (InterfaceError, OperationalError) as e:
# Ошибки соединения с БД (таймаут после долгих операций) - логируем, но не спамим админам
logger.warning('⚠️ Ошибка соединения с БД в GlobalErrorMiddleware: %s', e)
raise
except Exception as e:
logger.error('Неожиданная ошибка в GlobalErrorMiddleware: %s', e, exc_info=True)
# Отправляем уведомление об ошибке в админский чат
@@ -82,13 +87,13 @@ class GlobalErrorMiddleware(BaseMiddleware):
if self._is_old_query_error(error_message):
return await self._handle_old_query(event, error)
if self._is_message_not_modified_error(error_message):
return await self._handle_message_not_modified(event, error)
return await self._handle_message_not_modified(event, error, data)
if self._is_topic_required_error(error_message):
# Канал с топиками — просто игнорируем
logger.debug('[GlobalErrorMiddleware] Игнорируем ошибку топика: %s', error)
return None
if self._is_bad_request_error(error_message):
return await self._handle_bad_request(event, error)
return await self._handle_bad_request(event, error, data)
# Неизвестная ошибка — логируем и отправляем уведомление
logger.error('Неизвестная Telegram API ошибка: %s', error)
@@ -117,7 +122,9 @@ class GlobalErrorMiddleware(BaseMiddleware):
else:
logger.warning('[GlobalErrorMiddleware] Игнорируем устаревший запрос: %s', error)
async def _handle_message_not_modified(self, event: TelegramObject, error: TelegramBadRequest):
async def _handle_message_not_modified(
self, event: TelegramObject, error: TelegramBadRequest, data: dict[str, Any]
):
logger.debug('[GlobalErrorMiddleware] Сообщение не было изменено: %s', error)
if isinstance(event, CallbackQuery):
@@ -127,8 +134,13 @@ class GlobalErrorMiddleware(BaseMiddleware):
except TelegramBadRequest as answer_error:
if not self._is_old_query_error(str(answer_error).lower()):
logger.error('Ошибка при ответе на callback: %s', answer_error)
# Отправляем уведомление в админский чат
bot = data.get('bot')
if bot:
user_info = self._get_user_info(event)
schedule_error_notification(bot, answer_error, f'Callback answer error: {user_info}')
async def _handle_bad_request(self, event: TelegramObject, error: TelegramBadRequest):
async def _handle_bad_request(self, event: TelegramObject, error: TelegramBadRequest, data: dict[str, Any]):
error_message = str(error).lower()
if BOT_BLOCKED_PHRASE in error_message:
@@ -143,6 +155,11 @@ class GlobalErrorMiddleware(BaseMiddleware):
logger.warning('[GlobalErrorMiddleware] Чат или сообщение не найдено: %s', error)
return
logger.error('[GlobalErrorMiddleware] Неизвестная bad request ошибка: %s', error)
# Отправляем уведомление перед raise
bot = data.get('bot')
if bot:
user_info = self._get_user_info(event)
schedule_error_notification(bot, error, f'Bad request: {user_info}')
raise error
def _get_user_info(self, event: TelegramObject) -> str:
+54 -11
View File
@@ -30,9 +30,11 @@ from app.database.models import (
AdvertisingCampaign,
AdvertisingCampaignRegistration,
BroadcastHistory,
CloudPaymentsPayment,
CryptoBotPayment,
FreekassaPayment,
HeleketPayment,
KassaAiPayment,
MulenPayPayment,
Pal24Payment,
PaymentMethod,
@@ -957,6 +959,58 @@ class UserService:
except Exception as e:
logger.error(f'❌ Ошибка удаления Freekassa платежей: {e}')
# Удаляем Wata платежи (до транзакций, т.к. wata_payments.transaction_id -> transactions.id)
try:
wata_payments_result = await db.execute(select(WataPayment).where(WataPayment.user_id == user_id))
wata_payments = wata_payments_result.scalars().all()
if wata_payments:
logger.info(f'🔄 Удаляем {len(wata_payments)} Wata платежей')
await db.execute(
update(WataPayment).where(WataPayment.user_id == user_id).values(transaction_id=None)
)
await db.flush()
await db.execute(delete(WataPayment).where(WataPayment.user_id == user_id))
await db.flush()
except Exception as e:
logger.error(f'❌ Ошибка удаления Wata платежей: {e}')
# Удаляем CloudPayments платежи
try:
cloudpayments_result = await db.execute(
select(CloudPaymentsPayment).where(CloudPaymentsPayment.user_id == user_id)
)
cloudpayments_payments = cloudpayments_result.scalars().all()
if cloudpayments_payments:
logger.info(f'🔄 Удаляем {len(cloudpayments_payments)} CloudPayments платежей')
await db.execute(
update(CloudPaymentsPayment)
.where(CloudPaymentsPayment.user_id == user_id)
.values(transaction_id=None)
)
await db.flush()
await db.execute(delete(CloudPaymentsPayment).where(CloudPaymentsPayment.user_id == user_id))
await db.flush()
except Exception as e:
logger.error(f'❌ Ошибка удаления CloudPayments платежей: {e}')
# Удаляем KassaAi платежи
try:
kassa_ai_result = await db.execute(select(KassaAiPayment).where(KassaAiPayment.user_id == user_id))
kassa_ai_payments = kassa_ai_result.scalars().all()
if kassa_ai_payments:
logger.info(f'🔄 Удаляем {len(kassa_ai_payments)} KassaAi платежей')
await db.execute(
update(KassaAiPayment).where(KassaAiPayment.user_id == user_id).values(transaction_id=None)
)
await db.flush()
await db.execute(delete(KassaAiPayment).where(KassaAiPayment.user_id == user_id))
await db.flush()
except Exception as e:
logger.error(f'❌ Ошибка удаления KassaAi платежей: {e}')
try:
transactions_result = await db.execute(select(Transaction).where(Transaction.user_id == user_id))
transactions = transactions_result.scalars().all()
@@ -1056,17 +1110,6 @@ class UserService:
except Exception as e:
logger.error(f'❌ Ошибка удаления подписки: {e}')
try:
wata_payments_result = await db.execute(select(WataPayment).where(WataPayment.user_id == user_id))
wata_payments = wata_payments_result.scalars().all()
if wata_payments:
logger.info(f'🔄 Удаляем {len(wata_payments)} Wata платежей')
await db.execute(delete(WataPayment).where(WataPayment.user_id == user_id))
await db.flush()
except Exception as e:
logger.error(f'❌ Ошибка удаления Wata платежей: {e}')
try:
await db.execute(delete(User).where(User.id == user_id))
await db.commit()