Search code examples
pythonpython-3.xtelegramtelethonpyrogram

Telethon (or Pyrogram) forward whole album instead of last media without caption


I'm trying to forward any last message from a specififc channel using Telethon's client.iter_messages(channel_id, limit=1) and message.forward_to(group_id)

The problem is if the message is an album, only the last image of the album gets forwarded. Also caption is not included.

The exact same thing happens with Pyrogram's app.get_chat_history(channel_id, limit=1) and message.forward(group_id)

The problem itself, I suppose, lies in the way ids work for media in albums. I need a way to somehow forward the whole message.

Note: I am aware of Telethon's events.Album but don't see any way to implement it in my case. Also this (Forward message (album) telethon) somehow relates to my problem but again I don't know how to make it work properly. Also if message.grouped_id: might help.

Code (Telethon variant):

from telethon import TelegramClient

client = TelegramClient('telethon-client', api_id, api_hash)


async def main():
    async for message in client.iter_messages(test_channel_id, limit=1):
        await message.forward_to(test_group_id)


with client:
    client.loop.run_until_complete(main())

Solution

  • The problem is if the message is an album, only the last image of the album gets forwarded. Also caption is not included.

    This is because albums are in fact separate messages. "The last message" is the last photo of the album, and clients often put the caption in the first image of the album.

    The problem itself, I suppose, lies in the way ids work for media in albums. I need a way to somehow forward the whole message.

    You are correctly forwarding the "whole" message. The problem is you want to forward multiple messages at the same time.

    Also if message.grouped_id: might help

    Yes, you can use that to detect what messages belong to the same group. An album consists of up to ten messages that share the grouped_id.

    You can do something like this:

    current_album = None
    current_group_id = None
    
    async for message in client.iter_messages(test_channel_id):
        if current_group_id and message.grouped_id != current_group_id:
            print('Group finished:', current_group_id, 'had', len(current_album))
            current_group_id = None
            current_album = None
    
        if not current_group_id and message.grouped_id:
            print('New group:', message.grouped_id)
            current_group_id = message.grouped_id
            current_album = []
    
        if current_group_id:
            current_album.append(message)
        
    

    This will tell you how many messages are found in a group. Note that it is possible for messages that have a grouped_id to be interleaved with messages that don't (so the above code can fail):

    • msg_id 1001, grouped_id 4001
    • msg_id 1002, grouped_id None
    • msg_id 1003, grouped_id 4001

    is possible, and the code will detect the 4001 album twice, each time with one message. You can adapt the code to attempt to handle this. It is not possible to determine an album's length beforehand, you just need to fetch more messages to find out if they're in the same group.