Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
April 1, 2022 06:49 pm GMT

Add a module for debugging messages in admin mode and user mode for Telegram bot on NestJS

Links

https://github.com/EndyKaufman/kaufman-bot - source code of bot

https://telegram.me/DevelopKaufmanBot - current bot in telegram

Add new field to user for store debug mode state

Create migrations for append new user field

migrations/V202203310937AddDebugFieldToUserTable.pgsql

DO $$BEGIN    ALTER TABLE "User"        ADD "debugMode" boolean DEFAULT FALSE;EXCEPTION    WHEN duplicate_column THEN        NULL;END$$;

Apply migrations

npm run migrate:local

endy@endy-virtual-machine:~/Projects/current/kaufman-bot$ npm run migrate:local> [email protected] migrate:local> export $(xargs < ./.env.local) > /dev/null 2>&1 && export DATABASE_URL=$SERVER_POSTGRES_URL && npm run migrate> [email protected] migrate> npm run flyway -- migrate> [email protected] flyway> flyway -c .flyway.js "migrate"Flyway Community Edition 6.3.2 by RedgateDatabase: jdbc:postgresql://localhost:5432/kaufman_bot_develop (PostgreSQL 13.3)WARNING: Flyway upgrade recommended: PostgreSQL 13.3 is newer than this version of Flyway and support has not been tested. The latest supported version of PostgreSQL is 12.Successfully validated 3 migrations (execution time 00:00.018s)Current version of schema "public": 202203252144Migrating schema "public" to version 202203310937 - AddDebugFieldToUserTableSuccessfully applied 1 migration to schema "public" (execution time 00:00.032s)

Apply migrations

Update prisma schema and sdk

npm run prisma:pull:local

endy@endy-virtual-machine:~/Projects/current/kaufman-bot$ npm run prisma:pull:local> [email protected] prisma:pull:local> export $(xargs < ./.env.local) > /dev/null 2>&1 && export DATABASE_URL=$SERVER_POSTGRES_URL && npm run -- prisma db pull && npm run prisma:generate> [email protected] prisma> prisma "db" "pull"Prisma schema loaded from prisma/schema.prismaDatasource "db": PostgreSQL database "kaufman_bot_develop", schema "public" at "localhost:5432"Introspecting based on datasource defined in prisma/schema.prisma  Introspected 2 models and wrote them into prisma/schema.prisma in 303msRun prisma generate to generate Prisma Client.> [email protected] prisma:generate> npm run -- prisma generate> [email protected] prisma> prisma "generate"Prisma schema loaded from prisma/schema.prisma Generated Prisma Client (3.11.1 | library) to ./node_modules/@prisma/client in 165msYou can now start using Prisma Client in your code. Reference: https://pris.ly/d/clientimport { PrismaClient } from '@prisma/client'const prisma = new PrismaClient()

Update prisma schema and sdk

Check prisma schema
prisma/schema.prisma

generator client {  provider      = "prisma-client-js"  binaryTargets = ["native", "linux-musl"]}datasource db {  provider = "postgresql"  url      = env("DATABASE_URL")}model User {  id         String  @id(map: "PK_USERS") @default(dbgenerated("uuid_generate_v4()")) @db.Uuid  telegramId String  @unique(map: "UQ_USERS__TELEGRAM_ID") @db.VarChar(64)  langCode   String  @default("en") @db.VarChar(64)  debugMode  Boolean @default(false)}model migrations {  installed_rank Int      @id(map: "__migrations_pk")  version        String?  @db.VarChar(50)  description    String   @db.VarChar(200)  type           String   @db.VarChar(20)  script         String   @db.VarChar(1000)  checksum       Int?  installed_by   String   @db.VarChar(100)  installed_on   DateTime @default(now()) @db.Timestamp(6)  execution_time Int  success        Boolean  @@index([success], map: "__migrations_s_idx")  @@map("__migrations")}

Update core logic for correct work all logic needed in debug command

Update all interfaces

Before hook

libs/core/server/src/lib/bot-commands/bot-commands-types/on-before-bot-commands.interface.ts

import { BotCommandsProviderActionMsg } from './bot-commands-provider.interface';export interface OnBeforeBotCommands {  onBeforeBotCommands<    TMsg extends BotCommandsProviderActionMsg = BotCommandsProviderActionMsg  >(    msg: TMsg,    ctx?  ): Promise<TMsg>;}

After hook

libs/core/server/src/lib/bot-commands/bot-commands-types/on-after-bot-commands.interface.ts

import { BotCommandsProviderActionResultType } from './bot-commands-provider-action-result-type';import { BotCommandsProviderActionMsg } from './bot-commands-provider.interface';export interface OnAfterBotCommands {  onAfterBotCommands<    TMsg extends BotCommandsProviderActionMsg = BotCommandsProviderActionMsg,    TResult extends BotCommandsProviderActionResultType<TMsg> = BotCommandsProviderActionResultType<TMsg>  >(    result: TResult,    msg: TMsg,    ctx?  ): Promise<{ result: TResult; msg: TMsg }>;}

Update provider interface

libs/core/server/src/lib/bot-commands/bot-commands-types/bot-commands-provider.interface.ts

import { Context } from 'telegraf';import { Update } from 'telegraf/typings/core/types/typegram';import { BotCommandsProviderActionResultType } from './bot-commands-provider-action-result-type';export const BOT_COMMANDS_PROVIDER = Symbol('BOT_COMMANDS_PROVIDER');export type BotCommandsProviderActionMsg = Update.MessageUpdate['message'] & {  text: string;  // eslint-disable-next-line @typescript-eslint/no-explicit-any  botContext?: Record<string, any>;};export type BotCommandsProviderActionContext = Context<Update.MessageUpdate>;export interface BotCommandsProvider {  onHelp<    TMsg extends BotCommandsProviderActionMsg = BotCommandsProviderActionMsg  >(    msg: TMsg,    ctx  ): Promise<BotCommandsProviderActionResultType<TMsg>>;  onMessage<    TMsg extends BotCommandsProviderActionMsg = BotCommandsProviderActionMsg  >(    msg: TMsg,    ctx  ): Promise<BotCommandsProviderActionResultType<TMsg>>;}

Update core service

Add main logic of work with telegram to service

libs/core/server/src/lib/bot-commands/bot-commands-services/bot-commands.service.ts

import { Injectable } from '@nestjs/common';import { CustomInject } from 'nestjs-custom-injector';import { BotCommandsEnum } from '../bot-commands-types/bot-commands-enum';import { BotCommandsProviderActionResultType } from '../bot-commands-types/bot-commands-provider-action-result-type';import {  BotCommandsProvider,  BotCommandsProviderActionContext,  BotCommandsProviderActionMsg,  BOT_COMMANDS_PROVIDER,} from '../bot-commands-types/bot-commands-provider.interface';import { OnAfterBotCommands } from '../bot-commands-types/on-after-bot-commands.interface';import { OnBeforeBotCommands } from '../bot-commands-types/on-before-bot-commands.interface';import { BotommandsToolsService } from './bot-commands-tools.service';@Injectable()export class BotommandsService implements BotCommandsProvider {  @CustomInject(BOT_COMMANDS_PROVIDER, { multi: true })  private botCommandsProviders!: (BotCommandsProvider &    Partial<OnBeforeBotCommands> &    Partial<OnAfterBotCommands>)[];  constructor(    private readonly botommandsToolsService: BotommandsToolsService  ) {}  async process(ctx, defaultHandler?: () => Promise<unknown>) {    let msg: BotCommandsProviderActionMsg = ctx.update.message;    const result = await this.onMessage(msg, ctx, defaultHandler);    if (result?.type === 'message') {      msg = result.message;    }    if (result?.type === 'markdown') {      await ctx.reply(result.markdown, { parse_mode: 'MarkdownV2' });      return;    }    if (result?.type === 'text') {      await ctx.reply(result.text);      return;    }  }  async onHelp<TMsg extends BotCommandsProviderActionMsg>(    msg: TMsg,    ctx: BotCommandsProviderActionContext  ): Promise<BotCommandsProviderActionResultType<TMsg>> {    const allResults: string[] = [];    const len = this.botCommandsProviders.length;    for (let i = 0; i < len; i++) {      const botCommandsProvider = this.botCommandsProviders[i];      const result = await botCommandsProvider.onHelp(msg, ctx);      if (result !== null && result.type === 'text') {        allResults.push(result.text);      }      if (result !== null && result.type === 'markdown') {        allResults.push(result.markdown);      }    }    return {      type: 'markdown',      markdown: allResults.join('

'), }; } async onMessage<TMsg extends BotCommandsProviderActionMsg>( msg: TMsg, ctx: BotCommandsProviderActionContext, defaultHandler?: () => Promise<unknown> ): Promise<BotCommandsProviderActionResultType<TMsg>> { msg = await this.processOnBeforeBotCommands(msg, ctx); const len = this.botCommandsProviders.length; let result: BotCommandsProviderActionResultType<TMsg> = null; for (let i = 0; i < len; i++) { if (!result) { const botCommandsProvider = this.botCommandsProviders[i]; result = await botCommandsProvider.onMessage(msg, ctx); } } if ( result === null && this.botommandsToolsService.checkCommands( msg.text, [BotCommandsEnum.help], msg.from.language_code ) ) { return this.onHelp(msg, ctx); } const afterBotCommand = await this.processOnAfterBotCommands( result, msg, ctx ); if (defaultHandler) { await defaultHandler(); } return afterBotCommand.result; } async processOnBeforeBotCommands<TMsg extends BotCommandsProviderActionMsg>( msg: TMsg, ctx?: BotCommandsProviderActionContext ): Promise<TMsg> { const len = this.botCommandsProviders.length; for (let i = 0; i < len; i++) { const botCommandsProvider = this.botCommandsProviders[i]; if (botCommandsProvider.onBeforeBotCommands) msg = await botCommandsProvider.onBeforeBotCommands(msg, ctx); } return msg; } async processOnAfterBotCommands< TMsg extends BotCommandsProviderActionMsg, TResult extends BotCommandsProviderActionResultType<TMsg> = BotCommandsProviderActionResultType<TMsg> >( result: TResult, msg: TMsg, ctx?: BotCommandsProviderActionContext ): Promise<{ result: TResult; msg: TMsg }> { const len = this.botCommandsProviders.length; for (let i = 0; i < len; i++) { const botCommandsProvider = this.botCommandsProviders[i]; if (botCommandsProvider.onAfterBotCommands) { const afterBotCommand = await botCommandsProvider.onAfterBotCommands< TMsg, TResult >(result, msg, ctx); result = afterBotCommand.result; msg = afterBotCommand.msg; } } return { result, msg }; }}

Create DebugMessagesModule

Create new nx lib debug-messages

npm run -- nx g @nrwl/nest:lib debug-messages/server

endy@endy-virtual-machine:~/Projects/current/kaufman-bot$ npm run -- nx g @nrwl/nest:lib debug-messages/server> [email protected] nx> nx "g" "@nrwl/nest:lib" "debug-messages/server"CREATE libs/debug-messages/server/README.mdCREATE libs/debug-messages/server/.babelrcCREATE libs/debug-messages/server/src/index.tsCREATE libs/debug-messages/server/tsconfig.jsonCREATE libs/debug-messages/server/tsconfig.lib.jsonUPDATE tsconfig.base.jsonCREATE libs/debug-messages/server/project.jsonUPDATE workspace.jsonCREATE libs/debug-messages/server/.eslintrc.jsonCREATE libs/debug-messages/server/jest.config.jsCREATE libs/debug-messages/server/tsconfig.spec.jsonCREATE libs/debug-messages/server/src/lib/debug-messages-server.module.ts

Create new nx lib debug-messages

Create config file

libs/debug-messages/server/src/lib/debug-messages-config/debug-messages.config.ts

export const DEBUG_MESSAGES_CONFIG = 'DEBUG_MESSAGES_CONFIG';export interface DebugMessagesConfig {  name: string;  descriptions: string;  usage: string[];  spyWords: string[];}

Create commands enum

libs/debug-messages/server/src/lib/debug-messages-types/debug-messages-commands.ts

import { getText } from 'class-validator-multi-lang';export const DebugMessagesCommandsEnum = {  on: getText('on'),  off: getText('off'),  current: getText('state'),};

Create storage service for store user settings

libs/debug-messages/server/src/lib/debug-messages-services/debug-messages.storage.ts

import { PrismaClientService } from '@kaufman-bot/core/server';import { Injectable } from '@nestjs/common';@Injectable()export class DebugMessagesStorage {  private readonly debugModeOfUsers: Record<number, boolean> = {};  constructor(private readonly prismaClientService: PrismaClientService) {}  async getDebugModeOfUser(telegramUserId: number): Promise<boolean> {    const currentDebugMode = this.debugModeOfUsers[telegramUserId];    if (currentDebugMode) {      return currentDebugMode;    }    try {      const currentDebugModeFromDatabase =        await this.prismaClientService.user.findFirst({          where: { telegramId: telegramUserId.toString() },          rejectOnNotFound: true,        });      this.debugModeOfUsers[telegramUserId] =        currentDebugModeFromDatabase.debugMode;      return this.debugModeOfUsers[telegramUserId];    } catch (error) {      return false;    }  }  async setDebugModeOfUser(userId: number, debugMode: boolean): Promise<void> {    await this.prismaClientService.user.upsert({      create: { telegramId: userId.toString(), debugMode },      update: { debugMode },      where: { telegramId: userId.toString() },    });    this.debugModeOfUsers[userId] = debugMode;  }}

Create service with main logic of bot command

libs/debug-messages/server/src/lib/debug-messages-services/debug-messages.service.ts

import {  BotCommandsEnum,  BotCommandsProvider,  BotCommandsProviderActionMsg,  BotCommandsProviderActionResultType,  BotommandsToolsService,  OnAfterBotCommands,  OnBeforeBotCommands,} from '@kaufman-bot/core/server';import { Inject, Injectable, Logger } from '@nestjs/common';import { getText } from 'class-validator-multi-lang';import { TranslatesService } from 'nestjs-translates';import {  DebugMessagesConfig,  DEBUG_MESSAGES_CONFIG,} from '../debug-messages-config/debug-messages.config';import { DebugMessagesCommandsEnum } from '../debug-messages-types/debug-messages-commands';import { DebugMessagesStorage } from './debug-messages.storage';const DEBUG_MODE = 'debugMode';@Injectable()export class DebugMessagesService  implements BotCommandsProvider, OnBeforeBotCommands, OnAfterBotCommands{  private readonly logger = new Logger(DebugMessagesService.name);  constructor(    @Inject(DEBUG_MESSAGES_CONFIG)    private readonly debugMessagesConfig: DebugMessagesConfig,    private readonly translatesService: TranslatesService,    private readonly debugMessagesStorage: DebugMessagesStorage,    private readonly commandToolsService: BotommandsToolsService  ) {}  async onAfterBotCommands<    TMsg extends BotCommandsProviderActionMsg = BotCommandsProviderActionMsg,    TResult extends BotCommandsProviderActionResultType<TMsg> = BotCommandsProviderActionResultType<TMsg>  >(result: TResult, msg: TMsg, ctx): Promise<{ result: TResult; msg: TMsg }> {    const { botContext, ...debugData } = msg;    if (botContext?.[DEBUG_MODE] && ctx) {      ctx.reply(        ['```', JSON.stringify(debugData, undefined, 4), '```'].join('
'), { parse_mode: 'MarkdownV2', } ); } return { msg, result, }; } async onBeforeBotCommands< TMsg extends BotCommandsProviderActionMsg = BotCommandsProviderActionMsg >(msg: TMsg): Promise<TMsg> { const debugMode = await this.debugMessagesStorage.getDebugModeOfUser( msg.from?.id ); if (!msg.botContext) { msg.botContext = {}; } msg.botContext[DEBUG_MODE] = debugMode; return msg; } async onHelp< TMsg extends BotCommandsProviderActionMsg = BotCommandsProviderActionMsg >(msg: TMsg): Promise<BotCommandsProviderActionResultType<TMsg>> { return await this.onMessage({ ...msg, text: `${this.debugMessagesConfig.name} ${BotCommandsEnum.help}`, }); } async onMessage< TMsg extends BotCommandsProviderActionMsg = BotCommandsProviderActionMsg >(msg: TMsg): Promise<BotCommandsProviderActionResultType<TMsg>> { const locale = msg.from?.language_code || 'en'; const spyWord = this.debugMessagesConfig.spyWords.find((spyWord) => this.commandToolsService.checkCommands(msg.text, [spyWord], locale) ); if (spyWord) { if ( this.commandToolsService.checkCommands( msg.text, [BotCommandsEnum.help], locale ) ) { return { type: 'markdown', markdown: this.commandToolsService.generateHelpMessage( locale, this.debugMessagesConfig.name, this.debugMessagesConfig.descriptions, this.debugMessagesConfig.usage ), }; } const processedMsg = await this.process(msg, locale); if (typeof processedMsg === 'string') { return { type: 'text', text: processedMsg, }; } if (processedMsg) { return { type: 'message', message: processedMsg }; } this.logger.warn(`Unhandled commands for text: "${msg.text}"`); this.logger.debug(msg); } return null; } private async process< TMsg extends BotCommandsProviderActionMsg = BotCommandsProviderActionMsg >(msg: TMsg, locale: string) { const debugMode = await this.debugMessagesStorage.getDebugModeOfUser( msg.from?.id ); if ( this.commandToolsService.checkCommands( msg.text, [DebugMessagesCommandsEnum.on], locale ) ) { if (!debugMode) { await this.debugMessagesStorage.setDebugModeOfUser(msg.from?.id, true); return this.translatesService.translate( getText(`debug enabled`), locale, { locale, } ); } else { return this.translatesService.translate( getText(`debug already enabled`), locale, { locale, } ); } } if ( this.commandToolsService.checkCommands( msg.text, [DebugMessagesCommandsEnum.off], locale ) ) { if (debugMode) { await this.debugMessagesStorage.setDebugModeOfUser(msg.from?.id, false); return this.translatesService.translate( getText(`debug disabled`), locale, { locale, } ); } else { return this.translatesService.translate( getText(`debug already disabled`), locale, { locale, } ); } } if ( this.commandToolsService.checkCommands( msg.text, [DebugMessagesCommandsEnum.current], locale ) ) { return this.translatesService.translate( getText(`debug: {{debugMode}}`), locale, { debugMode: debugMode ? 'enable' : 'disable' } ); } return msg; }}

Create module

libs/debug-messages/server/src/lib/debug-messages.module.ts

import {  BotCommandsModule,  BOT_COMMANDS_PROVIDER,  PrismaClientModule,} from '@kaufman-bot/core/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 {  DebugMessagesConfig,  DEBUG_MESSAGES_CONFIG,} from './debug-messages-config/debug-messages.config';import { DebugMessagesService } from './debug-messages-services/debug-messages.service';import { DebugMessagesStorage } from './debug-messages-services/debug-messages.storage';@Module({  imports: [TranslatesModule, PrismaClientModule, BotCommandsModule],  providers: [DebugMessagesStorage],  exports: [    TranslatesModule,    PrismaClientModule,    BotCommandsModule,    DebugMessagesStorage,  ],})export class DebugMessagesModule {  static forRoot(): DynamicModule {    return {      module: DebugMessagesModule,      imports: [        CustomInjectorModule.forFeature({          imports: [DebugMessagesModule],          providers: [            {              provide: DEBUG_MESSAGES_CONFIG,              useValue: <DebugMessagesConfig>{                name: getText('Debug messages'),                usage: [                  getText('debug on'),                  getText('debug off'),                  getText('debug state'),                ],                descriptions: getText(                  'Commands for enable and disable debug mode'                ),                spyWords: [getText('debug')],              },            },            {              provide: BOT_COMMANDS_PROVIDER,              useClass: DebugMessagesService,            },          ],          exports: [DEBUG_MESSAGES_CONFIG],        }),      ],    };  }}

Update application

Update app service

apps/server/src/app/app.service.ts

import {  BotCommandsProviderActionMsg,  BotommandsService,} from '@kaufman-bot/core/server';import { Injectable, Logger } from '@nestjs/common';import { Hears, On, Start, Update } from 'nestjs-telegraf';import { Context } from 'telegraf';@Update()@Injectable()export class AppService {  private readonly logger = new Logger(AppService.name);  constructor(private readonly botommandsService: BotommandsService) {}  getData(): { message: string } {    return { message: 'Welcome to server!' };  }  @Start()  async startCommand(ctx: Context) {    await this.botommandsService.process(ctx, () => ctx.reply('Welcome'));  }  @On('sticker')  async onSticker(ctx) {    await this.botommandsService.process(ctx, () => ctx.reply(''));  }  @Hears('hi')  async hearsHi(ctx: Context) {    await this.botommandsService.process(ctx, () => ctx.reply('Hey there'));  }  @On('text')  async onMessage(ctx) {    let msg: BotCommandsProviderActionMsg = ctx.update.message;    const result = await this.botommandsService.onMessage(msg, ctx);    if (result?.type === 'message') {      msg = result.message;    }    if (result?.type === 'markdown') {      await ctx.reply(result.markdown, { parse_mode: 'MarkdownV2' });      return;    }    if (result?.type === 'text') {      await ctx.reply(result.text);      return;    }  }}

Update app module

apps/server/src/app/app.module.ts

import {  BotCommandsModule,  PrismaClientModule,} from '@kaufman-bot/core/server';import { CurrencyConverterModule } from '@kaufman-bot/currency-converter/server';import { DebugMessagesModule } from '@kaufman-bot/debug-messages/server';import { FactsGeneratorModule } from '@kaufman-bot/facts-generator/server';import {  DEFAULT_LANGUAGE,  LanguageSwitherModule,} from '@kaufman-bot/language-swither/server';import { Module } from '@nestjs/common';import env from 'env-var';import { TelegrafModule } from 'nestjs-telegraf';import {  getDefaultTranslatesModuleOptions,  TranslatesModule,} from 'nestjs-translates';import { join } from 'path';import { AppController } from './app.controller';import { AppService } from './app.service';@Module({  imports: [    TelegrafModule.forRoot({      token: env.get('TELEGRAM_BOT_TOKEN').required().asString(),    }),    PrismaClientModule.forRoot({      databaseUrl: env.get('SERVER_POSTGRES_URL').required().asString(),      logging: 'long_queries',      maxQueryExecutionTime: 5000,    }),    TranslatesModule.forRoot(      getDefaultTranslatesModuleOptions({        localePaths: [          join(__dirname, 'assets', 'i18n'),          join(__dirname, 'assets', 'i18n', 'class-validator-messages'),        ],        vendorLocalePaths: [join(__dirname, 'assets', 'i18n')],        locales: [DEFAULT_LANGUAGE, 'ru'],      })    ),    BotCommandsModule,    LanguageSwitherModule.forRoot(),    DebugMessagesModule.forRoot(),    CurrencyConverterModule.forRoot(),    FactsGeneratorModule.forRoot(),  ],  controllers: [AppController],  providers: [AppService],})export class AppModule {}

Translate all dictionaries

Run generate all need files

npm run generate

endy@endy-virtual-machine:~/Projects/current/kaufman-bot$ npm run generate> [email protected] generate> npm run prisma:generate && npm run rucken -- prepare --locales=en,ru && npm run lint:fix> [email protected] prisma:generate> npm run -- prisma generate> [email protected] prisma> prisma "generate"Prisma schema loaded from prisma/schema.prisma Generated Prisma Client (3.11.1 | library) to ./node_modules/@prisma/client in 193msYou can now start using Prisma Client in your code. Reference: https://pris.ly/d/client

import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient()

> [email protected] rucken> rucken "prepare" "--locales=en,ru"> [email protected] lint:fix> npm run tsc:lint && nx workspace-lint --fix && nx run-many --target=lint --all --fix && nx format:write --all> [email protected] tsc:lint> tsc --noEmit -p tsconfig.base.json      nx run currency-converter-server:lint  [local cache]      nx run language-swither-server:lint  [local cache]      nx run facts-generator-server:lint  [local cache]      nx run debug-messages-server:lint (1s)      nx run html-scraper-server:lint  [local cache]      nx run core-server:lint (1s)      nx run server:lint (1s)  >  NX   Successfully ran target lint for 7 projects (4s)         With additional flags:           --fix=true   Nx read the output from the cache instead of running the command for 4 out of 7 tasks. >  NX   Running affected:* commands with --all can result in very slow builds.   --all is not meant to be used for any sizable project or to be used in CI.   Learn more about checking only what is affected: https://nx.dev/latest/angular/cli/affected#affected.

Add translate for all empty words

View list of dictionaries for translate
View list of dictionaries for translate

Add translates in ru language
Add translates in ru language

Run generate for generate json dictionaries from po files

npm run generate

Check new logic in telegram bot

Common help message
Common help message

Help message for debug command
Help message for debug command

Enable debug mode and check work it
Enable debug mode and check work it

Change user locale with show debug info
Change user locale with show debug info

Common help message on Russia locale
Common help message on Russia locale

Example of debug emoji

Send
Send

Debug

{    "message_id": 822,    "from": {        "id": 102375526,        "is_bot": false,        "first_name": "IL'shat",        "last_name": "Khamitov",        "username": "KaufmanEndy",        "language_code": "ru"    },    "chat": {        "id": 102375526,        "first_name": "IL'shat",        "last_name": "Khamitov",        "username": "KaufmanEndy",        "type": "private"    },    "date": 1648837576,    "sticker": {        "width": 512,        "height": 512,        "emoji": "",        "set_name": "PeopleMemes",        "is_animated": true,        "is_video": false,        "thumb": {            "file_id": "AAMCAgADGQEAAgM2YkdDyN-EhN0TaqqYga12aOy6N3EAApoUAALJ5JFJ6q9bB_WLS2YBAAdtAAMjBA",            "file_unique_id": "AQADmhQAAsnkkUly",            "file_size": 6304,            "width": 128,            "height": 128        },        "file_id": "CAACAgIAAxkBAAIDNmJHQ8jfhITdE2qqmIGtdmjsujdxAAKaFAACyeSRSeqvWwf1i0tmIwQ",        "file_unique_id": "AgADmhQAAsnkkUk",        "file_size": 29792    }}

Debug

Answer
Answer

For emoji used top app handler
For emoji used top app handler

In the next post, I will add a module for process unhandled message with dialogwlow ai...


Original Link: https://dev.to/endykaufman/add-a-module-for-debugging-messages-in-admin-mode-and-user-mode-for-telegram-bot-on-nestjs-ebm

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To