feat(client): resolvePeerMany method

This commit is contained in:
teidesu 2021-05-11 22:43:11 +03:00
parent 46973c4830
commit 8b3caeb3d0
8 changed files with 147 additions and 30 deletions

View file

@ -14,6 +14,7 @@
"dependencies": {
"@mtcute/tl": "^0.0.0",
"@mtcute/core": "^0.0.0",
"@mtcute/file-id": "^0.0.0"
"@mtcute/file-id": "^0.0.0",
"eager-async-pool": "^1.0.0"
}
}

View file

@ -129,6 +129,7 @@ import { getMe } from './methods/users/get-me'
import { getProfilePhotos } from './methods/users/get-profile-photos'
import { getUsers } from './methods/users/get-users'
import { iterProfilePhotos } from './methods/users/iter-profile-photos'
import { resolvePeerMany } from './methods/users/resolve-peer-many'
import { resolvePeer } from './methods/users/resolve-peer'
import { setOffline } from './methods/users/set-offline'
import { setProfilePhoto } from './methods/users/set-profile-photo'
@ -2646,6 +2647,34 @@ export interface TelegramClient extends BaseTelegramClient {
maxId?: tl.Long
}
): AsyncIterableIterator<Photo>
/**
* Get multiple `InputPeer`s at once,
* while also normalizing and removing
* peers that can't be normalized to that type.
* Uses `async-eager-pool` internally, with a
* limit of 10.
*
* @param peerIds Peer Ids
* @param normalizer Normalization function
*/
resolvePeerMany<
T extends tl.TypeInputPeer | tl.TypeInputUser | tl.TypeInputChannel
>(
peerIds: InputPeerLike[],
normalizer: (
obj: tl.TypeInputPeer | tl.TypeInputUser | tl.TypeInputChannel
) => T | null
): Promise<T[]>
/**
* Get multiple `InputPeer`s at once.
* Uses `async-eager-pool` internally, with a
* limit of 10.
*
* @param peerIds Peer Ids
*/
resolvePeerMany(
peerIds: InputPeerLike[]
): Promise<(tl.TypeInputPeer | tl.TypeInputUser | tl.TypeInputChannel)[]>
/**
* Get the `InputPeer` of a known peer id.
* Useful when an `InputPeer` is needed.
@ -2867,6 +2896,7 @@ export class TelegramClient extends BaseTelegramClient {
getProfilePhotos = getProfilePhotos
getUsers = getUsers
iterProfilePhotos = iterProfilePhotos
resolvePeerMany = resolvePeerMany
resolvePeer = resolvePeer
setOffline = setOffline
setProfilePhoto = setProfilePhoto

View file

@ -46,11 +46,10 @@ export async function addChatMembers(
const updates = await this.call({
_: 'channels.inviteToChannel',
channel: normalizeToInputChannel(chat)!,
users: await Promise.all(
(users as InputPeerLike[]).map((u) =>
this.resolvePeer(u).then(normalizeToInputUser)
)
).then((res) => res.filter(Boolean)) as tl.TypeInputUser[],
users: await this.resolvePeerMany(
users as InputPeerLike[],
normalizeToInputUser
),
fwdLimit: forwardCount,
})
this._handleUpdate(updates)

View file

@ -23,10 +23,10 @@ export async function createGroup(
): Promise<Chat> {
if (!Array.isArray(users)) users = [users]
const peers = (await Promise.all(
(users as InputPeerLike[])
.map(u => this.resolvePeer(u).then(normalizeToInputUser))
)).filter(Boolean) as tl.TypeInputUser[]
const peers = await this.resolvePeerMany(
users as InputPeerLike[],
normalizeToInputUser
)
const res = await this.call({
_: 'messages.createChat',

View file

@ -97,11 +97,10 @@ export async function* getChatEventLog(
const chunkSize = Math.min(params.chunkSize ?? 100, total)
const admins: tl.TypeInputUser[] | undefined = params.users
? ((await Promise.all(
params.users
.map((u) => this.resolvePeer(u).then(normalizeToInputUser))
.filter(Boolean)
)) as tl.TypeInputUser[])
? await this.resolvePeerMany(
params.users,
normalizeToInputUser
)
: undefined
let serverFilter:

View file

@ -40,13 +40,10 @@ export async function deleteContacts(
const single = !Array.isArray(userIds)
if (single) userIds = [userIds as InputPeerLike]
const inputPeers = ((
await Promise.all(
(userIds as InputPeerLike[]).map((it) =>
this.resolvePeer(it).then(normalizeToInputUser)
)
)
).filter(Boolean) as unknown) as tl.TypeInputUser[]
const inputPeers = await this.resolvePeerMany(
userIds as InputPeerLike[],
normalizeToInputUser
)
if (single && !inputPeers.length)
throw new MtCuteInvalidPeerTypeError(

View file

@ -17,7 +17,9 @@ export async function getUsers(
/**
* Get information about multiple users.
* You can retrieve up to 200 users at once
* You can retrieve up to 200 users at once.
*
* Note that order is not guaranteed.
*
* @param ids Users' identifiers. Can be ID, username, phone number, `"me"`, `"self"` or TL object
* @internal
@ -35,13 +37,10 @@ export async function getUsers(
const isArray = Array.isArray(ids)
if (!isArray) ids = [ids as InputPeerLike]
const inputPeers = ((
await Promise.all(
(ids as InputPeerLike[]).map((it) =>
this.resolvePeer(it).then(normalizeToInputUser)
)
)
).filter(Boolean) as unknown) as tl.TypeInputUser[]
const inputPeers = await this.resolvePeerMany(
ids as InputPeerLike[],
normalizeToInputUser
)
let res = await this.call({
_: 'users.getUsers',

View file

@ -0,0 +1,92 @@
import { tl } from '@mtcute/tl'
import { TelegramClient } from '../../client'
import { InputPeerLike } from '../../types'
import { asyncPool } from 'eager-async-pool'
/**
* Get multiple `InputPeer`s at once,
* while also normalizing and removing
* peers that can't be normalized to that type.
* Uses `async-eager-pool` internally, with a
* limit of 10.
*
* @param peerIds Peer Ids
* @param normalizer Normalization function
* @internal
*/
export async function resolvePeerMany<
T extends tl.TypeInputPeer | tl.TypeInputUser | tl.TypeInputChannel
>(
this: TelegramClient,
peerIds: InputPeerLike[],
normalizer: (
obj: tl.TypeInputPeer | tl.TypeInputUser | tl.TypeInputChannel
) => T | null
): Promise<T[]>
/**
* Get multiple `InputPeer`s at once.
* Uses `async-eager-pool` internally, with a
* limit of 10.
*
* @param peerIds Peer Ids
* @internal
*/
export async function resolvePeerMany(
this: TelegramClient,
peerIds: InputPeerLike[]
): Promise<(tl.TypeInputPeer | tl.TypeInputUser | tl.TypeInputChannel)[]>
/**
* @internal
*/
export async function resolvePeerMany(
this: TelegramClient,
peerIds: InputPeerLike[],
normalizer?: (
obj: tl.TypeInputPeer | tl.TypeInputUser | tl.TypeInputChannel
) => tl.TypeInputPeer | tl.TypeInputUser | tl.TypeInputChannel | null
): Promise<(tl.TypeInputPeer | tl.TypeInputUser | tl.TypeInputChannel)[]> {
const ret: (
| tl.TypeInputPeer
| tl.TypeInputUser
| tl.TypeInputChannel
)[] = []
if (peerIds.length < 10) {
// no point in using async pool for <10 peers
const res = await Promise.all(peerIds.map((it) => this.resolvePeer(it)))
if (!normalizer) return res
for (const value of res) {
const norm = normalizer(value)
if (norm) {
ret.push(norm)
}
}
} else {
for await (const { error, value } of asyncPool(
(it) => this.resolvePeer(it),
peerIds,
{
limit: 10,
}
)) {
if (error) {
throw error
}
if (!value) continue
if (!normalizer) {
ret.push(value)
} else {
const norm = normalizer(value)
if (norm) {
ret.push(norm)
}
}
}
}
return ret
}