forked from Muzifs/LGBot
Изменение логики медленного режима
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
## changed at Sun Oct 19 13:23:17 MSK 2025
|
## changed at Sun Oct 19 17:30:33 MSK 2025
|
||||||
#Sun Oct 19 13:23:17 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.BeanMarkedPsi.shouldMark=true
|
||||||
com.gigaide.elements.ext.marker.solution.ConfigMarkedPsi.shouldMark=true
|
com.gigaide.elements.ext.marker.solution.ConfigMarkedPsi.shouldMark=true
|
||||||
com.gigaide.elements.ext.marker.solution.DataMarkedPsi.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 config import MODULES_DIR
|
||||||
|
|
||||||
|
from message_queue import init_message_queue, add_to_queue
|
||||||
|
|
||||||
# Загружаем токен бота из .env
|
# Загружаем токен бота из .env
|
||||||
load_dotenv()
|
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)
|
can_send, remaining_time = check_slow_mode(message.from_user.id, message.chat.id, user_karma)
|
||||||
|
|
||||||
if not can_send:
|
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:
|
try:
|
||||||
await self.bot.delete_message(message.chat.id, message.message_id)
|
await self.bot.delete_message(message.chat.id, message.message_id)
|
||||||
logger.info(f"[SLOW MODE] Удалено сообщение от {message.from_user.id} (карма: {user_karma}, осталось ждать: {remaining_time}с)")
|
logger.info(f"[SLOW MODE] Удалено сообщение от {message.from_user.id} (карма: {user_karma}, осталось ждать: {remaining_time}с)")
|
||||||
@@ -154,7 +173,7 @@ class UserUpdateMiddleware(BaseMiddleware):
|
|||||||
try:
|
try:
|
||||||
notification = await self.bot.send_message(
|
notification = await self.bot.send_message(
|
||||||
chat_id=message.chat.id,
|
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>. Повышайте карму, чтобы уменьшить задержку!",
|
f"💡 Ваша карма: <b>{user_karma}</b>. Повышайте карму, чтобы уменьшить задержку!",
|
||||||
message_thread_id=message.message_thread_id,
|
message_thread_id=message.message_thread_id,
|
||||||
)
|
)
|
||||||
@@ -283,6 +302,10 @@ async def main():
|
|||||||
# Устанавливаем команды бота
|
# Устанавливаем команды бота
|
||||||
await setup_bot_commands()
|
await setup_bot_commands()
|
||||||
|
|
||||||
|
# Инициализируем систему очереди сообщений
|
||||||
|
init_message_queue(bot)
|
||||||
|
logger.info("Система очереди сообщений инициализирована")
|
||||||
|
|
||||||
# Запускаем бота с обработкой реакций
|
# Запускаем бота с обработкой реакций
|
||||||
logger.info("Запуск бота с allowed_updates: message, message_reaction, chat_member")
|
logger.info("Запуск бота с allowed_updates: message, message_reaction, chat_member")
|
||||||
await bot.infinity_polling(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