From 6b4d28b000483f3552a65468f26b2357de936624 Mon Sep 17 00:00:00 2001 From: oneRain Date: Tue, 17 Mar 2020 16:17:19 +0800 Subject: [PATCH] =?UTF-8?q?*=20LCIMConversation.cs:=20chore:=20=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E4=BF=AE=E6=94=B9=E6=88=90=E5=91=98=E8=A7=92=E8=89=B2?= =?UTF-8?q?=EF=BC=9B=E6=94=AF=E6=8C=81=E4=BF=AE=E6=94=B9=E6=B6=88=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * LCIMClient.cs: * LCApplication.cs: * LCIMPageResult.cs: * LCIMMessage.cs: * Program.cs: * LCIMOperationFailure.cs: * LCIMTextMessage.cs: * LCIMTypedMessage.cs: * LCIMBinaryMessage.cs: * LCHttpClient.cs: * LCIMPartiallySuccessResult.cs: * LCIMConversationMemberInfo.cs: --- Realtime/Conversation/LCIMConversation.cs | 179 +++++++++++++++--- .../LCIMConversationMemberInfo.cs | 35 +++- Realtime/LCIMClient.cs | 12 +- Realtime/LCIMOperationFailure.cs | 25 +++ Realtime/LCIMPageResult.cs | 13 ++ Realtime/LCIMPartiallySuccessResult.cs | 18 ++ Realtime/Message/LCIMBinaryMessage.cs | 14 +- Realtime/Message/LCIMMessage.cs | 7 + Realtime/Message/LCIMTextMessage.cs | 12 +- Realtime/Message/LCIMTypedMessage.cs | 8 + Storage/Internal/Http/LCHttpClient.cs | 6 +- Storage/LCApplication.cs | 2 +- Test/RealtimeConsole/Program.cs | 19 +- 13 files changed, 303 insertions(+), 47 deletions(-) create mode 100644 Realtime/LCIMOperationFailure.cs create mode 100644 Realtime/LCIMPageResult.cs create mode 100644 Realtime/LCIMPartiallySuccessResult.cs diff --git a/Realtime/Conversation/LCIMConversation.cs b/Realtime/Conversation/LCIMConversation.cs index 3d4aaad..fb92742 100644 --- a/Realtime/Conversation/LCIMConversation.cs +++ b/Realtime/Conversation/LCIMConversation.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Threading.Tasks; using System.Linq; using Newtonsoft.Json; +using Google.Protobuf; using LeanCloud.Realtime.Protocol; using LeanCloud.Storage.Internal.Codec; @@ -191,23 +192,6 @@ namespace LeanCloud.Realtime { return message; } - public async Task Recall(LCIMMessage message) { - if (message == null) { - throw new ArgumentNullException(nameof(message)); - } - PatchCommand patch = new PatchCommand(); - PatchItem item = new PatchItem { - Cid = Id, - Mid = message.Id, - Recall = true - }; - patch.Patches.Add(item); - GenericCommand request = client.NewCommand(CommandType.Patch, OpType.Modify); - request.PatchMessage = patch; - GenericCommand response = await client.client.SendRequest(request); - return null; - } - /// /// 静音 /// @@ -243,7 +227,7 @@ namespace LeanCloud.Realtime { /// /// /// - public async Task MuteMembers(IEnumerable clientIds) { + public async Task MuteMembers(IEnumerable clientIds) { if (clientIds == null || clientIds.Count() == 0) { throw new ArgumentNullException(nameof(clientIds)); } @@ -254,7 +238,7 @@ namespace LeanCloud.Realtime { GenericCommand request = client.NewCommand(CommandType.Conv, OpType.AddShutup); request.ConvMessage = conv; GenericCommand response = await client.client.SendRequest(request); - + return NewPartiallySuccessResult(response.ConvMessage.AllowedPids, response.ConvMessage.FailedPids); } /// @@ -262,7 +246,7 @@ namespace LeanCloud.Realtime { /// /// /// - public async Task UnmuteMembers(IEnumerable clientIds) { + public async Task UnmuteMembers(IEnumerable clientIds) { if (clientIds == null || clientIds.Count() == 0) { throw new ArgumentNullException(nameof(clientIds)); } @@ -273,6 +257,7 @@ namespace LeanCloud.Realtime { GenericCommand request = client.NewCommand(CommandType.Conv, OpType.Remove); request.ConvMessage = conv; GenericCommand response = await client.client.SendRequest(request); + return NewPartiallySuccessResult(response.ConvMessage.AllowedPids, response.ConvMessage.FailedPids); } /// @@ -280,28 +265,115 @@ namespace LeanCloud.Realtime { /// /// /// - public async Task BlockMembers(IEnumerable clientIds) { + public async Task BlockMembers(IEnumerable clientIds) { if (clientIds == null || clientIds.Count() == 0) { throw new ArgumentNullException(nameof(clientIds)); } BlacklistCommand blacklist = new BlacklistCommand { SrcCid = Id, - }; + blacklist.ToPids.AddRange(clientIds); GenericCommand request = client.NewCommand(CommandType.Blacklist, OpType.Block); request.BlacklistMessage = blacklist; - await client.client.SendRequest(request); + GenericCommand response = await client.client.SendRequest(request); + return NewPartiallySuccessResult(response.BlacklistMessage.AllowedPids, response.BlacklistMessage.FailedPids); } - public async Task UnblockMembers(IEnumerable clientIds) { - + public async Task UnblockMembers(IEnumerable clientIds) { + if (clientIds == null || clientIds.Count() == 0) { + throw new ArgumentNullException(nameof(clientIds)); + } + BlacklistCommand blacklist = new BlacklistCommand { + SrcCid = Id, + }; + blacklist.ToPids.AddRange(clientIds); + GenericCommand request = client.NewCommand(CommandType.Blacklist, OpType.Unblock); + request.BlacklistMessage = blacklist; + GenericCommand response = await client.client.SendRequest(request); + return NewPartiallySuccessResult(response.BlacklistMessage.AllowedPids, response.BlacklistMessage.FailedPids); } + /// + /// 撤回消息 + /// + /// + /// + public async Task Recall(LCIMMessage message) { + if (message == null) { + throw new ArgumentNullException(nameof(message)); + } + PatchCommand patch = new PatchCommand(); + PatchItem item = new PatchItem { + Cid = Id, + Mid = message.Id, + Recall = true + }; + patch.Patches.Add(item); + GenericCommand request = client.NewCommand(CommandType.Patch, OpType.Modify); + request.PatchMessage = patch; + GenericCommand response = await client.client.SendRequest(request); + return null; + } + + /// + /// 修改消息 + /// + /// + /// + /// public async Task Update(LCIMMessage oldMessage, LCIMMessage newMessage) { + if (oldMessage == null) { + throw new ArgumentNullException(nameof(oldMessage)); + } + if (newMessage == null) { + throw new ArgumentNullException(nameof(newMessage)); + } + PatchCommand patch = new PatchCommand(); + PatchItem item = new PatchItem { + Cid = Id, + Mid = oldMessage.Id, + Timestamp = oldMessage.DeliveredTimestamp, + Recall = false, + }; + if (newMessage.GetText() != null) { + item.Data = newMessage.GetText(); + } + if (newMessage.GetBytes() != null) { + item.BinaryMsg = ByteString.CopyFrom(newMessage.GetBytes()); + } + if (newMessage.MentionList != null) { + item.MentionPids.AddRange(newMessage.MentionList); + } + if (newMessage.MentionAll) { + item.MentionAll = newMessage.MentionAll; + } + patch.Patches.Add(item); + GenericCommand request = client.NewCommand(CommandType.Patch, OpType.Modify); + request.PatchMessage = patch; + GenericCommand response = await client.client.SendRequest(request); return null; } public async Task UpdateMemberRole(string memberId, string role) { + if (string.IsNullOrEmpty(memberId)) { + throw new ArgumentNullException(nameof(memberId)); + } + if (role != LCIMConversationMemberInfo.Manager && role != LCIMConversationMemberInfo.Member) { + throw new ArgumentException("role MUST be Manager Or Memebr"); + } + ConvCommand conv = new ConvCommand { + Cid = Id, + TargetClientId = memberId, + Info = new ConvMemberInfo { + Pid = memberId, + Role = role + } + }; + GenericCommand request = client.NewCommand(CommandType.Conv, OpType.MemberInfoUpdate); + request.ConvMessage = conv; + GenericCommand response = await client.client.SendRequest(request); + // TODO 同步 members + return this; } @@ -309,12 +381,65 @@ namespace LeanCloud.Realtime { if (string.IsNullOrEmpty(memberId)) { throw new ArgumentNullException(nameof(memberId)); } - + List members = await GetAllMemberInfo(); + foreach (LCIMConversationMemberInfo member in members) { + if (member.MemberId == memberId) { + return member; + } + } return null; } public async Task> GetAllMemberInfo() { - return null; + string path = "classes/_ConversationMemberInfo"; + Dictionary headers = new Dictionary { + { "X-LC-IM-Session-Token", client.SessionToken } + }; + Dictionary queryParams = new Dictionary { + { "client_id", client.ClientId }, + { "cid", Id } + }; + Dictionary response = await LCApplication.HttpClient.Get>(path, + headers: headers, queryParams: queryParams); + List results = response["results"] as List; + List memberList = new List(); + foreach (Dictionary item in results) { + LCIMConversationMemberInfo member = new LCIMConversationMemberInfo { + ConversationId = item["cid"] as string, + MemberId = item["clientId"] as string, + Role = item["role"] as string + }; + memberList.Add(member); + } + return memberList; + } + + public async Task QueryMutedMembers(int limit = 50, string next = null) { + ConvCommand conv = new ConvCommand { + Cid = Id, + Limit = limit, + Next = next + }; + GenericCommand request = client.NewCommand(CommandType.Conv, OpType.QueryShutup); + request.ConvMessage = conv; + GenericCommand response = await client.client.SendRequest(request); + return new LCIMPageResult { + Results = response.ConvMessage.M.ToList(), + Next = response.ConvMessage.Next + }; + } + + private LCIMPartiallySuccessResult NewPartiallySuccessResult(IEnumerable succesfulIds, IEnumerable errors) { + LCIMPartiallySuccessResult result = new LCIMPartiallySuccessResult { + SuccessfulClientIdList = succesfulIds.ToList() + }; + if (errors != null) { + result.FailureList = new List(); + foreach (ErrorCommand error in errors) { + result.FailureList.Add(new LCIMOperationFailure(error)); + } + } + return result; } internal void MergeFrom(ConvCommand conv) { diff --git a/Realtime/Conversation/LCIMConversationMemberInfo.cs b/Realtime/Conversation/LCIMConversationMemberInfo.cs index dfe5fec..5809dec 100644 --- a/Realtime/Conversation/LCIMConversationMemberInfo.cs +++ b/Realtime/Conversation/LCIMConversationMemberInfo.cs @@ -1,7 +1,20 @@ -using System; - -namespace LeanCloud.Realtime { +namespace LeanCloud.Realtime { public class LCIMConversationMemberInfo { + /// + /// 群主 + /// + public const string Owner = "Owner"; + + /// + /// 管理员 + /// + public const string Manager = "Manager"; + + /// + /// 成员 + /// + public const string Member = "Member"; + public string ConversationId { get; set; } @@ -10,12 +23,20 @@ namespace LeanCloud.Realtime { get; set; } - public bool IsOwner { - get; set; - } - public string Role { get; set; } + + public bool IsOwner { + get { + return Role == Owner; + } + } + + public bool IsManager { + get { + return Role == Manager; + } + } } } diff --git a/Realtime/LCIMClient.cs b/Realtime/LCIMClient.cs index 1bbaf35..5941e2e 100644 --- a/Realtime/LCIMClient.cs +++ b/Realtime/LCIMClient.cs @@ -17,6 +17,11 @@ namespace LeanCloud.Realtime { get; private set; } + // TODO 判断过期 + internal string SessionToken { + get; private set; + } + /// /// 当前用户被加入某个对话的黑名单 /// @@ -85,9 +90,10 @@ namespace LeanCloud.Realtime { }; await client.Connect(); // Open Session - GenericCommand command = NewCommand(CommandType.Session, OpType.Open); - command.SessionMessage = new SessionCommand(); - await client.SendRequest(command); + GenericCommand request = NewCommand(CommandType.Session, OpType.Open); + request.SessionMessage = new SessionCommand(); + GenericCommand response = await client.SendRequest(request); + SessionToken = response.SessionMessage.St; } /// diff --git a/Realtime/LCIMOperationFailure.cs b/Realtime/LCIMOperationFailure.cs new file mode 100644 index 0000000..68e7e19 --- /dev/null +++ b/Realtime/LCIMOperationFailure.cs @@ -0,0 +1,25 @@ +using System.Linq; +using System.Collections.Generic; +using LeanCloud.Realtime.Protocol; + +namespace LeanCloud.Realtime { + public class LCIMOperationFailure { + public int Code { + get; set; + } + + public string Reason { + get; set; + } + + public List MemberList { + get; set; + } + + public LCIMOperationFailure(ErrorCommand error) { + Code = error.Code; + Reason = error.Reason; + MemberList = error.Pids.ToList(); + } + } +} diff --git a/Realtime/LCIMPageResult.cs b/Realtime/LCIMPageResult.cs new file mode 100644 index 0000000..e2b131d --- /dev/null +++ b/Realtime/LCIMPageResult.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; + +namespace LeanCloud.Realtime { + public class LCIMPageResult { + public List Results { + get; internal set; + } + + public string Next { + get; internal set; + } + } +} diff --git a/Realtime/LCIMPartiallySuccessResult.cs b/Realtime/LCIMPartiallySuccessResult.cs new file mode 100644 index 0000000..d0d416c --- /dev/null +++ b/Realtime/LCIMPartiallySuccessResult.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using LeanCloud.Storage; + +namespace LeanCloud.Realtime { + public class LCIMPartiallySuccessResult { + public List SuccessfulClientIdList { + get; internal set; + } + + public List FailureList { + get; internal set; + } + + public LCIMPartiallySuccessResult() { + } + } +} diff --git a/Realtime/Message/LCIMBinaryMessage.cs b/Realtime/Message/LCIMBinaryMessage.cs index aef85de..2707661 100644 --- a/Realtime/Message/LCIMBinaryMessage.cs +++ b/Realtime/Message/LCIMBinaryMessage.cs @@ -2,14 +2,24 @@ namespace LeanCloud.Realtime { public class LCIMBinaryMessage : LCIMMessage { - private byte[] data; + public byte[] Data { + get; set; + } public LCIMBinaryMessage(byte[] data) { - this.data = data; + Data = data; } internal override string Serialize() { throw new NotImplementedException(); } + + internal override string GetText() { + return null; + } + + internal override byte[] GetBytes() { + return Data; + } } } diff --git a/Realtime/Message/LCIMMessage.cs b/Realtime/Message/LCIMMessage.cs index c9cf132..82531e8 100644 --- a/Realtime/Message/LCIMMessage.cs +++ b/Realtime/Message/LCIMMessage.cs @@ -63,10 +63,17 @@ namespace LeanCloud.Realtime { get; set; } + public bool MentionAll { + get; set; + } + public LCIMMessage() { } internal abstract string Serialize(); + + internal abstract string GetText(); + internal abstract byte[] GetBytes(); } } diff --git a/Realtime/Message/LCIMTextMessage.cs b/Realtime/Message/LCIMTextMessage.cs index 2f45c51..ba4b852 100644 --- a/Realtime/Message/LCIMTextMessage.cs +++ b/Realtime/Message/LCIMTextMessage.cs @@ -5,14 +5,20 @@ namespace LeanCloud.Realtime { public class LCIMTextMessage : LCIMTypedMessage { const int TextMessageType = -1; - private string text; + public string Text { + get; set; + } public LCIMTextMessage(string text) : base(TextMessageType) { - this.text = text; + Text = text; } internal override string Serialize() { - return text; + return Text; + } + + internal override string GetText() { + return Text; } } } diff --git a/Realtime/Message/LCIMTypedMessage.cs b/Realtime/Message/LCIMTypedMessage.cs index 680977b..047cd8e 100644 --- a/Realtime/Message/LCIMTypedMessage.cs +++ b/Realtime/Message/LCIMTypedMessage.cs @@ -11,5 +11,13 @@ namespace LeanCloud.Realtime { internal override string Serialize() { throw new NotImplementedException(); } + + internal override string GetText() { + return null; + } + + internal override byte[] GetBytes() { + return null; + } } } diff --git a/Storage/Internal/Http/LCHttpClient.cs b/Storage/Internal/Http/LCHttpClient.cs index 36d0477..83fb444 100644 --- a/Storage/Internal/Http/LCHttpClient.cs +++ b/Storage/Internal/Http/LCHttpClient.cs @@ -11,7 +11,7 @@ using Newtonsoft.Json; using LeanCloud.Common; namespace LeanCloud.Storage.Internal.Http { - internal class LCHttpClient { + public class LCHttpClient { private readonly string appId; readonly string appKey; @@ -26,7 +26,7 @@ namespace LeanCloud.Storage.Internal.Http { readonly MD5 md5; - internal LCHttpClient(string appId, string appKey, string server, string sdkVersion, string apiVersion) { + public LCHttpClient(string appId, string appKey, string server, string sdkVersion, string apiVersion) { this.appId = appId; this.appKey = appKey; this.server = server; @@ -42,7 +42,7 @@ namespace LeanCloud.Storage.Internal.Http { md5 = MD5.Create(); } - internal async Task Get(string path, + public async Task Get(string path, Dictionary headers = null, Dictionary queryParams = null) { string url = await BuildUrl(path, queryParams); diff --git a/Storage/LCApplication.cs b/Storage/LCApplication.cs index 99cad60..db9c915 100644 --- a/Storage/LCApplication.cs +++ b/Storage/LCApplication.cs @@ -30,7 +30,7 @@ namespace LeanCloud { get; private set; } - internal static LCHttpClient HttpClient { + public static LCHttpClient HttpClient { get; private set; } diff --git a/Test/RealtimeConsole/Program.cs b/Test/RealtimeConsole/Program.cs index 3e7400a..9122cf9 100644 --- a/Test/RealtimeConsole/Program.cs +++ b/Test/RealtimeConsole/Program.cs @@ -54,10 +54,27 @@ namespace RealtimeConsole { List memberIdList = new List { "world", "code" }; string name = Guid.NewGuid().ToString(); - LCIMConversation conversation = await client.CreateConversation(memberIdList, name: name, unique: false); + LCIMConversation conversation = await client.CreateConversation(memberIdList, name: name, unique: true); LCIMTextMessage textMessage = new LCIMTextMessage("hello, world"); await conversation.Send(textMessage); + + await Task.Delay(3000); + + LCIMTextMessage newMessage = new LCIMTextMessage("hello, code"); + await conversation.Update(textMessage, newMessage); + + //// 设置成员的角色 + //await conversation.UpdateMemberRole("world", LCIMConversationMemberInfo.Manager); + + //List members = await conversation.GetAllMemberInfo(); + + //foreach (LCIMConversationMemberInfo member in members) { + // Console.WriteLine(member.MemberId); + //} + + //LCIMTextMessage textMessage = new LCIMTextMessage("hello, world"); + //await conversation.Send(textMessage); } } }