fix: get_message_link

fix: работа с изменёнными сообщениями
теперь новый текст тоже проверятся на совпадение
и соответсвенно пересылвается или удаляется
This commit is contained in:
Евгений Панков 2025-08-21 01:00:34 +03:00
parent 5a4fe0ae94
commit 0055684b34

117
main.py
View File

@ -2,7 +2,7 @@
# from __future__ import annotations # from __future__ import annotations
from telethon import TelegramClient, events 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 re
import os import os
import json import json
@ -159,6 +159,39 @@ async def prepare_entities(target_groups: list) -> list:
print(f"Неизвестная ошибка при обработке {item}: {e}") 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( async def forward_to_targets(
message: Message, message: Message,
targets: Optional[list[str | int]] = None, 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))): 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(): for str_chat_id, target_msg_id in forwarded_info['forwarded_msg_id'].items():
if str_chat_id == str(entity.id): 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}' 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') new_msg = await client.send_message(str_chat_id, text, reply_to=target_msg_id, parse_mode='markdown')
else: else:
@ -237,45 +270,55 @@ async def handler_NewMessages(event: events.NewMessage.Event):
@client.on(events.MessageEdited(chats=source_channel_username)) @client.on(events.MessageEdited(chats=source_channel_username))
async def handler_edited(event: events.MessageEdited.Event): async def handler_edited(event: events.MessageEdited.Event):
stored_m_info = source_messages.get(str(event.message.id)) 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: if stored_m_info and stored_m_info['text'] != event.message.text:
log.info(f"📝 Сообщение изменено: {shorten(stored_m_info['text'])}{shorten(event.message.text)}") 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(): for str_chat_id, msg_id in stored_m_info['forwarded_msg_id'].items():
chat_id = int(str_chat_id) 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) await client.delete_messages(chat_id, msg_id)
log.info(f"🔁 {chat_id} Сообщение было последним → Заменено") else:
else: log.info(f"📝 Сообщение изменено: {shorten(stored_m_info['text'])}{shorten(event.message.text)}")
# Не последнее → отправляем изменённый текст как ответ # Редактируем пересланное сообщение
new_msg = await client.send_message( for str_chat_id, msg_id in stored_m_info['forwarded_msg_id'].items():
chat_id, chat_id = int(str_chat_id)
f"🔄 Текст изменён:\n{event.message.text}", # Получаем ID последнего сообщения в целевом чате
reply_to=stored_m_info['forwarded_msg_id'][str_chat_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)
sm = source_messages.get(str(event.message.id)) log.debug(f'chat_id={chat_id}, stored_msg_id={msg_id}, last_msg_id_on_channel={last_msg_id}')
if not sm: # Проверяем, является ли наше пересланное сообщение последним
source_messages[str(event.message.id)] = { if msg_id == last_msg_id:
'text': event.message.text, # Это последнее сообщение — можно удалить и переслать заново
'timestamp': event.message.date.timestamp(), await forward_to_targets(event.message, targets=[chat_id])
'forwarded_msg_id': {str(new_msg.chat.id): new_msg.id} await client.delete_messages(chat_id, msg_id)
} log.info(f"🔁 {chat_id} Сообщение было последним → Заменено")
else: else:
sm['text'] = event.message.text # Не последнее → отправляем изменённый текст как ответ
sm['timestamp'] = event.message.date.timestamp() new_msg = await client.send_message(
sm['forwarded_msg_id'][str(new_msg.chat.id)] = new_msg.id chat_id,
# Обновляем последние известные id для канала f"🔄 Текст изменён:\n{event.message.text}",
last_known_msg_id[str(new_msg.chat.id)] = new_msg.id 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)) @client.on(events.MessageDeleted(chats=source_channel_username))