增加nft burn, youtube follow, youtube post相关模块
This commit is contained in:
parent
970f004dad
commit
bd2b7b577b
@ -86,6 +86,30 @@
|
||||
"pretasks": ["e2far3lj30vwcpe0mf8"],
|
||||
"cfg": {"icon": "discord"},
|
||||
"params": {"time": 6, "failRate": 60}
|
||||
}, {
|
||||
"id": "e2feyflj30vwcpe0sjx",
|
||||
"task": "YoutubeFollow",
|
||||
"title": "Follow Youtube",
|
||||
"type": 1,
|
||||
"desc": "Follow Counter Fire’s official YTB account",
|
||||
"category": "Social Tasks",
|
||||
"score": 100,
|
||||
"autoclaim": false,
|
||||
"pretasks": [],
|
||||
"cfg": {"icon": "youtube"},
|
||||
"params": {"time": 6, "failRate": 60}
|
||||
}, {
|
||||
"id": "e2feyflj30vwcpe0sjz",
|
||||
"task": "YoutubePost",
|
||||
"title": "Post Youtube",
|
||||
"type": 1,
|
||||
"desc": "Post a video introducing @_CounterFire",
|
||||
"category": "Social Tasks",
|
||||
"score": 100,
|
||||
"autoclaim": false,
|
||||
"pretasks": [],
|
||||
"cfg": {"icon": "youtube"},
|
||||
"params": {"time": 6, "failRate": 60}
|
||||
}, {
|
||||
"id": "e2f7fplj30vwcpe0l98",
|
||||
"task": "OkxLogin",
|
||||
@ -99,10 +123,10 @@
|
||||
"cfg": {"account": "okx", "icon": "okx"},
|
||||
"params": {}
|
||||
}, {
|
||||
"id": "e2f7fplj30vwcpe0l98",
|
||||
"id": "e2f7fplj30vwcpe0l96",
|
||||
"task": "DailyCheckIn",
|
||||
"title": "daily checkin",
|
||||
"type": 1,
|
||||
"type": 2,
|
||||
"desc": "",
|
||||
"category": "Special Quests",
|
||||
"score": 20,
|
||||
@ -110,6 +134,18 @@
|
||||
"pretasks": [],
|
||||
"cfg": {"score": [0, 15, 20, 20, 40, 40, 60]},
|
||||
"params": {"days": 1, "score": [0, 15, 20, 20, 40, 40, 60]}
|
||||
}, {
|
||||
"id": "e2f7fplj30vwcpe0l97",
|
||||
"task": "DailyCheckIn",
|
||||
"title": "daily checkin",
|
||||
"type": 1,
|
||||
"desc": "Check-in for 3 consecutive days.",
|
||||
"category": "Referral to Earn",
|
||||
"score": 100,
|
||||
"autoclaim": false,
|
||||
"pretasks": [],
|
||||
"cfg": {},
|
||||
"params": {"days": 3}
|
||||
}, {
|
||||
"id": "e2f7t4lj30vwcpe0ldr",
|
||||
"task": "ShareCode",
|
||||
@ -120,6 +156,57 @@
|
||||
"cfg": {},
|
||||
"score": 100,
|
||||
"params": {"score": [100, 20]}
|
||||
}, {
|
||||
"id": "e2f7t4lj31vwcpe0ldr",
|
||||
"task": "BurnNft",
|
||||
"type": 1,
|
||||
"show": true,
|
||||
"title": "Hero NFT",
|
||||
"desc": "Click to burn and redeem Flame",
|
||||
"category": "CF Pal",
|
||||
"autoclaim": false,
|
||||
"pretasks": [],
|
||||
"cfg": {"address": "0x59e751c2037B710090035B6ea928e0cce80aC03f"},
|
||||
"score": 200,
|
||||
"params": {"address": "0x59e751c2037B710090035B6ea928e0cce80aC03f"}
|
||||
}, {
|
||||
"id": "e2f7t4lj32vwcpe0ldr",
|
||||
"task": "BurnNft",
|
||||
"type": 1,
|
||||
"show": true,
|
||||
"title": "Candy Badge",
|
||||
"desc": "Click to burn and redeem Flame",
|
||||
"category": "CF Pal",
|
||||
"pretasks": [],
|
||||
"cfg": {"address": "0x6a673D946a976776fd5F163d9d831b2fEB600015"},
|
||||
"score": 100,
|
||||
"params": {"address": "0x6a673D946a976776fd5F163d9d831b2fEB600015"}
|
||||
}, {
|
||||
"id": "e2f7t4lj33vwcpe0ldr",
|
||||
"task": "BurnNft",
|
||||
"type": 1,
|
||||
"show": true,
|
||||
"title": "Explorer Badge",
|
||||
"desc": "Click to burn and redeem Flame",
|
||||
"category": "CF Pal",
|
||||
"autoclaim": false,
|
||||
"pretasks": [],
|
||||
"cfg": {"address": "0x7b6399DFbed8Bc46F6A498C6B1040E80c2B5C4bc"},
|
||||
"score": 100,
|
||||
"params": {"address": "0x7b6399DFbed8Bc46F6A498C6B1040E80c2B5C4bc"}
|
||||
}, {
|
||||
"id": "e2f7t4lj33vwcpe0ldr",
|
||||
"task": "BurnNft",
|
||||
"type": 1,
|
||||
"show": true,
|
||||
"title": "Gacha Badge",
|
||||
"desc": "Click to burn and redeem Flame",
|
||||
"category": "CF Pal",
|
||||
"autoclaim": false,
|
||||
"pretasks": [],
|
||||
"cfg": {"address": "0xe2E4D5a4045fBFcbCBECAf5b8A94303712d2FA97"},
|
||||
"score": 200,
|
||||
"params": {"address": "0xe2E4D5a4045fBFcbCBECAf5b8A94303712d2FA97"}
|
||||
}],
|
||||
"startTime": 1702628292366,
|
||||
"endTime": 1705220292366
|
||||
|
31
src/models/NFTBrunRecord.ts
Normal file
31
src/models/NFTBrunRecord.ts
Normal file
@ -0,0 +1,31 @@
|
||||
import { Severity, getModelForClass, index, modelOptions, mongoose, prop } from '@typegoose/typegoose'
|
||||
import { dbconn } from 'decorators/dbconn'
|
||||
import { BaseModule } from './Base'
|
||||
|
||||
|
||||
@dbconn()
|
||||
@index({ user: 1, chain: 1, address: 1}, { unique: false })
|
||||
@index({ user: 1, chain: 1, address: 1, tokenId: 1 }, { unique: true })
|
||||
@modelOptions({ schemaOptions: { collection: 'nft_burn_record', timestamps: true }, options: { allowMixed: Severity.ALLOW } })
|
||||
class NftBurnRecordClass extends BaseModule {
|
||||
@prop({ required: true})
|
||||
public user: string
|
||||
|
||||
@prop()
|
||||
public chain: number
|
||||
|
||||
@prop({ required: true})
|
||||
public address: string
|
||||
|
||||
@prop()
|
||||
public tokenId: number
|
||||
|
||||
@prop()
|
||||
public activity: string
|
||||
@prop()
|
||||
public task: string
|
||||
|
||||
}
|
||||
|
||||
export const NftBurnRecord = getModelForClass(NftBurnRecordClass, { existingConnection: NftBurnRecordClass['db'] })
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
export const queryCheckInList = async (address: string, days: string | number | string[], max: number = 0) => {
|
||||
export const queryCheckInList = async (address: string, days: string | number | string[], limit: number = 0) => {
|
||||
const url = process.env.CHAIN_SVR + '/task/check_in'
|
||||
return fetch(url, {
|
||||
method: 'POST',
|
||||
@ -7,7 +7,31 @@ export const queryCheckInList = async (address: string, days: string | number |
|
||||
body: JSON.stringify({
|
||||
address,
|
||||
days,
|
||||
max
|
||||
limit
|
||||
})
|
||||
}).then((res) => res.json())
|
||||
}
|
||||
|
||||
export const queryCheckInSeq = async (address: string) =>{
|
||||
const url = process.env.CHAIN_SVR + '/task/check_in/max_seq'
|
||||
return fetch(url, {
|
||||
method: 'POST',
|
||||
headers: {"Content-Type": "application/json"},
|
||||
body: JSON.stringify({
|
||||
address,
|
||||
})
|
||||
}).then((res) => res.json())
|
||||
}
|
||||
|
||||
export const queryBurnNftList = async (address: string, user: string, chain: number) => {
|
||||
const url = process.env.CHAIN_SVR + '/task/nft/checkburn'
|
||||
return fetch(url, {
|
||||
method: 'POST',
|
||||
headers: {"Content-Type": "application/json"},
|
||||
body: JSON.stringify({
|
||||
address,
|
||||
user,
|
||||
chain
|
||||
})
|
||||
}).then((res) => res.json())
|
||||
}
|
64
src/tasks/BurnNft.ts
Normal file
64
src/tasks/BurnNft.ts
Normal file
@ -0,0 +1,64 @@
|
||||
import { ITask } from "./base/ITask";
|
||||
import { TaskStatusEnum } from "models/ActivityUser";
|
||||
import { ZError } from "common/ZError";
|
||||
import { TaskCfg } from "models/ActivityInfo";
|
||||
import { queryBurnNftList } from "services/chain.svr";
|
||||
import { NftBurnRecord } from "models/NFTBrunRecord";
|
||||
|
||||
export default class BurnNft extends ITask {
|
||||
static desc = 'Butn NFT'
|
||||
static show: boolean = true
|
||||
async execute(data: any) {
|
||||
const { task } = data
|
||||
let cfg = this.params.activity.tasks.find((t: TaskCfg) => t.id === task.id)
|
||||
const address = cfg.params.address.toLowerCase()
|
||||
const chain = parseInt(process.env.CHAIN)
|
||||
const res = await queryBurnNftList(address, this.params.user.address, chain)
|
||||
if (res.errcode) {
|
||||
throw new ZError(res.errcode, res.errmsg)
|
||||
}
|
||||
const nftList = res.data
|
||||
const localNft = await NftBurnRecord.find({
|
||||
user: this.params.user.id,
|
||||
chain,
|
||||
address
|
||||
})
|
||||
const localNftSet = new Set();
|
||||
for (let nft of localNft) {
|
||||
localNftSet.add(nft.tokenId)
|
||||
}
|
||||
let finishNft
|
||||
for (let nft of nftList) {
|
||||
if (!localNftSet.has(nft.tokenId)) {
|
||||
finishNft = nft.tokenId
|
||||
break;
|
||||
}
|
||||
}
|
||||
const record = new NftBurnRecord({
|
||||
user: this.params.user.id,
|
||||
chain,
|
||||
address,
|
||||
tokenId: finishNft,
|
||||
activity: this.params.activity.id,
|
||||
task: task.id
|
||||
})
|
||||
await record.save()
|
||||
task.status = TaskStatusEnum.SUCCESS
|
||||
task.timeFinish = Date.now()
|
||||
task.data = {tokenId: finishNft}
|
||||
try {
|
||||
await this.params.user.save()
|
||||
} catch(err) {
|
||||
throw new ZError(100, 'save failed')
|
||||
}
|
||||
if (cfg.autoclaim) {
|
||||
try {
|
||||
await this.claimReward(task);
|
||||
} catch(err) {
|
||||
console.log(err)
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
import { ITask } from "./base/ITask";
|
||||
import { ZError } from "common/ZError";
|
||||
import { TaskStatus, TaskStatusEnum } from "models/ActivityUser";
|
||||
import { TaskCfg } from "models/ActivityInfo";
|
||||
import { queryCheckInList } from "services/chain.svr";
|
||||
import { TaskCfg, TaskTypeEnum } from "models/ActivityInfo";
|
||||
import { queryCheckInList, queryCheckInSeq } from "services/chain.svr";
|
||||
import { updateRankScore } from "services/rank.svr";
|
||||
|
||||
// TODO:: test
|
||||
@ -22,12 +22,17 @@ export default class DailyCheckIn extends ITask {
|
||||
let cfg = this.params.activity.tasks.find((t: TaskCfg) => t.id === task.id)
|
||||
const days = cfg.params.days || 1
|
||||
const limit = cfg.params.limit || 0
|
||||
const res = await queryCheckInList(address, days - 1, limit)
|
||||
const res = cfg.type === TaskTypeEnum.DAILY ?
|
||||
await queryCheckInList(address, days - 1, limit)
|
||||
: await queryCheckInSeq(address)
|
||||
if (res.errcode) {
|
||||
throw new ZError(res.errcode, res.errmsg)
|
||||
}
|
||||
let success = false
|
||||
|
||||
|
||||
if (task.status === TaskStatusEnum.RUNNING && res.data.length >= days) {
|
||||
if ((cfg.type === TaskTypeEnum.DAILY && task.status === TaskStatusEnum.RUNNING && res.data.length >= days)
|
||||
|| (cfg.type === TaskTypeEnum.ONCE && task.status === TaskStatusEnum.RUNNING && res.data.count >= days)) {
|
||||
task.status = TaskStatusEnum.SUCCESS
|
||||
task.timeFinish = Date.now()
|
||||
task.data = res.data
|
||||
@ -48,33 +53,37 @@ export default class DailyCheckIn extends ITask {
|
||||
}
|
||||
|
||||
public async claimReward(task: TaskStatus) {
|
||||
// await super.claimReward(task);
|
||||
// 增加连续签到奖励分
|
||||
// 请求前7天的签到记录, 往前查找连续签到的记录,
|
||||
const res = await queryCheckInList(this.params.user.address, 1, 0)
|
||||
const [taskId, dateTag] = task.id.split(':');
|
||||
let list: { day: string, time: number, count: number }[] = res.data;
|
||||
let cfg = this.params.activity.tasks.find((t: TaskCfg) => t.id === task.id)
|
||||
const countCfg = cfg.params.score.length;
|
||||
let count = list.length > 0 ? list[0].count : 0;
|
||||
let seq = count % countCfg;
|
||||
let score = cfg.params.score[seq] + cfg.score;
|
||||
const user = this.params.user
|
||||
if (user.boost > 1 && Date.now() < user.boostExpire) {
|
||||
score = Math.floor(score * user.boost)
|
||||
}
|
||||
await updateRankScore({
|
||||
user: this.params.user.id,
|
||||
score: score,
|
||||
activity: this.params.user.activity,
|
||||
scoreType: cfg.task,
|
||||
scoreParams: {
|
||||
taskId: task.id,
|
||||
date: dateTag,
|
||||
bouns: score,
|
||||
boost: user.boost,
|
||||
if (cfg.type === TaskTypeEnum.DAILY) {
|
||||
const res = await queryCheckInList(this.params.user.address, 1, 0)
|
||||
const [taskId, dateTag] = task.id.split(':');
|
||||
let list: { day: string, time: number, count: number }[] = res.data;
|
||||
|
||||
const countCfg = cfg.params.score.length;
|
||||
let count = list.length > 0 ? list[0].count : 0;
|
||||
let seq = count % countCfg;
|
||||
let score = cfg.params.score[seq] || 0 + cfg.score;
|
||||
const user = this.params.user
|
||||
if (user.boost > 1 && Date.now() < user.boostExpire) {
|
||||
score = Math.floor(score * user.boost)
|
||||
}
|
||||
})
|
||||
await updateRankScore({
|
||||
user: this.params.user.id,
|
||||
score: score,
|
||||
activity: this.params.user.activity,
|
||||
scoreType: cfg.task,
|
||||
scoreParams: {
|
||||
taskId: task.id,
|
||||
date: dateTag,
|
||||
bouns: score,
|
||||
boost: user.boost,
|
||||
}
|
||||
})
|
||||
} else {
|
||||
super.claimReward(task);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
38
src/tasks/YoutubeFollow.ts
Normal file
38
src/tasks/YoutubeFollow.ts
Normal file
@ -0,0 +1,38 @@
|
||||
import { ITask } from "./base/ITask";
|
||||
import { TaskStatusEnum } from "models/ActivityUser";
|
||||
import { ZError } from "common/ZError";
|
||||
import { TaskCfg } from "models/ActivityInfo";
|
||||
|
||||
export default class YoutubeFollow extends ITask {
|
||||
static desc = 'youtube follow'
|
||||
static show: boolean = true
|
||||
async execute(data: any) {
|
||||
const { task } = data
|
||||
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')
|
||||
}
|
||||
let num = Math.random() * 100
|
||||
if (num < cfg.params.failRate) {
|
||||
throw new ZError(12, 'follow failed')
|
||||
}
|
||||
task.status = TaskStatusEnum.SUCCESS
|
||||
task.timeFinish = Date.now()
|
||||
task.data = {}
|
||||
try {
|
||||
await this.params.user.save()
|
||||
} catch(err) {
|
||||
throw new ZError(100, 'save failed')
|
||||
}
|
||||
if (cfg.autoclaim) {
|
||||
try {
|
||||
await this.claimReward(task);
|
||||
} catch(err) {
|
||||
console.log(err)
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
37
src/tasks/YoutubePost.ts
Normal file
37
src/tasks/YoutubePost.ts
Normal file
@ -0,0 +1,37 @@
|
||||
import { ZError } from "common/ZError";
|
||||
import { ITask } from "./base/ITask";
|
||||
import { TaskStatusEnum } from "models/ActivityUser";
|
||||
|
||||
export default class YoutubePost extends ITask {
|
||||
static desc = 'youtube post'
|
||||
static show: boolean = true
|
||||
async execute(data: any) {
|
||||
const { task } = data
|
||||
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, 'post failed')
|
||||
}
|
||||
let num = Math.random() * 100
|
||||
if (num < cfg.params.failRate) {
|
||||
throw new ZError(12, 'post failed')
|
||||
}
|
||||
task.status = TaskStatusEnum.SUCCESS
|
||||
task.timeFinish = Date.now()
|
||||
task.data = {}
|
||||
try {
|
||||
await this.params.user.save()
|
||||
} catch(err) {
|
||||
throw new ZError(100, 'save failed')
|
||||
}
|
||||
if (cfg.autoclaim) {
|
||||
try {
|
||||
await this.claimReward(task);
|
||||
} catch(err) {
|
||||
console.log(err)
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user