Добавлен функционал для работы с медиагруппами и улучшена обработка сообщений
- Реализованы методы для добавления связи между постами и сообщениями в `PostRepository` и `AsyncBotDB`. - Обновлены обработчики публикации постов для корректной работы с медиагруппами, включая удаление и уведомление авторов. - Улучшена логика обработки сообщений в `AlbumMiddleware` для более эффективного сбора медиагрупп. - Обновлены тесты для проверки нового функционала и обработки ошибок.
This commit is contained in:
@@ -54,7 +54,12 @@ class PostPublishService:
|
||||
@track_errors("post_publish_service", "publish_post")
|
||||
async def publish_post(self, call: CallbackQuery) -> None:
|
||||
"""Основной метод публикации поста"""
|
||||
# Проверяем, является ли сообщение частью медиагруппы
|
||||
# Проверяем, является ли сообщение helper-сообщением медиагруппы
|
||||
if call.message.text == CONTENT_TYPE_MEDIA_GROUP:
|
||||
await self._publish_media_group(call)
|
||||
return
|
||||
|
||||
# Проверяем, является ли сообщение частью медиагруппы (для обратной совместимости)
|
||||
if call.message.media_group_id:
|
||||
await self._publish_media_group(call)
|
||||
return
|
||||
@@ -280,44 +285,42 @@ class PostPublishService:
|
||||
@track_media_processing("media_group")
|
||||
async def _publish_media_group(self, call: CallbackQuery) -> None:
|
||||
"""Публикация медиагруппы"""
|
||||
logger.info(f"Начинаю публикацию медиагруппы. Helper message ID: {call.message.message_id}")
|
||||
try:
|
||||
# call.message.message_id - это ID helper сообщения
|
||||
helper_message_id = call.message.message_id
|
||||
|
||||
# Получаем контент медиагруппы по helper_message_id
|
||||
logger.debug(f"Получаю контент медиагруппы для helper_message_id: {helper_message_id}")
|
||||
media_group_message_ids = await self.db.get_post_ids_by_helper_id(helper_message_id)
|
||||
if not media_group_message_ids:
|
||||
logger.error(f"_publish_media_group: Не найдены message_id медиагруппы для helper_message_id={helper_message_id}")
|
||||
raise PublishError("Не найдены message_id медиагруппы в базе данных")
|
||||
|
||||
post_content = await self.db.get_post_content_by_helper_id(helper_message_id)
|
||||
if not post_content:
|
||||
logger.error(f"Контент медиагруппы не найден в базе данных для helper_message_id: {helper_message_id}")
|
||||
logger.error(f"_publish_media_group: Контент медиагруппы не найден в базе данных для helper_message_id={helper_message_id}")
|
||||
raise PublishError("Контент медиагруппы не найден в базе данных")
|
||||
|
||||
# Получаем сырой текст и is_anonymous по helper_message_id
|
||||
logger.debug(f"Получаю текст и is_anonymous поста для helper_message_id: {helper_message_id}")
|
||||
raw_text, is_anonymous = await self.db.get_post_text_and_anonymity_by_helper_id(helper_message_id)
|
||||
if raw_text is None:
|
||||
raw_text = ""
|
||||
logger.debug(f"Текст поста получен: {'пустой' if not raw_text else f'длина: {len(raw_text)} символов'}, is_anonymous={is_anonymous}")
|
||||
|
||||
# Получаем ID автора по helper_message_id
|
||||
logger.debug(f"Получаю ID автора для helper_message_id: {helper_message_id}")
|
||||
author_id = await self.db.get_author_id_by_helper_message_id(helper_message_id)
|
||||
if not author_id:
|
||||
logger.error(f"Автор не найден для медиагруппы {helper_message_id}")
|
||||
logger.error(f"_publish_media_group: Автор не найден для медиагруппы helper_message_id={helper_message_id}")
|
||||
raise PostNotFoundError(f"Автор не найден для медиагруппы {helper_message_id}")
|
||||
logger.debug(f"ID автора получен: {author_id}")
|
||||
|
||||
# Получаем данные автора
|
||||
user = await self.db.get_user_by_id(author_id)
|
||||
if not user:
|
||||
raise PostNotFoundError(f"Пользователь {author_id} не найден в базе данных")
|
||||
|
||||
# Формируем финальный текст с учетом is_anonymous
|
||||
formatted_text = get_text_message(raw_text, user.first_name, user.username, is_anonymous)
|
||||
logger.debug(f"Сформирован финальный текст: {'пустой' if not formatted_text else f'длина: {len(formatted_text)} символов'}")
|
||||
|
||||
# Отправляем медиагруппу в канал
|
||||
logger.info(f"Отправляю медиагруппу в канал {self.main_public}")
|
||||
try:
|
||||
await self._get_bot(call.message).delete_messages(
|
||||
chat_id=self.group_for_posts,
|
||||
message_ids=media_group_message_ids
|
||||
)
|
||||
except Exception as e:
|
||||
logger.warning(f"_publish_media_group: Ошибка при удалении медиагруппы из чата модерации: {e}")
|
||||
|
||||
sent_messages = await send_media_group_to_channel(
|
||||
bot=self._get_bot(call.message),
|
||||
chat_id=self.main_public,
|
||||
@@ -326,31 +329,49 @@ class PostPublishService:
|
||||
s3_storage=self.s3_storage
|
||||
)
|
||||
|
||||
# Получаем оригинальные message_id из медиагруппы
|
||||
original_message_ids = await self.db.get_post_ids_from_telegram_by_last_id(helper_message_id)
|
||||
logger.debug(f"Получены оригинальные message_id медиагруппы: {original_message_ids}")
|
||||
|
||||
# Сохраняем published_message_id для каждого сообщения медиагруппы
|
||||
if len(sent_messages) == len(original_message_ids):
|
||||
for i, original_message_id in enumerate(original_message_ids):
|
||||
if len(sent_messages) == len(media_group_message_ids):
|
||||
for i, original_message_id in enumerate(media_group_message_ids):
|
||||
published_message_id = sent_messages[i].message_id
|
||||
await self.db.update_published_message_id(
|
||||
original_message_id=original_message_id,
|
||||
published_message_id=published_message_id
|
||||
)
|
||||
# Сохраняем медиафайл из опубликованного сообщения (используем уже сохраненный файл)
|
||||
await self._save_published_post_content(sent_messages[i], published_message_id, original_message_id)
|
||||
logger.debug(f"Сохранен published_message_id: {original_message_id} -> {published_message_id}")
|
||||
try:
|
||||
await self.db.update_published_message_id(
|
||||
original_message_id=original_message_id,
|
||||
published_message_id=published_message_id
|
||||
)
|
||||
await self._save_published_post_content(sent_messages[i], published_message_id, original_message_id)
|
||||
except Exception as e:
|
||||
logger.warning(f"_publish_media_group: Ошибка при сохранении published_message_id для {original_message_id}: {e}")
|
||||
else:
|
||||
logger.warning(f"Количество опубликованных сообщений ({len(sent_messages)}) не совпадает с количеством оригинальных ({len(original_message_ids)})")
|
||||
logger.warning(f"_publish_media_group: Количество опубликованных сообщений ({len(sent_messages)}) не совпадает с количеством оригинальных ({len(media_group_message_ids)})")
|
||||
|
||||
await self.db.update_status_for_media_group_by_helper_id(helper_message_id, "approved")
|
||||
logger.debug(f"Удаляю медиагруппу и уведомляю автора {author_id}")
|
||||
await self._delete_media_group_and_notify_author(call, author_id)
|
||||
logger.info(f'Медиагруппа опубликована в канале {self.main_public}, опубликовано сообщений: {len(sent_messages)}.')
|
||||
|
||||
# Удаляем helper сообщение - это критично, делаем это всегда
|
||||
try:
|
||||
await self._get_bot(call.message).delete_message(
|
||||
chat_id=self.group_for_posts,
|
||||
message_id=helper_message_id
|
||||
)
|
||||
except Exception as e:
|
||||
logger.warning(f"_publish_media_group: Ошибка при удалении helper сообщения: {e}")
|
||||
|
||||
try:
|
||||
await send_text_message(author_id, call.message, MESSAGE_POST_PUBLISHED)
|
||||
except Exception as e:
|
||||
if str(e) == ERROR_BOT_BLOCKED:
|
||||
logger.warning(f"_publish_media_group: Пользователь {author_id} заблокировал бота")
|
||||
raise UserBlockedBotError("Пользователь заблокировал бота")
|
||||
logger.error(f"_publish_media_group: Ошибка при отправке уведомления автору: {e}")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Ошибка при публикации медиагруппы: {e}")
|
||||
logger.error(f"_publish_media_group: Ошибка при публикации медиагруппы: {e}")
|
||||
# Пытаемся удалить helper сообщение даже при ошибке
|
||||
try:
|
||||
await self._get_bot(call.message).delete_message(
|
||||
chat_id=self.group_for_posts,
|
||||
message_id=call.message.message_id
|
||||
)
|
||||
except Exception as delete_error:
|
||||
logger.warning(f"_publish_media_group: Не удалось удалить helper сообщение при ошибке: {delete_error}")
|
||||
raise PublishError(f"Не удалось опубликовать медиагруппу: {str(e)}")
|
||||
|
||||
@track_time("decline_post", "post_publish_service")
|
||||
@@ -399,27 +420,32 @@ class PostPublishService:
|
||||
@track_media_processing("media_group")
|
||||
async def _decline_media_group(self, call: CallbackQuery) -> None:
|
||||
"""Отклонение медиагруппы"""
|
||||
await self.db.update_status_for_media_group_by_helper_id(call.message.message_id, "declined")
|
||||
helper_message_id = call.message.message_id
|
||||
|
||||
await self.db.update_status_for_media_group_by_helper_id(helper_message_id, "declined")
|
||||
|
||||
post_ids = await self.db.get_post_ids_from_telegram_by_last_id(call.message.message_id)
|
||||
message_ids = post_ids.copy()
|
||||
message_ids.append(call.message.message_id)
|
||||
logger.debug(f"Получены ID сообщений для удаления: {message_ids}")
|
||||
media_group_message_ids = await self.db.get_post_ids_by_helper_id(helper_message_id)
|
||||
|
||||
author_id = await self._get_author_id_for_media_group(call.message.message_id)
|
||||
logger.debug(f"ID автора медиагруппы получен: {author_id}")
|
||||
message_ids_to_delete = media_group_message_ids.copy()
|
||||
message_ids_to_delete.append(helper_message_id)
|
||||
|
||||
logger.debug(f"Удаляю {len(message_ids)} сообщений из группы {self.group_for_posts}")
|
||||
await self._get_bot(call.message).delete_messages(chat_id=self.group_for_posts, message_ids=message_ids)
|
||||
author_id = await self._get_author_id_for_media_group(helper_message_id)
|
||||
|
||||
try:
|
||||
await self._get_bot(call.message).delete_messages(
|
||||
chat_id=self.group_for_posts,
|
||||
message_ids=message_ids_to_delete
|
||||
)
|
||||
except Exception as e:
|
||||
logger.warning(f"_decline_media_group: Ошибка при удалении сообщений: {e}")
|
||||
|
||||
try:
|
||||
logger.debug(f"Отправляю уведомление об отклонении автору медиагруппы {author_id}")
|
||||
await send_text_message(author_id, call.message, MESSAGE_POST_DECLINED)
|
||||
except Exception as e:
|
||||
if str(e) == ERROR_BOT_BLOCKED:
|
||||
logger.warning(f"Пользователь {author_id} заблокировал бота")
|
||||
logger.warning(f"_decline_media_group: Пользователь {author_id} заблокировал бота")
|
||||
raise UserBlockedBotError("Пользователь заблокировал бота")
|
||||
logger.error(f"Ошибка при отправке уведомления автору медиагруппы {author_id}: {e}")
|
||||
logger.error(f"_decline_media_group: Ошибка при отправке уведомления автору {author_id}: {e}")
|
||||
raise
|
||||
|
||||
@track_time("_get_author_id", "post_publish_service")
|
||||
@@ -477,12 +503,15 @@ class PostPublishService:
|
||||
@track_errors("post_publish_service", "_delete_media_group_and_notify_author")
|
||||
@track_media_processing("media_group")
|
||||
async def _delete_media_group_and_notify_author(self, call: CallbackQuery, author_id: int) -> None:
|
||||
"""Удаление медиагруппы и уведомление автора"""
|
||||
post_ids = await self.db.get_post_ids_from_telegram_by_last_id(call.message.message_id)
|
||||
"""Удаление медиагруппы и уведомление автора (legacy метод, используется для обратной совместимости)"""
|
||||
helper_message_id = call.message.message_id
|
||||
|
||||
media_group_message_ids = await self.db.get_post_ids_by_helper_id(helper_message_id)
|
||||
|
||||
#message_ids = post_ids.copy()
|
||||
post_ids.append(call.message.message_id)
|
||||
await self._get_bot(call.message).delete_messages(chat_id=self.group_for_posts, message_ids=post_ids)
|
||||
message_ids_to_delete = media_group_message_ids.copy()
|
||||
message_ids_to_delete.append(helper_message_id)
|
||||
|
||||
await self._get_bot(call.message).delete_messages(chat_id=self.group_for_posts, message_ids=message_ids_to_delete)
|
||||
try:
|
||||
await send_text_message(author_id, call.message, MESSAGE_POST_PUBLISHED)
|
||||
except Exception as e:
|
||||
@@ -538,7 +567,12 @@ class BanService:
|
||||
@db_query_time("ban_user_from_post", "users", "mixed")
|
||||
async def ban_user_from_post(self, call: CallbackQuery) -> None:
|
||||
"""Бан пользователя за спам"""
|
||||
author_id = await self.db.get_author_id_by_message_id(call.message.message_id)
|
||||
# Если это helper-сообщение медиагруппы, используем специальный метод
|
||||
if call.message.text == CONTENT_TYPE_MEDIA_GROUP:
|
||||
author_id = await self.db.get_author_id_by_helper_message_id(call.message.message_id)
|
||||
else:
|
||||
author_id = await self.db.get_author_id_by_message_id(call.message.message_id)
|
||||
|
||||
if not author_id:
|
||||
raise UserNotFoundError(f"Автор не найден для сообщения {call.message.message_id}")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user