implement `MessagingService`

add list of replies to ``Message`` model
modify ``DBContext``
This commit is contained in:
Alan Moon 2025-02-14 13:44:19 -08:00
parent eb049bb4d5
commit 99f10fc547
3 changed files with 207 additions and 3 deletions

View File

@ -27,6 +27,7 @@ public class DBContext : DbContext {
// we had a brief debate on whether it's neighborhoods or neighborheed // we had a brief debate on whether it's neighborhoods or neighborheed
public DbSet<UserBan> UserBans { get; set; } = null!; public DbSet<UserBan> UserBans { get; set; } = null!;
public DbSet<Report> UserReports { get; set; } = null!; public DbSet<Report> UserReports { get; set; } = null!;
public DbSet<Message> Messages { get; set; } = null!;
public DbSet<Group> Groups { get; set; } = null!; public DbSet<Group> Groups { get; set; } = null!;
public DbSet<Rating> Ratings { get; set; } = null!; public DbSet<Rating> Ratings { get; set; } = null!;
public DbSet<RatingRank> RatingRanks { get; set; } = null!; public DbSet<RatingRank> RatingRanks { get; set; } = null!;
@ -305,6 +306,10 @@ public class DBContext : DbContext {
.WithMany(e => e.MessageBoard) .WithMany(e => e.MessageBoard)
.HasForeignKey(e => e.FromVikingId); .HasForeignKey(e => e.FromVikingId);
builder.Entity<Message>().HasOne(r => r.ParentMessage)
.WithMany(e => e.Replies)
.HasForeignKey(e => e.ParentMessageId);
// Groups // Groups
builder.Entity<Group>().HasMany(r => r.Vikings) builder.Entity<Group>().HasMany(r => r.Vikings)
.WithMany(e => e.Groups); .WithMany(e => e.Groups);

View File

@ -12,12 +12,13 @@ public class Message
public int VikingId { get; set; } public int VikingId { get; set; }
public int FromVikingId { get; set; } public int FromVikingId { get; set; }
public int? ParentMessageId { get; set; }
public int QueueID { get; set; } public int QueueID { get; set; }
public int? ConversationID { get; set; } public int? ConversationID { get; set; }
public int? ReplyToMessageID { get; set; }
public MessageType? MessageType { get; set; } public MessageType MessageType { get; set; }
public MessageTypeID? MessageTypeID { get; set; } public MessageTypeID MessageTypeID { get; set; }
public MessageLevel MessageLevel { get; set; } public MessageLevel MessageLevel { get; set; }
public string? Data { get; set; } public string? Data { get; set; }
@ -32,4 +33,6 @@ public class Message
public virtual Viking? Viking { get; set; } public virtual Viking? Viking { get; set; }
public virtual Viking? FromViking { get; set; } public virtual Viking? FromViking { get; set; }
public virtual Message? ParentMessage { get; set; }
public virtual ICollection<Message>? Replies { get; set; }
} }

View File

@ -0,0 +1,196 @@
using System;
using sodoff.Model;
using sodoff.Schema;
using sodoff.Util;
namespace sodoff.Services;
public class MessagingService
{
private readonly DBContext ctx;
public MessagingService(DBContext ctx)
{
this.ctx = ctx;
}
public Model.Message AddMessageToViking(Viking viking, Viking toViking, string apiToken, MessageType type, MessageTypeID typeID, MessageLevel level, string content, string memberMessage = "", string nonMemberMessage = "", bool isReply = false, int replyMessageID = 0) // previous implementation had seperate functions for text and data messages, lets combine them
{
Random rnd = new Random(); // 'ConversationId' and 'QueueId'
// create a new message
Model.Message message = new Model.Message
{
ConversationID = rnd.Next(1000, 9999),
QueueID = rnd.Next(1000, 9999),
CreatedAt = DateTime.UtcNow,
LastUpdatedAt = DateTime.UtcNow,
MessageType = type,
MessageLevel = level,
MessageTypeID = typeID,
Data = content,
IsNew = true // immediately mark as new
};
if (isReply == true && replyMessageID != 0)
{
// find the message this message is in reply to
Model.Message? messageToReplyTo = ctx.Messages.FirstOrDefault(e => e.Id == replyMessageID);
if(messageToReplyTo != null)
{
// set conversationid and queueid
message.ConversationID = messageToReplyTo.ConversationID;
message.QueueID = messageToReplyTo.QueueID;
// add to parent messages replies, create a collection of replies if message has none
if(messageToReplyTo.Replies == null) messageToReplyTo.Replies = new List<Model.Message>();
// add to list of replies
messageToReplyTo.Replies.Add(messageToReplyTo); // EF Core should do the rest (hopefully)
// return message here, do not add another parent message to message board
return message;
}
}
// add it to message lists
toViking.MessageBoard.Add(message);
viking.MessagesMade.Add(message);
ctx.SaveChanges();
return message;
}
public bool RemoveMessage(int id)
{
Model.Message? messageToRemove = ctx.Messages.FirstOrDefault(e => e.Id == id);
if (messageToRemove != null)
{
ctx.Messages.Remove(messageToRemove);
ctx.SaveChanges();
return true;
}
return false;
}
public CombinedListMessage[] ConstructCombinedMessageArray(Viking viking)
{
// get all viking messages
List<Model.Message> messages = viking.MessageBoard.ToList();
// create a new list of CombinedListMessage for the response
List<CombinedListMessage> response = new List<CombinedListMessage>();
// get current DateTime
DateTime now = DateTime.UtcNow;
foreach(Model.Message message in messages)
{
// if the message is older than 7 days or the 'IsDeleted' flag is set true, remove the message from the board
if(message.IsDeleted || message.CreatedAt > now.AddDays(7))
{
RemoveMessage(message.Id);
}
// construct a CombinedListMessage based on database model
CombinedListMessage msgRes = new CombinedListMessage
{
MessageType = (int)message.MessageType,
MessageBody = XmlUtil.SerializeXml(new Schema.Message
{
MessageID = message.Id,
ConversationID = message.ConversationID ?? 0,
ReplyToMessageID = message.ParentMessageId,
Creator = message.FromViking!.Uid.ToString() ?? "NotFound",
CreateTime = message.CreatedAt,
UpdateDate = message.LastUpdatedAt,
MessageType = message.MessageType,
MessageLevel = message.MessageLevel,
Content = message.Data ?? "There's nothing in this message! Please report this error to the server admins or devs.",
DisplayAttribute = "C=White" // hardcoding white for now
}),
MessageDate = message.CreatedAt
};
// if the message has a replies list, add those to response
if(message.Replies != null)
{
foreach(Model.Message replyMessage in message.Replies)
{
if (replyMessage.Viking == viking) continue; // this is in the original implementation, i forgot what it was for, might remove
CombinedListMessage replyRes = new CombinedListMessage
{
MessageType = (int)replyMessage.MessageType,
MessageBody = XmlUtil.SerializeXml(new Schema.Message
{
MessageID = replyMessage.Id,
ConversationID = replyMessage.ConversationID ?? 0,
ReplyToMessageID = replyMessage.ParentMessageId,
Creator = replyMessage.FromViking!.Uid.ToString() ?? "NotFound",
CreateTime = replyMessage.CreatedAt,
UpdateDate = replyMessage.LastUpdatedAt,
MessageType = replyMessage.MessageType,
MessageLevel = replyMessage.MessageLevel,
Content = replyMessage.Data ?? "There's nothing in this message! Please report this error to the server admins or devs.",
DisplayAttribute = "C=White" // hardcoding white for now
}),
MessageDate = replyMessage.CreatedAt
};
response.Add(replyRes);
}
}
response.Add(msgRes);
}
// TODO - announcements, data messages (if above code doesn't add them)
// sort response by newest first
List<CombinedListMessage> sortedList = response.OrderBy(e => e.MessageDate).ToList();
sortedList.Reverse();
// return response as an array
return response.ToArray();
}
public MessageInfo[] ConstructUserMessageInfoArray(Viking viking, bool showOldMessages, bool showDeletedMessages)
{
// get all recent messages from viking message board
List<Model.Message> recentMessages = viking.MessageBoard.OrderBy(e => e.CreatedAt)
.OrderBy(e => e.QueueID)
.ToList();
// make a new MessageInfo list for the response
List<MessageInfo> response = new List<MessageInfo>();
// get current DateTime
DateTime now = DateTime.UtcNow;
foreach(Model.Message message in recentMessages)
{
if(!showOldMessages && message.IsDeleted) continue;
if(!message.IsNew) continue;
if(message.MessageType == MessageType.Announcement) continue; // no return viking
if(message.CreatedAt > now.AddMinutes(30) && message.IsNew) continue; // do not add messages that are older than 30 minutes even if IsNew was marked
response.Add(new MessageInfo
{
MessageID = message.Id,
UserMessageQueueID = message.QueueID,
FromUserID = message.FromViking!.Uid.ToString() ?? "NotFound",
MessageTypeID = (int)message.MessageTypeID,
Data = message.Data ?? "NoData",
MemberMessage = message.MemberMessage ?? "NoData",
NonMemberMessage = message.NonMemberMessage ?? "NoData"
});
}
return response.ToArray();
}
}