From 83f2111be95e4e52d5b0df7146468bbed7318fb7 Mon Sep 17 00:00:00 2001
From: NickolaiH <48893302+WubbaLubbaDubDubDev@users.noreply.github.com>
Date: Tue, 19 Aug 2025 18:30:56 +0300
Subject: [PATCH 1/5] FIX get_dialogs.py
Fix infinite loop in get_dialogs() by preventing repeated dialogs
- Added tracking of seen dialog IDs to avoid yielding duplicates
- Added check for None top_message to safely stop pagination
- Preserved support for limit, pinned_only, and chat_list parameters
- Ensured correct offset updates for reliable pagination
---
pyrogram/methods/chats/get_dialogs.py | 60 +++++++++------------------
1 file changed, 19 insertions(+), 41 deletions(-)
diff --git a/pyrogram/methods/chats/get_dialogs.py b/pyrogram/methods/chats/get_dialogs.py
index cfd8c145a3..660637d5b7 100644
--- a/pyrogram/methods/chats/get_dialogs.py
+++ b/pyrogram/methods/chats/get_dialogs.py
@@ -16,11 +16,10 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
-from asyncio import sleep
from typing import AsyncGenerator, Optional
-import pyrogram
from pyrogram import types, raw, utils
+from pyrogram.errors import ChannelPrivate, PeerIdInvalid
class GetDialogs:
@@ -30,47 +29,24 @@ async def get_dialogs(
pinned_only: bool = False,
chat_list: int = 0
) -> Optional[AsyncGenerator["types.Dialog", None]]:
- """Get a user's dialogs sequentially.
-
- .. include:: /_includes/usable-by/users.rst
-
- Parameters:
- limit (``int``, *optional*):
- Limits the number of dialogs to be retrieved.
- By default, no limit is applied and all dialogs are returned.
-
- pinned_only (``bool``, *optional*):
- Pass True if you want to get only pinned dialogs.
- Defaults to False.
-
- chat_list (``int``, *optional*):
- Chat list from which to get the dialogs; Only Main (0) and Archive (1) chat lists are supported. Defaults to (0) Main chat list.
-
- Returns:
- ``Generator``: A generator yielding :obj:`~pyrogram.types.Dialog` objects.
-
- Example:
- .. code-block:: python
-
- # Iterate through all dialogs
- async for dialog in app.get_dialogs():
- print(dialog.chat.first_name or dialog.chat.title)
- """
+
current = 0
total = limit or (1 << 31) - 1
- limit = min(100, total)
+ request_limit = min(100, total)
offset_date = 0
offset_id = 0
offset_peer = raw.types.InputPeerEmpty()
+ seen_dialog_ids = set()
+
while True:
r = await self.invoke(
raw.functions.messages.GetDialogs(
offset_date=offset_date,
offset_id=offset_id,
offset_peer=offset_peer,
- limit=limit,
+ limit=request_limit,
hash=0,
exclude_pinned=not pinned_only,
folder_id=chat_list
@@ -88,13 +64,10 @@ async def get_dialogs(
continue
chat_id = utils.get_peer_id(message.peer_id)
- messages[chat_id] = await types.Message._parse(
- self,
- message,
- users,
- chats,
- replies=self.fetch_replies
- )
+ try:
+ messages[chat_id] = await types.Message._parse(self, message, users, chats)
+ except (ChannelPrivate, PeerIdInvalid):
+ continue
dialogs = []
@@ -102,22 +75,27 @@ async def get_dialogs(
if not isinstance(dialog, raw.types.Dialog):
continue
- dialogs.append(types.Dialog._parse(self, dialog, messages, users, chats))
+ parsed = types.Dialog._parse(self, dialog, messages, users, chats)
+ if parsed.chat.id in seen_dialog_ids:
+ continue
+ seen_dialog_ids.add(parsed.chat.id)
+
+ dialogs.append(parsed)
if not dialogs:
return
last = dialogs[-1]
+ if last.top_message is None:
+ return
+
offset_id = last.top_message.id
offset_date = utils.datetime_to_timestamp(last.top_message.date)
offset_peer = await self.resolve_peer(last.chat.id)
for dialog in dialogs:
- await sleep(0)
yield dialog
-
current += 1
-
if current >= total:
return
From 6ebe425edf79f955c2b2695c0efff11c85b9e6e6 Mon Sep 17 00:00:00 2001
From: NickolaiH <48893302+WubbaLubbaDubDubDev@users.noreply.github.com>
Date: Tue, 19 Aug 2025 18:59:59 +0300
Subject: [PATCH 2/5] FIX get_dialogs.py
fix: skip dialogs with no parsed chat to avoid errors
---
pyrogram/methods/chats/get_dialogs.py | 35 +++++++++++++++++++++++++--
1 file changed, 33 insertions(+), 2 deletions(-)
diff --git a/pyrogram/methods/chats/get_dialogs.py b/pyrogram/methods/chats/get_dialogs.py
index 660637d5b7..89a1f3b0bb 100644
--- a/pyrogram/methods/chats/get_dialogs.py
+++ b/pyrogram/methods/chats/get_dialogs.py
@@ -29,7 +29,32 @@ async def get_dialogs(
pinned_only: bool = False,
chat_list: int = 0
) -> Optional[AsyncGenerator["types.Dialog", None]]:
-
+ """Get a user's dialogs sequentially.
+
+ .. include:: /_includes/usable-by/users.rst
+
+ Parameters:
+ limit (``int``, *optional*):
+ Limits the number of dialogs to be retrieved.
+ By default, no limit is applied and all dialogs are returned.
+
+ pinned_only (``bool``, *optional*):
+ Pass True if you want to get only pinned dialogs.
+ Defaults to False.
+
+ chat_list (``int``, *optional*):
+ Chat list from which to get the dialogs; Only Main (0) and Archive (1) chat lists are supported. Defaults to (0) Main chat list.
+
+ Returns:
+ ``Generator``: A generator yielding :obj:`~pyrogram.types.Dialog` objects.
+
+ Example:
+ .. code-block:: python
+
+ # Iterate through all dialogs
+ async for dialog in app.get_dialogs():
+ print(dialog.chat.first_name or dialog.chat.title)
+ """
current = 0
total = limit or (1 << 31) - 1
request_limit = min(100, total)
@@ -76,10 +101,16 @@ async def get_dialogs(
continue
parsed = types.Dialog._parse(self, dialog, messages, users, chats)
+ if parsed is None:
+ continue
+
+ if parsed.chat is None:
+ continue
+
if parsed.chat.id in seen_dialog_ids:
continue
+
seen_dialog_ids.add(parsed.chat.id)
-
dialogs.append(parsed)
if not dialogs:
From 7c5883360baef2eb462c0d752b7f3bb1d8084375 Mon Sep 17 00:00:00 2001
From: Shrimadhav U K
Date: Wed, 20 Aug 2025 09:16:54 +0530
Subject: [PATCH 3/5] Update get_dialogs.py
---
pyrogram/methods/chats/get_dialogs.py | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/pyrogram/methods/chats/get_dialogs.py b/pyrogram/methods/chats/get_dialogs.py
index 89a1f3b0bb..40e1e173b9 100644
--- a/pyrogram/methods/chats/get_dialogs.py
+++ b/pyrogram/methods/chats/get_dialogs.py
@@ -16,10 +16,10 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
+from asyncio import sleep
from typing import AsyncGenerator, Optional
-from pyrogram import types, raw, utils
-from pyrogram.errors import ChannelPrivate, PeerIdInvalid
+from pyrogram import raw, types, utils
class GetDialogs:
@@ -89,10 +89,7 @@ async def get_dialogs(
continue
chat_id = utils.get_peer_id(message.peer_id)
- try:
- messages[chat_id] = await types.Message._parse(self, message, users, chats)
- except (ChannelPrivate, PeerIdInvalid):
- continue
+ messages[chat_id] = await types.Message._parse(self, message, users, chats, replies=self.fetch_replies)
dialogs = []
@@ -126,6 +123,7 @@ async def get_dialogs(
offset_peer = await self.resolve_peer(last.chat.id)
for dialog in dialogs:
+ await sleep(0)
yield dialog
current += 1
if current >= total:
From 1414e4ceb19587ad3dad07cfd52923d2813bef3b Mon Sep 17 00:00:00 2001
From: Shrimadhav U K
Date: Wed, 20 Aug 2025 09:17:21 +0530
Subject: [PATCH 4/5] Update get_dialogs.py
---
pyrogram/methods/chats/get_dialogs.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/pyrogram/methods/chats/get_dialogs.py b/pyrogram/methods/chats/get_dialogs.py
index 40e1e173b9..f06913a4c9 100644
--- a/pyrogram/methods/chats/get_dialogs.py
+++ b/pyrogram/methods/chats/get_dialogs.py
@@ -19,6 +19,7 @@
from asyncio import sleep
from typing import AsyncGenerator, Optional
+import pyrogram
from pyrogram import raw, types, utils
From d54c5bd5a89028b662ecd2201eadfcab8986c496 Mon Sep 17 00:00:00 2001
From: Shrimadhav U K
Date: Wed, 20 Aug 2025 09:18:05 +0530
Subject: [PATCH 5/5] Update get_dialogs.py
---
pyrogram/methods/chats/get_dialogs.py | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/pyrogram/methods/chats/get_dialogs.py b/pyrogram/methods/chats/get_dialogs.py
index f06913a4c9..3318dd2535 100644
--- a/pyrogram/methods/chats/get_dialogs.py
+++ b/pyrogram/methods/chats/get_dialogs.py
@@ -90,7 +90,13 @@ async def get_dialogs(
continue
chat_id = utils.get_peer_id(message.peer_id)
- messages[chat_id] = await types.Message._parse(self, message, users, chats, replies=self.fetch_replies)
+ messages[chat_id] = await types.Message._parse(
+ self,
+ message,
+ users,
+ chats,
+ replies=self.fetch_replies
+ )
dialogs = []