添加签到相关接口
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 { generateKeyValStr } from '../utils/string.util'
|
||||||
import axios from 'axios'
|
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中该游戏的配置
|
* 获取jcfw中该游戏的配置
|
||||||
* @param {string} gameid
|
* @param {string} gameid
|
||||||
* @param {string} channel
|
* @param {string} channel
|
||||||
* @return {Promise<AxiosResponse<any>>}
|
|
||||||
*/
|
*/
|
||||||
export function getGameConfig(gameid: string, channel: string) {
|
export function getGameConfig(gameid: string, channel: string) {
|
||||||
let data = { gameid, channel }
|
let url = `${ CONFIG_URL }?game_id=${gameid}&channel_id=${channel}`
|
||||||
let paramStr = generateKeyValStr(data)
|
return axios.get(url).then((res: any) => {
|
||||||
let url = `${ CONFIG_URL }&${ paramStr }`
|
if (res.data.errorcode && res.data.result) {
|
||||||
return axios.get(url)
|
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
|
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();
|
let time = Date.now();
|
||||||
return time - day * 1000 * 24 * 24;
|
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