diff --git a/packages/dispatcher/package.json b/packages/dispatcher/package.json index 0e5e2682..89b21329 100644 --- a/packages/dispatcher/package.json +++ b/packages/dispatcher/package.json @@ -15,6 +15,7 @@ "@mtcute/tl": "~1.131.0", "@mtcute/core": "^1.0.0", "@mtcute/client": "^1.0.0", + "events": "^3.2.0", "debug": "^4.3.1" } } diff --git a/packages/dispatcher/scripts/generate.js b/packages/dispatcher/scripts/generate.js index 966170da..1125f21f 100644 --- a/packages/dispatcher/scripts/generate.js +++ b/packages/dispatcher/scripts/generate.js @@ -76,6 +76,8 @@ function toSentence(type, stype = 'inline') { if (stype === 'inline') { return `${name[0].match(/[aeiouy]/i) ? 'an' : 'a'} ${name} handler` + } else if (stype === 'plain') { + return `${name} handler` } else { return `${name[0].toUpperCase()}${name.substr(1)} handler` } @@ -188,12 +190,23 @@ function generateBuilders() { function generateDispatcher() { const lines = [] + const declareLines = [] const imports = ['UpdateHandler'] types.forEach((type) => { imports.push(`${type.handlerTypeName}Handler`) if (type.updateType === 'IGNORE') { + declareLines.push(` + /** + * Register a plain old ${toSentence(type, 'plain')} + * + * @param name Event name + * @param handler ${toSentence(type, 'full')} + */ + on(name: '${type.typeName}', handler: ${type.handlerTypeName}Handler['callback']): this +`) + lines.push(` /** * Register ${toSentence(type)} without any filters @@ -222,6 +235,16 @@ function generateDispatcher() { } `) } else { + declareLines.push(` + /** + * Register a plain old ${toSentence(type, 'plain')} + * + * @param name Event name + * @param handler ${toSentence(type, 'full')} + */ + on(name: '${type.typeName}', handler: ${type.handlerTypeName}Handler['callback']): this + +`) lines.push(` /** * Register ${toSentence(type)} without any filters @@ -269,6 +292,7 @@ ${type.state ? ` replaceSections('dispatcher.ts', { codegen: lines.join('\n'), + 'codegen-declare': declareLines.join('\n'), 'codegen-imports': 'import {\n' + imports.map((i) => ` ${i},\n`).join('') + diff --git a/packages/dispatcher/src/dispatcher.ts b/packages/dispatcher/src/dispatcher.ts index db74a379..59647c88 100644 --- a/packages/dispatcher/src/dispatcher.ts +++ b/packages/dispatcher/src/dispatcher.ts @@ -40,6 +40,7 @@ import { DeleteMessageUpdate } from './updates/delete-message-update' import { IStateStorage, UpdateState, StateKeyDelegate } from './state' import { defaultStateKeyDelegate } from './state' import { PropagationAction } from './propagation' +import EventEmitter from 'events' const noop = () => {} @@ -136,10 +137,126 @@ Object.keys(PARSERS).forEach((upd: keyof typeof PARSERS) => { HANDLER_TYPE_TO_UPDATE[handler].push(upd) }) +export declare interface Dispatcher< + State = never, + SceneName extends string = string +> { + on( + name: 'update', + handler: (update: UpdateInfo & T) => void + ): this + + // begin-codegen-declare + + /** + * Register a plain old raw update handler + * + * @param name Event name + * @param handler Raw update handler + */ + on(name: 'raw', handler: RawUpdateHandler['callback']): this + + /** + * Register a plain old new message handler + * + * @param name Event name + * @param handler New message handler + */ + on(name: 'new_message', handler: NewMessageHandler['callback']): this + + /** + * Register a plain old edit message handler + * + * @param name Event name + * @param handler Edit message handler + */ + on(name: 'edit_message', handler: EditMessageHandler['callback']): this + + /** + * Register a plain old delete message handler + * + * @param name Event name + * @param handler Delete message handler + */ + on(name: 'delete_message', handler: DeleteMessageHandler['callback']): this + + /** + * Register a plain old chat member update handler + * + * @param name Event name + * @param handler Chat member update handler + */ + on(name: 'chat_member', handler: ChatMemberUpdateHandler['callback']): this + + /** + * Register a plain old inline query handler + * + * @param name Event name + * @param handler Inline query handler + */ + on(name: 'inline_query', handler: InlineQueryHandler['callback']): this + + /** + * Register a plain old chosen inline result handler + * + * @param name Event name + * @param handler Chosen inline result handler + */ + on( + name: 'chosen_inline_result', + handler: ChosenInlineResultHandler['callback'] + ): this + + /** + * Register a plain old callback query handler + * + * @param name Event name + * @param handler Callback query handler + */ + on(name: 'callback_query', handler: CallbackQueryHandler['callback']): this + + /** + * Register a plain old poll update handler + * + * @param name Event name + * @param handler Poll update handler + */ + on(name: 'poll', handler: PollUpdateHandler['callback']): this + + /** + * Register a plain old poll vote handler + * + * @param name Event name + * @param handler Poll vote handler + */ + on(name: 'poll_vote', handler: PollVoteHandler['callback']): this + + /** + * Register a plain old user status update handler + * + * @param name Event name + * @param handler User status update handler + */ + on(name: 'user_status', handler: UserStatusUpdateHandler['callback']): this + + /** + * Register a plain old user typing handler + * + * @param name Event name + * @param handler User typing handler + */ + on(name: 'user_typing', handler: UserTypingHandler['callback']): this + + // end-codegen-declare +} + /** * Updates dispatcher */ -export class Dispatcher { +export class Dispatcher< + State = never, + SceneName extends string = string +> extends EventEmitter { private _groups: Record< number, Record @@ -205,6 +322,8 @@ export class Dispatcher { storage?: IStateStorage | StateKeyDelegate, key?: StateKeyDelegate ) { + super() + if (client) { if (client instanceof TelegramClient) { this.bindToClient(client) @@ -421,6 +540,15 @@ export class Dispatcher { } if (shouldDispatch) { + if (update && !isRawMessage) { + this.emit('raw', update, users, chats) + } + + if (parsedType) { + this.emit('update', updateInfo) + this.emit(parsedType, parsed) + } + outer: for (const grp of this._groupsOrder) { const group = this._groups[grp] diff --git a/packages/dispatcher/src/handler.ts b/packages/dispatcher/src/handler.ts index 40677531..5a381845 100644 --- a/packages/dispatcher/src/handler.ts +++ b/packages/dispatcher/src/handler.ts @@ -30,10 +30,7 @@ type ParsedUpdateHandler = BaseUpdateHandler< (update: Update, state: State) => MaybeAsync > -export type UpdateInfo = T extends ParsedUpdateHandler< - infer K, - infer Q -> +export type UpdateInfo = T extends ParsedUpdateHandler ? { readonly type: K readonly data: Q