Skip to content

Instantly share code, notes, and snippets.

@ppabcd
Last active December 24, 2023 09:44
Show Gist options
  • Save ppabcd/df8c880812e87ffc9e25d2490303ca83 to your computer and use it in GitHub Desktop.
Save ppabcd/df8c880812e87ffc9e25d2490303ca83 to your computer and use it in GitHub Desktop.
Example of decorator @command, @Listener and @callbackQuery for telegram bot with grammY and inversify
/* eslint-disable @typescript-eslint/no-explicit-any */
import {ICommand} from "../core/ICommand"
import {IListener} from "../core/IListener"
import {ICallbackQuery} from "../core/ICallbackQuery"
import {kylaContainer} from "../../../di/inversify.config"
import {Container, injectable as originalInjectable} from "inversify"
import {promises as fs} from "fs"
import path from "path"
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const commandTypes: Array<new (...args: any[]) => ICommand> = []
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const listenerTypes: Array<new (...args: any[]) => IListener> = []
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const callbackQueryTypes: Array<new (...args: any[]) => ICallbackQuery> = []
export function registerDecorator<T>(
container: Container,
typeArray: Array<new (...args: any[]) => T>,
constructor: new (...args: any[]) => T
) {
originalInjectable()(constructor)
container.bind(constructor).toSelf().inSingletonScope()
typeArray.push(constructor)
}
export function command(container: Container = kylaContainer) {
return function <T extends { new(...args: any[]): ICommand }>(constructor: T) {
registerDecorator(container, commandTypes, constructor)
}
}
export function listener(container: Container = kylaContainer) {
return function <T extends { new(...args: any[]): IListener }>(constructor: T) {
registerDecorator(container, listenerTypes, constructor)
}
}
export function callbackQuery(container: Container = kylaContainer) {
return function <T extends { new(...args: any[]): ICallbackQuery }>(constructor: T) {
registerDecorator(container, callbackQueryTypes, constructor)
}
}
export function getCommands(container: Container = kylaContainer): ICommand[] {
return commandTypes.map(constructor => container.get(constructor))
}
export function getListeners(container: Container = kylaContainer): IListener[] {
return listenerTypes.map(constructor => container.get(constructor))
}
export function getCallbackQueries(container: Container = kylaContainer): ICallbackQuery[] {
return callbackQueryTypes.map(constructor => container.get(constructor))
}
export async function autoDiscover(directory: string) {
const entries = await fs.readdir(directory, {withFileTypes: true})
for (const entry of entries) {
const entryPath = path.join(directory, entry.name)
if (entry.isDirectory()) {
// If the entry is a directory, recursively explore it
await autoDiscover(entryPath)
} else if (entry.isFile() && (entry.name.endsWith(".ts") || entry.name.endsWith(".js"))) {
// If the entry is a file with a .ts or .js extension, import it
await import(entryPath)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment