Skip to content

get_chat_photos() does not return every photo for channels/groups when limit=0 #79

@Nissen96

Description

@Nissen96

Checklist

  • I am sure the error is coming from Hydrogram's code and not elsewhere
  • I have searched in the issue tracker for similar bug reports, including closed ones
  • I ran pip3 install -U https://github.com/hydrogram/hydrogram/archive/dev.zip and reproduced the issue using the latest development version

Description

For channel/supergroup peers, Client.get_chat_photos(chat_id) returns only one photo when called with the documented default limit=0, even when the chat has historical chat photo changes. This does not match the documented explanation: "By default, no limit is applied and all profile photos are returned."

Calling the same method with an explicit positive limit, e.g. limit=100, returns the expected current + historical chat photos.

Reason:

For an InputPeerChannel the limit is passed directly to messages.Search():

r = await utils.parse_messages(
    self,
    await self.invoke(
        raw.functions.messages.Search(
            peer=peer_id,
            q="",
            filter=raw.types.InputMessagesFilterChatPhotos(),
            min_date=0,
            max_date=0,
            offset_id=0,
            add_offset=0,
            limit=limit,
            max_id=0,
            min_id=0,
            hash=0,
        )
    ),
)

But this does not return all photos with limit=0. The core API docs says "Number of results to return, can be 0 to only return the message counter." and the pagination docs says "When 0 is provided the limit will often default to an intermediate value like ~20."

With a limit of 0, messages.Search() returns an empty list. With a positive limit like 100, all the historical photos were returned like expected.

Furthermore, the limit is also not handled correctly later when yielding the returned photos:

for current, photo in enumerate(photos, start=1):
    yield photo

    if current >= limit:
        return

A limit of 0 will return immediately after returning the current photo.

The function works fine for users, where photos are fetched with correct pagination and a total defaulting to (1 << 31) for a limit of 0. This is only relevant to groups/channels.

Steps to reproduce

  1. Authenticate with a user session (required to use the messages.Search functionality)
  2. Run client.get_chat_photos(<chat_id>) with an ID for a chat with multiple historical photos. Optionally set limit=0, but this is the default
  3. Notice it only returns the single current chat photo.
  4. Run again with client.get_chat_photos(<chat_id>, limit=1000) and see all photos are returned.

Code example

import asyncio
from hydrogram import Client

async def collect_photos(app: Client, *, limit: int = 0):
    photos = []
    async for photo in app.get_chat_photos(<CHAT_ID>, limit=limit):
        photos.append(photo)
    return photos

async def main():
    async with Client("default", <API_ID>, <API_HASH>) as app:
        default_photos = await collect_photos(app)
        limited_photos = await collect_photos(app, limit=100)

    print(f"default limit=0: {len(default_photos)} photo(s)")
    for i, photo in enumerate(default_photos, 1):
        print(f"  {i}. {photo.file_unique_id}")

    print(f"\nexplicit limit=100: {len(limited_photos)} photo(s)")
    for i, photo in enumerate(limited_photos, 1):
        print(f"  {i}. {photo.file_unique_id}")


if __name__ == "__main__":
    asyncio.run(main())

Logs

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions