pinkmine/src/notifications/adapters/status-change.adapter.service.ts

111 lines
3.3 KiB
TypeScript

import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import TelegramBot from 'node-telegram-bot-api';
import { Change } from 'src/models/change.model';
import { TelegramBotService } from 'src/telegram-bot/telegram-bot.service';
// eslint-disable-next-line @typescript-eslint/no-namespace
namespace StatusChangeAdapter {
export type MsgFromBatch = {
initiatorId: number;
recipientId: number;
issueId: number;
createdAt: number;
msg: string;
options?: TelegramBot.SendMessageOptions;
};
}
@Injectable()
export class StatusChangeAdapterService {
private periodValidityNotification: number;
constructor(
private telegramBotService: TelegramBotService,
private configService: ConfigService,
) {
this.periodValidityNotification = this.configService.get<number>(
'periodValidityNotification',
);
}
// TODO: Удалить устаревший метод send
/**
* @deprecated
* @see StatusChangeAdapterService.batchSend
*/
async send(change: Change): Promise<boolean[]> {
const promises = change.messages.map((m) => {
if (!m || !m.recipient || !m.recipient.id || !m.notification_message) {
return true;
}
return this.telegramBotService.sendMessageByRedmineId(
m.recipient.id,
m.notification_message,
{ parse_mode: 'HTML' },
);
});
return await Promise.all(promises);
}
async batchSend(changes: Change[]): Promise<void> {
const messages = this.getMessages(changes).map((item) => {
item.options = { parse_mode: 'HTML' };
return item;
});
for (let i = 0; i < messages.length; i++) {
const message = messages[i];
await this.telegramBotService.sendMessageByRedmineId(
message.recipientId,
message.msg,
message.options,
);
}
}
private getMessages(changes: Change[]): StatusChangeAdapter.MsgFromBatch[] {
const res: StatusChangeAdapter.MsgFromBatch[] = [];
const store: Record<string, StatusChangeAdapter.MsgFromBatch> = {};
const nowTimestamp = new Date().getTime();
for (let i = 0; i < changes.length; i++) {
const change = changes[i];
if (
nowTimestamp - change.created_on_timestamp >
this.periodValidityNotification
) {
continue;
}
for (let j = 0; j < change.messages.length; j++) {
const message = change.messages[j];
if (!message.notification_message) continue;
if (change.initiator.id == message.recipient.id) continue;
const item: StatusChangeAdapter.MsgFromBatch = {
initiatorId: change.initiator.id,
recipientId: message.recipient.id,
createdAt: change.created_on_timestamp,
issueId: change.issue_id,
msg: message.notification_message,
};
const key = this.keyForMsgFromBatch(item);
if (
!store[key] ||
(store[key] && store[key].createdAt < item.createdAt)
) {
store[key] = item;
}
}
}
for (const key in store) {
if (Object.prototype.hasOwnProperty.call(store, key)) {
const item = store[key];
res.push(item);
}
}
return res;
}
private keyForMsgFromBatch(item: StatusChangeAdapter.MsgFromBatch): string {
return `${item.issueId}-${item.recipientId}`;
}
}