feat(core): isPeerAvailable
method
This commit is contained in:
parent
baa8d287c6
commit
c92292249b
4 changed files with 128 additions and 23 deletions
|
@ -264,6 +264,7 @@ import { getMyUsername } from './methods/users/get-my-username.js'
|
||||||
import { getProfilePhoto } from './methods/users/get-profile-photo.js'
|
import { getProfilePhoto } from './methods/users/get-profile-photo.js'
|
||||||
import { getProfilePhotos } from './methods/users/get-profile-photos.js'
|
import { getProfilePhotos } from './methods/users/get-profile-photos.js'
|
||||||
import { getUsers } from './methods/users/get-users.js'
|
import { getUsers } from './methods/users/get-users.js'
|
||||||
|
import { isPeerAvailable } from './methods/users/is-peer-available.js'
|
||||||
import { iterProfilePhotos } from './methods/users/iter-profile-photos.js'
|
import { iterProfilePhotos } from './methods/users/iter-profile-photos.js'
|
||||||
import { resolvePeerMany } from './methods/users/resolve-peer-many.js'
|
import { resolvePeerMany } from './methods/users/resolve-peer-many.js'
|
||||||
import { resolveChannel, resolvePeer, resolveUser } from './methods/users/resolve-peer.js'
|
import { resolveChannel, resolvePeer, resolveUser } from './methods/users/resolve-peer.js'
|
||||||
|
@ -5536,6 +5537,27 @@ export interface TelegramClient extends ITelegramClient {
|
||||||
* @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
|
||||||
*/
|
*/
|
||||||
getUsers(ids: MaybeArray<InputPeerLike>): Promise<(User | null)[]>
|
getUsers(ids: MaybeArray<InputPeerLike>): Promise<(User | null)[]>
|
||||||
|
/**
|
||||||
|
* Check whether a given peer ID can be used to actually
|
||||||
|
* interact with the Telegram API.
|
||||||
|
* This method checks the internal peers cache for the given
|
||||||
|
* input peer, and returns `true` if it is available there.
|
||||||
|
*
|
||||||
|
* You can think of this method as a stripped down version of
|
||||||
|
* {@link resolvePeer}, which only returns `true` or `false`.
|
||||||
|
*
|
||||||
|
* > **Note:** This method works offline and never sends any requests.
|
||||||
|
* > This means that when passing a username or phone number, it will
|
||||||
|
* > only return `true` if the user with that username/phone number
|
||||||
|
* > is cached in the storage, and will not try to resolve the peer by calling the API,
|
||||||
|
* > which *may* lead to false negatives.
|
||||||
|
*
|
||||||
|
* **Available**: ✅ both users and bots
|
||||||
|
*
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
isPeerAvailable(
|
||||||
|
peerId: InputPeerLike): Promise<boolean>
|
||||||
/**
|
/**
|
||||||
* Iterate over profile photos
|
* Iterate over profile photos
|
||||||
*
|
*
|
||||||
|
@ -6529,6 +6551,9 @@ TelegramClient.prototype.getProfilePhotos = function (...args) {
|
||||||
TelegramClient.prototype.getUsers = function (...args) {
|
TelegramClient.prototype.getUsers = function (...args) {
|
||||||
return getUsers(this._client, ...args)
|
return getUsers(this._client, ...args)
|
||||||
}
|
}
|
||||||
|
TelegramClient.prototype.isPeerAvailable = function (...args) {
|
||||||
|
return isPeerAvailable(this._client, ...args)
|
||||||
|
}
|
||||||
TelegramClient.prototype.iterProfilePhotos = function (...args) {
|
TelegramClient.prototype.iterProfilePhotos = function (...args) {
|
||||||
return iterProfilePhotos(this._client, ...args)
|
return iterProfilePhotos(this._client, ...args)
|
||||||
}
|
}
|
||||||
|
|
|
@ -263,6 +263,7 @@ export { getMyUsername } from './methods/users/get-my-username.js'
|
||||||
export { getProfilePhoto } from './methods/users/get-profile-photo.js'
|
export { getProfilePhoto } from './methods/users/get-profile-photo.js'
|
||||||
export { getProfilePhotos } from './methods/users/get-profile-photos.js'
|
export { getProfilePhotos } from './methods/users/get-profile-photos.js'
|
||||||
export { getUsers } from './methods/users/get-users.js'
|
export { getUsers } from './methods/users/get-users.js'
|
||||||
|
export { isPeerAvailable } from './methods/users/is-peer-available.js'
|
||||||
export { iterProfilePhotos } from './methods/users/iter-profile-photos.js'
|
export { iterProfilePhotos } from './methods/users/iter-profile-photos.js'
|
||||||
export { resolvePeerMany } from './methods/users/resolve-peer-many.js'
|
export { resolvePeerMany } from './methods/users/resolve-peer-many.js'
|
||||||
export { resolvePeer } from './methods/users/resolve-peer.js'
|
export { resolvePeer } from './methods/users/resolve-peer.js'
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
import { parseMarkedPeerId } from '../../../utils/peer-utils.js'
|
||||||
|
import type { ITelegramClient } from '../../client.types'
|
||||||
|
import type { InputPeerLike } from '../../types'
|
||||||
|
|
||||||
|
import { _normalizePeerId } from './resolve-peer.js'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether a given peer ID can be used to actually
|
||||||
|
* interact with the Telegram API.
|
||||||
|
* This method checks the internal peers cache for the given
|
||||||
|
* input peer, and returns `true` if it is available there.
|
||||||
|
*
|
||||||
|
* You can think of this method as a stripped down version of
|
||||||
|
* {@link resolvePeer}, which only returns `true` or `false`.
|
||||||
|
*
|
||||||
|
* > **Note:** This method works offline and never sends any requests.
|
||||||
|
* > This means that when passing a username or phone number, it will
|
||||||
|
* > only return `true` if the user with that username/phone number
|
||||||
|
* > is cached in the storage, and will not try to resolve the peer by calling the API,
|
||||||
|
* > which *may* lead to false negatives.
|
||||||
|
*
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export async function isPeerAvailable(
|
||||||
|
client: ITelegramClient,
|
||||||
|
peerId: InputPeerLike,
|
||||||
|
): Promise<boolean> {
|
||||||
|
peerId = _normalizePeerId(peerId)
|
||||||
|
|
||||||
|
if (typeof peerId === 'object') {
|
||||||
|
// InputPeer (actual one, not mtcute.*)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof peerId === 'number') {
|
||||||
|
const fromStorage = await client.storage.peers.getById(peerId)
|
||||||
|
if (fromStorage) return true
|
||||||
|
|
||||||
|
// in some cases, the server allows bots to use access_hash=0.
|
||||||
|
const [peerType] = parseMarkedPeerId(peerId)
|
||||||
|
|
||||||
|
if (peerType === 'chat' || client.storage.self.getCached(true)?.isBot) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof peerId === 'string') {
|
||||||
|
if (peerId === 'self' || peerId === 'me') {
|
||||||
|
// inputPeerSelf is always available
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
peerId = peerId.replace(/[@+\s()]/g, '')
|
||||||
|
|
||||||
|
if (peerId.match(/^\d+$/)) {
|
||||||
|
// phone number
|
||||||
|
const fromStorage = await client.storage.peers.getByPhone(peerId)
|
||||||
|
if (fromStorage) return true
|
||||||
|
} else {
|
||||||
|
// username
|
||||||
|
const fromStorage = await client.storage.peers.getByUsername(peerId)
|
||||||
|
if (fromStorage) return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
|
@ -8,6 +8,33 @@ import { MtPeerNotFoundError } from '../../types/errors.js'
|
||||||
import type { InputPeerLike } from '../../types/peers/index.js'
|
import type { InputPeerLike } from '../../types/peers/index.js'
|
||||||
import { toInputChannel, toInputPeer, toInputUser } from '../../utils/peer-utils.js'
|
import { toInputChannel, toInputPeer, toInputUser } from '../../utils/peer-utils.js'
|
||||||
|
|
||||||
|
export function _normalizePeerId(peerId: InputPeerLike): number | string | tl.TypeInputPeer {
|
||||||
|
// for convenience we also accept tl and User/Chat objects directly
|
||||||
|
if (typeof peerId === 'object') {
|
||||||
|
if (tl.isAnyPeer(peerId)) {
|
||||||
|
peerId = getMarkedPeerId(peerId)
|
||||||
|
} else if ('inputPeer' in peerId) {
|
||||||
|
// User | Chat
|
||||||
|
peerId = peerId.inputPeer
|
||||||
|
} else {
|
||||||
|
peerId = toInputPeer(peerId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof peerId === 'object') {
|
||||||
|
switch (peerId._) {
|
||||||
|
case 'mtcute.dummyInputPeerMinUser':
|
||||||
|
return peerId.userId
|
||||||
|
case 'mtcute.dummyInputPeerMinChannel':
|
||||||
|
return toggleChannelIdMark(peerId.channelId)
|
||||||
|
default:
|
||||||
|
return peerId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return peerId
|
||||||
|
}
|
||||||
|
|
||||||
// @available=both
|
// @available=both
|
||||||
/**
|
/**
|
||||||
* Get the `InputPeer` of a known peer id.
|
* Get the `InputPeer` of a known peer id.
|
||||||
|
@ -21,29 +48,10 @@ export async function resolvePeer(
|
||||||
peerId: InputPeerLike,
|
peerId: InputPeerLike,
|
||||||
force = false,
|
force = false,
|
||||||
): Promise<tl.TypeInputPeer> {
|
): Promise<tl.TypeInputPeer> {
|
||||||
// for convenience we also accept tl and User/Chat objects directly
|
peerId = _normalizePeerId(peerId)
|
||||||
if (typeof peerId === 'object') {
|
if (typeof peerId === 'object') {
|
||||||
if (tl.isAnyPeer(peerId)) {
|
// InputPeer (actual one, not mtcute.*)
|
||||||
peerId = getMarkedPeerId(peerId)
|
return peerId
|
||||||
} else if ('inputPeer' in peerId) {
|
|
||||||
// User | Chat
|
|
||||||
peerId = peerId.inputPeer
|
|
||||||
} else {
|
|
||||||
peerId = toInputPeer(peerId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof peerId === 'object') {
|
|
||||||
switch (peerId._) {
|
|
||||||
case 'mtcute.dummyInputPeerMinUser':
|
|
||||||
peerId = peerId.userId
|
|
||||||
break
|
|
||||||
case 'mtcute.dummyInputPeerMinChannel':
|
|
||||||
peerId = toggleChannelIdMark(peerId.channelId)
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
return peerId
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof peerId === 'number' && !force) {
|
if (typeof peerId === 'number' && !force) {
|
||||||
|
@ -152,7 +160,7 @@ export async function resolvePeer(
|
||||||
// if it's not the case, we'll get an `PEER_ID_INVALID` error anyways
|
// if it's not the case, we'll get an `PEER_ID_INVALID` error anyways
|
||||||
const [peerType, bareId] = parseMarkedPeerId(peerId)
|
const [peerType, bareId] = parseMarkedPeerId(peerId)
|
||||||
|
|
||||||
if (peerType !== 'chat' && !client.storage.self.getCached(true)?.isBot) {
|
if (!(peerType === 'chat' || client.storage.self.getCached(true)?.isBot)) {
|
||||||
throw new MtPeerNotFoundError(`Peer ${peerId} is not found in local cache`)
|
throw new MtPeerNotFoundError(`Peer ${peerId} is not found in local cache`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue