feat(core): added findDialogs method

This commit is contained in:
alina 🌸 2024-05-30 19:15:34 +03:00
parent cc71f41a9a
commit f7e883fe2c
Signed by: teidesu
SSH key fingerprint: SHA256:uNeCpw6aTSU4aIObXLvHfLkDa82HWH9EiOj9AXOIRpI
3 changed files with 141 additions and 1 deletions

View file

@ -89,6 +89,7 @@ import { importContacts } from './methods/contacts/import-contacts.js'
import { createFolder } from './methods/dialogs/create-folder.js'
import { deleteFolder } from './methods/dialogs/delete-folder.js'
import { editFolder } from './methods/dialogs/edit-folder.js'
import { findDialogs } from './methods/dialogs/find-dialogs.js'
import { findFolder } from './methods/dialogs/find-folder.js'
import { getFolders } from './methods/dialogs/get-folders.js'
import { getPeerDialogs } from './methods/dialogs/get-peer-dialogs.js'
@ -1039,6 +1040,18 @@ export interface TelegramClient extends ITelegramClient {
*/
timeout?: number
/**
* Whether to "fire and forget" this request,
* in which case the promise will resolve as soon
* as the request is sent with an empty response.
*
* Useful for interacting with bots that don't correctly
* answer to callback queries and the request always times out.
*
* **Note**: any errors will be silently ignored.
*/
fireAndForget?: boolean
/**
* Whether this is a "play game" button
*/
@ -2156,6 +2169,18 @@ export interface TelegramClient extends ITelegramClient {
/** Modification to be applied to this folder */
modification: Partial<Omit<tl.RawDialogFilter, 'id' | '_'>>
}): Promise<tl.RawDialogFilter>
/**
* Try to find a dialog (dialogs) with a given peer (peers) by their ID, username or phone number.
*
* This might be an expensive call, as it will potentially iterate over all
* dialogs to find the one with the given peer
*
* **Available**: 👤 users only
*
* @throws {MtPeerNotFoundError} If a dialog with any of the given peers was not found
*/
findDialogs(peers: MaybeArray<string | number>): Promise<Dialog[]>
/**
* Find a folder by its parameter.
*
@ -5242,6 +5267,8 @@ export interface TelegramClient extends ITelegramClient {
* while also normalizing and removing
* peers that can't be normalized to that type.
*
* If a peer was not found, it will be skipped.
*
* Uses async pool internally, with a concurrent limit of 8
*
* @param peerIds Peer Ids
@ -5254,11 +5281,13 @@ export interface TelegramClient extends ITelegramClient {
/**
* Get multiple `InputPeer`s at once.
*
* If a peer was not found, `null` will be returned instead
*
* Uses async pool internally, with a concurrent limit of 8
*
* @param peerIds Peer Ids
*/
resolvePeerMany(peerIds: InputPeerLike[]): Promise<tl.TypeInputPeer[]>
resolvePeerMany(peerIds: InputPeerLike[]): Promise<(tl.TypeInputPeer | null)[]>
/**
* Get the `InputPeer` of a known peer id.
@ -5692,6 +5721,9 @@ TelegramClient.prototype.deleteFolder = function (...args) {
TelegramClient.prototype.editFolder = function (...args) {
return editFolder(this._client, ...args)
}
TelegramClient.prototype.findDialogs = function (...args) {
return findDialogs(this._client, ...args)
}
TelegramClient.prototype.findFolder = function (...args) {
return findFolder(this._client, ...args)
}

View file

@ -81,6 +81,7 @@ export { importContacts } from './methods/contacts/import-contacts.js'
export { createFolder } from './methods/dialogs/create-folder.js'
export { deleteFolder } from './methods/dialogs/delete-folder.js'
export { editFolder } from './methods/dialogs/edit-folder.js'
export { findDialogs } from './methods/dialogs/find-dialogs.js'
export { findFolder } from './methods/dialogs/find-folder.js'
export { getFolders } from './methods/dialogs/get-folders.js'
export { getPeerDialogs } from './methods/dialogs/get-peer-dialogs.js'

View file

@ -0,0 +1,107 @@
import { tl } from '@mtcute/tl'
import { MaybeArray } from '../../../types/utils.js'
import { ITelegramClient } from '../../client.types.js'
import { MtPeerNotFoundError } from '../../types/errors.js'
import { Dialog } from '../../types/messages/dialog.js'
import { resolvePeerMany } from '../users/resolve-peer-many.js'
import { getPeerDialogs } from './get-peer-dialogs.js'
import { iterDialogs } from './iter-dialogs.js'
// @available=user
/**
* Try to find a dialog (dialogs) with a given peer (peers) by their ID, username or phone number.
*
* This might be an expensive call, as it will potentially iterate over all
* dialogs to find the one with the given peer
*
* @throws {MtPeerNotFoundError} If a dialog with any of the given peers was not found
*/
export async function findDialogs(client: ITelegramClient, peers: MaybeArray<string | number>): Promise<Dialog[]> {
if (!Array.isArray(peers)) peers = [peers]
const resolved = await resolvePeerMany(client, peers)
// now we need to split `peers` into two parts: ids that we could resolve and those we couldn't
// those that we couldn't we'll iterate over all dialogs and try to find them by username/id
// those that we could we'll use getPeerDialogs
// id -> idx
const notFoundIds = new Map<number, number>()
// username -> idx
const notFoundUsernames = new Map<string, number>()
let notFoundCount = 0
const foundInputPeers: tl.TypeInputPeer[] = []
const foundIdxToOriginalIdx = new Map<number, number>()
for (let i = 0; i < peers.length; i++) {
const input = peers[i]
const resolvedPeer = resolved[i]
if (!resolvedPeer) {
if (typeof input === 'number') {
notFoundIds.set(input, i)
} else {
notFoundUsernames.set(input, i)
}
notFoundCount += 1
continue
}
foundInputPeers.push(resolvedPeer)
foundIdxToOriginalIdx.set(foundInputPeers.length - 1, i)
}
const dialogs = await getPeerDialogs(client, foundInputPeers)
if (foundInputPeers.length === peers.length) {
return dialogs
}
const ret = new Array<Dialog>(peers.length)
// populate found dialogs
for (const [idx, origIdx] of foundIdxToOriginalIdx) {
ret[origIdx] = dialogs[idx]
}
// now we need to iterate over all dialogs and try to find the rest
for await (const dialog of iterDialogs(client, {
archived: 'keep',
})) {
const chat = dialog.chat
const idxById = notFoundIds.get(chat.id)
if (idxById !== undefined) {
ret[idxById] = dialog
notFoundIds.delete(chat.id)
notFoundCount -= 1
}
if (notFoundCount === 0) break
if (!chat.username) continue
const idxByUsername = notFoundUsernames.get(chat.username)
if (idxByUsername !== undefined) {
ret[idxByUsername] = dialog
notFoundUsernames.delete(chat.username)
notFoundCount -= 1
}
if (notFoundCount === 0) break
}
// if we still have some dialogs that we couldn't find, fail
if (notFoundCount > 0) {
const notFound = [...notFoundIds.keys(), ...notFoundUsernames.keys()]
throw new MtPeerNotFoundError(`Could not find dialogs with peers: ${notFound.join(', ')}`)
}
return ret
}