聊天:添加跑马灯功能

This commit is contained in:
luying
2021-07-02 17:23:18 +08:00
parent 4fce369680
commit e9280a38c9
8 changed files with 187 additions and 1 deletions

View File

@@ -11,6 +11,7 @@ import { dispatch } from '../../../util/dispatcher';
import { SendMailFun } from '../../../services/mailService';
import { GM_MAIL_TYPE } from '../../../consts';
import { RewardInter } from '../../../pubUtils/interface';
import { MarqueeModel } from '../../../db/Marquee';
export default function(app: Application) {
return new GmHandler(app);
}
@@ -154,4 +155,21 @@ export class GmHandler {
});
}
}
async createMarquee(msg: { startTime: string, endTime: string, interval: number, content: string }, session: BackendSession) {
const { startTime, endTime, interval, content } = msg;
let marquee = await MarqueeModel.createData({ serverIds: [1], type: 2, startTime: new Date(startTime), endTime: new Date(endTime), interval, content });
return resResult(STATUS.SUCCESS, {
code: marquee.code
});
}
async sendMarquee(msg: { code: string }, session: BackendSession) {
const { code } = msg;
let systimerServers = this.app.getServersByType('systimer');
for(let { id } of systimerServers) {
await this.app.rpc.systimer.systimerRemote.setMarquee.toServer(id, code);
}
return resResult(STATUS.SUCCESS);
}
}

View File

@@ -3,6 +3,8 @@ import { resetPvpSeasonTime, setPvpDefResult, guildActivityStart, gateActivityEn
import PvpDefenseType from '../../../db/PvpDefense';
import { DicGuildActivity } from '../../../pubUtils/dictionary/DicGuildActivity';
import { reloadResources } from '../../../pubUtils/data';
import { setMarquee } from '../../../services/marqueeService';
export default function (app: Application) {
return new SystimerRemote(app);
}
@@ -45,4 +47,12 @@ export class SystimerRemote {
public async reloadResources() {
reloadResources();
}
/**
* @description 设置跑马灯配置
* @param code 跑马灯唯一code
*/
public async setMarquee(code: string) {
await setMarquee(code);
}
}

View File

@@ -0,0 +1,66 @@
import { MarqueeType, MarqueeModel } from "../db/Marquee";
import { MARQUEE_TYPE } from "../consts";
import { scheduleJob } from 'node-schedule';
import { createMarqueeMsg as sysCreateMarqueeMsg, pushMarqueeMsg as sysPushMarqueeMsg } from './sysChatService';
import { GroupMessageType } from "../db/GroupMessage";
export async function initMarquee() {
const marquees = await MarqueeModel.findEffectiveMarque();
for(let marquee of marquees) {
await generateMarqueeSchedule(marquee);
}
}
export async function setMarquee(code: string) {
let marquee = await MarqueeModel.findByCode(code);
if(marquee.type == MARQUEE_TYPE.INSTANT) {
let msgDatas = await createMarqueeMsg(marquee);
await pushMarqueeMsg(msgDatas);
} else {
await generateMarqueeSchedule(marquee);
}
}
async function generateMarqueeSchedule(marquee: MarqueeType) {
if(marquee.type != MARQUEE_TYPE.SCHEDULE) return false;
if(marquee.startTime.getTime() >= marquee.endTime.getTime()) return false
let startJob = scheduleJob(`start${marquee.code}`, marquee.startTime.getTime(), async () => {
console.log('************', `跑马灯定时器 ${marquee.code}开始`, '************');
let msgDatas = await createMarqueeMsg(marquee);
await pushMarqueeMsg(msgDatas);
let secondsJob = scheduleJob(`setSeconds${marquee.code}`, `*/${marquee.interval} * * * * *`, async () => {
await pushMarqueeMsg(msgDatas);
});
let endJob = scheduleJob(`end${marquee.code}`, marquee.endTime.getTime(), () => {
if(startJob) {
startJob.cancel();
startJob = undefined;
}
if(secondsJob) {
secondsJob.cancel();
secondsJob = undefined;
}
if(endJob) {
endJob.cancel();
endJob = undefined;
}
});
});
return true;
}
async function createMarqueeMsg(marquee: MarqueeType) {
let { serverIds, content } = marquee;
let msgDatas: GroupMessageType[] = [];
for(let serverId of serverIds) {
let msgData = await sysCreateMarqueeMsg('', '系统', serverId, content);
msgDatas.push(msgData);
}
return msgDatas;
}
async function pushMarqueeMsg(msgDatas: GroupMessageType[]) {
for(let msgData of msgDatas) {
await sysPushMarqueeMsg(msgData);
}
}

View File

@@ -10,6 +10,7 @@ import { pinus } from 'pinus';
import { resResult } from '../pubUtils/util';
import { BossInstanceType } from '../db/BossInstance';
import { getSimpleRoleInfo } from './roleService';
import { GroupMessageType } from '../db/GroupMessage';
async function pushNormalHeroInfoBySource(roleId: string, roleName: string, serverId: number | string, source: number, heroInfo: Partial<HeroType>) {
const hero = pick(heroInfo, ['hName', 'hid', 'seqId', 'quality', 'star', 'starStage', 'colorStar', 'colorStarStage']);
@@ -140,6 +141,15 @@ export async function pushVestigeFirstMsg(roleId: string, roleName: string, serv
return result;
}
export async function createMarqueeMsg(roleId: string, roleName: string, serverId: number | string, content: string) {
const msgData = await createGroupMsg(roleId, roleName, CHANNEL_PREFIX.SYS, `${serverId}`, MSG_TYPE.RICH_TEXT, MSG_SOURCE.SEND_MARQUEE, content, null, null);
return msgData;
}
export async function pushMarqueeMsg(msgData: GroupMessageType) {
await pushGroupMsgToRoom(msgData);
}
function shouldPushTowerMsg(lv: number) {
// 100 层之后每 50 层触发
return lv >= 100 && lv % 50 === 0;

View File

@@ -27,6 +27,7 @@ import { dispatch } from '../util/dispatcher';
import { Rank } from './rankService';
import { checkTask } from './taskService';
import { everydayRefresh } from './connectorService';
import { initMarquee } from './marqueeService';
const PER_SECOND = 1 * 1000;
const PER_DAY = 24 * 60 * 60;
@@ -83,6 +84,9 @@ export async function init() {
// 每天5点推送刷新时间消息
// 顺便每天0点计算前一天活跃玩家中位数战力
scheduleJob('everyDayRefresh', `0 0 ${REFRESH_TIME} * * ?`, everydayRefresh);
// 跑马灯
await initMarquee();
}
function setPvpSeasonSchdule() {
@@ -388,7 +392,7 @@ async function guildActivityStartSchedule() {
}
export async function guildActivityStart(dicGuildActivity?: DicGuildActivity) {
console.log('***********开始军团晚间活动****')
console.log('*******开始军团晚间活动****')
if(!dicGuildActivity) dicGuildActivity = getTodayGuildActivity();
if(!dicGuildActivity) return;

View File

@@ -54,6 +54,7 @@ export const MSG_SOURCE = {
EQUIP_REFRESH_BEST: 20,
ACQUIRE_RARE_GOODS: 21,
GROUP_SEND_GIFT: 22,
SEND_MARQUEE: 23
}
export const ON_PRIVATE_MSG_ROUTE = 'onPrivateMessage';

View File

@@ -668,3 +668,8 @@ export enum GACHA_CONTENT_TYPE {
}
export const GACHA_OCCUPY_HID = 9999; // 抽卡里占位的武将
export enum MARQUEE_TYPE {
INSTANT = 1, // 发送后立刻推送
SCHEDULE = 2, // 定时器
}

72
shared/db/Marquee.ts Normal file
View File

@@ -0,0 +1,72 @@
import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType, modelOptions } from '@typegoose/typegoose';
import { MARQUEE_TYPE } from '../consts';
import { genCode } from '../pubUtils/util';
/**
* 跑马灯
**/
@modelOptions({ schemaOptions: { id: false } })
export default class Marquee extends BaseModel {
@prop({ required: true })
code: string; // 跑马灯唯一标识
@prop({ required: true, type: Number })
serverIds: number[]; // 推送服务器
@prop({ required: true, enum: MARQUEE_TYPE })
type: MARQUEE_TYPE; // 推送类型
@prop({ required: true })
startTime: Date; // 活动开始时间
@prop({ required: true })
endTime: Date; // 活动结束时间
@prop({ required: true })
interval: number; // 活动结束时间
@prop({ required: true })
content: string; // 广播内容
/**
* 创建跑马灯
* @param params 参数
* @param uid 后台操作人
*/
public static async createData(params: MarqueeParam, uid = 1) {
const code = genCode(10);
const doc = new MarqueeModel();
const update = Object.assign(doc.toJSON(), params, { code, createdBy: uid, updatedBy: uid });
const result: MarqueeType = await MarqueeModel.findOneAndUpdate({ code }, { $setOnInsert: update }, { new: true, upsert: true }).lean();
return result;
}
/**
* 更新跑马灯
* @param code 唯一标识
* @param params 参数
* @param uid 后台操作人
*/
public static async updateData(code: string, params: MarqueeParam, uid = 1) {
const result: MarqueeType = await MarqueeModel.findOneAndUpdate({ code }, { $set: {...params, updatedBy: uid }}, { new: true }).lean();
return result;
}
/**
* 根据唯一code查询一条数据
* @param {String} code 唯一码
*/
public static async findByCode(code: string) {
const result: MarqueeType = await MarqueeModel.findOne({ code }).lean();
return result;
}
/**
* 查询所有生效中的跑马灯
*/
public static async findEffectiveMarque() {
const result: MarqueeType[] = await MarqueeModel.find({ type: MARQUEE_TYPE.SCHEDULE, startTime: { $lte: new Date() }, endTime: { $gte: new Date() } }).lean();
return result;
}
}
export const MarqueeModel = getModelForClass(Marquee);
export interface MarqueeType extends Pick<DocumentType<Marquee>, keyof Marquee> {};
export type MarqueeParam = Partial<MarqueeType>;