diff --git a/configs/admins.json b/configs/admins.json new file mode 100644 index 0000000..714e5a0 --- /dev/null +++ b/configs/admins.json @@ -0,0 +1,4 @@ +[ + "0x50A8e60041A206AcaA5F844a1104896224be6F39", + "0x210b8b648220a4C7e1bbE508C7B9723E2eCdec24" +] \ No newline at end of file diff --git a/configs/ingame_tasks.json b/configs/ingame_tasks.json index cb21ac4..b679206 100644 --- a/configs/ingame_tasks.json +++ b/configs/ingame_tasks.json @@ -14,7 +14,7 @@ }, { "id": "g3zkyh1rk6qs5exdefe", - "title": "登录游戏", + "title": "Log in to the Game", "desc": "", "task": "GameLogin", "show": true, @@ -29,7 +29,7 @@ }, { "id": "g3amegdkchm4pdjtjeb", - "title": "参与3场任意模式的比赛", + "title": "Complete 3 game matches in any mode", "desc": "", "task": "GameBattle", "show": true, @@ -37,7 +37,7 @@ "category": 1, "pretasks": ["g3885fwjnddej6jmcha"], "ticket": 0, - "tickettasks": ["g31x9wzja7eg18t3vtm"], + "tickettasks": [], "score": 20, "checkChain": false, "cfg": { "key": "battleTimes", "amount": 3 }, @@ -45,46 +45,30 @@ }, { "id": "g31x9wzja7eg18t3vtm", - "title": "累计完成10次击杀", + "title": "Accumulate 10 Kills in Total", "desc": "", "task": "GameKill", "show": true, "type": 2, "category": 1, "pretasks": ["g3885fwjnddej6jmcha"], - "ticket": 1, - "tickettasks": ["g3amegdkchm4pdjtjeb"], + "ticket": 0, + "tickettasks": [], "score": 20, "checkChain": false, "cfg": { "key": "kills", "amount": 10 }, "autoclaim": true }, - { - "id": "g38gejrp3twh1gvtr2e", - "title": "在Bounty或Rank模式下获得3次胜利", - "desc": "", - "task": "GameWin", - "show": true, - "type": 2, - "category": 2, - "pretasks": ["g3885fwjnddej6jmcha"], - "ticket": 0, - "score": 25, - "checkChain": false, - "checkTime": true, - "cfg": { "key": "winTimes", "amount": 3 }, - "autoclaim": true - }, { "id": "g33xf6688x67a2mdrrk", - "title": "在Gold模式下获取500金币", + "title": "Collect 500 Gold in Gold Mode", "desc": "", "task": "GameCoin", "show": true, - "category": 2, + "category": 3, "pretasks": ["g3885fwjnddej6jmcha"], "type": 2, - "ticket": 0, + "ticket": 1, "score": 25, "checkTime": true, "checkChain": false, @@ -94,7 +78,7 @@ { "id": "g3s6esb83da9wy9p25a", - "title": "Own CounterFile|Founder's Tag", + "title": "Founder's Tags Held", "desc": "", "task": "NftHolderCheck", "show": true, @@ -102,7 +86,7 @@ "type": 2, "category": 3, "ticket": 0, - "score": 100, + "score": 0, "checkChain": false, "checkTime": true, "cfg": { "address": "0xec23679653337d4c6390d0eeba682246a6067777", "chain": "1" }, diff --git a/initdatas/activity_info.json b/initdatas/activity_info.json index f24b337..0d2a709 100644 --- a/initdatas/activity_info.json +++ b/initdatas/activity_info.json @@ -355,6 +355,38 @@ "end": "2025-01-01 00:00", "checkChain": false, "params": { "time": 6, "failRate": 0 } + }, + { + "id": "e286nywaz7cmdf7keq6", + "task": "TwitterRetweet", + "title": "RT - Founder's Tag Utilities Unveiled", + "type": 1, + "desc": "Retweet specific tweets", + "category": "Social Tasks", + "score": 50, + "autoclaim": false, + "pretasks": ["e2yhq2lj30vwcpedv7p"], + "cfg": { "icon": "twitter", "content": "1789288035684921723"}, + "start": "2024-01-01 00:00", + "end": "2025-01-01 00:00", + "checkChain": false, + "params": { "time": 6, "failRate": 0 } + }, + { + "id": "e2cy5ha5nmre9w3pq3k", + "task": "TwitterLike", + "title": "Like - Founder's Tag Utilities Unveiled", + "type": 1, + "desc": "Like specific tweets", + "category": "Social Tasks", + "score": 50, + "autoclaim": false, + "pretasks": ["e2yhq2lj30vwcpedv7p"], + "cfg": { "icon": "twitter", "content": "1789288035684921723" }, + "start": "2024-01-01 00:00", + "end": "2025-01-01 00:00", + "checkChain": false, + "params": { "time": 6, "failRate": 0 } } ], "drawTime": 1715245160457, diff --git a/src/controllers/admin.controller.ts b/src/controllers/admin.controller.ts new file mode 100644 index 0000000..6d5f0de --- /dev/null +++ b/src/controllers/admin.controller.ts @@ -0,0 +1,44 @@ +import { ActivityUser } from 'models/ActivityUser' +import { BaseController, ZError, router } from 'zutils' +import { toEIP55 } from 'zutils/utils/chain.util' +import { createSigner } from 'fast-jwt' + +const sourceList = require('../../configs/admins.json') +const adminSet = new Set() +for (let o of sourceList) { + adminSet.add(o.toLowerCase()) +} + +/** + * 一些简单的管理接口 + */ + +class AdminController extends BaseController { + /** + * 任务列表 + */ + @router('get /api/g3y357zt67qryz3v6d6/fake_token/:address') + async taskList(req) { + const user = req.user + if (!adminSet.has(user.address.toLowerCase())) { + throw new ZError(10, 'not admin') + } + let { address } = req.params + address = toEIP55(address) + let record = await ActivityUser.findOne({ + address, + }) + if (!record) { + throw new ZError(11, 'user not found') + } + const signSync = createSigner({ + key: process.env.API_TOKEN_SECRET, + }) + const token = signSync({ + id: record.id, + address: record.address, + activity: 'uaw_activity', + }) + return { token } + } +} diff --git a/src/controllers/ingame.controller.ts b/src/controllers/ingame.controller.ts index 74e5428..7222033 100644 --- a/src/controllers/ingame.controller.ts +++ b/src/controllers/ingame.controller.ts @@ -81,10 +81,13 @@ class InGameController extends BaseController { for (let sub of list) { const Task = allTasks.get(sub.task) const taskInstance = new Task.default({ user, activity: req.activity }) - if (sub.status >= 0 && (await taskInstance.check(sub, gameData))) { + const checkResult = await taskInstance.check(sub, gameData) + if (sub.status >= 0 && !!checkResult) { sub.status = 2 if (sub.task === 'GoogleConnect') { sub.status = 3 + } else if (sub.task === 'NftHolderCheck') { + sub.ticket = checkResult } } sub.status = recordSet.has(sub.id) ? 3 : sub.status === 0 ? 1 : sub.status diff --git a/src/models/NftClaimRecord.ts b/src/models/NftClaimRecord.ts index 3f320af..85fa5ed 100644 --- a/src/models/NftClaimRecord.ts +++ b/src/models/NftClaimRecord.ts @@ -5,12 +5,15 @@ import { BaseModule } from './Base' @dbconn() @index({ address: 1, tokenId: 1, dateTag: 1 }, { unique: true }) @index({ address: 1, dateTag: 1 }, { unique: false }) +@index({ user: 1 }, { unique: false }) @modelOptions({ schemaOptions: { collection: 'nft_claim_record', timestamps: true }, }) class NftClaimRecordClass extends BaseModule { @prop() public address: string + @prop() + public user: string @prop() public tokenId: string diff --git a/src/taskingame/NftHolderCheck.ts b/src/taskingame/NftHolderCheck.ts index c2ba125..94bfca1 100644 --- a/src/taskingame/NftHolderCheck.ts +++ b/src/taskingame/NftHolderCheck.ts @@ -3,6 +3,7 @@ import { ITask } from './base/ITask' import { formatDate } from 'utils/utcdate.util' import { NftClaimRecord } from 'models/NftClaimRecord' import { ZError } from 'zutils' +import { InGameStats } from 'models/InGameStats' const sourceList = require('../../configs/nft_202403.json') const commonSet = new Set() @@ -65,10 +66,22 @@ export default class NftHolderCheck extends ITask { let claimRecord = new NftClaimRecord({ address, tokenId: record.tokenId, + user: this.user.id, dateTag, }) await claimRecord.save() } + if (ticket > 0) { + let saveRes = await InGameStats.findOneAndUpdate( + { user: this.user.id }, + { $inc: { ticket } }, + { + new: false, + upsert: false, + includeResultMetadata: true, + }, + ) + } return { score, ticket } } @@ -81,6 +94,17 @@ export default class NftHolderCheck extends ITask { historySet.add(history.tokenId) } let records = await NftHolder.find({ chain, address, user: this.user.address.toLowerCase() }) - return records.length > 0 + records = records.filter(o => !historySet.has(o.tokenId)) + let ticket = 0 + for (let record of records) { + if (commonSet.has(parseInt(record.tokenId))) { + ticket += rarityMap.get('Common') + } else if (legendarySet.has(parseInt(record.tokenId))) { + ticket += rarityMap.get('Legendary') + } else if (rareSet.has(parseInt(record.tokenId))) { + ticket += rarityMap.get('Rare') + } + } + return ticket } } diff --git a/src/taskingame/base/ITask.ts b/src/taskingame/base/ITask.ts index db211ee..894b576 100644 --- a/src/taskingame/base/ITask.ts +++ b/src/taskingame/base/ITask.ts @@ -54,7 +54,7 @@ export abstract class ITask { let ticket = 0 if (cfg.ticket > 0 && Date.now() >= this.activity.drawTime) { let canGet = false - if (cfg.tickettasks) { + if (cfg.tickettasks && cfg.tickettasks.length > 0) { let records = await InGameTaskRecord.find({ user: user.id, dateTag, task: { $in: cfg.tickettasks } }) if (records.length === cfg.tickettasks.length) { canGet = true @@ -70,7 +70,7 @@ export abstract class ITask { return { score, ticket } } - public async check(cfg: any, gameData: any) { + public async check(cfg: any, gameData: any): Promise { const subCfg = cfg.cfg const val = parseInt(gameData[subCfg.key] || '0') return val >= subCfg.amount