add twitter connect, accomplish other tasks
This commit is contained in:
parent
35c319d311
commit
5d2a3af490
@ -4,20 +4,23 @@
|
|||||||
"name": "First Activity1",
|
"name": "First Activity1",
|
||||||
"description": "This is the first test activity",
|
"description": "This is the first test activity",
|
||||||
"tasks": [{
|
"tasks": [{
|
||||||
"task": "TwitterFollow",
|
"task": "TwitterConnect",
|
||||||
"params": {}
|
"params": {}
|
||||||
|
}, {
|
||||||
|
"task": "TwitterFollow",
|
||||||
|
"params": {"time": 6, "failRate": 60}
|
||||||
}, {
|
}, {
|
||||||
"task": "TwitterRetweet",
|
"task": "TwitterRetweet",
|
||||||
"params": {}
|
"params": {"time": 6, "failRate": 60}
|
||||||
}, {
|
}, {
|
||||||
"task": "DiscordJoin",
|
"task": "DiscordJoin",
|
||||||
"params": {}
|
"params": {}
|
||||||
}, {
|
}, {
|
||||||
"task": "DiscordRole",
|
"task": "DiscordRole",
|
||||||
"params": {}
|
"params": {"time": 6, "failRate": 60}
|
||||||
}, {
|
}, {
|
||||||
"task": "UpdateScore",
|
"task": "UpdateScore",
|
||||||
"params": {}
|
"params": {"score": [100, 20]}
|
||||||
}],
|
}],
|
||||||
"startTime": 1702628292366,
|
"startTime": 1702628292366,
|
||||||
"endTime": 1705220292366
|
"endTime": 1705220292366
|
||||||
|
@ -2,7 +2,8 @@ import { ZError } from "common/ZError";
|
|||||||
import BaseController, { ROLE_ANON } from "common/base.controller";
|
import BaseController, { ROLE_ANON } from "common/base.controller";
|
||||||
import { role, router } from "decorators/router";
|
import { role, router } from "decorators/router";
|
||||||
import { all } from "deepmerge";
|
import { all } from "deepmerge";
|
||||||
import { ActivityUser, TaskStatusEnum } from "models/ActivityUser";
|
import { ActivityInfo } from "models/ActivityInfo";
|
||||||
|
import { ActivityUser, TaskStatus, TaskStatusEnum } from "models/ActivityUser";
|
||||||
import { join } from 'path'
|
import { join } from 'path'
|
||||||
const fs = require('fs')
|
const fs = require('fs')
|
||||||
|
|
||||||
@ -30,14 +31,16 @@ const parseCurrentTask = (user: typeof ActivityUser, task: string) => {
|
|||||||
}
|
}
|
||||||
let preEnd = true;
|
let preEnd = true;
|
||||||
let currentTask = null;
|
let currentTask = null;
|
||||||
|
let nextTask = null;
|
||||||
for (let taskData of user.taskProgress) {
|
for (let taskData of user.taskProgress) {
|
||||||
if (taskData.id === task) {
|
if (taskData.id === task) {
|
||||||
currentTask = taskData;
|
currentTask = taskData;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
if (taskData.status !== 2) {
|
if (taskData.status !== 2 && !currentTask) {
|
||||||
preEnd = false;
|
preEnd = false;
|
||||||
break;
|
}
|
||||||
|
if (currentTask && !nextTask) {
|
||||||
|
nextTask = taskData;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!preEnd) {
|
if (!preEnd) {
|
||||||
@ -46,7 +49,20 @@ const parseCurrentTask = (user: typeof ActivityUser, task: string) => {
|
|||||||
if (!currentTask) {
|
if (!currentTask) {
|
||||||
throw new ZError(13, 'task not found')
|
throw new ZError(13, 'task not found')
|
||||||
}
|
}
|
||||||
return {preEnd, currentTask}
|
return {preEnd, currentTask, nextTask}
|
||||||
|
}
|
||||||
|
|
||||||
|
const parseNextTask = async (
|
||||||
|
user: typeof ActivityUser,
|
||||||
|
activity: typeof ActivityInfo,
|
||||||
|
task: TaskStatus) => {
|
||||||
|
let Task = require('../tasks/' + task.id);
|
||||||
|
if (!Task.default.auto) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
let taskInstance = new Task.default({user, activity});
|
||||||
|
let result = await taskInstance.execute({});
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
export default class TasksController extends BaseController {
|
export default class TasksController extends BaseController {
|
||||||
|
|
||||||
@ -69,7 +85,7 @@ export default class TasksController extends BaseController {
|
|||||||
if (!user.taskProgress || user.taskProgress.length === 0) {
|
if (!user.taskProgress || user.taskProgress.length === 0) {
|
||||||
for (let task of activity.tasks) {
|
for (let task of activity.tasks) {
|
||||||
if (allTasks.has(task.task)) {
|
if (allTasks.has(task.task)) {
|
||||||
user.taskProgress.push({id: task.task, status: 0, time: 0})
|
user.taskProgress.push({id: task.task, status: 0})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await user.save();
|
await user.save();
|
||||||
@ -94,11 +110,17 @@ export default class TasksController extends BaseController {
|
|||||||
let user = req.user;
|
let user = req.user;
|
||||||
let activity = req.activity;
|
let activity = req.activity;
|
||||||
let { task } = req.params;
|
let { task } = req.params;
|
||||||
let { currentTask } = parseCurrentTask(user, task);
|
let { currentTask, nextTask } = parseCurrentTask(user, task);
|
||||||
|
if (currentTask.status !== TaskStatusEnum.RUNNING) {
|
||||||
|
throw new ZError(11, 'task not begin');
|
||||||
|
}
|
||||||
if (currentTask.status !== TaskStatusEnum.SUCCESS) {
|
if (currentTask.status !== TaskStatusEnum.SUCCESS) {
|
||||||
let Task = require('../tasks/' + task);
|
let Task = require('../tasks/' + task);
|
||||||
let taskInstance = new Task.default({user, activity});
|
let taskInstance = new Task.default({user, activity});
|
||||||
await taskInstance.check();
|
let result = await taskInstance.execute({});
|
||||||
|
if (result) {
|
||||||
|
await parseNextTask(user, activity, nextTask);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return currentTask
|
return currentTask
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ export class TaskStatus {
|
|||||||
@prop()
|
@prop()
|
||||||
timeFinish: number
|
timeFinish: number
|
||||||
@prop({ type: mongoose.Schema.Types.Mixed })
|
@prop({ type: mongoose.Schema.Types.Mixed })
|
||||||
params: any
|
data: any
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ActivityUserClass extends Base, TimeStamps {}
|
interface ActivityUserClass extends Base, TimeStamps {}
|
||||||
@ -34,6 +34,8 @@ interface ActivityUserClass extends Base, TimeStamps {}
|
|||||||
@index({ address: 1, activity: 1 }, { unique: true })
|
@index({ address: 1, activity: 1 }, { unique: true })
|
||||||
@index({ inviteCode: 1, activity: 1 }, { unique: true })
|
@index({ inviteCode: 1, activity: 1 }, { unique: true })
|
||||||
@index({ inviteUser: 1, activity: 1 }, { unique: false })
|
@index({ inviteUser: 1, activity: 1 }, { unique: false })
|
||||||
|
@index({ twitterId: 1 }, { unique: true, partialFilterExpression: { twitterId: { $exists: true } } })
|
||||||
|
@index({ discordId: 1 }, { unique: true, partialFilterExpression: { discordId: { $exists: true } } })
|
||||||
@modelOptions({ schemaOptions: { collection: 'activity_user', timestamps: true }, options: { allowMixed: Severity.ALLOW } })
|
@modelOptions({ schemaOptions: { collection: 'activity_user', timestamps: true }, options: { allowMixed: Severity.ALLOW } })
|
||||||
@pre<ActivityUserClass>('save', async function () {
|
@pre<ActivityUserClass>('save', async function () {
|
||||||
if (!this.inviteCode) {
|
if (!this.inviteCode) {
|
||||||
@ -68,6 +70,11 @@ class ActivityUserClass extends BaseModule {
|
|||||||
@prop()
|
@prop()
|
||||||
public comment?: string
|
public comment?: string
|
||||||
|
|
||||||
|
@prop()
|
||||||
|
public twitterId?: string
|
||||||
|
@prop()
|
||||||
|
public discordId: string
|
||||||
|
|
||||||
@prop()
|
@prop()
|
||||||
public lastLogin?: Date
|
public lastLogin?: Date
|
||||||
|
|
||||||
|
@ -1,14 +1,35 @@
|
|||||||
|
import { checkDiscord } from "services/oauth.svr";
|
||||||
import { ITask } from "./base/ITask";
|
import { ITask } from "./base/ITask";
|
||||||
|
import { ZError } from "common/ZError";
|
||||||
|
import { TaskStatusEnum } from "models/ActivityUser";
|
||||||
|
|
||||||
export default class DiscordJoin extends ITask {
|
export default class DiscordJoin extends ITask {
|
||||||
static desc = 'join discord'
|
static desc = 'join discord'
|
||||||
static show: boolean = true
|
static show: boolean = true
|
||||||
|
|
||||||
async execute(data: any) {
|
async execute(data: any) {
|
||||||
// do nothing
|
let { address } = this.params.user
|
||||||
}
|
let res = await checkDiscord(address)
|
||||||
async check(data: any) {
|
console.log(res);
|
||||||
// do nothing
|
if (res.status !== 200) {
|
||||||
|
throw new ZError(11, 'discord check failed')
|
||||||
|
}
|
||||||
|
if (res.data.errcode) {
|
||||||
|
throw new ZError(res.data.errcode, res.data.errmsg)
|
||||||
|
}
|
||||||
|
let task = this.params.user.taskProgress.find(t => t.id === this.constructor.name)
|
||||||
|
if (res.data.data.userid && task.status !== TaskStatusEnum.SUCCESS) {
|
||||||
|
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')
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,13 +1,25 @@
|
|||||||
|
import { ZError } from "common/ZError";
|
||||||
import { ITask } from "./base/ITask";
|
import { ITask } from "./base/ITask";
|
||||||
|
import { TaskStatusEnum } from "models/ActivityUser";
|
||||||
|
|
||||||
export default class DiscordRole extends ITask {
|
export default class DiscordRole extends ITask {
|
||||||
static desc = 'acquire discord role'
|
static desc = 'acquire discord role'
|
||||||
static show: boolean = true
|
static show: boolean = true
|
||||||
async execute(data: any) {
|
async execute(data: any) {
|
||||||
// do nothing
|
let task = this.params.user.taskProgress.find(t => t.id === this.constructor.name)
|
||||||
}
|
let cfg = this.params.activity.tasks.find(t => t.task === this.constructor.name)
|
||||||
async check(data: any) {
|
let time = cfg.params.time;
|
||||||
// do nothing
|
if (Date.now() - task.timeStart < time * 1000) {
|
||||||
|
throw new ZError(11, 'check discord role failed')
|
||||||
|
}
|
||||||
|
let num = Math.random() * 100
|
||||||
|
if (num < cfg.params.failRate) {
|
||||||
|
throw new ZError(12, 'check discord role failed')
|
||||||
|
}
|
||||||
|
task.status = TaskStatusEnum.SUCCESS
|
||||||
|
task.timeFinish = Date.now()
|
||||||
|
task.data = {}
|
||||||
|
await this.params.user.save()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
36
src/tasks/TwitterConnect.ts
Normal file
36
src/tasks/TwitterConnect.ts
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import { checkTwitter } from "services/oauth.svr";
|
||||||
|
import { ITask } from "./base/ITask";
|
||||||
|
import { ActivityUser, TaskStatusEnum } from "models/ActivityUser";
|
||||||
|
import { ZError } from "common/ZError";
|
||||||
|
|
||||||
|
export default class TwitterConnect extends ITask {
|
||||||
|
static desc = 'twitter connect'
|
||||||
|
static show: boolean = true
|
||||||
|
|
||||||
|
async execute(data: any) {
|
||||||
|
let { address } = this.params.user
|
||||||
|
let res = await checkTwitter(address)
|
||||||
|
console.log(res);
|
||||||
|
if (res.status !== 200) {
|
||||||
|
throw new ZError(11, 'twitter check failed')
|
||||||
|
}
|
||||||
|
if (res.data.errcode) {
|
||||||
|
throw new ZError(res.data.errcode, res.data.errmsg)
|
||||||
|
}
|
||||||
|
let task = this.params.user.taskProgress.find(t => t.id === this.constructor.name)
|
||||||
|
if (res.data.data.userid && task.status !== TaskStatusEnum.SUCCESS) {
|
||||||
|
task.status = TaskStatusEnum.SUCCESS
|
||||||
|
task.timeFinish = Date.now()
|
||||||
|
task.data = res.data.data
|
||||||
|
task.twitterId = res.data.data.userid
|
||||||
|
try {
|
||||||
|
await this.params.user.save()
|
||||||
|
} catch(err) {
|
||||||
|
throw new ZError(100, 'twitter already binded')
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,31 +1,25 @@
|
|||||||
import { checkTwitter } from "services/oauth.svr";
|
|
||||||
import { ITask } from "./base/ITask";
|
import { ITask } from "./base/ITask";
|
||||||
import { ActivityUser, TaskStatusEnum } from "models/ActivityUser";
|
import { TaskStatusEnum } from "models/ActivityUser";
|
||||||
import { ZError } from "common/ZError";
|
import { ZError } from "common/ZError";
|
||||||
|
|
||||||
export default class TwitterFollow extends ITask {
|
export default class TwitterFollow extends ITask {
|
||||||
static desc = 'twitter follow'
|
static desc = 'twitter follow'
|
||||||
static show: boolean = true
|
static show: boolean = true
|
||||||
async execute(data: any) {
|
async execute(data: any) {
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
async check(data: any) {
|
|
||||||
let { address } = this.params.user
|
|
||||||
let res = await checkTwitter(address)
|
|
||||||
console.log(res);
|
|
||||||
if (res.status !== 200) {
|
|
||||||
throw new ZError(11, 'twitter check failed')
|
|
||||||
}
|
|
||||||
if (res.data.errcode) {
|
|
||||||
throw new ZError(res.data.errcode, res.data.errmsg)
|
|
||||||
}
|
|
||||||
let task = this.params.user.taskProgress.find(t => t.id === this.constructor.name)
|
let task = this.params.user.taskProgress.find(t => t.id === this.constructor.name)
|
||||||
if (res.data.data.userid && task.status !== TaskStatusEnum.SUCCESS) {
|
let cfg = this.params.activity.tasks.find(t => t.task === this.constructor.name)
|
||||||
task.status = TaskStatusEnum.SUCCESS
|
let time = cfg.params.time;
|
||||||
task.timeFinish = Date.now()
|
if (Date.now() - task.timeStart < time * 1000) {
|
||||||
task.params = res.data.data
|
throw new ZError(11, 'follow failed')
|
||||||
await this.params.user.save()
|
|
||||||
}
|
}
|
||||||
|
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 = {}
|
||||||
|
await this.params.user.save()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,13 +1,25 @@
|
|||||||
|
import { ZError } from "common/ZError";
|
||||||
import { ITask } from "./base/ITask";
|
import { ITask } from "./base/ITask";
|
||||||
|
import { TaskStatusEnum } from "models/ActivityUser";
|
||||||
|
|
||||||
export default class TwitterRetweet extends ITask {
|
export default class TwitterRetweet extends ITask {
|
||||||
static desc = 'twitter retweet'
|
static desc = 'twitter retweet'
|
||||||
static show: boolean = true
|
static show: boolean = true
|
||||||
async execute(data: any) {
|
async execute(data: any) {
|
||||||
// do nothing
|
let task = this.params.user.taskProgress.find(t => t.id === this.constructor.name)
|
||||||
}
|
let cfg = this.params.activity.tasks.find(t => t.task === this.constructor.name)
|
||||||
async check(data: any) {
|
let time = cfg.params.time;
|
||||||
// do nothing
|
if (Date.now() - task.timeStart < time * 1000) {
|
||||||
|
throw new ZError(11, 'retweet failed')
|
||||||
|
}
|
||||||
|
let num = Math.random() * 100
|
||||||
|
if (num < cfg.params.failRate) {
|
||||||
|
throw new ZError(12, 'retweet failed')
|
||||||
|
}
|
||||||
|
task.status = TaskStatusEnum.SUCCESS
|
||||||
|
task.timeFinish = Date.now()
|
||||||
|
task.data = {}
|
||||||
|
await this.params.user.save()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,13 +1,23 @@
|
|||||||
|
import { ActivityUser, TaskStatus } from "models/ActivityUser";
|
||||||
import { ITask } from "./base/ITask";
|
import { ITask } from "./base/ITask";
|
||||||
|
import { TaskCfg } from "models/ActivityInfo";
|
||||||
|
|
||||||
export default class UpdateScore extends ITask {
|
export default class UpdateScore extends ITask {
|
||||||
static desc = 'update invite score'
|
static desc = 'update invite score'
|
||||||
static show: boolean = false
|
static show: boolean = false
|
||||||
|
static auto: boolean = true
|
||||||
async execute(data: any) {
|
async execute(data: any) {
|
||||||
// do nothing
|
let task = this.params.user.taskProgress.find((t: TaskStatus) => t.id === this.constructor.name)
|
||||||
}
|
let cfg = this.params.activity.tasks.find((t: TaskCfg) => t.task === this.constructor.name)
|
||||||
async check(data: any) {
|
let scores = cfg.params.scores;
|
||||||
// do nothing
|
for (let i = 0, l = scores.length; i < l; i++) {
|
||||||
|
let score = scores[i]
|
||||||
|
let user = await ActivityUser.findById(this.params.user.inviteUser)
|
||||||
|
if (user) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,11 +2,11 @@
|
|||||||
export abstract class ITask {
|
export abstract class ITask {
|
||||||
static desc: string
|
static desc: string
|
||||||
static show: boolean = true
|
static show: boolean = true
|
||||||
|
static auto: boolean = false
|
||||||
params: any
|
params: any
|
||||||
constructor(params: any) {
|
constructor(params: any) {
|
||||||
// do nothing
|
// do nothing
|
||||||
this.params = params
|
this.params = params
|
||||||
}
|
}
|
||||||
abstract execute(data: any): Promise<void>
|
abstract execute(data: any): Promise<boolean>
|
||||||
abstract check(data: any): Promise<boolean>
|
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user