jumpstart-games-reduxed/src/Services/MessagingService.cs

279 lines
11 KiB
C#

using System;
using System.Security.Cryptography.X509Certificates;
using Microsoft.EntityFrameworkCore;
using sodoff.Model;
using sodoff.Schema;
using sodoff.Util;
using ZstdSharp.Unsafe;
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, MessageType messageType, MessageTypeID messageTypeID, MessageLevel messageLevel, string data, string memberMessage = "", string nonMemberMessage = "", bool IsNew = true, bool IsDeleted = false, bool isReply = false, bool isPrivate = false, int parentMessageId = 0)
{
// get execution UTC timestamp
DateTime now = DateTime.UtcNow;
// for generating ConversationId and QueueId
Random rnd = new Random();
// construct message
Model.Message message = new Model.Message
{
Viking = viking,
VikingId = viking.Id,
ToViking = toViking,
ToVikingId = toViking.Id,
QueueID = rnd.Next(1000, 9999),
ConversationID = rnd.Next(1000, 9999),
MessageType = messageType,
MessageTypeID = messageTypeID,
MessageLevel = messageLevel,
Data = data,
MemberMessage = memberMessage,
NonMemberMessage = nonMemberMessage,
CreatedAt = now,
LastUpdatedAt = now,
IsDeleted = IsDeleted,
IsNew = IsNew,
IsPrivate = isPrivate
};
if (isReply && parentMessageId > 0)
{
// get message this is in reply to
Model.Message? messageToReplyTo = ctx.Messages.FirstOrDefault(e => e.Id == parentMessageId);
if (messageToReplyTo != null)
{
message.ParentMessage = messageToReplyTo;
message.ParentMessageId = messageToReplyTo.Id;
message.ConversationID = messageToReplyTo.ConversationID;
// add a message to the replier's board saying a thread update has occured (if reply isn't to self)
if (message.VikingId != message.ToVikingId) AddMessageToViking(message.Viking, message.ToViking, MessageType.Data, MessageTypeID.ThreadUpdate, MessageLevel.WhiteList, "[[Line1]]=[[{{BuddyUserName}} Replied To Your Message In {{BuddyUserName}}'s Message Board!]]", "[[Line1]]=[[{{BuddyUserName}} Replied To Your Message In {{BuddyUserName}}'s Message Board!]]", "[[Line1]]=[[{{BuddyUserName}} Replied To Your Message In {{BuddyUserName}}'s Message Board!]]", isPrivate: true);
} else throw new InvalidOperationException("Tried To Reply To A Message That Doesn't Exist");
}
// add message to database
ctx.Messages.Add(message);
ctx.SaveChanges();
// return constructed message
return message;
}
public void RemoveMessage(int id)
{
// find message
Model.Message? message = ctx.Messages.FirstOrDefault(e => e.Id == id);
if (message != null)
{
// remove it
ctx.Messages.Remove(message);
ctx.SaveChanges();
} else throw new InvalidOperationException("Tried To Delete A Message That Doesn't Exist");
}
public Model.Message? UpdateMessageByQueueID(int queueId, bool isNew, bool IsDeleted)
{
// get execution UTC timestamp
DateTime now = DateTime.UtcNow;
// find message
Model.Message? message = ctx.Messages.FirstOrDefault(e => e.QueueID == queueId);
if (message != null)
{
// set params (TODO - figure out what else the clients update in messages)
message.IsNew = isNew;
message.IsDeleted = IsDeleted;
message.LastUpdatedAt = now;
ctx.SaveChanges();
return message;
} else return null;
}
public ArrayOfCombinedListMessage ConstructCombinedMessageArray(Viking viking, Viking publicViking)
{
// get all messages in viking board
List<Model.Message> messages = ctx.Messages.Where(e => e.ToVikingId == viking.Id).ToList();
List<CombinedListMessage> combinedListMessages = new List<CombinedListMessage>();
ArrayOfCombinedListMessage response = new ArrayOfCombinedListMessage();
foreach(var message in messages)
{
if (message.IsDeleted)
{
ctx.Messages.Remove(message);
continue;
}
if (message.IsPrivate && (viking.Id != publicViking.Id)) continue;
Viking? msgAuthor = ctx.Vikings.FirstOrDefault(e => e.Id == message.VikingId) ?? new Viking();
// construct a CombinedListMessage based on Model.Message
CombinedListMessage clm = new CombinedListMessage
{
MessageType = (int?)message.MessageType ?? 0,
MessageDate = message.CreatedAt
};
// if type id is messaging, use Schema.Message, otherwise treat it as Schema.MessageInfo
if (message.MessageTypeID == MessageTypeID.Messaging)
{
clm.MessageBody = XmlUtil.SerializeXml(new Schema.Message
{
MessageID = message.Id,
ConversationID = message.ConversationID ?? 0,
ReplyToMessageID = message.ParentMessageId,
Creator = msgAuthor.Uid.ToString() ?? "Ghost",
CreateTime = message.CreatedAt,
UpdateDate = message.LastUpdatedAt,
MessageType = message.MessageType.Value,
MessageLevel = message.MessageLevel,
Content = message.Data ?? "No Data Found In This Message. This Might Be An Error.",
DisplayAttribute = "C=White" // still having it always white :)
});
} else if (message.Data.StartsWith("<?xml"))
{
// xml data needs to be parsed and put in the right format for response
ArrayOfKeyValuePairOfStringString arrayOfKVP = XmlUtil.DeserializeXml<ArrayOfKeyValuePairOfStringString>(message.Data);
string data = "";
List<KeyValuePairOfStringString> pairList = new List<KeyValuePairOfStringString>();
for(int i = 0; i < arrayOfKVP.KeyValuePairOfStringString.Length; i++)
{
pairList.Add(arrayOfKVP.KeyValuePairOfStringString[i]);
}
foreach(KeyValuePairOfStringString pair in pairList)
{
data = data + $"[[{pair.Key}]]=[[{pair.Value}]]";
}
clm.MessageBody = XmlUtil.SerializeXml(new MessageInfo
{
UserMessageQueueID = message.QueueID,
MessageID = message.Id,
MessageTypeID = (int?)message.MessageTypeID,
FromUserID = msgAuthor.Uid.ToString() ?? "NotFound",
MemberMessage = message.MemberMessage ?? "NoData",
NonMemberMessage = message.NonMemberMessage ?? "NoData",
Data = data
});
} else
{
clm.MessageBody = XmlUtil.SerializeXml(new MessageInfo
{
UserMessageQueueID = message.QueueID,
MessageID = message.Id,
MessageTypeID = (int?)message.MessageTypeID,
FromUserID = msgAuthor.Uid.ToString() ?? "NotFound",
MemberMessage = message.MemberMessage ?? "NoData",
NonMemberMessage = message.NonMemberMessage ?? "NoData",
Data = message.Data
});
}
// add clm to list
combinedListMessages.Add(clm);
// ensure all replies are included in response
foreach(var reply in message.Replies)
{
Viking? replyAuthor = ctx.Vikings.FirstOrDefault(e => e.Id == reply.VikingId) ?? new Viking();
CombinedListMessage clmReply = new CombinedListMessage
{
MessageType = (int)reply.MessageType,
MessageBody = XmlUtil.SerializeXml(new Schema.Message
{
MessageID = reply.Id,
ConversationID = reply.ConversationID ?? 0,
ReplyToMessageID = reply.ParentMessageId,
Creator = replyAuthor.Uid.ToString() ?? "Ghost",
CreateTime = reply.CreatedAt,
UpdateDate = reply.LastUpdatedAt,
MessageType = reply.MessageType.Value,
MessageLevel = reply.MessageLevel,
Content = reply.Data ?? "No Data Found In This Message. This Might Be An Error.",
DisplayAttribute = "C=White" // still having it always white :)
}),
MessageDate = reply.CreatedAt
};
combinedListMessages.Add(clmReply);
}
}
// save any changes made to db
ctx.SaveChanges();
// reverse list
combinedListMessages.Reverse();
// add list as array to response
response.CombinedListMessage = combinedListMessages.ToArray();
// return response
return response;
}
public ArrayOfMessageInfo ConstructUserMessageInfoArray(Viking viking, bool showOldMessages, bool showDeletedMessages)
{
// get execution UTC timestamp
DateTime now = DateTime.UtcNow;
// get all recent messages
List<Model.Message> messages = ctx.Messages.Where(e => e.ToVikingId == viking.Id)
.OrderBy(e => e.CreatedAt)
.OrderBy(e => e.QueueID)
.ToList();
List<MessageInfo> messageInfos = new List<MessageInfo>();
ArrayOfMessageInfo response = new ArrayOfMessageInfo();
foreach(var message in messages)
{
Viking? msgAuthor = ctx.Vikings.FirstOrDefault(e => e.Id == message.VikingId) ?? new Viking();
if(message.IsDeleted) { ctx.Messages.Remove(message); continue; }
if(DateTime.Compare(now, message.CreatedAt.AddMinutes(30)) > 0) { message.IsNew = false; continue; } // sometimes clients won't set IsNew flag when updating messages, so do not add messages more than 30 minutes old to response
if(!message.IsNew && !showOldMessages) continue;
messageInfos.Add(new MessageInfo
{
MessageID = message.Id,
UserMessageQueueID = message.QueueID,
FromUserID = msgAuthor.Uid.ToString() ?? "NotFound",
MessageTypeID = (int?)message.MessageTypeID,
Data = message.Data ?? "NoData",
MemberMessage = message.MemberMessage ?? "NoMessage",
NonMemberMessage = message.NonMemberMessage ?? "NoMessage"
});
}
// save any database changes
ctx.SaveChanges();
// add list as array to response
response.MessageInfo = messageInfos.ToArray();
// return response
return response;
}
}