diff --git a/main.py b/main.py index 24f2b5d..72c70b0 100644 --- a/main.py +++ b/main.py @@ -2,7 +2,7 @@ # from __future__ import annotations from telethon import TelegramClient, events -from telethon.tl.types import PeerUser, PeerChat, PeerChannel, Message +from telethon.tl.types import PeerUser, PeerChat, Chat, PeerChannel, Channel, Message import re import os import json @@ -159,6 +159,39 @@ async def prepare_entities(target_groups: list) -> list: print(f"Неизвестная ошибка при обработке {item}: {e}") +async def get_message_link(client, message): + """ + Генерирует ссылку на сообщение вида https://t.me/username/123 или https://t.me/c/123456789/123 + Работает с любыми чатами: личка, группа, канал (публичный/приватный). + """ + msg_id = message.id + + # Шаг 1: Пытаемся использовать message.chat, если он загружен и имеет username + if message.chat and getattr(message.chat, 'username', None): + return f"https://t.me/{message.chat.username}/{msg_id}" + + # Шаг 2: Используем peer_id для получения сущности + try: + chat = await client.get_entity(message.peer_id) + except Exception as e: + print(f"Failed to get entity from peer_id: {e}") + return None + + # Шаг 3: Строим ссылку + if getattr(chat, 'username', None): + return f"https://t.me/{chat.username}/{msg_id}" + + # Для приватных чатов и каналов: используем формат t.me/c/{id}/{msg_id} + chat_id = str(chat.id) + + if isinstance(chat, (Channel, Chat)) and chat_id.startswith('-100'): + base_id = chat_id[4:] # Убираем -100 + return f"https://t.me/c/{base_id}/{msg_id}" + + # На всякий случай (редкий случай) + return f"https://t.me/c/{chat_id}/{msg_id}" + + async def forward_to_targets( message: Message, targets: Optional[list[str | int]] = None, @@ -172,7 +205,7 @@ async def forward_to_targets( if source_reply_to_msg_id and (forwarded_info:=source_messages.get(str(source_reply_to_msg_id))): for str_chat_id, target_msg_id in forwarded_info['forwarded_msg_id'].items(): if str_chat_id == str(entity.id): - link = await client.get_message_link(message) + link = await get_message_link(message) text = f'Переслано из [{message.chat.title}]({link})\n{message.text}' new_msg = await client.send_message(str_chat_id, text, reply_to=target_msg_id, parse_mode='markdown') else: @@ -237,45 +270,55 @@ async def handler_NewMessages(event: events.NewMessage.Event): @client.on(events.MessageEdited(chats=source_channel_username)) async def handler_edited(event: events.MessageEdited.Event): stored_m_info = source_messages.get(str(event.message.id)) + if not stored_m_info: + if check(event.message.text): + log.info(f"📝 Изменённое с новым триггером, пересылаю: {shorten(event.message.text)}") + await forward_to_targets(event.message) if stored_m_info and stored_m_info['text'] != event.message.text: - log.info(f"📝 Сообщение изменено: {shorten(stored_m_info['text'])} → {shorten(event.message.text)}") - # Редактируем пересланное сообщение - for str_chat_id, msg_id in stored_m_info['forwarded_msg_id'].items(): - chat_id = int(str_chat_id) - # Получаем ID последнего сообщения в целевом чате - last_msg_id = last_known_msg_id.get(str_chat_id) - if not last_msg_id: - last_msg_id = await update_last_msg_id(chat_id) - log.debug(f'chat_id={chat_id}, stored_msg_id={msg_id}, last_msg_id_on_channel={last_msg_id}') - # Проверяем, является ли наше пересланное сообщение последним - if msg_id == last_msg_id: - # Это последнее сообщение — можно удалить и переслать заново - await forward_to_targets(event.message, targets=[chat_id]) + if not check(event.message.text): + log.info(f"📝 Сообщение изменено, не попадает в фильтр - удаляю: {shorten(stored_m_info['text'])} → {shorten(event.message.text)}") + for str_chat_id, msg_id in stored_m_info['forwarded_msg_id'].items(): + chat_id = int(str_chat_id) await client.delete_messages(chat_id, msg_id) - log.info(f"🔁 {chat_id} Сообщение было последним → Заменено") - else: - # Не последнее → отправляем изменённый текст как ответ - new_msg = await client.send_message( - chat_id, - f"🔄 Текст изменён:\n{event.message.text}", - reply_to=stored_m_info['forwarded_msg_id'][str_chat_id] - ) - # Запоминаем пересланные данные сообщения - sm = source_messages.get(str(event.message.id)) - if not sm: - source_messages[str(event.message.id)] = { - 'text': event.message.text, - 'timestamp': event.message.date.timestamp(), - 'forwarded_msg_id': {str(new_msg.chat.id): new_msg.id} - } + else: + log.info(f"📝 Сообщение изменено: {shorten(stored_m_info['text'])} → {shorten(event.message.text)}") + # Редактируем пересланное сообщение + for str_chat_id, msg_id in stored_m_info['forwarded_msg_id'].items(): + chat_id = int(str_chat_id) + # Получаем ID последнего сообщения в целевом чате + last_msg_id = last_known_msg_id.get(str_chat_id) + if not last_msg_id: + last_msg_id = await update_last_msg_id(chat_id) + log.debug(f'chat_id={chat_id}, stored_msg_id={msg_id}, last_msg_id_on_channel={last_msg_id}') + # Проверяем, является ли наше пересланное сообщение последним + if msg_id == last_msg_id: + # Это последнее сообщение — можно удалить и переслать заново + await forward_to_targets(event.message, targets=[chat_id]) + await client.delete_messages(chat_id, msg_id) + log.info(f"🔁 {chat_id} Сообщение было последним → Заменено") else: - sm['text'] = event.message.text - sm['timestamp'] = event.message.date.timestamp() - sm['forwarded_msg_id'][str(new_msg.chat.id)] = new_msg.id - # Обновляем последние известные id для канала - last_known_msg_id[str(new_msg.chat.id)] = new_msg.id + # Не последнее → отправляем изменённый текст как ответ + new_msg = await client.send_message( + chat_id, + f"🔄 Текст изменён:\n{event.message.text}", + reply_to=stored_m_info['forwarded_msg_id'][str_chat_id] + ) + # Запоминаем пересланные данные сообщения + sm = source_messages.get(str(event.message.id)) + if not sm: + source_messages[str(event.message.id)] = { + 'text': event.message.text, + 'timestamp': event.message.date.timestamp(), + 'forwarded_msg_id': {str(new_msg.chat.id): new_msg.id} + } + else: + sm['text'] = event.message.text + sm['timestamp'] = event.message.date.timestamp() + sm['forwarded_msg_id'][str(new_msg.chat.id)] = new_msg.id + # Обновляем последние известные id для канала + last_known_msg_id[str(new_msg.chat.id)] = new_msg.id - log.info(f"💬 {chat_id} Сообщение не последнее → Отправлен ответ") + log.info(f"💬 {chat_id} Сообщение не последнее → Отправлен ответ") @client.on(events.MessageDeleted(chats=source_channel_username))