Добавлен обработчик получения комментария для дейли
This commit is contained in:
parent
addff66c8c
commit
e71491b637
9 changed files with 244 additions and 3 deletions
|
|
@ -3,7 +3,8 @@
|
|||
"dbs": {
|
||||
"changes": "",
|
||||
"userMetaInfo": "",
|
||||
"eccmDailyReports": ""
|
||||
"eccmDailyReports": "",
|
||||
"eccmDailyReportsUserComments": ""
|
||||
}
|
||||
},
|
||||
"telegramBotToken": "",
|
||||
|
|
|
|||
|
|
@ -32,6 +32,9 @@ import { ChangesService } from './changes/changes.service';
|
|||
import { DailyEccmReportsDatasource } from './couchdb-datasources/daily-eccm-reports.datasource';
|
||||
import { ScheduleModule } from '@nestjs/schedule';
|
||||
import { DailyEccmReportTask } from './reports/daily-eccm.report.task';
|
||||
import { DailyEccmReportsUserCommentsDatasource } from './couchdb-datasources/daily-eccm-reports-user-comments.datasource';
|
||||
import { DailyEccmUserCommentsService } from './reports/daily-eccm-user-comments.service';
|
||||
import { SetDailyEccmUserCommentBotHandlerService } from './telegram-bot/handlers/set-daily-eccm-user-comment.bot-handler.service';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
|
|
@ -70,6 +73,9 @@ import { DailyEccmReportTask } from './reports/daily-eccm.report.task';
|
|||
ChangesService,
|
||||
DailyEccmReportsDatasource,
|
||||
DailyEccmReportTask,
|
||||
DailyEccmReportsUserCommentsDatasource,
|
||||
DailyEccmUserCommentsService,
|
||||
SetDailyEccmUserCommentBotHandlerService,
|
||||
],
|
||||
})
|
||||
export class AppModule implements OnModuleInit {
|
||||
|
|
@ -95,6 +101,7 @@ export class AppModule implements OnModuleInit {
|
|||
Changes.getDatasource();
|
||||
UserMetaInfo.getDatasource();
|
||||
DailyEccmReportsDatasource.getDatasource();
|
||||
DailyEccmReportsUserCommentsDatasource.getDatasource();
|
||||
|
||||
this.enhancerService.addEnhancer([
|
||||
this.timestampEnhancer,
|
||||
|
|
|
|||
1
src/consts/date-time.consts.ts
Normal file
1
src/consts/date-time.consts.ts
Normal file
|
|
@ -0,0 +1 @@
|
|||
export const ISO_DATE_FORMAT = 'yyyy-MM-dd';
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
import { CouchDb } from '@app/event-emitter/couchdb-datasources/couchdb';
|
||||
import nano from 'nano';
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
import configuration from '../configs/app';
|
||||
import { DailyEccmUserComments } from 'src/reports/daily-eccm-user-comments.service';
|
||||
|
||||
const config = configuration();
|
||||
|
||||
@Injectable()
|
||||
export class DailyEccmReportsUserCommentsDatasource {
|
||||
private static logger = new Logger(
|
||||
DailyEccmReportsUserCommentsDatasource.name,
|
||||
);
|
||||
private static db = null;
|
||||
private static initilized = false;
|
||||
|
||||
static async getDatasource(): Promise<
|
||||
nano.DocumentScope<DailyEccmUserComments.Models.Item>
|
||||
> {
|
||||
if (DailyEccmReportsUserCommentsDatasource.initilized) {
|
||||
return DailyEccmReportsUserCommentsDatasource.db;
|
||||
}
|
||||
DailyEccmReportsUserCommentsDatasource.initilized = true;
|
||||
const n = CouchDb.getCouchDb();
|
||||
const dbName = config.couchDb.dbs.eccmDailyReportsUserComments;
|
||||
const dbs = await n.db.list();
|
||||
if (!dbs.includes(dbName)) {
|
||||
await n.db.create(dbName);
|
||||
}
|
||||
DailyEccmReportsUserCommentsDatasource.db = await n.db.use(dbName);
|
||||
DailyEccmReportsUserCommentsDatasource.initilized = true;
|
||||
DailyEccmReportsUserCommentsDatasource.logger.log(
|
||||
`Connected to eccm_daily_reports_user_comments db - ${dbName}`,
|
||||
);
|
||||
return DailyEccmReportsUserCommentsDatasource.db;
|
||||
}
|
||||
|
||||
async getDatasource(): Promise<
|
||||
nano.DocumentScope<DailyEccmUserComments.Models.Item>
|
||||
> {
|
||||
return await DailyEccmReportsUserCommentsDatasource.getDatasource();
|
||||
}
|
||||
}
|
||||
|
|
@ -14,6 +14,7 @@ export type AppConfig = {
|
|||
changes: string;
|
||||
userMetaInfo: string;
|
||||
eccmDailyReports: string;
|
||||
eccmDailyReportsUserComments: string;
|
||||
};
|
||||
};
|
||||
telegramBotToken: string;
|
||||
|
|
|
|||
93
src/reports/daily-eccm-user-comments.service.ts
Normal file
93
src/reports/daily-eccm-user-comments.service.ts
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
/* eslint-disable @typescript-eslint/no-namespace */
|
||||
import { UNLIMITED } from '@app/event-emitter/consts/consts';
|
||||
import { Timestamped } from '@app/event-emitter/models/timestamped';
|
||||
import { TimestampNowFill } from '@app/event-emitter/utils/timestamp-now-fill';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import nano from 'nano';
|
||||
import { DailyEccmReportsUserCommentsDatasource } from 'src/couchdb-datasources/daily-eccm-reports-user-comments.datasource';
|
||||
|
||||
export namespace DailyEccmUserComments {
|
||||
export namespace Models {
|
||||
export type Item = {
|
||||
userId: number;
|
||||
date: string;
|
||||
comment: string;
|
||||
};
|
||||
|
||||
export type CouchDbItem = Item & Timestamped & nano.DocumentGetResponse;
|
||||
}
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class DailyEccmUserCommentsService {
|
||||
constructor(private datasource: DailyEccmReportsUserCommentsDatasource) {}
|
||||
|
||||
async setComment(
|
||||
userId: number,
|
||||
date: string,
|
||||
comment: string,
|
||||
): Promise<void> {
|
||||
const key = this.getKey(userId, date);
|
||||
const ds = await this.datasource.getDatasource();
|
||||
let existsItem: any;
|
||||
try {
|
||||
existsItem = await ds.get(key);
|
||||
} catch (ex) {
|
||||
existsItem = null;
|
||||
}
|
||||
const item: DailyEccmUserComments.Models.CouchDbItem = TimestampNowFill({
|
||||
userId: userId,
|
||||
date: date,
|
||||
comment: comment,
|
||||
_id: key,
|
||||
_rev: existsItem?._rev,
|
||||
});
|
||||
await ds.insert(item);
|
||||
}
|
||||
|
||||
async loadComment(userId: number, date: string): Promise<string | null> {
|
||||
const key = this.getKey(userId, date);
|
||||
const ds = await this.datasource.getDatasource();
|
||||
try {
|
||||
const res: any = await ds.get(key);
|
||||
return res.comment;
|
||||
} catch (ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async loadComments(
|
||||
userIds: number[],
|
||||
date: string,
|
||||
): Promise<Record<number, string>> {
|
||||
const query: nano.MangoQuery = {
|
||||
limit: UNLIMITED,
|
||||
selector: {
|
||||
userId: {
|
||||
$in: userIds,
|
||||
},
|
||||
date: {
|
||||
$eq: date,
|
||||
},
|
||||
},
|
||||
};
|
||||
const ds = await this.datasource.getDatasource();
|
||||
const resp = await ds.find(query);
|
||||
if (!resp || !resp.docs || resp.docs.length <= 0) {
|
||||
return [];
|
||||
}
|
||||
const items = resp.docs;
|
||||
const res: Record<number, string> = {};
|
||||
for (const key in items) {
|
||||
if (Object.prototype.hasOwnProperty.call(items, key)) {
|
||||
const item = items[key];
|
||||
res[item.userId] = item.comment;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
private getKey(userId: number, date: string): string {
|
||||
return `${date} - ${userId}`;
|
||||
}
|
||||
}
|
||||
|
|
@ -14,6 +14,7 @@ import { DailyEccmReportsDatasource } from 'src/couchdb-datasources/daily-eccm-r
|
|||
import { Timestamped } from '@app/event-emitter/models/timestamped';
|
||||
import { TimestampNowFill } from '@app/event-emitter/utils/timestamp-now-fill';
|
||||
import { DateTime } from 'luxon';
|
||||
import { ISO_DATE_FORMAT } from 'src/consts/date-time.consts';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-namespace
|
||||
export namespace DailyEccmReport {
|
||||
|
|
@ -413,7 +414,7 @@ export class DailyEccmReportService {
|
|||
if (!toDate.isValid) throw new Error('to is invalid date');
|
||||
let nameValue: string | null = name || null;
|
||||
if (!nameValue) {
|
||||
nameValue = DateTime.now().toFormat('yyyy-MM-dd');
|
||||
nameValue = DateTime.now().toFormat(ISO_DATE_FORMAT);
|
||||
}
|
||||
return {
|
||||
from: fromDate.toISO(),
|
||||
|
|
|
|||
|
|
@ -0,0 +1,88 @@
|
|||
/* eslint-disable @typescript-eslint/no-namespace */
|
||||
import { TelegramBotService } from '../telegram-bot.service';
|
||||
import { TelegramBotHandlerInterface } from '../telegram.bot-handler.interface';
|
||||
import TelegramBot from 'node-telegram-bot-api';
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
import { UserMetaInfoService } from 'src/user-meta-info/user-meta-info.service';
|
||||
import { Subject } from 'rxjs';
|
||||
import { DateTime } from 'luxon';
|
||||
import { ISO_DATE_FORMAT } from 'src/consts/date-time.consts';
|
||||
|
||||
export namespace SetDailyEccmUserCommentBotHandler {
|
||||
export namespace Models {
|
||||
export type SetDailyEccmUserComment = {
|
||||
userId: number;
|
||||
date: string;
|
||||
comment: string;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class SetDailyEccmUserCommentBotHandlerService
|
||||
implements TelegramBotHandlerInterface
|
||||
{
|
||||
private service: TelegramBotService;
|
||||
private regexp = /\/set_daily_eccm_user_comment (.+)/;
|
||||
private logger = new Logger(SetDailyEccmUserCommentBotHandlerService.name);
|
||||
private dateParamRegexp = /^date=([\d\-]+) (.+)$/;
|
||||
|
||||
$messages =
|
||||
new Subject<SetDailyEccmUserCommentBotHandler.Models.SetDailyEccmUserComment>();
|
||||
|
||||
constructor(private userMetaInfoService: UserMetaInfoService) {
|
||||
return;
|
||||
}
|
||||
|
||||
async init(service: TelegramBotService, bot: TelegramBot): Promise<void> {
|
||||
if (!this.service) {
|
||||
this.service = service;
|
||||
}
|
||||
bot.onText(this.regexp, async (msg) => {
|
||||
const userMetaInfo = await this.userMetaInfoService.findByTelegramId(
|
||||
msg.chat.id,
|
||||
);
|
||||
const redmineUserId = userMetaInfo.user_id;
|
||||
const data = this.parseDate(msg.text);
|
||||
this.logger.debug(
|
||||
`Setting user comment for daily eccm ` +
|
||||
`by redmineUserId = ${redmineUserId}, ` +
|
||||
`full text - ${msg.text}, ` +
|
||||
`parsed data - ${JSON.stringify(data)}`,
|
||||
);
|
||||
this.$messages.next({
|
||||
userId: redmineUserId,
|
||||
date: data.date,
|
||||
comment: data.msg,
|
||||
});
|
||||
return;
|
||||
});
|
||||
}
|
||||
|
||||
getHelpMsg(): string {
|
||||
return (
|
||||
`/set_daily_eccm_user_comment ` +
|
||||
`[дата=yyyy-MM-dd] <комментарий> ` +
|
||||
`- дополнительный комментарий для дейли`
|
||||
);
|
||||
}
|
||||
|
||||
private parseDate(src: string): { date: string; msg: string } | null {
|
||||
let msgWithoutCommand: any = src.match(this.regexp);
|
||||
if (!msgWithoutCommand || !msgWithoutCommand[1]) {
|
||||
return null;
|
||||
}
|
||||
msgWithoutCommand = msgWithoutCommand[1];
|
||||
const msgWithDate: any = msgWithoutCommand.match(this.dateParamRegexp);
|
||||
let date: any = '';
|
||||
if (msgWithDate && msgWithDate[1] && msgWithDate[2]) {
|
||||
date = msgWithDate[1];
|
||||
if (DateTime.fromFormat(date, ISO_DATE_FORMAT).isValid) {
|
||||
msgWithoutCommand = msgWithDate[2];
|
||||
} else {
|
||||
date = '';
|
||||
}
|
||||
}
|
||||
return { date: date, msg: msgWithoutCommand };
|
||||
}
|
||||
}
|
||||
|
|
@ -7,6 +7,7 @@ import axios from 'axios';
|
|||
import { UserMetaInfoModel } from 'src/models/user-meta-info.model';
|
||||
import { CurrentIssuesEccmBotHandlerService } from './handlers/current-issues-eccm.bot-handler.service';
|
||||
import { TelegramBotHandlerInterface } from './telegram.bot-handler.interface';
|
||||
import { SetDailyEccmUserCommentBotHandlerService } from './handlers/set-daily-eccm-user-comment.bot-handler.service';
|
||||
|
||||
@Injectable()
|
||||
export class TelegramBotService {
|
||||
|
|
@ -24,12 +25,14 @@ export class TelegramBotService {
|
|||
private usersService: UsersService,
|
||||
private configService: ConfigService,
|
||||
private currentIssuesBotHandlerService: CurrentIssuesEccmBotHandlerService,
|
||||
private setDailyEccmUserCommentBotHandlerService: SetDailyEccmUserCommentBotHandlerService,
|
||||
) {
|
||||
this.telegramBotToken = this.configService.get<string>('telegramBotToken');
|
||||
this.redminePublicUrlPrefix =
|
||||
this.configService.get<string>('redmineUrlPublic');
|
||||
this.initTelegramBot();
|
||||
this.handlers.push(this.currentIssuesBotHandlerService);
|
||||
this.handlers.push(this.setDailyEccmUserCommentBotHandlerService);
|
||||
}
|
||||
|
||||
private async initTelegramBot(): Promise<void> {
|
||||
|
|
@ -47,7 +50,10 @@ export class TelegramBotService {
|
|||
this.bot.onText(/\/leave/, async (msg) => {
|
||||
await this.leave(msg);
|
||||
});
|
||||
this.currentIssuesBotHandlerService.init(this, this.bot);
|
||||
for (let i = 0; i < this.handlers.length; i++) {
|
||||
const handler = this.handlers[i];
|
||||
await handler.init(this, this.bot);
|
||||
}
|
||||
}
|
||||
|
||||
private async showHelpMessage(msg: TelegramBot.Message): Promise<void> {
|
||||
|
|
|
|||
Loading…
Reference in a new issue