forked from SoDOff-Project/sodoff
implement `MessagingService
`
add additional messaging schemas
This commit is contained in:
parent
1ca53d580f
commit
c53b6b9348
@ -41,6 +41,7 @@ builder.Services.AddScoped<GameDataService>();
|
|||||||
builder.Services.AddScoped<ProfileService>();
|
builder.Services.AddScoped<ProfileService>();
|
||||||
builder.Services.AddScoped<NeighborhoodService>();
|
builder.Services.AddScoped<NeighborhoodService>();
|
||||||
builder.Services.AddScoped<ModerationService>();
|
builder.Services.AddScoped<ModerationService>();
|
||||||
|
builder.Services.AddScoped<MessagingService>();
|
||||||
|
|
||||||
bool assetServer = builder.Configuration.GetSection("AssetServer").GetValue<bool>("Enabled");
|
bool assetServer = builder.Configuration.GetSection("AssetServer").GetValue<bool>("Enabled");
|
||||||
string assetIP = builder.Configuration.GetSection("AssetServer").GetValue<string>("ListenIP");
|
string assetIP = builder.Configuration.GetSection("AssetServer").GetValue<string>("ListenIP");
|
||||||
|
12
src/Schema/ArrayOfCombinedListMessage.cs
Normal file
12
src/Schema/ArrayOfCombinedListMessage.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
|
namespace sodoff.Schema
|
||||||
|
{
|
||||||
|
[XmlRoot(ElementName = "ArrayOfCombinedListMessage")]
|
||||||
|
[Serializable]
|
||||||
|
public class ArrayOfCombinedListMessage
|
||||||
|
{
|
||||||
|
[XmlElement("CombinedListMessage")]
|
||||||
|
public CombinedListMessage[] CombinedListMessage;
|
||||||
|
}
|
||||||
|
}
|
11
src/Schema/ArrayOfKeyValuePairOfStringString.cs
Normal file
11
src/Schema/ArrayOfKeyValuePairOfStringString.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
|
namespace sodoff.Schema
|
||||||
|
{
|
||||||
|
[XmlRoot(ElementName = "ArrayOfKeyValuePairOfStringString")]
|
||||||
|
public class ArrayOfKeyValuePairOfStringString
|
||||||
|
{
|
||||||
|
[XmlElement(ElementName = "KeyValuePairOfStringString")]
|
||||||
|
public KeyValuePairOfStringString[]? KeyValuePairOfStringString { get; set; }
|
||||||
|
}
|
||||||
|
}
|
17
src/Schema/CombinedListMessage.cs
Normal file
17
src/Schema/CombinedListMessage.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
|
namespace sodoff.Schema
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
public class CombinedListMessage
|
||||||
|
{
|
||||||
|
[XmlElement(ElementName = "MessageType")]
|
||||||
|
public int MessageType;
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "MessageDate")]
|
||||||
|
public DateTime MessageDate;
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "Body", IsNullable = true)]
|
||||||
|
public string MessageBody;
|
||||||
|
}
|
||||||
|
}
|
13
src/Schema/KeyValuePairOfStringString.cs
Normal file
13
src/Schema/KeyValuePairOfStringString.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
|
namespace sodoff.Schema
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
public class KeyValuePairOfStringString
|
||||||
|
{
|
||||||
|
[XmlElement(ElementName = "Key")]
|
||||||
|
public string? Key { get; set; }
|
||||||
|
[XmlElement(ElementName = "Value")]
|
||||||
|
public string? Value { get; set; }
|
||||||
|
}
|
||||||
|
}
|
39
src/Schema/Message.cs
Normal file
39
src/Schema/Message.cs
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
|
namespace sodoff.Schema
|
||||||
|
{
|
||||||
|
[XmlRoot(ElementName = "Message")]
|
||||||
|
[Serializable]
|
||||||
|
public class Message
|
||||||
|
{
|
||||||
|
[XmlElement(ElementName = "MessageID")]
|
||||||
|
public int? MessageID;
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "Creator")]
|
||||||
|
public string Creator;
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "MessageLevel")]
|
||||||
|
public MessageLevel MessageLevel;
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "MessageType")]
|
||||||
|
public MessageType MessageType;
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "Content", IsNullable = true)]
|
||||||
|
public string? Content;
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "ReplyToMessageID", IsNullable = true)]
|
||||||
|
public int? ReplyToMessageID;
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "CreateTime")]
|
||||||
|
public DateTime CreateTime;
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "UpdateDate", IsNullable = true)]
|
||||||
|
public DateTime? UpdateDate;
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "ConversationID")]
|
||||||
|
public int ConversationID;
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "DisplayAttribute", IsNullable = true)]
|
||||||
|
public string? DisplayAttribute;
|
||||||
|
}
|
||||||
|
}
|
237
src/Services/MessagingService.cs
Normal file
237
src/Services/MessagingService.cs
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
using System;
|
||||||
|
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, 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
|
||||||
|
};
|
||||||
|
|
||||||
|
if (isReply)
|
||||||
|
{
|
||||||
|
// 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;
|
||||||
|
} 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? UpdateMessage(int id, bool isNew, bool IsDeleted)
|
||||||
|
{
|
||||||
|
// get execution UTC timestamp
|
||||||
|
DateTime now = DateTime.UtcNow;
|
||||||
|
|
||||||
|
// find message
|
||||||
|
Model.Message? message = ctx.Messages.FirstOrDefault(e => e.Id == id);
|
||||||
|
|
||||||
|
if (message != null)
|
||||||
|
{
|
||||||
|
// set params (TODO - figure out what else the clients update in messages)
|
||||||
|
message.IsNew = isNew;
|
||||||
|
message.IsDeleted = IsDeleted;
|
||||||
|
message.LastUpdatedAt = now;
|
||||||
|
|
||||||
|
return message;
|
||||||
|
} else return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayOfCombinedListMessage ConstructCombinedMessageArray(Viking viking)
|
||||||
|
{
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// save any changes made to db
|
||||||
|
ctx.SaveChanges();
|
||||||
|
|
||||||
|
// sort messages by newest first
|
||||||
|
combinedListMessages = combinedListMessages.OrderBy(e => e.MessageDate).ToList();
|
||||||
|
|
||||||
|
// 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>(0);
|
||||||
|
ArrayOfMessageInfo response = new ArrayOfMessageInfo();
|
||||||
|
|
||||||
|
foreach(var message in messages)
|
||||||
|
{
|
||||||
|
Viking? msgAuthor = ctx.Vikings.FirstOrDefault(e => e.Id == message.VikingId) ?? new Viking();
|
||||||
|
|
||||||
|
if(!showOldMessages && message.IsNew && DateTime.Compare(message.CreatedAt, now.AddMinutes(30)) > 0 || message.IsDeleted) 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"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// add list as array to response
|
||||||
|
response.MessageInfo = messageInfos.ToArray();
|
||||||
|
|
||||||
|
// return response
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user