mirror of
https://github.com/Maks1mS/nestjs-telegraf.git
synced 2025-03-16 06:53:44 +03:00
feat(): multiple instances support
This commit is contained in:
parent
b1a6e50f8f
commit
ccb2db0106
@ -1,4 +1,5 @@
|
|||||||
import { Inject } from '@nestjs/common';
|
import { Inject } from '@nestjs/common';
|
||||||
import { TELEGRAF_PROVIDER } from '../telegraf.constants';
|
import { getBotToken } from '../utils';
|
||||||
|
|
||||||
export const InjectBot = (): ParameterDecorator => Inject(TELEGRAF_PROVIDER);
|
export const InjectBot = (name?: string): ParameterDecorator =>
|
||||||
|
Inject(getBotToken(name));
|
||||||
|
@ -9,4 +9,8 @@ export * as Extra from 'telegraf/extra';
|
|||||||
export * from './decorators';
|
export * from './decorators';
|
||||||
export * from './interfaces';
|
export * from './interfaces';
|
||||||
export * from './telegraf.module';
|
export * from './telegraf.module';
|
||||||
export * from './telegraf.provider';
|
|
||||||
|
/**
|
||||||
|
* Backward compatibility with versions < 1.4.0
|
||||||
|
*/
|
||||||
|
export { Telegraf as TelegrafProvider } from 'telegraf';
|
||||||
|
@ -1,2 +1,3 @@
|
|||||||
export * from './context.interface';
|
export * from './context.interface';
|
||||||
export * from './telegraf-options.interface';
|
export * from './telegraf-options.interface';
|
||||||
|
export * from './update-metadata.interface';
|
||||||
|
@ -4,6 +4,7 @@ import {
|
|||||||
LaunchPollingOptions,
|
LaunchPollingOptions,
|
||||||
LaunchWebhookOptions,
|
LaunchWebhookOptions,
|
||||||
} from 'telegraf/typings/telegraf';
|
} from 'telegraf/typings/telegraf';
|
||||||
|
import { Middleware } from 'telegraf/typings/composer';
|
||||||
|
|
||||||
export interface TelegrafModuleOptions {
|
export interface TelegrafModuleOptions {
|
||||||
token: string;
|
token: string;
|
||||||
@ -12,6 +13,9 @@ export interface TelegrafModuleOptions {
|
|||||||
polling?: LaunchPollingOptions;
|
polling?: LaunchPollingOptions;
|
||||||
webhook?: LaunchWebhookOptions;
|
webhook?: LaunchWebhookOptions;
|
||||||
};
|
};
|
||||||
|
botName?: string;
|
||||||
|
include?: Function[];
|
||||||
|
middlewares?: ReadonlyArray<Middleware<any>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TelegrafOptionsFactory {
|
export interface TelegrafOptionsFactory {
|
||||||
@ -20,6 +24,7 @@ export interface TelegrafOptionsFactory {
|
|||||||
|
|
||||||
export interface TelegrafModuleAsyncOptions
|
export interface TelegrafModuleAsyncOptions
|
||||||
extends Pick<ModuleMetadata, 'imports'> {
|
extends Pick<ModuleMetadata, 'imports'> {
|
||||||
|
botName?: string;
|
||||||
useExisting?: Type<TelegrafOptionsFactory>;
|
useExisting?: Type<TelegrafOptionsFactory>;
|
||||||
useClass?: Type<TelegrafOptionsFactory>;
|
useClass?: Type<TelegrafOptionsFactory>;
|
||||||
useFactory?: (
|
useFactory?: (
|
||||||
|
6
lib/interfaces/update-metadata.interface.ts
Normal file
6
lib/interfaces/update-metadata.interface.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
export interface UpdateMetadata {
|
||||||
|
name: string;
|
||||||
|
type: string;
|
||||||
|
methodName: string;
|
||||||
|
callback?: Function | Record<string, any>;
|
||||||
|
}
|
59
lib/services/base-explorer.service.ts
Normal file
59
lib/services/base-explorer.service.ts
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
import { InstanceWrapper } from '@nestjs/core/injector/instance-wrapper';
|
||||||
|
import { Module } from '@nestjs/core/injector/module';
|
||||||
|
import { flattenDeep, groupBy, identity, isEmpty, mapValues } from 'lodash';
|
||||||
|
import { UpdateMetadata } from '../interfaces';
|
||||||
|
|
||||||
|
export class BaseExplorerService {
|
||||||
|
getModules(
|
||||||
|
modulesContainer: Map<string, Module>,
|
||||||
|
include: Function[],
|
||||||
|
): Module[] {
|
||||||
|
if (!include || isEmpty(include)) {
|
||||||
|
return [...modulesContainer.values()];
|
||||||
|
}
|
||||||
|
const whitelisted = this.includeWhitelisted(modulesContainer, include);
|
||||||
|
return whitelisted;
|
||||||
|
}
|
||||||
|
|
||||||
|
includeWhitelisted(
|
||||||
|
modulesContainer: Map<string, Module>,
|
||||||
|
include: Function[],
|
||||||
|
): Module[] {
|
||||||
|
const modules = [...modulesContainer.values()];
|
||||||
|
return modules.filter(({ metatype }) =>
|
||||||
|
include.some((item) => item === metatype),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
flatMap<T = UpdateMetadata>(
|
||||||
|
modules: Module[],
|
||||||
|
callback: (instance: InstanceWrapper, moduleRef: Module) => T | T[],
|
||||||
|
): T[] {
|
||||||
|
const invokeMap = () => {
|
||||||
|
return modules.map((moduleRef) => {
|
||||||
|
const providers = [...moduleRef.providers.values()];
|
||||||
|
return providers.map((wrapper) => callback(wrapper, moduleRef));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
return flattenDeep(invokeMap()).filter(identity);
|
||||||
|
}
|
||||||
|
|
||||||
|
groupMetadata(resolvers: UpdateMetadata[]) {
|
||||||
|
const groupByType = groupBy(
|
||||||
|
resolvers,
|
||||||
|
(metadata: UpdateMetadata) => metadata.type,
|
||||||
|
);
|
||||||
|
const groupedMetadata = mapValues(
|
||||||
|
groupByType,
|
||||||
|
(resolversArr: UpdateMetadata[]) =>
|
||||||
|
resolversArr.reduce(
|
||||||
|
(prev, curr) => ({
|
||||||
|
...prev,
|
||||||
|
[curr.name]: curr.callback,
|
||||||
|
}),
|
||||||
|
{},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return groupedMetadata;
|
||||||
|
}
|
||||||
|
}
|
2
lib/services/index.ts
Normal file
2
lib/services/index.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export * from './updates-explorer.service';
|
||||||
|
export * from './metadata-accessor.service';
|
@ -12,11 +12,11 @@ import {
|
|||||||
OnOptions,
|
OnOptions,
|
||||||
PhoneOptions,
|
PhoneOptions,
|
||||||
UpdateHookOptions,
|
UpdateHookOptions,
|
||||||
} from './decorators';
|
} from '../decorators';
|
||||||
import { DECORATORS } from './telegraf.constants';
|
import { DECORATORS } from '../telegraf.constants';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class TelegrafMetadataAccessor {
|
export class MetadataAccessorService {
|
||||||
constructor(private readonly reflector: Reflector) {}
|
constructor(private readonly reflector: Reflector) {}
|
||||||
|
|
||||||
isUpdate(target: Type<any> | Function): boolean {
|
isUpdate(target: Type<any> | Function): boolean {
|
@ -1,10 +1,12 @@
|
|||||||
import { Injectable, OnModuleInit } from '@nestjs/common';
|
import { Inject, Injectable, Logger, OnModuleInit } from '@nestjs/common';
|
||||||
import { DiscoveryService, ModuleRef } from '@nestjs/core';
|
import { DiscoveryService, ModuleRef, ModulesContainer } from '@nestjs/core';
|
||||||
import { InstanceWrapper } from '@nestjs/core/injector/instance-wrapper';
|
import { InstanceWrapper } from '@nestjs/core/injector/instance-wrapper';
|
||||||
import { MetadataScanner } from '@nestjs/core/metadata-scanner';
|
import { MetadataScanner } from '@nestjs/core/metadata-scanner';
|
||||||
import { TelegrafMetadataAccessor } from './telegraf-metadata.accessor';
|
import { MetadataAccessorService } from './metadata-accessor.service';
|
||||||
import { TelegrafProvider } from './telegraf.provider';
|
import {
|
||||||
import { TELEGRAF_PROVIDER } from './telegraf.constants';
|
TELEGRAF_BOT_NAME,
|
||||||
|
TELEGRAF_MODULE_OPTIONS,
|
||||||
|
} from '../telegraf.constants';
|
||||||
import {
|
import {
|
||||||
ActionOptions,
|
ActionOptions,
|
||||||
CashtagOptions,
|
CashtagOptions,
|
||||||
@ -17,65 +19,88 @@ import {
|
|||||||
OnOptions,
|
OnOptions,
|
||||||
PhoneOptions,
|
PhoneOptions,
|
||||||
UpdateHookOptions,
|
UpdateHookOptions,
|
||||||
} from './decorators';
|
} from '../decorators';
|
||||||
|
import { Telegraf } from 'telegraf';
|
||||||
|
import { TelegrafModuleOptions } from '../interfaces';
|
||||||
|
import { BaseExplorerService } from './base-explorer.service';
|
||||||
|
import { Module } from '@nestjs/core/injector/module';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class TelegrafExplorer implements OnModuleInit {
|
export class UpdatesExplorerService
|
||||||
|
extends BaseExplorerService
|
||||||
|
implements OnModuleInit {
|
||||||
|
private readonly logger = new Logger(UpdatesExplorerService.name);
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
@Inject(TELEGRAF_BOT_NAME)
|
||||||
|
private readonly botName: string,
|
||||||
|
@Inject(TELEGRAF_MODULE_OPTIONS)
|
||||||
|
private readonly telegrafModuleOptions: TelegrafModuleOptions,
|
||||||
private readonly moduleRef: ModuleRef,
|
private readonly moduleRef: ModuleRef,
|
||||||
private readonly discoveryService: DiscoveryService,
|
private readonly discoveryService: DiscoveryService,
|
||||||
private readonly metadataAccessor: TelegrafMetadataAccessor,
|
private readonly metadataAccessor: MetadataAccessorService,
|
||||||
private readonly metadataScanner: MetadataScanner,
|
private readonly metadataScanner: MetadataScanner,
|
||||||
) {}
|
private readonly modulesContainer: ModulesContainer,
|
||||||
|
) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
private telegraf: TelegrafProvider;
|
private bot: Telegraf<any>;
|
||||||
|
|
||||||
onModuleInit() {
|
onModuleInit(): void {
|
||||||
this.telegraf = this.moduleRef.get<TelegrafProvider>(TELEGRAF_PROVIDER, {
|
this.logger.debug(this.botName);
|
||||||
|
this.bot = this.moduleRef.get<Telegraf<any>>(this.botName, {
|
||||||
strict: false,
|
strict: false,
|
||||||
});
|
});
|
||||||
this.explore();
|
this.explore();
|
||||||
}
|
}
|
||||||
|
|
||||||
explore() {
|
explore() {
|
||||||
/**
|
const modules = this.getModules(
|
||||||
* Update providers section is only for decorators under Update decorator
|
this.modulesContainer,
|
||||||
*/
|
this.telegrafModuleOptions.include || [],
|
||||||
const updateProviders: InstanceWrapper[] = this.discoveryService
|
);
|
||||||
.getProviders()
|
const updates = this.flatMap(modules, (instance, moduleRef) =>
|
||||||
.filter((wrapper: InstanceWrapper) =>
|
this.applyUpdates(instance, moduleRef),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private applyUpdates(wrapper: InstanceWrapper, moduleRef: Module) {
|
||||||
|
const { instance } = wrapper;
|
||||||
|
if (!instance) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
const prototype = Object.getPrototypeOf(instance);
|
||||||
|
|
||||||
|
const providers: InstanceWrapper[] = this.discoveryService.getProviders();
|
||||||
|
const updateProviders: InstanceWrapper[] = providers.filter(
|
||||||
|
(wrapper: InstanceWrapper) =>
|
||||||
this.metadataAccessor.isUpdate(wrapper.metatype),
|
this.metadataAccessor.isUpdate(wrapper.metatype),
|
||||||
);
|
);
|
||||||
|
|
||||||
updateProviders.forEach((wrapper: InstanceWrapper) => {
|
updateProviders.forEach((wrapper: InstanceWrapper) => {
|
||||||
const { instance } = wrapper;
|
const { instance } = wrapper;
|
||||||
|
if (!instance) {
|
||||||
this.metadataScanner.scanFromPrototype(
|
return undefined;
|
||||||
instance,
|
}
|
||||||
Object.getPrototypeOf(instance),
|
this.metadataScanner.scanFromPrototype(instance, prototype, (name) => {
|
||||||
(key: string) => {
|
if (this.metadataAccessor.isUpdateHook(instance[name])) {
|
||||||
if (this.metadataAccessor.isUpdateHook(instance[key])) {
|
const metadata = this.metadataAccessor.getUpdateHookMetadata(
|
||||||
const metadata = this.metadataAccessor.getUpdateHookMetadata(
|
instance[name],
|
||||||
instance[key],
|
);
|
||||||
);
|
this.handleUpdateHook(instance, name, metadata);
|
||||||
this.handleUpdateHook(instance, key, metadata);
|
}
|
||||||
}
|
});
|
||||||
},
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const providers: InstanceWrapper[] = this.discoveryService.getProviders();
|
|
||||||
|
|
||||||
providers.forEach((wrapper: InstanceWrapper) => {
|
providers.forEach((wrapper: InstanceWrapper) => {
|
||||||
const { instance } = wrapper;
|
const { instance } = wrapper;
|
||||||
|
|
||||||
if (!instance) {
|
if (!instance) {
|
||||||
return;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.metadataScanner.scanFromPrototype(
|
this.metadataScanner.scanFromPrototype(
|
||||||
instance,
|
instance,
|
||||||
Object.getPrototypeOf(instance),
|
prototype,
|
||||||
(key: string) => {
|
(key: string) => {
|
||||||
if (this.metadataAccessor.isTelegrafUse(instance[key])) {
|
if (this.metadataAccessor.isTelegrafUse(instance[key])) {
|
||||||
this.handleTelegrafUse(instance, key);
|
this.handleTelegrafUse(instance, key);
|
||||||
@ -146,19 +171,19 @@ export class TelegrafExplorer implements OnModuleInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleUpdateHook(instance: object, key: string, metadata: UpdateHookOptions) {
|
handleUpdateHook(instance: object, key: string, metadata: UpdateHookOptions) {
|
||||||
this.telegraf.on(metadata.updateType, instance[key].bind(instance));
|
this.bot.on(metadata.updateType, instance[key].bind(instance));
|
||||||
}
|
}
|
||||||
|
|
||||||
handleTelegrafUse(instance: object, key: string) {
|
handleTelegrafUse(instance: object, key: string) {
|
||||||
this.telegraf.use(instance[key].bind(instance));
|
this.bot.use(instance[key].bind(instance));
|
||||||
}
|
}
|
||||||
|
|
||||||
handleTelegrafOn(instance: object, key: string, metadata: OnOptions) {
|
handleTelegrafOn(instance: object, key: string, metadata: OnOptions) {
|
||||||
this.telegraf.on(metadata.updateTypes, instance[key].bind(instance));
|
this.bot.on(metadata.updateTypes, instance[key].bind(instance));
|
||||||
}
|
}
|
||||||
|
|
||||||
handleTelegrafHears(instance: object, key: string, metadata: HearsOptions) {
|
handleTelegrafHears(instance: object, key: string, metadata: HearsOptions) {
|
||||||
this.telegraf.hears(metadata.triggers, instance[key].bind(instance));
|
this.bot.hears(metadata.triggers, instance[key].bind(instance));
|
||||||
}
|
}
|
||||||
|
|
||||||
handleTelegrafCommand(
|
handleTelegrafCommand(
|
||||||
@ -166,25 +191,25 @@ export class TelegrafExplorer implements OnModuleInit {
|
|||||||
key: string,
|
key: string,
|
||||||
metadata: CommandOptions,
|
metadata: CommandOptions,
|
||||||
) {
|
) {
|
||||||
this.telegraf.command(metadata.commands, instance[key].bind(instance));
|
this.bot.command(metadata.commands, instance[key].bind(instance));
|
||||||
}
|
}
|
||||||
|
|
||||||
handleTelegrafStart(instance: object, key: string) {
|
handleTelegrafStart(instance: object, key: string) {
|
||||||
this.telegraf.start(instance[key].bind(instance));
|
this.bot.start(instance[key].bind(instance));
|
||||||
}
|
}
|
||||||
|
|
||||||
handleTelegrafHelp(instance: object, key: string) {
|
handleTelegrafHelp(instance: object, key: string) {
|
||||||
this.telegraf.help(instance[key].bind(instance));
|
this.bot.help(instance[key].bind(instance));
|
||||||
}
|
}
|
||||||
|
|
||||||
handleTelegrafSettings(instance: object, key: string) {
|
handleTelegrafSettings(instance: object, key: string) {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
this.telegraf.settings(instance[key].bind(instance));
|
this.bot.settings(instance[key].bind(instance));
|
||||||
}
|
}
|
||||||
|
|
||||||
handleTelegrafEntity(instance: object, key: string, metadata: EntityOptions) {
|
handleTelegrafEntity(instance: object, key: string, metadata: EntityOptions) {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
this.telegraf.entity(metadata.entity, instance[key].bind(instance));
|
this.bot.entity(metadata.entity, instance[key].bind(instance));
|
||||||
}
|
}
|
||||||
|
|
||||||
handleTelegrafMention(
|
handleTelegrafMention(
|
||||||
@ -193,12 +218,12 @@ export class TelegrafExplorer implements OnModuleInit {
|
|||||||
metadata: MentionOptions,
|
metadata: MentionOptions,
|
||||||
) {
|
) {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
this.telegraf.mention(metadata.username, instance[key].bind(instance));
|
this.bot.mention(metadata.username, instance[key].bind(instance));
|
||||||
}
|
}
|
||||||
|
|
||||||
handleTelegrafPhone(instance: object, key: string, metadata: PhoneOptions) {
|
handleTelegrafPhone(instance: object, key: string, metadata: PhoneOptions) {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
this.telegraf.phone(metadata.phone, instance[key].bind(instance));
|
this.bot.phone(metadata.phone, instance[key].bind(instance));
|
||||||
}
|
}
|
||||||
|
|
||||||
handleTelegrafHashtag(
|
handleTelegrafHashtag(
|
||||||
@ -207,7 +232,7 @@ export class TelegrafExplorer implements OnModuleInit {
|
|||||||
metadata: HashtagOptions,
|
metadata: HashtagOptions,
|
||||||
) {
|
) {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
this.telegraf.hashtag(metadata.hashtag, instance[key].bind(instance));
|
this.bot.hashtag(metadata.hashtag, instance[key].bind(instance));
|
||||||
}
|
}
|
||||||
|
|
||||||
handleTelegrafCashtag(
|
handleTelegrafCashtag(
|
||||||
@ -216,11 +241,11 @@ export class TelegrafExplorer implements OnModuleInit {
|
|||||||
metadata: CashtagOptions,
|
metadata: CashtagOptions,
|
||||||
) {
|
) {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
this.telegraf.cashtag(metadata.cashtag, instance[key].bind(instance));
|
this.bot.cashtag(metadata.cashtag, instance[key].bind(instance));
|
||||||
}
|
}
|
||||||
|
|
||||||
handleTelegrafAction(instance: object, key: string, metadata: ActionOptions) {
|
handleTelegrafAction(instance: object, key: string, metadata: ActionOptions) {
|
||||||
this.telegraf.action(metadata.triggers, instance[key].bind(instance));
|
this.bot.action(metadata.triggers, instance[key].bind(instance));
|
||||||
}
|
}
|
||||||
|
|
||||||
handleTelegrafInlineQuery(
|
handleTelegrafInlineQuery(
|
||||||
@ -230,16 +255,13 @@ export class TelegrafExplorer implements OnModuleInit {
|
|||||||
) {
|
) {
|
||||||
if (metadata.triggers) {
|
if (metadata.triggers) {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
this.telegraf.inlineQuery(
|
this.bot.inlineQuery(metadata.triggers, instance[key].bind(instance));
|
||||||
metadata.triggers,
|
|
||||||
instance[key].bind(instance),
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
this.telegraf.on(metadata.updateType, instance[key].bind(instance));
|
this.bot.on(metadata.updateType, instance[key].bind(instance));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleTelegrafGameQuery(instance: object, key: string) {
|
handleTelegrafGameQuery(instance: object, key: string) {
|
||||||
this.telegraf.gameQuery(instance[key].bind(instance));
|
this.bot.gameQuery(instance[key].bind(instance));
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,56 +1,120 @@
|
|||||||
import { DiscoveryModule } from '@nestjs/core';
|
import { DiscoveryModule, ModuleRef } from '@nestjs/core';
|
||||||
import { Module, DynamicModule, Provider, Type } from '@nestjs/common';
|
import {
|
||||||
|
Module,
|
||||||
|
DynamicModule,
|
||||||
|
Provider,
|
||||||
|
Type,
|
||||||
|
Global,
|
||||||
|
Inject,
|
||||||
|
OnApplicationShutdown,
|
||||||
|
Logger,
|
||||||
|
} from '@nestjs/common';
|
||||||
import {
|
import {
|
||||||
TelegrafModuleOptions,
|
TelegrafModuleOptions,
|
||||||
TelegrafModuleAsyncOptions,
|
TelegrafModuleAsyncOptions,
|
||||||
TelegrafOptionsFactory,
|
TelegrafOptionsFactory,
|
||||||
} from './interfaces';
|
} from './interfaces';
|
||||||
import {
|
import {
|
||||||
|
TELEGRAF_BOT_NAME,
|
||||||
TELEGRAF_MODULE_OPTIONS,
|
TELEGRAF_MODULE_OPTIONS,
|
||||||
TELEGRAF_PROVIDER,
|
|
||||||
} from './telegraf.constants';
|
} from './telegraf.constants';
|
||||||
import { TelegrafMetadataAccessor } from './telegraf-metadata.accessor';
|
import { MetadataAccessorService, UpdatesExplorerService } from './services';
|
||||||
import { TelegrafExplorer } from './telegraf.explorer';
|
import { getBotToken } from './utils';
|
||||||
import { TelegrafProvider } from './telegraf.provider';
|
import { Telegraf } from 'telegraf';
|
||||||
|
import { defer } from 'rxjs';
|
||||||
|
|
||||||
|
@Global()
|
||||||
@Module({
|
@Module({
|
||||||
imports: [DiscoveryModule],
|
imports: [DiscoveryModule],
|
||||||
providers: [TelegrafMetadataAccessor, TelegrafExplorer],
|
providers: [UpdatesExplorerService, MetadataAccessorService],
|
||||||
})
|
})
|
||||||
export class TelegrafCoreModule {
|
export class TelegrafCoreModule implements OnApplicationShutdown {
|
||||||
|
private readonly logger = new Logger(TelegrafCoreModule.name);
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
@Inject(TELEGRAF_BOT_NAME) private readonly botName: string,
|
||||||
|
private readonly moduleRef: ModuleRef,
|
||||||
|
) {
|
||||||
|
this.logger.debug(botName);
|
||||||
|
}
|
||||||
|
|
||||||
public static forRoot(options: TelegrafModuleOptions): DynamicModule {
|
public static forRoot(options: TelegrafModuleOptions): DynamicModule {
|
||||||
const telegrafProvider = {
|
const telegrafBotName = getBotToken(options.botName);
|
||||||
provide: TELEGRAF_PROVIDER,
|
|
||||||
useClass: TelegrafProvider,
|
const telegrafBotProvider = {
|
||||||
inject: [TELEGRAF_MODULE_OPTIONS],
|
provide: telegrafBotName,
|
||||||
|
useFactory: async (): Promise<any> =>
|
||||||
|
await defer(async () => {
|
||||||
|
const bot = new Telegraf(options.token);
|
||||||
|
this.applyBotMiddlewares(bot, options.middlewares);
|
||||||
|
await bot.launch(options.launchOptions);
|
||||||
|
return bot;
|
||||||
|
}).toPromise(),
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
module: TelegrafCoreModule,
|
module: TelegrafCoreModule,
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: TELEGRAF_MODULE_OPTIONS, useValue: options },
|
{
|
||||||
telegrafProvider,
|
provide: TELEGRAF_MODULE_OPTIONS,
|
||||||
|
useValue: options,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provide: TELEGRAF_BOT_NAME,
|
||||||
|
useValue: telegrafBotName,
|
||||||
|
},
|
||||||
|
telegrafBotProvider,
|
||||||
],
|
],
|
||||||
exports: [telegrafProvider],
|
exports: [telegrafBotProvider],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public static forRootAsync(
|
public static forRootAsync(
|
||||||
options: TelegrafModuleAsyncOptions,
|
options: TelegrafModuleAsyncOptions,
|
||||||
): DynamicModule {
|
): DynamicModule {
|
||||||
const telegrafProvider = {
|
const telegrafBotName = getBotToken(options.botName);
|
||||||
provide: TELEGRAF_PROVIDER,
|
|
||||||
useClass: TelegrafProvider,
|
const telegrafBotProvider = {
|
||||||
|
provide: telegrafBotName,
|
||||||
|
useFactory: async (
|
||||||
|
telegrafModuleOptions: TelegrafModuleOptions,
|
||||||
|
): Promise<any> => {
|
||||||
|
const { botName, ...telegrafOptions } = telegrafModuleOptions;
|
||||||
|
|
||||||
|
return await defer(async () => {
|
||||||
|
const bot = new Telegraf(telegrafOptions.token);
|
||||||
|
this.applyBotMiddlewares(bot, telegrafOptions.middlewares);
|
||||||
|
await bot.launch(telegrafOptions.launchOptions);
|
||||||
|
return bot;
|
||||||
|
}).toPromise();
|
||||||
|
},
|
||||||
inject: [TELEGRAF_MODULE_OPTIONS],
|
inject: [TELEGRAF_MODULE_OPTIONS],
|
||||||
};
|
};
|
||||||
|
|
||||||
const asyncProviders = this.createAsyncProviders(options);
|
const asyncProviders = this.createAsyncProviders(options);
|
||||||
return {
|
return {
|
||||||
module: TelegrafCoreModule,
|
module: TelegrafCoreModule,
|
||||||
imports: options.imports,
|
imports: options.imports,
|
||||||
providers: [...asyncProviders, telegrafProvider],
|
providers: [
|
||||||
exports: [telegrafProvider],
|
...asyncProviders,
|
||||||
|
{
|
||||||
|
provide: TELEGRAF_BOT_NAME,
|
||||||
|
useValue: telegrafBotName,
|
||||||
|
},
|
||||||
|
telegrafBotProvider,
|
||||||
|
],
|
||||||
|
exports: [telegrafBotProvider],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static applyBotMiddlewares(bot, middlewares) {
|
||||||
|
if (middlewares) {
|
||||||
|
middlewares.forEach((middleware) => {
|
||||||
|
bot.use(middleware);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static createAsyncProviders(
|
private static createAsyncProviders(
|
||||||
options: TelegrafModuleAsyncOptions,
|
options: TelegrafModuleAsyncOptions,
|
||||||
): Provider[] {
|
): Provider[] {
|
||||||
@ -88,4 +152,9 @@ export class TelegrafCoreModule {
|
|||||||
inject,
|
inject,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async onApplicationShutdown(): Promise<void> {
|
||||||
|
const bot = this.moduleRef.get<any>(this.botName);
|
||||||
|
bot && (await bot.stop());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
export const TELEGRAF_MODULE_OPTIONS = 'TELEGRAF_MODULE_OPTIONS';
|
export const TELEGRAF_MODULE_OPTIONS = 'TELEGRAF_MODULE_OPTIONS';
|
||||||
export const TELEGRAF_PROVIDER = 'TelegrafProvider';
|
export const TELEGRAF_BOT_NAME = 'TELEGRAF_BOT_NAME';
|
||||||
|
export const DEFAULT_BOT_NAME = 'DEFAULT_BOT_NAME';
|
||||||
|
|
||||||
export const DECORATORS_PREFIX = 'TELEGRAF';
|
export const DECORATORS_PREFIX = 'TELEGRAF';
|
||||||
export const DECORATORS = {
|
export const DECORATORS = {
|
||||||
|
@ -1,37 +0,0 @@
|
|||||||
import {
|
|
||||||
Injectable,
|
|
||||||
Inject,
|
|
||||||
OnApplicationBootstrap,
|
|
||||||
Logger,
|
|
||||||
OnApplicationShutdown,
|
|
||||||
} from '@nestjs/common';
|
|
||||||
import { Telegraf } from 'telegraf';
|
|
||||||
import { Context, TelegrafModuleOptions } from './interfaces';
|
|
||||||
import { TELEGRAF_MODULE_OPTIONS } from './telegraf.constants';
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class TelegrafProvider extends Telegraf<Context>
|
|
||||||
implements OnApplicationBootstrap, OnApplicationShutdown {
|
|
||||||
private logger = new Logger('Telegraf');
|
|
||||||
private readonly launchOptions;
|
|
||||||
|
|
||||||
constructor(@Inject(TELEGRAF_MODULE_OPTIONS) options: TelegrafModuleOptions) {
|
|
||||||
super(options.token, options.options);
|
|
||||||
this.launchOptions = options.launchOptions;
|
|
||||||
}
|
|
||||||
|
|
||||||
async onApplicationBootstrap() {
|
|
||||||
this.catch((err, ctx: Context) => {
|
|
||||||
this.logger.error(
|
|
||||||
`Encountered an error for ${ctx.updateType} update type`,
|
|
||||||
err,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
await this.launch(this.launchOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
async onApplicationShutdown() {
|
|
||||||
await this.stop();
|
|
||||||
}
|
|
||||||
}
|
|
7
lib/utils/get-bot-token.util.ts
Normal file
7
lib/utils/get-bot-token.util.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import { DEFAULT_BOT_NAME } from '../telegraf.constants';
|
||||||
|
|
||||||
|
export function getBotToken(name?: string) {
|
||||||
|
return name && name !== DEFAULT_BOT_NAME
|
||||||
|
? `${name}_BOT_NAME`
|
||||||
|
: DEFAULT_BOT_NAME;
|
||||||
|
}
|
1
lib/utils/index.ts
Normal file
1
lib/utils/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './get-bot-token.util';
|
Loading…
Reference in New Issue
Block a user