first commit
This commit is contained in:
60
bot/middlewares/album.py
Normal file
60
bot/middlewares/album.py
Normal file
@@ -0,0 +1,60 @@
|
||||
import asyncio
|
||||
from typing import Any, Dict, Union
|
||||
|
||||
from aiogram import BaseMiddleware
|
||||
from aiogram.types import Message
|
||||
|
||||
|
||||
class AlbumMiddleware(BaseMiddleware):
|
||||
def __init__(self, latency: Union[int, float] = 0.19):
|
||||
# Initialize latency and album_data dictionary
|
||||
self.latency = latency
|
||||
self.album_data = {}
|
||||
|
||||
#
|
||||
def collect_album_messages(self, event: Message):
|
||||
"""
|
||||
Collect messages of the same media group.
|
||||
"""
|
||||
# # Check if media_group_id exists in album_data
|
||||
if event.media_group_id not in self.album_data:
|
||||
# # Create a new entry for the media group
|
||||
self.album_data[event.media_group_id] = {"messages": []}
|
||||
#
|
||||
# # Append the new message to the media group
|
||||
self.album_data[event.media_group_id]["messages"].append(event)
|
||||
#
|
||||
# # Return the total number of messages in the current media group
|
||||
return len(self.album_data[event.media_group_id]["messages"])
|
||||
|
||||
#
|
||||
async def __call__(self, handler, event: Message, data: Dict[str, Any]) -> Any:
|
||||
"""
|
||||
Main middleware logic.
|
||||
"""
|
||||
# # If the event has no media_group_id, pass it to the handler immediately
|
||||
if not event.media_group_id:
|
||||
return await handler(event, data)
|
||||
#
|
||||
# # Collect messages of the same media group
|
||||
total_before = self.collect_album_messages(event)
|
||||
#
|
||||
# # Wait for a specified latency period
|
||||
await asyncio.sleep(self.latency)
|
||||
#
|
||||
# # Check the total number of messages after the latency
|
||||
total_after = len(self.album_data[event.media_group_id]["messages"])
|
||||
#
|
||||
# # If new messages were added during the latency, exit
|
||||
if total_before != total_after:
|
||||
return
|
||||
#
|
||||
# # Sort the album messages by message_id and add to data
|
||||
album_messages = self.album_data[event.media_group_id]["messages"]
|
||||
album_messages.sort(key=lambda x: x.message_id)
|
||||
data["album"] = album_messages
|
||||
#
|
||||
# # Remove the media group from tracking to free up memory
|
||||
del self.album_data[event.media_group_id]
|
||||
# # Call the original event handler
|
||||
return await handler(event, data)
|
||||
93
bot/middlewares/users_control.py
Normal file
93
bot/middlewares/users_control.py
Normal file
@@ -0,0 +1,93 @@
|
||||
from aiogram import types
|
||||
from aiogram import BaseMiddleware
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from collections import deque
|
||||
import asyncio
|
||||
|
||||
# Const
|
||||
from create_bot import orm
|
||||
|
||||
|
||||
class AntiFloodMiddleware(BaseMiddleware):
|
||||
|
||||
def __init__(
|
||||
self, max_messages: int = 5, interval: float = 2, block_time: float = 60.0
|
||||
):
|
||||
"""
|
||||
Инициализация AntiFloodMiddleware.
|
||||
|
||||
:param max_messages: Максимальное количество сообщений.
|
||||
:param interval: Временной интервал (в секундах) для проверки сообщений.
|
||||
:param block_time: Время блокировки пользователя (в секундах).
|
||||
"""
|
||||
super(AntiFloodMiddleware, self).__init__()
|
||||
self.max_messages = max_messages
|
||||
self.interval = interval
|
||||
self.block_time = block_time
|
||||
self.user_messages = {} # user_id: deque of message timestamps
|
||||
self.blocked_users = {} # user_id: unblock_time
|
||||
self.lock = asyncio.Lock() # Для обеспечения потокобезопасности
|
||||
|
||||
async def __call__(self, handler, event: types.Message, data):
|
||||
user_id = event.from_user.id
|
||||
current_time = datetime.now(timezone.utc)
|
||||
|
||||
async with self.lock:
|
||||
# Проверка, заблокирован ли пользователь
|
||||
if user_id in self.blocked_users:
|
||||
unblock_time = self.blocked_users[user_id]
|
||||
if current_time < unblock_time:
|
||||
# Пользователь всё ещё заблокирован
|
||||
return
|
||||
else:
|
||||
# Блокировка истекла
|
||||
del self.blocked_users[user_id]
|
||||
|
||||
if isinstance(event, types.CallbackQuery):
|
||||
return await handler(event, data)
|
||||
|
||||
# Инициализация очереди сообщений для пользователя, если её ещё нет
|
||||
if user_id not in self.user_messages:
|
||||
self.user_messages[user_id] = deque()
|
||||
|
||||
user_queue = self.user_messages[user_id]
|
||||
user_queue.append(current_time)
|
||||
|
||||
# Удаление сообщений, которые старше интервала
|
||||
while (
|
||||
user_queue
|
||||
and (current_time - user_queue[0]).total_seconds() > self.interval
|
||||
):
|
||||
user_queue.popleft()
|
||||
|
||||
# Проверка, превысил ли пользователь лимит сообщений
|
||||
if len(user_queue) > self.max_messages:
|
||||
# Блокировка пользователя
|
||||
self.blocked_users[user_id] = current_time + timedelta(
|
||||
seconds=self.block_time
|
||||
)
|
||||
# Очистка очереди сообщений
|
||||
del self.user_messages[user_id]
|
||||
|
||||
await event.answer(text="🧊 Вы заморожены на 1 минуту за флуд!")
|
||||
|
||||
# Отмена обработки сообщения и блокировка
|
||||
return
|
||||
|
||||
return await handler(event, data)
|
||||
|
||||
|
||||
class BlacklistMiddleware(BaseMiddleware):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
async def __call__(self, handler, event: types.Update, data: dict):
|
||||
user_id = self.get_user_id(event)
|
||||
if user_id:
|
||||
if await orm.is_blacklisted(user_id):
|
||||
return
|
||||
|
||||
return await handler(event, data)
|
||||
|
||||
def get_user_id(self, event: types.Update):
|
||||
return event.from_user.id
|
||||
Reference in New Issue
Block a user