fix: properly handle peers without access hash

This commit is contained in:
teidesu 2022-10-30 20:25:49 +03:00
parent 89fd8e8ef0
commit 7d10e65ecc
2 changed files with 84 additions and 30 deletions

View file

@ -7,7 +7,7 @@ import {
} from '@mtcute/core' } from '@mtcute/core'
import { TelegramClient } from '../../client' import { TelegramClient } from '../../client'
import { InputPeerLike, MtNotFoundError } from '../../types' import { InputPeerLike, MtNotFoundError, MtTypeAssertionError } from "../../types";
import { normalizeToInputPeer } from '../../utils/peer-utils' import { normalizeToInputPeer } from '../../utils/peer-utils'
import { assertTypeIs } from '../../utils/type-assertion' import { assertTypeIs } from '../../utils/type-assertion'
@ -83,35 +83,58 @@ export async function resolvePeer(
const id = res.peer.userId const id = res.peer.userId
const found = res.users.find((it) => it.id === id) const found = res.users.find((it) => it.id === id)
if (found && found._ === 'user') if (found && found._ === 'user') {
if (!found.accessHash) {
// no access hash, we can't use it
// this may happen when bot resolves a username
// of a user who hasn't started a conversation with it
throw new MtNotFoundError(
`Peer (user) with username ${peerId} was found, but it has no access hash`
)
}
return { return {
_: 'inputPeerUser', _: 'inputPeerUser',
userId: found.id, userId: found.id,
accessHash: found.accessHash!, accessHash: found.accessHash,
} }
} else { }
const id = } else if (res.peer._ === 'peerChannel') {
res.peer._ === 'peerChannel' const id = res.peer.channelId
? res.peer.channelId
: res.peer.chatId
const found = res.chats.find((it) => it.id === id) const found = res.chats.find((it) => it.id === id)
if (found)
switch (found._) { if (found) {
case 'channel': if (!(found._ === 'channel' || found._ === 'channelForbidden')) {
case 'channelForbidden': // chats can't have usernames
return { // furthermore, our id is a channel id, so it must be a channel
_: 'inputPeerChannel', // this should never happen, unless Telegram goes crazy
channelId: found.id, throw new MtTypeAssertionError(
accessHash: found.accessHash!, 'contacts.resolveUsername#chats',
} 'channel',
case 'chat': found._
case 'chatForbidden': )
return {
_: 'inputPeerChat',
chatId: found.id,
}
} }
if (!found.accessHash) {
// shouldn't happen? but just in case
throw new MtNotFoundError(
`Peer (channel) with username ${peerId} was found, but it has no access hash`
)
}
return {
_: 'inputPeerChannel',
channelId: found.id,
accessHash: found.accessHash,
}
}
} else {
// chats can't have usernames
throw new MtTypeAssertionError(
'contacts.resolveUsername',
'user or channel',
res.peer._
)
} }
throw new MtNotFoundError( throw new MtNotFoundError(
@ -137,12 +160,20 @@ export async function resolvePeer(
}) })
const found = res.find((it) => it.id === peerId) const found = res.find((it) => it.id === peerId)
if (found && found._ === 'user') if (found && found._ === 'user') {
if (!found.accessHash) {
// shouldn't happen? but just in case
throw new MtNotFoundError(
`Peer (user) with username ${peerId} was found, but it has no access hash`
)
}
return { return {
_: 'inputPeerUser', _: 'inputPeerUser',
userId: found.id, userId: found.id,
accessHash: found.accessHash!, accessHash: found.accessHash,
} }
}
break break
} }
@ -185,12 +216,20 @@ export async function resolvePeer(
if ( if (
found && found &&
(found._ === 'channel' || found._ === 'channelForbidden') (found._ === 'channel' || found._ === 'channelForbidden')
) ) {
if (!found.accessHash) {
// shouldn't happen? but just in case
throw new MtNotFoundError(
`Peer (channel) with username ${peerId} was found, but it has no access hash`
)
}
return { return {
_: 'inputPeerChannel', _: 'inputPeerChannel',
channelId: found.id, channelId: found.id,
accessHash: found.accessHash!, accessHash: found.accessHash ?? Long.ZERO,
} }
}
break break
} }

View file

@ -889,9 +889,17 @@ export class BaseTelegramClient extends EventEmitter {
switch (peer._) { switch (peer._) {
case 'user': case 'user':
if (!peer.accessHash) {
this.log.warn(
'received user without access hash: %j',
peer
)
continue
}
parsedPeers.push({ parsedPeers.push({
id: peer.id, id: peer.id,
accessHash: peer.accessHash!, accessHash: peer.accessHash,
username: peer.username?.toLowerCase(), username: peer.username?.toLowerCase(),
phone: peer.phone, phone: peer.phone,
type: 'user', type: 'user',
@ -909,9 +917,16 @@ export class BaseTelegramClient extends EventEmitter {
break break
case 'channel': case 'channel':
case 'channelForbidden': case 'channelForbidden':
if (!peer.accessHash) {
this.log.warn(
'received user without access hash: %j',
peer
)
continue
}
parsedPeers.push({ parsedPeers.push({
id: toggleChannelIdMark(peer.id), id: toggleChannelIdMark(peer.id),
accessHash: peer.accessHash!, accessHash: peer.accessHash,
username: username:
peer._ === 'channel' peer._ === 'channel'
? peer.username?.toLowerCase() ? peer.username?.toLowerCase()