refactor: extract common handler logic into decorators
- Add @answer_callback for auto-answering callback queries - Add @with_user_and_session for injecting user/session - Add @require_state for state validation - Reduce handlers.py from ~850 to ~540 lines
This commit is contained in:
76
src/decorators.py
Normal file
76
src/decorators.py
Normal file
@@ -0,0 +1,76 @@
|
||||
from functools import wraps
|
||||
from typing import Callable
|
||||
|
||||
from telegram import Update
|
||||
from telegram.ext import ContextTypes
|
||||
|
||||
from src.database import (
|
||||
User,
|
||||
UserSession,
|
||||
UserState,
|
||||
get_or_create_user,
|
||||
get_user_session,
|
||||
)
|
||||
|
||||
INVALID_STATE_TEXT = "❌ Некорректное действие. Используйте /start для начала."
|
||||
|
||||
|
||||
def answer_callback(func: Callable) -> Callable:
|
||||
"""Автоматически отвечает на callback query."""
|
||||
|
||||
@wraps(func)
|
||||
async def wrapper(
|
||||
update: Update, context: ContextTypes.DEFAULT_TYPE, *args, **kwargs
|
||||
):
|
||||
if update.callback_query:
|
||||
await update.callback_query.answer()
|
||||
return await func(update, context, *args, **kwargs)
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
def with_user_and_session(func: Callable) -> Callable:
|
||||
"""Добавляет user и session в kwargs."""
|
||||
|
||||
@wraps(func)
|
||||
async def wrapper(
|
||||
update: Update, context: ContextTypes.DEFAULT_TYPE, *args, **kwargs
|
||||
):
|
||||
user = get_or_create_user(update.effective_user.id)
|
||||
session = get_user_session(user.id)
|
||||
return await func(update, context, *args, user=user, session=session, **kwargs)
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
def require_state(*states: UserState):
|
||||
"""Проверяет, что сессия в одном из указанных состояний."""
|
||||
|
||||
def decorator(func: Callable) -> Callable:
|
||||
@wraps(func)
|
||||
async def wrapper(
|
||||
update: Update,
|
||||
context: ContextTypes.DEFAULT_TYPE,
|
||||
*args,
|
||||
user: User,
|
||||
session: UserSession | None,
|
||||
**kwargs,
|
||||
):
|
||||
if not session or session.state not in states:
|
||||
if update.callback_query:
|
||||
await update.callback_query.edit_message_text(INVALID_STATE_TEXT)
|
||||
elif update.message:
|
||||
await update.message.reply_text(INVALID_STATE_TEXT)
|
||||
return
|
||||
return await func(
|
||||
update, context, *args, user=user, session=session, **kwargs
|
||||
)
|
||||
|
||||
return wrapper
|
||||
|
||||
return decorator
|
||||
|
||||
|
||||
def require_states(*states: UserState):
|
||||
"""Алиас для require_state с несколькими состояниями."""
|
||||
return require_state(*states)
|
||||
1034
src/handlers.py
1034
src/handlers.py
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user