forked from Muzifs/LGBot
Изменение логики медленного режима
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
## changed at Sun Oct 19 13:23:17 MSK 2025
|
||||
#Sun Oct 19 13:23:17 MSK 2025
|
||||
## changed at Sun Oct 19 17:30:33 MSK 2025
|
||||
#Sun Oct 19 17:30:33 MSK 2025
|
||||
com.gigaide.elements.ext.marker.solution.BeanMarkedPsi.shouldMark=true
|
||||
com.gigaide.elements.ext.marker.solution.ConfigMarkedPsi.shouldMark=true
|
||||
com.gigaide.elements.ext.marker.solution.DataMarkedPsi.shouldMark=true
|
||||
|
27
src/main.py
27
src/main.py
@@ -16,6 +16,8 @@ from action_reporter import init_action_reporter
|
||||
|
||||
from config import MODULES_DIR
|
||||
|
||||
from message_queue import init_message_queue, add_to_queue
|
||||
|
||||
# Загружаем токен бота из .env
|
||||
load_dotenv()
|
||||
|
||||
@@ -143,7 +145,24 @@ class UserUpdateMiddleware(BaseMiddleware):
|
||||
can_send, remaining_time = check_slow_mode(message.from_user.id, message.chat.id, user_karma)
|
||||
|
||||
if not can_send:
|
||||
# Удаляем сообщение
|
||||
# Сохраняем текст сообщения перед удалением
|
||||
message_text = message.text
|
||||
|
||||
# Добавляем сообщение в очередь для отправки после задержки
|
||||
try:
|
||||
add_to_queue(
|
||||
chat_id=message.chat.id,
|
||||
user_id=message.from_user.id,
|
||||
user_name=message.from_user.first_name,
|
||||
text=message_text,
|
||||
delay_seconds=remaining_time,
|
||||
thread_id=message.message_thread_id
|
||||
)
|
||||
logger.info(f"[SLOW MODE] Сообщение от {message.from_user.id} добавлено в очередь на {remaining_time}с")
|
||||
except Exception as e:
|
||||
logger.error(f"Ошибка добавления сообщения в очередь: {e}")
|
||||
|
||||
# Удаляем оригинальное сообщение
|
||||
try:
|
||||
await self.bot.delete_message(message.chat.id, message.message_id)
|
||||
logger.info(f"[SLOW MODE] Удалено сообщение от {message.from_user.id} (карма: {user_karma}, осталось ждать: {remaining_time}с)")
|
||||
@@ -154,7 +173,7 @@ class UserUpdateMiddleware(BaseMiddleware):
|
||||
try:
|
||||
notification = await self.bot.send_message(
|
||||
chat_id=message.chat.id,
|
||||
text=f"⏱ <b>{message.from_user.first_name}</b>, подождите ещё <b>{format_time(remaining_time)}</b> перед отправкой следующего сообщения.\n\n"
|
||||
text=f"⏱ <b>{message.from_user.first_name}</b>, ваше сообщение будет отправлено через <b>{format_time(remaining_time)}</b>.\n\n"
|
||||
f"💡 Ваша карма: <b>{user_karma}</b>. Повышайте карму, чтобы уменьшить задержку!",
|
||||
message_thread_id=message.message_thread_id,
|
||||
)
|
||||
@@ -283,6 +302,10 @@ async def main():
|
||||
# Устанавливаем команды бота
|
||||
await setup_bot_commands()
|
||||
|
||||
# Инициализируем систему очереди сообщений
|
||||
init_message_queue(bot)
|
||||
logger.info("Система очереди сообщений инициализирована")
|
||||
|
||||
# Запускаем бота с обработкой реакций
|
||||
logger.info("Запуск бота с allowed_updates: message, message_reaction, chat_member")
|
||||
await bot.infinity_polling(allowed_updates=['message', 'message_reaction', 'chat_member'])
|
||||
|
150
src/message_queue.py
Normal file
150
src/message_queue.py
Normal file
@@ -0,0 +1,150 @@
|
||||
# Очередь отложенных сообщений для медленного режима
|
||||
# Сохраняет сообщения и отправляет их после истечения задержки
|
||||
|
||||
import asyncio
|
||||
import time
|
||||
import logging
|
||||
from typing import Dict, List, Optional
|
||||
from dataclasses import dataclass
|
||||
from collections import deque
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@dataclass
|
||||
class QueuedMessage:
|
||||
"""Сообщение в очереди"""
|
||||
chat_id: int
|
||||
user_id: int
|
||||
user_name: str
|
||||
text: str
|
||||
send_time: float # Unix timestamp когда нужно отправить
|
||||
thread_id: Optional[int] = None
|
||||
|
||||
# Очередь сообщений для каждого чата
|
||||
_message_queues: Dict[int, deque[QueuedMessage]] = {}
|
||||
_processing_task: Optional[asyncio.Task] = None
|
||||
_bot_instance = None
|
||||
|
||||
def init_message_queue(bot):
|
||||
"""
|
||||
Инициализирует систему очереди сообщений.
|
||||
|
||||
Args:
|
||||
bot: Экземпляр бота для отправки сообщений
|
||||
"""
|
||||
global _bot_instance, _processing_task
|
||||
_bot_instance = bot
|
||||
|
||||
# Запускаем фоновую задачу обработки очереди, если она ещё не запущена
|
||||
if _processing_task is None or _processing_task.done():
|
||||
_processing_task = asyncio.create_task(_process_queue())
|
||||
logger.info("Система очереди сообщений инициализирована")
|
||||
|
||||
def add_to_queue(chat_id: int, user_id: int, user_name: str, text: str, delay_seconds: int, thread_id: Optional[int] = None):
|
||||
"""
|
||||
Добавляет сообщение в очередь для отправки после задержки.
|
||||
|
||||
Args:
|
||||
chat_id: ID чата
|
||||
user_id: ID пользователя
|
||||
user_name: Имя пользователя
|
||||
text: Текст сообщения
|
||||
delay_seconds: Задержка в секундах перед отправкой
|
||||
thread_id: ID топика (для супергрупп с топиками)
|
||||
"""
|
||||
send_time = time.time() + delay_seconds
|
||||
|
||||
message = QueuedMessage(
|
||||
chat_id=chat_id,
|
||||
user_id=user_id,
|
||||
user_name=user_name,
|
||||
text=text,
|
||||
send_time=send_time,
|
||||
thread_id=thread_id
|
||||
)
|
||||
|
||||
# Добавляем очередь для чата, если её ещё нет
|
||||
if chat_id not in _message_queues:
|
||||
_message_queues[chat_id] = deque()
|
||||
|
||||
_message_queues[chat_id].append(message)
|
||||
logger.info(f"[QUEUE] Сообщение от {user_name} ({user_id}) добавлено в очередь чата {chat_id}, отправка через {delay_seconds}с")
|
||||
|
||||
async def _process_queue():
|
||||
"""
|
||||
Фоновая задача для обработки очереди сообщений.
|
||||
Проверяет каждую секунду, есть ли сообщения готовые к отправке.
|
||||
"""
|
||||
global _bot_instance
|
||||
logger.info("[QUEUE] Запущена фоновая задача обработки очереди")
|
||||
|
||||
while True:
|
||||
try:
|
||||
current_time = time.time()
|
||||
|
||||
# Проходим по всем чатам
|
||||
for chat_id in list(_message_queues.keys()):
|
||||
queue = _message_queues[chat_id]
|
||||
|
||||
# Обрабатываем сообщения, которые готовы к отправке
|
||||
while queue and queue[0].send_time <= current_time:
|
||||
message = queue.popleft()
|
||||
|
||||
try:
|
||||
# Отправляем сообщение
|
||||
formatted_text = f"💬 <b>{message.user_name}</b>:\n{message.text}"
|
||||
|
||||
await _bot_instance.send_message(
|
||||
chat_id=message.chat_id,
|
||||
text=formatted_text,
|
||||
message_thread_id=message.thread_id
|
||||
)
|
||||
|
||||
logger.info(f"[QUEUE] Сообщение от {message.user_name} ({message.user_id}) отправлено в чат {message.chat_id}")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"[QUEUE] Ошибка отправки сообщения из очереди: {e}", exc_info=True)
|
||||
|
||||
# Удаляем пустые очереди
|
||||
if not queue:
|
||||
del _message_queues[chat_id]
|
||||
|
||||
# Ждём 1 секунду перед следующей проверкой
|
||||
await asyncio.sleep(1)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"[QUEUE] Ошибка в обработке очереди: {e}", exc_info=True)
|
||||
await asyncio.sleep(1)
|
||||
|
||||
def get_queue_size(chat_id: int) -> int:
|
||||
"""
|
||||
Возвращает количество сообщений в очереди для чата.
|
||||
|
||||
Args:
|
||||
chat_id: ID чата
|
||||
|
||||
Returns:
|
||||
Количество сообщений в очереди
|
||||
"""
|
||||
return len(_message_queues.get(chat_id, []))
|
||||
|
||||
def get_user_queue_position(chat_id: int, user_id: int) -> Optional[int]:
|
||||
"""
|
||||
Возвращает позицию пользователя в очереди (1-based).
|
||||
|
||||
Args:
|
||||
chat_id: ID чата
|
||||
user_id: ID пользователя
|
||||
|
||||
Returns:
|
||||
Позиция в очереди или None если нет сообщений
|
||||
"""
|
||||
if chat_id not in _message_queues:
|
||||
return None
|
||||
|
||||
queue = _message_queues[chat_id]
|
||||
for i, msg in enumerate(queue):
|
||||
if msg.user_id == user_id:
|
||||
return i + 1
|
||||
|
||||
return None
|
Reference in New Issue
Block a user