系统:停服维护逻辑

This commit is contained in:
luying
2021-07-15 14:31:29 +08:00
parent 352aecfb56
commit 0028c9b992
26 changed files with 348 additions and 50 deletions

View File

@@ -675,4 +675,16 @@ export const GACHA_OCCUPY_HID = 9999; // 抽卡里占位的武将
export enum MARQUEE_TYPE {
INSTANT = 1, // 发送后立刻推送
SCHEDULE = 2, // 定时器
}
export enum SERVER_STATUS {
NEW = 1, // 新服
HOT = 2, // 火爆
WILL_OPEN = 3, // 即将开启
MAINTENANCE = 4, // 维护中
}
export enum WHITE_LIST_TYPE {
IP = 1, // ip地址
TEL = 2, // 玩家手机号
}

View File

@@ -7,6 +7,7 @@ export const STATUS = {
CONNECTOR_ERR: { code: 4, simStr: '连接服配置错误' },
LOGIN_ERR: { code: 5, simStr: '检测到您的账号异地登录,已被迫下线' },
REDLOCK_ERR: { code: 6, simStr: 'redlock错误' },
SERVER_MAINTENANCE: { code: 7, simStr: '服务器维护中' },
GLOBAL_ERR: { code: 1003, simStr: '服务器内部错误' },
// 账号相关状态 10000 - 19999

52
shared/db/Maintenance.ts Normal file
View File

@@ -0,0 +1,52 @@
import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType, mongoose, Ref } from '@typegoose/typegoose';
import Marquee from './Marquee';
import Notice from './Notice';
import GMMail from './GMMail';
/**
* 开服策略
*/
@index({ id: 1 })
export default class Maintenance extends BaseModel {
@prop({ required: true })
code: string; // 策略唯一标志
@prop({ required: true, type: Number })
serverIds: number[]; // 服务器类型
@prop({ required: true })
isOpen: boolean; // 维护是否使用
@prop({ required: true })
startTime: Date; // 维护开始时间
@prop({ ref: 'Marquee', type: mongoose.Schema.Types.ObjectId })
marquee: Ref<Marquee>; // 跑马灯连接到marquee表
@prop({ ref: 'Notice', type: mongoose.Schema.Types.ObjectId })
notice: Ref<Notice>; // 维护公告
@prop({ ref: 'Notice', type: mongoose.Schema.Types.ObjectId })
mail: Ref<GMMail>; // 维护结束邮件
public static async findOpenMaintenance() {
const rec: MaintenanceType = await MaintenanceModel.findOne({ isOpen: true }, { _id: 0 }).populate('marquee').populate('notice').lean();
return rec;
}
public static async findByCode(code: string) {
const rec: MaintenanceType = await MaintenanceModel.findOne({ code }).lean();
return rec;
}
}
export const MaintenanceModel = getModelForClass(Maintenance);
export interface MaintenanceType extends Pick<DocumentType<Maintenance>, keyof Maintenance> { }
export type MaintenanceTypeParam = Partial<MaintenanceType>; // 将所有字段变成可选项

View File

@@ -2,7 +2,7 @@ import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType, modelOptions } from '@typegoose/typegoose';
import { GameModel } from './Game';
import { CounterModel } from './Counter';
import { COUNTER } from '../consts';
import { COUNTER, SERVER_STATUS } from '../consts';
import { ServerStategyTypeParam } from './ServerStategy';
import { getServerName, getServerGroupName } from '../pubUtils/data';
@@ -39,7 +39,7 @@ export default class Serverlist extends BaseModel {
@prop({ required: false, default: 3014 })
port: number; // pinus端口
@prop({ required: true, default: 1 })
@prop({ required: true, default: 1, enum: SERVER_STATUS })
serverStatus: number; // 服务器状态
@prop({ required: true, type: Number })
@@ -50,7 +50,7 @@ export default class Serverlist extends BaseModel {
if (now > this.openTime) {
return this.serverStatus;
} else {
return 3; // 未开服
return SERVER_STATUS.WILL_OPEN; // 未开服
}
}
@@ -81,6 +81,11 @@ export default class Serverlist extends BaseModel {
return server;
}
public static async updateByServerIds(serverIds: number[], update: ServerlistUpdate) {
const result = await ServerlistModel.updateMany({ id: { $in: serverIds } }, { $set: update });
return result;
}
public static async updateGroupName(groupId: number, groupName: string) {
let server = await ServerlistModel.updateMany({ groupId }, { $set: { groupName } });
return server;
@@ -175,6 +180,7 @@ export default class Serverlist extends BaseModel {
let result = await ServerlistModel.updateMany({ activityGroupId: { $elemMatch: { $eq: groupId } }}, { $pull: { activityGroupId: groupId } }, { new: true }).lean(true);
return result;
}
}
export const ServerlistModel = getModelForClass(Serverlist);

View File

@@ -105,7 +105,7 @@ export default class User extends BaseModel {
@prop({ required: false, default: "" })
getuiCID: string;
public static async createUser(isGuest: boolean, tel: string, token: string, platform: string, pkgName: string, serverType: string, deviceId: string, guestTime: number = 0) {
public static async createUser(isGuest: boolean, tel: string, token: string, platform: string, pkgName: string, serverType: string, deviceId: string, guestTime: number = 0, ip: string = '') {
let _tel = aesEncryptcfb(tel, ENCRYPT_KEY, ENCRYPT_IV);
const curTime: Date = new Date();
@@ -113,7 +113,7 @@ export default class User extends BaseModel {
const userCode = genCode(8);
const doc = new UserModel();
let update = {};
update = Object.assign(update, doc.toJSON(), { platform, pkgName, serverType, createTime: curTime, uid, userCode, username: `用户${uid}`, isGuest, token, lastLoginTime: curTime, guestTime });
update = Object.assign(update, doc.toJSON(), { platform, pkgName, serverType, createTime: curTime, uid, userCode, username: `用户${uid}`, isGuest, token, lastLoginTime: curTime, guestTime, ip });
if (isGuest) update["guestId"] = _tel;
delete update["device"];
@@ -126,11 +126,11 @@ export default class User extends BaseModel {
return user;
}
public static async updateToken(tel: string, token: string, deviceId: string) {
public static async updateToken(tel: string, token: string, deviceId: string, ip: string) {
const curTime: Date = new Date();
let user = await UserModel.findOneAndUpdate({ tel }, { $set: { token, lastLoginTime: curTime }, $addToSet: { device: deviceId } }, { new: true }).lean({ getters: true });
let user = await UserModel.findOneAndUpdate({ tel }, { $set: { token, lastLoginTime: curTime, ip }, $addToSet: { device: deviceId } }, { new: true }).lean({ getters: true });
return user;
}
@@ -139,14 +139,14 @@ export default class User extends BaseModel {
return user;
}
public static async createOrUpdate(isGuest: boolean, tel: string, token: string, platform: string, pkgName: string, serverType: string, deviceId: string) {
public static async createOrUpdate(isGuest: boolean, tel: string, token: string, platform: string, pkgName: string, serverType: string, deviceId: string, ip: string) {
// console.log(tel);
let user: UserType = await UserModel.findOne({ tel }).lean({ getters: true });
if (!user) {
user = await UserModel.createUser(isGuest, tel, token, platform, pkgName, serverType, deviceId);
user = await UserModel.createUser(isGuest, tel, token, platform, pkgName, serverType, deviceId, 0, ip);
} else {
user = await UserModel.updateToken(tel, token, deviceId);
user = await UserModel.updateToken(tel, token, deviceId, ip);
}
return user;
}
@@ -185,7 +185,7 @@ export default class User extends BaseModel {
}
public static async findUserByToken(token: string) {
const user: UserType = await UserModel.findOne({ token }).select('uid token serverType auth tel userCode pkgName').lean({ getters: true });
const user: UserType = await UserModel.findOne({ token }).select('uid token serverType auth tel userCode pkgName ip').lean({ getters: true });
return user;
}

27
shared/db/WhiteList.ts Normal file
View File

@@ -0,0 +1,27 @@
import BaseModel from './BaseModel';
import { getModelForClass, prop, DocumentType } from '@typegoose/typegoose';
import { WHITE_LIST_TYPE } from '../consts';
export default class WhiteList extends BaseModel {
@prop({ required: true, enum: WHITE_LIST_TYPE })
type: WHITE_LIST_TYPE; // 区号
@prop({ required: true })
str: string; // ip或手机号
public static async checkIp(ip: string) {
const rec: WhiteListModelType = await WhiteListModel.findOne({ type: WHITE_LIST_TYPE.IP, str: ip }).lean();
return rec;
}
public static async checkTel(tel: string) {
const rec: WhiteListModelType = await WhiteListModel.findOne({ type: WHITE_LIST_TYPE.TEL, str: tel }).lean();
return rec;
}
}
export const WhiteListModel = getModelForClass(WhiteList);
export interface WhiteListModelType extends Pick<DocumentType<WhiteList>, keyof WhiteList> { }
export type WhiteListModelTypeParam = Partial<WhiteListModelType>; // 将所有字段变成可选项

View File

@@ -9,6 +9,8 @@ import { HERO_CE_RATIO, ABI_STAGE, GACHA_TO_FLOOR, REFRESH_TIME } from '../const
import { findIndex } from 'underscore';
import { getTimeFunM } from './timeUtil';
import { Floor } from '../domain/activityField/gachaField';
import { WhiteListModel } from '../db/WhiteList';
import { UserModel } from '../db/User';
const randomName = require("chinese-random-name");
const moment = require('moment');
const crypto = require('crypto');
@@ -580,4 +582,26 @@ export function getFloorStatus(gachaId: number, floor: Floor[]) {
count: floorMap.get(id) || 0
}
});
}
export async function checkWhiteListWithUid(uid: number) {
let user = await UserModel.findUserByUid(uid);
if(!user) return false;
let { tel, ip, auth } = user;
return await checkWhiteList(tel, ip, auth);
}
export async function checkWhiteList(tel: string, ip: string, auth: number) {
if(auth == 1) {
return true;
}
if(tel) {
let result = await WhiteListModel.checkTel(tel);
if(!!result) return true;
}
if(ip) {
let result = await WhiteListModel.checkIp(ip);
if(!!result) return true;
}
return false
}