2021-06-06 15:20:41 +03:00
|
|
|
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
2021-04-28 23:00:51 +03:00
|
|
|
import {
|
2021-05-05 01:50:04 +03:00
|
|
|
CallbackQuery,
|
2021-05-11 21:46:59 +03:00
|
|
|
ChatsIndex,
|
2021-04-28 23:00:51 +03:00
|
|
|
InlineQuery,
|
2021-05-27 01:02:31 +03:00
|
|
|
MaybeAsync,
|
2021-04-28 23:00:51 +03:00
|
|
|
Message,
|
|
|
|
MtCuteArgumentError,
|
|
|
|
TelegramClient,
|
2021-05-11 21:46:59 +03:00
|
|
|
UsersIndex,
|
2021-04-28 23:00:51 +03:00
|
|
|
} from '@mtcute/client'
|
2021-04-23 22:35:37 +03:00
|
|
|
import { tl } from '@mtcute/tl'
|
2021-05-05 00:43:35 +03:00
|
|
|
// begin-codegen-imports
|
2021-04-27 20:31:04 +03:00
|
|
|
import {
|
2021-05-05 00:43:35 +03:00
|
|
|
UpdateHandler,
|
|
|
|
RawUpdateHandler,
|
|
|
|
NewMessageHandler,
|
|
|
|
EditMessageHandler,
|
2021-05-16 13:06:26 +03:00
|
|
|
DeleteMessageHandler,
|
2021-05-04 14:07:40 +03:00
|
|
|
ChatMemberUpdateHandler,
|
|
|
|
InlineQueryHandler,
|
2021-05-05 00:43:35 +03:00
|
|
|
ChosenInlineResultHandler,
|
2021-05-05 01:50:04 +03:00
|
|
|
CallbackQueryHandler,
|
2021-05-07 15:37:17 +03:00
|
|
|
PollUpdateHandler,
|
|
|
|
PollVoteHandler,
|
2021-05-08 16:35:25 +03:00
|
|
|
UserStatusUpdateHandler,
|
|
|
|
UserTypingHandler,
|
2021-04-27 20:31:04 +03:00
|
|
|
} from './handler'
|
2021-05-05 00:43:35 +03:00
|
|
|
// end-codegen-imports
|
2021-07-03 16:42:41 +03:00
|
|
|
import { UpdateInfo } from './handler'
|
2021-04-23 22:35:37 +03:00
|
|
|
import { filters, UpdateFilter } from './filters'
|
|
|
|
import { handlers } from './builders'
|
2021-04-27 20:31:04 +03:00
|
|
|
import { ChatMemberUpdate } from './updates'
|
2021-05-04 14:07:40 +03:00
|
|
|
import { ChosenInlineResult } from './updates/chosen-inline-result'
|
2021-05-07 15:37:17 +03:00
|
|
|
import { PollUpdate } from './updates/poll-update'
|
|
|
|
import { PollVoteUpdate } from './updates/poll-vote'
|
2021-05-08 16:35:25 +03:00
|
|
|
import { UserStatusUpdate } from './updates/user-status-update'
|
|
|
|
import { UserTypingUpdate } from './updates/user-typing-update'
|
2021-05-16 13:06:26 +03:00
|
|
|
import { DeleteMessageUpdate } from './updates/delete-message-update'
|
2021-05-27 01:02:31 +03:00
|
|
|
import { IStateStorage, UpdateState, StateKeyDelegate } from './state'
|
2021-06-27 23:59:04 +03:00
|
|
|
import { defaultStateKeyDelegate } from './state'
|
2021-06-14 18:58:07 +03:00
|
|
|
import { PropagationAction } from './propagation'
|
2021-04-23 22:35:37 +03:00
|
|
|
|
|
|
|
const noop = () => {}
|
|
|
|
|
2021-04-28 23:00:51 +03:00
|
|
|
type ParserFunction = (
|
|
|
|
client: TelegramClient,
|
|
|
|
upd: tl.TypeUpdate | tl.TypeMessage,
|
2021-05-11 21:46:59 +03:00
|
|
|
users: UsersIndex,
|
|
|
|
chats: ChatsIndex
|
2021-04-28 23:00:51 +03:00
|
|
|
) => any
|
|
|
|
type UpdateParser = [Exclude<UpdateHandler['type'], 'raw'>, ParserFunction]
|
|
|
|
|
|
|
|
const baseMessageParser: ParserFunction = (
|
|
|
|
client: TelegramClient,
|
|
|
|
upd,
|
|
|
|
users,
|
|
|
|
chats
|
|
|
|
) =>
|
|
|
|
new Message(
|
|
|
|
client,
|
|
|
|
tl.isAnyMessage(upd) ? upd : (upd as any).message,
|
|
|
|
users,
|
2021-05-23 14:04:28 +03:00
|
|
|
chats,
|
|
|
|
upd._ === 'updateNewScheduledMessage'
|
2021-04-28 23:00:51 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
const newMessageParser: UpdateParser = ['new_message', baseMessageParser]
|
|
|
|
const editMessageParser: UpdateParser = ['edit_message', baseMessageParser]
|
|
|
|
const chatMemberParser: UpdateParser = [
|
|
|
|
'chat_member',
|
|
|
|
(client, upd, users, chats) =>
|
|
|
|
new ChatMemberUpdate(client, upd as any, users, chats),
|
|
|
|
]
|
2021-05-05 01:50:04 +03:00
|
|
|
const callbackQueryParser: UpdateParser = [
|
|
|
|
'callback_query',
|
|
|
|
(client, upd, users) => new CallbackQuery(client, upd as any, users),
|
|
|
|
]
|
2021-05-08 16:35:25 +03:00
|
|
|
const userTypingParser: UpdateParser = [
|
|
|
|
'user_typing',
|
2021-05-11 21:46:59 +03:00
|
|
|
(client, upd) => new UserTypingUpdate(client, upd as any),
|
2021-05-08 16:35:25 +03:00
|
|
|
]
|
2021-05-16 13:06:26 +03:00
|
|
|
const deleteMessageParser: UpdateParser = [
|
|
|
|
'delete_message',
|
2021-05-23 14:43:40 +03:00
|
|
|
(client, upd) => new DeleteMessageUpdate(client, upd as any),
|
2021-05-16 13:06:26 +03:00
|
|
|
]
|
2021-04-28 23:00:51 +03:00
|
|
|
|
|
|
|
const PARSERS: Partial<
|
|
|
|
Record<(tl.TypeUpdate | tl.TypeMessage)['_'], UpdateParser>
|
|
|
|
> = {
|
|
|
|
message: newMessageParser,
|
|
|
|
messageEmpty: newMessageParser,
|
|
|
|
messageService: newMessageParser,
|
|
|
|
updateNewMessage: newMessageParser,
|
|
|
|
updateNewChannelMessage: newMessageParser,
|
|
|
|
updateNewScheduledMessage: newMessageParser,
|
|
|
|
updateEditMessage: editMessageParser,
|
|
|
|
updateEditChannelMessage: editMessageParser,
|
|
|
|
updateChatParticipant: chatMemberParser,
|
|
|
|
updateChannelParticipant: chatMemberParser,
|
|
|
|
updateBotInlineQuery: [
|
|
|
|
'inline_query',
|
|
|
|
(client, upd, users) => new InlineQuery(client, upd as any, users),
|
|
|
|
],
|
2021-05-04 14:07:40 +03:00
|
|
|
updateBotInlineSend: [
|
|
|
|
'chosen_inline_result',
|
|
|
|
(client, upd, users) =>
|
|
|
|
new ChosenInlineResult(client, upd as any, users),
|
|
|
|
],
|
2021-05-05 01:50:04 +03:00
|
|
|
updateBotCallbackQuery: callbackQueryParser,
|
|
|
|
updateInlineBotCallbackQuery: callbackQueryParser,
|
2021-05-07 15:37:17 +03:00
|
|
|
updateMessagePoll: [
|
|
|
|
'poll',
|
|
|
|
(client, upd, users) => new PollUpdate(client, upd as any, users),
|
|
|
|
],
|
|
|
|
updateMessagePollVote: [
|
|
|
|
'poll_vote',
|
|
|
|
(client, upd, users) => new PollVoteUpdate(client, upd as any, users),
|
|
|
|
],
|
2021-05-08 16:35:25 +03:00
|
|
|
updateUserStatus: [
|
|
|
|
'user_status',
|
|
|
|
(client, upd) => new UserStatusUpdate(client, upd as any),
|
|
|
|
],
|
|
|
|
updateChannelUserTyping: userTypingParser,
|
|
|
|
updateChatUserTyping: userTypingParser,
|
|
|
|
updateUserTyping: userTypingParser,
|
2021-05-16 13:06:26 +03:00
|
|
|
updateDeleteChannelMessages: deleteMessageParser,
|
|
|
|
updateDeleteMessages: deleteMessageParser,
|
2021-04-28 23:00:51 +03:00
|
|
|
}
|
|
|
|
|
2021-05-23 15:38:03 +03:00
|
|
|
const HANDLER_TYPE_TO_UPDATE: Record<string, string[]> = {}
|
|
|
|
Object.keys(PARSERS).forEach((upd: keyof typeof PARSERS) => {
|
|
|
|
const handler = PARSERS[upd]![0]
|
2021-05-27 01:02:31 +03:00
|
|
|
if (!(handler in HANDLER_TYPE_TO_UPDATE))
|
|
|
|
HANDLER_TYPE_TO_UPDATE[handler] = []
|
2021-05-23 15:38:03 +03:00
|
|
|
HANDLER_TYPE_TO_UPDATE[handler].push(upd)
|
|
|
|
})
|
|
|
|
|
2021-04-23 22:35:37 +03:00
|
|
|
/**
|
2021-05-08 16:35:25 +03:00
|
|
|
* Updates dispatcher
|
2021-04-23 22:35:37 +03:00
|
|
|
*/
|
2021-05-27 01:02:31 +03:00
|
|
|
export class Dispatcher<State = never, SceneName extends string = string> {
|
2021-05-23 14:43:40 +03:00
|
|
|
private _groups: Record<
|
|
|
|
number,
|
|
|
|
Record<UpdateHandler['type'], UpdateHandler[]>
|
|
|
|
> = {}
|
2021-04-23 22:35:37 +03:00
|
|
|
private _groupsOrder: number[] = []
|
|
|
|
|
|
|
|
private _client?: TelegramClient
|
|
|
|
|
2021-05-27 01:02:31 +03:00
|
|
|
private _parent?: Dispatcher<any>
|
|
|
|
private _children: Dispatcher<any>[] = []
|
|
|
|
|
|
|
|
private _scenes: Record<string, Dispatcher<any, SceneName>>
|
|
|
|
private _scene?: SceneName
|
|
|
|
private _sceneScoped?: boolean
|
|
|
|
|
|
|
|
private _storage: State extends never ? undefined : IStateStorage
|
|
|
|
private _stateKeyDelegate: State extends never
|
|
|
|
? undefined
|
|
|
|
: StateKeyDelegate
|
|
|
|
|
|
|
|
private _customStateKeyDelegate?: StateKeyDelegate
|
|
|
|
private _customStorage?: IStateStorage
|
2021-04-23 22:35:37 +03:00
|
|
|
|
2021-05-23 15:38:03 +03:00
|
|
|
private _handlersCount: Record<string, number> = {}
|
|
|
|
|
2021-07-03 16:42:41 +03:00
|
|
|
private _errorHandler?: <T = {}>(
|
2021-06-07 23:59:17 +03:00
|
|
|
err: Error,
|
2021-07-03 16:42:41 +03:00
|
|
|
update: UpdateInfo<UpdateHandler> & T,
|
2021-06-07 23:59:17 +03:00
|
|
|
state?: UpdateState<State, SceneName>
|
2021-06-27 23:59:04 +03:00
|
|
|
) => MaybeAsync<boolean>
|
2021-06-07 23:59:17 +03:00
|
|
|
|
2021-07-03 16:42:41 +03:00
|
|
|
private _preUpdateHandler?: <T = {}>(
|
|
|
|
update: UpdateInfo<UpdateHandler> & T,
|
|
|
|
state?: UpdateState<State, SceneName>
|
|
|
|
) => MaybeAsync<PropagationAction | void>
|
|
|
|
|
|
|
|
private _postUpdateHandler?: <T = {}>(
|
|
|
|
handled: boolean,
|
|
|
|
update: UpdateInfo<UpdateHandler> & T,
|
|
|
|
state?: UpdateState<State, SceneName>
|
|
|
|
) => MaybeAsync<void>
|
|
|
|
|
2021-04-23 22:35:37 +03:00
|
|
|
/**
|
2021-05-27 01:02:31 +03:00
|
|
|
* Create a new dispatcher, that will be used as a child,
|
|
|
|
* optionally providing a custom key delegate
|
|
|
|
*/
|
|
|
|
constructor(key?: StateKeyDelegate)
|
|
|
|
/**
|
|
|
|
* Create a new dispatcher, that will be used as a child, optionally
|
|
|
|
* providing custom storage and key delegate
|
|
|
|
*/
|
|
|
|
constructor(storage: IStateStorage, key?: StateKeyDelegate)
|
|
|
|
/**
|
|
|
|
* Create a new dispatcher and bind it to client and optionally
|
|
|
|
* FSM storage
|
2021-04-23 22:35:37 +03:00
|
|
|
*/
|
2021-05-27 01:02:31 +03:00
|
|
|
constructor(
|
|
|
|
client: TelegramClient,
|
|
|
|
...args: State extends never ? [] : [IStateStorage, StateKeyDelegate?]
|
|
|
|
)
|
|
|
|
constructor(
|
|
|
|
client?: TelegramClient | IStateStorage | StateKeyDelegate,
|
|
|
|
storage?: IStateStorage | StateKeyDelegate,
|
|
|
|
key?: StateKeyDelegate
|
|
|
|
) {
|
2021-04-23 22:35:37 +03:00
|
|
|
if (client) {
|
2021-05-27 01:02:31 +03:00
|
|
|
if (client instanceof TelegramClient) {
|
|
|
|
this.bindToClient(client)
|
|
|
|
if (storage) {
|
|
|
|
this._storage = storage as any
|
2021-06-06 15:20:41 +03:00
|
|
|
this._stateKeyDelegate = (key ??
|
|
|
|
defaultStateKeyDelegate) as any
|
2021-05-27 01:02:31 +03:00
|
|
|
}
|
|
|
|
} else if (typeof client === 'function') {
|
|
|
|
// is StateKeyDelegate
|
|
|
|
this._customStateKeyDelegate = client as any
|
|
|
|
} else {
|
|
|
|
this._customStorage = client as any
|
|
|
|
|
|
|
|
if (storage) {
|
|
|
|
this._customStateKeyDelegate = client as any
|
|
|
|
}
|
|
|
|
}
|
2021-04-23 22:35:37 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Bind the dispatcher to the client.
|
|
|
|
* Called by the constructor automatically if
|
|
|
|
* `client` was passed.
|
|
|
|
*
|
|
|
|
* Under the hood, this replaces client's `dispatchUpdate`
|
|
|
|
* function, meaning you can't bind two different
|
|
|
|
* dispatchers to the same client at the same time.
|
|
|
|
* Instead, use {@link extend}, {@link addChild}
|
|
|
|
* or {@link addScene} on the existing, already bound dispatcher.
|
|
|
|
*
|
|
|
|
* Dispatcher also uses bound client to throw errors
|
|
|
|
*/
|
|
|
|
bindToClient(client: TelegramClient): void {
|
|
|
|
client['dispatchUpdate'] = this.dispatchUpdate.bind(this)
|
|
|
|
this._client = client
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Unbind a dispatcher from the client.
|
|
|
|
*
|
|
|
|
* This will replace client's dispatchUpdate with a no-op.
|
|
|
|
* If this dispatcher is not bound, nothing will happen.
|
|
|
|
*/
|
|
|
|
unbind(): void {
|
|
|
|
if (this._client) {
|
|
|
|
this._client['dispatchUpdate'] = noop
|
|
|
|
this._client = undefined
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Process an update with this dispatcher.
|
|
|
|
* Calling this method without bound client will not work.
|
|
|
|
*
|
|
|
|
* Under the hood asynchronously calls {@link dispatchUpdateNow}
|
|
|
|
* with error handler set to client's one.
|
|
|
|
*
|
|
|
|
* @param update Update to process
|
|
|
|
* @param users Map of users
|
|
|
|
* @param chats Map of chats
|
|
|
|
*/
|
|
|
|
dispatchUpdate(
|
|
|
|
update: tl.TypeUpdate | tl.TypeMessage,
|
2021-05-11 21:46:59 +03:00
|
|
|
users: UsersIndex,
|
|
|
|
chats: ChatsIndex
|
2021-04-23 22:35:37 +03:00
|
|
|
): void {
|
|
|
|
if (!this._client) return
|
|
|
|
|
|
|
|
// order does not matter in the dispatcher,
|
|
|
|
// so we can handle each update in its own task
|
|
|
|
this.dispatchUpdateNow(update, users, chats).catch((err) =>
|
|
|
|
this._client!['_emitError'](err)
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Process an update right now in the current stack.
|
|
|
|
*
|
|
|
|
* Unlike {@link dispatchUpdate}, this does not schedule
|
|
|
|
* the update to be dispatched, but dispatches it immediately,
|
|
|
|
* and after `await`ing this method you can be certain that the update
|
|
|
|
* was fully processed by all the registered handlers, including children.
|
|
|
|
*
|
|
|
|
* @param update Update to process
|
|
|
|
* @param users Map of users
|
|
|
|
* @param chats Map of chats
|
2021-07-03 16:42:41 +03:00
|
|
|
* @returns Whether the update was handled
|
2021-04-23 22:35:37 +03:00
|
|
|
*/
|
|
|
|
async dispatchUpdateNow(
|
|
|
|
update: tl.TypeUpdate | tl.TypeMessage,
|
2021-05-11 21:46:59 +03:00
|
|
|
users: UsersIndex,
|
2021-05-23 14:43:40 +03:00
|
|
|
chats: ChatsIndex
|
2021-07-03 16:42:41 +03:00
|
|
|
): Promise<boolean> {
|
2021-05-23 14:16:01 +03:00
|
|
|
return this._dispatchUpdateNowImpl(update, users, chats)
|
|
|
|
}
|
|
|
|
|
|
|
|
private async _dispatchUpdateNowImpl(
|
2021-06-14 18:58:07 +03:00
|
|
|
update: tl.TypeUpdate | tl.TypeMessage | null,
|
|
|
|
users: UsersIndex | null,
|
|
|
|
chats: ChatsIndex | null,
|
2021-05-27 01:02:31 +03:00
|
|
|
// this is getting a bit crazy lol
|
2021-05-23 14:16:01 +03:00
|
|
|
parsed?: any,
|
2021-05-27 01:02:31 +03:00
|
|
|
parsedType?: Exclude<UpdateHandler['type'], 'raw'> | null,
|
|
|
|
parsedState?: UpdateState<State, SceneName> | null,
|
|
|
|
parsedScene?: string | null,
|
|
|
|
forceScene?: true
|
2021-07-03 16:42:41 +03:00
|
|
|
): Promise<boolean> {
|
|
|
|
if (!this._client) return false
|
2021-04-23 22:35:37 +03:00
|
|
|
|
2021-06-14 18:58:07 +03:00
|
|
|
const isRawMessage = update && tl.isAnyMessage(update)
|
2021-05-27 01:02:31 +03:00
|
|
|
|
2021-06-14 18:58:07 +03:00
|
|
|
if (parsed === undefined && this._handlersCount[update!._]) {
|
|
|
|
const pair = PARSERS[update!._]
|
2021-05-23 14:16:01 +03:00
|
|
|
if (pair) {
|
2021-06-14 18:58:07 +03:00
|
|
|
parsed = pair[1](this._client, update!, users!, chats!)
|
2021-05-23 14:16:01 +03:00
|
|
|
parsedType = pair[0]
|
|
|
|
} else {
|
|
|
|
parsed = parsedType = null
|
|
|
|
}
|
|
|
|
}
|
2021-04-27 20:31:04 +03:00
|
|
|
|
2021-05-27 01:02:31 +03:00
|
|
|
if (parsedScene === undefined) {
|
|
|
|
if (
|
|
|
|
this._storage &&
|
|
|
|
this._scenes &&
|
|
|
|
(parsedType === 'new_message' ||
|
|
|
|
parsedType === 'edit_message' ||
|
|
|
|
parsedType === 'callback_query')
|
|
|
|
) {
|
|
|
|
// no need to fetch scene if there are no registered scenes
|
|
|
|
const key = await this._stateKeyDelegate!(parsed)
|
|
|
|
if (key) {
|
|
|
|
parsedScene = await this._storage.getCurrentScene(key)
|
|
|
|
} else {
|
|
|
|
parsedScene = null
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
parsedScene = null
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!forceScene && parsedScene !== null) {
|
|
|
|
if (this._scene) {
|
|
|
|
if (this._scene !== parsedScene)
|
|
|
|
// should not happen, but just in case
|
2021-07-03 16:42:41 +03:00
|
|
|
return false
|
2021-05-27 01:02:31 +03:00
|
|
|
} else {
|
|
|
|
if (!this._scenes || !(parsedScene in this._scenes))
|
|
|
|
// not registered scene
|
2021-07-03 16:42:41 +03:00
|
|
|
return false
|
2021-05-27 01:02:31 +03:00
|
|
|
|
|
|
|
return this._scenes[parsedScene]._dispatchUpdateNowImpl(
|
|
|
|
update,
|
|
|
|
users,
|
|
|
|
chats,
|
|
|
|
parsed,
|
|
|
|
parsedType,
|
|
|
|
parsedState,
|
|
|
|
parsedScene,
|
|
|
|
true
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (parsedState === undefined) {
|
|
|
|
if (
|
|
|
|
this._storage &&
|
|
|
|
(parsedType === 'new_message' ||
|
|
|
|
parsedType === 'edit_message' ||
|
|
|
|
parsedType === 'callback_query')
|
|
|
|
) {
|
|
|
|
const key = await this._stateKeyDelegate!(parsed)
|
|
|
|
if (key) {
|
|
|
|
let customKey
|
2021-06-06 15:20:41 +03:00
|
|
|
if (
|
|
|
|
!this._customStateKeyDelegate ||
|
|
|
|
(customKey = await this._customStateKeyDelegate(parsed))
|
|
|
|
) {
|
2021-05-27 01:02:31 +03:00
|
|
|
parsedState = new UpdateState(
|
|
|
|
this._storage!,
|
|
|
|
key,
|
|
|
|
this._scene ?? null,
|
|
|
|
this._sceneScoped,
|
|
|
|
this._customStorage,
|
|
|
|
customKey
|
|
|
|
)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
parsedState = null
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
parsedState = null
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-03 16:42:41 +03:00
|
|
|
let shouldDispatch = true
|
|
|
|
let shouldDispatchChildren = true
|
|
|
|
let wasHandled = false
|
2021-05-23 14:43:40 +03:00
|
|
|
|
2021-07-03 16:42:41 +03:00
|
|
|
const updateInfo = { type: parsedType, data: parsed }
|
|
|
|
switch (
|
|
|
|
await this._preUpdateHandler?.(
|
|
|
|
updateInfo as any,
|
|
|
|
parsedState as any
|
|
|
|
)
|
|
|
|
) {
|
|
|
|
case 'stop':
|
|
|
|
shouldDispatch = false
|
|
|
|
break
|
|
|
|
case 'stop-children':
|
|
|
|
return false
|
|
|
|
}
|
2021-06-14 18:58:07 +03:00
|
|
|
|
2021-07-03 16:42:41 +03:00
|
|
|
if (shouldDispatch) {
|
|
|
|
outer: for (const grp of this._groupsOrder) {
|
|
|
|
const group = this._groups[grp]
|
2021-05-23 14:43:40 +03:00
|
|
|
|
2021-07-03 16:42:41 +03:00
|
|
|
if (update && !isRawMessage && 'raw' in group) {
|
|
|
|
const handlers = group['raw'] as RawUpdateHandler[]
|
2021-05-23 14:43:40 +03:00
|
|
|
|
2021-06-07 23:59:17 +03:00
|
|
|
for (const h of handlers) {
|
2021-06-14 18:58:07 +03:00
|
|
|
let result: void | PropagationAction
|
2021-06-07 23:59:17 +03:00
|
|
|
|
|
|
|
if (
|
|
|
|
!h.check ||
|
2021-07-03 16:42:41 +03:00
|
|
|
(await h.check(
|
|
|
|
this._client,
|
|
|
|
update as any,
|
|
|
|
users!,
|
|
|
|
chats!
|
|
|
|
))
|
2021-06-07 23:59:17 +03:00
|
|
|
) {
|
|
|
|
result = await h.callback(
|
2021-07-03 16:42:41 +03:00
|
|
|
this._client,
|
|
|
|
update as any,
|
|
|
|
users!,
|
|
|
|
chats!
|
2021-06-07 23:59:17 +03:00
|
|
|
)
|
2021-07-03 16:42:41 +03:00
|
|
|
wasHandled = true
|
2021-06-07 23:59:17 +03:00
|
|
|
} else continue
|
|
|
|
|
2021-06-14 18:58:07 +03:00
|
|
|
switch (result) {
|
|
|
|
case 'continue':
|
|
|
|
continue
|
|
|
|
case 'stop':
|
|
|
|
break outer
|
|
|
|
case 'stop-children':
|
2021-07-03 16:42:41 +03:00
|
|
|
shouldDispatchChildren = false
|
|
|
|
break outer
|
|
|
|
}
|
2021-06-14 18:58:07 +03:00
|
|
|
|
2021-07-03 16:42:41 +03:00
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
2021-06-14 18:58:07 +03:00
|
|
|
|
2021-07-03 16:42:41 +03:00
|
|
|
if (parsedType && parsedType in group) {
|
|
|
|
// raw is not handled here, so we can safely assume this
|
|
|
|
const handlers = group[parsedType] as Exclude<
|
|
|
|
UpdateHandler,
|
|
|
|
RawUpdateHandler
|
|
|
|
>[]
|
|
|
|
|
|
|
|
try {
|
|
|
|
for (const h of handlers) {
|
|
|
|
let result: void | PropagationAction
|
|
|
|
|
|
|
|
if (
|
|
|
|
!h.check ||
|
|
|
|
(await h.check(parsed, parsedState as never))
|
|
|
|
) {
|
|
|
|
result = await h.callback(
|
2021-06-14 18:58:07 +03:00
|
|
|
parsed,
|
2021-07-03 16:42:41 +03:00
|
|
|
parsedState as never
|
2021-06-14 18:58:07 +03:00
|
|
|
)
|
2021-07-03 16:42:41 +03:00
|
|
|
wasHandled = true
|
|
|
|
} else continue
|
|
|
|
|
|
|
|
switch (result) {
|
|
|
|
case 'continue':
|
|
|
|
continue
|
|
|
|
case 'stop':
|
|
|
|
break outer
|
|
|
|
case 'stop-children':
|
|
|
|
shouldDispatchChildren = false
|
|
|
|
break outer
|
|
|
|
case 'scene': {
|
|
|
|
if (!parsedState)
|
|
|
|
throw new MtCuteArgumentError(
|
|
|
|
'Cannot use ToScene without state'
|
|
|
|
)
|
|
|
|
|
|
|
|
const scene = parsedState['_scene']
|
|
|
|
|
|
|
|
if (!scene)
|
|
|
|
throw new MtCuteArgumentError(
|
|
|
|
'Cannot use ToScene without entering a scene'
|
|
|
|
)
|
|
|
|
|
|
|
|
return this._scenes[
|
|
|
|
scene
|
|
|
|
]._dispatchUpdateNowImpl(
|
|
|
|
update,
|
|
|
|
users,
|
|
|
|
chats,
|
|
|
|
parsed,
|
|
|
|
parsedType,
|
|
|
|
undefined,
|
|
|
|
scene,
|
|
|
|
true
|
|
|
|
)
|
|
|
|
}
|
2021-06-14 18:58:07 +03:00
|
|
|
}
|
2021-06-07 23:59:17 +03:00
|
|
|
|
2021-07-03 16:42:41 +03:00
|
|
|
break
|
|
|
|
}
|
|
|
|
} catch (e) {
|
|
|
|
if (this._errorHandler) {
|
|
|
|
const handled = await this._errorHandler(
|
|
|
|
e,
|
|
|
|
updateInfo as any,
|
|
|
|
parsedState as never
|
|
|
|
)
|
|
|
|
if (!handled) throw e
|
|
|
|
} else {
|
|
|
|
throw e
|
|
|
|
}
|
2021-06-07 23:59:17 +03:00
|
|
|
}
|
2021-05-23 14:43:40 +03:00
|
|
|
}
|
|
|
|
}
|
2021-04-23 22:35:37 +03:00
|
|
|
}
|
|
|
|
|
2021-07-03 16:42:41 +03:00
|
|
|
if (shouldDispatchChildren) {
|
|
|
|
for (const child of this._children) {
|
|
|
|
wasHandled ||= await child._dispatchUpdateNowImpl(
|
|
|
|
update,
|
|
|
|
users,
|
|
|
|
chats,
|
|
|
|
parsed,
|
|
|
|
parsedType
|
|
|
|
)
|
|
|
|
}
|
2021-04-23 22:35:37 +03:00
|
|
|
}
|
2021-07-03 16:42:41 +03:00
|
|
|
|
|
|
|
this._postUpdateHandler?.(
|
|
|
|
wasHandled,
|
|
|
|
updateInfo as any,
|
|
|
|
parsedState as any
|
|
|
|
)
|
|
|
|
|
|
|
|
return wasHandled
|
2021-04-23 22:35:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Add an update handler to a given handlers group
|
|
|
|
*
|
|
|
|
* @param handler Update handler
|
|
|
|
* @param group Handler group index
|
|
|
|
*/
|
|
|
|
addUpdateHandler(handler: UpdateHandler, group = 0): void {
|
|
|
|
if (!(group in this._groups)) {
|
2021-05-23 14:43:40 +03:00
|
|
|
this._groups[group] = {} as any
|
2021-04-23 22:35:37 +03:00
|
|
|
this._groupsOrder.push(group)
|
|
|
|
this._groupsOrder.sort((a, b) => a - b)
|
|
|
|
}
|
|
|
|
|
2021-05-23 14:43:40 +03:00
|
|
|
if (!(handler.type in this._groups[group])) {
|
|
|
|
this._groups[group][handler.type] = []
|
|
|
|
}
|
|
|
|
|
2021-05-23 15:38:03 +03:00
|
|
|
HANDLER_TYPE_TO_UPDATE[handler.type].forEach((upd) => {
|
|
|
|
if (!(upd in this._handlersCount)) this._handlersCount[upd] = 0
|
|
|
|
this._handlersCount[upd] += 1
|
|
|
|
})
|
|
|
|
|
2021-05-23 14:43:40 +03:00
|
|
|
this._groups[group][handler.type].push(handler)
|
2021-04-23 22:35:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Remove an update handler (or handlers) from a given
|
|
|
|
* handler group.
|
|
|
|
*
|
|
|
|
* @param handler Update handler to remove, its type or `'all'` to remove all
|
2021-05-23 14:43:40 +03:00
|
|
|
* @param group Handler group index (-1 to affect all groups)
|
2021-04-23 22:35:37 +03:00
|
|
|
* @internal
|
|
|
|
*/
|
|
|
|
removeUpdateHandler(
|
|
|
|
handler: UpdateHandler | UpdateHandler['type'] | 'all',
|
|
|
|
group = 0
|
|
|
|
): void {
|
2021-05-23 14:43:40 +03:00
|
|
|
if (group !== -1 && !(group in this._groups)) {
|
2021-04-23 22:35:37 +03:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if (typeof handler === 'string') {
|
|
|
|
if (handler === 'all') {
|
2021-05-23 14:43:40 +03:00
|
|
|
if (group === -1) {
|
|
|
|
this._groups = {}
|
2021-05-23 15:38:03 +03:00
|
|
|
this._handlersCount = {}
|
2021-05-23 14:43:40 +03:00
|
|
|
} else {
|
2021-05-23 15:38:03 +03:00
|
|
|
const grp = this._groups[group] as any
|
|
|
|
Object.keys(grp).forEach((handler) => {
|
|
|
|
HANDLER_TYPE_TO_UPDATE[handler].forEach((upd) => {
|
|
|
|
this._handlersCount[upd] -= grp[handler].length
|
|
|
|
})
|
|
|
|
})
|
2021-05-23 14:43:40 +03:00
|
|
|
delete this._groups[group]
|
|
|
|
}
|
2021-04-23 22:35:37 +03:00
|
|
|
} else {
|
2021-05-23 15:38:03 +03:00
|
|
|
HANDLER_TYPE_TO_UPDATE[handler].forEach((upd) => {
|
2021-05-27 01:02:31 +03:00
|
|
|
this._handlersCount[upd] -= this._groups[group][
|
|
|
|
handler
|
|
|
|
].length
|
2021-05-23 15:38:03 +03:00
|
|
|
})
|
2021-05-23 14:43:40 +03:00
|
|
|
delete this._groups[group][handler]
|
2021-04-23 22:35:37 +03:00
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(handler.type in this._groups[group])) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2021-05-23 14:43:40 +03:00
|
|
|
const idx = this._groups[group][handler.type].indexOf(handler)
|
2021-04-23 22:35:37 +03:00
|
|
|
if (idx > 0) {
|
2021-05-23 14:43:40 +03:00
|
|
|
this._groups[group][handler.type].splice(idx, 1)
|
2021-05-23 15:38:03 +03:00
|
|
|
|
|
|
|
HANDLER_TYPE_TO_UPDATE[handler.type].forEach((upd) => {
|
|
|
|
this._handlersCount[upd] -= 1
|
|
|
|
})
|
2021-04-23 22:35:37 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-07 23:59:17 +03:00
|
|
|
/**
|
|
|
|
* Register an error handler.
|
|
|
|
*
|
|
|
|
* This is used locally within this dispatcher
|
|
|
|
* (does not affect children/parent) whenever
|
|
|
|
* an error is thrown inside an update handler.
|
|
|
|
* Not used for raw update handlers
|
|
|
|
*
|
|
|
|
* When an error is thrown, but there is no error
|
|
|
|
* handler, it is propagated to `TelegramClient`.
|
|
|
|
*
|
|
|
|
* There can be at most one error handler.
|
|
|
|
* Pass `null` to remove it.
|
|
|
|
*
|
|
|
|
* @param handler Error handler
|
|
|
|
*/
|
2021-07-03 16:42:41 +03:00
|
|
|
onError<T = {}>(
|
2021-06-07 23:59:17 +03:00
|
|
|
handler:
|
|
|
|
| ((
|
|
|
|
err: Error,
|
2021-07-03 16:42:41 +03:00
|
|
|
update: UpdateInfo<UpdateHandler> & T,
|
2021-06-07 23:59:17 +03:00
|
|
|
state?: UpdateState<State, SceneName>
|
2021-06-27 23:59:04 +03:00
|
|
|
) => MaybeAsync<boolean>)
|
2021-06-07 23:59:17 +03:00
|
|
|
| null
|
|
|
|
): void {
|
|
|
|
if (handler) this._errorHandler = handler
|
|
|
|
else this._errorHandler = undefined
|
|
|
|
}
|
|
|
|
|
2021-07-03 16:42:41 +03:00
|
|
|
/**
|
|
|
|
* Register pre-update middleware.
|
|
|
|
*
|
|
|
|
* This is used locally within this dispatcher
|
|
|
|
* (does not affect children/parent) before processing
|
|
|
|
* an update, and can be used to skip this update.
|
|
|
|
*
|
|
|
|
* There can be at most one pre-update middleware.
|
|
|
|
* Pass `null` to remove it.
|
|
|
|
*
|
|
|
|
* @param handler Pre-update middleware
|
|
|
|
*/
|
|
|
|
onPreUpdate<T = {}>(
|
|
|
|
handler:
|
|
|
|
| ((
|
|
|
|
update: UpdateInfo<UpdateHandler> & T,
|
|
|
|
state?: UpdateState<State, SceneName>
|
|
|
|
) => MaybeAsync<PropagationAction | void>)
|
|
|
|
| null
|
|
|
|
): void {
|
|
|
|
if (handler) this._preUpdateHandler = handler
|
|
|
|
else this._preUpdateHandler = undefined
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Register post-update middleware.
|
|
|
|
*
|
|
|
|
* This is used locally within this dispatcher
|
|
|
|
* (does not affect children/parent) after successfully
|
|
|
|
* processing an update, and can be used for stats.
|
|
|
|
*
|
|
|
|
* There can be at most one post-update middleware.
|
|
|
|
* Pass `null` to remove it.
|
|
|
|
*
|
|
|
|
* @param handler Pre-update middleware
|
|
|
|
*/
|
|
|
|
onPostUpdate<T = {}>(
|
|
|
|
handler:
|
|
|
|
| ((
|
|
|
|
handled: boolean,
|
|
|
|
update: UpdateInfo<UpdateHandler> & T,
|
|
|
|
state?: UpdateState<State, SceneName>
|
|
|
|
) => MaybeAsync<void>)
|
|
|
|
| null
|
|
|
|
): void {
|
|
|
|
if (handler) this._postUpdateHandler = handler
|
|
|
|
else this._postUpdateHandler = undefined
|
|
|
|
}
|
|
|
|
|
2021-06-14 18:58:07 +03:00
|
|
|
/**
|
|
|
|
* Set error handler that will propagate
|
|
|
|
* the error to the parent dispatcher
|
|
|
|
*/
|
|
|
|
propagateErrorToParent<T extends Exclude<UpdateHandler, RawUpdateHandler>>(
|
|
|
|
err: Error,
|
2021-07-03 16:42:41 +03:00
|
|
|
update: UpdateInfo<T>,
|
2021-06-14 18:58:07 +03:00
|
|
|
state?: UpdateState<State, SceneName>
|
2021-06-27 23:59:04 +03:00
|
|
|
): MaybeAsync<boolean> {
|
2021-06-14 18:58:07 +03:00
|
|
|
if (!this.parent)
|
|
|
|
throw new MtCuteArgumentError('This dispatcher is not a child')
|
|
|
|
|
|
|
|
if (this.parent._errorHandler) {
|
|
|
|
return this.parent._errorHandler(err, update, state)
|
|
|
|
} else {
|
|
|
|
throw err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-23 22:35:37 +03:00
|
|
|
// children //
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get parent dispatcher if current dispatcher is a child.
|
|
|
|
* Otherwise, return `null`
|
|
|
|
*/
|
2021-05-27 01:02:31 +03:00
|
|
|
get parent(): Dispatcher<any> | null {
|
2021-04-23 22:35:37 +03:00
|
|
|
return this._parent ?? null
|
|
|
|
}
|
|
|
|
|
2021-05-27 01:02:31 +03:00
|
|
|
private _prepareChild(child: Dispatcher<any>): void {
|
|
|
|
if (child._client) {
|
|
|
|
throw new MtCuteArgumentError(
|
|
|
|
'Provided dispatcher is ' +
|
|
|
|
(child._parent
|
|
|
|
? 'already a child. Use parent.removeChild() before calling addChild()'
|
|
|
|
: 'already bound to a client. Use unbind() before calling addChild()')
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
child._parent = this as any
|
|
|
|
child._client = this._client
|
|
|
|
child._storage = this._storage
|
|
|
|
child._stateKeyDelegate = this._stateKeyDelegate
|
|
|
|
}
|
|
|
|
|
2021-04-23 22:35:37 +03:00
|
|
|
/**
|
|
|
|
* Add a child dispatcher.
|
|
|
|
*
|
|
|
|
* Child dispatchers are called when dispatching updates
|
|
|
|
* just like normal, except they can be controlled
|
|
|
|
* externally. Additionally, child dispatcher have their own
|
|
|
|
* independent handler grouping that does not interfere with parent's,
|
|
|
|
* including `StopPropagation` (i.e. returning `StopPropagation` will
|
|
|
|
* still call children. To entirely stop, use `StopChildrenPropagation`)
|
|
|
|
*
|
2021-05-27 01:02:31 +03:00
|
|
|
* Note that child dispatchers share the same TelegramClient and
|
|
|
|
* storage binding as the parent, don't bind them manually.
|
2021-04-23 22:35:37 +03:00
|
|
|
*
|
2021-05-27 01:02:31 +03:00
|
|
|
* @param child Other dispatcher
|
2021-04-23 22:35:37 +03:00
|
|
|
*/
|
2021-05-27 01:02:31 +03:00
|
|
|
addChild(child: Dispatcher<State, SceneName>): void {
|
|
|
|
if (this._children.indexOf(child) > -1) return
|
2021-04-23 22:35:37 +03:00
|
|
|
|
2021-05-27 01:02:31 +03:00
|
|
|
this._prepareChild(child)
|
|
|
|
this._children.push(child)
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Add a dispatcher as a scene with a non-scoped state.
|
|
|
|
*
|
|
|
|
* Scoped storage for a scene means that the scene will
|
|
|
|
* have its own storage, that is only available within
|
|
|
|
* the scene and does not interfere with global state.
|
|
|
|
* Non-scoped, on the other hand, is the same state as
|
|
|
|
* the one used for the root dispatcher
|
|
|
|
*
|
|
|
|
* @param uid UID of the scene
|
|
|
|
* @param scene Dispatcher representing the scene
|
|
|
|
* @param scoped Whether to use scoped FSM storage for the scene
|
|
|
|
*/
|
|
|
|
addScene(
|
|
|
|
uid: SceneName,
|
|
|
|
scene: Dispatcher<State, SceneName>,
|
|
|
|
scoped: false
|
|
|
|
): void
|
|
|
|
/**
|
|
|
|
* Add a dispatcher as a scene with a scoped state
|
|
|
|
*
|
|
|
|
* Scoped storage for a scene means that the scene will
|
|
|
|
* have its own storage, that is only available within
|
|
|
|
* the scene and does not interfere with global state.
|
|
|
|
* Non-scoped, on the other hand, is the same state as
|
|
|
|
* the one used for the root dispatcher
|
|
|
|
*
|
|
|
|
* @param uid UID of the scene
|
|
|
|
* @param scene Dispatcher representing the scene
|
|
|
|
* @param scoped Whether to use scoped FSM storage for the scene (defaults to `true`)
|
|
|
|
*/
|
|
|
|
addScene(
|
|
|
|
uid: SceneName,
|
|
|
|
scene: Dispatcher<any, SceneName>,
|
|
|
|
scoped?: true
|
|
|
|
): void
|
|
|
|
addScene(
|
|
|
|
uid: SceneName,
|
|
|
|
scene: Dispatcher<any, SceneName>,
|
|
|
|
scoped = true
|
|
|
|
): void {
|
|
|
|
if (!this._scenes) this._scenes = {}
|
|
|
|
if (uid in this._scenes) {
|
2021-04-23 22:35:37 +03:00
|
|
|
throw new MtCuteArgumentError(
|
2021-05-27 01:02:31 +03:00
|
|
|
`Scene with UID ${uid} is already registered!`
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
if (uid[0] === '$') {
|
2021-06-06 15:20:41 +03:00
|
|
|
throw new MtCuteArgumentError(`Scene UID cannot start with $`)
|
2021-04-23 22:35:37 +03:00
|
|
|
}
|
|
|
|
|
2021-05-27 01:02:31 +03:00
|
|
|
if (scene._scene) {
|
|
|
|
throw new MtCuteArgumentError(
|
|
|
|
`This dispatcher is already registered as scene ${scene._scene}`
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
this._prepareChild(scene)
|
|
|
|
scene._scene = uid
|
|
|
|
scene._sceneScoped = scoped
|
|
|
|
this._scenes[uid] = scene
|
2021-04-23 22:35:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Remove a child dispatcher.
|
|
|
|
*
|
|
|
|
* Removing child dispatcher will also remove
|
|
|
|
* child dispatcher's client binding.
|
|
|
|
*
|
|
|
|
* If the provided dispatcher is not a child of current,
|
|
|
|
* this function will silently fail.
|
|
|
|
*
|
2021-05-27 01:02:31 +03:00
|
|
|
* @param child Other dispatcher
|
2021-04-23 22:35:37 +03:00
|
|
|
*/
|
2021-05-27 01:02:31 +03:00
|
|
|
removeChild(child: Dispatcher): void {
|
|
|
|
const idx = this._children.indexOf(child)
|
2021-04-23 22:35:37 +03:00
|
|
|
if (idx > -1) {
|
2021-06-14 18:58:07 +03:00
|
|
|
child._unparent()
|
2021-04-23 22:35:37 +03:00
|
|
|
this._children.splice(idx, 1)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-14 18:58:07 +03:00
|
|
|
private _unparent(): void {
|
|
|
|
this._parent = this._client = undefined
|
|
|
|
;(this as any)._stateKeyDelegate = undefined
|
|
|
|
;(this as any)._storage = undefined
|
|
|
|
}
|
|
|
|
|
2021-04-23 22:35:37 +03:00
|
|
|
/**
|
|
|
|
* Extend current dispatcher by copying other dispatcher's
|
|
|
|
* handlers and children to the current.
|
|
|
|
*
|
|
|
|
* This might be more efficient for simple cases, but do note that the handler
|
2021-06-14 18:58:07 +03:00
|
|
|
* groups, children and scenes will get merged (unlike {@link addChild},
|
|
|
|
* where they are independent). Also note that unlike with children,
|
2021-04-23 22:35:37 +03:00
|
|
|
* when adding handlers to `other` *after* you extended
|
|
|
|
* the current dispatcher, changes will not be applied.
|
|
|
|
*
|
|
|
|
* @param other Other dispatcher
|
|
|
|
*/
|
2021-05-27 01:02:31 +03:00
|
|
|
extend(other: Dispatcher<State, SceneName>): void {
|
2021-06-14 18:58:07 +03:00
|
|
|
if (other._customStorage || other._customStateKeyDelegate) {
|
|
|
|
throw new MtCuteArgumentError(
|
|
|
|
'Provided dispatcher has custom storage and cannot be extended from.'
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2021-04-23 22:35:37 +03:00
|
|
|
other._groupsOrder.forEach((group) => {
|
|
|
|
if (!(group in this._groups)) {
|
2021-05-23 14:43:40 +03:00
|
|
|
this._groups[group] = other._groups[group]
|
2021-04-23 22:35:37 +03:00
|
|
|
this._groupsOrder.push(group)
|
2021-05-23 14:43:40 +03:00
|
|
|
} else {
|
|
|
|
const otherGrp = other._groups[group] as any
|
|
|
|
const selfGrp = this._groups[group] as any
|
|
|
|
Object.keys(otherGrp).forEach((typ) => {
|
|
|
|
if (!(typ in selfGrp)) {
|
|
|
|
selfGrp[typ] = otherGrp[typ]
|
|
|
|
} else {
|
|
|
|
selfGrp[typ].push(...otherGrp[typ])
|
|
|
|
}
|
|
|
|
})
|
2021-04-23 22:35:37 +03:00
|
|
|
}
|
|
|
|
})
|
|
|
|
|
2021-06-14 18:58:07 +03:00
|
|
|
Object.keys(other._handlersCount).forEach((typ) => {
|
|
|
|
this._handlersCount[typ] += other._handlersCount[typ]
|
|
|
|
})
|
|
|
|
|
|
|
|
other._children.forEach((it) => {
|
|
|
|
it._unparent()
|
|
|
|
this.addChild(it as any)
|
|
|
|
})
|
|
|
|
|
|
|
|
if (other._scenes) {
|
|
|
|
Object.keys(other._scenes).forEach((key) => {
|
|
|
|
other._scenes[key]._unparent()
|
|
|
|
if (key in this._scenes) {
|
|
|
|
// will be overwritten
|
|
|
|
delete this._scenes[key]
|
|
|
|
}
|
|
|
|
|
|
|
|
this.addScene(
|
|
|
|
key as any,
|
|
|
|
other._scenes[key] as any,
|
|
|
|
other._scenes[key]._sceneScoped as any
|
|
|
|
)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2021-04-23 22:35:37 +03:00
|
|
|
this._groupsOrder.sort((a, b) => a - b)
|
|
|
|
}
|
|
|
|
|
2021-05-27 01:02:31 +03:00
|
|
|
/**
|
2021-06-14 18:58:07 +03:00
|
|
|
* Create a clone of this dispatcher, that has the same handlers,
|
|
|
|
* but is not bound to a client or to a parent dispatcher.
|
2021-05-27 01:02:31 +03:00
|
|
|
*
|
2021-06-14 18:58:07 +03:00
|
|
|
* Custom Storage and key delegate are copied too.
|
2021-05-27 01:02:31 +03:00
|
|
|
*
|
2021-06-14 18:58:07 +03:00
|
|
|
* By default, child dispatchers (and scenes) are ignored, since
|
|
|
|
* that requires cloning every single one of them recursively
|
|
|
|
* and then binding them back.
|
2021-05-27 01:02:31 +03:00
|
|
|
*
|
2021-06-14 18:58:07 +03:00
|
|
|
* @param children Whether to also clone children and scenes
|
2021-05-27 01:02:31 +03:00
|
|
|
*/
|
2021-06-14 18:58:07 +03:00
|
|
|
clone(children = false): Dispatcher<State, SceneName> {
|
|
|
|
const dp = new Dispatcher<State, SceneName>()
|
|
|
|
|
|
|
|
// copy handlers.
|
|
|
|
Object.keys(this._groups).forEach((key) => {
|
|
|
|
const idx = (key as any) as number
|
|
|
|
|
|
|
|
dp._groups[idx] = {} as any
|
|
|
|
|
|
|
|
Object.keys(this._groups[idx]).forEach(
|
|
|
|
(type: UpdateHandler['type']) => {
|
|
|
|
dp._groups[idx][type] = [...this._groups[idx][type]]
|
|
|
|
}
|
2021-05-27 01:02:31 +03:00
|
|
|
)
|
2021-06-14 18:58:07 +03:00
|
|
|
})
|
|
|
|
|
|
|
|
dp._groupsOrder = [...this._groupsOrder]
|
|
|
|
dp._handlersCount = { ...this._handlersCount }
|
|
|
|
dp._errorHandler = this._errorHandler
|
|
|
|
dp._customStateKeyDelegate = this._customStateKeyDelegate
|
|
|
|
dp._customStorage = this._customStorage
|
|
|
|
|
|
|
|
if (children) {
|
|
|
|
this._children.forEach((it) => {
|
|
|
|
const child = it.clone(true)
|
|
|
|
dp.addChild(child as any)
|
|
|
|
})
|
|
|
|
|
|
|
|
if (this._scenes) {
|
|
|
|
Object.keys(this._scenes).forEach((key) => {
|
|
|
|
const scene = this._scenes[key].clone(true)
|
|
|
|
dp.addScene(
|
|
|
|
key as any,
|
|
|
|
scene as any,
|
|
|
|
this._scenes[key]._sceneScoped as any
|
|
|
|
)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return dp
|
2021-05-27 01:02:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get update state object for the given key.
|
|
|
|
*
|
|
|
|
* For custom keys, use prefix starting with `$` to avoid
|
|
|
|
* clashing with other keys (scene name can't start with `$`)
|
|
|
|
*
|
|
|
|
* @param key State storage key
|
|
|
|
* @template S State type, defaults to dispatcher's state type. Only checked at compile-time
|
|
|
|
*/
|
|
|
|
getState<S = State>(key: string): UpdateState<S, SceneName>
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get update state object for the given object.
|
|
|
|
*
|
|
|
|
* Equivalent to `getState(string)`, but derives
|
|
|
|
* the key with the registered {@link StateKeyDelegate},
|
|
|
|
* and since it could be async, this method is async too.
|
|
|
|
*
|
|
|
|
* @param object Object for which the state should be fetched
|
|
|
|
* @template S State type, defaults to dispatcher's state type. Only checked at compile-time
|
|
|
|
*/
|
|
|
|
getState<S = State>(
|
|
|
|
object: Parameters<StateKeyDelegate>[0]
|
|
|
|
): Promise<UpdateState<S, SceneName>>
|
|
|
|
getState<S = State>(
|
2021-05-31 23:29:26 +03:00
|
|
|
object: string | Parameters<StateKeyDelegate>[0]
|
2021-05-27 01:02:31 +03:00
|
|
|
): MaybeAsync<UpdateState<S, SceneName>> {
|
|
|
|
if (!this._storage)
|
|
|
|
throw new MtCuteArgumentError(
|
|
|
|
'Cannot use getUpdateState() filter without state storage'
|
|
|
|
)
|
|
|
|
|
2021-05-31 23:29:26 +03:00
|
|
|
if (typeof object === 'string') {
|
2021-05-27 01:02:31 +03:00
|
|
|
return new UpdateState(
|
|
|
|
this._storage!,
|
2021-05-31 23:29:26 +03:00
|
|
|
object,
|
2021-05-27 01:02:31 +03:00
|
|
|
this._scene ?? null,
|
|
|
|
this._sceneScoped,
|
|
|
|
this._customStorage
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2021-06-06 15:20:41 +03:00
|
|
|
return Promise.resolve(this._stateKeyDelegate!(object)).then((key) => {
|
|
|
|
if (!key) {
|
|
|
|
throw new MtCuteArgumentError(
|
|
|
|
'Cannot derive key from given object'
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!this._customStateKeyDelegate) {
|
|
|
|
return new UpdateState(
|
|
|
|
this._storage!,
|
|
|
|
key,
|
|
|
|
this._scene ?? null,
|
|
|
|
this._sceneScoped,
|
|
|
|
this._customStorage
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
return Promise.resolve(this._customStateKeyDelegate(object)).then(
|
|
|
|
(customKey) => {
|
|
|
|
if (!customKey) {
|
|
|
|
throw new MtCuteArgumentError(
|
|
|
|
'Cannot derive custom key from given object'
|
|
|
|
)
|
|
|
|
}
|
2021-05-27 01:02:31 +03:00
|
|
|
|
2021-05-31 23:29:26 +03:00
|
|
|
return new UpdateState(
|
|
|
|
this._storage!,
|
|
|
|
key,
|
|
|
|
this._scene ?? null,
|
|
|
|
this._sceneScoped,
|
2021-06-06 15:20:41 +03:00
|
|
|
this._customStorage,
|
|
|
|
customKey
|
2021-05-31 23:29:26 +03:00
|
|
|
)
|
|
|
|
}
|
2021-06-06 15:20:41 +03:00
|
|
|
)
|
|
|
|
})
|
2021-05-27 01:02:31 +03:00
|
|
|
}
|
|
|
|
|
2021-06-14 18:58:07 +03:00
|
|
|
/**
|
|
|
|
* Get global state.
|
|
|
|
*
|
|
|
|
* This will load the state for the given object
|
|
|
|
* ignoring local custom storage, key delegate and scene scope.
|
|
|
|
*/
|
2021-06-20 02:52:19 +03:00
|
|
|
getGlobalState<T>(
|
|
|
|
object: Parameters<StateKeyDelegate>[0]
|
|
|
|
): Promise<UpdateState<T, SceneName>> {
|
2021-06-14 18:58:07 +03:00
|
|
|
if (!this._parent) {
|
2021-06-20 02:52:19 +03:00
|
|
|
throw new MtCuteArgumentError(
|
|
|
|
'This dispatcher does not have a parent'
|
|
|
|
)
|
2021-06-14 18:58:07 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return Promise.resolve(this._stateKeyDelegate!(object)).then((key) => {
|
|
|
|
if (!key) {
|
|
|
|
throw new MtCuteArgumentError(
|
|
|
|
'Cannot derive key from given object'
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
return new UpdateState(
|
|
|
|
this._storage!,
|
|
|
|
key,
|
|
|
|
this._scene ?? null,
|
|
|
|
false
|
|
|
|
)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2021-04-23 22:35:37 +03:00
|
|
|
// addUpdateHandler convenience wrappers //
|
|
|
|
|
|
|
|
private _addKnownHandler(
|
|
|
|
name: keyof typeof handlers,
|
|
|
|
filter: any,
|
|
|
|
handler?: any,
|
|
|
|
group?: number
|
|
|
|
): void {
|
|
|
|
if (typeof handler === 'number') {
|
|
|
|
this.addUpdateHandler((handlers as any)[name](filter), handler)
|
|
|
|
} else {
|
|
|
|
this.addUpdateHandler(
|
|
|
|
(handlers as any)[name](filter, handler),
|
|
|
|
group
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-05 00:43:35 +03:00
|
|
|
// begin-codegen
|
|
|
|
|
2021-04-23 22:35:37 +03:00
|
|
|
/**
|
2021-05-05 00:43:35 +03:00
|
|
|
* Register a raw update handler without any filters
|
2021-04-23 22:35:37 +03:00
|
|
|
*
|
2021-05-05 00:43:35 +03:00
|
|
|
* @param handler Raw update handler
|
2021-04-23 22:35:37 +03:00
|
|
|
* @param group Handler group index
|
|
|
|
*/
|
|
|
|
onRawUpdate(handler: RawUpdateHandler['callback'], group?: number): void
|
|
|
|
|
|
|
|
/**
|
2021-05-05 00:43:35 +03:00
|
|
|
* Register a raw update handler with a filter
|
2021-04-23 22:35:37 +03:00
|
|
|
*
|
|
|
|
* @param filter Update filter function
|
2021-05-05 00:43:35 +03:00
|
|
|
* @param handler Raw update handler
|
2021-04-23 22:35:37 +03:00
|
|
|
* @param group Handler group index
|
|
|
|
*/
|
|
|
|
onRawUpdate(
|
|
|
|
filter: RawUpdateHandler['check'],
|
|
|
|
handler: RawUpdateHandler['callback'],
|
|
|
|
group?: number
|
|
|
|
): void
|
|
|
|
|
|
|
|
/** @internal */
|
|
|
|
onRawUpdate(filter: any, handler?: any, group?: number): void {
|
|
|
|
this._addKnownHandler('rawUpdate', filter, handler, group)
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2021-05-05 00:45:09 +03:00
|
|
|
* Register a new message handler without any filters
|
2021-04-23 22:35:37 +03:00
|
|
|
*
|
2021-05-05 00:43:35 +03:00
|
|
|
* @param handler New message handler
|
2021-04-23 22:35:37 +03:00
|
|
|
* @param group Handler group index
|
|
|
|
*/
|
2021-05-27 01:02:31 +03:00
|
|
|
onNewMessage(
|
|
|
|
handler: NewMessageHandler<
|
|
|
|
Message,
|
|
|
|
State extends never ? never : UpdateState<State, SceneName>
|
|
|
|
>['callback'],
|
|
|
|
group?: number
|
|
|
|
): void
|
2021-04-23 22:35:37 +03:00
|
|
|
|
|
|
|
/**
|
2021-05-05 00:43:35 +03:00
|
|
|
* Register a new message handler with a filter
|
2021-04-23 22:35:37 +03:00
|
|
|
*
|
|
|
|
* @param filter Update filter
|
2021-05-05 00:43:35 +03:00
|
|
|
* @param handler New message handler
|
2021-04-23 22:35:37 +03:00
|
|
|
* @param group Handler group index
|
|
|
|
*/
|
|
|
|
onNewMessage<Mod>(
|
2021-06-14 18:58:07 +03:00
|
|
|
filter: UpdateFilter<Message, Mod, State>,
|
2021-05-27 01:02:31 +03:00
|
|
|
handler: NewMessageHandler<
|
|
|
|
filters.Modify<Message, Mod>,
|
2021-06-20 02:52:19 +03:00
|
|
|
State extends never ? never : UpdateState<State, SceneName>
|
|
|
|
>['callback'],
|
|
|
|
group?: number
|
|
|
|
): void
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Register a new message handler with a filter
|
|
|
|
*
|
|
|
|
* @param filter Update filter
|
|
|
|
* @param handler New message handler
|
|
|
|
* @param group Handler group index
|
|
|
|
*/
|
|
|
|
onNewMessage<Mod>(
|
|
|
|
filter: UpdateFilter<Message, Mod>,
|
|
|
|
handler: NewMessageHandler<
|
|
|
|
filters.Modify<Message, Mod>,
|
|
|
|
State extends never ? never : UpdateState<State, SceneName>
|
2021-05-27 01:02:31 +03:00
|
|
|
>['callback'],
|
2021-04-23 22:35:37 +03:00
|
|
|
group?: number
|
|
|
|
): void
|
|
|
|
|
|
|
|
/** @internal */
|
|
|
|
onNewMessage(filter: any, handler?: any, group?: number): void {
|
|
|
|
this._addKnownHandler('newMessage', filter, handler, group)
|
|
|
|
}
|
2021-04-27 20:31:04 +03:00
|
|
|
|
2021-05-05 00:43:35 +03:00
|
|
|
/**
|
2021-05-05 00:45:09 +03:00
|
|
|
* Register an edit message handler without any filters
|
2021-05-05 00:43:35 +03:00
|
|
|
*
|
|
|
|
* @param handler Edit message handler
|
|
|
|
* @param group Handler group index
|
|
|
|
*/
|
2021-05-27 01:02:31 +03:00
|
|
|
onEditMessage(
|
|
|
|
handler: EditMessageHandler<
|
|
|
|
Message,
|
|
|
|
State extends never ? never : UpdateState<State, SceneName>
|
|
|
|
>['callback'],
|
|
|
|
group?: number
|
|
|
|
): void
|
2021-05-05 00:43:35 +03:00
|
|
|
|
2021-06-20 02:52:19 +03:00
|
|
|
/**
|
|
|
|
* Register an edit message handler with a filter
|
|
|
|
*
|
|
|
|
* @param filter Update filter
|
|
|
|
* @param handler Edit message handler
|
|
|
|
* @param group Handler group index
|
|
|
|
*/
|
|
|
|
onEditMessage<Mod>(
|
|
|
|
filter: UpdateFilter<Message, Mod, State>,
|
|
|
|
handler: EditMessageHandler<
|
|
|
|
filters.Modify<Message, Mod>,
|
|
|
|
State extends never ? never : UpdateState<State, SceneName>
|
|
|
|
>['callback'],
|
|
|
|
group?: number
|
|
|
|
): void
|
|
|
|
|
2021-05-05 00:43:35 +03:00
|
|
|
/**
|
|
|
|
* Register an edit message handler with a filter
|
|
|
|
*
|
|
|
|
* @param filter Update filter
|
|
|
|
* @param handler Edit message handler
|
|
|
|
* @param group Handler group index
|
|
|
|
*/
|
|
|
|
onEditMessage<Mod>(
|
|
|
|
filter: UpdateFilter<Message, Mod>,
|
2021-05-27 01:02:31 +03:00
|
|
|
handler: EditMessageHandler<
|
|
|
|
filters.Modify<Message, Mod>,
|
|
|
|
State extends never ? never : UpdateState<State, SceneName>
|
|
|
|
>['callback'],
|
2021-05-05 00:43:35 +03:00
|
|
|
group?: number
|
|
|
|
): void
|
|
|
|
|
|
|
|
/** @internal */
|
|
|
|
onEditMessage(filter: any, handler?: any, group?: number): void {
|
|
|
|
this._addKnownHandler('editMessage', filter, handler, group)
|
|
|
|
}
|
|
|
|
|
2021-05-16 13:06:26 +03:00
|
|
|
/**
|
|
|
|
* Register a delete message handler without any filters
|
|
|
|
*
|
|
|
|
* @param handler Delete message handler
|
|
|
|
* @param group Handler group index
|
|
|
|
*/
|
|
|
|
onDeleteMessage(
|
|
|
|
handler: DeleteMessageHandler['callback'],
|
|
|
|
group?: number
|
|
|
|
): void
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Register a delete message handler with a filter
|
|
|
|
*
|
|
|
|
* @param filter Update filter
|
|
|
|
* @param handler Delete message handler
|
|
|
|
* @param group Handler group index
|
|
|
|
*/
|
|
|
|
onDeleteMessage<Mod>(
|
|
|
|
filter: UpdateFilter<DeleteMessageUpdate, Mod>,
|
|
|
|
handler: DeleteMessageHandler<
|
|
|
|
filters.Modify<DeleteMessageUpdate, Mod>
|
|
|
|
>['callback'],
|
|
|
|
group?: number
|
|
|
|
): void
|
|
|
|
|
|
|
|
/** @internal */
|
|
|
|
onDeleteMessage(filter: any, handler?: any, group?: number): void {
|
|
|
|
this._addKnownHandler('deleteMessage', filter, handler, group)
|
|
|
|
}
|
|
|
|
|
2021-04-27 20:31:04 +03:00
|
|
|
/**
|
2021-05-05 00:45:09 +03:00
|
|
|
* Register a chat member update handler without any filters
|
2021-04-27 20:31:04 +03:00
|
|
|
*
|
2021-05-05 00:43:35 +03:00
|
|
|
* @param handler Chat member update handler
|
2021-04-27 20:31:04 +03:00
|
|
|
* @param group Handler group index
|
|
|
|
*/
|
|
|
|
onChatMemberUpdate(
|
|
|
|
handler: ChatMemberUpdateHandler['callback'],
|
|
|
|
group?: number
|
|
|
|
): void
|
|
|
|
|
|
|
|
/**
|
2021-05-05 00:43:35 +03:00
|
|
|
* Register a chat member update handler with a filter
|
2021-04-27 20:31:04 +03:00
|
|
|
*
|
|
|
|
* @param filter Update filter
|
2021-05-05 00:43:35 +03:00
|
|
|
* @param handler Chat member update handler
|
2021-04-27 20:31:04 +03:00
|
|
|
* @param group Handler group index
|
|
|
|
*/
|
|
|
|
onChatMemberUpdate<Mod>(
|
|
|
|
filter: UpdateFilter<ChatMemberUpdate, Mod>,
|
|
|
|
handler: ChatMemberUpdateHandler<
|
|
|
|
filters.Modify<ChatMemberUpdate, Mod>
|
|
|
|
>['callback'],
|
|
|
|
group?: number
|
|
|
|
): void
|
|
|
|
|
|
|
|
/** @internal */
|
|
|
|
onChatMemberUpdate(filter: any, handler?: any, group?: number): void {
|
|
|
|
this._addKnownHandler('chatMemberUpdate', filter, handler, group)
|
|
|
|
}
|
2021-04-28 23:00:51 +03:00
|
|
|
|
|
|
|
/**
|
2021-05-05 00:45:09 +03:00
|
|
|
* Register an inline query handler without any filters
|
2021-04-28 23:00:51 +03:00
|
|
|
*
|
2021-05-05 00:43:35 +03:00
|
|
|
* @param handler Inline query handler
|
2021-04-28 23:00:51 +03:00
|
|
|
* @param group Handler group index
|
|
|
|
*/
|
2021-05-04 14:07:40 +03:00
|
|
|
onInlineQuery(handler: InlineQueryHandler['callback'], group?: number): void
|
2021-04-28 23:00:51 +03:00
|
|
|
|
|
|
|
/**
|
2021-05-05 00:43:35 +03:00
|
|
|
* Register an inline query handler with a filter
|
2021-04-28 23:00:51 +03:00
|
|
|
*
|
|
|
|
* @param filter Update filter
|
2021-05-05 00:43:35 +03:00
|
|
|
* @param handler Inline query handler
|
2021-04-28 23:00:51 +03:00
|
|
|
* @param group Handler group index
|
|
|
|
*/
|
|
|
|
onInlineQuery<Mod>(
|
|
|
|
filter: UpdateFilter<InlineQuery, Mod>,
|
|
|
|
handler: InlineQueryHandler<
|
|
|
|
filters.Modify<InlineQuery, Mod>
|
|
|
|
>['callback'],
|
|
|
|
group?: number
|
|
|
|
): void
|
|
|
|
|
|
|
|
/** @internal */
|
|
|
|
onInlineQuery(filter: any, handler?: any, group?: number): void {
|
|
|
|
this._addKnownHandler('inlineQuery', filter, handler, group)
|
|
|
|
}
|
2021-05-04 14:07:40 +03:00
|
|
|
|
|
|
|
/**
|
2021-05-05 00:45:09 +03:00
|
|
|
* Register a chosen inline result handler without any filters
|
2021-05-04 14:07:40 +03:00
|
|
|
*
|
2021-05-05 00:43:35 +03:00
|
|
|
* @param handler Chosen inline result handler
|
2021-05-04 14:07:40 +03:00
|
|
|
* @param group Handler group index
|
|
|
|
*/
|
|
|
|
onChosenInlineResult(
|
|
|
|
handler: ChosenInlineResultHandler['callback'],
|
|
|
|
group?: number
|
|
|
|
): void
|
|
|
|
|
|
|
|
/**
|
2021-05-05 00:43:35 +03:00
|
|
|
* Register a chosen inline result handler with a filter
|
2021-05-04 14:07:40 +03:00
|
|
|
*
|
|
|
|
* @param filter Update filter
|
2021-05-05 00:43:35 +03:00
|
|
|
* @param handler Chosen inline result handler
|
2021-05-04 14:07:40 +03:00
|
|
|
* @param group Handler group index
|
|
|
|
*/
|
|
|
|
onChosenInlineResult<Mod>(
|
|
|
|
filter: UpdateFilter<ChosenInlineResult, Mod>,
|
|
|
|
handler: ChosenInlineResultHandler<
|
|
|
|
filters.Modify<ChosenInlineResult, Mod>
|
|
|
|
>['callback'],
|
|
|
|
group?: number
|
|
|
|
): void
|
|
|
|
|
|
|
|
/** @internal */
|
|
|
|
onChosenInlineResult(filter: any, handler?: any, group?: number): void {
|
|
|
|
this._addKnownHandler('chosenInlineResult', filter, handler, group)
|
|
|
|
}
|
2021-05-05 00:43:35 +03:00
|
|
|
|
2021-05-05 01:50:04 +03:00
|
|
|
/**
|
|
|
|
* Register a callback query handler without any filters
|
|
|
|
*
|
|
|
|
* @param handler Callback query handler
|
|
|
|
* @param group Handler group index
|
|
|
|
*/
|
|
|
|
onCallbackQuery(
|
2021-05-27 01:02:31 +03:00
|
|
|
handler: CallbackQueryHandler<
|
|
|
|
CallbackQuery,
|
|
|
|
State extends never ? never : UpdateState<State, SceneName>
|
|
|
|
>['callback'],
|
2021-05-05 01:50:04 +03:00
|
|
|
group?: number
|
|
|
|
): void
|
2021-06-20 02:52:19 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Register a callback query handler with a filter
|
|
|
|
*
|
|
|
|
* @param filter Update filter
|
|
|
|
* @param handler Callback query handler
|
|
|
|
* @param group Handler group index
|
|
|
|
*/
|
|
|
|
onCallbackQuery<Mod>(
|
|
|
|
filter: UpdateFilter<CallbackQuery, Mod, State>,
|
|
|
|
handler: CallbackQueryHandler<
|
|
|
|
filters.Modify<CallbackQuery, Mod>,
|
|
|
|
State extends never ? never : UpdateState<State, SceneName>
|
|
|
|
>['callback'],
|
|
|
|
group?: number
|
|
|
|
): void
|
2021-05-05 01:50:04 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Register a callback query handler with a filter
|
|
|
|
*
|
|
|
|
* @param filter Update filter
|
|
|
|
* @param handler Callback query handler
|
|
|
|
* @param group Handler group index
|
|
|
|
*/
|
|
|
|
onCallbackQuery<Mod>(
|
|
|
|
filter: UpdateFilter<CallbackQuery, Mod>,
|
|
|
|
handler: CallbackQueryHandler<
|
2021-05-27 01:02:31 +03:00
|
|
|
filters.Modify<CallbackQuery, Mod>,
|
|
|
|
State extends never ? never : UpdateState<State, SceneName>
|
2021-05-05 01:50:04 +03:00
|
|
|
>['callback'],
|
|
|
|
group?: number
|
|
|
|
): void
|
|
|
|
|
|
|
|
/** @internal */
|
|
|
|
onCallbackQuery(filter: any, handler?: any, group?: number): void {
|
|
|
|
this._addKnownHandler('callbackQuery', filter, handler, group)
|
|
|
|
}
|
|
|
|
|
2021-05-07 15:37:17 +03:00
|
|
|
/**
|
|
|
|
* Register a poll update handler without any filters
|
|
|
|
*
|
|
|
|
* @param handler Poll update handler
|
|
|
|
* @param group Handler group index
|
|
|
|
*/
|
|
|
|
onPollUpdate(handler: PollUpdateHandler['callback'], group?: number): void
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Register a poll update handler with a filter
|
|
|
|
*
|
|
|
|
* @param filter Update filter
|
|
|
|
* @param handler Poll update handler
|
|
|
|
* @param group Handler group index
|
|
|
|
*/
|
|
|
|
onPollUpdate<Mod>(
|
|
|
|
filter: UpdateFilter<PollUpdate, Mod>,
|
|
|
|
handler: PollUpdateHandler<filters.Modify<PollUpdate, Mod>>['callback'],
|
|
|
|
group?: number
|
|
|
|
): void
|
|
|
|
|
|
|
|
/** @internal */
|
|
|
|
onPollUpdate(filter: any, handler?: any, group?: number): void {
|
|
|
|
this._addKnownHandler('pollUpdate', filter, handler, group)
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Register a poll vote handler without any filters
|
|
|
|
*
|
|
|
|
* @param handler Poll vote handler
|
|
|
|
* @param group Handler group index
|
|
|
|
*/
|
|
|
|
onPollVote(handler: PollVoteHandler['callback'], group?: number): void
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Register a poll vote handler with a filter
|
|
|
|
*
|
|
|
|
* @param filter Update filter
|
|
|
|
* @param handler Poll vote handler
|
|
|
|
* @param group Handler group index
|
|
|
|
*/
|
|
|
|
onPollVote<Mod>(
|
|
|
|
filter: UpdateFilter<PollVoteUpdate, Mod>,
|
|
|
|
handler: PollVoteHandler<
|
|
|
|
filters.Modify<PollVoteUpdate, Mod>
|
|
|
|
>['callback'],
|
|
|
|
group?: number
|
|
|
|
): void
|
|
|
|
|
|
|
|
/** @internal */
|
|
|
|
onPollVote(filter: any, handler?: any, group?: number): void {
|
|
|
|
this._addKnownHandler('pollVote', filter, handler, group)
|
|
|
|
}
|
|
|
|
|
2021-05-08 16:35:25 +03:00
|
|
|
/**
|
|
|
|
* Register an user status update handler without any filters
|
|
|
|
*
|
|
|
|
* @param handler User status update handler
|
|
|
|
* @param group Handler group index
|
|
|
|
*/
|
|
|
|
onUserStatusUpdate(
|
|
|
|
handler: UserStatusUpdateHandler['callback'],
|
|
|
|
group?: number
|
|
|
|
): void
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Register an user status update handler with a filter
|
|
|
|
*
|
|
|
|
* @param filter Update filter
|
|
|
|
* @param handler User status update handler
|
|
|
|
* @param group Handler group index
|
|
|
|
*/
|
|
|
|
onUserStatusUpdate<Mod>(
|
|
|
|
filter: UpdateFilter<UserStatusUpdate, Mod>,
|
|
|
|
handler: UserStatusUpdateHandler<
|
|
|
|
filters.Modify<UserStatusUpdate, Mod>
|
|
|
|
>['callback'],
|
|
|
|
group?: number
|
|
|
|
): void
|
|
|
|
|
|
|
|
/** @internal */
|
|
|
|
onUserStatusUpdate(filter: any, handler?: any, group?: number): void {
|
|
|
|
this._addKnownHandler('userStatusUpdate', filter, handler, group)
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Register an user typing handler without any filters
|
|
|
|
*
|
|
|
|
* @param handler User typing handler
|
|
|
|
* @param group Handler group index
|
|
|
|
*/
|
|
|
|
onUserTyping(handler: UserTypingHandler['callback'], group?: number): void
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Register an user typing handler with a filter
|
|
|
|
*
|
|
|
|
* @param filter Update filter
|
|
|
|
* @param handler User typing handler
|
|
|
|
* @param group Handler group index
|
|
|
|
*/
|
|
|
|
onUserTyping<Mod>(
|
|
|
|
filter: UpdateFilter<UserTypingUpdate, Mod>,
|
|
|
|
handler: UserTypingHandler<
|
|
|
|
filters.Modify<UserTypingUpdate, Mod>
|
|
|
|
>['callback'],
|
|
|
|
group?: number
|
|
|
|
): void
|
|
|
|
|
|
|
|
/** @internal */
|
|
|
|
onUserTyping(filter: any, handler?: any, group?: number): void {
|
|
|
|
this._addKnownHandler('userTyping', filter, handler, group)
|
|
|
|
}
|
|
|
|
|
2021-05-05 00:43:35 +03:00
|
|
|
// end-codegen
|
2021-04-23 22:35:37 +03:00
|
|
|
}
|