Разделение сообщения
This commit is contained in:
@@ -0,0 +1,17 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Knot.Contracts.Messaging.Domain;
|
||||||
|
|
||||||
|
public class Media
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
public string Type { get; set; } = string.Empty;
|
||||||
|
public string? Url { get; set; }
|
||||||
|
public string? ThumbnailUrl { get; set; }
|
||||||
|
public long? Size { get; set; }
|
||||||
|
public int Width { get; set; }
|
||||||
|
public int Height { get; set; }
|
||||||
|
public string? FileId { get; set; }
|
||||||
|
public string? Filename { get; set; }
|
||||||
|
public string? Duration { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Knot.Contracts.Messaging.Domain;
|
||||||
|
|
||||||
|
public class MediaMessage : Message
|
||||||
|
{
|
||||||
|
public override string Type => MediaType.ToString().ToLower();
|
||||||
|
public override string? Content { get; protected set; }
|
||||||
|
public string? Caption { get => Content; private set => Content = value; }
|
||||||
|
public MediaType MediaType { get; private set; }
|
||||||
|
|
||||||
|
private List<Media> _media = new();
|
||||||
|
public IReadOnlyCollection<Media> Media => _media.AsReadOnly();
|
||||||
|
|
||||||
|
private MediaMessage() : base() { MediaType = MediaType.File; }
|
||||||
|
|
||||||
|
public MediaMessage(Guid id, Guid chatId, Guid senderId, MediaType mediaType, string? caption, Guid? replyToId, Guid? forwardedFromId, DateTime createdAt, bool isImported)
|
||||||
|
: base(id, chatId, senderId, replyToId, forwardedFromId, createdAt, isImported) { MediaType = mediaType; Caption = caption; }
|
||||||
|
|
||||||
|
public MediaMessage(Guid id, Guid chatId, Guid senderId, string mediaType, string? caption, Guid? replyToId, Guid? forwardedFromId, DateTime createdAt, bool isImported)
|
||||||
|
: this(id, chatId, senderId, Enum.TryParse<MediaType>(mediaType, true, out var mt) ? mt : MediaType.File, caption, replyToId, forwardedFromId, createdAt, isImported) { }
|
||||||
|
|
||||||
|
public void AddMedia(string type, string url, string? filename, long? size) => _media.Add(new Media { Type = type, Url = url, FileId = filename, Size = size });
|
||||||
|
|
||||||
|
public override void Edit(string newCaption) => base.Edit(newCaption);
|
||||||
|
|
||||||
|
public override void Delete() { Caption = null; base.Delete(); }
|
||||||
|
}
|
||||||
@@ -16,18 +16,17 @@ public abstract class Message : AggregateRoot<Guid>
|
|||||||
public MessageState State { get; protected set; }
|
public MessageState State { get; protected set; }
|
||||||
public abstract string Type { get; }
|
public abstract string Type { get; }
|
||||||
public abstract string? Content { get; protected set; }
|
public abstract string? Content { get; protected set; }
|
||||||
public virtual string? Quote { get; protected set; } = null;
|
|
||||||
public virtual Guid? StoryId => null;
|
|
||||||
public virtual string? StoryMediaUrl => null;
|
|
||||||
public virtual string? StoryMediaType => null;
|
|
||||||
public virtual IReadOnlyCollection<Media> Media => Array.Empty<Media>();
|
|
||||||
public bool IsEdited => HasState(MessageState.IsEdited);
|
public bool IsEdited => HasState(MessageState.IsEdited);
|
||||||
public bool IsDeleted => HasState(MessageState.IsDeleted);
|
public bool IsDeleted => HasState(MessageState.IsDeleted);
|
||||||
public bool IsDeletedForUser(Guid userId) => _deletedFor.Exists(d => d.UserId == userId);
|
|
||||||
protected List<DeletedMessage> _deletedFor = new();
|
protected List<DeletedMessage> _deletedFor = new();
|
||||||
public IReadOnlyCollection<DeletedMessage> DeletedFor => _deletedFor.AsReadOnly();
|
public IReadOnlyCollection<DeletedMessage> DeletedFor => _deletedFor.AsReadOnly();
|
||||||
|
|
||||||
protected Message() : base(Guid.Empty) { }
|
protected Message() : base(Guid.Empty) { }
|
||||||
protected Message(Guid id, Guid chatId, Guid senderId, Guid? replyToId, Guid? forwardedFromId, DateTime createdAt, bool isImported) : base(id)
|
|
||||||
|
protected Message(Guid id, Guid chatId, Guid senderId, Guid? replyToId, Guid? forwardedFromId, DateTime createdAt, bool isImported)
|
||||||
|
: base(id)
|
||||||
{
|
{
|
||||||
ChatId = chatId;
|
ChatId = chatId;
|
||||||
SenderId = senderId;
|
SenderId = senderId;
|
||||||
@@ -36,91 +35,22 @@ public abstract class Message : AggregateRoot<Guid>
|
|||||||
CreatedAt = createdAt;
|
CreatedAt = createdAt;
|
||||||
if (isImported) AddState(MessageState.IsImported);
|
if (isImported) AddState(MessageState.IsImported);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddState(MessageState state) => State |= state;
|
public void AddState(MessageState state) => State |= state;
|
||||||
public void RemoveState(MessageState state) => State &= ~state;
|
public void RemoveState(MessageState state) => State &= ~state;
|
||||||
public bool HasState(MessageState state) => (State & state) == state;
|
public bool HasState(MessageState state) => (State & state) == state;
|
||||||
|
public bool IsDeletedForUser(Guid userId) => _deletedFor.Exists(d => d.UserId == userId);
|
||||||
|
|
||||||
public virtual void Delete() => AddState(MessageState.IsDeleted);
|
public virtual void Delete() => AddState(MessageState.IsDeleted);
|
||||||
public virtual void Edit(string newContent) { Content = newContent; AddState(MessageState.IsEdited); }
|
public virtual void Edit(string newContent)
|
||||||
public void DeleteForUser(Guid userId) { if (!_deletedFor.Exists(x => x.UserId == userId)) _deletedFor.Add(new DeletedMessage(Id, userId)); }
|
{
|
||||||
|
Content = newContent;
|
||||||
|
AddState(MessageState.IsEdited);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Media
|
public void DeleteForUser(Guid userId)
|
||||||
{
|
{
|
||||||
public Guid Id { get; set; }
|
if (!_deletedFor.Exists(x => x.UserId == userId))
|
||||||
public string Type { get; set; } = string.Empty;
|
_deletedFor.Add(new DeletedMessage(Id, userId));
|
||||||
public string? Url { get; set; }
|
|
||||||
public string? ThumbnailUrl { get; set; }
|
|
||||||
public long? Size { get; set; }
|
|
||||||
public int Width { get; set; }
|
|
||||||
public int Height { get; set; }
|
|
||||||
public string? FileId { get; set; }
|
|
||||||
public string? Filename { get; set; }
|
|
||||||
public string? Duration { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class TextMessage : Message
|
|
||||||
{
|
|
||||||
public override string Type => "text";
|
|
||||||
public override string? Content { get; protected set; }
|
|
||||||
public TextMessage() : base() { }
|
|
||||||
public TextMessage(Guid id, Guid chatId, Guid senderId, string content, Guid? replyToId, Guid? forwardedFromId, DateTime createdAt, bool isImported = false)
|
|
||||||
: base(id, chatId, senderId, replyToId, forwardedFromId, createdAt, isImported) => Content = content;
|
|
||||||
public TextMessage(Guid id, Guid chatId, Guid senderId, string content, Guid? replyToId, string? quote, Guid? forwardedFromId, DateTime createdAt, bool isImported = false)
|
|
||||||
: this(id, chatId, senderId, content, replyToId, forwardedFromId, createdAt, isImported) => Quote = quote;
|
|
||||||
}
|
|
||||||
|
|
||||||
public class MediaMessage : Message
|
|
||||||
{
|
|
||||||
public override string Type => MediaType.ToString().ToLower();
|
|
||||||
public override string? Content { get; protected set; }
|
|
||||||
public string? Caption { get => Content; private set => Content = value; }
|
|
||||||
public MediaType MediaType { get; private set; }
|
|
||||||
private List<Media> _media = new();
|
|
||||||
public override IReadOnlyCollection<Media> Media => _media.AsReadOnly();
|
|
||||||
private MediaMessage() : base() { MediaType = MediaType.File; }
|
|
||||||
public MediaMessage(Guid id, Guid chatId, Guid senderId, MediaType mediaType, string? caption, Guid? replyToId, Guid? forwardedFromId, DateTime createdAt, bool isImported)
|
|
||||||
: base(id, chatId, senderId, replyToId, forwardedFromId, createdAt, isImported) { MediaType = mediaType; Caption = caption; }
|
|
||||||
public MediaMessage(Guid id, Guid chatId, Guid senderId, string mediaType, string? caption, Guid? replyToId, Guid? forwardedFromId, DateTime createdAt, bool isImported)
|
|
||||||
: this(id, chatId, senderId, Enum.TryParse<MediaType>(mediaType, true, out var mt) ? mt : MediaType.File, caption, replyToId, forwardedFromId, createdAt, isImported) { }
|
|
||||||
public void AddMedia(string type, string url, string? filename, long? size) => _media.Add(new Media { Type = type, Url = url, FileId = filename, Size = size });
|
|
||||||
public override void Edit(string newCaption) => base.Edit(newCaption);
|
|
||||||
public override void Delete() { Caption = null; base.Delete(); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class StoryMessage : Message
|
|
||||||
{
|
|
||||||
public override string Type => "story";
|
|
||||||
public override string? Content { get; protected set; }
|
|
||||||
public override Guid? StoryId { get; }
|
|
||||||
public string? InternalStoryMediaUrl { get; private set; }
|
|
||||||
public override string? StoryMediaUrl => InternalStoryMediaUrl;
|
|
||||||
public override string? StoryMediaType { get; }
|
|
||||||
public StoryMessage() : base() { }
|
|
||||||
public StoryMessage(Guid id, Guid chatId, Guid senderId, Guid storyId, string? storyMediaUrl, string? storyMediaType, DateTime createdAt)
|
|
||||||
: base(id, chatId, senderId, null, null, createdAt, false) { StoryId = storyId; InternalStoryMediaUrl = storyMediaUrl; StoryMediaType = storyMediaType; }
|
|
||||||
public StoryMessage(Guid id, Guid chatId, Guid senderId, Guid storyId, string? storyMediaUrl, string? storyMediaType, string? content, Guid? replyToId, Guid? forwardedFromId, DateTime createdAt, bool isImported)
|
|
||||||
: this(id, chatId, senderId, storyId, storyMediaUrl, storyMediaType, createdAt) { Content = content; ReplyToId = replyToId; ForwardedFromId = forwardedFromId; if (isImported) AddState(MessageState.IsImported); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class PollMessage : Message
|
|
||||||
{
|
|
||||||
public override string Type => "poll";
|
|
||||||
public override string? Content { get; protected set; }
|
|
||||||
public List<PollOption> Options { get; } = new();
|
|
||||||
public List<PollVote> Votes { get; } = new();
|
|
||||||
public bool IsMultipleChoice { get; set; }
|
|
||||||
public DateTime? ExpiresAt { get; set; }
|
|
||||||
public bool IsClosed { get; set; }
|
|
||||||
public PollMessage() : base() { }
|
|
||||||
public PollMessage(Guid id, Guid chatId, Guid senderId, string? question, List<string>? options, bool isAnonymous, bool isMultiple, DateTime? expiresAt, Guid? replyToId, Guid? forwardedFromId, DateTime createdAt, bool isImported)
|
|
||||||
: base(id, chatId, senderId, replyToId, forwardedFromId, createdAt, isImported)
|
|
||||||
{
|
|
||||||
Content = question ?? "Poll";
|
|
||||||
if (options != null) foreach (var opt in options) Options.Add(new PollOption { Text = opt });
|
|
||||||
IsMultipleChoice = isMultiple;
|
|
||||||
ExpiresAt = expiresAt;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PollOption { public string Text { get; set; } = string.Empty; public int VoteCount { get; set; } }
|
|
||||||
public class PollVote { public Guid OptionIndex { get; set; } public Guid UserId { get; set; } public DateTime VotedAt { get; set; } }
|
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Knot.Contracts.Messaging.Domain;
|
||||||
|
|
||||||
|
public class PollMessage : Message
|
||||||
|
{
|
||||||
|
public override string Type => "poll";
|
||||||
|
public override string? Content { get; protected set; }
|
||||||
|
public List<PollOption> Options { get; } = new();
|
||||||
|
public List<PollVote> Votes { get; } = new();
|
||||||
|
public bool IsMultipleChoice { get; set; }
|
||||||
|
public DateTime? ExpiresAt { get; set; }
|
||||||
|
public bool IsClosed { get; set; }
|
||||||
|
|
||||||
|
public PollMessage() : base() { }
|
||||||
|
|
||||||
|
public PollMessage(Guid id, Guid chatId, Guid senderId, string? question, List<string>? options, bool isAnonymous, bool isMultiple, DateTime? expiresAt, Guid? replyToId, Guid? forwardedFromId, DateTime createdAt, bool isImported)
|
||||||
|
: base(id, chatId, senderId, replyToId, forwardedFromId, createdAt, isImported)
|
||||||
|
{
|
||||||
|
Content = question ?? "Poll";
|
||||||
|
if (options != null)
|
||||||
|
{
|
||||||
|
foreach (var opt in options)
|
||||||
|
{
|
||||||
|
Options.Add(new PollOption { Text = opt });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
IsMultipleChoice = isMultiple;
|
||||||
|
ExpiresAt = expiresAt;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace Knot.Contracts.Messaging.Domain;
|
||||||
|
|
||||||
|
public class PollOption
|
||||||
|
{
|
||||||
|
public string Text { get; set; } = string.Empty;
|
||||||
|
public int VoteCount { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Knot.Contracts.Messaging.Domain;
|
||||||
|
|
||||||
|
public class PollVote
|
||||||
|
{
|
||||||
|
public Guid OptionIndex { get; set; }
|
||||||
|
public Guid UserId { get; set; }
|
||||||
|
public DateTime VotedAt { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Knot.Contracts.Messaging.Domain;
|
||||||
|
|
||||||
|
public class StoryMessage : Message
|
||||||
|
{
|
||||||
|
public override string Type => "story";
|
||||||
|
public override string? Content { get; protected set; }
|
||||||
|
public Guid? StoryId { get; private set; }
|
||||||
|
public string? StoryMediaUrl { get; private set; }
|
||||||
|
public string? StoryMediaType { get; private set; }
|
||||||
|
|
||||||
|
public StoryMessage() : base() { }
|
||||||
|
|
||||||
|
public StoryMessage(Guid id, Guid chatId, Guid senderId, Guid storyId, string? storyMediaUrl, string? storyMediaType, DateTime createdAt)
|
||||||
|
: base(id, chatId, senderId, null, null, createdAt, false)
|
||||||
|
{
|
||||||
|
StoryId = storyId;
|
||||||
|
StoryMediaUrl = storyMediaUrl;
|
||||||
|
StoryMediaType = storyMediaType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StoryMessage(Guid id, Guid chatId, Guid senderId, Guid storyId, string? storyMediaUrl, string? storyMediaType, string? content, Guid? replyToId, Guid? forwardedFromId, DateTime createdAt, bool isImported)
|
||||||
|
: this(id, chatId, senderId, storyId, storyMediaUrl, storyMediaType, createdAt)
|
||||||
|
{
|
||||||
|
Content = content;
|
||||||
|
ReplyToId = replyToId;
|
||||||
|
ForwardedFromId = forwardedFromId;
|
||||||
|
if (isImported) AddState(MessageState.IsImported);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Knot.Contracts.Messaging.Domain;
|
||||||
|
|
||||||
|
public class TextMessage : Message
|
||||||
|
{
|
||||||
|
public override string Type => "text";
|
||||||
|
public override string? Content { get; protected set; }
|
||||||
|
public string? Quote { get; protected set; }
|
||||||
|
|
||||||
|
public TextMessage() : base() { }
|
||||||
|
|
||||||
|
public TextMessage(Guid id, Guid chatId, Guid senderId, string content, Guid? replyToId, Guid? forwardedFromId, DateTime createdAt, bool isImported = false)
|
||||||
|
: base(id, chatId, senderId, replyToId, forwardedFromId, createdAt, isImported) => Content = content;
|
||||||
|
|
||||||
|
public TextMessage(Guid id, Guid chatId, Guid senderId, string content, Guid? replyToId, string? quote, Guid? forwardedFromId, DateTime createdAt, bool isImported = false)
|
||||||
|
: this(id, chatId, senderId, content, replyToId, forwardedFromId, createdAt, isImported) => Quote = quote;
|
||||||
|
}
|
||||||
@@ -109,6 +109,10 @@ internal sealed class GetChatByIdQueryHandler : IQueryHandler<GetChatByIdQuery,
|
|||||||
.Select(m => new ReadByDto(m.UserId))
|
.Select(m => new ReadByDto(m.UserId))
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
|
var textMessage = latestMessage as TextMessage;
|
||||||
|
var mediaMessage = latestMessage as MediaMessage;
|
||||||
|
var storyMessage = latestMessage as StoryMessage;
|
||||||
|
|
||||||
messagesList.Add(new ChatMessageDto(
|
messagesList.Add(new ChatMessageDto(
|
||||||
latestMessage.Id,
|
latestMessage.Id,
|
||||||
latestMessage.ChatId,
|
latestMessage.ChatId,
|
||||||
@@ -116,15 +120,15 @@ internal sealed class GetChatByIdQueryHandler : IQueryHandler<GetChatByIdQuery,
|
|||||||
latestMessage.Content,
|
latestMessage.Content,
|
||||||
latestMessage.Type,
|
latestMessage.Type,
|
||||||
latestMessage.ReplyToId,
|
latestMessage.ReplyToId,
|
||||||
latestMessage.Quote,
|
textMessage?.Quote,
|
||||||
latestMessage.StoryId,
|
storyMessage?.StoryId,
|
||||||
latestMessage.StoryMediaUrl,
|
storyMessage?.StoryMediaUrl,
|
||||||
latestMessage.StoryMediaType,
|
storyMessage?.StoryMediaType,
|
||||||
latestMessage.IsEdited,
|
latestMessage.IsEdited,
|
||||||
latestMessage.IsDeleted,
|
latestMessage.IsDeleted,
|
||||||
latestMessage.CreatedAt,
|
latestMessage.CreatedAt,
|
||||||
latestMessage.SequenceId,
|
latestMessage.SequenceId,
|
||||||
latestMessage.Media.Select(media => new MediaDto(media.Id, media.Type, media.Url, media.Filename, media.Size)).ToList(),
|
mediaMessage?.Media.Select(media => new MediaDto(media.Id, media.Type, media.Url, media.Filename, media.Size)).ToList() ?? new List<MediaDto>(),
|
||||||
senderObj != null ? new MessageSenderDto(
|
senderObj != null ? new MessageSenderDto(
|
||||||
senderObj.Id,
|
senderObj.Id,
|
||||||
senderObj.Username,
|
senderObj.Username,
|
||||||
|
|||||||
@@ -101,6 +101,10 @@ internal sealed class GetChatsQueryHandler : IQueryHandler<GetChatsQuery, List<C
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var textMessage = latestMessage as TextMessage;
|
||||||
|
var mediaMessage = latestMessage as MediaMessage;
|
||||||
|
var storyMessage = latestMessage as StoryMessage;
|
||||||
|
|
||||||
messagesList.Add(new ChatMessageDto(
|
messagesList.Add(new ChatMessageDto(
|
||||||
latestMessage.Id,
|
latestMessage.Id,
|
||||||
latestMessage.ChatId,
|
latestMessage.ChatId,
|
||||||
@@ -108,15 +112,15 @@ internal sealed class GetChatsQueryHandler : IQueryHandler<GetChatsQuery, List<C
|
|||||||
latestMessage.Content,
|
latestMessage.Content,
|
||||||
latestMessage.Type,
|
latestMessage.Type,
|
||||||
latestMessage.ReplyToId,
|
latestMessage.ReplyToId,
|
||||||
latestMessage.Quote,
|
textMessage?.Quote,
|
||||||
latestMessage.StoryId,
|
storyMessage?.StoryId,
|
||||||
latestMessage.StoryMediaUrl,
|
storyMessage?.StoryMediaUrl,
|
||||||
latestMessage.StoryMediaType,
|
storyMessage?.StoryMediaType,
|
||||||
latestMessage.IsEdited,
|
latestMessage.IsEdited,
|
||||||
latestMessage.IsDeleted,
|
latestMessage.IsDeleted,
|
||||||
latestMessage.CreatedAt,
|
latestMessage.CreatedAt,
|
||||||
latestMessage.SequenceId,
|
latestMessage.SequenceId,
|
||||||
latestMessage.Media.Select(media => new MediaDto(media.Id, media.Type, media.Url, media.Filename, media.Size)).ToList(),
|
mediaMessage?.Media.Select(media => new MediaDto(media.Id, media.Type, media.Url, media.Filename, media.Size)).ToList() ?? new List<MediaDto>(),
|
||||||
senderObj != null ? new MessageSenderDto(
|
senderObj != null ? new MessageSenderDto(
|
||||||
senderObj.Id,
|
senderObj.Id,
|
||||||
senderObj.Username,
|
senderObj.Username,
|
||||||
|
|||||||
+10
-6
@@ -96,7 +96,7 @@ internal sealed class GetMessagesQueryHandler : IQueryHandler<GetMessagesQuery,
|
|||||||
replyMsg.Id,
|
replyMsg.Id,
|
||||||
replyMsg.Content,
|
replyMsg.Content,
|
||||||
replyMsg.IsDeleted,
|
replyMsg.IsDeleted,
|
||||||
replyMsg.Media.Select(rm => new MediaDto(rm.Id, rm.Type, rm.Url, rm.Filename, rm.Size)).ToList(),
|
(replyMsg as MediaMessage)?.Media.Select(rm => new MediaDto(rm.Id, rm.Type, rm.Url, rm.Filename, rm.Size)).ToList() ?? new List<MediaDto>(),
|
||||||
senderObj
|
senderObj
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -117,6 +117,10 @@ internal sealed class GetMessagesQueryHandler : IQueryHandler<GetMessagesQuery,
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var textMessage = message as TextMessage;
|
||||||
|
var mediaMessage = message as MediaMessage;
|
||||||
|
var storyMessage = message as StoryMessage;
|
||||||
|
|
||||||
result.Add(new MessageDetailDto(
|
result.Add(new MessageDetailDto(
|
||||||
message.Id,
|
message.Id,
|
||||||
message.ChatId,
|
message.ChatId,
|
||||||
@@ -125,17 +129,17 @@ internal sealed class GetMessagesQueryHandler : IQueryHandler<GetMessagesQuery,
|
|||||||
message.Type,
|
message.Type,
|
||||||
message.ReplyToId,
|
message.ReplyToId,
|
||||||
replyToObj,
|
replyToObj,
|
||||||
message.Quote,
|
textMessage?.Quote,
|
||||||
message.IsEdited,
|
message.IsEdited,
|
||||||
message.IsDeleted,
|
message.IsDeleted,
|
||||||
message.CreatedAt,
|
message.CreatedAt,
|
||||||
message.SequenceId,
|
message.SequenceId,
|
||||||
message.ForwardedFromId,
|
message.ForwardedFromId,
|
||||||
message.ForwardedFromId.HasValue && senders.TryGetValue(message.ForwardedFromId.Value, out var fwdUser) ? new MessageSenderDto(fwdUser.Id, fwdUser.Username, fwdUser.DisplayName, fwdUser.Avatar) : null,
|
message.ForwardedFromId.HasValue && senders.TryGetValue(message.ForwardedFromId.Value, out var fwdUser) ? new MessageSenderDto(fwdUser.Id, fwdUser.Username, fwdUser.DisplayName, fwdUser.Avatar) : null,
|
||||||
message.StoryId,
|
storyMessage?.StoryId,
|
||||||
message.StoryMediaUrl,
|
storyMessage?.StoryMediaUrl,
|
||||||
message.StoryMediaType,
|
storyMessage?.StoryMediaType,
|
||||||
message.Media.Select(media => new MediaDto(media.Id, media.Type, media.Url, media.Filename, media.Size)).ToList(),
|
mediaMessage?.Media.Select(media => new MediaDto(media.Id, media.Type, media.Url, media.Filename, media.Size)).ToList() ?? new List<MediaDto>(),
|
||||||
senders.TryGetValue(message.SenderId, out var senderUser) ? new MessageSenderDto(senderUser.Id, senderUser.Username, senderUser.DisplayName, senderUser.Avatar) : null,
|
senders.TryGetValue(message.SenderId, out var senderUser) ? new MessageSenderDto(senderUser.Id, senderUser.Username, senderUser.DisplayName, senderUser.Avatar) : null,
|
||||||
chat.Members.Where(m => m.LastReadSequenceId >= message.SequenceId && m.UserId != message.SenderId).Select(m => new ReadByDto(m.UserId)).ToList(),
|
chat.Members.Where(m => m.LastReadSequenceId >= message.SequenceId && m.UserId != message.SenderId).Select(m => new ReadByDto(m.UserId)).ToList(),
|
||||||
reactionsWithUser
|
reactionsWithUser
|
||||||
|
|||||||
+18
-11
@@ -48,13 +48,20 @@ internal sealed class GetSharedMediaQueryHandler : IQueryHandler<GetSharedMediaQ
|
|||||||
|
|
||||||
foreach (var message in messages)
|
foreach (var message in messages)
|
||||||
{
|
{
|
||||||
|
var mediaMessage = message as MediaMessage;
|
||||||
|
var textMessage = message as TextMessage;
|
||||||
|
var storyMessage = message as StoryMessage;
|
||||||
|
|
||||||
if (filterType == "links")
|
if (filterType == "links")
|
||||||
{
|
{
|
||||||
var messageContent = message.Content;
|
var messageContent = message.Content;
|
||||||
var linkRegex = new Regex(@"https?://[^\s]+", RegexOptions.IgnoreCase);
|
var linkRegex = new Regex(@"https?://[^\s]+", RegexOptions.IgnoreCase);
|
||||||
var contentLinks = !string.IsNullOrEmpty(messageContent) ? linkRegex.Matches(messageContent).Select(match => match.Value).ToList() : new List<string>();
|
var contentLinks = !string.IsNullOrEmpty(messageContent) ? linkRegex.Matches(messageContent).Select(match => match.Value).ToList() : new List<string>();
|
||||||
var messageMediaColl = message.Media;
|
|
||||||
var mediaLinks = (messageMediaColl ?? Enumerable.Empty<Media>()).Where(media => media.Type?.ToString().ToLower() == "link").Select(media => media.Url).ToList();
|
var mediaLinks = (mediaMessage?.Media ?? Enumerable.Empty<Media>())
|
||||||
|
.Where(media => media.Type?.ToString().ToLower() == "link" && !string.IsNullOrEmpty(media.Url))
|
||||||
|
.Select(media => media.Url!)
|
||||||
|
.ToList();
|
||||||
var allLinks = contentLinks.Concat(mediaLinks).Distinct().ToList();
|
var allLinks = contentLinks.Concat(mediaLinks).Distinct().ToList();
|
||||||
|
|
||||||
if (allLinks.Any())
|
if (allLinks.Any())
|
||||||
@@ -72,7 +79,7 @@ internal sealed class GetSharedMediaQueryHandler : IQueryHandler<GetSharedMediaQ
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var messageMedia = message.Media;
|
var messageMedia = mediaMessage?.Media;
|
||||||
if (messageMedia == null || !messageMedia.Any())
|
if (messageMedia == null || !messageMedia.Any())
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
@@ -80,8 +87,8 @@ internal sealed class GetSharedMediaQueryHandler : IQueryHandler<GetSharedMediaQ
|
|||||||
|
|
||||||
var filteredMedia = messageMedia.Where(media =>
|
var filteredMedia = messageMedia.Where(media =>
|
||||||
{
|
{
|
||||||
var mediaType = media.Type?.ToLower() ?? "file";
|
var mType = media.Type?.ToLower() ?? "file";
|
||||||
var isGif = mediaType == "image" && (media.Url.EndsWith(".mp4", StringComparison.OrdinalIgnoreCase) || media.Url.EndsWith(".gif", StringComparison.OrdinalIgnoreCase));
|
var isGif = mType == "image" && media.Url != null && (media.Url.EndsWith(".mp4", StringComparison.OrdinalIgnoreCase) || media.Url.EndsWith(".gif", StringComparison.OrdinalIgnoreCase));
|
||||||
|
|
||||||
if (filterType == "gifs")
|
if (filterType == "gifs")
|
||||||
{
|
{
|
||||||
@@ -90,12 +97,12 @@ internal sealed class GetSharedMediaQueryHandler : IQueryHandler<GetSharedMediaQ
|
|||||||
|
|
||||||
if (filterType == "files")
|
if (filterType == "files")
|
||||||
{
|
{
|
||||||
return mediaType != "image" && mediaType != "video" && mediaType != "link";
|
return mType != "image" && mType != "video" && mType != "link";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filterType == "media")
|
if (filterType == "media")
|
||||||
{
|
{
|
||||||
return (mediaType == "image" || mediaType == "video") && !isGif;
|
return (mType == "image" || mType == "video") && !isGif;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -111,10 +118,10 @@ internal sealed class GetSharedMediaQueryHandler : IQueryHandler<GetSharedMediaQ
|
|||||||
null,
|
null,
|
||||||
sender != null ? new MessageSenderDto(sender.Id, sender.Username, sender.DisplayName, sender.Avatar) : null,
|
sender != null ? new MessageSenderDto(sender.Id, sender.Username, sender.DisplayName, sender.Avatar) : null,
|
||||||
message.ReplyToId,
|
message.ReplyToId,
|
||||||
message.Quote,
|
textMessage?.Quote,
|
||||||
message.StoryId,
|
storyMessage?.StoryId,
|
||||||
message.StoryMediaUrl,
|
storyMessage?.StoryMediaUrl,
|
||||||
message.StoryMediaType,
|
storyMessage?.StoryMediaType,
|
||||||
message.IsEdited,
|
message.IsEdited,
|
||||||
message.Type,
|
message.Type,
|
||||||
filteredMedia.Select(media => new MediaDto(media.Id, media.Type, media.Url, media.Filename, media.Size)).ToList()
|
filteredMedia.Select(media => new MediaDto(media.Id, media.Type, media.Url, media.Filename, media.Size)).ToList()
|
||||||
|
|||||||
+13
-7
@@ -41,28 +41,34 @@ internal sealed class SearchMessagesQueryHandler : IQueryHandler<SearchMessagesQ
|
|||||||
var allReactions = await _reactionRepository.GetReactionsForMessagesAsync(messageIds, cancellationToken);
|
var allReactions = await _reactionRepository.GetReactionsForMessagesAsync(messageIds, cancellationToken);
|
||||||
var reactionsByMessage = allReactions.GroupBy(r => r.MessageId).ToDictionary(g => g.Key, g => g.ToList());
|
var reactionsByMessage = allReactions.GroupBy(r => r.MessageId).ToDictionary(g => g.Key, g => g.ToList());
|
||||||
|
|
||||||
var result = messages.Select(message => new SearchMessageDto(
|
var result = messages.Select(message => {
|
||||||
|
var textMessage = message as TextMessage;
|
||||||
|
var mediaMessage = message as MediaMessage;
|
||||||
|
var storyMessage = message as StoryMessage;
|
||||||
|
|
||||||
|
return new SearchMessageDto(
|
||||||
message.Id,
|
message.Id,
|
||||||
message.ChatId,
|
message.ChatId,
|
||||||
message.SenderId,
|
message.SenderId,
|
||||||
message.Content,
|
message.Content,
|
||||||
message.Type,
|
message.Type,
|
||||||
message.ReplyToId,
|
message.ReplyToId,
|
||||||
message.Quote,
|
textMessage?.Quote,
|
||||||
message.IsEdited,
|
message.IsEdited,
|
||||||
message.IsDeleted,
|
message.IsDeleted,
|
||||||
message.CreatedAt,
|
message.CreatedAt,
|
||||||
message.SequenceId,
|
message.SequenceId,
|
||||||
message.ForwardedFromId,
|
message.ForwardedFromId,
|
||||||
null,
|
null,
|
||||||
message.StoryId,
|
storyMessage?.StoryId,
|
||||||
message.StoryMediaUrl,
|
storyMessage?.StoryMediaUrl,
|
||||||
message.StoryMediaType,
|
storyMessage?.StoryMediaType,
|
||||||
message.Media.Select(media => new MediaDto(media.Id, media.Type, media.Url, media.Filename, media.Size)).ToList(),
|
mediaMessage?.Media.Select(media => new MediaDto(media.Id, media.Type, media.Url, media.Filename, media.Size)).ToList() ?? new List<MediaDto>(),
|
||||||
senders.TryGetValue(message.SenderId, out var senderUser) ? new MessageSenderDto(senderUser.Id, senderUser.Username, senderUser.DisplayName, senderUser.Avatar) : new MessageSenderDto(message.SenderId, "unknown", "Unknown", null),
|
senders.TryGetValue(message.SenderId, out var senderUser) ? new MessageSenderDto(senderUser.Id, senderUser.Username, senderUser.DisplayName, senderUser.Avatar) : new MessageSenderDto(message.SenderId, "unknown", "Unknown", null),
|
||||||
reactionsByMessage.TryGetValue(message.Id, out var mr) ? mr.Select(reaction => new SimpleReactionDto(reaction.UserId, reaction.Emoji)).ToList() : new List<SimpleReactionDto>(),
|
reactionsByMessage.TryGetValue(message.Id, out var mr) ? mr.Select(reaction => new SimpleReactionDto(reaction.UserId, reaction.Emoji)).ToList() : new List<SimpleReactionDto>(),
|
||||||
new List<ReadByDto>()
|
new List<ReadByDto>()
|
||||||
)).ToList();
|
);
|
||||||
|
}).ToList();
|
||||||
|
|
||||||
return Result.Success(result);
|
return Result.Success(result);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ public class MediaMessage : Message
|
|||||||
public MediaType MediaType { get; private set; } // image, video, file, voice
|
public MediaType MediaType { get; private set; } // image, video, file, voice
|
||||||
|
|
||||||
private List<Media> _media = new();
|
private List<Media> _media = new();
|
||||||
public override IReadOnlyCollection<Media> Media => _media.AsReadOnly();
|
public IReadOnlyCollection<Media> Media => _media.AsReadOnly();
|
||||||
|
|
||||||
private MediaMessage() : base()
|
private MediaMessage() : base()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -34,12 +34,6 @@ public abstract class Message : AggregateRoot<Guid>
|
|||||||
public abstract string Type { get; }
|
public abstract string Type { get; }
|
||||||
public abstract string? Content { get; protected set; }
|
public abstract string? Content { get; protected set; }
|
||||||
|
|
||||||
public virtual string? Quote { get; protected set; } = null;
|
|
||||||
public virtual Guid? StoryId => null;
|
|
||||||
public virtual string? StoryMediaUrl => null;
|
|
||||||
public virtual string? StoryMediaType => null;
|
|
||||||
public virtual IReadOnlyCollection<Media> Media => Array.Empty<Media>();
|
|
||||||
|
|
||||||
public bool IsEdited => HasState(MessageState.IsEdited);
|
public bool IsEdited => HasState(MessageState.IsEdited);
|
||||||
public bool IsDeleted => HasState(MessageState.IsDeleted);
|
public bool IsDeleted => HasState(MessageState.IsDeleted);
|
||||||
public bool IsDeletedForUser(Guid userId) => _deletedFor.Exists(d => d.UserId == userId);
|
public bool IsDeletedForUser(Guid userId) => _deletedFor.Exists(d => d.UserId == userId);
|
||||||
|
|||||||
@@ -112,47 +112,3 @@ public class PollMessage : Message
|
|||||||
base.Delete();
|
base.Delete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PollOption
|
|
||||||
{
|
|
||||||
public Guid Id { get; private set; }
|
|
||||||
public Guid PollId { get; private set; }
|
|
||||||
public string Text { get; private set; }
|
|
||||||
|
|
||||||
// Денормализованные данные для быстрой отдачи
|
|
||||||
public int VotesCount { get; private set; }
|
|
||||||
public int Percentage { get; private set; }
|
|
||||||
|
|
||||||
private PollOption() { } // EF
|
|
||||||
|
|
||||||
public PollOption(Guid id, Guid pollId, string text)
|
|
||||||
{
|
|
||||||
Id = id;
|
|
||||||
PollId = pollId;
|
|
||||||
Text = text;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdateResults(int count, int percentage)
|
|
||||||
{
|
|
||||||
VotesCount = count;
|
|
||||||
Percentage = percentage;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class PollVote
|
|
||||||
{
|
|
||||||
public Guid PollId { get; private set; }
|
|
||||||
public Guid UserId { get; private set; }
|
|
||||||
public Guid OptionId { get; private set; }
|
|
||||||
public DateTime VotedAt { get; private set; }
|
|
||||||
|
|
||||||
private PollVote() { } // EF
|
|
||||||
|
|
||||||
public PollVote(Guid pollId, Guid userId, Guid optionId, DateTime votedAt)
|
|
||||||
{
|
|
||||||
PollId = pollId;
|
|
||||||
UserId = userId;
|
|
||||||
OptionId = optionId;
|
|
||||||
VotedAt = votedAt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Knot.Modules.Messaging.Domain;
|
||||||
|
|
||||||
|
public class PollOption
|
||||||
|
{
|
||||||
|
public Guid Id { get; private set; }
|
||||||
|
public Guid PollId { get; private set; }
|
||||||
|
public string Text { get; private set; } = string.Empty;
|
||||||
|
|
||||||
|
// Денормализованные данные для быстрой отдачи
|
||||||
|
public int VotesCount { get; private set; }
|
||||||
|
public int Percentage { get; private set; }
|
||||||
|
|
||||||
|
private PollOption() { } // EF
|
||||||
|
|
||||||
|
public PollOption(Guid id, Guid pollId, string text)
|
||||||
|
{
|
||||||
|
Id = id;
|
||||||
|
PollId = pollId;
|
||||||
|
Text = text;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateResults(int count, int percentage)
|
||||||
|
{
|
||||||
|
VotesCount = count;
|
||||||
|
Percentage = percentage;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Knot.Modules.Messaging.Domain;
|
||||||
|
|
||||||
|
public class PollVote
|
||||||
|
{
|
||||||
|
public Guid PollId { get; private set; }
|
||||||
|
public Guid UserId { get; private set; }
|
||||||
|
public Guid OptionId { get; private set; }
|
||||||
|
public DateTime VotedAt { get; private set; }
|
||||||
|
|
||||||
|
private PollVote() { } // EF
|
||||||
|
|
||||||
|
public PollVote(Guid pollId, Guid userId, Guid optionId, DateTime votedAt)
|
||||||
|
{
|
||||||
|
PollId = pollId;
|
||||||
|
UserId = userId;
|
||||||
|
OptionId = optionId;
|
||||||
|
VotedAt = votedAt;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,13 +10,13 @@ public class StoryMessage : Message
|
|||||||
public override string? Content { get; protected set; }
|
public override string? Content { get; protected set; }
|
||||||
|
|
||||||
public Guid InternalStoryId { get; private set; }
|
public Guid InternalStoryId { get; private set; }
|
||||||
public override Guid? StoryId => InternalStoryId;
|
public Guid? StoryId => InternalStoryId;
|
||||||
|
|
||||||
public string InternalStoryMediaUrl { get; private set; }
|
public string InternalStoryMediaUrl { get; private set; }
|
||||||
public override string? StoryMediaUrl => InternalStoryMediaUrl;
|
public string? StoryMediaUrl => InternalStoryMediaUrl;
|
||||||
|
|
||||||
public MediaType InternalStoryMediaType { get; private set; }
|
public MediaType InternalStoryMediaType { get; private set; }
|
||||||
public override string? StoryMediaType => InternalStoryMediaType.ToString().ToLower();
|
public string? StoryMediaType => InternalStoryMediaType.ToString().ToLower();
|
||||||
|
|
||||||
private StoryMessage() : base()
|
private StoryMessage() : base()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ public class TextMessage : Message
|
|||||||
{
|
{
|
||||||
public override string Type => "text";
|
public override string Type => "text";
|
||||||
public override string? Content { get; protected set; }
|
public override string? Content { get; protected set; }
|
||||||
public override string? Quote { get; protected set; }
|
public string? Quote { get; protected set; }
|
||||||
|
|
||||||
private TextMessage() : base()
|
private TextMessage() : base()
|
||||||
{
|
{
|
||||||
|
|||||||
+8
-8
@@ -54,8 +54,8 @@ public sealed class MessageSentDomainEventHandler : INotificationHandler<Message
|
|||||||
{
|
{
|
||||||
Id = replyMsg.Id,
|
Id = replyMsg.Id,
|
||||||
Content = replyMsg.Content,
|
Content = replyMsg.Content,
|
||||||
Quote = message.Quote,
|
Quote = message is TextMessage tm ? tm.Quote : null,
|
||||||
media = replyMsg.Media.Select(rm => new { rm.Type, rm.Url }).ToList(),
|
media = (replyMsg as MediaMessage)?.Media.Select(rm => new { rm.Type, rm.Url }).ToList() ?? (object)Array.Empty<object>(),
|
||||||
Sender = replySenderInfo != null
|
Sender = replySenderInfo != null
|
||||||
? new { Id = replySenderInfo.Id, Username = replySenderInfo.Username, DisplayName = replySenderInfo.DisplayName }
|
? new { Id = replySenderInfo.Id, Username = replySenderInfo.Username, DisplayName = replySenderInfo.DisplayName }
|
||||||
: new { Id = replyMsg.SenderId, Username = "unknown", DisplayName = "Unknown" }
|
: new { Id = replyMsg.SenderId, Username = "unknown", DisplayName = "Unknown" }
|
||||||
@@ -75,19 +75,19 @@ public sealed class MessageSentDomainEventHandler : INotificationHandler<Message
|
|||||||
forwardedFrom = forwardedFromObj,
|
forwardedFrom = forwardedFromObj,
|
||||||
replyToId = message.ReplyToId,
|
replyToId = message.ReplyToId,
|
||||||
replyTo = replyToObj,
|
replyTo = replyToObj,
|
||||||
quote = message.Quote,
|
quote = message is TextMessage tm2 ? tm2.Quote : null,
|
||||||
media = message.Media.Select(m => new
|
media = (message as MediaMessage)?.Media.Select(m => new
|
||||||
{
|
{
|
||||||
type = m.Type,
|
type = m.Type,
|
||||||
url = m.Url,
|
url = m.Url,
|
||||||
filename = m.FileId,
|
filename = m.FileId,
|
||||||
size = m.Size
|
size = m.Size
|
||||||
}).ToList(),
|
}).ToList() ?? (object)Array.Empty<object>(),
|
||||||
sender = senderObj,
|
sender = senderObj,
|
||||||
readBy = new List<object>(),
|
readBy = new List<object>(),
|
||||||
storyId = message.StoryId,
|
storyId = (message as StoryMessage)?.StoryId,
|
||||||
storyMediaUrl = message.StoryMediaUrl,
|
storyMediaUrl = (message as StoryMessage)?.StoryMediaUrl,
|
||||||
storyMediaType = message.StoryMediaType
|
storyMediaType = (message as StoryMessage)?.StoryMediaType
|
||||||
}, cancellationToken);
|
}, cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-2
@@ -30,13 +30,15 @@ public static class MongoDbMapConfigurator
|
|||||||
cm.AutoMap();
|
cm.AutoMap();
|
||||||
cm.MapField("_deletedFor").SetElementName("DeletedFor");
|
cm.MapField("_deletedFor").SetElementName("DeletedFor");
|
||||||
cm.MapProperty(c => c.Content).SetSerializer(new EncryptedStringSerializer());
|
cm.MapProperty(c => c.Content).SetSerializer(new EncryptedStringSerializer());
|
||||||
cm.MapProperty(c => c.Quote).SetSerializer(new EncryptedStringSerializer());
|
cm.SetIgnoreExtraElements(true);
|
||||||
cm.SetIsRootClass(true);
|
cm.SetIsRootClass(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
BsonClassMap.RegisterClassMap<TextMessage>(cm =>
|
BsonClassMap.RegisterClassMap<TextMessage>(cm =>
|
||||||
{
|
{
|
||||||
cm.AutoMap();
|
cm.AutoMap();
|
||||||
|
cm.MapProperty(c => c.Quote).SetSerializer(new EncryptedStringSerializer());
|
||||||
|
cm.SetIgnoreExtraElements(true);
|
||||||
cm.SetDiscriminator("TextMessage");
|
cm.SetDiscriminator("TextMessage");
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -44,6 +46,7 @@ public static class MongoDbMapConfigurator
|
|||||||
{
|
{
|
||||||
cm.AutoMap();
|
cm.AutoMap();
|
||||||
cm.MapField("_media").SetElementName("Media");
|
cm.MapField("_media").SetElementName("Media");
|
||||||
|
cm.SetIgnoreExtraElements(true);
|
||||||
cm.SetDiscriminator("MediaMessage");
|
cm.SetDiscriminator("MediaMessage");
|
||||||
cm.UnmapProperty(c => c.Caption);
|
cm.UnmapProperty(c => c.Caption);
|
||||||
});
|
});
|
||||||
@@ -51,8 +54,9 @@ public static class MongoDbMapConfigurator
|
|||||||
BsonClassMap.RegisterClassMap<StoryMessage>(cm =>
|
BsonClassMap.RegisterClassMap<StoryMessage>(cm =>
|
||||||
{
|
{
|
||||||
cm.AutoMap();
|
cm.AutoMap();
|
||||||
|
cm.SetIgnoreExtraElements(true);
|
||||||
cm.SetDiscriminator("StoryMessage");
|
cm.SetDiscriminator("StoryMessage");
|
||||||
cm.MapProperty(c => c.InternalStoryMediaUrl).SetSerializer(new EncryptedStringSerializer());
|
cm.MapProperty(c => c.StoryMediaUrl).SetSerializer(new EncryptedStringSerializer());
|
||||||
});
|
});
|
||||||
|
|
||||||
BsonClassMap.RegisterClassMap<DeletedMessage>(cm => cm.AutoMap());
|
BsonClassMap.RegisterClassMap<DeletedMessage>(cm => cm.AutoMap());
|
||||||
@@ -63,6 +67,7 @@ public static class MongoDbMapConfigurator
|
|||||||
cm.AutoMap();
|
cm.AutoMap();
|
||||||
cm.MapProperty(c => c.Options).SetElementName("_options");
|
cm.MapProperty(c => c.Options).SetElementName("_options");
|
||||||
cm.MapProperty(c => c.Votes).SetElementName("_votes");
|
cm.MapProperty(c => c.Votes).SetElementName("_votes");
|
||||||
|
cm.SetIgnoreExtraElements(true);
|
||||||
cm.SetDiscriminator("PollMessage");
|
cm.SetDiscriminator("PollMessage");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user