mirror of
https://github.com/xCyanGrizzly/DragonsStash.git
synced 2026-05-10 22:01:16 +00:00
fix: use loadChats API and load chat folders for complete chat discovery
Some checks failed
continuous-integration/drone/push Build is failing
Some checks failed
continuous-integration/drone/push Build is failing
- Switch from getChats pagination to loadChats (the TDLib-recommended API) which properly loads all chats into TDLib's cache and signals completion with a 404 error - Discover and load chat folders via getChatFolders so chats in user-created folders are included - Load from main + archive + all folders in both worker startup and getAccountChats channel discovery - After loading, use getChats with high limit to retrieve all cached IDs - This ensures private chats, 1-on-1 conversations, Saved Messages, basic groups, and archived/folder chats are all discoverable Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -34,31 +34,64 @@ export async function getAccountChats(
|
|||||||
log.warn("Failed to get current user via getMe");
|
log.warn("Failed to get current user via getMe");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load ALL chats from both main and archive lists by paginating getChats.
|
// First, load all chats into TDLib's cache using loadChats (the proper API).
|
||||||
// TDLib's getChats returns batches — keep calling until it returns
|
// loadChats returns 404 when all chats have been loaded.
|
||||||
// an empty list, which signals all chats have been loaded.
|
// Then use getChats to retrieve the IDs for enrichment.
|
||||||
|
// Load from main, archive, AND chat folders to cover all chat types.
|
||||||
|
const folderLists: { _: "chatListFolder"; chat_folder_id: number }[] = [];
|
||||||
|
try {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
const folders = (await client.invoke({ _: "getChatFolders" })) as any;
|
||||||
|
if (folders?.chat_folders) {
|
||||||
|
for (const f of folders.chat_folders) {
|
||||||
|
folderLists.push({ _: "chatListFolder", chat_folder_id: f.id });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// getChatFolders may not be available in older TDLib versions
|
||||||
|
}
|
||||||
|
|
||||||
|
const chatLists: Record<string, unknown>[] = [
|
||||||
|
{ _: "chatListMain" },
|
||||||
|
{ _: "chatListArchive" },
|
||||||
|
...folderLists,
|
||||||
|
];
|
||||||
|
|
||||||
|
// Phase 1: Load all chats into TDLib's cache
|
||||||
|
for (const chatList of chatLists) {
|
||||||
|
try {
|
||||||
|
for (let page = 0; page < 500; page++) {
|
||||||
|
await withFloodWait(
|
||||||
|
() => client.invoke({ _: "loadChats", chat_list: chatList, limit: 100 }),
|
||||||
|
"loadChats"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// 404 = all chats loaded (expected), or unsupported list type
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Phase 2: Retrieve chat IDs and enrich with details
|
||||||
const seenChatIds = new Set<number>();
|
const seenChatIds = new Set<number>();
|
||||||
|
|
||||||
for (const chatList of [
|
for (const chatList of chatLists) {
|
||||||
{ _: "chatListMain" as const },
|
|
||||||
{ _: "chatListArchive" as const },
|
|
||||||
]) {
|
|
||||||
const MAX_PAGES = 500; // support up to 50,000 chats per list
|
|
||||||
for (let page = 0; page < MAX_PAGES; page++) {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
const result = (await withFloodWait(
|
let result: { chat_ids: number[] };
|
||||||
|
try {
|
||||||
|
result = (await withFloodWait(
|
||||||
() => client.invoke({
|
() => client.invoke({
|
||||||
_: "getChats",
|
_: "getChats",
|
||||||
chat_list: chatList,
|
chat_list: chatList,
|
||||||
limit: 100,
|
limit: 50000,
|
||||||
}),
|
}),
|
||||||
"getChats"
|
"getChats"
|
||||||
)) as { chat_ids: number[] };
|
)) as { chat_ids: number[] };
|
||||||
|
} catch {
|
||||||
if (!result.chat_ids || result.chat_ids.length === 0) {
|
continue;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!result.chat_ids || result.chat_ids.length === 0) continue;
|
||||||
|
|
||||||
for (const chatId of result.chat_ids) {
|
for (const chatId of result.chat_ids) {
|
||||||
if (seenChatIds.has(chatId)) continue;
|
if (seenChatIds.has(chatId)) continue;
|
||||||
seenChatIds.add(chatId);
|
seenChatIds.add(chatId);
|
||||||
@@ -79,7 +112,6 @@ export async function getAccountChats(
|
|||||||
let title = chat.title ?? `Chat ${chatId}`;
|
let title = chat.title ?? `Chat ${chatId}`;
|
||||||
|
|
||||||
if (chatType === "chatTypeSupergroup") {
|
if (chatType === "chatTypeSupergroup") {
|
||||||
// Get supergroup details to check if it's a channel or group
|
|
||||||
try {
|
try {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
const sg = (await withFloodWait(
|
const sg = (await withFloodWait(
|
||||||
@@ -99,7 +131,6 @@ export async function getAccountChats(
|
|||||||
type = "group";
|
type = "group";
|
||||||
} else if (chatType === "chatTypePrivate" || chatType === "chatTypeSecret") {
|
} else if (chatType === "chatTypePrivate" || chatType === "chatTypeSecret") {
|
||||||
type = "private";
|
type = "private";
|
||||||
// Label the self-chat as "Saved Messages"
|
|
||||||
if (selfUserId !== null && chat.type?.user_id === selfUserId) {
|
if (selfUserId !== null && chat.type?.user_id === selfUserId) {
|
||||||
title = "Saved Messages";
|
title = "Saved Messages";
|
||||||
}
|
}
|
||||||
@@ -115,14 +146,11 @@ export async function getAccountChats(
|
|||||||
log.warn({ chatId, err }, "Failed to get chat details, skipping");
|
log.warn({ chatId, err }, "Failed to get chat details, skipping");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await sleep(config.apiDelayMs);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
log.info(
|
log.info(
|
||||||
{ total: chats.length },
|
{ total: chats.length },
|
||||||
"Fetched all chats from Telegram (main + archive)"
|
"Fetched all chats from Telegram (main + archive + folders)"
|
||||||
);
|
);
|
||||||
|
|
||||||
return chats;
|
return chats;
|
||||||
|
|||||||
@@ -335,25 +335,45 @@ export async function runWorkerForAccount(
|
|||||||
phone: account.phone,
|
phone: account.phone,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Load the full chat list so TDLib knows about all chats.
|
// Load all chats into TDLib's local cache using loadChats (the recommended API).
|
||||||
// Without this, getChat/searchChatMessages fail with "Chat not found".
|
// Without this, getChat/searchChatMessages fail with "Chat not found".
|
||||||
// TDLib returns chats in batches — keep calling until empty.
|
// loadChats returns a 404 when all chats have been loaded — that's the stop signal.
|
||||||
// Load from both main and archive lists to cover older/archived chats.
|
// Load from main, archive, AND chat folders to cover all chat types.
|
||||||
for (const chatList of [
|
{
|
||||||
{ _: "chatListMain" as const },
|
// Discover chat folders first
|
||||||
{ _: "chatListArchive" as const },
|
const folderLists: { _: "chatListFolder"; chat_folder_id: number }[] = [];
|
||||||
]) {
|
|
||||||
try {
|
try {
|
||||||
for (let page = 0; page < 500; page++) {
|
const folders = await client.invoke({ _: "getChatFolders" }) as {
|
||||||
const chatResult = await client.invoke({
|
chat_folders?: { id: number }[];
|
||||||
_: "getChats",
|
};
|
||||||
chat_list: chatList,
|
if (folders.chat_folders) {
|
||||||
limit: 100,
|
for (const f of folders.chat_folders) {
|
||||||
}) as { chat_ids?: number[] };
|
folderLists.push({ _: "chatListFolder", chat_folder_id: f.id });
|
||||||
if (!chatResult.chat_ids || chatResult.chat_ids.length === 0) break;
|
}
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
// Ignore — chat list may already be loaded
|
// getChatFolders may not be available in older TDLib versions
|
||||||
|
}
|
||||||
|
|
||||||
|
const chatLists: Record<string, unknown>[] = [
|
||||||
|
{ _: "chatListMain" },
|
||||||
|
{ _: "chatListArchive" },
|
||||||
|
...folderLists,
|
||||||
|
];
|
||||||
|
|
||||||
|
for (const chatList of chatLists) {
|
||||||
|
try {
|
||||||
|
for (let page = 0; page < 500; page++) {
|
||||||
|
await client.invoke({
|
||||||
|
_: "loadChats",
|
||||||
|
chat_list: chatList,
|
||||||
|
limit: 100,
|
||||||
|
});
|
||||||
|
// loadChats returns ok — keep going until 404
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// 404 = all chats loaded (expected), or unsupported list type
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user