添加签到相关接口

This commit is contained in:
zhl 2021-01-27 20:13:46 +08:00
parent cd1a821a33
commit 67d6f7b206
6 changed files with 281 additions and 6 deletions

View File

@ -0,0 +1,163 @@
import BaseController from '../common/base.controller'
import { router } from '../decorators/router'
import { SvrConfig } from '../service/SvrConfig'
import { SignRecord } from '../models/SignRecord'
import { ZError } from '../common/ZError'
import { parseGameAccountId } from '../utils/string.util'
import { calcBetweenDays } from '../utils/time.util'
import ItemCtrl from '../logic/ItemCtrl'
import { ItemInfo } from '../logic/ItemDef'
import { BagItem } from '../models/BagItem'
export default class DaySignController extends BaseController {
/**
*
*/
@router('post /api/:accountid/sign/list')
async signList(req: any) {
let { accountid, retroactive } = req.params
retroactive = retroactive || 1
let { gameid, channel } = parseGameAccountId(accountid)
if (!gameid || !channel) {
throw new ZError(11, '无法从accountid获取gameid和channel')
}
const cfgs = await new SvrConfig().getSignCfg(gameid, channel)
let record = (await SignRecord.findOrCreate({ accountid })).doc
if (!cfgs || !Array.isArray(cfgs)) {
throw new ZError(10, 'error get svr sign cfg')
}
let userData: any = {}
for (let cfg of cfgs) {
cfg.status = record.data.get(cfg.id + '') || 0
if (record.data.has(cfg.id + '')) {
userData[cfg.id] = 3
}
}
let betweenDays = 0
if (record.last == 0) {
betweenDays = 0
} else {
betweenDays = calcBetweenDays(Date.now(), record.last)
}
let doubleReward = betweenDays == 0 ? record.double : 0
let needNext = true
if (betweenDays === 0) {
needNext = false
}
if (needNext) {
if (betweenDays == 2 && !!retroactive) {
for (let i = 0; i < cfgs.length - 1; i++) {
if (cfgs[i].status == 3 && cfgs[i + 1].status == 0) {
cfgs[i + 1].status = 1 //可补签
if (i + 2 < cfgs.length) {
cfgs[i + 2].status = 2 //可领取
} else {
cfgs[0].status = 2
}
needNext = false
break
}
}
}
}
if (needNext) {
//正常或者超过两天的
let count = 0
for (let obj of cfgs) {
obj.status == 3 && count++
}
if (count == 7 || betweenDays > 1) {
//一轮领完 或者过期了, 2上面处理过了
// this.refreshData();
for (let obj of cfgs) {
obj.status = 0
}
record.data.clear()
record.last = 0
betweenDays = 0
doubleReward = 0
userData = {}
await record.save()
}
for (let obj of cfgs) {
if (obj.status == 0) {
obj.status = 2
break
}
}
}
return {
cfgs,
last: record.last / 1000 | 0,
betweenDays,
doubleReward,
userData
}
}
/**
*
*/
@router('post /api/:accountid/sign/get')
async receiveReward(req: any) {
// type: 1: 普通领取, 2: 双倍领取, 3: 补签
let { accountid, type, id } = req.params
type = parseInt(type)
let { gameid, channel } = parseGameAccountId(accountid)
if (!gameid || !channel) {
throw new ZError(11, '无法从accountid获取gameid和channel')
}
const cfgs: any[] = await new SvrConfig().getSignCfg(gameid, channel)
let record = (await SignRecord.findOrCreate({ accountid })).doc
let rate = 1
let cfg = cfgs.find(o => o.id === id)
if (!cfg) {
throw new ZError(13, '无法获取对应的配置')
}
switch (type) {
case 1:
if (record.data.has(id + '')) {
throw new ZError(12, '不满足领取条件')
}
record.double = 0
record.last = Date.now()
break
case 2:
if (!record.data.has(id + '')) {
rate = 2
}
record.double = 1
record.last = Date.now()
break
case 3:
if (record.data.has(id + '')) {
throw new ZError(12, '不满足补签条件')
}
record.double = 0
record.last = Date.now() - 3600 * 24 * 1000
break
default:
if (record.data.has(id + '')) {
throw new ZError(12, '不满足领取条件')
}
record.double = 0
record.last = Date.now()
break
}
record.data.set(id + '', 3)
let itemStr = ''
if (cfg.reward_list && Array.isArray(cfg.reward_list)) {
for (let sub of cfg.reward_list) {
if (itemStr.length > 0) itemStr += '|'
itemStr += `${sub.reward_type}:${sub.reward_count}`
}
} else {
itemStr += `${cfg.reward_type}:${cfg.reward_count}`
}
const itemInfos: ItemInfo[] = ItemCtrl.getItemsByInfo(itemStr)
await BagItem.addItems(accountid, itemInfos)
await record.save()
return itemInfos
}
}

49
src/models/SignRecord.ts Normal file
View File

@ -0,0 +1,49 @@
import { dbconn } from '../decorators/dbconn'
import {
getModelForClass,
index,
modelOptions, plugin,
prop
} from '@typegoose/typegoose'
import {
Base,
FindOrCreate,
TimeStamps
} from '@typegoose/typegoose/lib/defaultClasses'
// @ts-ignore
import findOrCreate from 'mongoose-findorcreate'
import { Card } from './subdoc/Card'
interface SignRecordClass extends Base<string>, TimeStamps {
}
@dbconn()
@plugin(findOrCreate)
@index({ accountid: 1 }, { unique: false })
@modelOptions({
schemaOptions:
{ collection: 'sign_record', timestamps: true }
})
class SignRecordClass extends FindOrCreate{
@prop({ required: true })
public accountid!: string
@prop({default: 0})
public last: number
// 0 未完成3 已完成
@prop({ type: Number, default: new Map() })
public data: Map<string, number>
@prop({default: 0})
public double: number
public toJson() {
return {
accoundid: this.accountid,
last: this.last,
data: this.data
}
}
}
export const SignRecord = getModelForClass(SignRecordClass,
// @ts-ignore
{ existingConnection: SignRecordClass['db'] })

34
src/service/SvrConfig.ts Normal file
View File

@ -0,0 +1,34 @@
import { singleton } from '../decorators/singleton.decorator'
import { getGameConfig } from './jcfw'
@singleton
export class SvrConfig {
public cfgMap: Map<string, any> = new Map()
public async loadData(gameid: string, channel: string) {
const cfgs = await getGameConfig(gameid, channel)
let map: Map<string, any> = new Map()
for (let cfg of cfgs) {
try {
let obj = JSON.parse(cfg.value)
map.set(cfg.key, obj)
} catch(e) {
map.set(cfg.key, cfg.value)
}
}
this.cfgMap.set(SvrConfig.generateKey(gameid, channel), map)
}
public static generateKey(gameid: string, channel: string) {
return `${gameid}_${channel}`
}
public async getSignCfg(gameid: string, channel: string) {
let key = SvrConfig.generateKey(gameid, channel)
if (!this.cfgMap.has(key)) {
await this.loadData(gameid, channel)
}
return this.cfgMap.get(key).get('sign_list')
}
}

View File

@ -1,17 +1,19 @@
import { generateKeyValStr } from '../utils/string.util'
import axios from 'axios'
const CONFIG_URL = 'https://cloud.kingsome.cn/webapp/index.php?c=Config&a=read'
const CONFIG_URL = 'https://center.kingsome.cn/api/cfg_list'
/**
* jcfw中该游戏的配置
* @param {string} gameid
* @param {string} channel
* @return {Promise<AxiosResponse<any>>}
*/
export function getGameConfig(gameid: string, channel: string) {
let data = { gameid, channel }
let paramStr = generateKeyValStr(data)
let url = `${ CONFIG_URL }&${ paramStr }`
return axios.get(url)
let url = `${ CONFIG_URL }?game_id=${gameid}&channel_id=${channel}`
return axios.get(url).then((res: any) => {
if (res.data.errorcode && res.data.result) {
throw new Error(`error get game cfg, code: ${res.errorcode}, msg: ${res.errmsg}`)
}
return JSON.parse(res.data.result)
})
}

View File

@ -43,3 +43,23 @@ export function keyValToObject(str: string,
}
return result
}
export function isJsonString(str: string) {
try {
if (typeof JSON.parse(str) == "object") {
return true;
}
} catch(e) {
}
return false;
}
export function checkAccountId(accountId: string) {
return /^\d{4}_\d{4}_.+$/.test(accountId);
}
export function parseGameAccountId(accountId: string) {
const arr = accountId.split('_');
const gameid = arr[1];
const channel = arr[0];
return {gameid, channel};
}

View File

@ -7,3 +7,10 @@ export function timeBeforeDay(day: number): number {
let time = Date.now();
return time - day * 1000 * 24 * 24;
}
//间隔天数
export function calcBetweenDays(time1: number, time2: number) {
let v1 = Math.floor(time1/3600/24/1000);
let v2 = Math.floor(time2/3600/24/1000);
return Math.abs(v1 - v2);
}