111 lines
3.3 KiB
TypeScript
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.change_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}`;
|
|
}
|
|
}
|