nestjs-telegraf/lib/telegraf-core.module.ts

188 lines
5.1 KiB
TypeScript
Raw Normal View History

2021-01-02 01:27:01 +03:00
import { DiscoveryModule, ModuleRef } from '@nestjs/core';
import {
Module,
DynamicModule,
Provider,
Type,
Global,
Inject,
OnApplicationShutdown,
2021-01-02 02:00:10 +03:00
Logger,
2021-01-02 01:27:01 +03:00
} from '@nestjs/common';
2020-03-19 16:21:35 +03:00
import {
TelegrafModuleOptions,
TelegrafModuleAsyncOptions,
TelegrafOptionsFactory,
2021-01-02 02:00:10 +03:00
Context,
2020-03-19 16:21:35 +03:00
} from './interfaces';
import {
2021-01-02 01:27:01 +03:00
TELEGRAF_BOT_NAME,
2020-03-19 16:21:35 +03:00
TELEGRAF_MODULE_OPTIONS,
} from './telegraf.constants';
2021-01-02 01:27:01 +03:00
import { MetadataAccessorService, UpdatesExplorerService } from './services';
import { getBotToken } from './utils';
import { Telegraf } from 'telegraf';
import { defer } from 'rxjs';
2020-03-19 16:21:35 +03:00
2021-01-02 01:27:01 +03:00
@Global()
2020-03-19 16:21:35 +03:00
@Module({
imports: [DiscoveryModule],
2021-01-02 01:27:01 +03:00
providers: [UpdatesExplorerService, MetadataAccessorService],
2020-03-19 16:21:35 +03:00
})
2021-01-02 01:27:01 +03:00
export class TelegrafCoreModule implements OnApplicationShutdown {
2021-01-02 02:00:10 +03:00
private static logger = new Logger(TelegrafCoreModule.name);
2021-01-02 01:27:01 +03:00
constructor(
@Inject(TELEGRAF_BOT_NAME) private readonly botName: string,
private readonly moduleRef: ModuleRef,
2021-01-02 01:32:49 +03:00
) {}
2021-01-02 01:27:01 +03:00
2020-03-19 16:21:35 +03:00
public static forRoot(options: TelegrafModuleOptions): DynamicModule {
2021-01-02 01:27:01 +03:00
const telegrafBotName = getBotToken(options.botName);
const telegrafBotProvider = {
provide: telegrafBotName,
useFactory: async (): Promise<any> =>
await defer(async () => {
2021-01-02 02:00:10 +03:00
const bot = new Telegraf<Context>(options.token);
2021-01-02 01:27:01 +03:00
this.applyBotMiddlewares(bot, options.middlewares);
2021-01-02 02:00:10 +03:00
/**
* Backward compatibility with versions < 1.4.0,
* TODO: remove that on next major release,
* after exception filters has been added
*/
if (!options.disableGlobalCatch) {
bot.catch((err, ctx: Context) => {
this.logger.error(
`Encountered an error for ${ctx.updateType} update type`,
err,
);
});
}
2021-01-02 01:27:01 +03:00
await bot.launch(options.launchOptions);
return bot;
}).toPromise(),
2020-03-19 19:23:51 +03:00
};
2021-01-02 01:27:01 +03:00
2020-03-19 16:21:35 +03:00
return {
module: TelegrafCoreModule,
2020-03-19 19:23:51 +03:00
providers: [
2021-01-02 01:27:01 +03:00
{
provide: TELEGRAF_MODULE_OPTIONS,
useValue: options,
},
{
provide: TELEGRAF_BOT_NAME,
useValue: telegrafBotName,
},
telegrafBotProvider,
2020-03-19 19:23:51 +03:00
],
2021-01-02 01:27:01 +03:00
exports: [telegrafBotProvider],
2020-03-19 16:21:35 +03:00
};
}
public static forRootAsync(
options: TelegrafModuleAsyncOptions,
): DynamicModule {
2021-01-02 01:27:01 +03:00
const telegrafBotName = getBotToken(options.botName);
const telegrafBotProvider = {
provide: telegrafBotName,
useFactory: async (
telegrafModuleOptions: TelegrafModuleOptions,
): Promise<any> => {
const { botName, ...telegrafOptions } = telegrafModuleOptions;
return await defer(async () => {
2021-01-02 02:00:10 +03:00
const bot = new Telegraf<Context>(telegrafOptions.token);
2021-01-02 01:27:01 +03:00
this.applyBotMiddlewares(bot, telegrafOptions.middlewares);
2021-01-02 02:00:10 +03:00
/**
* Backward compatibility with versions < 1.4.0,
* TODO: remove that on next major release,
* after exception filters has been added
*/
if (!telegrafOptions.disableGlobalCatch) {
bot.catch((err, ctx: Context) => {
this.logger.error(
`Encountered an error for ${ctx.updateType} update type`,
err,
);
});
}
2021-01-02 01:27:01 +03:00
await bot.launch(telegrafOptions.launchOptions);
return bot;
}).toPromise();
},
2020-03-19 16:21:35 +03:00
inject: [TELEGRAF_MODULE_OPTIONS],
};
2021-01-02 01:27:01 +03:00
2020-03-19 16:21:35 +03:00
const asyncProviders = this.createAsyncProviders(options);
return {
module: TelegrafCoreModule,
imports: options.imports,
2021-01-02 01:27:01 +03:00
providers: [
...asyncProviders,
{
provide: TELEGRAF_BOT_NAME,
useValue: telegrafBotName,
},
telegrafBotProvider,
],
exports: [telegrafBotProvider],
2020-03-19 16:21:35 +03:00
};
}
2021-01-02 01:27:01 +03:00
private static applyBotMiddlewares(bot, middlewares) {
if (middlewares) {
middlewares.forEach((middleware) => {
bot.use(middleware);
});
}
}
2020-03-19 16:21:35 +03:00
private static createAsyncProviders(
options: TelegrafModuleAsyncOptions,
): Provider[] {
if (options.useExisting || options.useFactory) {
return [this.createAsyncOptionsProvider(options)];
}
const useClass = options.useClass as Type<TelegrafOptionsFactory>;
return [
this.createAsyncOptionsProvider(options),
{
provide: useClass,
useClass,
},
];
}
private static createAsyncOptionsProvider(
options: TelegrafModuleAsyncOptions,
): Provider {
if (options.useFactory) {
return {
provide: TELEGRAF_MODULE_OPTIONS,
useFactory: options.useFactory,
inject: options.inject || [],
};
}
// `as Type<TelegrafOptionsFactory>` is a workaround for microsoft/TypeScript#31603
const inject = [
(options.useClass || options.useExisting) as Type<TelegrafOptionsFactory>,
];
return {
provide: TELEGRAF_MODULE_OPTIONS,
useFactory: async (optionsFactory: TelegrafOptionsFactory) =>
await optionsFactory.createTelegrafOptions(),
inject,
};
}
2021-01-02 01:27:01 +03:00
async onApplicationShutdown(): Promise<void> {
const bot = this.moduleRef.get<any>(this.botName);
bot && (await bot.stop());
}
2020-03-19 16:21:35 +03:00
}