import { getModelForClass, prop, DocumentType, Ref, ReturnModelType, modelOptions, Severity, index, } from '@typegoose/typegoose'; import { Group } from '../group/group'; import { Base, TimeStamps } from '@typegoose/typegoose/lib/defaultClasses'; import { Converse } from './converse'; import { User } from '../user/user'; import type { FilterQuery, Types } from 'mongoose'; import type { MessageMetaStruct } from 'tailchat-server-sdk'; class MessageReaction { /** * 消息反应名 * 可以直接为emoji表情 */ @prop() name: string; @prop({ ref: () => User }) author?: Ref; } @modelOptions({ options: { allowMixed: Severity.ALLOW, }, }) @index({ createdAt: -1 }) @index({ converseId: 1, _id: -1 }) // for fetchConverseMessage export class Message extends TimeStamps implements Base { _id: Types.ObjectId; id: string; @prop() content: string; @prop({ ref: () => User }) author?: Ref; @prop({ ref: () => Group }) groupId?: Ref; /** * 会话ID 必填 * 私信的本质就是创建一个双人的会话 */ @prop({ ref: () => Converse, index: true }) converseId!: Ref; @prop({ type: () => MessageReaction }) reactions?: MessageReaction[]; /** * 是否已撤回 */ @prop({ default: false, }) hasRecall: boolean; /** * 消息的其他数据 */ @prop() meta?: MessageMetaStruct; /** * 获取会话消息 */ static async fetchConverseMessage( this: ReturnModelType, converseId: string, startId: string | null, limit = 50 ) { const conditions: FilterQuery = { converseId, }; if (startId !== null) { conditions['_id'] = { $lt: startId, }; } const res = await this.find({ ...conditions }) .sort({ _id: -1 }) .limit(limit) .exec(); return res; } } export type MessageDocument = DocumentType; const model = getModelForClass(Message); export type MessageModel = typeof model; export default model;