diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..3ba2eab Binary files /dev/null and b/.DS_Store differ diff --git a/Runtime/.DS_Store b/Runtime/.DS_Store new file mode 100644 index 0000000..1ea6448 Binary files /dev/null and b/Runtime/.DS_Store differ diff --git a/Runtime/Models/Request.cs b/Runtime/Models/Request.cs index f50c697..d1d4d94 100644 --- a/Runtime/Models/Request.cs +++ b/Runtime/Models/Request.cs @@ -9,8 +9,7 @@ public class Request : EventArgs private string GameId { get; set; } [JsonProperty("2", NullValueHandling = NullValueHandling.Ignore)] private string Protocol { get; set; } [JsonProperty("3")] public int? ReceiverId { get; set; } - [JsonProperty("4")] - public string Method { get; set; } + [JsonProperty("4")] public string Method { get; set; } [JsonProperty("5", NullValueHandling = NullValueHandling.Ignore)] public string Payload { get; set; } [JsonProperty("6")] public int? SenderId { get; set; } diff --git a/Runtime/Services/Chat/Chat.cs b/Runtime/Services/Chat/Chat.cs deleted file mode 100644 index 984c70b..0000000 --- a/Runtime/Services/Chat/Chat.cs +++ /dev/null @@ -1,121 +0,0 @@ -//using adapters.repositories.table.services; -//using models.dto; -//using models.inputs; - -//namespace adapters.services.table.services -//{ - -// public partial class MessageType -// { -// public const string ChatSendPrivate = "chat:send"; -// public const string ChatSendGroup = "chat:group:send"; -// public const string ChatSubscribe = "chat:subscribe"; -// public const string ChatUnsubscribe = "chat:unsubscribe"; -// public const string ChatMessageEdit = "chat:message:edit"; -// public const string ChatMessageDelete = "chat:message:delete"; -// public const string ChatMessagePurge = "chat:message:purge"; -// public const string ChatMessageDeleteAll = "chat:group:delete"; -// } - -// public class ChatService: IChat -// { -// // dependencies -// private IChatRepository _repository; - -// public ChatService() -// { -// _repository = new ChatRepository(); -// // TODO: Realtime -// //DynamicPixels.Agent.OnMessageReceived += OnMessage; -// } - -// private void OnMessage(object source, Request packet) -// { -// switch (packet.Method) -// { -// case MessageType.ChatSendPrivate: -// Send(new SendParams{}); -// break; -// case MessageType.ChatSendGroup: -// Send(new SendParams{}); -// break; -// case MessageType.ChatSubscribe: -// Subscribe(new SubscribeParams{}); -// break; -// case MessageType.ChatUnsubscribe: -// Unsubscribe(new UnsubscribeParams{}); -// break; -// case MessageType.ChatMessageEdit: -// EditMessage(new EditMessageParams{}); -// break; -// case MessageType.ChatMessageDelete: -// DeleteMessage(new DeleteMessageParams{}); -// break; -// case MessageType.ChatMessagePurge: - -// break; -// case MessageType.ChatMessageDeleteAll: -// DeleteAllMessage(new DeleteAllMessageParams{}); -// break; -// } -// } - - -// // interactions -// public Task Send(T param) where T : SendParams -// { -// DynamicPixels.Agent.Send(new Request -// { -// Method = MessageType.ChatSendGroup, -// Payload = param.ToString(), -// }); - -// return Task.CompletedTask; -// } - -// public Task Subscribe(T param) where T : SubscribeParams -// { -// throw new System.NotImplementedException(); -// } - -// public Task Unsubscribe(T param) where T : UnsubscribeParams -// { -// throw new System.NotImplementedException(); -// } - -// public Task EditMessage(T param) where T : EditMessageParams -// { -// throw new System.NotImplementedException(); -// } - -// public Task DeleteMessage(T param) where T : DeleteMessageParams -// { -// throw new System.NotImplementedException(); -// } - -// public Task DeleteAllMessage(T param) where T : DeleteAllMessageParams -// { -// throw new System.NotImplementedException(); -// } - -// // https -// public async Task> GetSubscribedConversations(T param) where T : GetSubscribedConversationsParams -// { -// var conversations = await this._repository.GetSubscribedConversations(param); -// return conversations.List; -// } - -// public async Task> GetConversationMessages(T param) where T : GetConversationMessagesParams -// { -// var messages = await this._repository.GetConversationMessages(param); -// return messages.List; -// } - -// public async Task> GetConversationMembers(T param) where T : GetConversationMembersParams -// { -// var members = await this._repository.GetConversationMembers(param); -// return members.List; -// } - -// } -//} \ No newline at end of file diff --git a/Runtime/Services/Chat/ChatService.cs b/Runtime/Services/Chat/ChatService.cs new file mode 100644 index 0000000..aca97db --- /dev/null +++ b/Runtime/Services/Chat/ChatService.cs @@ -0,0 +1,184 @@ +//using adapters.repositories.table.services; +//using models.dto; +//using models.inputs; + +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using DynamicPixels.GameService.Models; +using DynamicPixels.GameService.Services.Chat; +using DynamicPixels.GameService.Services.Chat.Models; +using DynamicPixels.GameService.Services.Chat.Repositories; +using DynamicPixels.GameService.Utils.WebsocketClient; +using Newtonsoft.Json; +using MessageType = DynamicPixels.Services.Chat.MessageType; + +namespace DynamicPixels.GameService.Services.services +{ + public class ChatService: IChatService + { + + private readonly ISocketAgent _socketAgent; + private readonly IChatRepository _repository; + + public event EventHandler OnPrivateMessage; + public event EventHandler OnPublicMessage; + public event EventHandler OnSubscribe; + public event EventHandler OnUnsubscribe; + public event EventHandler OnEditMessage; + public event EventHandler OnDeleteMessage; + public event EventHandler OnDeleteAllMessage; + + public ChatService(ISocketAgent socketAgent) + { + _socketAgent = socketAgent; + _repository = new ChatRepository(); + _socketAgent.OnMessageReceived += OnMessage; + } + + private void OnMessage(object source, Request packet) + { + switch (packet.Method) + { + case MessageType.ChatSendPrivate: + var privateMsg = JsonConvert.DeserializeObject(packet.Payload); + OnPrivateMessage?.Invoke(this, privateMsg); + break; + case MessageType.ChatSendGroup: + var groupMsg = JsonConvert.DeserializeObject(packet.Payload); + OnPublicMessage?.Invoke(this, groupMsg); + break; + case MessageType.ChatSubscribe: + var conversation = JsonConvert.DeserializeObject(packet.Payload); + OnSubscribe?.Invoke(this, conversation); + break; + case MessageType.ChatUnsubscribe: + OnUnsubscribe?.Invoke(this, Int32.Parse(packet.Payload)); + break; + case MessageType.ChatMessageEdit: + var editedMsg = JsonConvert.DeserializeObject(packet.Payload); + OnEditMessage?.Invoke(this, editedMsg); + break; + case MessageType.ChatMessageDelete: + var deletedMsg = JsonConvert.DeserializeObject(packet.Payload); + OnDeleteMessage?.Invoke(this, deletedMsg); + break; + case MessageType.ChatMessageDeleteAll: + OnDeleteAllMessage?.Invoke(this, packet); + break; + } + } + + + // interactions + public Task Send(T param) where T : SendParams + { + _socketAgent.Send(new Request + { + Method = param.Type == ConversationType.Private ? MessageType.ChatSendPrivate: MessageType.ChatSendGroup, + ReceiverId = param.TargetUserId, + Payload = new Payload + { + TargetId = param.TargetUserId, + Message = param.Message + }.ToString(), + }); + + return Task.CompletedTask; + } + + public Task Subscribe(T param) where T : SubscribeParams + { + _socketAgent.Send(new Request + { + Method = MessageType.ChatSubscribe, + Payload = new Payload + { + TargetId = param.ConversationId, + Value = param.ConversationName, + }.ToString(), + }); + + return Task.CompletedTask; + } + + public Task Unsubscribe(T param) where T : UnsubscribeParams + { + _socketAgent.Send(new Request + { + Method = MessageType.ChatUnsubscribe, + Payload = new Payload + { + TargetId = param.ConversationId, + }.ToString(), + }); + + return Task.CompletedTask; + } + + public Task EditMessage(T param) where T : EditMessageParams + { + _socketAgent.Send(new Request + { + Method = MessageType.ChatMessageEdit, + Payload = new Payload + { + TargetId = param.ConversationId, + MessageId = param.MessageId, + Message = param.Message, + }.ToString(), + }); + + return Task.CompletedTask; + } + + public Task DeleteMessage(T param) where T : DeleteMessageParams + { + _socketAgent.Send(new Request + { + Method = MessageType.ChatMessageDelete, + Payload = new Payload { + TargetId = param.ConversationId, + MessageId = param.MessageId, + }.ToString(), + }); + + return Task.CompletedTask; + } + + public Task DeleteAllMessage(T param) where T : DeleteAllMessageParams + { + _socketAgent.Send(new Request + { + Method = MessageType.ChatMessageDeleteAll, + Payload = new Payload + { + TargetId = param.ConversationId, + SubTargetId = param.TargetUserId, + }.ToString(), + }); + + return Task.CompletedTask; + } + + // https + public async Task> GetSubscribedConversations(T param) where T : GetSubscribedConversationsParams + { + var conversations = await this._repository.GetSubscribedConversations(param); + return conversations.List; + } + + public async Task> GetConversationMessages(T param) where T : GetConversationMessagesParams + { + var messages = await this._repository.GetConversationMessages(param); + return messages.List; + } + + public async Task> GetConversationMembers(T param) where T : GetConversationMembersParams + { + var members = await this._repository.GetConversationMembers(param); + return members.List; + } + + } +} \ No newline at end of file diff --git a/Runtime/Services/Chat/IChat.cs b/Runtime/Services/Chat/IChatService.cs similarity index 96% rename from Runtime/Services/Chat/IChat.cs rename to Runtime/Services/Chat/IChatService.cs index 572325c..4c6945e 100644 --- a/Runtime/Services/Chat/IChat.cs +++ b/Runtime/Services/Chat/IChatService.cs @@ -5,7 +5,7 @@ namespace DynamicPixels.GameService.Services.Chat { - public interface IChat + public interface IChatService { public Task Send(T param) where T : SendParams; public Task Subscribe(T param) where T : SubscribeParams; diff --git a/Runtime/Services/Chat/MessageTypes.cs b/Runtime/Services/Chat/MessageTypes.cs new file mode 100644 index 0000000..b2fd1cd --- /dev/null +++ b/Runtime/Services/Chat/MessageTypes.cs @@ -0,0 +1,14 @@ +namespace DynamicPixels.Services.Chat +{ + public partial class MessageType + { + public const string ChatSendPrivate = "chat:send"; + public const string ChatSendGroup = "chat:group:send"; + public const string ChatSubscribe = "chat:subscribe"; + public const string ChatUnsubscribe = "chat:unsubscribe"; + public const string ChatMessageEdit = "chat:message:edit"; + public const string ChatMessageDelete = "chat:message:delete"; + // public const string ChatMessagePurge = "chat:message:purge"; + public const string ChatMessageDeleteAll = "chat:group:delete"; + } +} \ No newline at end of file diff --git a/Runtime/Services/Chat/Models/chat.cs b/Runtime/Services/Chat/Models/Chat.cs similarity index 100% rename from Runtime/Services/Chat/Models/chat.cs rename to Runtime/Services/Chat/Models/Chat.cs diff --git a/Runtime/Services/Chat/Models/Payload.cs b/Runtime/Services/Chat/Models/Payload.cs new file mode 100644 index 0000000..f5a1898 --- /dev/null +++ b/Runtime/Services/Chat/Models/Payload.cs @@ -0,0 +1,30 @@ +using System.Collections.Generic; +using DynamicPixels.GameService.Services.Chat.Repositories; +using Newtonsoft.Json; + +namespace DynamicPixels.GameService.Services.Chat.Models +{ + public class Payload + { + [JsonProperty("target_id")] public int TargetId { get; set; } + + [JsonProperty("sub_target_id")] public int SubTargetId { get; set; } + + [JsonProperty("message_id")] public int MessageId { get; set; } + + [JsonProperty("payload")] public Message? Message { get; set; } + + [JsonProperty("value")] public string Value { get; set; } = ""; + + [JsonProperty("skip")] public int Skip { get; set; } + + [JsonProperty("limit")] public int Limit { get; set; } + + [JsonProperty("properties")] public Dictionary? properties { get; set; } + + public override string ToString() + { + return JsonConvert.SerializeObject(this); + } + } +} \ No newline at end of file diff --git a/Runtime/Services/Table/Services.cs b/Runtime/Services/Table/Services.cs index 8699f20..15ac083 100644 --- a/Runtime/Services/Table/Services.cs +++ b/Runtime/Services/Table/Services.cs @@ -6,6 +6,7 @@ using DynamicPixels.GameService.Services.MultiPlayer.Match; using DynamicPixels.GameService.Services.MultiPlayer.Room; using DynamicPixels.GameService.Services.Party; +using DynamicPixels.GameService.Services.services; using DynamicPixels.GameService.Services.User; using DynamicPixels.GameService.Utils.WebsocketClient; @@ -18,7 +19,7 @@ public Services(ISocketAgent agent) { Leaderboard = new LeaderboardService(); Achievement = new AchievementService(); - //Chats = new ChatService(); + Chats = new ChatService(agent); Friendship = new FriendshipService(); Party = new PartyService(); Users = new UserService(); @@ -30,7 +31,7 @@ public Services(ISocketAgent agent) public ILeaderboard Leaderboard { get; private set; } public IAchievement Achievement { get; private set; } - public IChat Chats { get; private set; } + public IChatService Chats { get; private set; } public IFriendship Friendship { get; private set; } public IParty Party { get; private set; } public IUser Users { get; private set; } diff --git a/Runtime/models/BaseGetAllParams.cs b/Runtime/models/BaseGetAllParams.cs new file mode 100644 index 0000000..c742e60 --- /dev/null +++ b/Runtime/models/BaseGetAllParams.cs @@ -0,0 +1,8 @@ +namespace DynamicPixels.GameService.Models +{ + public abstract class BaseGetAllParams + { + public int Skip { get; set; } + public int Take { get; set; } + } +} \ No newline at end of file diff --git a/Runtime/models/Request.cs b/Runtime/models/Request.cs new file mode 100644 index 0000000..d1d4d94 --- /dev/null +++ b/Runtime/models/Request.cs @@ -0,0 +1,24 @@ +using System; +using Newtonsoft.Json; + +namespace DynamicPixels.GameService.Models +{ + public class Request : EventArgs + { + [JsonProperty("1", NullValueHandling = NullValueHandling.Ignore)] + private string GameId { get; set; } + [JsonProperty("2", NullValueHandling = NullValueHandling.Ignore)] private string Protocol { get; set; } + [JsonProperty("3")] public int? ReceiverId { get; set; } + [JsonProperty("4")] public string Method { get; set; } + [JsonProperty("5", NullValueHandling = NullValueHandling.Ignore)] public string Payload { get; set; } + [JsonProperty("6")] public int? SenderId { get; set; } + + public override string ToString() + { + return JsonConvert.SerializeObject(this, new JsonSerializerSettings + { + NullValueHandling = NullValueHandling.Ignore + }); + } + } +} \ No newline at end of file diff --git a/Runtime/models/inputs/Aggregation.cs b/Runtime/models/inputs/Aggregation.cs new file mode 100644 index 0000000..66964b6 --- /dev/null +++ b/Runtime/models/inputs/Aggregation.cs @@ -0,0 +1,64 @@ +using System.Collections.Generic; + +namespace DynamicPixels.GameService.Models.inputs +{ + public interface Aggregarion + { + // public Tuple> ToString(int index); + } + + public class Match : Aggregarion + { + private Query query; + public Match(Query query) + { + this.query = query; + } + } + + public class Skip : Aggregarion + { + private int skip; + public Skip(int skip) + { + this.skip = skip; + } + } + + public class Limit : Aggregarion + { + private int limit; + public Limit(int limit) + { + this.limit = limit; + } + } + + public class Select : Aggregarion + { + public Select(int select) + { + + } + } + + public class Sort : Aggregarion + { + private Dictionary sorts = new Dictionary(); + public Sort(Dictionary sorts) + { + this.sorts = sorts; + } + } + + public class Join : Aggregarion + { + private string tableName; + private Query condition; + public Join(string tableName, Query condition) + { + this.tableName = tableName; + this.condition = condition; + } + } +} \ No newline at end of file diff --git a/Runtime/models/inputs/Order.cs b/Runtime/models/inputs/Order.cs new file mode 100644 index 0000000..327a3c4 --- /dev/null +++ b/Runtime/models/inputs/Order.cs @@ -0,0 +1,9 @@ +namespace DynamicPixels.GameService.Models.inputs +{ + public enum Order + { + ASC, + DESC + } + +} \ No newline at end of file diff --git a/Runtime/models/inputs/Query.cs b/Runtime/models/inputs/Query.cs new file mode 100644 index 0000000..49d1ad9 --- /dev/null +++ b/Runtime/models/inputs/Query.cs @@ -0,0 +1,182 @@ +using System.Collections.Generic; +using Newtonsoft.Json; + +namespace DynamicPixels.GameService.Models.inputs +{ + public interface Query + { + public QueryParam ToQuery(); + } + + public class QueryParam + { + [JsonProperty("op")] + public string Op { get; set; } + [JsonProperty("field")] + public string? Field { get; set; } + [JsonProperty("value", NullValueHandling = NullValueHandling.Ignore)] public dynamic? Value { get; set; } + [JsonProperty("values", NullValueHandling = NullValueHandling.Ignore)] public dynamic[]? Values { get; set; } + [JsonProperty("list", NullValueHandling = NullValueHandling.Ignore)] public QueryParam[]? list { get; set; } + } + + public class JoinParams + { + [JsonProperty("table_name")] + public string TableName { get; set; } + [JsonProperty("local_field")] + public string localField { get; set; } + [JsonProperty("foreign_field")] + public string foreignField { get; set; } + } + + public class And : Query + { + private List _queries = new List(); + + public And(Query queryOne, params Query?[] queries) + { + _queries.Add(queryOne.ToQuery()); + foreach (var q in queries) + { + if (q != null) _queries.Add(q.ToQuery()); + } + } + + public QueryParam ToQuery() + { + return new QueryParam + { + Op = "AND", + list = _queries.ToArray(), // Convert List to Array + }; + } + } + + public class Or : Query + { + private List _queries = new List(); + + public Or(Query queryOne, params Query?[] queries) + { + _queries.Add(queryOne.ToQuery()); + foreach (var q in queries) + { + if (q != null) _queries.Add(q.ToQuery()); + } + } + + public QueryParam ToQuery() + { + return new QueryParam + { + Op = "OR", + list = _queries.ToArray(), // Convert List to Array + }; + } + } + + public class Eq : Query + { + private string Field { get; set; } + private dynamic Value { get; set; } + + public Eq(string field, dynamic value) + { + Field = field; + Value = value; + } + + public QueryParam ToQuery() + { + return new QueryParam + { + Op = "=", + Field = Field, + Value = Value + }; + } + } + + public class Neq : Query + { + public string Field { get; set; } + public dynamic Value { get; set; } + + public Neq(string field, dynamic value) + { + Field = field; + Value = value; + } + + public QueryParam ToQuery() + { + return new QueryParam + { + Op = "!=", + Field = Field, + Value = Value + }; + } + } + + public class Compare : Query + { + public string Field { get; set; } + public dynamic Value { get; set; } + public string Operator { get; set; } + + public QueryParam ToQuery() + { + return new QueryParam + { + Op = Operator, + Field = Field, + Value = Value + }; + } + } + + public class In : Query + { + public string Field { get; set; } + public dynamic[] Values { get; set; } + + public In(string field, dynamic[] values) + { + Field = field; + Values = values; + } + + public QueryParam ToQuery() + { + return new QueryParam + { + Op = "=", + Field = Field, + Values = Values + }; + } + } + + public class Nin : Query + { + public string Field; + public dynamic[] Values; + + public Nin(string field, dynamic[] values) + { + Field = field; + Values = values; + } + + public QueryParam ToQuery() + { + return new QueryParam + { + Op = "!=", + Field = Field, + Values = Values + }; + } + } +}