change task id

This commit is contained in:
CounterFire2023 2024-01-04 19:08:33 +08:00
parent ff41a769b7
commit eb9ce07ff5
16 changed files with 178 additions and 55 deletions

View File

@ -101,12 +101,14 @@ SiweMessage的nonce说明(具体参考例子):
"tasks": [ // 该活动需要完成的任务
{
"id": "任务id",
"task": "任务类型",
"title": "任务名",
"desc": "任务描述",
"type": 1, //任务类型, 1: 一次性任务, 2: 日常任务
"pretasks": ["task id 1"], //前置任务
"score": 0, // 完成任务可获得的积分
"category": "", // 任务分类
"data": {}, // 其他一些任务相关配置参数, 比如icon, 或者其他未考虑的参数
"autoclaim": false // 任务完成后是否自动获取奖励
}
],

View File

@ -4,50 +4,108 @@
"name": "First Activity1",
"description": "This is the first test activity",
"tasks": [{
"id": "TwitterConnect",
"id": "e2yhq2lj30vwcpedv7p",
"task": "TwitterConnect",
"title": "Connect Twitter",
"type": 1,
"desc": "",
"score": 100,
"category": "",
"autoclaim": true,
"data": {},
"params": {}
}, {
"id": "TwitterFollow",
"id": "e2fclylj30vwcpe0szl",
"task": "TwitterFollow",
"title": "Follow Twitter",
"type": 1,
"desc": "",
"category": "",
"desc": "Follow Counter Fires official X account",
"category": "Social Tasks",
"score": 100,
"autoclaim": false,
"pretasks": ["TwitterConnect"],
"data": {},
"params": {"time": 6, "failRate": 60}
}, {
"id": "OkxLogin",
"title": "okx wallet login",
"id": "e2feyflj30vwcpe0sjy",
"task": "TwitterFollow",
"title": "Follow Twitter",
"type": 1,
"desc": "",
"category": "",
"category": "Social Tasks",
"score": 100,
"autoclaim": false,
"pretasks": [],
"params": {}
"pretasks": ["TwitterConnect"],
"data": {},
"params": {"time": 6, "failRate": 60}
}, {
"id": "TwitterRetweet",
"title": "ReTwitt",
"id": "e2fuah0j30vwcpe0my7",
"task": "TwitterRetweet",
"title": "ReTwitter",
"type": 2,
"desc": "",
"category": "Social Tasks",
"score": 100,
"autoclaim": false,
"pretasks": ["TwitterConnect"],
"data": {},
"params": {"time": 6, "failRate": 60}
}, {
"id": "e2far3lj30vwcpe0mh7",
"task": "DiscordConnect",
"title": "Connect Discord",
"type": 2,
"desc": "",
"category": "",
"score": 100,
"autoclaim": false,
"pretasks": ["TwitterConnect"],
"pretasks": [],
"data": {},
"params": {}
}, {
"id": "e2far3lj30vwcpe0mf8",
"task": "DiscordJoin",
"title": "Join Discord",
"type": 2,
"desc": "",
"category": "",
"score": 100,
"autoclaim": false,
"pretasks": [],
"data": {},
"params": {"time": 6, "failRate": 60}
}, {
"id": "UpdateScore",
"id": "e2fak2lj30vwcpe0awc",
"task": "DiscordRole",
"title": "Discord Role",
"type": 2,
"desc": "",
"category": "Social Tasks",
"score": 100,
"autoclaim": false,
"pretasks": ["DiscordJoin"],
"data": {},
"params": {"time": 6, "failRate": 60}
}, {
"id": "e2f7fplj30vwcpe0l98",
"task": "OkxLogin",
"title": "okx wallet login",
"type": 1,
"desc": "",
"category": "Special Quests",
"score": 100,
"autoclaim": false,
"pretasks": [],
"data": {},
"params": {}
}, {
"id": "e2f7t4lj30vwcpe0ldr",
"task": "ShareCode",
"type": 1,
"show": false,
"autoclaim": false,
"pretasks": ["TwitterConnect", "TwitterFollow"],
"pretasks": [],
"data": {},
"params": {"score": [100, 20]}
}],
"startTime": 1702628292366,

View File

@ -63,7 +63,7 @@ export default class ActivityController extends BaseController {
let user = await ActivityUser.findById(id)
results.push({
rank: start + i / 2 + 1,
address: user.address,
address: user?.address || 'unknow',
score
})
}

View File

@ -44,20 +44,20 @@ export default class TasksController extends BaseController {
let modified = false;
let visibleTasks = new Set();
for (let task of activity.tasks) {
if (!allTasks.has(task.id)) {
if (!allTasks.has(task.task)) {
continue;
}
if (task.type === TaskTypeEnum.DAILY ) {
let id = `${task.id}:${dateTag}`
if (!taskAddedSet.has(id)) {
modified = true;
user.taskProgress.push({id, dateTag: dateTag, status: TaskStatusEnum.NOT_START})
user.taskProgress.push({id, task:task.task ,dateTag: dateTag, status: TaskStatusEnum.NOT_START})
}
if (task.show) visibleTasks.add(id);
} else if (task.type === TaskTypeEnum.ONCE ) {
if (!taskAddedSet.has(task.id)) {
modified = true;
user.taskProgress.push({id: task.id, status: TaskStatusEnum.NOT_START})
user.taskProgress.push({id: task.id, task: task.task, status: TaskStatusEnum.NOT_START})
}
if (task.show) visibleTasks.add(task.id);
}
@ -132,7 +132,7 @@ export default class TasksController extends BaseController {
throw new ZError(11, 'task not begin');
}
if (currentTask.status === TaskStatusEnum.RUNNING) {
let Task = require('../tasks/' + taskId);
let Task = require('../tasks/' + currentTask.task);
let taskInstance = new Task.default({user, activity});
await taskInstance.execute({task: currentTask});
}
@ -155,7 +155,7 @@ export default class TasksController extends BaseController {
throw new ZError(13, 'task not end')
}
const Task = require('../tasks/' + task);
const Task = require('../tasks/' + currentTask.task);
const taskInstance = new Task.default({user, activity});
await taskInstance.claimReward(currentTask);
return currentTask

View File

@ -15,6 +15,8 @@ export class TaskCfg {
@prop()
id: string
@prop()
task: string
@prop()
title: string
@prop({ enum: TaskTypeEnum, default: TaskTypeEnum.ONCE })
type: TaskTypeEnum
@ -31,6 +33,8 @@ export class TaskCfg {
@prop({default: true})
show: boolean
@prop({ type: mongoose.Schema.Types.Mixed })
data: any
@prop({ type: mongoose.Schema.Types.Mixed })
params: any
}
interface ActivityInfoClass extends Base, TimeStamps {}
@ -68,6 +72,7 @@ class ActivityInfoClass extends BaseModule {
if (task.show) {
tasks.push({
id: task.id,
task: task.task,
title: task.title,
desc: task.desc,
type: task.type,
@ -75,6 +80,7 @@ class ActivityInfoClass extends BaseModule {
score: task.score,
category: task.category,
autoclaim: task.autoclaim,
data: task.data,
})
}
}

View File

@ -19,6 +19,8 @@ export enum TaskStatusEnum {
export class TaskStatus {
@prop()
id: string
@prop()
task: string
// 0: not start, 1: running, 2: success
@prop({ enum: TaskStatusEnum, default: TaskStatusEnum.NOT_START })
status: TaskStatusEnum

View File

@ -0,0 +1,44 @@
import { checkDiscord } from "services/oauth.svr";
import { ITask } from "./base/ITask";
import { ZError } from "common/ZError";
import { TaskStatusEnum } from "models/ActivityUser";
import { TaskCfg } from "models/ActivityInfo";
export default class DiscordConnect extends ITask {
static desc = 'join discord'
static show: boolean = true
async execute(data: any) {
const { address } = this.params.user
const { task } = data
const res = await checkDiscord(address)
let cfg = this.params.activity.tasks.find((t: TaskCfg) => t.id === task.id)
if (res.status !== 200) {
throw new ZError(11, 'discord check failed')
}
if (res.data.errcode) {
throw new ZError(res.data.errcode, res.data.errmsg)
}
if (res.data.data.userid && task.status === TaskStatusEnum.RUNNING) {
task.status = TaskStatusEnum.SUCCESS
task.timeFinish = Date.now()
task.data = res.data.data
task.discordId = res.data.data.userid
try {
await this.params.user.save()
} catch(err) {
throw new ZError(100, 'discord already binded')
}
if (cfg.autoclaim) {
try {
await this.claimReward(task);
} catch(err) {
console.log(err)
}
}
}
return true
}
}

View File

@ -1,4 +1,3 @@
import { checkDiscord } from "services/oauth.svr";
import { ITask } from "./base/ITask";
import { ZError } from "common/ZError";
import { TaskStatusEnum } from "models/ActivityUser";
@ -9,32 +8,29 @@ export default class DiscordJoin extends ITask {
static show: boolean = true
async execute(data: any) {
const { address } = this.params.user
const res = await checkDiscord(address)
let cfg = this.params.activity.tasks.find((t: TaskCfg) => t.id === this.constructor.name)
if (res.status !== 200) {
throw new ZError(11, 'discord check failed')
}
if (res.data.errcode) {
throw new ZError(res.data.errcode, res.data.errmsg)
}
const { task } = data
if (res.data.data.userid && task.status === TaskStatusEnum.RUNNING) {
task.status = TaskStatusEnum.SUCCESS
task.timeFinish = Date.now()
task.data = res.data.data
task.discordId = res.data.data.userid
let cfg = this.params.activity.tasks.find((t: TaskCfg) => t.id === task.id)
let time = cfg.params.time;
if (Date.now() - task.timeStart < time * 1000) {
throw new ZError(11, 'check discord join failed')
}
let num = Math.random() * 100
if (num < cfg.params.failRate) {
throw new ZError(12, 'check discord join failed')
}
task.status = TaskStatusEnum.SUCCESS
task.timeFinish = Date.now()
task.data = {}
try {
await this.params.user.save()
} catch(err) {
throw new ZError(100, 'already join discord')
}
if (cfg.autoclaim) {
try {
await this.params.user.save()
await this.claimReward(task);
} catch(err) {
throw new ZError(100, 'discord already binded')
}
if (cfg.autoclaim) {
try {
await this.claimReward(task);
} catch(err) {
console.log(err)
}
console.log(err)
}
}
return true

View File

@ -8,7 +8,7 @@ export default class DiscordRole extends ITask {
static show: boolean = true
async execute(data: any) {
const { task } = data
let cfg = this.params.activity.tasks.find((t: TaskCfg) => t.id === this.constructor.name)
let cfg = this.params.activity.tasks.find((t: TaskCfg) => t.id === task.id)
let time = cfg.params.time;
if (Date.now() - task.timeStart < time * 1000) {
throw new ZError(11, 'check discord role failed')

View File

@ -12,7 +12,7 @@ export default class OkxLogin extends ITask {
async execute(data: any) {
const { task } = data
const { activity } = this.params.user
let cfg = this.params.activity.tasks.find((t: TaskCfg) => t.id === this.constructor.name)
let cfg = this.params.activity.tasks.find((t: TaskCfg) => t.id === task.id)
let wallet = 'okx';
let record = LoginRecord.findOne({ user: this.params.user.id, activity, wallet})
if (!record ) {

View File

@ -29,8 +29,8 @@ export default class ShareCode extends ITask {
static show: boolean = false
async execute(data: any) {
let task = this.params.user.taskProgress.find((t: TaskStatus) => t.id === this.constructor.name)
let cfg = this.params.activity.tasks.find((t: TaskCfg) => t.id === this.constructor.name)
let {task} = data
let cfg = this.params.activity.tasks.find((t: TaskCfg) => t.id === task.id)
let scores = cfg.params.score;
task.status = TaskStatusEnum.SUCCESS
task.timeFinish = Date.now()
@ -39,7 +39,7 @@ export default class ShareCode extends ITask {
// According to configuration, add score to user who invite current user
if (cfg.autoclaim) {
try {
await updateInviteScore(this.params.user, scores, 0, this.constructor.name)
await updateInviteScore(this.params.user, scores, 0, task.task)
} catch(err) {
console.log(err)
}
@ -48,8 +48,8 @@ export default class ShareCode extends ITask {
}
public async claimReward(task: TaskStatus) {
let cfg = this.params.activity.tasks.find((t: TaskCfg) => t.id === this.constructor.name)
let cfg = this.params.activity.tasks.find((t: TaskCfg) => t.id === task.id)
let scores = cfg.params.score;
await updateInviteScore(this.params.user, scores, 0, this.constructor.name)
await updateInviteScore(this.params.user, scores, 0, task.task)
}
}

View File

@ -28,7 +28,7 @@ export default class TwitterConnect extends ITask {
} catch(err) {
throw new ZError(100, 'twitter already binded')
}
let cfg = this.params.activity.tasks.find((t: TaskCfg) => t.id === this.constructor.name)
let cfg = this.params.activity.tasks.find((t: TaskCfg) => t.id === task.id)
if (cfg.autoclaim) {
try {
await this.claimReward(task);

View File

@ -8,7 +8,7 @@ export default class TwitterFollow extends ITask {
static show: boolean = true
async execute(data: any) {
const { task } = data
let cfg = this.params.activity.tasks.find((t: TaskCfg) => t.id === this.constructor.name)
let cfg = this.params.activity.tasks.find((t: TaskCfg) => t.id === task.id)
let time = cfg.params.time;
if (Date.now() - task.timeStart < time * 1000) {
throw new ZError(11, 'follow failed')

View File

@ -7,7 +7,7 @@ export default class TwitterRetweet extends ITask {
static show: boolean = true
async execute(data: any) {
const { task } = data
let cfg = this.params.activity.tasks.find(t => t.id === this.constructor.name)
let cfg = this.params.activity.tasks.find(t => t.id === task.id)
let time = cfg.params.time;
if (Date.now() - task.timeStart < time * 1000) {
throw new ZError(11, 'retweet failed')

View File

@ -25,7 +25,7 @@ export abstract class ITask {
user: user.id,
score: cfg.score,
activity: user.activity,
scoreType: taskId,
scoreType: cfg.task,
scoreParams: {
date: dateTag,
taskId: task.id

View File

@ -136,4 +136,19 @@ export const base58ToHex = (base58String: string) => {
num = num * BigInt(58) + BigInt(charIndex);
}
return num.toString(16);
}
export const hexToBase32 = (hexString: string) => {
const bytes = hexString.match(/.{1,2}/g).map(byte => parseInt(byte, 16));
const base32Alphabet = 'qpzry9x8gf2tvdw0s3jn54khce6mua7l';
let base32String = '';
let num = BigInt('0x' + hexString);
while (num > BigInt(0)) {
const remainder = num % BigInt(32);
num = num / BigInt(32);
base32String = base32Alphabet[Number(remainder)] + base32String;
}
return base32String;
}