Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,9 @@ tg = Telegram(
)
tg.login()

# If this is the first run, the library needs to preload all chats.
# Otherwise, the message will not be sent.
result = tg.get_chats()
# The chat must be in the tdlib database before you can send a message to it.
# `get_chats` loads up to `limit` chats from the main chat list.
result = tg.get_chats(limit=100)
result.wait()

chat_id = 123456789
Expand Down
2 changes: 2 additions & 0 deletions docs/source/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ Changelog
- Calling a method after ``stop`` raises ``ClientDestroyedError`` instead of crashing the process. The destroyed tdlib handle was passed to the C library as a ``NULL`` pointer.
- An exception raised by an update handler no longer stops the worker thread. The error is logged and the worker keeps processing the queue.
- When the handler queue is full, the update is dropped and an error is logged instead of raising ``queue.Full``.
- ``get_chats`` no longer sends the ``offset_order`` and ``offset_chat_id`` parameters. tdlib removed them from ``getChats`` in 1.8.0 and silently ignored them since then, so passing them had no effect. The signature is now ``get_chats(limit=100, chat_list=None)``, which also makes it possible to read the archive and chat folders instead of only the main chat list. This is a breaking change for code that passes the offsets.
- Added ``load_chats``, which wraps the tdlib ``loadChats`` method.

[0.19.0] - 2024-06-23
---------------------
Expand Down
2 changes: 1 addition & 1 deletion examples/clear_group_messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ def delete_messages(chat_id, message_ids):
print(result.update)

# get chats
result = tg.get_chats(9223372036854775807) # const 2^62-1: from the first
result = tg.get_chats(limit=100)
result.wait()
chats = result.update["chat_ids"]

Expand Down
6 changes: 3 additions & 3 deletions examples/send_message.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@
# you must call login method before others
tg.login()

# if this is the first run, library needs to preload all chats
# otherwise the message will not be sent
get_chats_result = tg.get_chats()
# the chat must be in the tdlib database before you can send a message to it,
# `get_chats` loads up to `limit` chats from the main chat list
get_chats_result = tg.get_chats(limit=100)
# `tdlib` is asynchronous, so `python-telegram` always returns you an `AsyncResult` object.
# You can wait for a result with the blocking `wait` method.
get_chats_result.wait()
Expand Down
48 changes: 44 additions & 4 deletions telegram/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -396,9 +396,20 @@ def get_user_full_info(self, user_id: int) -> AsyncResult:

return self.call_method("getUserFullInfo", params={"user_id": user_id})

def get_chats(self, offset_order: int = 0, offset_chat_id: int = 0, limit: int = 100) -> AsyncResult:
def get_chats(self, limit: int = 100, chat_list: dict | None = None) -> AsyncResult:
"""
Returns a list of chats.
Returns an ordered list of chats from the beginning of a chat list.

tdlib loads chats from the server until ``limit`` chats are available
or the end of the list is reached, so this method also saves those
chats to the database.

https://core.telegram.org/tdlib/docs/classtd_1_1td__api_1_1get_chats.html

Args:
limit: the maximum number of chats to return
chat_list: the chat list to return chats from, the main chat list
if not set. For example: ``{'@type': 'chatListArchive'}``

Returns:
AsyncResult
Expand All @@ -407,6 +418,7 @@ def get_chats(self, offset_order: int = 0, offset_chat_id: int = 0, limit: int =

{
'@type': 'chats',
'total_count': 10,
'chat_ids': [...],
'@extra': {
'request_id': '...'
Expand All @@ -415,8 +427,36 @@ def get_chats(self, offset_order: int = 0, offset_chat_id: int = 0, limit: int =
"""
data = {
"@type": "getChats",
"offset_order": offset_order,
"offset_chat_id": offset_chat_id,
"chat_list": chat_list,
"limit": limit,
}

return self._send_data(data)

def load_chats(self, limit: int = 100, chat_list: dict | None = None) -> AsyncResult:
"""
Loads more chats from a chat list.

The chats are not returned by this method, they are sent through
updates. tdlib chooses how many chats to load and can load fewer
than ``limit``.

https://core.telegram.org/tdlib/docs/classtd_1_1td__api_1_1load_chats.html

Args:
limit: the maximum number of chats to load
chat_list: the chat list to load chats from, the main chat list
if not set. For example: ``{'@type': 'chatListArchive'}``

Returns:
AsyncResult

The update will be ``{'@type': 'ok'}``, or an error with the code
404 when all the chats in the list have already been loaded.
"""
data = {
"@type": "loadChats",
"chat_list": chat_list,
"limit": limit,
}

Expand Down
36 changes: 31 additions & 5 deletions tests/test_telegram_methods.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,16 +261,42 @@ def test_get_chat(self, telegram):
telegram._tdjson.send.assert_called_once_with(exp_data)

def test_get_chats(self, telegram):
offset_order = 1
offset_chat_id = 1
limit = 100

async_result = telegram.get_chats(offset_order=offset_order, offset_chat_id=offset_chat_id, limit=limit)
async_result = telegram.get_chats(limit=limit)

exp_data = {
"@type": "getChats",
"offset_order": offset_order,
"offset_chat_id": offset_chat_id,
"chat_list": None,
"limit": limit,
"@extra": {"request_id": async_result.id},
}

telegram._tdjson.send.assert_called_once_with(exp_data)

def test_get_chats_with_chat_list(self, telegram):
limit = 10
chat_list = {"@type": "chatListArchive"}

async_result = telegram.get_chats(limit=limit, chat_list=chat_list)

exp_data = {
"@type": "getChats",
"chat_list": chat_list,
"limit": limit,
"@extra": {"request_id": async_result.id},
}

telegram._tdjson.send.assert_called_once_with(exp_data)

def test_load_chats(self, telegram):
limit = 100

async_result = telegram.load_chats(limit=limit)

exp_data = {
"@type": "loadChats",
"chat_list": None,
"limit": limit,
"@extra": {"request_id": async_result.id},
}
Expand Down