feat: массовое удаление broadcast сообщений у всех получателей
- Quick delete теперь удаляет сообщения у всех получателей broadcast - Добавлен метод get_message_by_telegram_id в ChatMessageService - При удалении проходит по всем forwarded_message_ids и удаляет у каждого - Показывает статистику удаления админу (автоматически исчезает через 3 сек) - Помечает сообщение как удалённое в БД
This commit is contained in:
@@ -185,6 +185,23 @@ class ChatMessageService:
|
|||||||
)
|
)
|
||||||
return result.scalar_one_or_none()
|
return result.scalar_one_or_none()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
async def get_message_by_telegram_id(
|
||||||
|
session: AsyncSession,
|
||||||
|
telegram_message_id: int,
|
||||||
|
user_id: Optional[int] = None
|
||||||
|
) -> Optional[ChatMessage]:
|
||||||
|
"""Получить сообщение по telegram_message_id"""
|
||||||
|
query = select(ChatMessage).where(
|
||||||
|
ChatMessage.telegram_message_id == telegram_message_id
|
||||||
|
)
|
||||||
|
|
||||||
|
if user_id:
|
||||||
|
query = query.where(ChatMessage.user_id == user_id)
|
||||||
|
|
||||||
|
result = await session.execute(query)
|
||||||
|
return result.scalar_one_or_none()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
async def get_user_messages(
|
async def get_user_messages(
|
||||||
session: AsyncSession,
|
session: AsyncSession,
|
||||||
|
|||||||
@@ -2,11 +2,13 @@
|
|||||||
Хэндлеры для управления сообщениями администратором
|
Хэндлеры для управления сообщениями администратором
|
||||||
"""
|
"""
|
||||||
import logging
|
import logging
|
||||||
from aiogram import Router, F
|
from aiogram import Router, F, Bot
|
||||||
from aiogram.types import Message, CallbackQuery
|
from aiogram.types import Message, CallbackQuery
|
||||||
from aiogram.filters import Command
|
from aiogram.filters import Command
|
||||||
|
|
||||||
from ..core.config import ADMIN_IDS
|
from ..core.config import ADMIN_IDS
|
||||||
|
from ..core.database import async_session_maker
|
||||||
|
from ..core.chat_services import ChatMessageService
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -86,16 +88,75 @@ async def quick_delete_replied_message(message: Message):
|
|||||||
- "удалить", "delete", "del"
|
- "удалить", "delete", "del"
|
||||||
- 🗑️ (мусорная корзина)
|
- 🗑️ (мусорная корзина)
|
||||||
- ❌ (крестик)
|
- ❌ (крестик)
|
||||||
|
|
||||||
|
Удаляет сообщение у всех получателей broadcast рассылки
|
||||||
"""
|
"""
|
||||||
if not is_admin(message.from_user.id):
|
if not is_admin(message.from_user.id):
|
||||||
return # Не админ - пропускаем
|
return # Не админ - пропускаем
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Удаляем сообщение на которое ответили
|
replied_msg = message.reply_to_message
|
||||||
await message.reply_to_message.delete()
|
deleted_count = 0
|
||||||
# Удаляем команду
|
|
||||||
|
# Пытаемся найти сообщение в БД по telegram_message_id
|
||||||
|
async with async_session_maker() as session:
|
||||||
|
chat_message = await ChatMessageService.get_message_by_telegram_id(
|
||||||
|
session,
|
||||||
|
telegram_message_id=replied_msg.message_id
|
||||||
|
)
|
||||||
|
|
||||||
|
# Если нашли broadcast сообщение - удаляем у всех получателей
|
||||||
|
if chat_message and chat_message.forwarded_message_ids:
|
||||||
|
bot = message.bot
|
||||||
|
|
||||||
|
for user_telegram_id, forwarded_msg_id in chat_message.forwarded_message_ids.items():
|
||||||
|
try:
|
||||||
|
await bot.delete_message(
|
||||||
|
chat_id=int(user_telegram_id),
|
||||||
|
message_id=forwarded_msg_id
|
||||||
|
)
|
||||||
|
deleted_count += 1
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"Не удалось удалить сообщение у {user_telegram_id}: {e}")
|
||||||
|
|
||||||
|
# Помечаем как удалённое в БД
|
||||||
|
await ChatMessageService.delete_message(
|
||||||
|
session,
|
||||||
|
message_id=chat_message.id,
|
||||||
|
deleted_by=message.from_user.id
|
||||||
|
)
|
||||||
|
|
||||||
|
logger.info(
|
||||||
|
f"Администратор {message.from_user.id} удалил broadcast сообщение "
|
||||||
|
f"{replied_msg.message_id} у {deleted_count} получателей"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Удаляем исходное сообщение (на которое ответили)
|
||||||
|
await replied_msg.delete()
|
||||||
|
|
||||||
|
# Удаляем команду админа
|
||||||
await message.delete()
|
await message.delete()
|
||||||
logger.info(f"Администратор {message.from_user.id} быстро удалил сообщение {message.reply_to_message.message_id}")
|
|
||||||
|
# Если было broadcast удаление - показываем статистику
|
||||||
|
if deleted_count > 0:
|
||||||
|
status_msg = await message.answer(
|
||||||
|
f"✅ Сообщение удалено у {deleted_count} получателей",
|
||||||
|
reply_to_message_id=None
|
||||||
|
)
|
||||||
|
# Удаляем статус через 3 секунды
|
||||||
|
import asyncio
|
||||||
|
await asyncio.sleep(3)
|
||||||
|
try:
|
||||||
|
await status_msg.delete()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Ошибка при быстром удалении сообщения: {e}")
|
logger.error(f"Ошибка при быстром удалении сообщения: {e}")
|
||||||
await message.answer(f"❌ Не удалось удалить: {str(e)}", reply_to_message_id=message.message_id)
|
try:
|
||||||
|
await message.answer(
|
||||||
|
f"❌ Не удалось удалить: {str(e)}",
|
||||||
|
reply_to_message_id=message.message_id
|
||||||
|
)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|||||||
Reference in New Issue
Block a user