报警增加代金券消耗和累计充值
This commit is contained in:
parent
9e2efe6320
commit
daeac2e263
@ -13,3 +13,5 @@ export const taConfig = {
|
||||
};
|
||||
|
||||
export const taUrl = 'http://47.112.98.161:8992';
|
||||
|
||||
export const fromDate = '2023-12-28';
|
||||
|
5
src/server/ta/constant.ts
Normal file
5
src/server/ta/constant.ts
Normal file
@ -0,0 +1,5 @@
|
||||
|
||||
export enum EResourceId {
|
||||
DJQ = 2226,
|
||||
XIAN_YU = 202,
|
||||
}
|
@ -10,6 +10,13 @@ export interface IRecordInfo {
|
||||
num: number;
|
||||
}
|
||||
|
||||
export interface INotifyInfo {
|
||||
uid: string;
|
||||
num: number;
|
||||
recharge: number;
|
||||
djq: number;
|
||||
}
|
||||
|
||||
export interface INotifyConfig {
|
||||
useXianYu: number;
|
||||
getXianYu: number;
|
||||
|
@ -4,15 +4,15 @@
|
||||
|
||||
import axios from 'axios';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { EChangeType, IRecordInfo } from './interface';
|
||||
import { EChangeType, INotifyInfo, IRecordInfo } from './interface';
|
||||
|
||||
@Injectable()
|
||||
export class NotifyService {
|
||||
private _itemTemplate = '[channel][uids]等玩家的[itemId][type量]已超过预警值,请注意处理';
|
||||
private _rechargeTemplate = '[channel][uids]等玩家的充值已超过预警值,请注意处理';
|
||||
private _itemTemplate = '[channel][itemId][type量]已触发报警,请注意处理\n';
|
||||
private _rechargeTemplate = '[channel]充值已触发报警,请注意处理\n';
|
||||
private records: Map<string, string[]> = new Map();
|
||||
|
||||
async notifyRecharge(data: IRecordInfo[], channel: string) {
|
||||
async notifyRecharge(data: INotifyInfo[], channel: string) {
|
||||
if (data.length === 0) return;
|
||||
|
||||
const key = `${channel}-recharge`;
|
||||
@ -21,15 +21,15 @@ export class NotifyService {
|
||||
const uids = data.map(d => d.uid).filter(uid => !old.includes(uid));
|
||||
if (uids.length === 0) return;
|
||||
|
||||
const content = this.formatRecharge(channel, uids);
|
||||
const content = this.formatRecharge(channel, data);
|
||||
console.log(content);
|
||||
|
||||
await this.sendDD(content);
|
||||
old.push(...uids);
|
||||
this.records.set(key, old);
|
||||
// old.push(...uids);
|
||||
// this.records.set(key, old);
|
||||
}
|
||||
|
||||
async notifyItemChange(data: IRecordInfo[], channel: string, itemId: number | string, type: EChangeType) {
|
||||
async notifyItemChange(data: INotifyInfo[], channel: string, itemId: number | string, type: EChangeType) {
|
||||
if (data.length === 0) return;
|
||||
|
||||
const key = `${channel}-${type}`;
|
||||
@ -38,25 +38,27 @@ export class NotifyService {
|
||||
const uids = data.map(d => d.uid).filter(uid => !old.includes(uid));
|
||||
if (uids.length === 0) return;
|
||||
|
||||
const content = this.formatItem(channel, uids, itemId, type);
|
||||
const content = this.formatItem(channel, data, itemId, type);
|
||||
console.log(content);
|
||||
|
||||
await this.sendDD(content);
|
||||
old.push(...uids);
|
||||
this.records.set(key, old);
|
||||
// old.push(...uids);
|
||||
// this.records.set(key, old);
|
||||
}
|
||||
|
||||
private formatItem(channel: string, uids: string[], itemId: string | number, type: EChangeType) {
|
||||
private formatItem(channel: string, data: INotifyInfo[], itemId: string | number, type: EChangeType) {
|
||||
return this._itemTemplate
|
||||
.replace('channel', channel)
|
||||
.replace('uids', uids.join(','))
|
||||
.replace('itemId', itemId as string)
|
||||
.replace('type', type === 'use' ? '消耗' : '获取')
|
||||
.replace('type', type === 'use' ? '消耗' : '获取') + this.formatNotifyInfo(data);
|
||||
}
|
||||
private formatRecharge(channel: string, uids: string[]) {
|
||||
private formatRecharge(channel: string, data: INotifyInfo[]) {
|
||||
return this._rechargeTemplate
|
||||
.replace('channel', channel)
|
||||
.replace('uids', uids.join(','));
|
||||
.replace('channel', channel) + this.formatNotifyInfo(data);
|
||||
}
|
||||
|
||||
private formatNotifyInfo(data: INotifyInfo[]) {
|
||||
return data.map(d => `[${d.uid}][总代金券消耗: ${d.djq}][总充值: ${d.recharge}]`).join('\n');
|
||||
}
|
||||
|
||||
private async sendDD(content: string) {
|
||||
|
@ -5,10 +5,12 @@ import moment from 'moment';
|
||||
import axios, { AxiosInstance } from 'axios';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Cron, CronExpression } from '@nestjs/schedule';
|
||||
import { taConfig, taUrl } from '../../config/ta.config';
|
||||
import { fromDate, taConfig, taUrl } from '../../config/ta.config';
|
||||
import { NotifyService } from './notify.service';
|
||||
import { INotifyConfig, IRecordInfo, ITaConfig } from './interface';
|
||||
import { EChangeType, INotifyConfig, INotifyInfo, IRecordInfo, ITaConfig } from './interface';
|
||||
import { __ROOT__ } from '../../config/config';
|
||||
import { EResourceId } from './constant';
|
||||
import { getEventName } from './util';
|
||||
|
||||
@Injectable()
|
||||
export class TaService {
|
||||
@ -41,10 +43,13 @@ export class TaService {
|
||||
const { eventDb, apiSecret, channel } = config;
|
||||
const sql = this.rechargeSql(eventDb, date, limit);
|
||||
const res = await this.readData(apiSecret, sql);
|
||||
await this._notifyService.notifyRecharge(res, channel);
|
||||
if (res.length === 0) return;
|
||||
|
||||
const ni = await this.getNotifyInfo(apiSecret, eventDb, res);
|
||||
await this._notifyService.notifyRecharge(ni, channel);
|
||||
}
|
||||
|
||||
private async checkXianYu(config: ITaConfig, date: string, type: 'use' | 'get', limit: number) {
|
||||
private async checkXianYu(config: ITaConfig, date: string, type: EChangeType, limit: number) {
|
||||
if (!limit) {
|
||||
console.log(`none checkGetXianYu config, limit: ${limit}`);
|
||||
return;
|
||||
@ -54,10 +59,13 @@ export class TaService {
|
||||
const eventName = type === 'use' ? 'use_xian_yu' : 'get_xian_yu';
|
||||
const sql = this.xianYuChangeSql(eventDb, date, eventName, limit);
|
||||
const res = await this.readData(apiSecret, sql);
|
||||
await this._notifyService.notifyItemChange(res, channel, '仙玉', type);
|
||||
if (res.length === 0) return;
|
||||
|
||||
const ni = await this.getNotifyInfo(apiSecret, eventDb, res);
|
||||
await this._notifyService.notifyItemChange(ni, channel, '仙玉', type);
|
||||
}
|
||||
|
||||
private async checkItem(config: ITaConfig, date: string, itemId: number, type: 'use' | 'get', limit: number) {
|
||||
private async checkItem(config: ITaConfig, date: string, itemId: number, type: EChangeType, limit: number) {
|
||||
if (!limit) {
|
||||
console.log(`none checkItem config, type: ${type}, limit: ${limit}`);
|
||||
return;
|
||||
@ -67,8 +75,41 @@ export class TaService {
|
||||
const eventName = type === 'use' ? 'use_item' : 'get_item';
|
||||
const sql = this.itemChangeSql(eventDb, date, itemId, eventName, limit);
|
||||
const res = await this.readData(apiSecret, sql);
|
||||
if (res.length === 0) return;
|
||||
|
||||
await this._notifyService.notifyItemChange(res, channel, itemId, type);
|
||||
const ni = await this.getNotifyInfo(apiSecret, eventDb, res);
|
||||
await this._notifyService.notifyItemChange(ni, channel, itemId, type);
|
||||
}
|
||||
|
||||
private async getNotifyInfo(apiSecret: string, eventDb: string, infos: IRecordInfo[]) {
|
||||
const uids = infos.map(r => r.uid);
|
||||
const totalRecharge = await this.getTotalRecharge(apiSecret, eventDb, uids);
|
||||
const totalDjq = await this.getTotalDjq(apiSecret, eventDb, uids, 'use');
|
||||
|
||||
const res: INotifyInfo[] = [];
|
||||
|
||||
for (const info of infos) {
|
||||
const rechargeRecord = totalRecharge.find(t => t.uid === info.uid);
|
||||
const djqRecord = totalDjq.find(t => t.uid === info.uid);
|
||||
|
||||
res.push({
|
||||
...info,
|
||||
djq: djqRecord?.num || 0,
|
||||
recharge: rechargeRecord?.num || 0
|
||||
});
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
private async getTotalRecharge(apiSecret: string, db: string, uids: string[]) {
|
||||
const sql = this.totalRechargeSql(db, uids, fromDate);
|
||||
return this.readData(apiSecret, sql);
|
||||
}
|
||||
|
||||
private async getTotalDjq(apiSecret: string, db: string, uids: string[], type: EChangeType) {
|
||||
const sql = this.itemTotalSql(db, EResourceId.DJQ, getEventName(type), uids, fromDate);
|
||||
return this.readData(apiSecret, sql);
|
||||
}
|
||||
|
||||
private readConfig() {
|
||||
@ -86,7 +127,7 @@ export class TaService {
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
}
|
||||
});
|
||||
// console.log('data', data);
|
||||
// console.log('data', data)
|
||||
return this.formatData(data);
|
||||
}
|
||||
|
||||
@ -118,8 +159,18 @@ export class TaService {
|
||||
GROUP BY "#account_id" HAVING sum ("pay_amount") > ${limit}
|
||||
`;
|
||||
}
|
||||
private totalRechargeSql(db: string, uids: string[], fromDate: string) {
|
||||
return `
|
||||
SELECT "#account_id" AS "uid", sum("pay_amount") AS "num"
|
||||
FROM ${db}
|
||||
WHERE "$part_date" >= '${fromDate}'
|
||||
AND "#event_name" = 'order_finish'
|
||||
AND "#account_id" IN (${uids.map(u => `'${u}'`).join(',')})
|
||||
GROUP BY "#account_id";
|
||||
`;
|
||||
}
|
||||
|
||||
private xianYuChangeSql(db: string, date: string, eventName: string, limit = 10 * 1000) {
|
||||
private xianYuChangeSql(db: string, date: string, eventName: string, limit: number) {
|
||||
return `
|
||||
SELECT "#account_id" AS "uid", sum ("change_num") AS "num"
|
||||
FROM ${db}
|
||||
@ -128,12 +179,24 @@ export class TaService {
|
||||
`;
|
||||
}
|
||||
|
||||
private itemChangeSql(db: string, date: string, itemId: number, eventName: string, limit = 100000) {
|
||||
private itemTotalSql(db: string, itemId: number, eventName: string, uids: string[], fromDate: string) {
|
||||
return `
|
||||
SELECT "#account_id" AS "uid", sum("change_num") AS "num"
|
||||
FROM ${db}
|
||||
WHERE "$part_date" >= '${fromDate}'
|
||||
AND "#event_name" = '${eventName}'
|
||||
AND "item_id" = ${itemId}
|
||||
AND "#account_id" IN (${uids.map(u => `'${u}'`).join(',')})
|
||||
GROUP BY "#account_id";
|
||||
`;
|
||||
}
|
||||
|
||||
private itemChangeSql(db: string, date: string, itemId: number, eventName: string, limit: number, dateC = '=') {
|
||||
return `
|
||||
SELECT "#account_id" AS "uid", sum ("change_num") AS "num"
|
||||
FROM ${db}
|
||||
WHERE "$part_date" = '${date}' AND "#event_name" = '${eventName}' AND "item_id" = ${itemId}
|
||||
GROUP BY "#account_id" HAVING sum ("change_num") > ${limit}
|
||||
WHERE "$part_date" ${dateC} '${date}' AND "#event_name" = '${eventName}' AND "item_id" = ${itemId}
|
||||
GROUP BY "#account_id" HAVING sum ("change_num") >= ${limit}
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
3
src/server/ta/util.ts
Normal file
3
src/server/ta/util.ts
Normal file
@ -0,0 +1,3 @@
|
||||
import { EChangeType } from './interface';
|
||||
|
||||
export const getEventName = (type: EChangeType) => type === 'get' ? 'get_item' : 'use_item';
|
Loading…
Reference in New Issue
Block a user