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": { "dependencies": {
"@mtcute/tl": "^0.0.0", "@mtcute/tl": "^0.0.0",
"@mtcute/core": "^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 { getProfilePhotos } from './methods/users/get-profile-photos'
import { getUsers } from './methods/users/get-users' import { getUsers } from './methods/users/get-users'
import { iterProfilePhotos } from './methods/users/iter-profile-photos' import { iterProfilePhotos } from './methods/users/iter-profile-photos'
import { resolvePeerMany } from './methods/users/resolve-peer-many'
import { resolvePeer } from './methods/users/resolve-peer' import { resolvePeer } from './methods/users/resolve-peer'
import { setOffline } from './methods/users/set-offline' import { setOffline } from './methods/users/set-offline'
import { setProfilePhoto } from './methods/users/set-profile-photo' import { setProfilePhoto } from './methods/users/set-profile-photo'
@ -2646,6 +2647,34 @@ export interface TelegramClient extends BaseTelegramClient {
maxId?: tl.Long maxId?: tl.Long
} }
): AsyncIterableIterator<Photo> ): 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. * Get the `InputPeer` of a known peer id.
* Useful when an `InputPeer` is needed. * Useful when an `InputPeer` is needed.
@ -2867,6 +2896,7 @@ export class TelegramClient extends BaseTelegramClient {
getProfilePhotos = getProfilePhotos getProfilePhotos = getProfilePhotos
getUsers = getUsers getUsers = getUsers
iterProfilePhotos = iterProfilePhotos iterProfilePhotos = iterProfilePhotos
resolvePeerMany = resolvePeerMany
resolvePeer = resolvePeer resolvePeer = resolvePeer
setOffline = setOffline setOffline = setOffline
setProfilePhoto = setProfilePhoto setProfilePhoto = setProfilePhoto

View file

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

View file

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

View file

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

View file

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

View file

@ -17,7 +17,9 @@ export async function getUsers(
/** /**
* Get information about multiple users. * 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 * @param ids Users' identifiers. Can be ID, username, phone number, `"me"`, `"self"` or TL object
* @internal * @internal
@ -35,13 +37,10 @@ export async function getUsers(
const isArray = Array.isArray(ids) const isArray = Array.isArray(ids)
if (!isArray) ids = [ids as InputPeerLike] if (!isArray) ids = [ids as InputPeerLike]
const inputPeers = (( const inputPeers = await this.resolvePeerMany(
await Promise.all( ids as InputPeerLike[],
(ids as InputPeerLike[]).map((it) => normalizeToInputUser
this.resolvePeer(it).then(normalizeToInputUser) )
)
)
).filter(Boolean) as unknown) as tl.TypeInputUser[]
let res = await this.call({ let res = await this.call({
_: 'users.getUsers', _: '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
}