Как в Telethon правильно обработать список сущностей при пересылке нескольких сообщений?

Как можно удалить ссылки при пересылке группы сообщений, учитывая, что метод <code>forward_messages()</code> не позволяет изменять список <code>entities</code> на уровне API Telegram? Я создал свой класс для группировки сообщений и использую метод <code>send_file()</code>, в который можно передать список файлов, подпись и <code>entities</code>. Есть ли другие подходы или рекомендации для решения этой проблемы?
  • 3 октября 2024 г. 20:34
Ответы на вопрос 2
Для обработки списка сущностей при пересылке нескольких сообщений с использованием Telethon, а также для удаления ссылок можно рассмотреть несколько подходов. Как вы правильно заметили, метод `forward_messages()` не позволяет изменять сущности, так как они формируются на стороне API Telegram.

1. **Использование `send_message()` вместо `forward_messages()`:**
   Как вы уже упомянули, вы можете использовать метод `send_file()` с вашими собственными изменениями. Вы можете пройтись по сообщениям, извлекать текст и сущности, и затем модифицировать их по своему усмотрению, например, удалять ссылки. После этого вы можете использовать `send_message()` для отправки модифицированного текста и новых сущностей.

2. **Создание собственного класса для обработки сообщений:**
   Если вы уже создали свой класс для группировки сообщений, добавьте в него метод для обработки текста и модификации сущностей. В этом методе можете реализовать логику удаления ссылок из текста сообщения.

   Пример кода для удаления ссылок из текста и работы с сущностями:

   ```python
   import re
   from telethon import TelegramClient
   from telethon.tl.types import MessageEntityUrl

   async def process_and_send_messages(client, messages, target):
       for message in messages:
           text = message.message
           entities = list(message.entities)  # Копируем сущности

           # Удаляем ссылки из текста
           urls_to_remove = {entity for entity in entities if isinstance(entity, MessageEntityUrl)}
           for url in urls_to_remove:
               start = url.offset
               end = start + url.length
               text = text[:start] + text[end:]  # Удаляем URL из текста
               # Освобождаем сущность URL от списка
               entities.remove(url)

           # Отправляем сообщение без ссылок
           await client.send_message(target, text, entities=entities)

   # Пример использования:
   async with TelegramClient('session_name', api_id, api_hash) as client:
       messages_to_send = await client.get_messages('source_chat', limit=10)
       await process_and_send_messages(client, messages_to_send, 'target_chat')
   ```

3. **Группировка сообщений:**
   Если вы хотите отправить сообщения группами, вы можете дополнительно сохранять сообщения в временном списке и отправлять их партиями, используя `await client.send_message()` для каждой группы.

4. **Дополнительные подходы:**
   - **Webhook-based solution:** Если это критично, вы можете настроить свой собственный прокси-сервер, который будет обрабатывать сообщения перед отправкой. Это более сложный путь, но полезный, если вам нужно выполнить больше манипуляций с сообщениями.
   - **Использование формата Markdown или HTML:** Если вы хотите просто убрать ссылки, а не тексты, можете использовать форматирование в Telethon. Например, можно послать текст с форматированием, где ссылки просто не будут отображаться.

Используя один из этих подходов, вы сможете управлять сущностями и контролировать содержимое сообщений при их пересылке.
Решил проблему под свои нужды изменением кода в библиотеке. Оказалось, если передаётся список медиа, то он обрабатывается <a href="https://github.com/LonamiWebs/Telethon/blob/04aea46fe43eaed98054a7333911f72e13262f46/telethon/client/uploads.py#L376" rel="nofollow">в этом блоке </a> через цикл, с помощью вызова метода <a href="https://github.com/LonamiWebs/Telethon/blob/04aea46fe43eaed98054a7333911f72e13262f46/telethon/client/uploads.py#L389" rel="nofollow">_send_album()</a> , который даже не принимает переданные ранее <a href="https://github.com/LonamiWebs/Telethon/blob/04aea46fe43eaed98054a7333911f72e13262f46/telethon/client/uploads.py#L122" rel="nofollow">formatting_entities</a> . <br/> <br/> Поэтому, я дописал в аргументы метода <a href="https://github.com/LonamiWebs/Telethon/blob/04aea46fe43eaed98054a7333911f72e13262f46/telethon/client/uploads.py#L433" rel="nofollow">_send_album()</a> аргумент formatting_entities: <br/> <pre><code class="python">async def _send_album(self: 'TelegramClient', entity, files, caption='',
                          formatting_entities=None,
                          progress_callback=None, reply_to=None,
                          parse_mode=(), silent=None, schedule=None,
                          supports_streaming=None, clear_draft=None,
                          force_document=False, background=None, ttl=None):</code></pre> <br/> И в сам <a href="https://github.com/LonamiWebs/Telethon/blob/04aea46fe43eaed98054a7333911f72e13262f46/telethon/client/uploads.py#L387" rel="nofollow">вызов _send_album()</a> тоже дописал передачу наших <code>formatted_entities</code> <br/> <pre><code class="python">result = []
            while file:
                result += await self._send_album(
                    entity, file[:10], caption=captions[:10], formatting_entities=formatting_entities,
                    progress_callback=used_callback, reply_to=reply_to,
                    parse_mode=parse_mode, silent=silent, schedule=schedule,
                    supports_streaming=supports_streaming, clear_draft=clear_draft,
                    force_document=force_document, background=background,
                )
                file = file[10:]
                captions = captions[10:]
                sent_count += 10

            return result</code></pre> <br/> Затем, <a href="https://github.com/LonamiWebs/Telethon/blob/04aea46fe43eaed98054a7333911f72e13262f46/telethon/client/uploads.py#L453" rel="nofollow">внутри метода _send_album()</a> после обработки подписей вставил код, чтобы <code>formatted_entities</code> к первому сообщению, если оно содержит текст: <br/> <pre><code class="python">if captions and captions[0]:
            captions[0] = (captions[0][0], formatting_entities)</code></pre> <br/> Ну и всё заработало. Теперь группа отправляется с форматированием. Но эти изменения тоже необходимо немного подкорректировать чтобы они универсально работали в разных случаях.
Похожие вопросы