Add middleware and refactor admin handlers for improved functionality

- Introduced `DependenciesMiddleware` and `BlacklistMiddleware` for enhanced request handling across all routers.
- Refactored admin handlers to utilize new middleware, improving access control and error handling.
- Updated the `admin_router` to include middleware for access checks and streamlined the process of banning users.
- Enhanced the structure of admin handler imports for better organization and maintainability.
- Improved error handling in various admin functions to ensure robust user interactions.
This commit is contained in:
2025-08-28 23:54:17 +03:00
parent f75e7f82c9
commit 8cee629e28
32 changed files with 1922 additions and 1574 deletions

View File

@@ -1,25 +1,50 @@
"""Service classes for private handlers"""
# Standard library imports
import random
import asyncio
import html
from datetime import datetime
from pathlib import Path
from typing import Dict, Callable
from typing import Dict, Callable, Any, Protocol, Union
from dataclasses import dataclass
# Third-party imports
from aiogram import types
from aiogram.types import FSInputFile
# Local imports - utilities
from helper_bot.utils.helper_func import (
get_first_name, get_text_message, send_text_message, send_photo_message,
send_media_group_message_to_private_chat, prepare_media_group_from_middlewares,
send_video_message, send_video_note_message, send_audio_message, send_voice_message,
add_in_db_media, check_username_and_full_name
get_first_name,
get_text_message,
send_text_message,
send_photo_message,
send_media_group_message_to_private_chat,
prepare_media_group_from_middlewares,
send_video_message,
send_video_note_message,
send_audio_message,
send_voice_message,
add_in_db_media,
check_username_and_full_name
)
from helper_bot.keyboards import get_reply_keyboard_for_post
class DatabaseProtocol(Protocol):
"""Protocol for database operations"""
def user_exists(self, user_id: int) -> bool: ...
def add_new_user_in_db(self, user_id: int, first_name: str, full_name: str,
username: str, is_bot: bool, language_code: str,
emoji: str, created_date: str, updated_date: str) -> None: ...
def update_username_and_full_name(self, user_id: int, username: str, full_name: str) -> None: ...
def update_date_for_user(self, date: str, user_id: int) -> None: ...
def add_post_in_db(self, message_id: int, text: str, user_id: int) -> None: ...
def update_info_about_stickers(self, user_id: int) -> None: ...
def add_new_message_in_db(self, text: str, user_id: int, message_id: int, date: str) -> None: ...
def update_helper_message_in_db(self, message_id: int, helper_message_id: int) -> None: ...
@dataclass
class BotSettings:
"""Bot configuration settings"""
@@ -36,7 +61,7 @@ class BotSettings:
class UserService:
"""Service for user-related operations"""
def __init__(self, db, settings: BotSettings):
def __init__(self, db: DatabaseProtocol, settings: BotSettings) -> None:
self.db = db
self.settings = settings
@@ -90,7 +115,7 @@ class UserService:
class PostService:
"""Service for post-related operations"""
def __init__(self, db, settings: BotSettings):
def __init__(self, db: DatabaseProtocol, settings: BotSettings) -> None:
self.db = db
self.settings = settings
@@ -168,7 +193,7 @@ class PostService:
"""Handle media group post submission"""
post_caption = " "
if album[0].caption:
if album and album[0].caption:
post_caption = get_text_message(album[0].caption.lower(), first_name, message.from_user.username)
media_group = await prepare_media_group_from_middlewares(album, post_caption)
@@ -185,7 +210,7 @@ class PostService:
message_id=media_group_message_id, helper_message_id=help_message_id
)
async def process_post(self, message: types.Message, album: list = None) -> None:
async def process_post(self, message: types.Message, album: Union[list[types.Message], None] = None) -> None:
"""Process post based on content type"""
first_name = get_first_name(message)
@@ -220,12 +245,14 @@ class PostService:
class StickerService:
"""Service for sticker-related operations"""
def __init__(self, settings: BotSettings):
def __init__(self, settings: BotSettings) -> None:
self.settings = settings
async def send_random_hello_sticker(self, message: types.Message) -> None:
"""Send random hello sticker"""
name_stick_hello = list(Path('Stick').rglob('Hello_*'))
if not name_stick_hello:
return
random_stick_hello = random.choice(name_stick_hello)
random_stick_hello = FSInputFile(path=random_stick_hello)
await message.answer_sticker(random_stick_hello)
@@ -234,6 +261,8 @@ class StickerService:
async def send_random_goodbye_sticker(self, message: types.Message) -> None:
"""Send random goodbye sticker"""
name_stick_bye = list(Path('Stick').rglob('Universal_*'))
if not name_stick_bye:
return
random_stick_bye = random.choice(name_stick_bye)
random_stick_bye = FSInputFile(path=random_stick_bye)
await message.answer_sticker(random_stick_bye)