import { ActivityInfo } from 'models/ActivityInfo' import { ActivityUser } from 'models/ActivityUser' import { rankKey, rankLevel } from 'services/rank.svr' import { BaseController, ROLE_ANON, SyncLocker, ZError, ZRedisClient, role, router } from 'zutils' import { ScoreRecord } from 'models/ScoreRecord' import { formatAddress } from 'zutils/utils/chain.util' import { isValidShareCode } from 'common/Utils' import { checkReCaptcha } from 'services/google.svr' const MAX_LIMIT = 100 export default class ActivityController extends BaseController { @role(ROLE_ANON) @router('get /api/activity/:id') async info(req) { let { id } = req.params if (!id) { throw new ZError(11, 'invalid activity id') } let activity = await ActivityInfo.findById(id) if (!activity) { throw new ZError(12, 'activity not found') } return activity.toJson() } /** * 更新邀请码 * @param req * @returns */ @router('post /api/activity/upload_invite_code') async uploadInviteCode(req) { new SyncLocker().checkLock(req) await checkReCaptcha(req, 'invite_user') let { code } = req.params if (!isValidShareCode(code)) { throw new ZError(11, 'invalid invite code') } let user = req.user if (user.inviteUser) { throw new ZError(11, 'invite user already set') } if (!user.allTaskFinished()) { throw new ZError(12, 'not all tasks finished') } // In production, users cannot invite themselves if (process.env.NODE_ENV === 'production' && code === user.inviteCode) { throw new ZError(13, 'cannot invite yourself') } let inviteUser = await ActivityUser.findByCode(code, user.activity) if (!inviteUser) { throw new ZError(12, 'invalid invite code') } // const dateTag = formatDate(new Date()) // // 更新邀请积分-邀请人 // await updateRankScore({ // user: inviteUser.id, // score: shareCfg.inviter, // activity: user.activity, // scoreType: SCORE_INVITE_USER, // scoreParams: { // date: dateTag, // user: user.id, // }, // }) // // 更新邀请积分-被邀请人 // await updateRankScore({ // user: user.id, // score: shareCfg.invitee, // activity: user.activity, // scoreType: SCORE_INVITE_INVITEE, // scoreParams: { // date: dateTag, // user: inviteUser.id, // }, // }) user.inviteUser = inviteUser.id await user.save() // return { score: shareCfg.invitee } return { score: 0 } } /** * 邀请列表 */ @router('get /api/activity/invite_list') async inviteUserList(req) { let user = req.user const totalKey = rankKey(user.activity) let users = await ActivityUser.find({ inviteUser: user.id }) let results = [] for (let u of users) { const totalScore = await new ZRedisClient().zscore(totalKey, u.id) const score = totalScore ? parseInt(totalScore + '') : 0 results.push({ // user: u.id, level: rankLevel(score), nickname: u.twitterName || u.discordName || formatAddress(u.address), score, }) } return results } /** * 积分详情列表 */ @router('get /api/activity/score_list') async scoreList(req) { let user = req.user const records = await ScoreRecord.find({ user: user.id, activity: user.activity }) return records.map(record => { return { score: record.score, type: record.type, //@ts-ignore time: record.createdAt.getTime(), } }) } @role(ROLE_ANON) @router('get /api/activity/leaderboard/:activity/:page') async inviteCode(req) { let { page, activity, limit } = req.params page = parseInt(page || '0') limit = parseInt(limit || MAX_LIMIT) page = page < 0 ? 0 : page const start = page * limit const end = start + limit - 1 const records = await new ZRedisClient().zrevrange(`${activity}:score`, start, end) let results: any = [] // const yesterdayKey = rankKey(activity, yesterday()) for (let i = 0; i < records.length; i += 2) { const id = records[i] let score = parseInt(records[i + 1]) const user = await ActivityUser.findById(id) // let invite = '' // if (user?.inviteUser) { // const inviteUser = await ActivityUser.findById(user.inviteUser) // if (inviteUser) { // invite = inviteUser.address // } // } // const yesterdayScore = await new ZRedisClient().zscore(yesterdayKey, id) results.push({ rank: start + i / 2 + 1, level: rankLevel(score), nickname: user?.twitterName || user?.discordName || user?.address ? formatAddress(user.address) : 'unknown', score, // yesterday: yesterdayScore ? parseInt(yesterdayScore + '') : 0, }) } return results } }