Skip to content

Commit

Permalink
Added persistence for chats IDs (#22)
Browse files Browse the repository at this point in the history
* feat(persistence-chats): migrate to Yarn Package Manager

* feat(persistence-chats): added persistence for chat IDs

* feat(persistence-chats): bumped application version and updated README

feat #4
  • Loading branch information
jpmoura authored Dec 6, 2020
1 parent 445bb6b commit 4d28dea
Show file tree
Hide file tree
Showing 10 changed files with 5,412 additions and 7,561 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,4 @@ typings/
.vscode/launch.json

/dist
bot.db
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ In order to use this bot you need to create a .ENV file with two specific keys:

You will need to apply for a key in [Twitter](https://developer.twitter.com/en/apply-for-access.html). After set this .ENV file with these five keys, just run the command ```npm install && npm start```.

This bot was built on top of NodeJS v12.
This bot was built on top of NodeJS v14.

## Know Issues

Expand All @@ -37,7 +37,7 @@ If you plan to serve this bot to different users and not just for yourself you g
## TODO

* Automatized tests that covers at least 80%;
* Persist the chat ids;
* ~~Persist the chat ids;~~
* ~~More elegant message about Fantasy League transactions;~~
* Allow to add more than one fantasy league to update about it.
* Aggregate posts from [NFL @ Instagram](https://www.instagram.com/nfl/);
Expand Down
7,541 changes: 0 additions & 7,541 deletions package-lock.json

This file was deleted.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "nfl-telegram-bot",
"version": "2.0.0",
"version": "2.1.0",
"description": "A Telegram bot that provides the latest news about the NFL",
"repository": "github:jpmoura/nfl-news-for-telegram",
"main": "index.ts",
Expand Down Expand Up @@ -31,11 +31,13 @@
"dependencies": {
"@types/cheerio": "^0.22.22",
"@types/dotenv": "^8.2.0",
"@types/nedb": "^1.8.11",
"@types/node-schedule": "^1.3.1",
"@types/twit": "^2.2.28",
"axios": "^0.18.0",
"cheerio": "^1.0.0-rc.2",
"dotenv": "^6.1.0",
"nedb": "^1.8.0",
"node-schedule": "^1.3.0",
"telegraf": "^3.25.0",
"twit": "^2.2.11"
Expand Down
24 changes: 16 additions & 8 deletions src/application/BotManager.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import Telegraf, { Telegram } from 'telegraf';
import { TelegrafContext } from 'telegraf/typings/context';
import * as schedule from 'node-schedule';
import { Message } from 'telegraf/typings/telegram-types';
import CommandService from './service/interaction/CommandService';
import GlobalService from './service/interaction/GlobalService';
import HearingService from './service/interaction/HearingService';
import UpdateService from './service/update/UpdateService';
import MessageService from './service/message/MessageService';
import News from '../domain/model/News';
import ChatService from './service/message/ChatService';

export default class BotManager {
private news = new Map<string, News>();

private readonly chats: Set<string | number> = new Set();

private readonly bot: Telegraf<TelegrafContext>;

private readonly globalService: GlobalService;
Expand All @@ -25,13 +25,16 @@ export default class BotManager {

private readonly messageService: MessageService;

private readonly chatService: ChatService;

constructor(bot: Telegraf<TelegrafContext>, mailman: Telegram) {
this.bot = bot;
this.globalService = new GlobalService();
this.commandService = new CommandService(this.chats, mailman);
this.commandService = new CommandService(mailman);
this.hearingService = new HearingService();
this.updateService = new UpdateService();
this.messageService = new MessageService(mailman);
this.chatService = new ChatService();
}

private setupGlobal(): void {
Expand All @@ -40,9 +43,9 @@ export default class BotManager {
}

private setupCommands(): void {
this.bot.command('firstdown', (ctx) => this.commandService.addUser(ctx));
this.bot.command('fumble', (ctx) => this.commandService.removeUser(ctx));
this.bot.command('latest', (ctx) => this.commandService.sendLatest(ctx, this.news));
this.bot.command('firstdown', async (ctx) => this.commandService.addUser(ctx));
this.bot.command('fumble', async (ctx) => this.commandService.removeUser(ctx));
this.bot.command('latest', async (ctx) => this.commandService.sendLatest(ctx, this.news));
}

private setupHearings(): void {
Expand Down Expand Up @@ -70,12 +73,17 @@ export default class BotManager {

private broadcast(news: Array<News>) {
console.log(`Sending new ${news.length} itens`);
const promises: Array<Promise<Message>> = [];
const chats = this.chatService.list();
console.log(chats);

news.forEach((specificNews) => {
this.chats.forEach((chat) => {
this.messageService.send(chat, specificNews);
chats.forEach((chat) => {
promises.push(this.messageService.send(chat, specificNews));
});
});

Promise.all(promises);
}

async update(firedAt: Date) {
Expand Down
17 changes: 9 additions & 8 deletions src/application/service/interaction/CommandService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,33 @@ import { TelegrafContext } from 'telegraf/typings/context';
import { Message } from 'telegraf/typings/telegram-types';
import ICommandService from '../../../domain/interface/application/service/interaction/ICommandService';
import News from '../../../domain/model/News';
import ChatService from '../message/ChatService';
import MessageService from '../message/MessageService';

export default class CommandService implements ICommandService {
private readonly messageService: MessageService;

private readonly chats: Set<string | number>;
private readonly chatService: ChatService;

constructor(chats: Set<string | number>, mailman: Telegram) {
this.chats = chats;
constructor(mailman: Telegram) {
this.messageService = new MessageService(mailman);
this.chatService = new ChatService();
}

addUser(ctx: TelegrafContext): Promise<Message> {
this.chats.add(ctx.message.chat.id);
async addUser(ctx: TelegrafContext): Promise<Message> {
await this.chatService.create(ctx.message.chat.id);
console.log(`New client ${ctx.message.chat.id} added`);
return ctx.reply(`Gotcha ${ctx.message.chat.first_name}! From now on you will receive news about NFL as soon them are published 👌`);
}

removeUser(ctx: TelegrafContext): Promise<Message> {
this.chats.delete(ctx.message.chat.id);
async removeUser(ctx: TelegrafContext): Promise<Message> {
await this.chatService.delete(ctx.message.chat.id);
console.log(`Chat ${ctx.message.chat.id} removed from list`);
return ctx.replyWithMarkdown('Ok then, you will not hear from me anymore 😭\n'
+ 'If you change your mind, just send me `/firstdown` again 😉');
}

sendLatest(ctx: TelegrafContext, news: Map<string, News>): Promise<Message> {
async sendLatest(ctx: TelegrafContext, news: Map<string, News>): Promise<Message> {
if (news.size > 0) {
return this.messageService.send(ctx.message.chat.id, news.values().next().value);
}
Expand Down
17 changes: 17 additions & 0 deletions src/application/service/message/ChatService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import ChatRepository from '../../../infra/repository/chat/ChatRepository';

export default class ChatService {
private readonly chatRepository: ChatRepository = new ChatRepository();

async create(chatId: number): Promise<void> {
await this.chatRepository.insert(chatId);
}

list(): Array<number> {
return this.chatRepository.list().map((chatId) => Number(chatId));
}

async delete(chatId: number): Promise<void> {
await this.chatRepository.delete(chatId);
}
}
2 changes: 1 addition & 1 deletion src/application/service/message/MessageService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export default class MessageService {
this.messageRepository = new MessageRepository(mailman);
}

send(chatId: string | number, news: News): Promise<Message> {
send(chatId: number, news: News): Promise<Message> {
return this.messageRepository.send(chatId, news.toString());
}
}
28 changes: 28 additions & 0 deletions src/infra/repository/chat/ChatRepository.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import Datastore from 'nedb';
import { promisify } from 'util';

export default class ChatRepository {
private readonly db: Datastore;

private readonly promisifyUpdate: any;

private readonly promisifyRemove: any;

constructor() {
this.db = new Datastore({ filename: 'bot.db', autoload: true });
this.promisifyUpdate = promisify(this.db.update.bind(this.db));
this.promisifyRemove = promisify(this.db.remove).bind(this.db);
}

async insert(chatId: number) {
await this.promisifyUpdate({ chatId }, { $set: { chatId } }, { upsert: true });
}

list(): any[] {
return this.db.getAllData().map((item) => item.chatId);
}

async delete(chatId: number) {
await this.promisifyRemove({ chatId }, {});
}
}
Loading

0 comments on commit 4d28dea

Please sign in to comment.