diff --git a/app/middlewares/auth.py b/app/middlewares/auth.py index a2f3cb5d..47493b2f 100644 --- a/app/middlewares/auth.py +++ b/app/middlewares/auth.py @@ -7,7 +7,7 @@ from aiogram.types import Message, CallbackQuery, TelegramObject, User as TgUser from aiogram.fsm.context import FSMContext from app.config import settings -from app.database.database import get_db +from app.database.database import AsyncSessionLocal from app.database.crud.user import get_user_by_telegram_id, create_user from app.services.remnawave_service import RemnaWaveService from app.states import RegistrationStates @@ -54,26 +54,26 @@ class AuthMiddleware(BaseMiddleware): if user.is_bot: return await handler(event, data) - async for db in get_db(): + async with AsyncSessionLocal() as db: try: db_user = await get_user_by_telegram_id(db, user.id) - + if not db_user: state: FSMContext = data.get('state') current_state = None - + if state: current_state = await state.get_state() is_reg_process = is_registration_process(event, current_state) - - is_channel_check = (isinstance(event, CallbackQuery) + + is_channel_check = (isinstance(event, CallbackQuery) and event.data == "sub_channel_check") - - is_start_command = (isinstance(event, Message) - and event.text + + is_start_command = (isinstance(event, Message) + and event.text and event.text.startswith('/start')) - + if is_reg_process or is_channel_check or is_start_command: if is_start_command: logger.info(f"πŸš€ ΠŸΡ€ΠΎΠΏΡƒΡΠΊΠ°Π΅ΠΌ ΠΊΠΎΠΌΠ°Π½Π΄Ρƒ /start ΠΎΡ‚ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ {user.id}") @@ -84,7 +84,9 @@ class AuthMiddleware(BaseMiddleware): data['db'] = db data['db_user'] = None data['is_admin'] = False - return await handler(event, data) + result = await handler(event, data) + await db.commit() + return result else: if isinstance(event, Message): await event.answer( @@ -99,7 +101,7 @@ class AuthMiddleware(BaseMiddleware): return else: from app.database.models import UserStatus - + if db_user.status == UserStatus.BLOCKED.value: if isinstance(event, Message): await event.answer("🚫 Π’Π°Ρˆ Π°ΠΊΠΊΠ°ΡƒΠ½Ρ‚ Π·Π°Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π½ администратором.") @@ -107,14 +109,14 @@ class AuthMiddleware(BaseMiddleware): await event.answer("🚫 Π’Π°Ρˆ Π°ΠΊΠΊΠ°ΡƒΠ½Ρ‚ Π·Π°Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π½ администратором.", show_alert=True) logger.info(f"🚫 Π—Π°Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹ΠΉ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒ {user.id} попытался ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π±ΠΎΡ‚Π°") return - + if db_user.status == UserStatus.DELETED.value: state: FSMContext = data.get('state') current_state = None - + if state: current_state = await state.get_state() - + registration_states = [ RegistrationStates.waiting_for_language.state, RegistrationStates.waiting_for_rules_accept.state, @@ -134,13 +136,15 @@ class AuthMiddleware(BaseMiddleware): ) ) ) - + if is_start_or_registration: logger.info(f"πŸ”„ Π£Π΄Π°Π»Π΅Π½Π½Ρ‹ΠΉ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒ {user.id} Π½Π°Ρ‡ΠΈΠ½Π°Π΅Ρ‚ ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½ΡƒΡŽ Ρ€Π΅Π³ΠΈΡΡ‚Ρ€Π°Ρ†ΠΈΡŽ") data['db'] = db - data['db_user'] = None + data['db_user'] = None data['is_admin'] = False - return await handler(event, data) + result = await handler(event, data) + await db.commit() + return result else: if isinstance(event, Message): await event.answer( @@ -154,16 +158,16 @@ class AuthMiddleware(BaseMiddleware): ) logger.info(f"❌ Π£Π΄Π°Π»Π΅Π½Π½Ρ‹ΠΉ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒ {user.id} попытался ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π±ΠΎΡ‚Π° Π±Π΅Π· /start") return - - + + profile_updated = False - + if db_user.username != user.username: old_username = db_user.username db_user.username = user.username logger.info(f"πŸ”„ [Middleware] Username ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½ для {user.id}: '{old_username}' β†’ '{db_user.username}'") profile_updated = True - + safe_first = sanitize_telegram_name(user.first_name) safe_last = sanitize_telegram_name(user.last_name) if db_user.first_name != safe_first: @@ -171,13 +175,13 @@ class AuthMiddleware(BaseMiddleware): db_user.first_name = safe_first logger.info(f"πŸ”„ [Middleware] Имя ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΎ для {user.id}: '{old_first_name}' β†’ '{db_user.first_name}'") profile_updated = True - + if db_user.last_name != safe_last: old_last_name = db_user.last_name db_user.last_name = safe_last logger.info(f"πŸ”„ [Middleware] Ѐамилия ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½Π° для {user.id}: '{old_last_name}' β†’ '{db_user.last_name}'") profile_updated = True - + db_user.last_activity = datetime.utcnow() if profile_updated: @@ -198,14 +202,14 @@ class AuthMiddleware(BaseMiddleware): ) ) - await db.commit() - data['db'] = db data['db_user'] = db_user data['is_admin'] = settings.is_admin(user.id) - return await handler(event, data) - + result = await handler(event, data) + await db.commit() + return result + except Exception as e: logger.error(f"Ошибка Π² AuthMiddleware: {e}") logger.error(f"Event type: {type(event)}") diff --git a/app/middlewares/channel_checker.py b/app/middlewares/channel_checker.py index 67fa2db0..3e873843 100644 --- a/app/middlewares/channel_checker.py +++ b/app/middlewares/channel_checker.py @@ -9,7 +9,7 @@ from aiogram.enums import ChatMemberStatus from sqlalchemy.ext.asyncio import AsyncSession from app.config import settings -from app.database.database import get_db +from app.database.database import AsyncSessionLocal from app.database.crud.campaign import get_campaign_by_start_parameter from app.database.crud.subscription import deactivate_subscription, reactivate_subscription from app.database.crud.user import get_user_by_telegram_id @@ -228,7 +228,7 @@ class ChannelCheckerMiddleware(BaseMiddleware): if state_data.get("campaign_notification_sent"): return - async for db in get_db(): + async with AsyncSessionLocal() as db: try: campaign = await get_campaign_by_start_parameter( db, @@ -236,7 +236,7 @@ class ChannelCheckerMiddleware(BaseMiddleware): only_active=True, ) if not campaign: - break + return user = await get_user_by_telegram_id(db, telegram_user.id) @@ -249,14 +249,14 @@ class ChannelCheckerMiddleware(BaseMiddleware): ) if sent: await state.update_data(campaign_notification_sent=True) + await db.commit() except Exception as error: logger.error( "❌ Ошибка ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠΈ увСдомлСния ΠΎ ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄Π΅ ΠΏΠΎ ΠΊΠ°ΠΌΠΏΠ°Π½ΠΈΠΈ %s: %s", payload, error, ) - finally: - break + await db.rollback() async def _deactivate_subscription_on_unsubscribe( self, telegram_id: int, bot: Bot, channel_link: Optional[str] @@ -265,21 +265,21 @@ class ChannelCheckerMiddleware(BaseMiddleware): if not settings.CHANNEL_DISABLE_TRIAL_ON_UNSUBSCRIBE and not settings.CHANNEL_REQUIRED_FOR_ALL: return - async for db in get_db(): + async with AsyncSessionLocal() as db: try: user = await get_user_by_telegram_id(db, telegram_id) if not user or not user.subscription: - break + return subscription = user.subscription if subscription.status != SubscriptionStatus.ACTIVE.value: - break + return if settings.CHANNEL_REQUIRED_FOR_ALL: pass elif not subscription.is_trial: - break + return await deactivate_subscription(db, subscription) sub_type = "Π’Ρ€ΠΈΠ°Π»ΡŒΠ½Π°Ρ" if subscription.is_trial else "ΠŸΠ»Π°Ρ‚Π½Π°Ρ" @@ -316,35 +316,35 @@ class ChannelCheckerMiddleware(BaseMiddleware): telegram_id, notify_error, ) + await db.commit() except Exception as db_error: logger.error( "❌ Ошибка Π΄Π΅Π°ΠΊΡ‚ΠΈΠ²Π°Ρ†ΠΈΠΈ подписки ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ %s послС отписки: %s", telegram_id, db_error, ) - finally: - break + await db.rollback() async def _reactivate_subscription_on_subscribe(self, telegram_id: int, bot: Bot) -> None: """РСактивация подписки послС ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½ΠΎΠΉ подписки Π½Π° ΠΊΠ°Π½Π°Π».""" if not settings.CHANNEL_DISABLE_TRIAL_ON_UNSUBSCRIBE and not settings.CHANNEL_REQUIRED_FOR_ALL: return - async for db in get_db(): + async with AsyncSessionLocal() as db: try: user = await get_user_by_telegram_id(db, telegram_id) if not user or not user.subscription: - break + return subscription = user.subscription # Π Π΅Π°ΠΊΡ‚ΠΈΠ²ΠΈΡ€ΡƒΠ΅ΠΌ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ DISABLED подписки if subscription.status != SubscriptionStatus.DISABLED.value: - break + return # ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡΠ΅ΠΌ Ρ‡Ρ‚ΠΎ подписка Π΅Ρ‰Ρ‘ Π½Π΅ истСкла if subscription.end_date and subscription.end_date <= datetime.utcnow(): - break + return # Π Π΅Π°ΠΊΡ‚ΠΈΠ²ΠΈΡ€ΡƒΠ΅ΠΌ Π² Π‘Π” await reactivate_subscription(db, subscription) @@ -382,14 +382,14 @@ class ChannelCheckerMiddleware(BaseMiddleware): telegram_id, notify_error, ) + await db.commit() except Exception as db_error: logger.error( "❌ Ошибка Ρ€Π΅Π°ΠΊΡ‚ΠΈΠ²Π°Ρ†ΠΈΠΈ подписки ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ %s: %s", telegram_id, db_error, ) - finally: - break + await db.rollback() @staticmethod async def _deny_message(