refactor(client)!: extracted inline callback query into a separate update

breaking: `CallbackQuery` -> `CallbackQuery` and `InlineCallbackQuery`
also removed some redundant fields
This commit is contained in:
alina 🌸 2023-12-14 00:34:51 +03:00
parent e259701837
commit 2728166727
Signed by: teidesu
SSH key fingerprint: SHA256:uNeCpw6aTSU4aIObXLvHfLkDa82HWH9EiOj9AXOIRpI
16 changed files with 190 additions and 145 deletions

View file

@ -7,6 +7,7 @@ chat_member: ChatMemberUpdate = ChatMemberUpdate
inline_query = InlineQuery in InlineQueryContext inline_query = InlineQuery in InlineQueryContext
chosen_inline_result = ChosenInlineResult in ChosenInlineResultContext chosen_inline_result = ChosenInlineResult in ChosenInlineResultContext
callback_query = CallbackQuery + State in CallbackQueryContext callback_query = CallbackQuery + State in CallbackQueryContext
inline_callback_query = InlineCallbackQuery + State in InlineCallbackQueryContext
poll: PollUpdate = PollUpdate poll: PollUpdate = PollUpdate
poll_vote = PollVoteUpdate poll_vote = PollVoteUpdate
user_status: UserStatusUpdate = UserStatusUpdate user_status: UserStatusUpdate = UserStatusUpdate

View file

@ -1,6 +1,6 @@
import { BaseTelegramClient, Long } from '@mtcute/core' import { BaseTelegramClient, Long } from '@mtcute/core'
import { CallbackQuery } from '../../types/bots/callback-query.js' import { CallbackQuery } from '../../types/updates/callback-query.js'
/** /**
* Send an answer to a callback query. * Send an answer to a callback query.

View file

@ -1,6 +1,7 @@
import { BaseTelegramClient, Long, tl } from '@mtcute/core' import { BaseTelegramClient, Long, tl } from '@mtcute/core'
import { BotInline, InlineQuery, InputInlineResult } from '../../types/bots/index.js' import { BotInline, InputInlineResult } from '../../types/bots/index.js'
import { InlineQuery } from '../../types/updates/inline-query.js'
/** /**
* Answer an inline query. * Answer an inline query.

View file

@ -1,9 +1,9 @@
import { BaseTelegramClient, tl } from '@mtcute/core' import { BaseTelegramClient, tl } from '@mtcute/core'
import { assertTypeIsNot } from '@mtcute/core/utils.js' import { assertTypeIsNot } from '@mtcute/core/utils.js'
import type { CallbackQuery } from '../../types/bots/callback-query.js'
import { Message } from '../../types/messages/message.js' import { Message } from '../../types/messages/message.js'
import { InputPeerLike, PeersIndex } from '../../types/peers/index.js' import { InputPeerLike, PeersIndex } from '../../types/peers/index.js'
import type { CallbackQuery } from '../../types/updates/callback-query.js'
import { isInputPeerChannel, toInputChannel } from '../../utils/peer-utils.js' import { isInputPeerChannel, toInputChannel } from '../../utils/peer-utils.js'
import { resolvePeer } from '../users/resolve-peer.js' import { resolvePeer } from '../users/resolve-peer.js'

View file

@ -1,7 +1,5 @@
export * from './callback-query.js'
export * from './command-scope.js' export * from './command-scope.js'
export * from './game-high-score.js' export * from './game-high-score.js'
export * from './inline-query.js'
export * from './input/index.js' export * from './input/index.js'
export * from './keyboard-builder.js' export * from './keyboard-builder.js'
export * from './keyboards.js' export * from './keyboards.js'

View file

@ -1,4 +1,4 @@
import { BasicPeerType, getBasicPeerType, getMarkedPeerId, MtArgumentError, tl } from '@mtcute/core' import { MtArgumentError, tl } from '@mtcute/core'
import { makeInspectable, utf8Decode } from '../../utils/index.js' import { makeInspectable, utf8Decode } from '../../utils/index.js'
import { encodeInlineMessageId } from '../../utils/inline-utils.js' import { encodeInlineMessageId } from '../../utils/inline-utils.js'
@ -7,11 +7,8 @@ import { Chat } from '../peers/chat.js'
import { PeersIndex } from '../peers/peers-index.js' import { PeersIndex } from '../peers/peers-index.js'
import { User } from '../peers/user.js' import { User } from '../peers/user.js'
/** /** Base class for callback queries */
* An incoming callback query, originated from a callback button class BaseCallbackQuery {
* of an inline keyboard.
*/
export class CallbackQuery {
constructor( constructor(
readonly raw: tl.RawUpdateBotCallbackQuery | tl.RawUpdateInlineBotCallbackQuery, readonly raw: tl.RawUpdateBotCallbackQuery | tl.RawUpdateInlineBotCallbackQuery,
readonly _peers: PeersIndex, readonly _peers: PeersIndex,
@ -39,96 +36,6 @@ export class CallbackQuery {
return this.raw.chatInstance return this.raw.chatInstance
} }
/**
* Whether this callback query originates from
* a button that was attached to a message sent
* *via* the bot (i.e. using inline mode).
*
* If `true`, `messageId` is available and `getMessage` can be used,
* otherwise `inlineMessageId` and `inlineMessageIdStr` are available
*/
get isInline(): boolean {
return this.raw._ === 'updateInlineBotCallbackQuery'
}
/**
* Identifier of the previously sent inline message,
* that contained the button which was clicked.
* This ID can be used in `TelegramClient.editInlineMessage`
*
* Is only available in case `isInline = true`
*/
get inlineMessageId(): tl.TypeInputBotInlineMessageID {
if (this.raw._ !== 'updateInlineBotCallbackQuery') {
throw new MtArgumentError('Cannot get inline message id for non-inline callback')
}
return this.raw.msgId
}
/**
* Identifier of the previously sent inline message,
* that contained the button which was clicked,
* as a TDLib and Bot API compatible string.
* Can be used instead of {@link inlineMessageId} in
* case you want to store it in some storage.
*
* Is only available in case `isInline = true`
*/
get inlineMessageIdStr(): string {
if (this.raw._ !== 'updateInlineBotCallbackQuery') {
throw new MtArgumentError('Cannot get inline message id for non-inline callback')
}
return encodeInlineMessageId(this.raw.msgId)
}
/**
* Identifier of the chat where this message was sent
*/
get chatId(): number {
if (this.raw._ !== 'updateBotCallbackQuery') {
throw new MtArgumentError('Cannot get message id for inline callback')
}
return getMarkedPeerId(this.raw.peer)
}
/**
* Chat where this message was sent
*
* Only available in case `isInline = false`
*/
get chat(): Chat {
if (this.raw._ !== 'updateBotCallbackQuery') {
throw new MtArgumentError('Cannot get message id for inline callback')
}
return new Chat(this._peers.get(this.raw.peer))
}
/**
* Basic peer type of the chat where this message was sent,
* derived based on {@link chatId}
*/
get chatType(): BasicPeerType {
return getBasicPeerType(this.chatId)
}
/**
* Identifier of the message sent by the bot
* that contained the button which was clicked.
*
* Is only available in case `isInline = false`
*/
get messageId(): number {
if (this.raw._ !== 'updateBotCallbackQuery') {
throw new MtArgumentError('Cannot get message id for inline callback')
}
return this.raw.msgId
}
/** /**
* Data that was contained in the callback button, if any * Data that was contained in the callback button, if any
* *
@ -162,5 +69,70 @@ export class CallbackQuery {
} }
} }
memoizeGetters(CallbackQuery, ['user', 'chat', 'dataStr', 'inlineMessageIdStr']) /**
* A callback query originating from a normal message sent by the bot.
*/
export class CallbackQuery extends BaseCallbackQuery {
constructor(
readonly raw: tl.RawUpdateBotCallbackQuery,
_peers: PeersIndex,
) {
super(raw, _peers)
}
/**
* Chat where the originating message was sent
*/
get chat(): Chat {
if (this.raw._ !== 'updateBotCallbackQuery') {
throw new MtArgumentError('Cannot get message id for inline callback')
}
return new Chat(this._peers.get(this.raw.peer))
}
/**
* Identifier of the message containing the button which was clicked.
*/
get messageId(): number {
return this.raw.msgId
}
}
memoizeGetters(CallbackQuery, ['user', 'dataStr', 'chat'])
makeInspectable(CallbackQuery) makeInspectable(CallbackQuery)
/**
* A callback query originating from an inline message sent by the bot.
*/
export class InlineCallbackQuery extends BaseCallbackQuery {
constructor(
readonly raw: tl.RawUpdateInlineBotCallbackQuery,
_peers: PeersIndex,
) {
super(raw, _peers)
}
/**
* Identifier of the previously sent inline message,
* that contained the button which was clicked.
* This ID can be used in `TelegramClient.editInlineMessage`
*/
get inlineMessageId(): tl.TypeInputBotInlineMessageID {
return this.raw.msgId
}
/**
* Identifier of the previously sent inline message,
* that contained the button which was clicked,
* as a TDLib and Bot API compatible string.
* Can be used instead of {@link inlineMessageId} in
* case you want to store it in some storage.
*/
get inlineMessageIdStr(): string {
return encodeInlineMessageId(this.raw.msgId)
}
}
memoizeGetters(InlineCallbackQuery, ['user', 'dataStr', 'inlineMessageIdStr'])
makeInspectable(InlineCallbackQuery)

View file

@ -1,8 +1,10 @@
import type { CallbackQuery, InlineQuery, Message } from '../../types/index.js' import type { Message } from '../../types/index.js'
import { BotChatJoinRequestUpdate } from './bot-chat-join-request.js' import { BotChatJoinRequestUpdate } from './bot-chat-join-request.js'
import { BotStoppedUpdate } from './bot-stopped.js' import { BotStoppedUpdate } from './bot-stopped.js'
import { CallbackQuery, InlineCallbackQuery } from './callback-query.js'
import { ChatJoinRequestUpdate } from './chat-join-request.js' import { ChatJoinRequestUpdate } from './chat-join-request.js'
import { ChatMemberUpdate } from './chat-member-update.js' import { ChatMemberUpdate } from './chat-member-update.js'
import { InlineQuery } from './inline-query.js'
export type { ChatMemberUpdateType } from './chat-member-update.js' export type { ChatMemberUpdateType } from './chat-member-update.js'
import { ChosenInlineResult } from './chosen-inline-result.js' import { ChosenInlineResult } from './chosen-inline-result.js'
import { DeleteMessageUpdate } from './delete-message-update.js' import { DeleteMessageUpdate } from './delete-message-update.js'
@ -18,12 +20,15 @@ import { UserTypingUpdate } from './user-typing-update.js'
export { export {
BotChatJoinRequestUpdate, BotChatJoinRequestUpdate,
BotStoppedUpdate, BotStoppedUpdate,
CallbackQuery,
ChatJoinRequestUpdate, ChatJoinRequestUpdate,
ChatMemberUpdate, ChatMemberUpdate,
ChosenInlineResult, ChosenInlineResult,
DeleteMessageUpdate, DeleteMessageUpdate,
DeleteStoryUpdate, DeleteStoryUpdate,
HistoryReadUpdate, HistoryReadUpdate,
InlineCallbackQuery,
InlineQuery,
PollUpdate, PollUpdate,
PollVoteUpdate, PollVoteUpdate,
PreCheckoutQuery, PreCheckoutQuery,
@ -42,6 +47,7 @@ export type ParsedUpdate =
| { name: 'inline_query'; data: InlineQuery } | { name: 'inline_query'; data: InlineQuery }
| { name: 'chosen_inline_result'; data: ChosenInlineResult } | { name: 'chosen_inline_result'; data: ChosenInlineResult }
| { name: 'callback_query'; data: CallbackQuery } | { name: 'callback_query'; data: CallbackQuery }
| { name: 'inline_callback_query'; data: InlineCallbackQuery }
| { name: 'poll'; data: PollUpdate } | { name: 'poll'; data: PollUpdate }
| { name: 'poll_vote'; data: PollVoteUpdate } | { name: 'poll_vote'; data: PollVoteUpdate }
| { name: 'user_status'; data: UserStatusUpdate } | { name: 'user_status'; data: UserStatusUpdate }

View file

@ -11,6 +11,7 @@ import {
DeleteMessageUpdate, DeleteMessageUpdate,
DeleteStoryUpdate, DeleteStoryUpdate,
HistoryReadUpdate, HistoryReadUpdate,
InlineCallbackQuery,
InlineQuery, InlineQuery,
Message, Message,
ParsedUpdate, ParsedUpdate,
@ -44,8 +45,9 @@ export function _parseUpdate(update: tl.TypeUpdate, peers: PeersIndex): ParsedUp
case 'updateBotInlineSend': case 'updateBotInlineSend':
return { name: 'chosen_inline_result', data: new ChosenInlineResult(update, peers) } return { name: 'chosen_inline_result', data: new ChosenInlineResult(update, peers) }
case 'updateBotCallbackQuery': case 'updateBotCallbackQuery':
case 'updateInlineBotCallbackQuery':
return { name: 'callback_query', data: new CallbackQuery(update, peers) } return { name: 'callback_query', data: new CallbackQuery(update, peers) }
case 'updateInlineBotCallbackQuery':
return { name: 'inline_callback_query', data: new InlineCallbackQuery(update, peers) }
case 'updateMessagePoll': case 'updateMessagePoll':
return { name: 'poll', data: new PollUpdate(update, peers) } return { name: 'poll', data: new PollUpdate(update, peers) }
case 'updateMessagePollVote': case 'updateMessagePollVote':

View file

@ -1,12 +1,4 @@
import { import { CallbackQuery, InlineCallbackQuery, MaybeAsync, Message, TelegramClient } from '@mtcute/client'
CallbackQuery,
getMarkedPeerId,
MaybeAsync,
Message,
MtArgumentError,
MtMessageNotFoundError,
TelegramClient,
} from '@mtcute/client'
import { UpdateContext } from './base.js' import { UpdateContext } from './base.js'
@ -34,33 +26,16 @@ export class CallbackQueryContext extends CallbackQuery implements UpdateContext
* Get the message containing the callback button being clicked. * Get the message containing the callback button being clicked.
* *
* Note that the message may have been deleted, in which case * Note that the message may have been deleted, in which case
* `MessageNotFoundError` is thrown. * `null` will be returned.
*/ */
async getMessage() { async getMessage(): Promise<Message | null> {
if (this.raw._ !== 'updateBotCallbackQuery') { return this.client.getCallbackQueryMessage(this)
throw new MtArgumentError('Cannot get message for inline callback query')
}
const msg = await this.client.getCallbackQueryMessage(this)
if (!msg) {
throw new MtMessageNotFoundError(getMarkedPeerId(this.raw.peer), this.raw.msgId, 'Message not found')
}
return msg
} }
/** /**
* Edit the message that contained the callback button that was clicked. * Edit the message that contained the callback button that was clicked.
*/ */
async editMessage(params: Omit<Parameters<TelegramClient['editInlineMessage']>[0], 'messageId'>) { async editMessage(params: Omit<Parameters<TelegramClient['editInlineMessage']>[0], 'messageId'>) {
if (this.raw._ === 'updateInlineBotCallbackQuery') {
return this.client.editInlineMessage({
messageId: this.raw.msgId,
...params,
})
}
return this.client.editMessage({ return this.client.editMessage({
chatId: this.raw.peer, chatId: this.raw.peer,
message: this.raw.msgId, message: this.raw.msgId,
@ -81,3 +56,34 @@ export class CallbackQueryContext extends CallbackQuery implements UpdateContext
return this.editMessage(res) return this.editMessage(res)
} }
} }
/**
* Context of an inline-originated callback query update.
*
* This is a subclass of {@link InlineCallbackQuery}, so all its fields are also available.
*/
export class InlineCallbackQueryContext extends InlineCallbackQuery implements UpdateContext<InlineCallbackQuery> {
readonly _name = 'inline_callback_query'
constructor(
readonly client: TelegramClient,
query: InlineCallbackQuery,
) {
super(query.raw, query._peers)
}
/** Answer to this callback query */
answer(params: Parameters<TelegramClient['answerCallbackQuery']>[1]) {
return this.client.answerCallbackQuery(this.id, params)
}
/**
* Edit the message that contained the callback button that was clicked.
*/
async editMessage(params: Omit<Parameters<TelegramClient['editInlineMessage']>[0], 'messageId'>) {
return this.client.editInlineMessage({
messageId: this.raw.msgId,
...params,
})
}
}

View file

@ -28,6 +28,7 @@ import {
CallbackQueryContext, CallbackQueryContext,
ChatJoinRequestUpdateContext, ChatJoinRequestUpdateContext,
ChosenInlineResultContext, ChosenInlineResultContext,
InlineCallbackQueryContext,
InlineQueryContext, InlineQueryContext,
MessageContext, MessageContext,
PreCheckoutQueryContext, PreCheckoutQueryContext,
@ -46,6 +47,7 @@ import {
DeleteStoryHandler, DeleteStoryHandler,
EditMessageHandler, EditMessageHandler,
HistoryReadHandler, HistoryReadHandler,
InlineCallbackQueryHandler,
InlineQueryHandler, InlineQueryHandler,
MessageGroupHandler, MessageGroupHandler,
NewMessageHandler, NewMessageHandler,
@ -1359,6 +1361,57 @@ export class Dispatcher<State extends object = never> {
this._addKnownHandler('callback_query', filter, handler, group) this._addKnownHandler('callback_query', filter, handler, group)
} }
/**
* Register an inline callback query handler without any filters
*
* @param handler Inline callback query handler
* @param group Handler group index
*/
onInlineCallbackQuery(
handler: InlineCallbackQueryHandler<
InlineCallbackQueryContext,
State extends never ? never : UpdateState<State>
>['callback'],
group?: number,
): void
/**
* Register an inline callback query handler with a filter
*
* @param filter Update filter
* @param handler Inline callback query handler
* @param group Handler group index
*/
onInlineCallbackQuery<Mod>(
filter: UpdateFilter<InlineCallbackQueryContext, Mod, State>,
handler: InlineCallbackQueryHandler<
filters.Modify<InlineCallbackQueryContext, Mod>,
State extends never ? never : UpdateState<State>
>['callback'],
group?: number,
): void
/**
* Register an inline callback query handler with a filter
*
* @param filter Update filter
* @param handler Inline callback query handler
* @param group Handler group index
*/
onInlineCallbackQuery<Mod>(
filter: UpdateFilter<InlineCallbackQueryContext, Mod>,
handler: InlineCallbackQueryHandler<
filters.Modify<InlineCallbackQueryContext, Mod>,
State extends never ? never : UpdateState<State>
>['callback'],
group?: number,
): void
/** @internal */
onInlineCallbackQuery(filter: any, handler?: any, group?: number): void {
this._addKnownHandler('inline_callback_query', filter, handler, group)
}
/** /**
* Register a poll update handler without any filters * Register a poll update handler without any filters
* *

View file

@ -1,9 +1,11 @@
import { CallbackQuery, ChosenInlineResult, InlineQuery, Message } from '@mtcute/client' import { CallbackQuery, ChosenInlineResult, InlineCallbackQuery, InlineQuery, Message } from '@mtcute/client'
import { UpdateContextDistributed } from '../context/base.js' import { UpdateContextDistributed } from '../context/base.js'
import { UpdateFilter } from './types.js' import { UpdateFilter } from './types.js'
type UpdatesWithText = UpdateContextDistributed<Message | InlineQuery | ChosenInlineResult | CallbackQuery> type UpdatesWithText = UpdateContextDistributed<
Message | InlineQuery | ChosenInlineResult | CallbackQuery | InlineCallbackQuery
>
function extractText(obj: UpdatesWithText): string | null { function extractText(obj: UpdatesWithText): string | null {
switch (obj._name) { switch (obj._name) {
@ -14,6 +16,7 @@ function extractText(obj: UpdatesWithText): string | null {
case 'chosen_inline_result': case 'chosen_inline_result':
return obj.id return obj.id
case 'callback_query': case 'callback_query':
case 'inline_callback_query':
if (obj.raw.data) return obj.dataStr if (obj.raw.data) return obj.dataStr
} }

View file

@ -1,4 +1,4 @@
import { CallbackQuery, ChatMemberUpdate, ChatMemberUpdateType, MaybeArray, UserStatus, UserStatusUpdate } from '@mtcute/client' import { ChatMemberUpdate, ChatMemberUpdateType, MaybeArray, UserStatus, UserStatusUpdate } from '@mtcute/client'
import { UpdateFilter } from './types.js' import { UpdateFilter } from './types.js'
@ -56,9 +56,3 @@ export const userStatus: {
* regarding current user * regarding current user
*/ */
export const chatMemberSelf: UpdateFilter<ChatMemberUpdate, { isSelf: true }> = (upd) => upd.isSelf export const chatMemberSelf: UpdateFilter<ChatMemberUpdate, { isSelf: true }> = (upd) => upd.isSelf
/**
* Create a filter for callback queries that
* originated from an inline message
*/
export const callbackInline: UpdateFilter<CallbackQuery, { isInline: true }> = (q) => q.isInline

View file

@ -5,6 +5,7 @@ import {
ChosenInlineResult, ChosenInlineResult,
DeleteStoryUpdate, DeleteStoryUpdate,
HistoryReadUpdate, HistoryReadUpdate,
InlineCallbackQuery,
InlineQuery, InlineQuery,
MaybeArray, MaybeArray,
Message, Message,
@ -44,6 +45,7 @@ export const userId: {
| ChatMemberUpdate | ChatMemberUpdate
| ChosenInlineResult | ChosenInlineResult
| CallbackQuery | CallbackQuery
| InlineCallbackQuery
| PollVoteUpdate | PollVoteUpdate
| BotChatJoinRequestUpdate | BotChatJoinRequestUpdate
>> >>
@ -58,6 +60,7 @@ export const userId: {
| ChatMemberUpdate | ChatMemberUpdate
| ChosenInlineResult | ChosenInlineResult
| CallbackQuery | CallbackQuery
| InlineCallbackQuery
| PollVoteUpdate | PollVoteUpdate
| BotChatJoinRequestUpdate | BotChatJoinRequestUpdate
>> >>

View file

@ -21,6 +21,7 @@ import {
CallbackQueryContext, CallbackQueryContext,
ChatJoinRequestUpdateContext, ChatJoinRequestUpdateContext,
ChosenInlineResultContext, ChosenInlineResultContext,
InlineCallbackQueryContext,
InlineQueryContext, InlineQueryContext,
MessageContext, MessageContext,
PreCheckoutQueryContext, PreCheckoutQueryContext,
@ -59,6 +60,11 @@ export type ChatMemberUpdateHandler<T = UpdateContext<ChatMemberUpdate>> = Parse
export type InlineQueryHandler<T = InlineQueryContext> = ParsedUpdateHandler<'inline_query', T> export type InlineQueryHandler<T = InlineQueryContext> = ParsedUpdateHandler<'inline_query', T>
export type ChosenInlineResultHandler<T = ChosenInlineResultContext> = ParsedUpdateHandler<'chosen_inline_result', T> export type ChosenInlineResultHandler<T = ChosenInlineResultContext> = ParsedUpdateHandler<'chosen_inline_result', T>
export type CallbackQueryHandler<T = CallbackQueryContext, S = never> = ParsedUpdateHandler<'callback_query', T, S> export type CallbackQueryHandler<T = CallbackQueryContext, S = never> = ParsedUpdateHandler<'callback_query', T, S>
export type InlineCallbackQueryHandler<T = InlineCallbackQueryContext, S = never> = ParsedUpdateHandler<
'inline_callback_query',
T,
S
>
export type PollUpdateHandler<T = UpdateContext<PollUpdate>> = ParsedUpdateHandler<'poll', T> export type PollUpdateHandler<T = UpdateContext<PollUpdate>> = ParsedUpdateHandler<'poll', T>
export type PollVoteHandler<T = UpdateContext<PollVoteUpdate>> = ParsedUpdateHandler<'poll_vote', T> export type PollVoteHandler<T = UpdateContext<PollVoteUpdate>> = ParsedUpdateHandler<'poll_vote', T>
export type UserStatusUpdateHandler<T = UpdateContext<UserStatusUpdate>> = ParsedUpdateHandler<'user_status', T> export type UserStatusUpdateHandler<T = UpdateContext<UserStatusUpdate>> = ParsedUpdateHandler<'user_status', T>
@ -87,6 +93,7 @@ export type UpdateHandler =
| InlineQueryHandler | InlineQueryHandler
| ChosenInlineResultHandler | ChosenInlineResultHandler
| CallbackQueryHandler | CallbackQueryHandler
| InlineCallbackQueryHandler
| PollUpdateHandler | PollUpdateHandler
| PollVoteHandler | PollVoteHandler
| UserStatusUpdateHandler | UserStatusUpdateHandler

View file

@ -45,10 +45,9 @@ export const defaultStateKeyDelegate: StateKeyDelegate = (upd): string | null =>
} }
if (upd._name === 'callback_query') { if (upd._name === 'callback_query') {
if (upd.isInline) return null if (upd.chat.chatType === 'private') return `${upd.user.id}`
if (upd.chatType === 'user') return `${upd.user.id}`
return `${upd.chatId}_${upd.user.id}` return `${upd.chat.id}_${upd.user.id}`
} }
return null return null