DEV Community

ILshat Khamitov
ILshat Khamitov

Posted on

Create module for generate random quote of famous people in Telegram bot on NestJS

Links

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

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

https://www.forismatic.com/ - site for generate random quotes in English and Russian languages

Description of work

If you describe the addition of two modules at once on people's quotes and jokes, a very large post will come out

I decided to split the work into two separate posts

This module is a copy of the fact generator, it just uses another site for data parsing and other settings

This module uses features of the scrapper module that have not been used before:
1) using the user's locale in the page address for parsing
2) multiple element selector
3) modification of pre-installed anti anti ddos headers

Create QuoteModule

Add new library plugins

npm run -- nx g @nrwl/nest:lib quotes-generator/server

endy@endy-virtual-machine:~/Projects/current/kaufman-bot$ npm run -- nx g @nrwl/nest:lib quotes-generator/server

> kaufman-bot@0.0.0 nx
> nx "g" "@nrwl/nest:lib" "quotes-generator/server"

CREATE libs/quotes-generator/server/README.md
CREATE libs/quotes-generator/server/.babelrc
CREATE libs/quotes-generator/server/src/index.ts
CREATE libs/quotes-generator/server/tsconfig.json
CREATE libs/quotes-generator/server/tsconfig.lib.json
UPDATE tsconfig.base.json
CREATE libs/quotes-generator/server/project.json
UPDATE workspace.json
CREATE libs/quotes-generator/server/.eslintrc.json
CREATE libs/quotes-generator/server/jest.config.js
CREATE libs/quotes-generator/server/tsconfig.spec.json
CREATE libs/quotes-generator/server/src/lib/quotes-generator-server.module.ts
Enter fullscreen mode Exit fullscreen mode

npm run -- nx g @nrwl/nest:lib quotes-generator/server

Add QuotesGeneratorService

libs/quotes-generator/server/src/lib/quotes-generator-services/quotes-generator.service.ts

import {
  BotCommandsEnum,
  BotCommandsProvider,
  BotCommandsProviderActionMsg,
  BotCommandsProviderActionResultType,
  BotСommandsToolsService,
} from '@kaufman-bot/core/server';
import { ScraperService } from '@kaufman-bot/html-scraper/server';
import { Injectable } from '@nestjs/common';

@Injectable()
export class QuotesGeneratorService implements BotCommandsProvider {
  constructor(
    private readonly scraperService: ScraperService,
    private readonly botСommandsToolsService: BotСommandsToolsService
  ) {}

  async onHelp<
    TMsg extends BotCommandsProviderActionMsg = BotCommandsProviderActionMsg
  >(msg: TMsg) {
    return await this.scraperService.onHelp(msg);
  }

  async onMessage<
    TMsg extends BotCommandsProviderActionMsg = BotCommandsProviderActionMsg
  >(msg: TMsg): Promise<BotCommandsProviderActionResultType<TMsg>> {
    let locale = msg.from?.language_code;
    if (!locale?.includes('ru') || !locale?.includes('en')) {
      locale = 'en';
    }
    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',
            text: result.text.split('\\"').join('"').split('\n').join(' '),
          };
        }
        return result;
      } catch (err) {
        console.debug(result);
        console.error(err, err.stack);
        throw err;
      }
    }
    return null;
  }
}

Enter fullscreen mode Exit fullscreen mode

Add QuotesGeneratorModule

libs/quotes-generator/server/src/lib/quotes-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 { TranslatesModule } from 'nestjs-translates';
import { QuotesGeneratorService } from './quotes-generator-services/quotes-generator.service';

@Module({
  imports: [TranslatesModule, BotCommandsModule],
  exports: [TranslatesModule, BotCommandsModule],
})
export class QuotesGeneratorModule {
  static forRoot(): DynamicModule {
    return {
      module: QuotesGeneratorModule,
      imports: [
        ScraperModule.forRoot({
          name: getText('Quotes generator'),
          descriptions: getText(
            'Command to generate text with a random quotes'
          ),
          usage: [getText('get quote'), getText('quotes help')],
          contentSelector:
            'forismatic > quote > quotetext, forismatic > quote > quoteauthor',
          spyWords: [getText('quotes'), getText('quote')],
          removeWords: [getText('get'), getText('please')],
          uri: 'https://api.forismatic.com/api/1.0/?method=getQuote&format=xml&lang={{locale}}',
          contentCodepage: 'utf8',
          headers: [{}],
        }),
      ],
      providers: [
        {
          provide: BOT_COMMANDS_PROVIDER,
          useClass: QuotesGeneratorService,
        },
      ],
      exports: [ScraperModule],
    };
  }
}

Enter fullscreen mode Exit fullscreen mode

Prepare files

npm run generate
npm run generate

Translate all words with po editor

Look list of all dictionaries
Look list of all dictionaries

Append all needed translates
Append all needed translates

Prepare files for convert po dictionaries to json

npm run generate

Add QuotesGeneratorModule to AppModule

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

@Module({
  imports: [
    ...
    QuotesGeneratorModule.forRoot(),
    ...
  ],
  ...
})
export class AppModule {}
Enter fullscreen mode Exit fullscreen mode

Check new logic in telegram bot

Common help message

Common help message

Get quotes in English language

Get quotes in English language

Get quotes in Russian language

Get quotes in Russian language

In the next post, I will add people jokes for English and Russian languages...

Top comments (0)