添加签到相关接口
This commit is contained in:
parent
cd1a821a33
commit
67d6f7b206
163
src/controllers/DaySignController.ts
Normal file
163
src/controllers/DaySignController.ts
Normal 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
49
src/models/SignRecord.ts
Normal 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
34
src/service/SvrConfig.ts
Normal 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')
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -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)
|
||||
})
|
||||
}
|
||||
|
@ -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};
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user