Отправка отформатированных по шаблону персональных сообщений
This commit is contained in:
parent
b5a90b357b
commit
4b2a070851
5 changed files with 91 additions and 10 deletions
|
|
@ -21,6 +21,7 @@ import { Users } from '@app/event-emitter/couchdb-datasources/users';
|
|||
import { TelegramBotService } from './telegram-bot/telegram-bot.service';
|
||||
import { UserMetaInfoService } from './user-meta-info/user-meta-info.service';
|
||||
import { UserMetaInfo } from './couchdb-datasources/user-meta-info';
|
||||
import { PersonalNotificationAdapterService } from './notifications/adapters/personal-notification.adapter/personal-notification.adapter.service';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
|
|
@ -45,6 +46,7 @@ import { UserMetaInfo } from './couchdb-datasources/user-meta-info';
|
|||
TelegramBotService,
|
||||
UserMetaInfoService,
|
||||
UserMetaInfo,
|
||||
PersonalNotificationAdapterService,
|
||||
],
|
||||
})
|
||||
export class AppModule implements OnModuleInit {
|
||||
|
|
@ -60,6 +62,7 @@ export class AppModule implements OnModuleInit {
|
|||
private statusChangeNotificationsService: StatusChangeNotificationsService,
|
||||
private changesCacheWriterService: ChangesCacheWriterService,
|
||||
private telegramBotService: TelegramBotService,
|
||||
private personalNotificationAdapterService: PersonalNotificationAdapterService,
|
||||
) {}
|
||||
|
||||
onModuleInit() {
|
||||
|
|
@ -74,13 +77,14 @@ export class AppModule implements OnModuleInit {
|
|||
this.currentUserEnhancer,
|
||||
]);
|
||||
|
||||
this.personalNotificationsService.$messages.subscribe((message) => {
|
||||
this.personalNotificationsService.$messages.subscribe((resp) => {
|
||||
this.logger.log(
|
||||
`Get personal message ` +
|
||||
JSON.stringify(message.message) +
|
||||
JSON.stringify(resp.personalParsedMessage.message) +
|
||||
` for recipients ` +
|
||||
JSON.stringify(message.recipients),
|
||||
JSON.stringify(resp.personalParsedMessage.recipients),
|
||||
);
|
||||
this.personalNotificationAdapterService.send(resp);
|
||||
});
|
||||
this.statusChangeNotificationsService.$changes.subscribe((change) => {
|
||||
this.logger.log(
|
||||
|
|
@ -125,6 +129,10 @@ export class AppModule implements OnModuleInit {
|
|||
this.logger.debug('Save changes in couchdb successed');
|
||||
return args;
|
||||
}),
|
||||
switchMap(async (args) => {
|
||||
this.logger.debug(``);
|
||||
return args;
|
||||
}),
|
||||
)
|
||||
.subscribe(async (args) => {
|
||||
this.logger.debug(
|
||||
|
|
|
|||
7
src/models/issue-and-personal-parsed-message.model.ts
Normal file
7
src/models/issue-and-personal-parsed-message.model.ts
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
import { RedmineTypes } from '@app/event-emitter/models/redmine-types';
|
||||
import { PersonalParsedMessage } from './personal-parsed-message.model';
|
||||
|
||||
export type IssueAndPersonalParsedMessageModel = {
|
||||
issue: RedmineTypes.Issue;
|
||||
personalParsedMessage: PersonalParsedMessage;
|
||||
};
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
import { UsersService } from '@app/event-emitter/users/users.service';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { IssueAndPersonalParsedMessageModel } from 'src/models/issue-and-personal-parsed-message.model';
|
||||
import { TelegramBotService } from 'src/telegram-bot/telegram-bot.service';
|
||||
import Handlebars from 'handlebars';
|
||||
|
||||
@Injectable()
|
||||
export class PersonalNotificationAdapterService {
|
||||
private personalMessageTemplate: HandlebarsTemplateDelegate;
|
||||
private redminePublicUrlPrefix: string;
|
||||
|
||||
constructor(
|
||||
private telegramBotService: TelegramBotService,
|
||||
private configService: ConfigService,
|
||||
private usersService: UsersService,
|
||||
) {
|
||||
const template = this.configService.get<string>('personalMessageTemplate');
|
||||
this.personalMessageTemplate = Handlebars.compile(template);
|
||||
this.redminePublicUrlPrefix =
|
||||
this.configService.get<string>('redmineUrlPublic');
|
||||
}
|
||||
|
||||
async send(
|
||||
issueAndMessages: IssueAndPersonalParsedMessageModel,
|
||||
): Promise<void> {
|
||||
const promises = issueAndMessages.personalParsedMessage.recipients.map(
|
||||
async (recipient) => {
|
||||
const redmineId = recipient;
|
||||
const issueUrl = `${this.redminePublicUrlPrefix}/issues/${issueAndMessages.issue.id}`;
|
||||
const issue = issueAndMessages.issue;
|
||||
const issueUrlHtml = `<a href="${issueUrl}">${issue.tracker.name} #${issue.id}</a>`;
|
||||
const sender = await this.usersService.getUser(
|
||||
issueAndMessages.personalParsedMessage.sender,
|
||||
);
|
||||
const data = {
|
||||
data: {
|
||||
issue: issueAndMessages.issue,
|
||||
messages: issueAndMessages.personalParsedMessage,
|
||||
},
|
||||
issue_url: issueUrlHtml,
|
||||
sender_name: sender.name,
|
||||
message: issueAndMessages.personalParsedMessage.message,
|
||||
};
|
||||
const message = this.personalMessageTemplate(data);
|
||||
return await this.telegramBotService.sendMessageByRedmineId(
|
||||
redmineId,
|
||||
message,
|
||||
{ parse_mode: 'HTML' },
|
||||
);
|
||||
},
|
||||
);
|
||||
await Promise.all(promises);
|
||||
}
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@ import { SaveResponse } from '@app/event-emitter/models/save-response';
|
|||
import { UsersService } from '@app/event-emitter/users/users.service';
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
import { Subject } from 'rxjs';
|
||||
import { IssueAndPersonalParsedMessageModel } from 'src/models/issue-and-personal-parsed-message.model';
|
||||
import { PersonalParsedMessage } from 'src/models/personal-parsed-message.model';
|
||||
|
||||
@Injectable()
|
||||
|
|
@ -10,11 +11,13 @@ export class PersonalNotificationsService {
|
|||
private userNameRe = /@([\wА-Яа-яЁё]+) ([\wА-Яа-яЁё]+)@/g;
|
||||
private logger = new Logger(PersonalNotificationsService.name);
|
||||
|
||||
$messages = new Subject<PersonalParsedMessage>();
|
||||
$messages = new Subject<IssueAndPersonalParsedMessageModel>();
|
||||
|
||||
constructor(private usersService: UsersService) {}
|
||||
|
||||
async analize(data: SaveResponse): Promise<PersonalParsedMessage[]> {
|
||||
async analize(
|
||||
data: SaveResponse,
|
||||
): Promise<IssueAndPersonalParsedMessageModel[]> {
|
||||
this.logger.debug(
|
||||
`Analize personal messages for issue ` +
|
||||
`#${data.current.id} (${data.current.subject}) start`,
|
||||
|
|
@ -29,11 +32,16 @@ export class PersonalNotificationsService {
|
|||
`from sender ${message.sender} ` +
|
||||
`for recipients ${JSON.stringify(message.recipients)}`,
|
||||
);
|
||||
this.$messages.next(message);
|
||||
this.$messages.next({
|
||||
issue: data.current,
|
||||
personalParsedMessage: message,
|
||||
});
|
||||
}
|
||||
return message;
|
||||
});
|
||||
const res = (await Promise.all(pMessages)).filter((m) => Boolean(m));
|
||||
const res = (await Promise.all(pMessages))
|
||||
.filter((m) => Boolean(m))
|
||||
.map((m) => ({ issue: data.current, personalParsedMessage: m }));
|
||||
this.logger.debug(
|
||||
`Analize personal messages for issue ` +
|
||||
`#${data.current.id} (${data.current.subject}) finished`,
|
||||
|
|
|
|||
|
|
@ -74,17 +74,19 @@ export class TelegramBotService {
|
|||
async sendMessageByRedmineId(
|
||||
redmineId: number,
|
||||
msg: string,
|
||||
options?: TelegramBot.SendMessageOptions,
|
||||
): Promise<boolean> {
|
||||
const userMetaInfo = await this.userMetaInfoService.findByRedmineId(
|
||||
redmineId,
|
||||
);
|
||||
if (!userMetaInfo) return false;
|
||||
const chatId = userMetaInfo.telegram_chat_id;
|
||||
await this.bot.sendMessage(chatId, msg);
|
||||
await this.bot.sendMessage(chatId, msg, options);
|
||||
this.logger.debug(
|
||||
`Sent message for redmineUserId = ${redmineId}, ` +
|
||||
`telegramChatId = ${chatId}, ` +
|
||||
`message = ${msg}`,
|
||||
`message = ${msg}, ` +
|
||||
`options = ${JSON.stringify(options)}`,
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -93,10 +95,11 @@ export class TelegramBotService {
|
|||
firstname: string,
|
||||
lastname: string,
|
||||
msg: string,
|
||||
options?: TelegramBot.SendMessageOptions,
|
||||
): Promise<boolean> {
|
||||
const user = await this.usersService.findUserByName(firstname, lastname);
|
||||
if (!user) return false;
|
||||
return await this.sendMessageByRedmineId(user.id, msg);
|
||||
return await this.sendMessageByRedmineId(user.id, msg, options);
|
||||
}
|
||||
|
||||
private async register(
|
||||
|
|
|
|||
Loading…
Reference in a new issue