diff --git a/docs/uaw.md b/docs/uaw.md index 0095c4a..27f4899 100644 --- a/docs/uaw.md +++ b/docs/uaw.md @@ -60,6 +60,10 @@ 1. 检查签到并领取奖励(23), 增加post参数, 可以领取指定天数的奖励 1. 宝箱助力(18), 宝箱助力状态查询(26) 增加返回scoreBonus, 表示当前宝箱已得到的助力积分 +#### 20240506 +1. 增加验证google的access token(32) +2. 增加两种任务类型: GoogleConnect, GameAchievement + ### 1. 钱包预登录 #### Request @@ -960,4 +964,31 @@ body: ```js ['1234567890ab'] // 激活码列表 +``` + +### 32.\* 验证google的access token + +#### Request + +- URL:`/api/user/verify_google` +- 方法:POST +- 头部: + - Authorization: Bearer JWT_token + + +body: + +```js +{ + "code": "google oauth access token" +} + +``` + + +#### Response + +```js +{ +} ``` \ No newline at end of file diff --git a/initdatas/activity_info.json b/initdatas/activity_info.json index a9d65fb..fa98fd8 100644 --- a/initdatas/activity_info.json +++ b/initdatas/activity_info.json @@ -6,162 +6,261 @@ "baseTasks": ["e2yhq2lj30vwcpedv7p", "e2fclylj30vwcpe0szl", "e2far3lj30vwcpe0mh7", "e2far3lj30vwcpe0mf8"], "tasks": [ { - "id": "e2yhq2lj30vwcpedv7p", - "task": "TwitterConnect", - "title": "Connect your X", - "type": 1, - "desc": "Please connect your X account", - "score": 100, - "category": "Social Tasks", - "autoclaim": false, - "cfg": {"icon": "twitter"}, - "start": "2024-01-01 00:00", - "end": "2025-01-01 00:00", - "checkChain": false, - "params": {} - }, { - "id": "e2fclylj30vwcpe0szl", - "task": "TwitterFollow", - "title": "Follow @playCounterFire on X", - "type": 1, - "desc": "Follow Counter Fire’s official X account", - "category": "Social Tasks", - "score": 100, - "autoclaim": false, - "pretasks": ["e2yhq2lj30vwcpedv7p"], - "cfg": {"account": "playCounterFire", "icon": "twitter"}, - "start": "2024-01-01 00:00", - "end": "2025-01-01 00:00", - "checkChain": false, - "params": {"time": 6, "failRate": 0} - }, { - "id": "e2far3lj30vwcpe0mh7", - "task": "DiscordConnect", - "title": "Connect your Discord", - "type": 1, - "desc": "Connect your Discord account", - "category": "", - "score": 100, - "autoclaim": false, - "pretasks": [], - "cfg": {"icon": "discord"}, - "start": "2024-01-01 00:00", - "end": "2025-01-01 00:00", - "checkChain": false, - "params": {} - },{ - "id": "e2far3lj30vwcpe0mf8", - "task": "DiscordJoin", - "title": "Join Counter Fire Discord", - "type": 1, - "desc": "Join Counter Fire’s official Discord server", - "category": "Social Tasks", - "score": 100, - "autoclaim": false, - "pretasks": ["e2far3lj30vwcpe0mh7"], - "cfg": {"icon": "discord", "account": "counterfire"}, - "start": "2024-01-01 00:00", - "end": "2025-01-01 00:00", - "checkChain": false, - "params": {"time": 6, "failRate": 0} - }, { - "id": "e2fuah0j30vwcpe0my7", - "task": "TwitterRetweet", - "title": "RT - Hill's Treasure Hunt", - "type": 1, - "desc": "Retweet specific tweets", - "category": "Social Tasks", - "score": 50, - "autoclaim": false, - "pretasks": ["e2yhq2lj30vwcpedv7p"], - "cfg": {"icon": "twitter", "content": "1779507826714681538"}, - "start": "2024-01-01 00:00", - "end": "2025-01-01 00:00", - "checkChain": false, - "params": {"time": 6, "failRate": 0} - }, - { - "id": "e2fuah0j30vwcpe0my9", - "task": "TwitterLike", - "title": "Like - Hill's Treasure Hunt", - "type": 1, - "desc": "Like specific tweets", - "category": "Social Tasks", - "score": 50, - "autoclaim": false, - "pretasks": ["e2yhq2lj30vwcpedv7p"], - "cfg": {"icon": "twitter", "content": "1779507826714681538"}, - "start": "2024-01-01 00:00", - "end": "2025-01-01 00:00", - "checkChain": false, - "params": {"time": 6, "failRate": 0} - }, - { - "id": "e2il5vwl0u2bl0uyxbq", - "task": "TwitterRetweet", - "title": "RT - Hill's Treasure Hunt #2", - "type": 1, - "desc": "Retweet specific tweets", - "category": "Social Tasks", - "score": 50, - "autoclaim": false, - "pretasks": ["e2yhq2lj30vwcpedv7p"], - "cfg": {"icon": "twitter", "content": "1781323951853228188"}, - "start": "2024-01-01 00:00", - "end": "2025-01-01 00:00", - "checkChain": false, - "params": {"time": 6, "failRate": 0} - }, - { - "id": "e27r3pxezl1z8idqzq5", - "task": "TwitterLike", - "title": "Like - Hill's Treasure Hunt #2", - "type": 1, - "desc": "Like specific tweets", - "category": "Social Tasks", - "score": 50, - "autoclaim": false, - "pretasks": ["e2yhq2lj30vwcpedv7p"], - "cfg": {"icon": "twitter", "content": "1781323951853228188"}, - "start": "2024-01-01 00:00", - "end": "2025-01-01 00:00", - "checkChain": false, - "params": {"time": 6, "failRate": 0} - }, - { - "id": "e2ltjmohtvldpdhtz6o", - "task": "TwitterRetweet", - "title": "RT - Counter Fire x opBNB", - "type": 1, - "desc": "Retweet specific tweets", - "category": "Social Tasks", - "score": 50, - "autoclaim": false, - "pretasks": ["e2yhq2lj30vwcpedv7p"], - "cfg": {"icon": "twitter", "content": "1782375351244804306"}, - "start": "2024-01-01 00:00", - "end": "2025-01-01 00:00", - "checkChain": false, - "params": {"time": 6, "failRate": 0} - }, - { - "id": "e2dcbweojt7tzgl5xh4", - "task": "TwitterLike", - "title": "Like - Counter Fire x opBNB", - "type": 1, - "desc": "Like specific tweets", - "category": "Social Tasks", - "score": 50, - "autoclaim": false, - "pretasks": ["e2yhq2lj30vwcpedv7p"], - "cfg": {"icon": "twitter", "content": "1782375351244804306"}, - "start": "2024-01-01 00:00", - "end": "2025-01-01 00:00", - "checkChain": false, - "params": {"time": 6, "failRate": 0} - } + "id": "e2yhq2lj30vwcpedv7p", + "task": "TwitterConnect", + "title": "Connect your X", + "type": 1, + "desc": "Please connect your X account", + "score": 100, + "category": "Social Tasks", + "autoclaim": false, + "cfg": { "icon": "twitter" }, + "start": "2024-01-01 00:00", + "end": "2025-01-01 00:00", + "checkChain": false, + "params": {} + }, + { + "id": "e2fclylj30vwcpe0szl", + "task": "TwitterFollow", + "title": "Follow @playCounterFire on X", + "type": 1, + "desc": "Follow Counter Fire’s official X account", + "category": "Social Tasks", + "score": 100, + "autoclaim": false, + "pretasks": ["e2yhq2lj30vwcpedv7p"], + "cfg": { "account": "playCounterFire", "icon": "twitter" }, + "start": "2024-01-01 00:00", + "end": "2025-01-01 00:00", + "checkChain": false, + "params": { "time": 6, "failRate": 0 } + }, + { + "id": "e2far3lj30vwcpe0mh7", + "task": "DiscordConnect", + "title": "Connect your Discord", + "type": 1, + "desc": "Connect your Discord account", + "category": "", + "score": 100, + "autoclaim": false, + "pretasks": [], + "cfg": { "icon": "discord" }, + "start": "2024-01-01 00:00", + "end": "2025-01-01 00:00", + "checkChain": false, + "params": {} + }, + { + "id": "e2far3lj30vwcpe0mf8", + "task": "DiscordJoin", + "title": "Join Counter Fire Discord", + "type": 1, + "desc": "Join Counter Fire’s official Discord server", + "category": "Social Tasks", + "score": 100, + "autoclaim": false, + "pretasks": ["e2far3lj30vwcpe0mh7"], + "cfg": { "icon": "discord", "account": "counterfire" }, + "start": "2024-01-01 00:00", + "end": "2025-01-01 00:00", + "checkChain": false, + "params": { "time": 6, "failRate": 0 } + }, + { + "id": "e2fuah0j30vwcpe0my7", + "task": "TwitterRetweet", + "title": "RT - Hill's Treasure Hunt", + "type": 1, + "desc": "Retweet specific tweets", + "category": "Social Tasks", + "score": 50, + "autoclaim": false, + "pretasks": ["e2yhq2lj30vwcpedv7p"], + "cfg": { "icon": "twitter", "content": "1779507826714681538" }, + "start": "2024-01-01 00:00", + "end": "2025-01-01 00:00", + "checkChain": false, + "params": { "time": 6, "failRate": 0 } + }, + { + "id": "e2fuah0j30vwcpe0my9", + "task": "TwitterLike", + "title": "Like - Hill's Treasure Hunt", + "type": 1, + "desc": "Like specific tweets", + "category": "Social Tasks", + "score": 50, + "autoclaim": false, + "pretasks": ["e2yhq2lj30vwcpedv7p"], + "cfg": { "icon": "twitter", "content": "1779507826714681538" }, + "start": "2024-01-01 00:00", + "end": "2025-01-01 00:00", + "checkChain": false, + "params": { "time": 6, "failRate": 0 } + }, + { + "id": "e2il5vwl0u2bl0uyxbq", + "task": "TwitterRetweet", + "title": "RT - Hill's Treasure Hunt #2", + "type": 1, + "desc": "Retweet specific tweets", + "category": "Social Tasks", + "score": 50, + "autoclaim": false, + "pretasks": ["e2yhq2lj30vwcpedv7p"], + "cfg": { "icon": "twitter", "content": "1781323951853228188" }, + "start": "2024-01-01 00:00", + "end": "2025-01-01 00:00", + "checkChain": false, + "params": { "time": 6, "failRate": 0 } + }, + { + "id": "e27r3pxezl1z8idqzq5", + "task": "TwitterLike", + "title": "Like - Hill's Treasure Hunt #2", + "type": 1, + "desc": "Like specific tweets", + "category": "Social Tasks", + "score": 50, + "autoclaim": false, + "pretasks": ["e2yhq2lj30vwcpedv7p"], + "cfg": { "icon": "twitter", "content": "1781323951853228188" }, + "start": "2024-01-01 00:00", + "end": "2025-01-01 00:00", + "checkChain": false, + "params": { "time": 6, "failRate": 0 } + }, + { + "id": "e2ltjmohtvldpdhtz6o", + "task": "TwitterRetweet", + "title": "RT - Counter Fire x opBNB", + "type": 1, + "desc": "Retweet specific tweets", + "category": "Social Tasks", + "score": 50, + "autoclaim": false, + "pretasks": ["e2yhq2lj30vwcpedv7p"], + "cfg": { "icon": "twitter", "content": "1782375351244804306" }, + "start": "2024-01-01 00:00", + "end": "2025-01-01 00:00", + "checkChain": false, + "params": { "time": 6, "failRate": 0 } + }, + { + "id": "e2dcbweojt7tzgl5xh4", + "task": "TwitterLike", + "title": "Like - Counter Fire x opBNB", + "type": 1, + "desc": "Like specific tweets", + "category": "Social Tasks", + "score": 50, + "autoclaim": false, + "pretasks": ["e2yhq2lj30vwcpedv7p"], + "cfg": { "icon": "twitter", "content": "1782375351244804306" }, + "start": "2024-01-01 00:00", + "end": "2025-01-01 00:00", + "checkChain": false, + "params": { "time": 6, "failRate": 0 } + }, + { + "id": "e2ltjmohtvldpdhtz7o", + "task": "TwitterRetweet", + "title": "RT - Preseason Testing", + "type": 1, + "desc": "Retweet specific tweets", + "category": "Social Tasks", + "score": 50, + "autoclaim": false, + "pretasks": ["e2yhq2lj30vwcpedv7p"], + "cfg": { "icon": "twitter", "content": "1785304706325340422" }, + "start": "2024-01-01 00:00", + "end": "2025-01-01 00:00", + "checkChain": false, + "params": { "time": 6, "failRate": 0 } + }, + { + "id": "e2dcbweojt7tzgl5x74", + "task": "TwitterLike", + "title": "Like - Preseason Testing", + "type": 1, + "desc": "Like specific tweets", + "category": "Social Tasks", + "score": 50, + "autoclaim": false, + "pretasks": ["e2yhq2lj30vwcpedv7p"], + "cfg": { "icon": "twitter", "content": "1785304706325340422" }, + "start": "2024-01-01 00:00", + "end": "2025-01-01 00:00", + "checkChain": false, + "params": { "time": 6, "failRate": 0 } + }, + { + "id": "e2ltjmohtvldpdhtz8o", + "task": "TwitterRetweet", + "title": "RT - Play Counter Fire!", + "type": 1, + "desc": "Retweet specific tweets", + "category": "Social Tasks", + "score": 50, + "autoclaim": false, + "pretasks": ["e2yhq2lj30vwcpedv7p"], + "cfg": { "icon": "twitter", "content": "1786035573653979616" }, + "start": "2024-01-01 00:00", + "end": "2025-01-01 00:00", + "checkChain": false, + "params": { "time": 6, "failRate": 0 } + }, + { + "id": "e2dcbweojt7tzgl5x84", + "task": "TwitterLike", + "title": "Like - Play Counter Fire! ", + "type": 1, + "desc": "Like specific tweets", + "category": "Social Tasks", + "score": 50, + "autoclaim": false, + "pretasks": ["e2yhq2lj30vwcpedv7p"], + "cfg": { "icon": "twitter", "content": "1786035573653979616" }, + "start": "2024-01-01 00:00", + "end": "2025-01-01 00:00", + "checkChain": false, + "params": { "time": 6, "failRate": 0 } + }, + { + "id": "e2yhq2lj30vwcpedv8p", + "task": "GoogleConnect", + "title": "Connect your game account", + "type": 1, + "desc": "Please connect your game account", + "score": 100, + "category": "Social Tasks", + "autoclaim": false, + "cfg": { "icon": "google" }, + "start": "2024-01-01 00:00", + "end": "2025-01-01 00:00", + "checkChain": false, + "params": {} + }, + { + "id": "e2fclylj30vwcpe1szl", + "task": "GameAchievement", + "title": "Receive Game Achievement", + "type": 1, + "desc": "Receive Game Achievement", + "category": "Social Tasks", + "score": 100, + "autoclaim": false, + "pretasks": ["e2yhq2lj30vwcpedv8p"], + "cfg": { }, + "start": "2024-01-01 00:00", + "end": "2025-01-01 00:00", + "checkChain": false, + "params": { "time": 6, "failRate": 0 } + } ], "startTime": 1713355200000, "endTime": 1715903999999 } -] \ No newline at end of file +] diff --git a/package.json b/package.json index a844342..11ed879 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "fastify": "^4.15.0", "fastify-plugin": "^3.0.0", "fastify-xml-body-parser": "^2.2.0", + "google-auth-library": "^9.9.0", "ioredis": "^5.4.1", "mongodb-extended-json": "^1.11.1", "mongoose": "8.2.3", diff --git a/src/controllers/sign.controller.ts b/src/controllers/sign.controller.ts index abf560d..d47a9d9 100644 --- a/src/controllers/sign.controller.ts +++ b/src/controllers/sign.controller.ts @@ -22,6 +22,7 @@ import { import { formatNumShow, isObjectIdString } from 'common/Utils' import { ChestEnhanceRecord } from 'models/ChestEnhanceRecord' import logger from 'logger/logger' +import { verifyToken } from 'services/google.svr' const LOGIN_TIP = 'This signature is just to verify your identity' @@ -174,4 +175,31 @@ class SignController extends BaseController { await user.save() return { boost: user.boost, boostExpire: user.boostExpire } } + + @router('post /api/user/verify_google') + async verifyGoogleToken(req) { + const user = req.user + if (user.googleId) { + throw new ZError(11, 'already bind google') + } + const { openId, data } = await verifyToken(req) + const exstisUser = await ActivityUser.findOne({ + googleId: openId, + }) + if (exstisUser) { + throw new ZError(12, 'google account already bind') + } + if (data.email) { + user.googleEmail = data.email + } + if (data.nickname) { + user.googleName = data.nickname + } + if (data.avatar) { + user.googleAvatar = data.avatar + } + user.googleId = openId + await user.save() + return {} + } } diff --git a/src/models/ActivityUser.ts b/src/models/ActivityUser.ts index 4d1f2a5..d7d8d58 100644 --- a/src/models/ActivityUser.ts +++ b/src/models/ActivityUser.ts @@ -49,6 +49,7 @@ export interface ActivityUserClass extends Base, TimeStamps {} @index({ inviteCode: 1, activity: 1 }, { unique: true, partialFilterExpression: { inviteCode: { $exists: true } } }) @index({ inviteUser: 1, activity: 1 }, { unique: false }) @index({ twitterId: 1 }, { unique: true, partialFilterExpression: { twitterId: { $exists: true } } }) +@index({ googleId: 1 }, { unique: true, partialFilterExpression: { twitterId: { $exists: true } } }) @index({ discordId: 1 }, { unique: true, partialFilterExpression: { discordId: { $exists: true } } }) @modelOptions({ schemaOptions: { collection: 'activity_user', timestamps: true }, @@ -101,6 +102,15 @@ export class ActivityUserClass extends BaseModule { @prop() public discordName?: string + @prop() + public googleId?: string + @prop() + public googleName?: string + @prop() + public googleAvatar?: string + @prop() + public googleEmail?: string + @prop({ default: false }) public inWhiteList: boolean diff --git a/src/rankquery.ts b/src/rankquery.ts new file mode 100644 index 0000000..24fd4a1 --- /dev/null +++ b/src/rankquery.ts @@ -0,0 +1,70 @@ +import mongoose from 'mongoose' +import * as dotenv from 'dotenv' +const envFile = process.env.NODE_ENV && process.env.NODE_ENV === 'production' ? `.env.production` : '.env.development' +dotenv.config({ path: envFile }) +console.log(process.env.DB_MAIN) +import { ZRedisClient } from 'zutils' +import { RANK_SCORE_SCALE } from 'common/Constants' +import { ScoreRecord } from 'models/ScoreRecord' + +const db = mongoose.connection + +;(async () => { + try { + // const activity = 'uaw_activity' + // const start = 0 + // const end = 500 + // let opts = { url: process.env.REDIS } + // new ZRedisClient(opts) + // const records = await new ZRedisClient().zrevrange(`uaw_activity:score`, start, 100) + // let score100 = 0 + + // console.log(records.length) + // for (let i = 0; i < records.length; i += 2) { + // let score = parseInt(records[i + 1]) / 100 + // score100 += score + // } + // const record500 = await new ZRedisClient().zrevrange(`uaw_activity:score`, start, 500) + // let score500 = 0 + + // console.log(record500.length) + // for (let i = 0; i < record500.length; i += 2) { + // let score = parseInt(record500[i + 1]) / 100 + // score500 += score + // } + // console.log('score100:', score100) + // console.log('score500:', score500) + let begin = new Date('2024-04-17T00:00:00.000Z') + const oneDay = 24 * 60 * 60 * 1000 + let end = new Date(begin.getTime() + oneDay) + let resultMap1 = new Map() + let resultMap2 = new Map() + let resultMap = new Map() + while (end < new Date()) { + let record = await ScoreRecord.aggregate([ + { + $match: { + type: { $ne: 'invite_rebate' }, + $and: [{ createdAt: { $gte: begin } }, { createdAt: { $lt: end } }], + }, + }, + { $group: { _id: null, count: { $sum: '$score' } } }, + ]) + let record2 = await ScoreRecord.aggregate([ + { + $match: { + type: 'invite_rebate', + $and: [{ createdAt: { $gte: begin } }, { createdAt: { $lt: end } }], + }, + }, + { $group: { _id: null, count: { $sum: '$score' } } }, + ]) + console.log(begin, '\t', record[0].count + record2[0].count, '\t', record[0].count, '\t', record2[0].count) + begin = end + end = new Date(begin.getTime() + oneDay) + } + } catch (e) { + console.log(e) + } + process.exit(0) +})() diff --git a/src/services/google.svr.ts b/src/services/google.svr.ts index f88937d..2b15f7a 100644 --- a/src/services/google.svr.ts +++ b/src/services/google.svr.ts @@ -1,4 +1,6 @@ import { RECAPTCHA_MIN_SCORE } from 'common/Constants' +import { OAuth2Client } from 'google-auth-library' +import logger from 'logger/logger' import { ZError } from 'zutils' export const checkReCaptcha = async (req: any, action: string) => { @@ -25,3 +27,68 @@ export const checkReCaptcha = async (req: any, action: string) => { } return true } + +const GOOGLE_OAUTH_ISS = 'https://accounts.google.com' +const GOOGLE_OAUTH_ISS1 = 'accounts.google.com' +const IOS_TEST = '53206975661-0d6q9pqljn84n9l63gm0to1ulap9cbk4.apps.googleusercontent.com' +const CLIENT_ID = '53206975661-asnf3qe4bg29p8h981pgf099osvrjbme.apps.googleusercontent.com' +const CLIENT_ID2 = '53206975661-ih3r0ubph3rqejdq97b029difbrk2bqj.apps.googleusercontent.com' +const CLIENT_ID_IOS = '53206975661-qan0rnefniegjv53ohild375pv0p7ekd.apps.googleusercontent.com' +const CLIENT_ID3 = '436789193812-5vh7ahctkaofjir9tnilfnvm19cf3vve.apps.googleusercontent.com' +const CLIENT_ID4 = '436789193812-9vubggj1op881elm41i7b9raeec9dgrj.apps.googleusercontent.com' +const CLIENT_ID5 = '436789193812-9vubggj1op881elm41i7b9raeec9dgrj.apps.googleusercontent.com' +const CLIENTS = [CLIENT_ID, CLIENT_ID2, CLIENT_ID3, CLIENT_ID4, CLIENT_ID_IOS, IOS_TEST, CLIENT_ID5] + +export const verifyToken = async (req: any) => { + let { code, token } = req.params + code = code || token + if (!code) { + throw new ZError(50, 'code is required') + } + const client = new OAuth2Client(CLIENT_ID) + let data: any = {} + let openId: string + try { + const ticket = await client.verifyIdToken({ + idToken: code, + audience: CLIENTS, // Specify the CLIENT_ID of the app that accesses the backend + // Or, if multiple clients access the backend: + //[CLIENT_ID_1, CLIENT_ID_2, CLIENT_ID_3] + }) + const payload = ticket.getPayload() + if (!(payload.iss === GOOGLE_OAUTH_ISS || payload.iss === GOOGLE_OAUTH_ISS1)) { + throw new ZError(10, 'id token error') + } + if (CLIENTS.indexOf(payload.aud) === -1) { + throw new ZError(11, 'client id mismatch') + } + + if (payload.email) data.email = payload.email + if (process.env.NODE_ENV !== 'development') { + if (payload.email_verified !== undefined) data.emailVerified = payload.email_verified + } + if (payload.locale) data.locale = payload.locale + if (payload.name) data.nickname = payload.name + if (payload.picture) data.avatar = payload.picture + openId = payload.sub + } catch (err) { + logger.log('error parse google id token', err) + try { + let info: any = await client.getTokenInfo(code) + console.log(info) + if (info.email) data.email = info.email + if (info.aud !== CLIENT_ID2) { + throw new ZError(11, 'client id mismatch') + } + if (process.env.NODE_ENV !== 'development') { + if (info.email_verified !== undefined) data.emailVerified = info.email_verified + } + if (info.name) data.nickname = info.name + openId = info.sub + } catch (e2) { + logger.log('error parse google access token', e2) + throw new ZError(10, 'id token error') + } + } + return { openId, data } +} diff --git a/src/tasks/GameAchievement.ts b/src/tasks/GameAchievement.ts new file mode 100644 index 0000000..03cb9be --- /dev/null +++ b/src/tasks/GameAchievement.ts @@ -0,0 +1,37 @@ +import { ZError } from 'zutils' +import { ITask } from './base/ITask' +import { TaskStatusEnum } from 'models/ActivityUser' +import { TaskCfg } from 'models/ActivityInfo' + +export default class GameAchievement extends ITask { + static desc = 'acquire game achievement' + static show: boolean = true + async execute(data: any) { + const { task } = data + let cfg = this.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 game achievement failed') + } + let num = Math.random() * 100 + if (num < cfg.params.failRate) { + throw new ZError(12, 'check game achievement failed') + } + task.status = TaskStatusEnum.SUCCESS + task.timeFinish = Date.now() + task.data = {} + try { + await this.user.save() + } catch (err) { + throw new ZError(100, 'already acquired game achievement') + } + if (cfg.autoclaim) { + try { + await this.claimReward(task) + } catch (err) { + console.log(err) + } + } + return true + } +} diff --git a/src/tasks/GoogleConnect.ts b/src/tasks/GoogleConnect.ts new file mode 100644 index 0000000..c2c5348 --- /dev/null +++ b/src/tasks/GoogleConnect.ts @@ -0,0 +1,38 @@ +import { ITask } from './base/ITask' +import { TaskStatusEnum } from 'models/ActivityUser' +import { ZError } from 'zutils' +import { TaskCfg } from 'models/ActivityInfo' + +export default class GoogleConnect extends ITask { + static desc = 'google connect' + static show: boolean = true + + async execute(data: any) { + if (!this.user.googleId) { + throw new ZError(100, 'google account already binded') + } + const { task } = data + if (task.status === TaskStatusEnum.RUNNING) { + task.status = TaskStatusEnum.SUCCESS + task.timeFinish = Date.now() + task.data = { + userid: this.user.googleId, + email: this.user.googleEmail, + } + try { + await this.user.save() + } catch (err) { + throw new ZError(100, 'google account already binded') + } + let cfg = this.activity.tasks.find((t: TaskCfg) => t.id === task.id) + if (cfg.autoclaim) { + try { + await this.claimReward(task) + } catch (err) { + console.log(err) + } + } + } + return true + } +} diff --git a/yarn.lock b/yarn.lock index 9a0c950..e1dac95 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1628,6 +1628,13 @@ aes-js@3.0.0: resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" integrity sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw== +agent-base@^7.0.2: + version "7.1.1" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.1.tgz#bdbded7dfb096b751a2a087eeeb9664725b2e317" + integrity sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA== + dependencies: + debug "^4.3.4" + ajv-formats@^2.1.1: version "2.1.1" resolved "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz" @@ -1871,7 +1878,7 @@ base-x@^3.0.2, base-x@^3.0.8: dependencies: safe-buffer "^5.0.1" -base64-js@^1.3.1: +base64-js@^1.3.0, base64-js@^1.3.1: version "1.5.1" resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== @@ -2037,6 +2044,11 @@ bson@^6.2.0: resolved "https://registry.yarnpkg.com/bson/-/bson-6.2.0.tgz#4b6acafc266ba18eeee111373c2699304a9ba0a3" integrity sha512-ID1cI+7bazPDyL9wYy9GaQ8gEEohWvcUl/Yf0dIdutJxnmInEEyCsb4awy/OiBfall7zBA179Pahi3vCdFze3Q== +buffer-equal-constant-time@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" + integrity sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA== + buffer-from@^1.0.0: version "1.1.2" resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz" @@ -2452,7 +2464,7 @@ debug@2.6.9, debug@^2.2.0: dependencies: ms "2.0.0" -debug@4.x, debug@^4.0.0, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: +debug@4, debug@4.x, debug@^4.0.0, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: version "4.3.4" resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -2591,7 +2603,7 @@ ecc-jsbn@~0.1.1: jsbn "~0.1.0" safer-buffer "^2.1.0" -ecdsa-sig-formatter@^1.0.11: +ecdsa-sig-formatter@1.0.11, ecdsa-sig-formatter@^1.0.11: version "1.0.11" resolved "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz" integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ== @@ -3125,7 +3137,7 @@ ext@^1.7.0: dependencies: type "^2.7.2" -extend@~3.0.2: +extend@^3.0.2, extend@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== @@ -3449,6 +3461,25 @@ function-bind@^1.1.2: resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== +gaxios@^6.0.0, gaxios@^6.1.1: + version "6.5.0" + resolved "https://registry.yarnpkg.com/gaxios/-/gaxios-6.5.0.tgz#21bc20e24f21189ce8907079b56205ff9fd2c0d7" + integrity sha512-R9QGdv8j4/dlNoQbX3hSaK/S0rkMijqjVvW3YM06CoBdbU/VdKd159j4hePpng0KuE6Lh6JJ7UdmVGJZFcAG1w== + dependencies: + extend "^3.0.2" + https-proxy-agent "^7.0.1" + is-stream "^2.0.0" + node-fetch "^2.6.9" + uuid "^9.0.1" + +gcp-metadata@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/gcp-metadata/-/gcp-metadata-6.1.0.tgz#9b0dd2b2445258e7597f2024332d20611cbd6b8c" + integrity sha512-Jh/AIwwgaxan+7ZUUmRLCjtchyDiqh4KjBJ5tW3plBZb5iL/BPcso8A5DlzeD9qlw0duCamnNdpFjxwaT0KyKg== + dependencies: + gaxios "^6.0.0" + json-bigint "^1.0.0" + gensync@^1.0.0-beta.2: version "1.0.0-beta.2" resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" @@ -3552,6 +3583,18 @@ globby@^11.1.0: merge2 "^1.4.1" slash "^3.0.0" +google-auth-library@^9.9.0: + version "9.9.0" + resolved "https://registry.yarnpkg.com/google-auth-library/-/google-auth-library-9.9.0.tgz#71488ef444335ff4ea91611729b88c0f57625fdf" + integrity sha512-9l+zO07h1tDJdIHN74SpnWIlNR+OuOemXlWJlLP9pXy6vFtizgpEzMuwJa4lqY9UAdiAv5DVd5ql0Am916I+aA== + dependencies: + base64-js "^1.3.0" + ecdsa-sig-formatter "^1.0.11" + gaxios "^6.1.1" + gcp-metadata "^6.1.0" + gtoken "^7.0.0" + jws "^4.0.0" + gopd@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" @@ -3605,6 +3648,14 @@ graphemer@^1.4.0: resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== +gtoken@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/gtoken/-/gtoken-7.1.0.tgz#d61b4ebd10132222817f7222b1e6064bd463fc26" + integrity sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw== + dependencies: + gaxios "^6.0.0" + jws "^4.0.0" + har-schema@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" @@ -3748,6 +3799,14 @@ http2-wrapper@^2.1.10: quick-lru "^5.1.1" resolve-alpn "^1.2.0" +https-proxy-agent@^7.0.1: + version "7.0.4" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz#8e97b841a029ad8ddc8731f26595bad868cb4168" + integrity sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg== + dependencies: + agent-base "^7.0.2" + debug "4" + human-signals@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" @@ -4402,6 +4461,13 @@ jsesc@^2.5.1: resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== +json-bigint@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-bigint/-/json-bigint-1.0.0.tgz#ae547823ac0cad8398667f8cd9ef4730f5b01ff1" + integrity sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ== + dependencies: + bignumber.js "^9.0.0" + json-buffer@3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" @@ -4471,6 +4537,23 @@ jsprim@^1.2.2: json-schema "0.4.0" verror "1.10.0" +jwa@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/jwa/-/jwa-2.0.0.tgz#a7e9c3f29dae94027ebcaf49975c9345593410fc" + integrity sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA== + dependencies: + buffer-equal-constant-time "1.0.1" + ecdsa-sig-formatter "1.0.11" + safe-buffer "^5.0.1" + +jws@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jws/-/jws-4.0.0.tgz#2d4e8cf6a318ffaa12615e9dec7e86e6c97310f4" + integrity sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg== + dependencies: + jwa "^2.0.0" + safe-buffer "^5.0.1" + kareem@2.5.1: version "2.5.1" resolved "https://registry.yarnpkg.com/kareem/-/kareem-2.5.1.tgz#7b8203e11819a8e77a34b3517d3ead206764d15d" @@ -4958,7 +5041,7 @@ node-addon-api@^2.0.0: resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32" integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA== -node-fetch@2, node-fetch@^2.6.12: +node-fetch@2, node-fetch@^2.6.12, node-fetch@^2.6.9: version "2.7.0" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== @@ -6436,7 +6519,7 @@ uuid@^3.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== -uuid@^9.0.0: +uuid@^9.0.0, uuid@^9.0.1: version "9.0.1" resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30" integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==