|
|
|
|
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<User>;
|
|
|
|
|
|
|
|
|
|
@prop({
|
|
|
|
|
ref: () => Group,
|
|
|
|
|
})
|
|
|
|
|
groupId!: Ref<Group>;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 过期时间,如果不存在则永不过期
|
|
|
|
|
*/
|
|
|
|
|
@prop()
|
|
|
|
|
expiredAt?: Date;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 被使用次数
|
|
|
|
|
*/
|
|
|
|
|
@prop({
|
|
|
|
|
default: 0,
|
|
|
|
|
})
|
|
|
|
|
usage: number;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 使用上限,如果为空则不限制
|
|
|
|
|
*/
|
|
|
|
|
@prop()
|
|
|
|
|
usageLimit?: number;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 创建群组邀请
|
|
|
|
|
* @param groupId 群组id
|
|
|
|
|
* @param type 普通(7天) 永久
|
|
|
|
|
*/
|
|
|
|
|
static async createGroupInvite(
|
|
|
|
|
this: ReturnModelType<typeof GroupInvite>,
|
|
|
|
|
groupId: string,
|
|
|
|
|
creator: string,
|
|
|
|
|
inviteType: 'normal' | 'permanent'
|
|
|
|
|
): Promise<GroupInviteDocument> {
|
|
|
|
|
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<GroupInvite>;
|
|
|
|
|
|
|
|
|
|
const model = getModelForClass(GroupInvite);
|
|
|
|
|
|
|
|
|
|
export type GroupInviteModel = typeof model;
|
|
|
|
|
|
|
|
|
|
export default model;
|