NestJS의 Telegram 봇에서 재귀적 상황에 맞는 작업을 사용하여 짧은 명령 및 예제 만들기
62683 단어 kaufmanbottelegramnestjsrecursive
연결
https://github.com/EndyKaufman/kaufman-bot - 봇의 소스 코드
https://telegram.me/DevelopKaufmanBot - 전보의 현재 봇
작품 설명
이 게시물에서는 빠른 명령 호출에 필요한 짧은 명령 모듈의 생성에 대해 설명합니다.
게시물의 끝에서 재귀 컨텍스트 작업을 사용하는 예를 제공합니다.
짧은 명령 추가
이 명령 모듈은 다른 명령 처리기를 실행하기 위해 짧은 버전을 사용해야 합니다.
nx 라이브러리 생성
npm run -- nx g @nrwl/nest:lib short-commands/server
endy@endy-virtual-machine:~/Projects/current/kaufman-bot$ npm run -- nx g @nrwl/nest:lib short-commands/server
> [email protected] nx
> nx "g" "@nrwl/nest:lib" "short-commands/server"
CREATE libs/short-commands/server/README.md
CREATE libs/short-commands/server/.babelrc
CREATE libs/short-commands/server/src/index.ts
CREATE libs/short-commands/server/tsconfig.json
CREATE libs/short-commands/server/tsconfig.lib.json
UPDATE tsconfig.base.json
CREATE libs/short-commands/server/project.json
UPDATE workspace.json
CREATE libs/short-commands/server/.eslintrc.json
CREATE libs/short-commands/server/jest.config.js
CREATE libs/short-commands/server/tsconfig.spec.json
CREATE libs/short-commands/server/src/lib/short-commands-server.module.ts
ShortCommandsConfig 추가
libs/short-commands/server/src/lib/short-commands-config/short-commands.config.ts
export const SHORT_COMMANDS_CONFIG = Symbol('SHORT_COMMANDS_CONFIG');
export interface ShortCommandsConfig {
title: string;
name: string;
descriptions: string;
usage: string[];
spyWords: string[];
commands: { [langCode: string]: { [text: string]: string } };
}
ShortCommandsService 추가
libs/short-commands/server/src/lib/short-commands-services/short-commands.service.ts
import {
BotCommandsEnum,
BotCommandsProvider,
BotCommandsProviderActionMsg,
BotCommandsProviderActionResultType,
BotСommandsToolsService,
OnBeforeBotCommands,
} from '@kaufman-bot/core/server';
import { DEFAULT_LANGUAGE } from '@kaufman-bot/language-swither/server';
import { Inject, Injectable, Logger } from '@nestjs/common';
import { getText } from 'class-validator-multi-lang';
import { TranslatesService, TranslatesStorage } from 'nestjs-translates';
import {
ShortCommandsConfig,
SHORT_COMMANDS_CONFIG,
} from '../short-commands-config/short-commands.config';
@Injectable()
export class ShortCommandsService
implements BotCommandsProvider, OnBeforeBotCommands
{
private readonly logger = new Logger(ShortCommandsService.name);
constructor(
@Inject(SHORT_COMMANDS_CONFIG)
private readonly shortCommandsConfig: ShortCommandsConfig,
private readonly botСommandsToolsService: BotСommandsToolsService,
private readonly translatesStorage: TranslatesStorage,
private readonly translatesService: TranslatesService
) {}
async onBeforeBotCommands<
TMsg extends BotCommandsProviderActionMsg = BotCommandsProviderActionMsg
>(msg: TMsg): Promise<TMsg> {
const locale = msg.from.language_code;
const text = msg.text;
if (locale && this.shortCommandsConfig) {
const shortCommands = this.shortCommandsConfig.commands[locale] || {};
const matchedCommands = Object.keys(shortCommands)
.filter((commands) =>
this.botСommandsToolsService.checkCommands(text, commands.split('|'))
)
.map((commands) => shortCommands[commands]);
if (matchedCommands?.length > 0) {
msg.text = matchedCommands[0];
}
}
return msg;
}
async onHelp<
TMsg extends BotCommandsProviderActionMsg = BotCommandsProviderActionMsg
>(msg: TMsg): Promise<BotCommandsProviderActionResultType<TMsg>> {
return await this.onMessage({
...msg,
text: `${this.shortCommandsConfig.name} ${BotCommandsEnum.help}`,
});
}
async onMessage<
TMsg extends BotCommandsProviderActionMsg = BotCommandsProviderActionMsg
>(msg: TMsg): Promise<BotCommandsProviderActionResultType<TMsg>> {
let locale = msg.from?.language_code;
if (
!locale ||
!Object.keys(this.translatesStorage.translates).find((key) =>
locale?.includes(key)
)
) {
locale = DEFAULT_LANGUAGE;
}
const spyWord = this.shortCommandsConfig.spyWords.find((spyWord) =>
this.botСommandsToolsService.checkCommands(msg.text, [spyWord], locale)
);
if (spyWord) {
if (
this.botСommandsToolsService.checkCommands(
msg.text,
[BotCommandsEnum.help],
locale
)
) {
return {
type: 'markdown',
message: msg,
markdown: this.botСommandsToolsService.generateHelpMessage({
locale,
name: this.shortCommandsConfig.title,
descriptions: this.shortCommandsConfig.descriptions,
usage: this.shortCommandsConfig.usage,
}),
};
}
if (
this.botСommandsToolsService.checkCommands(
msg.text,
[BotCommandsEnum.state],
locale
)
) {
const detectedLang =
Object.keys(this.shortCommandsConfig.commands).filter(
(langCode) =>
this.shortCommandsConfig.commands[langCode] && langCode === locale
)[0] || DEFAULT_LANGUAGE;
const commands = this.shortCommandsConfig.commands[detectedLang] || {};
const aliases = Object.keys(commands);
const markdown = [
`__${this.translatesService.translate(
getText('List of short commands:'),
locale
)}__`,
...aliases.map((alias) =>
locale
? [
`${this.translatesService.translate(
getText('alias'),
locale
)}: ${alias
.split('|')
.map((u) => `_${u}_`)
.join(', ')}`,
`${this.translatesService.translate(
getText('command'),
locale
)}: ${commands[alias]}\n`,
].join('\n')
: ''
),
]
.filter(Boolean)
.join('\n');
return {
type: 'markdown',
message: msg,
markdown,
};
}
this.logger.warn(`Unhandled commands for text: "${msg.text}"`);
this.logger.debug(msg);
}
return null;
}
}
ShortCommandsModule
libs/짧은 명령/서버/src/lib/짧은 명령.module.ts
import {
BotCommandsModule,
BOT_COMMANDS_PROVIDER,
} from '@kaufman-bot/core/server';
import { DynamicModule, Module } from '@nestjs/common';
import { getText } from 'class-validator-multi-lang';
import { TranslatesModule } from 'nestjs-translates';
import {
ShortCommandsConfig,
SHORT_COMMANDS_CONFIG,
} from './short-commands-config/short-commands.config';
import { ShortCommandsService } from './short-commands-services/short-commands.service';
@Module({
imports: [TranslatesModule, BotCommandsModule],
exports: [TranslatesModule, BotCommandsModule],
})
export class ShortCommandsModule {
static forRoot(config: Pick<ShortCommandsConfig, 'commands'>): DynamicModule {
return {
module: ShortCommandsModule,
providers: [
{
provide: SHORT_COMMANDS_CONFIG,
useValue: <ShortCommandsConfig>{
title: getText('Short commands'),
name: 'scmd',
usage: [getText('scmd state'), getText('scmd help')],
descriptions: getText(
'Shortened versions of commands for quick launch'
),
spyWords: [getText('scmd')],
commands: config.commands,
},
},
{
provide: BOT_COMMANDS_PROVIDER,
useClass: ShortCommandsService,
},
],
};
}
}
파일 준비
npm run generate
포 편집기로 모든 단어 번역
po 사전을 json으로 변환하기 위한 파일 준비
npm run generate
ShortCommandsModule을 AppModule에 추가
앱/서버/src/app/app.module.ts
@Module({
imports: [
...
BotCommandsModule.forRoot(),
LanguageSwitherModule.forRoot(),
DebugMessagesModule.forRoot(),
ShortCommandsModule.forRoot({
commands: {
en: {
joke: 'get jokes',
'quote|thought|wisdom': 'get quotes',
'facts|fact|history': 'get facts',
},
ru: {
'joke|jokes|шутка|шутки|пошути|шути|рассмеши|смешинки|смешинка':
'get jokes',
'quote|thought|wisdom|цитата|цитаты|цитируй|мысль|мудрость|залечи':
'get quotes',
'facts|fact|history|факт|факты|история': 'get facts',
},
},
}),
...
],
...
})
export class AppModule {}
텔레그램 봇의 새로운 로직 확인
일반적인 도움말 메시지
짧은 명령의 상태 가져오기
짧은 명령 중 하나를 사용해보십시오
재귀적 상황에 맞는 작업
나는 이 로직을 생성하는 모든 프로세스를 작성하지 않습니다. 훨씬 더 많은 코드가 있기 때문에 농담 명령에 대한 간단한 예제에 대한 사용법에 대해서만 작성합니다.
JokesGeneratorService 업데이트
libs/jokes-generator/server/src/lib/jokes-generator-services/jokes-generator.service.ts
import {
BotCommandsEnum,
BotCommandsProvider,
BotCommandsProviderActionMsg,
BotCommandsProviderActionResultType,
BotСommandsToolsService,
OnContextBotCommands,
} from '@kaufman-bot/core/server';
import { ScraperService, ScraperConfig,
SCRAPER_CONFIG, } from '@kaufman-bot/html-scraper/server';
import { DEFAULT_LANGUAGE } from '@kaufman-bot/language-swither/server';
import { Injectable } from '@nestjs/common';
import { TranslatesStorage } from 'nestjs-translates';
@Injectable()
export class JokesGeneratorService
implements BotCommandsProvider, OnContextBotCommands
{
constructor(
@Inject(SCRAPER_CONFIG)
private readonly scraperConfig: ScraperConfig,
private readonly scraperService: ScraperService,
private readonly botСommandsToolsService: BotСommandsToolsService,
private readonly translatesStorage: TranslatesStorage
) {}
async onContextBotCommands<
TMsg extends BotCommandsProviderActionMsg = BotCommandsProviderActionMsg
>(msg: TMsg): Promise<BotCommandsProviderActionResultType<TMsg>> {
const locale = msg.from?.language_code;
if (
this.botСommandsToolsService.checkCommands(
msg.text,
[getText('more'), getText('next')],
locale
)
) {
msg.text = `${BotCommandsEnum.get} ${this.scraperConfig.name}`;
return {
type: 'message',
message: msg,
};
}
return null;
}
async onHelp<
TMsg extends BotCommandsProviderActionMsg = BotCommandsProviderActionMsg
>(msg: TMsg) {
const locale = msg.from?.language_code;
if (
Object.keys(this.translatesStorage.translates).find((key) =>
locale?.includes(key)
) &&
!locale?.includes(DEFAULT_LANGUAGE)
) {
return null;
}
return await this.scraperService.onHelp(msg);
}
async onMessage<
TMsg extends BotCommandsProviderActionMsg = BotCommandsProviderActionMsg
>(msg: TMsg): Promise<BotCommandsProviderActionResultType<TMsg>> {
const locale = msg.from?.language_code;
if (
Object.keys(this.translatesStorage.translates).find((key) =>
locale?.includes(key)
) &&
!locale?.includes(DEFAULT_LANGUAGE)
) {
return null;
}
if (
this.botСommandsToolsService.checkCommands(
msg.text,
[...Object.keys(BotCommandsEnum)],
locale
)
) {
const result = await this.scraperService.onMessage(msg);
try {
if (result?.type === 'text') {
return {
type: 'text',
message: msg,
text: result.text.split('\\"').join('"').split('\n').join(' '),
};
}
return result;
} catch (err) {
console.debug(result);
console.error(err, err.stack);
throw err;
}
}
return null;
}
}
JokesGeneratorModule 업데이트
libs/jokes-generator/server/src/lib/jokes-generator.module.ts
import {
BotCommandsModule,
BOT_COMMANDS_PROVIDER,
} from '@kaufman-bot/core/server';
import { ScraperModule } from '@kaufman-bot/html-scraper/server';
import { DynamicModule, Module } from '@nestjs/common';
import { getText } from 'class-validator-multi-lang';
import { CustomInjectorModule } from 'nestjs-custom-injector';
import { TranslatesModule } from 'nestjs-translates';
import { JokesGeneratorService } from './jokes-generator-services/jokes-generator.service';
import { RuJokesGeneratorService } from './jokes-generator-services/ru-jokes-generator.service';
@Module({
imports: [TranslatesModule, BotCommandsModule],
exports: [TranslatesModule, BotCommandsModule],
})
export class JokesGeneratorModule {
static forRoot(): DynamicModule {
return {
module: JokesGeneratorModule,
imports: [
CustomInjectorModule.forFeature({
imports: [
ScraperModule.forRoot({
title: getText('Jokes generator'),
name: 'jokes',
descriptions: getText(
'Command to generate text with a random jokes'
),
usage: [getText('get joke'), getText('jokes help')],
contextUsage: [getText('more'), getText('next')],
contentSelector: '#joke > table > tbody > tr > td',
spyWords: [getText('jokes'), getText('joke')],
removeWords: [getText('get'), getText('please')],
uri: 'https://randstuff.ru/joke/',
contentCodepage: 'utf8',
}),
],
providers: [
{
provide: BOT_COMMANDS_PROVIDER,
useClass: RuJokesGeneratorService,
},
],
exports: [ScraperModule],
}),
CustomInjectorModule.forFeature({
imports: [
ScraperModule.forRoot({
title: getText('Jokes generator'),
name: 'jokes',
descriptions: getText(
'Command to generate text with a random jokes'
),
usage: [getText('get joke'), getText('jokes help')],
contextUsage: [getText('more'), getText('next')],
contentSelector: 'data > joke',
spyWords: [getText('jokes'), getText('joke')],
removeWords: [getText('get'), getText('please')],
uri: 'https://v2.jokeapi.dev/joke/Any?blacklistFlags=nsfw,religious,political,racist,sexist,explicit&type=single&format=xml',
contentCodepage: 'utf8',
}),
],
providers: [
{
provide: BOT_COMMANDS_PROVIDER,
useClass: JokesGeneratorService,
},
],
exports: [ScraperModule],
}),
],
};
}
}
텔레그램 봇의 새로운 로직 확인
마지막 활성 명령의 정보를 저장하고 응답 생성에 사용하는 예
도움말 텍스트에서 볼 수 있는 상황에 맞는 모드에서 사용할 단어
다음 게시물에서는 "if else"논리를 포함하는 예제 재귀 작업과 함께 간단한 명령 모듈을 추가합니다...
Reference
이 문제에 관하여(NestJS의 Telegram 봇에서 재귀적 상황에 맞는 작업을 사용하여 짧은 명령 및 예제 만들기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/endykaufman/create-short-commands-and-example-using-recursive-contextable-work-in-telegram-bot-on-nestjs-3gfo텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)