task-svr/src/controllers/activity.controller.ts
2024-04-23 20:41:40 +08:00

170 lines
5.5 KiB
TypeScript

import { ActivityInfo } from 'models/ActivityInfo'
import { ActivityUser } from 'models/ActivityUser'
import { rankKey, rankLevel } from 'services/rank.svr'
import { BaseController, ROLE_ANON, ZError, ZRedisClient, role, router } from 'zutils'
import { SyncLocker } from 'common/SyncLocker'
import { ScoreRecord } from 'models/ScoreRecord'
import { formatAddress } from 'zutils/utils/chain.util'
import { formatNumShow, isValidShareCode } from 'common/Utils'
import { checkReCaptcha } from 'services/google.svr'
import { RANK_SCORE_SCALE, SCORE_INVITE_REBATE } from 'common/Constants'
import logger from 'logger/logger'
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) {
await new SyncLocker().checkLock(req)
logger.db('upload_invite_code', 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)
const keyInvite = `${user.activity}:invite`
let users = await ActivityUser.find({ inviteUser: user.id })
let records = await ScoreRecord.find({ type: SCORE_INVITE_REBATE, user: user.id, activity: user.activity })
let scoreMap = new Map()
for (let r of records) {
if (!scoreMap.has(r.data.fromUser)) {
scoreMap.set(r.data.fromUser, 0)
}
scoreMap.set(r.data.fromUser, scoreMap.get(r.data.fromUser) + r.score)
}
let results = []
for (let u of users) {
const totalScore = await new ZRedisClient().zscore(totalKey, u.id)
// const inviteScore = await new ZRedisClient().zscore(keyInvite, `${user.id}_${u.id}`)
const score = totalScore ? parseInt(totalScore + '') / RANK_SCORE_SCALE : 0
const scoreInvite = scoreMap.get(u.id) || 0
results.push({
// user: u.id,
level: rankLevel(score),
nickname: u.twitterName || u.discordName || formatAddress(u.address),
avatar: u.twitterAvatar || '',
score: formatNumShow(score),
scoreInvite: formatNumShow(scoreInvite),
})
}
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, score: { $gt: 0 } }).sort({
_id: -1,
})
return records.map(record => {
return {
score: formatNumShow(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 = formatNumShow(parseInt(records[i + 1]) / RANK_SCORE_SCALE)
const user = await ActivityUser.findById(id)
const rank = start + i / 2 + 1
results.push({
rank,
level: rankLevel(rank),
nickname: user?.twitterName || user?.discordName || user?.address ? formatAddress(user.address) : 'unknown',
avatar: user?.twitterAvatar || '',
score,
// yesterday: yesterdayScore ? parseInt(yesterdayScore + '') : 0,
})
}
return results
}
}