refactor(dispatcher): codegen for update types
i'm just too lazy to be bothered with pasting that. also, i forgot to implement builder for editMessage, teehee~
This commit is contained in:
parent
fd92121b14
commit
1c1aed147a
5 changed files with 394 additions and 42 deletions
272
packages/dispatcher/scripts/generate.js
Normal file
272
packages/dispatcher/scripts/generate.js
Normal file
|
@ -0,0 +1,272 @@
|
|||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const prettier = require('prettier')
|
||||
const {
|
||||
snakeToCamel,
|
||||
camelToPascal,
|
||||
camelToSnake,
|
||||
} = require('../../tl/scripts/common')
|
||||
|
||||
function parseUpdateTypes() {
|
||||
const lines = fs
|
||||
.readFileSync(path.join(__dirname, 'update-types.txt'), 'utf-8')
|
||||
.split('\n')
|
||||
.map((it) => it.trim())
|
||||
.filter((it) => it && it[0] !== '#')
|
||||
|
||||
const ret = []
|
||||
|
||||
for (const line of lines) {
|
||||
const m = line.match(/^([a-z_]+)(?:: ([a-zA-Z]+))? = ([a-zA-Z]+)$/)
|
||||
if (!m) throw new Error(`invalid syntax: ${line}`)
|
||||
ret.push({
|
||||
typeName: m[1],
|
||||
handlerTypeName: m[2] || camelToPascal(snakeToCamel(m[1])),
|
||||
updateType: m[3],
|
||||
funcName: m[2]
|
||||
? m[2][0].toLowerCase() + m[2].substr(1)
|
||||
: snakeToCamel(m[1]),
|
||||
})
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
function replaceSections(filename, sections) {
|
||||
let lines = fs
|
||||
.readFileSync(path.join(__dirname, '../src', filename), 'utf-8')
|
||||
.split('\n')
|
||||
|
||||
const findMarker = (marker) => {
|
||||
const idx = lines.findIndex((line) => line.trim() === `// ${marker}`)
|
||||
if (idx === -1) throw new Error(marker + ' not found')
|
||||
return idx
|
||||
}
|
||||
|
||||
for (const [name, content] of Object.entries(sections)) {
|
||||
const start = findMarker(`begin-${name}`)
|
||||
const end = findMarker(`end-${name}`)
|
||||
|
||||
if (start > end) throw new Error('begin is after end')
|
||||
|
||||
lines.splice(start + 1, end - start - 1, content)
|
||||
}
|
||||
|
||||
fs.writeFileSync(path.join(__dirname, '../src', filename), lines.join('\n'))
|
||||
}
|
||||
|
||||
const types = parseUpdateTypes()
|
||||
console.log(types)
|
||||
|
||||
async function formatFile(filename) {
|
||||
const targetFile = path.join(__dirname, '../src/', filename)
|
||||
const prettierConfig = await prettier.resolveConfig(targetFile)
|
||||
let fullSource = await fs.promises.readFile(targetFile, 'utf-8')
|
||||
fullSource = await prettier.format(fullSource, {
|
||||
...(prettierConfig || {}),
|
||||
filepath: targetFile,
|
||||
})
|
||||
await fs.promises.writeFile(targetFile, fullSource)
|
||||
}
|
||||
|
||||
function toSentence(type, stype = 'inline') {
|
||||
const name = camelToSnake(type.handlerTypeName)
|
||||
.toLowerCase()
|
||||
.replace(/_/g, ' ')
|
||||
|
||||
if (stype === 'inline') {
|
||||
return `${name[0].match(/[aeiouy]/i) ? 'an' : 'a'} ${name} handler`
|
||||
} else {
|
||||
return `${name[0].toUpperCase()}${name.substr(1)} handler`
|
||||
}
|
||||
}
|
||||
|
||||
function generateBuilders() {
|
||||
const lines = []
|
||||
const imports = ['UpdateHandler']
|
||||
|
||||
types.forEach((type) => {
|
||||
imports.push(`${type.handlerTypeName}Handler`)
|
||||
|
||||
if (type.updateType === 'IGNORE') {
|
||||
lines.push(`
|
||||
/**
|
||||
* Create ${toSentence(type)}
|
||||
*
|
||||
* @param handler ${toSentence(type, 'full')}
|
||||
*/
|
||||
export function ${type.funcName}(
|
||||
handler: ${type.handlerTypeName}Handler['callback']
|
||||
): ${type.handlerTypeName}Handler
|
||||
|
||||
/**
|
||||
* Create ${toSentence(type)} with a filter
|
||||
*
|
||||
* @param filter Predicate to check the update against
|
||||
* @param handler ${toSentence(type, 'full')}
|
||||
*/
|
||||
export function ${type.funcName}(
|
||||
filter: ${type.handlerTypeName}Handler['check'],
|
||||
handler: ${type.handlerTypeName}Handler['callback']
|
||||
): ${type.handlerTypeName}Handler
|
||||
|
||||
/** @internal */
|
||||
export function ${type.funcName}(filter: any, handler?: any): ${
|
||||
type.handlerTypeName
|
||||
}Handler {
|
||||
return _create('${type.typeName}', filter, handler)
|
||||
}
|
||||
`)
|
||||
} else {
|
||||
lines.push(`
|
||||
/**
|
||||
* Create ${toSentence(type)}
|
||||
*
|
||||
* @param handler ${toSentence(type, 'full')}
|
||||
*/
|
||||
export function ${type.funcName}(
|
||||
handler: ${type.handlerTypeName}Handler['callback']
|
||||
): ${type.handlerTypeName}Handler
|
||||
|
||||
/**
|
||||
* Create ${toSentence(type)} with a filter
|
||||
*
|
||||
* @param filter Update filter
|
||||
* @param handler ${toSentence(type, 'full')}
|
||||
*/
|
||||
export function ${type.funcName}<Mod>(
|
||||
filter: UpdateFilter<${type.updateType}, Mod>,
|
||||
handler: ${type.handlerTypeName}Handler<
|
||||
filters.Modify<${type.updateType}, Mod>
|
||||
>['callback']
|
||||
): ${type.handlerTypeName}Handler
|
||||
|
||||
export function ${type.funcName}(
|
||||
filter: any,
|
||||
handler?: any
|
||||
): ${type.handlerTypeName}Handler {
|
||||
return _create('${type.typeName}', filter, handler)
|
||||
}
|
||||
`)
|
||||
}
|
||||
})
|
||||
|
||||
replaceSections('builders.ts', {
|
||||
codegen: lines.join('\n'),
|
||||
'codegen-imports':
|
||||
'import {\n' +
|
||||
imports.map((i) => ` ${i},\n`).join('') +
|
||||
"} from './handler'",
|
||||
})
|
||||
}
|
||||
|
||||
function generateHandler() {
|
||||
const lines = []
|
||||
const names = ['RawUpdateHandler']
|
||||
|
||||
// imports must be added manually because yeah
|
||||
|
||||
types.forEach((type) => {
|
||||
if (type.updateType === 'IGNORE') return
|
||||
|
||||
lines.push(
|
||||
`export type ${type.handlerTypeName}Handler<T = ${type.updateType}> = ParsedUpdateHandler<'${type.typeName}', T>`
|
||||
)
|
||||
names.push(`${type.handlerTypeName}Handler`)
|
||||
})
|
||||
|
||||
replaceSections('handler.ts', {
|
||||
codegen:
|
||||
lines.join('\n') +
|
||||
'\n\nexport type UpdateHandler = \n' +
|
||||
names.map((i) => ` | ${i}\n`).join(''),
|
||||
})
|
||||
}
|
||||
|
||||
function generateDispatcher() {
|
||||
const lines = []
|
||||
const imports = ['UpdateHandler']
|
||||
|
||||
types.forEach((type) => {
|
||||
imports.push(`${type.handlerTypeName}Handler`)
|
||||
|
||||
if (type.updateType === 'IGNORE') {
|
||||
lines.push(`
|
||||
/**
|
||||
* Register ${toSentence(type)} without any filters
|
||||
*
|
||||
* @param handler ${toSentence(type, 'full')}
|
||||
* @param group Handler group index
|
||||
*/
|
||||
on${type.handlerTypeName}(handler: ${type.handlerTypeName}Handler['callback'], group?: number): void
|
||||
|
||||
/**
|
||||
* Register ${toSentence(type)} with a filter
|
||||
*
|
||||
* @param filter Update filter function
|
||||
* @param handler ${toSentence(type, 'full')}
|
||||
* @param group Handler group index
|
||||
*/
|
||||
on${type.handlerTypeName}(
|
||||
filter: ${type.handlerTypeName}Handler['check'],
|
||||
handler: ${type.handlerTypeName}Handler['callback'],
|
||||
group?: number
|
||||
): void
|
||||
|
||||
/** @internal */
|
||||
on${type.handlerTypeName}(filter: any, handler?: any, group?: number): void {
|
||||
this._addKnownHandler('${type.funcName}', filter, handler, group)
|
||||
}
|
||||
`)
|
||||
} else {
|
||||
lines.push(`
|
||||
/**
|
||||
* Register ${toSentence(type)} without any filters
|
||||
*
|
||||
* @param handler ${toSentence(type, 'full')}
|
||||
* @param group Handler group index
|
||||
* @internal
|
||||
*/
|
||||
on${type.handlerTypeName}(handler: ${type.handlerTypeName}Handler['callback'], group?: number): void
|
||||
|
||||
/**
|
||||
* Register ${toSentence(type)} with a filter
|
||||
*
|
||||
* @param filter Update filter
|
||||
* @param handler ${toSentence(type, 'full')}
|
||||
* @param group Handler group index
|
||||
*/
|
||||
on${type.handlerTypeName}<Mod>(
|
||||
filter: UpdateFilter<${type.updateType}, Mod>,
|
||||
handler: ${type.handlerTypeName}Handler<filters.Modify<${type.updateType}, Mod>>['callback'],
|
||||
group?: number
|
||||
): void
|
||||
|
||||
/** @internal */
|
||||
on${type.handlerTypeName}(filter: any, handler?: any, group?: number): void {
|
||||
this._addKnownHandler('${type.funcName}', filter, handler, group)
|
||||
}
|
||||
`)
|
||||
}
|
||||
})
|
||||
|
||||
replaceSections('dispatcher.ts', {
|
||||
codegen: lines.join('\n'),
|
||||
'codegen-imports':
|
||||
'import {\n' +
|
||||
imports.map((i) => ` ${i},\n`).join('') +
|
||||
"} from './handler'",
|
||||
})
|
||||
}
|
||||
|
||||
async function main() {
|
||||
generateBuilders()
|
||||
generateHandler()
|
||||
generateDispatcher()
|
||||
|
||||
await formatFile('builders.ts')
|
||||
await formatFile('handler.ts')
|
||||
await formatFile('dispatcher.ts')
|
||||
}
|
||||
|
||||
main().catch(console.error)
|
8
packages/dispatcher/scripts/update-types.txt
Normal file
8
packages/dispatcher/scripts/update-types.txt
Normal file
|
@ -0,0 +1,8 @@
|
|||
# format: type_name[: handler_type_name] = update_type
|
||||
# IGNORE as update_type disables filters modification
|
||||
raw: RawUpdate = IGNORE
|
||||
new_message = Message
|
||||
edit_message = Message
|
||||
chat_member: ChatMemberUpdate = ChatMemberUpdate
|
||||
inline_query = InlineQuery
|
||||
chosen_inline_result = ChosenInlineResult
|
|
@ -1,11 +1,14 @@
|
|||
// begin-codegen-imports
|
||||
import {
|
||||
ChatMemberUpdateHandler,
|
||||
ChosenInlineResultHandler,
|
||||
InlineQueryHandler,
|
||||
NewMessageHandler,
|
||||
RawUpdateHandler,
|
||||
UpdateHandler,
|
||||
RawUpdateHandler,
|
||||
NewMessageHandler,
|
||||
EditMessageHandler,
|
||||
ChatMemberUpdateHandler,
|
||||
InlineQueryHandler,
|
||||
ChosenInlineResultHandler,
|
||||
} from './handler'
|
||||
// end-codegen-imports
|
||||
import { filters, UpdateFilter } from './filters'
|
||||
import { InlineQuery, Message } from '@mtcute/client'
|
||||
import { ChatMemberUpdate } from './updates'
|
||||
|
@ -31,44 +34,47 @@ function _create<T extends UpdateHandler>(
|
|||
}
|
||||
|
||||
export namespace handlers {
|
||||
// begin-codegen
|
||||
|
||||
/**
|
||||
* Create a {@link RawUpdateHandler}
|
||||
* Create a raw update handler
|
||||
*
|
||||
* @param handler Update handler
|
||||
* @param handler Raw update handler
|
||||
*/
|
||||
export function rawUpdate(
|
||||
handler: RawUpdateHandler['callback']
|
||||
): RawUpdateHandler
|
||||
|
||||
/**
|
||||
* Create a {@link RawUpdateHandler} with a predicate
|
||||
* Create a raw update handler with a filter
|
||||
*
|
||||
* @param filter Predicate to check the update against
|
||||
* @param handler Update handler
|
||||
* @param handler Raw update handler
|
||||
*/
|
||||
export function rawUpdate(
|
||||
filter: RawUpdateHandler['check'],
|
||||
handler: RawUpdateHandler['callback']
|
||||
): RawUpdateHandler
|
||||
|
||||
/** @internal */
|
||||
export function rawUpdate(filter: any, handler?: any): RawUpdateHandler {
|
||||
return _create('raw', filter, handler)
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link NewMessageHandler}
|
||||
* Create a new message handler
|
||||
*
|
||||
* @param handler Message handler
|
||||
* @param handler New message handler
|
||||
*/
|
||||
export function newMessage(
|
||||
handler: NewMessageHandler['callback']
|
||||
): NewMessageHandler
|
||||
|
||||
/**
|
||||
* Create a {@link NewMessageHandler} with a filter
|
||||
* Create a new message handler with a filter
|
||||
*
|
||||
* @param filter Message update filter
|
||||
* @param handler Message handler
|
||||
* @param filter Update filter
|
||||
* @param handler New message handler
|
||||
*/
|
||||
export function newMessage<Mod>(
|
||||
filter: UpdateFilter<Message, Mod>,
|
||||
|
@ -80,7 +86,34 @@ export namespace handlers {
|
|||
}
|
||||
|
||||
/**
|
||||
* Create a {@link ChatMemberUpdateHandler}
|
||||
* Create an edit message handler
|
||||
*
|
||||
* @param handler Edit message handler
|
||||
*/
|
||||
export function editMessage(
|
||||
handler: EditMessageHandler['callback']
|
||||
): EditMessageHandler
|
||||
|
||||
/**
|
||||
* Create an edit message handler with a filter
|
||||
*
|
||||
* @param filter Update filter
|
||||
* @param handler Edit message handler
|
||||
*/
|
||||
export function editMessage<Mod>(
|
||||
filter: UpdateFilter<Message, Mod>,
|
||||
handler: EditMessageHandler<filters.Modify<Message, Mod>>['callback']
|
||||
): EditMessageHandler
|
||||
|
||||
export function editMessage(
|
||||
filter: any,
|
||||
handler?: any
|
||||
): EditMessageHandler {
|
||||
return _create('edit_message', filter, handler)
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a chat member update handler
|
||||
*
|
||||
* @param handler Chat member update handler
|
||||
*/
|
||||
|
@ -89,9 +122,9 @@ export namespace handlers {
|
|||
): ChatMemberUpdateHandler
|
||||
|
||||
/**
|
||||
* Create a {@link ChatMemberUpdateHandler} with a filter
|
||||
* Create a chat member update handler with a filter
|
||||
*
|
||||
* @param filter Chat member update filter
|
||||
* @param filter Update filter
|
||||
* @param handler Chat member update handler
|
||||
*/
|
||||
export function chatMemberUpdate<Mod>(
|
||||
|
@ -118,9 +151,9 @@ export namespace handlers {
|
|||
): InlineQueryHandler
|
||||
|
||||
/**
|
||||
* Create an inline query with a filter
|
||||
* Create an inline query handler with a filter
|
||||
*
|
||||
* @param filter Inline query update filter
|
||||
* @param filter Update filter
|
||||
* @param handler Inline query handler
|
||||
*/
|
||||
export function inlineQuery<Mod>(
|
||||
|
@ -149,7 +182,7 @@ export namespace handlers {
|
|||
/**
|
||||
* Create a chosen inline result handler with a filter
|
||||
*
|
||||
* @param filter Chosen inline result filter
|
||||
* @param filter Update filter
|
||||
* @param handler Chosen inline result handler
|
||||
*/
|
||||
export function chosenInlineResult<Mod>(
|
||||
|
@ -165,4 +198,6 @@ export namespace handlers {
|
|||
): ChosenInlineResultHandler {
|
||||
return _create('chosen_inline_result', filter, handler)
|
||||
}
|
||||
|
||||
// end-codegen
|
||||
}
|
||||
|
|
|
@ -11,14 +11,17 @@ import {
|
|||
StopChildrenPropagation,
|
||||
StopPropagation,
|
||||
} from './propagation'
|
||||
// begin-codegen-imports
|
||||
import {
|
||||
ChatMemberUpdateHandler,
|
||||
ChosenInlineResultHandler,
|
||||
InlineQueryHandler,
|
||||
NewMessageHandler,
|
||||
RawUpdateHandler,
|
||||
UpdateHandler,
|
||||
RawUpdateHandler,
|
||||
NewMessageHandler,
|
||||
EditMessageHandler,
|
||||
ChatMemberUpdateHandler,
|
||||
InlineQueryHandler,
|
||||
ChosenInlineResultHandler,
|
||||
} from './handler'
|
||||
// end-codegen-imports
|
||||
import { filters, UpdateFilter } from './filters'
|
||||
import { handlers } from './builders'
|
||||
import { ChatMemberUpdate } from './updates'
|
||||
|
@ -381,19 +384,21 @@ export class Dispatcher {
|
|||
}
|
||||
}
|
||||
|
||||
// begin-codegen
|
||||
|
||||
/**
|
||||
* Register a raw update handler
|
||||
* Register a raw update handler without any filters
|
||||
*
|
||||
* @param handler Handler function
|
||||
* @param handler Raw update handler
|
||||
* @param group Handler group index
|
||||
*/
|
||||
onRawUpdate(handler: RawUpdateHandler['callback'], group?: number): void
|
||||
|
||||
/**
|
||||
* Register a filtered raw update handler
|
||||
* Register a raw update handler with a filter
|
||||
*
|
||||
* @param filter Update filter function
|
||||
* @param handler Handler function
|
||||
* @param handler Raw update handler
|
||||
* @param group Handler group index
|
||||
*/
|
||||
onRawUpdate(
|
||||
|
@ -408,19 +413,19 @@ export class Dispatcher {
|
|||
}
|
||||
|
||||
/**
|
||||
* Register a message handler without any filters.
|
||||
* Register a new message handler without any filters.
|
||||
*
|
||||
* @param handler Message handler
|
||||
* @param handler New message handler
|
||||
* @param group Handler group index
|
||||
* @internal
|
||||
*/
|
||||
onNewMessage(handler: NewMessageHandler['callback'], group?: number): void
|
||||
|
||||
/**
|
||||
* Register a message handler with a given filter
|
||||
* Register a new message handler with a filter
|
||||
*
|
||||
* @param filter Update filter
|
||||
* @param handler Message handler
|
||||
* @param handler New message handler
|
||||
* @param group Handler group index
|
||||
*/
|
||||
onNewMessage<Mod>(
|
||||
|
@ -434,10 +439,37 @@ export class Dispatcher {
|
|||
this._addKnownHandler('newMessage', filter, handler, group)
|
||||
}
|
||||
|
||||
/**
|
||||
* Register an edit message handler without any filters.
|
||||
*
|
||||
* @param handler Edit message handler
|
||||
* @param group Handler group index
|
||||
* @internal
|
||||
*/
|
||||
onEditMessage(handler: EditMessageHandler['callback'], group?: number): void
|
||||
|
||||
/**
|
||||
* 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>,
|
||||
handler: EditMessageHandler<filters.Modify<Message, Mod>>['callback'],
|
||||
group?: number
|
||||
): void
|
||||
|
||||
/** @internal */
|
||||
onEditMessage(filter: any, handler?: any, group?: number): void {
|
||||
this._addKnownHandler('editMessage', filter, handler, group)
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a chat member update handler without any filters.
|
||||
*
|
||||
* @param handler Update handler
|
||||
* @param handler Chat member update handler
|
||||
* @param group Handler group index
|
||||
* @internal
|
||||
*/
|
||||
|
@ -447,10 +479,10 @@ export class Dispatcher {
|
|||
): void
|
||||
|
||||
/**
|
||||
* Register a message handler with a given filter
|
||||
* Register a chat member update handler with a filter
|
||||
*
|
||||
* @param filter Update filter
|
||||
* @param handler Update handler
|
||||
* @param handler Chat member update handler
|
||||
* @param group Handler group index
|
||||
*/
|
||||
onChatMemberUpdate<Mod>(
|
||||
|
@ -469,17 +501,17 @@ export class Dispatcher {
|
|||
/**
|
||||
* Register an inline query handler without any filters.
|
||||
*
|
||||
* @param handler Update handler
|
||||
* @param handler Inline query handler
|
||||
* @param group Handler group index
|
||||
* @internal
|
||||
*/
|
||||
onInlineQuery(handler: InlineQueryHandler['callback'], group?: number): void
|
||||
|
||||
/**
|
||||
* Register an inline query handler with a given filter
|
||||
* Register an inline query handler with a filter
|
||||
*
|
||||
* @param filter Update filter
|
||||
* @param handler Update handler
|
||||
* @param handler Inline query handler
|
||||
* @param group Handler group index
|
||||
*/
|
||||
onInlineQuery<Mod>(
|
||||
|
@ -498,7 +530,7 @@ export class Dispatcher {
|
|||
/**
|
||||
* Register a chosen inline result handler without any filters.
|
||||
*
|
||||
* @param handler Update handler
|
||||
* @param handler Chosen inline result handler
|
||||
* @param group Handler group index
|
||||
* @internal
|
||||
*/
|
||||
|
@ -508,10 +540,10 @@ export class Dispatcher {
|
|||
): void
|
||||
|
||||
/**
|
||||
* Register an inline query handler with a given filter
|
||||
* Register a chosen inline result handler with a filter
|
||||
*
|
||||
* @param filter Update filter
|
||||
* @param handler Update handler
|
||||
* @param handler Chosen inline result handler
|
||||
* @param group Handler group index
|
||||
*/
|
||||
onChosenInlineResult<Mod>(
|
||||
|
@ -526,4 +558,6 @@ export class Dispatcher {
|
|||
onChosenInlineResult(filter: any, handler?: any, group?: number): void {
|
||||
this._addKnownHandler('chosenInlineResult', filter, handler, group)
|
||||
}
|
||||
|
||||
// end-codegen
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ export type RawUpdateHandler = BaseUpdateHandler<
|
|||
) => MaybeAsync<boolean>
|
||||
>
|
||||
|
||||
// begin-codegen
|
||||
export type NewMessageHandler<T = Message> = ParsedUpdateHandler<
|
||||
'new_message',
|
||||
T
|
||||
|
@ -68,3 +69,5 @@ export type UpdateHandler =
|
|||
| ChatMemberUpdateHandler
|
||||
| InlineQueryHandler
|
||||
| ChosenInlineResultHandler
|
||||
|
||||
// end-codegen
|
||||
|
|
Loading…
Reference in a new issue