Отправка отформатированных по шаблону персональных сообщений
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 { TelegramBotService } from './telegram-bot/telegram-bot.service';
|
||||||
import { UserMetaInfoService } from './user-meta-info/user-meta-info.service';
|
import { UserMetaInfoService } from './user-meta-info/user-meta-info.service';
|
||||||
import { UserMetaInfo } from './couchdb-datasources/user-meta-info';
|
import { UserMetaInfo } from './couchdb-datasources/user-meta-info';
|
||||||
|
import { PersonalNotificationAdapterService } from './notifications/adapters/personal-notification.adapter/personal-notification.adapter.service';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
|
|
@ -45,6 +46,7 @@ import { UserMetaInfo } from './couchdb-datasources/user-meta-info';
|
||||||
TelegramBotService,
|
TelegramBotService,
|
||||||
UserMetaInfoService,
|
UserMetaInfoService,
|
||||||
UserMetaInfo,
|
UserMetaInfo,
|
||||||
|
PersonalNotificationAdapterService,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class AppModule implements OnModuleInit {
|
export class AppModule implements OnModuleInit {
|
||||||
|
|
@ -60,6 +62,7 @@ export class AppModule implements OnModuleInit {
|
||||||
private statusChangeNotificationsService: StatusChangeNotificationsService,
|
private statusChangeNotificationsService: StatusChangeNotificationsService,
|
||||||
private changesCacheWriterService: ChangesCacheWriterService,
|
private changesCacheWriterService: ChangesCacheWriterService,
|
||||||
private telegramBotService: TelegramBotService,
|
private telegramBotService: TelegramBotService,
|
||||||
|
private personalNotificationAdapterService: PersonalNotificationAdapterService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
onModuleInit() {
|
onModuleInit() {
|
||||||
|
|
@ -74,13 +77,14 @@ export class AppModule implements OnModuleInit {
|
||||||
this.currentUserEnhancer,
|
this.currentUserEnhancer,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
this.personalNotificationsService.$messages.subscribe((message) => {
|
this.personalNotificationsService.$messages.subscribe((resp) => {
|
||||||
this.logger.log(
|
this.logger.log(
|
||||||
`Get personal message ` +
|
`Get personal message ` +
|
||||||
JSON.stringify(message.message) +
|
JSON.stringify(resp.personalParsedMessage.message) +
|
||||||
` for recipients ` +
|
` for recipients ` +
|
||||||
JSON.stringify(message.recipients),
|
JSON.stringify(resp.personalParsedMessage.recipients),
|
||||||
);
|
);
|
||||||
|
this.personalNotificationAdapterService.send(resp);
|
||||||
});
|
});
|
||||||
this.statusChangeNotificationsService.$changes.subscribe((change) => {
|
this.statusChangeNotificationsService.$changes.subscribe((change) => {
|
||||||
this.logger.log(
|
this.logger.log(
|
||||||
|
|
@ -125,6 +129,10 @@ export class AppModule implements OnModuleInit {
|
||||||
this.logger.debug('Save changes in couchdb successed');
|
this.logger.debug('Save changes in couchdb successed');
|
||||||
return args;
|
return args;
|
||||||
}),
|
}),
|
||||||
|
switchMap(async (args) => {
|
||||||
|
this.logger.debug(``);
|
||||||
|
return args;
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
.subscribe(async (args) => {
|
.subscribe(async (args) => {
|
||||||
this.logger.debug(
|
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 { UsersService } from '@app/event-emitter/users/users.service';
|
||||||
import { Injectable, Logger } from '@nestjs/common';
|
import { Injectable, Logger } from '@nestjs/common';
|
||||||
import { Subject } from 'rxjs';
|
import { Subject } from 'rxjs';
|
||||||
|
import { IssueAndPersonalParsedMessageModel } from 'src/models/issue-and-personal-parsed-message.model';
|
||||||
import { PersonalParsedMessage } from 'src/models/personal-parsed-message.model';
|
import { PersonalParsedMessage } from 'src/models/personal-parsed-message.model';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
|
|
@ -10,11 +11,13 @@ export class PersonalNotificationsService {
|
||||||
private userNameRe = /@([\wА-Яа-яЁё]+) ([\wА-Яа-яЁё]+)@/g;
|
private userNameRe = /@([\wА-Яа-яЁё]+) ([\wА-Яа-яЁё]+)@/g;
|
||||||
private logger = new Logger(PersonalNotificationsService.name);
|
private logger = new Logger(PersonalNotificationsService.name);
|
||||||
|
|
||||||
$messages = new Subject<PersonalParsedMessage>();
|
$messages = new Subject<IssueAndPersonalParsedMessageModel>();
|
||||||
|
|
||||||
constructor(private usersService: UsersService) {}
|
constructor(private usersService: UsersService) {}
|
||||||
|
|
||||||
async analize(data: SaveResponse): Promise<PersonalParsedMessage[]> {
|
async analize(
|
||||||
|
data: SaveResponse,
|
||||||
|
): Promise<IssueAndPersonalParsedMessageModel[]> {
|
||||||
this.logger.debug(
|
this.logger.debug(
|
||||||
`Analize personal messages for issue ` +
|
`Analize personal messages for issue ` +
|
||||||
`#${data.current.id} (${data.current.subject}) start`,
|
`#${data.current.id} (${data.current.subject}) start`,
|
||||||
|
|
@ -29,11 +32,16 @@ export class PersonalNotificationsService {
|
||||||
`from sender ${message.sender} ` +
|
`from sender ${message.sender} ` +
|
||||||
`for recipients ${JSON.stringify(message.recipients)}`,
|
`for recipients ${JSON.stringify(message.recipients)}`,
|
||||||
);
|
);
|
||||||
this.$messages.next(message);
|
this.$messages.next({
|
||||||
|
issue: data.current,
|
||||||
|
personalParsedMessage: message,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return 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(
|
this.logger.debug(
|
||||||
`Analize personal messages for issue ` +
|
`Analize personal messages for issue ` +
|
||||||
`#${data.current.id} (${data.current.subject}) finished`,
|
`#${data.current.id} (${data.current.subject}) finished`,
|
||||||
|
|
|
||||||
|
|
@ -74,17 +74,19 @@ export class TelegramBotService {
|
||||||
async sendMessageByRedmineId(
|
async sendMessageByRedmineId(
|
||||||
redmineId: number,
|
redmineId: number,
|
||||||
msg: string,
|
msg: string,
|
||||||
|
options?: TelegramBot.SendMessageOptions,
|
||||||
): Promise<boolean> {
|
): Promise<boolean> {
|
||||||
const userMetaInfo = await this.userMetaInfoService.findByRedmineId(
|
const userMetaInfo = await this.userMetaInfoService.findByRedmineId(
|
||||||
redmineId,
|
redmineId,
|
||||||
);
|
);
|
||||||
if (!userMetaInfo) return false;
|
if (!userMetaInfo) return false;
|
||||||
const chatId = userMetaInfo.telegram_chat_id;
|
const chatId = userMetaInfo.telegram_chat_id;
|
||||||
await this.bot.sendMessage(chatId, msg);
|
await this.bot.sendMessage(chatId, msg, options);
|
||||||
this.logger.debug(
|
this.logger.debug(
|
||||||
`Sent message for redmineUserId = ${redmineId}, ` +
|
`Sent message for redmineUserId = ${redmineId}, ` +
|
||||||
`telegramChatId = ${chatId}, ` +
|
`telegramChatId = ${chatId}, ` +
|
||||||
`message = ${msg}`,
|
`message = ${msg}, ` +
|
||||||
|
`options = ${JSON.stringify(options)}`,
|
||||||
);
|
);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -93,10 +95,11 @@ export class TelegramBotService {
|
||||||
firstname: string,
|
firstname: string,
|
||||||
lastname: string,
|
lastname: string,
|
||||||
msg: string,
|
msg: string,
|
||||||
|
options?: TelegramBot.SendMessageOptions,
|
||||||
): Promise<boolean> {
|
): Promise<boolean> {
|
||||||
const user = await this.usersService.findUserByName(firstname, lastname);
|
const user = await this.usersService.findUserByName(firstname, lastname);
|
||||||
if (!user) return false;
|
if (!user) return false;
|
||||||
return await this.sendMessageByRedmineId(user.id, msg);
|
return await this.sendMessageByRedmineId(user.id, msg, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async register(
|
private async register(
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue