task-svr/src/models/ActivityUser.ts
2024-01-09 22:05:48 +08:00

114 lines
3.3 KiB
TypeScript

import { getModelForClass, index, modelOptions, mongoose, pre, prop, ReturnModelType, Severity } from '@typegoose/typegoose'
import { dbconn } from 'decorators/dbconn'
// @ts-ignore
import findOrCreate from 'mongoose-findorcreate'
import { Base, TimeStamps } from '@typegoose/typegoose/lib/defaultClasses'
import { BaseModule } from './Base'
import { convert } from 'utils/number.util'
const alphabet = '3fBCM8j17XNA9xYun4wmLWep2oHFlhPcgyEJskqOz6GK0UtV5ZRaDSvrTbidQI'
export enum TaskStatusEnum {
NOT_START = 0,
RUNNING = 1,
SUCCESS = 2,
CLAIMED = 3,
PART_SUCCESS = 4,
}
@modelOptions({ schemaOptions: { _id: false }, options: { allowMixed: Severity.ALLOW }})
export class TaskStatus {
@prop()
id: string
@prop()
task: string
// 0: not start, 1: running, 2: success
@prop({ enum: TaskStatusEnum, default: TaskStatusEnum.NOT_START })
status: TaskStatusEnum
@prop()
dateTag: string
@prop()
timeStart: number
@prop()
timeFinish: number
@prop()
timeClaim: number
@prop({ type: mongoose.Schema.Types.Mixed })
data: any
}
interface ActivityUserClass extends Base, TimeStamps {}
@dbconn()
@index({ address: 1, activity: 1 }, { unique: true })
@index({ inviteCode: 1, activity: 1 }, { unique: true })
@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 } })
@pre<ActivityUserClass>('save', async function () {
if (!this.inviteCode) {
// 取ObjectId的time和inc段,
// 将time段倒序(倒序后, 如果以0开始, 则移除0, 随机拼接一个hex字符), 然后拼接inc段, 再转换成52进制
let timeStr = this.id.slice(0, 8).split("").reverse().join("");
if (timeStr.indexOf('0') === 0) {
let randomStr = convert({ numStr: (Math.random() * 51 | 0 + 1) + '', base:10, to: 52})
timeStr = randomStr + timeStr.slice(1)
}
let shortId = timeStr + this.id.slice(-6)
this.inviteCode = convert({numStr: shortId, base: 16, to: 52, alphabet})
}
})
class ActivityUserClass extends BaseModule {
@prop({ required: true })
public address: string
@prop({ required: true })
public activity: string
// 用户的邀请码
@prop()
public inviteCode: string
// 用户的邀请人
@prop()
public inviteUser: string
@prop({ default: false })
public locked: boolean
@prop()
public lockedTime?: Date
@prop()
public comment?: string
@prop()
public twitterId?: string
@prop()
public twitterName?: string
@prop()
public discordId?: string
@prop()
public discordName?: string
@prop({default: 1})
public boost: number
/**
* boost过期时间
* 计算得分时, 如果boost过期, 则不计算boost
*/
@prop()
public boostExpire?: Date
@prop()
public lastLogin?: Date
@prop({ type: () => [TaskStatus], default: [] })
public taskProgress?: TaskStatus[]
public static async findByCode(this: ReturnModelType<typeof ActivityUserClass>, inviteCode: string, activity: string) {
return this.findOne({ inviteCode, activity }).exec()
}
}
export const ActivityUser = getModelForClass(ActivityUserClass, { existingConnection: ActivityUserClass.db })