添加项目文件。
This commit is contained in:
@@ -0,0 +1,217 @@
|
||||
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
|
||||
{
|
||||
/// <summary>
|
||||
/// 聊天类型
|
||||
/// (0:私聊,1:群聊)
|
||||
/// </summary>
|
||||
public ChatType ChatType { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 消息类型
|
||||
/// (0:文本,1:图片,2:语音,3:视频,4:文件,5:语音聊天,6:视频聊天)
|
||||
/// </summary>
|
||||
public MessageType MsgType { get; private set; }
|
||||
public Guid ClientMsgId { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 消息内容
|
||||
/// </summary>
|
||||
public MessageContent Content { get; private set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// 发送者
|
||||
/// </summary>
|
||||
public Guid SenderId { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 接收者(私聊为用户ID,群聊为群聊ID)
|
||||
/// </summary>
|
||||
public Guid TargetId { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 消息状态(0:已发送,1:已撤回)
|
||||
/// </summary>
|
||||
public MessageState State { get; private set; } = MessageState.Sent;
|
||||
|
||||
/// <summary>
|
||||
/// 消息推送唯一标识符
|
||||
/// </summary>
|
||||
public string StreamKey { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 消息排序标识
|
||||
/// </summary>
|
||||
|
||||
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;
|
||||
}
|
||||
/// <summary>
|
||||
/// 文本消息
|
||||
/// </summary>
|
||||
/// <param name="ctx"></param>
|
||||
/// <param name="text">文本内容</param>
|
||||
/// <param name="sequenceId"></param>
|
||||
/// <returns></returns>
|
||||
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);
|
||||
}
|
||||
/// <summary>
|
||||
/// 图片消息
|
||||
/// </summary>
|
||||
/// <param name="ctx"></param>
|
||||
/// <param name="url">相对路径</param>
|
||||
/// <param name="width">宽度</param>
|
||||
/// <param name="height">高度</param>
|
||||
/// <param name="thumb">预览图</param>
|
||||
/// <param name="sequenceId"></param>
|
||||
/// <returns></returns>
|
||||
public static Message BuildImg(MessageCreateContext ctx, string url,
|
||||
int width, int height, string thumb, long sequenceId)
|
||||
{
|
||||
var content = new MessageContent("[图片]", new ImageBody(url, width, height, thumb));
|
||||
return new Message(ctx, sequenceId, MessageType.Image, content);
|
||||
}
|
||||
/// <summary>
|
||||
/// 视频消息
|
||||
/// </summary>
|
||||
/// <param name="ctx"></param>
|
||||
/// <param name="url"></param>
|
||||
/// <param name="width"></param>
|
||||
/// <param name="height"></param>
|
||||
/// <param name="thumb"></param>
|
||||
/// <param name="sequenceId"></param>
|
||||
/// <returns></returns>
|
||||
public static Message BuildVideo(MessageCreateContext ctx, string url,
|
||||
int width, int height, string thumb, long sequenceId)
|
||||
{
|
||||
var content = new MessageContent("[视频]", new VideoBody(url, width, height, thumb));
|
||||
return new Message(ctx, sequenceId, MessageType.Video, content);
|
||||
}
|
||||
/// <summary>
|
||||
/// 语音消息
|
||||
/// </summary>
|
||||
/// <param name="ctx"></param>
|
||||
/// <param name="url"></param>
|
||||
/// <param name="duration">持续时间</param>
|
||||
/// <param name="sequenceId"></param>
|
||||
/// <returns></returns>
|
||||
public static Message BuildVoice(MessageCreateContext ctx, string url,
|
||||
int duration, long sequenceId)
|
||||
{
|
||||
var content = new MessageContent("[音频]", new VoiceBody(url, duration));
|
||||
return new Message(ctx, sequenceId, MessageType.Voice, content);
|
||||
}
|
||||
/// <summary>
|
||||
/// 文件
|
||||
/// </summary>
|
||||
/// <param name="ctx"></param>
|
||||
/// <param name="url">相对路径</param>
|
||||
/// <param name="name">文件名</param>
|
||||
/// <param name="size">文件大小(KB)</param>
|
||||
/// <param name="format">文件格式</param>
|
||||
/// <param name="sequenceId"></param>
|
||||
/// <returns></returns>
|
||||
public static Message BuildFile(MessageCreateContext ctx, string url,
|
||||
string name, long size,
|
||||
string format, long sequenceId)
|
||||
{
|
||||
var content = new MessageContent("[文件]", new FileBody(url, name, size, format));
|
||||
return new Message(ctx, sequenceId, MessageType.File, content);
|
||||
}
|
||||
/// <summary>
|
||||
/// 添加扩展字段
|
||||
/// </summary>
|
||||
/// <param name="key">字段名</param>
|
||||
/// <param name="value">值</param>
|
||||
/// <returns></returns>
|
||||
public Message WithExt(string key, string value)
|
||||
{
|
||||
var dic = new Dictionary<string, string>();
|
||||
dic.Add(key, value);
|
||||
Content.RawExt = JsonSerializer.Serialize(dic);
|
||||
return this;
|
||||
}
|
||||
/// <summary>
|
||||
/// 添加消息引用
|
||||
/// </summary>
|
||||
/// <param name="quote"></param>
|
||||
/// <returns></returns>
|
||||
public Message WithQuote(QuoteInfo quote)
|
||||
{
|
||||
this.Content.Quote = quote;
|
||||
return this;
|
||||
}
|
||||
/// <summary>
|
||||
/// 完成消息
|
||||
/// </summary>
|
||||
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
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user