import { getModelForClass, prop, DocumentType, Ref, ReturnModelType, } from '@typegoose/typegoose'; import { Base, TimeStamps } from '@typegoose/typegoose/lib/defaultClasses'; import moment from 'moment'; import type { Types } from 'mongoose'; import { nanoid } from 'nanoid'; import { User } from '../user/user'; import { Group } from './group'; import promiseRetry from 'promise-retry'; function generateCode() { return nanoid(8); } export class GroupInvite extends TimeStamps implements Base { _id: Types.ObjectId; id: string; @prop({ index: true, unique: true, default: () => generateCode(), }) code!: string; @prop({ ref: () => User, }) creator: Ref; @prop({ ref: () => Group, }) groupId!: Ref; /** * 过期时间,如果不存在则永不过期 */ @prop() expiredAt?: Date; /** * 被使用次数 */ @prop({ default: 0, }) usage: number; /** * 使用上限,如果为空则不限制 */ @prop() usageLimit?: number; /** * 创建群组邀请 * @param groupId 群组id * @param type 普通(7天) 永久 */ static async createGroupInvite( this: ReturnModelType, groupId: string, creator: string, inviteType: 'normal' | 'permanent' ): Promise { let expiredAt = moment().add(7, 'day').toDate(); // 默认7天 if (inviteType === 'permanent') { expiredAt = undefined; } const code = await promiseRetry( async () => { const code = generateCode(); const exists = await this.exists({ code }); if (exists) { throw new Error('Cannot find unused invite code, please try again.'); } return code; }, { minTimeout: 0, maxTimeout: 0, retries: 5, } ); const invite = await this.create({ groupId, code, creator, expiredAt, }); return invite; } } export type GroupInviteDocument = DocumentType; const model = getModelForClass(GroupInvite); export type GroupInviteModel = typeof model; export default model;