Не могу правильно поменять параметр класса
Создаю бота для копирования сообщений в тг. Использую Telethon. Логика такая: Ищу сообщения Сортирую по датам и типам Редактирую и вешаю флаг is_changed для сообщения на основе классе CMessage (сам создал) Удаляю все, что имеет is_changed = False
Со всеми сообщениями у меня все круто. Но с альбомами беда. Помимо того, что в телеге странная система медиа - они разбиты по разным классам, и некоторые имеют взаимозаменяемость, а некоторые нет, пример:
Давайте так, "->" можно заменить, "--" нельзя
сообщение -> сообщение с одним медиа
сообщение -- сообщение с группой медиа
сообщение с одним медиа -- сообщение
сообщение с одним медиа -> сообщение с группой медиа (берем 1 сообщение группы - остальное удаляем)
сообщение с группой медиа -> сообщение с одни медиа (остальные сообщения группы удаляем)
сообщение с группой медиа -- сообщение
Ну так вот, я использую метод _edit_post чтобы отредактировать сообщение, и если сообщение отредактировано - меняю флаг класса CMessage на True. Если сообщение оказывается частью media group - запускаю _edit_album. И тут проблема - там я создаю новый список сообщений, и из вне уже не могу отследить is_changed общего альбома. Если я буду ставить флаг параметру target_message функции _edit_album, то нет гарантий что флаг применится нужному сообщению. И в принципе, ошибку я понимаю, но правильно организовать не могу.
Вот основной код
async def _edit_post(self, target_message: CMessage, source_message: CMessage) -> bool:
try:
"""Ну и редактируем сообщение, здесь нет сложной логики"""
logger.info(f"Редактируем {target_message.id} ({target_message.date.date()}) -> {source_message.id}")
# Дефолт параметры
edit_params = {
'entity': target_message.peer_id,
'message': target_message.id,
'text': source_message.message or ''
}
"""Разные тайпы сообщений -> разные способы изменения"""
if source_message.grouped_id or target_message.grouped_id:
await self._edit_album(target_message=target_message, source_message=source_message)
elif (
(
(source_message.media and not source_message.grouped_id)
and
(target_message.media and not target_message.grouped_id)
)
or
(not target_message.media and source_message.media)
or
(
(target_message.grouped_id or not target_message.media)
and
(source_message.media and not source_message.grouped_id)
)):
"""
Трудная проверка, но разобраться можно. Если не медиагруппа в основном и целевом канале,
или нету текст в целевом - медиа в основном - ставим медиа
"""
edit_params['file'] = source_message.media
"""Тут редачу"""
await self.edit_message(**edit_params)
"""
Вот и флаг is_changed - для него и делал класс CMessage.
Флаг говорит о том, что внутри одного процесса пост уже был изменен
"""
target_message.is_changed = True
return True
except MessageNotModifiedError:
target_message.is_changed = True
return True
except Exception as e:
logger.error(f"Ошибка при редактировании {target_message.id}: {e}")
return False
async def _edit_album(self, target_message: CMessage, source_message: CMessage) -> None:
"""Тут собираю альбом"""
target_album = await self._remake_album_messages(album_message=target_message)
source_album = await self._remake_album_messages(album_message=source_message)
for i, (target, source) in enumerate(zip(target_album, source_album)):
if i >= len(target_album):
break
edit_params = {
'entity': target.peer_id,
'message': target.id,
'text': source.message or '',
'file': source.media
}
try:
await self.edit_message(**edit_params)
except MessageNotModifiedError:
pass
except Exception as e:
logger.error(f"Ошибка при редактировании элемента альбома {target.id}: {e}")
async def _remake_album_messages(self, album_message: CMessage) -> list[CMessage]:
"""Достаю все сообщения альбома"""
if not album_message.grouped_id:
return [album_message]
messages = await self.get_messages(
entity=album_message.peer_id,
limit=11,
offset_id=album_message.id
)
album_messages = [
CMessage.to_cmessage(message) for message in messages
if message.grouped_id == album_message.grouped_id
]
return sorted(album_messages, key=lambda x: x.date.date())
async def _delete_unchanged_messages(self, target_list: list[CMessage]) -> None:
print([(msg.message, msg.is_changed) for msg in target_list])
for message in target_list:
if not message.is_changed:
try:
await self.delete_messages(entity=message.peer_id, message_ids=message.id)
logger.info(f"Удалено сообщение {message.id}, с текстом: {message.message}")
except Exception as e:
logger.error(f"Произошла ошибка при удалении сообщения {message.id} ({message.date.date()}): {e}")
Вот класс CMessage
class CMessage(Message):
"""
Мой класс CMessage, сюда я добавил параметр is_change,
чтобы отслеживать, изменял ли я сообщение в текущей итерации или нет
"""
def __init__(self, id, peer_id, date, message, out = None, mentioned = None, media_unread = None, silent = None, post = None, from_scheduled = None, legacy = None, edit_hide = None, pinned = None, noforwards = None, invert_media = None, offline = None, video_processing_pending = None, from_id = None, from_boosts_applied = None, saved_peer_id = None, fwd_from = None, via_bot_id = None, via_business_bot_id = None, reply_to = None, media = None, reply_markup = None, entities = None, views = None, forwards = None, replies = None, edit_date = None, post_author = None, grouped_id = None, reactions = None, restriction_reason = None, ttl_period = None, quick_reply_shortcut_id = None, effect = None, factcheck = None, report_delivery_until_date = None, is_changed = False):
super().__init__(id, peer_id, date, message, out, mentioned, media_unread, silent, post, from_scheduled, legacy, edit_hide, pinned, noforwards, invert_media, offline, video_processing_pending, from_id, from_boosts_applied, saved_peer_id, fwd_from, via_bot_id, via_business_bot_id, reply_to, media, reply_markup, entities, views, forwards, replies, edit_date, post_author, grouped_id, reactions, restriction_reason, ttl_period, quick_reply_shortcut_id, effect, factcheck, report_delivery_until_date)
self.is_changed = is_changed
def __str__(self):
info = super().__str__().replace("Message", "CMessage")
return info[:-1] + f", is_changed={self.is_changed})"
@staticmethod
def to_cmessage(message: Message, is_changed: bool = False) -> "CMessage":
"""Создает экземпляр CMessage из экземпляра Message"""
return CMessage(
id=message.id,
peer_id=message.peer_id,
date=message.date,
message=message.message,
out=message.out,
mentioned=message.mentioned,
media_unread=message.media_unread,
silent=message.silent,
post=message.post,
from_scheduled=message.from_scheduled,
legacy=message.legacy,
edit_hide=message.edit_hide,
pinned=message.pinned,
noforwards=message.noforwards,
invert_media=message.invert_media,
offline=message.offline,
video_processing_pending=message.video_processing_pending,
from_id=message.from_id,
from_boosts_applied=message.from_boosts_applied,
saved_peer_id=message.saved_peer_id,
fwd_from=message.fwd_from,
via_bot_id=message.via_bot_id,
via_business_bot_id=message.via_business_bot_id,
reply_to=message.reply_to,
media=message.media,
reply_markup=message.reply_markup,
entities=message.entities,
views=message.views,
forwards=message.forwards,
replies=message.replies,
edit_date=message.edit_date,
post_author=message.post_author,
grouped_id=message.grouped_id,
reactions=message.reactions,
restriction_reason=message.restriction_reason,
ttl_period=message.ttl_period,
quick_reply_shortcut_id=message.quick_reply_shortcut_id,
effect=message.effect,
factcheck=message.factcheck,
report_delivery_until_date=message.report_delivery_until_date,
is_changed=is_changed
)