using IM.Commons.IntegrationEvents;
using IM.DomainCommons;
using MessageService.Domain.Enums;
using MessageService.Domain.Events;
using MessageService.Domain.KeyObjects;
using MessageService.Domain.Tools;
using System.Text.Json;
namespace MessageService.Domain.Entities
{
public class Message : AggregateRootEntity
{
///
/// 聊天类型
/// (0:私聊,1:群聊)
///
public ChatType ChatType { get; private set; }
///
/// 消息类型
/// (0:文本,1:图片,2:语音,3:视频,4:文件,5:语音聊天,6:视频聊天)
///
public MessageType MsgType { get; private set; }
public Guid ClientMsgId { get; private set; }
///
/// 消息内容
///
public MessageContent Content { get; private set; } = null!;
///
/// 发送者
///
public Guid SenderId { get; private set; }
///
/// 接收者(私聊为用户ID,群聊为群聊ID)
///
public Guid TargetId { get; private set; }
///
/// 消息状态(0:已发送,1:已撤回)
///
public MessageState State { get; private set; } = MessageState.Sent;
///
/// 消息推送唯一标识符
///
public string StreamKey { get; private set; }
///
/// 消息排序标识
///
public long SequenceId { get; private set; }
private Message() { }
private Message(MessageCreateContext ctx, long sequenceId, MessageType messageType
, MessageContent content
)
{
ChatType = ctx.ChatType;
SenderId = ctx.SenderId;
ClientMsgId = ctx.ClientMsgId;
TargetId = ctx.TargetId;
SequenceId = sequenceId;
MsgType = messageType;
StreamKey = ChatType == ChatType.GROUP ? StreamKeyBuilder.Group(ctx.TargetId) : StreamKeyBuilder.Private(ctx.SenderId, ctx.TargetId);
Content = content;
}
///
/// 文本消息
///
///
/// 文本内容
///
///
public static Message BuildTxt(MessageCreateContext ctx, string text, long sequenceId)
{
var content = new MessageContent(text, new TextBody(text));
return new Message(ctx, sequenceId, MessageType.Text, content);
}
///
/// 图片消息
///
///
/// 相对路径
/// 宽度
/// 高度
/// 预览图
///
///
public static Message BuildImg(MessageCreateContext ctx, string? url,
int width, int height, string thumb, long sequenceId, Guid? fileId = null)
{
var content = new MessageContent("[图片]", new ImageBody(url, width, height, thumb, fileId));
return new Message(ctx, sequenceId, MessageType.Image, content);
}
///
/// 视频消息
///
///
///
///
///
///
///
///
public static Message BuildVideo(MessageCreateContext ctx, string? url,
int width, int height, string thumb, long sequenceId, Guid? fileId = null)
{
var content = new MessageContent("[视频]", new VideoBody(url, width, height, thumb, fileId));
return new Message(ctx, sequenceId, MessageType.Video, content);
}
///
/// 语音消息
///
///
///
/// 持续时间
///
///
public static Message BuildVoice(MessageCreateContext ctx, string? url,
int duration, long sequenceId, Guid? fileId = null)
{
var content = new MessageContent("[音频]", new VoiceBody(url, duration, fileId));
return new Message(ctx, sequenceId, MessageType.Voice, content);
}
///
/// 文件
///
///
/// 相对路径
/// 文件名
/// 文件大小(KB)
/// 文件格式
///
///
public static Message BuildFile(MessageCreateContext ctx, Guid fileId, string? url,
string name, long size,
string format, long sequenceId)
{
var content = new MessageContent("[文件]", new FileBody(fileId, url, name, size, format));
return new Message(ctx, sequenceId, MessageType.File, content);
}
///
/// 添加扩展字段
///
/// 字段名
/// 值
///
public Message WithExt(string key, string value)
{
var dic = new Dictionary();
dic.Add(key, value);
Content.RawExt = JsonSerializer.Serialize(dic);
return this;
}
///
/// 添加消息引用
///
///
///
public Message WithQuote(QuoteInfo quote)
{
this.Content.Quote = quote;
return this;
}
///
/// 完成消息
///
public void Send()
{
AddDomainEvent(new MessageCreatedDomainEvent(this));
}
public void Withdraw()
{
if (State != MessageState.Sent)
{
throw new DomainException("消息不可撤回");
}
State = MessageState.Withdrwan;
AddDomainEvent(new MessageWithdrawDomainEvent(this));
}
public MsgCreatedEvent ToIntegrationEvent()
{
return new MsgCreatedEvent
{
Id = this.Id,
ClientId = this.ClientMsgId, // 假设你有存发送端的设备ID
ChatType = this.ChatType.ToString(), // 比如 "private" 或 "group"
MsgType = this.MsgType.ToString() ?? MessageType.Text.ToString(), // 动态获取类型名,或从 Content 里的定义拿
SenderId = this.SenderId,
TargetId = this.TargetId,
State = State.ToString(),
StreamKey = this.StreamKey,
SequenceId = this.SequenceId,
// 核心载荷:利用计算属性触发反序列化,打包成 DTO
Content = new MsgContent(
this.Content.Fallback,
this.Content.Body, // 触发实体内部的反序列化逻辑
this.Content.Ext,
this.Content.Quote != null ? new QuoteInfoDto(
this.Content.Quote.MessageId,
this.Content.Quote.SenderId,
this.Content.Quote.SenderName,
this.Content.Quote.MessageType.ToString(),
this.Content.Quote.Preview
) : null
)
};
}
}
}