Search code examples
pythontelegrammessage-queuetelethon

Dealing with multiple media attachments in Telegram message handler with Python and Zeromq message queue


I'am writing telegram bot that gets all new messages in telegram news group and putting all the data to the zeromq message queue for consumer distribution. The idea is one post (text+media) - one element in queue. But the problem rises when post contains several media items, because event handler treats them like separate messages. So for example if few photos was attached to telegram chat message, code will put them separate elements in message queue, while I need everything to be put into one element. Here's the code:

@tg_client.on(events.NewMessage(chats=('tewst123')))
async def handler(event):
    message = event.message
    text = message.message
    file = await tg_client.download_media(message.media, 'temp')
    # at the moment I need only path to medias
    publisher.send_json(
        {
            "message_id": message.id,
            "chat_name": message.chat.username,
            "text": message.message,
            "media_path": file,
        }
    )

I tried to use album handler:

@tg_client.on(events.NewMessage(chats=('tewst123')))
async def album_handler(event):
    message = event.message
    text = message.message
    album_files = []
    for mes in event.messages:
        # Download each media item
        file_path = await tg_client.download_media(message=mes)
        album_files.append(file_path)

    publisher.send_json(
        {
            "message_id": message.id,
            "chat_name": message.chat.username,
            "text": message.message,
            "media_path": album_files,
        }
    )

But I am getting an error: AttributeError: 'Message' object has no attribute 'messages'

Name: Telethon Version: 1.28.5

Python 3.10.5

Windows 11 x64


Solution

  • Your event.message does not have an attribute messages, lets try to use events.Album instead of events.NewMessage.

    edit: lets change id to grouped_id so that refer it to the media group instead and for the event firing every time, we will check if the event is an album before handling it, then handle non-album messages separately.

    @tg_client.on(events.NewMessage(chats=('tewst123')))
    async def handler(event):
        if not event.grouped_id:
            message = event.message
            text = message.text
            file = await tg_client.download_media(message.media, 'temp')
    
            publisher.send_json(
                {
                    "message_id": message.id,
                    "chat_name": message.chat.username,
                    "text": message.text,
                    "media_path": file,
                }
            )
    
    @tg_client.on(events.Album())
    async def album_handler(event):
        text = event.text
        album_files = []
        for message in event.messages:
            file_path = await tg_client.download_media(message=message)
            album_files.append(file_path)
    
        publisher.send_json(
            {
                "message_id": event.grouped_id,
                "chat_name": event.chat.username,
                "text": text,
                "media_path": album_files,
            }
        )