fix quality code
This commit is contained in:
@@ -6,27 +6,24 @@ from .constants import ERROR_MESSAGES, FSM_STATES
|
||||
from .decorators import error_handler
|
||||
from .exceptions import NoReplyToMessageError, UserNotFoundError
|
||||
from .group_handlers import GroupHandlers, create_group_handlers, group_router
|
||||
|
||||
# Local imports - services
|
||||
from .services import AdminReplyService, DatabaseProtocol
|
||||
|
||||
__all__ = [
|
||||
# Main components
|
||||
'group_router',
|
||||
'create_group_handlers',
|
||||
'GroupHandlers',
|
||||
|
||||
"group_router",
|
||||
"create_group_handlers",
|
||||
"GroupHandlers",
|
||||
# Services
|
||||
'AdminReplyService',
|
||||
'DatabaseProtocol',
|
||||
|
||||
"AdminReplyService",
|
||||
"DatabaseProtocol",
|
||||
# Constants
|
||||
'FSM_STATES',
|
||||
'ERROR_MESSAGES',
|
||||
|
||||
"FSM_STATES",
|
||||
"ERROR_MESSAGES",
|
||||
# Exceptions
|
||||
'NoReplyToMessageError',
|
||||
'UserNotFoundError',
|
||||
|
||||
"NoReplyToMessageError",
|
||||
"UserNotFoundError",
|
||||
# Utilities
|
||||
'error_handler'
|
||||
"error_handler",
|
||||
]
|
||||
|
||||
@@ -3,12 +3,10 @@
|
||||
from typing import Dict, Final
|
||||
|
||||
# FSM States
|
||||
FSM_STATES: Final[Dict[str, str]] = {
|
||||
"CHAT": "CHAT"
|
||||
}
|
||||
FSM_STATES: Final[Dict[str, str]] = {"CHAT": "CHAT"}
|
||||
|
||||
# Error messages
|
||||
ERROR_MESSAGES: Final[Dict[str, str]] = {
|
||||
"NO_REPLY_TO_MESSAGE": "Блять, выдели сообщение!",
|
||||
"USER_NOT_FOUND": "Не могу найти кому ответить в базе, проебали сообщение."
|
||||
"USER_NOT_FOUND": "Не могу найти кому ответить в базе, проебали сообщение.",
|
||||
}
|
||||
|
||||
@@ -6,12 +6,14 @@ from typing import Any, Callable
|
||||
|
||||
# Third-party imports
|
||||
from aiogram import types
|
||||
|
||||
# Local imports
|
||||
from logs.custom_logger import logger
|
||||
|
||||
|
||||
def error_handler(func: Callable[..., Any]) -> Callable[..., Any]:
|
||||
"""Decorator for centralized error handling"""
|
||||
|
||||
async def wrapper(*args: Any, **kwargs: Any) -> Any:
|
||||
try:
|
||||
return await func(*args, **kwargs)
|
||||
@@ -19,18 +21,23 @@ def error_handler(func: Callable[..., Any]) -> Callable[..., Any]:
|
||||
logger.error(f"Error in {func.__name__}: {str(e)}")
|
||||
# Try to send error to logs if possible
|
||||
try:
|
||||
message = next((arg for arg in args if isinstance(arg, types.Message)), None)
|
||||
if message and hasattr(message, 'bot'):
|
||||
from helper_bot.utils.base_dependency_factory import \
|
||||
get_global_instance
|
||||
message = next(
|
||||
(arg for arg in args if isinstance(arg, types.Message)), None
|
||||
)
|
||||
if message and hasattr(message, "bot"):
|
||||
from helper_bot.utils.base_dependency_factory import (
|
||||
get_global_instance,
|
||||
)
|
||||
|
||||
bdf = get_global_instance()
|
||||
important_logs = bdf.settings['Telegram']['important_logs']
|
||||
important_logs = bdf.settings["Telegram"]["important_logs"]
|
||||
await message.bot.send_message(
|
||||
chat_id=important_logs,
|
||||
text=f"Произошла ошибка в {func.__name__}: {str(e)}\n\nTraceback:\n{traceback.format_exc()}"
|
||||
text=f"Произошла ошибка в {func.__name__}: {str(e)}\n\nTraceback:\n{traceback.format_exc()}",
|
||||
)
|
||||
except Exception:
|
||||
# If we can't log the error, at least it was logged to logger
|
||||
pass
|
||||
raise
|
||||
|
||||
return wrapper
|
||||
|
||||
@@ -3,9 +3,11 @@
|
||||
|
||||
class NoReplyToMessageError(Exception):
|
||||
"""Raised when admin tries to reply without selecting a message"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class UserNotFoundError(Exception):
|
||||
"""Raised when user is not found in database for the given message_id"""
|
||||
|
||||
pass
|
||||
|
||||
@@ -3,11 +3,14 @@
|
||||
# Third-party imports
|
||||
from aiogram import Router, types
|
||||
from aiogram.fsm.context import FSMContext
|
||||
|
||||
# Local imports - filters
|
||||
from database.async_db import AsyncBotDB
|
||||
from helper_bot.filters.main import ChatTypeFilter
|
||||
|
||||
# Local imports - metrics
|
||||
from helper_bot.utils.metrics import metrics, track_errors, track_time
|
||||
|
||||
# Local imports - utilities
|
||||
from logs.custom_logger import logger
|
||||
|
||||
@@ -20,25 +23,24 @@ from .services import AdminReplyService
|
||||
|
||||
class GroupHandlers:
|
||||
"""Main handler class for group messages"""
|
||||
|
||||
|
||||
def __init__(self, db: AsyncBotDB, keyboard_markup: types.ReplyKeyboardMarkup):
|
||||
self.db = db
|
||||
self.keyboard_markup = keyboard_markup
|
||||
self.admin_reply_service = AdminReplyService(db)
|
||||
|
||||
|
||||
# Create router
|
||||
self.router = Router()
|
||||
|
||||
|
||||
# Register handlers
|
||||
self._register_handlers()
|
||||
|
||||
|
||||
def _register_handlers(self):
|
||||
"""Register all message handlers"""
|
||||
self.router.message.register(
|
||||
self.handle_message,
|
||||
ChatTypeFilter(chat_type=["group", "supergroup"])
|
||||
self.handle_message, ChatTypeFilter(chat_type=["group", "supergroup"])
|
||||
)
|
||||
|
||||
|
||||
@error_handler
|
||||
@track_errors("group_handlers", "handle_message")
|
||||
@track_time("handle_message", "group_handlers")
|
||||
@@ -46,44 +48,46 @@ class GroupHandlers:
|
||||
"""Handle admin reply to user through group chat"""
|
||||
|
||||
logger.info(
|
||||
f'Получено сообщение в группе {message.chat.title} (ID: {message.chat.id}) '
|
||||
f"Получено сообщение в группе {message.chat.title} (ID: {message.chat.id}) "
|
||||
f'от пользователя {message.from_user.full_name} (ID: {message.from_user.id}): "{message.text}"'
|
||||
)
|
||||
|
||||
|
||||
# Check if message is a reply
|
||||
if not message.reply_to_message:
|
||||
await message.answer(ERROR_MESSAGES["NO_REPLY_TO_MESSAGE"])
|
||||
logger.warning(
|
||||
f'В группе {message.chat.title} (ID: {message.chat.id}) '
|
||||
f'админ не выделил сообщение для ответа.'
|
||||
f"В группе {message.chat.title} (ID: {message.chat.id}) "
|
||||
f"админ не выделил сообщение для ответа."
|
||||
)
|
||||
return
|
||||
|
||||
|
||||
message_id = message.reply_to_message.message_id
|
||||
reply_text = message.text
|
||||
|
||||
|
||||
try:
|
||||
# Get user ID for reply
|
||||
chat_id = await self.admin_reply_service.get_user_id_for_reply(message_id)
|
||||
|
||||
|
||||
# Send reply to user
|
||||
await self.admin_reply_service.send_reply_to_user(
|
||||
chat_id, message, reply_text, self.keyboard_markup
|
||||
)
|
||||
|
||||
|
||||
# Set state
|
||||
await state.set_state(FSM_STATES["CHAT"])
|
||||
|
||||
|
||||
except UserNotFoundError:
|
||||
await message.answer(ERROR_MESSAGES["USER_NOT_FOUND"])
|
||||
logger.error(
|
||||
f'Ошибка при поиске пользователя в базе для ответа на сообщение: {reply_text} '
|
||||
f'в группе {message.chat.title} (ID сообщения: {message.message_id})'
|
||||
f"Ошибка при поиске пользователя в базе для ответа на сообщение: {reply_text} "
|
||||
f"в группе {message.chat.title} (ID сообщения: {message.message_id})"
|
||||
)
|
||||
|
||||
|
||||
# Factory function to create handlers with dependencies
|
||||
def create_group_handlers(db: AsyncBotDB, keyboard_markup: types.ReplyKeyboardMarkup) -> GroupHandlers:
|
||||
def create_group_handlers(
|
||||
db: AsyncBotDB, keyboard_markup: types.ReplyKeyboardMarkup
|
||||
) -> GroupHandlers:
|
||||
"""Create group handlers instance with dependencies"""
|
||||
return GroupHandlers(db, keyboard_markup)
|
||||
|
||||
@@ -91,21 +95,23 @@ def create_group_handlers(db: AsyncBotDB, keyboard_markup: types.ReplyKeyboardMa
|
||||
# Legacy router for backward compatibility
|
||||
group_router = Router()
|
||||
|
||||
|
||||
# Initialize with global dependencies (for backward compatibility)
|
||||
def init_legacy_router():
|
||||
"""Initialize legacy router with global dependencies"""
|
||||
global group_router
|
||||
|
||||
|
||||
from helper_bot.keyboards.keyboards import get_reply_keyboard_leave_chat
|
||||
from helper_bot.utils.base_dependency_factory import get_global_instance
|
||||
|
||||
|
||||
bdf = get_global_instance()
|
||||
#TODO: поменять архитектуру и подключить правильный BotDB
|
||||
# TODO: поменять архитектуру и подключить правильный BotDB
|
||||
db = bdf.get_db()
|
||||
keyboard_markup = get_reply_keyboard_leave_chat()
|
||||
|
||||
|
||||
handlers = create_group_handlers(db, keyboard_markup)
|
||||
group_router = handlers.router
|
||||
|
||||
|
||||
# Initialize legacy router
|
||||
init_legacy_router()
|
||||
|
||||
@@ -5,8 +5,10 @@ from typing import Optional, Protocol
|
||||
|
||||
# Third-party imports
|
||||
from aiogram import types
|
||||
|
||||
# Local imports
|
||||
from helper_bot.utils.helper_func import send_text_message
|
||||
|
||||
# Local imports - metrics
|
||||
from helper_bot.utils.metrics import db_query_time, track_errors, track_time
|
||||
from logs.custom_logger import logger
|
||||
@@ -16,29 +18,32 @@ from .exceptions import NoReplyToMessageError, UserNotFoundError
|
||||
|
||||
class DatabaseProtocol(Protocol):
|
||||
"""Protocol for database operations"""
|
||||
|
||||
async def get_user_by_message_id(self, message_id: int) -> Optional[int]: ...
|
||||
async def add_message(self, message_text: str, user_id: int, message_id: int, date: int = None): ...
|
||||
async def add_message(
|
||||
self, message_text: str, user_id: int, message_id: int, date: int = None
|
||||
): ...
|
||||
|
||||
|
||||
class AdminReplyService:
|
||||
"""Service for admin reply operations"""
|
||||
|
||||
|
||||
def __init__(self, db: DatabaseProtocol) -> None:
|
||||
self.db = db
|
||||
|
||||
|
||||
@track_time("get_user_id_for_reply", "admin_reply_service")
|
||||
@track_errors("admin_reply_service", "get_user_id_for_reply")
|
||||
@db_query_time("get_user_id_for_reply", "users", "select")
|
||||
async def get_user_id_for_reply(self, message_id: int) -> int:
|
||||
"""
|
||||
Get user ID for reply by message ID.
|
||||
|
||||
|
||||
Args:
|
||||
message_id: ID of the message to reply to
|
||||
|
||||
|
||||
Returns:
|
||||
User ID for the reply
|
||||
|
||||
|
||||
Raises:
|
||||
UserNotFoundError: If user is not found in database
|
||||
"""
|
||||
@@ -46,19 +51,19 @@ class AdminReplyService:
|
||||
if user_id is None:
|
||||
raise UserNotFoundError(f"User not found for message_id: {message_id}")
|
||||
return user_id
|
||||
|
||||
|
||||
@track_time("send_reply_to_user", "admin_reply_service")
|
||||
@track_errors("admin_reply_service", "send_reply_to_user")
|
||||
async def send_reply_to_user(
|
||||
self,
|
||||
chat_id: int,
|
||||
message: types.Message,
|
||||
reply_text: str,
|
||||
markup: types.ReplyKeyboardMarkup
|
||||
self,
|
||||
chat_id: int,
|
||||
message: types.Message,
|
||||
reply_text: str,
|
||||
markup: types.ReplyKeyboardMarkup,
|
||||
) -> None:
|
||||
"""
|
||||
Send reply to user.
|
||||
|
||||
|
||||
Args:
|
||||
chat_id: User's chat ID
|
||||
message: Original message from admin
|
||||
|
||||
Reference in New Issue
Block a user