diff --git a/AppRouter/AppRouter/AppRouter.csproj b/AppRouter/AppRouter/AppRouter.csproj deleted file mode 100644 index 722603d..0000000 --- a/AppRouter/AppRouter/AppRouter.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - - netstandard2.0 - 0.1.0 - - - - - - - - - - diff --git a/Common/AppRouter/AppRouter.cs b/Common/AppRouter/LCAppRouter.cs similarity index 69% rename from Common/AppRouter/AppRouter.cs rename to Common/AppRouter/LCAppRouter.cs index a46ed81..d7a0699 100644 --- a/Common/AppRouter/AppRouter.cs +++ b/Common/AppRouter/LCAppRouter.cs @@ -5,14 +5,14 @@ using System.Collections.Generic; using Newtonsoft.Json; namespace LeanCloud.Common { - public class AppRouter { + public class LCAppRouter { private readonly string appId; private readonly string server; - private AppServer appServer; + private LCAppServer appServer; - public AppRouter(string appId, string server) { + public LCAppRouter(string appId, string server) { if (!IsInternalApp(appId) && string.IsNullOrEmpty(server)) { // 国内节点必须配置自定义域名 throw new Exception("Please init with your server url."); @@ -26,36 +26,49 @@ namespace LeanCloud.Common { if (!string.IsNullOrEmpty(server)) { return server; } + LCAppServer appServ = await FetchAppServer(); + return appServ.ApiServer; + } + + public async Task GetRealtimeServer() { + if (!string.IsNullOrEmpty(server)) { + return server; + } + LCAppServer appServ = await FetchAppServer(); + return appServ.PushServer; + } + + async Task FetchAppServer() { // 判断节点地区 if (!IsInternalApp(appId)) { // 国内节点必须配置自定义域名 throw new Exception("Please init with your server url."); } // 向 App Router 请求地址 - if (appServer == null || appServer.IsExpired) { + if (appServer == null || !appServer.IsValid) { try { HttpRequestMessage request = new HttpRequestMessage { RequestUri = new Uri($"https://app-router.com/2/route?appId={appId}"), Method = HttpMethod.Get }; HttpClient client = new HttpClient(); - HttpUtils.PrintRequest(client, request); + LCHttpUtils.PrintRequest(client, request); HttpResponseMessage response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead); request.Dispose(); string resultString = await response.Content.ReadAsStringAsync(); response.Dispose(); - HttpUtils.PrintResponse(response, resultString); + LCHttpUtils.PrintResponse(response, resultString); Dictionary data = JsonConvert.DeserializeObject>(resultString); - appServer = new AppServer(data); + appServer = new LCAppServer(data); } catch (Exception e) { - Logger.Error(e.Message); + LCLogger.Error(e); // 拉取服务地址失败后,使用国际节点的默认服务地址 - appServer = AppServer.GetInternalFallbackAppServer(appId); + appServer = LCAppServer.GetInternalFallbackAppServer(appId); } } - return appServer.ApiServer; + return appServer; } private static bool IsInternalApp(string appId) { diff --git a/Common/AppRouter/AppServer.cs b/Common/AppRouter/LCAppServer.cs similarity index 80% rename from Common/AppRouter/AppServer.cs rename to Common/AppRouter/LCAppServer.cs index 0ae29ae..7f4e3ec 100644 --- a/Common/AppRouter/AppServer.cs +++ b/Common/AppRouter/LCAppServer.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; namespace LeanCloud.Common { - public class AppServer { + public class LCAppServer { public string ApiServer { get; private set; } @@ -19,9 +19,9 @@ namespace LeanCloud.Common { get; private set; } - public bool IsExpired { + public bool IsValid { get { - return ttl != -1 && DateTime.Now > expiredAt; + return ttl != -1 || DateTime.Now < expiredAt; } } @@ -29,7 +29,7 @@ namespace LeanCloud.Common { private readonly int ttl; - public AppServer(Dictionary data) { + public LCAppServer(Dictionary data) { ApiServer = GetUrlWithScheme(data["api_server"] as string); PushServer = GetUrlWithScheme(data["push_server"] as string); EngineServer = GetUrlWithScheme(data["engine_server"] as string); @@ -41,9 +41,9 @@ namespace LeanCloud.Common { return url.StartsWith("https://") ? url : $"https://{url}"; } - internal static AppServer GetInternalFallbackAppServer(string appId) { + internal static LCAppServer GetInternalFallbackAppServer(string appId) { string prefix = appId.Substring(0, 8).ToLower(); - return new AppServer(new Dictionary { + return new LCAppServer(new Dictionary { { "api_server", $"https://{prefix}.api.lncldglobal.com" }, { "push_server", $"https://{prefix}.engine.lncldglobal.com" }, { "engine_server", $"https://{prefix}.push.lncldglobal.com" }, diff --git a/Common/Http/HttpUtils.cs b/Common/Http/LCHttpUtils.cs similarity index 93% rename from Common/Http/HttpUtils.cs rename to Common/Http/LCHttpUtils.cs index 7edaa6e..40fd13f 100644 --- a/Common/Http/HttpUtils.cs +++ b/Common/Http/LCHttpUtils.cs @@ -3,7 +3,7 @@ using System.Text; using System.Net.Http; namespace LeanCloud.Common { - public static class HttpUtils { + public static class LCHttpUtils { public static void PrintRequest(HttpClient client, HttpRequestMessage request, string content = null) { if (client == null) { return; @@ -31,7 +31,7 @@ namespace LeanCloud.Common { sb.AppendLine($"Content: {content}"); } sb.AppendLine("=== HTTP Request End ==="); - Logger.Debug(sb.ToString()); + LCLogger.Debug(sb.ToString()); } public static void PrintResponse(HttpResponseMessage response, string content = null) { @@ -43,7 +43,7 @@ namespace LeanCloud.Common { sb.AppendLine($"Content: {content}"); } sb.AppendLine("=== HTTP Response End ==="); - Logger.Debug(sb.ToString()); + LCLogger.Debug(sb.ToString()); } } } diff --git a/Common/Json/JsonExtensions.cs b/Common/Json/LCJsonUtils.cs similarity index 96% rename from Common/Json/JsonExtensions.cs rename to Common/Json/LCJsonUtils.cs index d0a131b..25ec9fd 100644 --- a/Common/Json/JsonExtensions.cs +++ b/Common/Json/LCJsonUtils.cs @@ -5,7 +5,7 @@ namespace LeanCloud.Common { /// /// 为 Json 解析提供异步接口 /// - public static class JsonUtils { + public static class LCJsonUtils { public static async Task SerializeObjectAsync(object obj) { string str = null; await Task.Run(() => { diff --git a/Common/Log/LogLevel.cs b/Common/Log/LCLogLevel.cs similarity index 84% rename from Common/Log/LogLevel.cs rename to Common/Log/LCLogLevel.cs index 5d9344c..f43aaf5 100644 --- a/Common/Log/LogLevel.cs +++ b/Common/Log/LCLogLevel.cs @@ -1,8 +1,8 @@ -namespace LeanCloud.Common { +namespace LeanCloud { /// /// 日志级别 /// - public enum LogLevel { + public enum LCLogLevel { /// /// 调试级别 /// diff --git a/Common/Log/LCLogger.cs b/Common/Log/LCLogger.cs new file mode 100644 index 0000000..1ffbcac --- /dev/null +++ b/Common/Log/LCLogger.cs @@ -0,0 +1,51 @@ +using System; +using System.Text; + +namespace LeanCloud { + /// + /// 日志类 + /// + public static class LCLogger { + /// + /// 日志回调接口,方便开发者调试 + /// + /// The log delegate. + public static Action LogDelegate { + get; set; + } + + public static void Debug(string log) { + LogDelegate?.Invoke(LCLogLevel.Debug, log); + } + + public static void Debug(string format, params object[] args) { + LogDelegate?.Invoke(LCLogLevel.Debug, string.Format(format, args)); + } + + public static void Warn(string log) { + LogDelegate?.Invoke(LCLogLevel.Warn, log); + } + + public static void Warn(string format, params object[] args) { + LogDelegate?.Invoke(LCLogLevel.Warn, string.Format(format, args)); + } + + public static void Error(string log) { + LogDelegate?.Invoke(LCLogLevel.Error, log); + } + + public static void Error(string format, params object[] args) { + LogDelegate?.Invoke(LCLogLevel.Error, string.Format(format, args)); + } + + public static void Error(Exception e) { + StringBuilder sb = new StringBuilder(); + sb.Append(e.GetType()); + sb.Append("\n"); + sb.Append(e.Message); + sb.Append("\n"); + sb.Append(e.StackTrace); + Error(sb.ToString()); + } + } +} diff --git a/Common/Log/Logger.cs b/Common/Log/Logger.cs deleted file mode 100644 index 4e499d5..0000000 --- a/Common/Log/Logger.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; - -namespace LeanCloud.Common { - /// - /// 日志类 - /// - public static class Logger { - /// - /// 日志回调接口,方便开发者调试 - /// - /// The log delegate. - public static Action LogDelegate { - get; set; - } - - public static void Debug(string log) { - LogDelegate?.Invoke(LogLevel.Debug, log); - } - - public static void Debug(string format, params object[] args) { - LogDelegate?.Invoke(LogLevel.Debug, string.Format(format, args)); - } - - public static void Warn(string log) { - LogDelegate?.Invoke(LogLevel.Warn, log); - } - - public static void Warn(string format, params object[] args) { - LogDelegate?.Invoke(LogLevel.Warn, string.Format(format, args)); - } - - public static void Error(string log) { - LogDelegate?.Invoke(LogLevel.Error, log); - } - - public static void Error(string format, params object[] args) { - LogDelegate?.Invoke(LogLevel.Error, string.Format(format, args)); - } - } -} diff --git a/Common/Task/TaskExtensions.cs b/Common/Task/LCTaskExtensions.cs similarity index 99% rename from Common/Task/TaskExtensions.cs rename to Common/Task/LCTaskExtensions.cs index 2137ec5..bd0b0cb 100644 --- a/Common/Task/TaskExtensions.cs +++ b/Common/Task/LCTaskExtensions.cs @@ -10,7 +10,7 @@ namespace LeanCloud.Common { /// /// Provides helper methods that allow us to use terser code elsewhere. /// - public static class TaskExtensions { + public static class LCTaskExtensions { /// /// Ensures a task (even null) is awaitable. /// diff --git a/Common/Task/SingleThreadSynchronizationContext.cs b/Common/Task/SingleThreadSynchronizationContext.cs new file mode 100644 index 0000000..cd08e62 --- /dev/null +++ b/Common/Task/SingleThreadSynchronizationContext.cs @@ -0,0 +1,43 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using System.Collections.Concurrent; +using System.Collections.Generic; + +namespace LeanCloud.Common { + /// + /// 单线程环境,用于控制台应用 await 返回 + /// + public class SingleThreadSynchronizationContext : SynchronizationContext { + private readonly BlockingCollection> queue = new BlockingCollection>(); + + public override void Post(SendOrPostCallback d, object state) { + queue.Add(new KeyValuePair(d, state)); + } + + public void RunOnCurrentThread() { + while (queue.TryTake(out KeyValuePair workItem, Timeout.Infinite)) { + workItem.Key(workItem.Value); + } + } + + public void Complete() { + queue.CompleteAdding(); + } + + public static void Run(Func func) { + SynchronizationContext prevContext = Current; + try { + SingleThreadSynchronizationContext syncContext = new SingleThreadSynchronizationContext(); + SetSynchronizationContext(syncContext); + + Task t = func(); + syncContext.RunOnCurrentThread(); + + t.GetAwaiter().GetResult(); + } finally { + SetSynchronizationContext(prevContext); + } + } + } +} diff --git a/RTM/RTM.PCL/Properties/AssemblyInfo.cs b/RTM/RTM.PCL/Properties/AssemblyInfo.cs deleted file mode 100644 index 669b160..0000000 --- a/RTM/RTM.PCL/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; - -// Information about this assembly is defined by the following attributes. -// Change them to the values specific to your project. - -[assembly: AssemblyTitle("RTM.PCL")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("")] -[assembly: AssemblyCopyright("${AuthorCopyright}")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". -// The form "{Major}.{Minor}.*" will automatically update the build and revision, -// and "{Major}.{Minor}.{Build}.*" will update just the revision. - -[assembly: AssemblyVersion("1.0.*")] - -// The following attributes are used to specify the signing key for the assembly, -// if desired. See the Mono documentation for more information about signing. - -//[assembly: AssemblyDelaySign(false)] -//[assembly: AssemblyKeyFile("")] diff --git a/RTM/RTM.PCL/RTM.PCL.csproj b/RTM/RTM.PCL/RTM.PCL.csproj deleted file mode 100644 index a67701e..0000000 --- a/RTM/RTM.PCL/RTM.PCL.csproj +++ /dev/null @@ -1,210 +0,0 @@ - - - - Debug - AnyCPU - {92B2B40E-A3CD-4672-AC84-2E894E1A6CE5} - {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - Library - RTM.PCL - RTM.PCL - v4.5 - Profile111 - 0.1.0 - - - true - full - false - bin\Debug - DEBUG; - prompt - 4 - - - true - bin\Release - prompt - 4 - - - - - Internal\AVIMCorePlugins.cs - - - Internal\IAVIMPlatformHooks.cs - - - Internal\Command\AVIMCommand.cs - - - Internal\Command\AVIMCommandRunner.cs - - - Internal\Command\AckCommand.cs - - - Internal\Command\ConversationCommand.cs - - - Internal\Command\IAVIMCommandRunner.cs - - - Internal\Command\MessageCommand.cs - - - Internal\Command\PatchCommand.cs - - - Internal\Command\ReadCommand.cs - - - Internal\Command\SessionCommand.cs - - - Internal\DataEngine\Controller\DateTimeEngine.cs - - - Internal\DataEngine\Controller\DictionaryEngine.cs - - - Internal\DataEngine\Controller\StringEngine.cs - - - Internal\Message\Subclassing\FreeStyleMessageClassInfo.cs - - - Internal\Message\Subclassing\FreeStyleMessageClassingController.cs - - - Internal\Message\Subclassing\IFreeStyleMessageClassingController.cs - - - Internal\Protocol\AVIMProtocol.cs - - - Internal\Router\AVRouterController.cs - - - Internal\Router\IAVRouterController.cs - - - Internal\Router\State\RouterState.cs - - - Internal\Timer\IAVTimer.cs - - - Internal\Timer\Portable\AVTimer.Portable.cs - - - Internal\WebSocket\IWebSocketClient.cs - - - Internal\WebSocket\Portable\DefaultWebSocketClient.Portable.cs - - - Public\AVIMAudioMessage.cs - - - Public\AVIMBinaryMessage.cs - - - Public\AVIMClient.cs - - - Public\AVIMConversation.cs - - - Public\AVIMConversationQuery.cs - - - Public\AVIMEnumerator.cs - - - Public\AVIMEventArgs.cs - - - Public\AVIMException.cs - - - Public\AVIMImageMessage.cs - - - Public\AVIMMessage.cs - - - Public\AVIMMessageClassNameAttribute.cs - - - Public\AVIMMessageFieldNameAttribute.cs - - - Public\AVIMMessageListener.cs - - - Public\AVIMNotice.cs - - - Public\AVIMRecalledMessage.cs - - - Public\AVIMSignature.cs - - - Public\AVIMTemporaryConversation.cs - - - Public\AVIMTextMessage.cs - - - Public\AVIMTypedMessage.cs - - - Public\AVIMTypedMessageTypeIntAttribute.cs - - - Public\AVRealtime.cs - - - Public\IAVIMListener.cs - - - Public\IAVIMMessage.cs - - - Public\ICacheEngine.cs - - - Public\ISignatureFactory.cs - - - Public\Listener\AVIMConversationListener.cs - - - Public\Listener\ConversationUnreadListener.cs - - - Public\Listener\GoAwayListener.cs - - - Public\Listener\MessagePatchListener.cs - - - Public\Listener\OfflineMessageListener.cs - - - Public\Listener\SessionListener.cs - - - - - - - - ..\..\packages\Websockets.Pcl.1.1.9\lib\portable-net45+win+wpa81+wp80+MonoAndroid10+xamarinios10\WebSockets.PCL.dll - - - - \ No newline at end of file diff --git a/RTM/RTM.PCL/packages.config b/RTM/RTM.PCL/packages.config deleted file mode 100644 index 105fd5f..0000000 --- a/RTM/RTM.PCL/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/RTM/RTM.Test/RTM.Test.csproj b/RTM/RTM.Test/RTM.Test.csproj deleted file mode 100644 index 66eada9..0000000 --- a/RTM/RTM.Test/RTM.Test.csproj +++ /dev/null @@ -1,41 +0,0 @@ - - - - Debug - AnyCPU - {A1BBD0B5-41C6-4579-B9A3-5EF778BE7F95} - Library - RTM.Test - RTM.Test - v4.7 - 0.1.0 - - - true - full - false - bin\Debug - DEBUG; - prompt - 4 - - - true - bin\Release - prompt - 4 - - - - - ..\..\packages\NUnit.2.6.4\lib\nunit.framework.dll - - - - - - - - - - \ No newline at end of file diff --git a/RTM/RTM.Test/Test.cs b/RTM/RTM.Test/Test.cs deleted file mode 100644 index 4f8a269..0000000 --- a/RTM/RTM.Test/Test.cs +++ /dev/null @@ -1,10 +0,0 @@ -using NUnit.Framework; -using System; -namespace RTM.Test { - [TestFixture()] - public class Test { - [Test()] - public void TestCase() { - } - } -} diff --git a/RTM/RTM.Test/packages.config b/RTM/RTM.Test/packages.config deleted file mode 100644 index bbb222f..0000000 --- a/RTM/RTM.Test/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/RTM/RTM.Unity/Properties/AssemblyInfo.cs b/RTM/RTM.Unity/Properties/AssemblyInfo.cs deleted file mode 100644 index 5485e9a..0000000 --- a/RTM/RTM.Unity/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; - -// Information about this assembly is defined by the following attributes. -// Change them to the values specific to your project. - -[assembly: AssemblyTitle("RTM.Unity")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("")] -[assembly: AssemblyCopyright("${AuthorCopyright}")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". -// The form "{Major}.{Minor}.*" will automatically update the build and revision, -// and "{Major}.{Minor}.{Build}.*" will update just the revision. - -[assembly: AssemblyVersion("1.0.*")] - -// The following attributes are used to specify the signing key for the assembly, -// if desired. See the Mono documentation for more information about signing. - -//[assembly: AssemblyDelaySign(false)] -//[assembly: AssemblyKeyFile("")] diff --git a/RTM/RTM.Unity/RTM.Unity.csproj b/RTM/RTM.Unity/RTM.Unity.csproj deleted file mode 100644 index 2d18b38..0000000 --- a/RTM/RTM.Unity/RTM.Unity.csproj +++ /dev/null @@ -1,219 +0,0 @@ - - - - Debug - AnyCPU - {1E608FCD-9039-4FF7-8EE7-BA8B00E15D1C} - Library - RTM.Unity - RTM.Unity - v4.7 - 0.1.0 - - - true - full - false - bin\Debug - DEBUG; - prompt - 4 - false - - - true - bin\Release - prompt - 4 - false - - - - - ..\..\Libs\UnityEngine.dll - - - ..\..\Libs\websocket-sharp.dll - - - - - - Internal\AVIMCorePlugins.cs - - - Internal\IAVIMPlatformHooks.cs - - - Internal\Command\AVIMCommand.cs - - - Internal\Command\AVIMCommandRunner.cs - - - Internal\Command\AckCommand.cs - - - Internal\Command\ConversationCommand.cs - - - Internal\Command\IAVIMCommandRunner.cs - - - Internal\Command\MessageCommand.cs - - - Internal\Command\PatchCommand.cs - - - Internal\Command\ReadCommand.cs - - - Internal\Command\SessionCommand.cs - - - Internal\DataEngine\Controller\DateTimeEngine.cs - - - Internal\DataEngine\Controller\DictionaryEngine.cs - - - Internal\DataEngine\Controller\StringEngine.cs - - - Internal\Message\Subclassing\FreeStyleMessageClassInfo.cs - - - Internal\Message\Subclassing\FreeStyleMessageClassingController.cs - - - Internal\Message\Subclassing\IFreeStyleMessageClassingController.cs - - - Internal\Protocol\AVIMProtocol.cs - - - Internal\Router\AVRouterController.cs - - - Internal\Router\IAVRouterController.cs - - - Internal\Router\State\RouterState.cs - - - Internal\Timer\IAVTimer.cs - - - Internal\Timer\Unity\AVTimer.Unity.cs - - - Internal\WebSocket\IWebSocketClient.cs - - - Internal\WebSocket\Unity\DefaultWebSocketClient.Unity.cs - - - Public\AVIMAudioMessage.cs - - - Public\AVIMBinaryMessage.cs - - - Public\AVIMClient.cs - - - Public\AVIMConversation.cs - - - Public\AVIMConversationQuery.cs - - - Public\AVIMEnumerator.cs - - - Public\AVIMEventArgs.cs - - - Public\AVIMException.cs - - - Public\AVIMImageMessage.cs - - - Public\AVIMMessage.cs - - - Public\AVIMMessageClassNameAttribute.cs - - - Public\AVIMMessageFieldNameAttribute.cs - - - Public\AVIMMessageListener.cs - - - Public\AVIMNotice.cs - - - Public\AVIMRecalledMessage.cs - - - Public\AVIMSignature.cs - - - Public\AVIMTemporaryConversation.cs - - - Public\AVIMTextMessage.cs - - - Public\AVIMTypedMessage.cs - - - Public\AVIMTypedMessageTypeIntAttribute.cs - - - Public\AVRealtime.cs - - - Public\IAVIMListener.cs - - - Public\IAVIMMessage.cs - - - Public\ICacheEngine.cs - - - Public\ISignatureFactory.cs - - - Public\Listener\AVIMConversationListener.cs - - - Public\Listener\ConversationUnreadListener.cs - - - Public\Listener\GoAwayListener.cs - - - Public\Listener\MessagePatchListener.cs - - - Public\Listener\OfflineMessageListener.cs - - - Public\Listener\SessionListener.cs - - - Public\Unity\AVRealtimeBehavior.cs - - - - - Internal\WebSocket\Unity\websocket-sharp.dll - - - - \ No newline at end of file diff --git a/RTM/Source/Internal/AVIMCorePlugins.cs b/RTM/Source/Internal/AVIMCorePlugins.cs deleted file mode 100644 index 859e0bc..0000000 --- a/RTM/Source/Internal/AVIMCorePlugins.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace LeanCloud.Realtime.Internal -{ - internal class AVIMCorePlugins - { - private static readonly AVIMCorePlugins instance = new AVIMCorePlugins(); - public static AVIMCorePlugins Instance - { - get - { - return instance; - } - } - - private readonly object mutex = new object(); - - private IAVRouterController routerController; - public IAVRouterController RouterController - { - get - { - lock (mutex) - { - routerController = routerController ?? new AVRouterController(); - return routerController; - } - } - internal set - { - lock (mutex) - { - routerController = value; - } - } - } - - - private IFreeStyleMessageClassingController freeStyleClassingController; - public IFreeStyleMessageClassingController FreeStyleClassingController - { - get - { - lock (mutex) - { - freeStyleClassingController = freeStyleClassingController ?? new FreeStyleMessageClassingController(); - return freeStyleClassingController; - } - } - } - } -} diff --git a/RTM/Source/Internal/Command/AVIMCommand.cs b/RTM/Source/Internal/Command/AVIMCommand.cs deleted file mode 100644 index 18300e5..0000000 --- a/RTM/Source/Internal/Command/AVIMCommand.cs +++ /dev/null @@ -1,176 +0,0 @@ -using LeanCloud; -using LeanCloud.Storage.Internal; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace LeanCloud.Realtime.Internal -{ - /// - /// Command. - /// - public class AVIMCommand - { - protected readonly string cmd; - protected readonly string op; - protected string appId; - protected string peerId; - protected AVIMSignature signature; - protected readonly IDictionary arguments; - - public int TimeoutInSeconds { get; set; } - - protected readonly IDictionary estimatedData = new Dictionary(); - internal readonly object mutex = new object(); - internal static readonly object Mutex = new object(); - - public AVIMCommand() : - this(arguments: new Dictionary()) - { - - } - protected AVIMCommand(string cmd = null, - string op = null, - string appId = null, - string peerId = null, - AVIMSignature signature = null, - IDictionary arguments = null) - { - this.cmd = cmd; - this.op = op; - this.arguments = arguments == null ? new Dictionary() : arguments; - this.peerId = peerId; - this.signature = signature; - } - - protected AVIMCommand(AVIMCommand source, - string cmd = null, - string op = null, - string appId = null, - string peerId = null, - IDictionary arguments = null, - AVIMSignature signature = null) - { - if (source == null) - { - throw new ArgumentNullException("source", "Source can not be null"); - } - this.cmd = source.cmd; - this.op = source.op; - this.arguments = source.arguments; - this.peerId = source.peerId; - this.appId = source.appId; - this.signature = source.signature; - - if (cmd != null) - { - this.cmd = cmd; - } - if (op != null) - { - this.op = op; - } - if (arguments != null) - { - this.arguments = arguments; - } - if (peerId != null) - { - this.peerId = peerId; - } - if (appId != null) - { - this.appId = appId; - } - if (signature != null) - { - this.signature = signature; - } - } - - public AVIMCommand Command(string cmd) - { - return new AVIMCommand(this, cmd: cmd); - } - public AVIMCommand Option(string op) - { - return new AVIMCommand(this, op: op); - } - public AVIMCommand Argument(string key, object value) - { - lock (mutex) - { - this.arguments[key] = value; - return new AVIMCommand(this); - } - } - public AVIMCommand AppId(string appId) - { - this.appId = appId; - return new AVIMCommand(this, appId: appId); - } - - public AVIMCommand PeerId(string peerId) - { - this.peerId = peerId; - return new AVIMCommand(this, peerId: peerId); - } - - public AVIMCommand IDlize() - { - this.Argument("i", AVIMCommand.NextCmdId); - return this; - } - - public virtual IDictionary Encode() - { - lock (mutex) - { - estimatedData.Clear(); - estimatedData.Merge(arguments); - estimatedData.Add("cmd", cmd); - estimatedData.Add("appId", this.appId); - if (!string.IsNullOrEmpty(op)) - estimatedData.Add("op", op); - if (!string.IsNullOrEmpty(peerId)) - estimatedData.Add("peerId", peerId); - - return estimatedData; - } - } - - public virtual string EncodeJsonString() - { - var json = this.Encode(); - return Json.Encode(json); - } - - public bool IsValid - { - get - { - return !string.IsNullOrEmpty(this.cmd); - } - } - - private static Int32 lastCmdId = -65536; - internal static Int32 NextCmdId - { - get - { - lock (Mutex) - { - lastCmdId++; - - if (lastCmdId > ushort.MaxValue) - { - lastCmdId = -65536; - } - return lastCmdId; - } - } - } - } -} diff --git a/RTM/Source/Internal/Command/AVIMCommandRunner.cs b/RTM/Source/Internal/Command/AVIMCommandRunner.cs deleted file mode 100644 index 2052c46..0000000 --- a/RTM/Source/Internal/Command/AVIMCommandRunner.cs +++ /dev/null @@ -1,92 +0,0 @@ -using LeanCloud; -using LeanCloud.Storage.Internal; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -namespace LeanCloud.Realtime.Internal -{ - public class AVIMCommandRunner : IAVIMCommandRunner - { - private readonly IWebSocketClient webSocketClient; - public AVIMCommandRunner(IWebSocketClient webSocketClient) - { - this.webSocketClient = webSocketClient; - } - - public void RunCommand(AVIMCommand command) - { - command.IDlize(); - var requestString = command.EncodeJsonString(); - AVRealtime.PrintLog("websocket=>" + requestString); - webSocketClient.Send(requestString); - } - - /// - /// - /// - /// - /// - /// - public Task>> RunCommandAsync(AVIMCommand command, CancellationToken cancellationToken = default(CancellationToken)) - { - var tcs = new TaskCompletionSource>>(); - - command.IDlize(); - - var requestString = command.EncodeJsonString(); - if (!command.IsValid) - { - requestString = "{}"; - } - AVRealtime.PrintLog("websocket=>" + requestString); - webSocketClient.Send(requestString); - var requestJson = command.Encode(); - - - Action onMessage = null; - onMessage = (response) => - { - //AVRealtime.PrintLog("response<=" + response); - var responseJson = Json.Parse(response) as IDictionary; - if (responseJson.Keys.Contains("i")) - { - if (requestJson["i"].ToString() == responseJson["i"].ToString()) - { - var result = new Tuple>(-1, responseJson); - if (responseJson.Keys.Contains("code")) - { - var errorCode = int.Parse(responseJson["code"].ToString()); - var reason = string.Empty; - int appCode = 0; - - if (responseJson.Keys.Contains("reason")) - { - reason = responseJson["reason"].ToString(); - } - if (responseJson.Keys.Contains("appCode")) - { - appCode = int.Parse(responseJson["appCode"].ToString()); - } - tcs.SetException(new AVIMException(errorCode, appCode, reason, null)); - } - if (tcs.Task.Exception == null) - { - tcs.SetResult(result); - } - webSocketClient.OnMessage -= onMessage; - } - else - { - - } - } - }; - webSocketClient.OnMessage += onMessage; - return tcs.Task; - } - } -} diff --git a/RTM/Source/Internal/Command/AckCommand.cs b/RTM/Source/Internal/Command/AckCommand.cs deleted file mode 100644 index 938f078..0000000 --- a/RTM/Source/Internal/Command/AckCommand.cs +++ /dev/null @@ -1,63 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace LeanCloud.Realtime.Internal -{ - internal class AckCommand : AVIMCommand - { - public AckCommand() - : base(cmd: "ack") - { - - } - - public AckCommand(AVIMCommand source) - : base(source) - { - - } - - public AckCommand Message(IAVIMMessage message) - { - return new AckCommand() - .ConversationId(message.ConversationId) - .MessageId(message.Id); - } - - public AckCommand MessageId(string messageId) - { - if (string.IsNullOrEmpty(messageId)) - { - messageId = ""; - } - return new AckCommand(this.Argument("mid", messageId)); - } - - public AckCommand ConversationId(string conversationId) - { - if (string.IsNullOrEmpty(conversationId)) - { - conversationId = ""; - } - return new AckCommand(this.Argument("cid", conversationId)); - } - - public AckCommand FromTimeStamp(long startTimeStamp) - { - return new AckCommand(this.Argument("fromts", startTimeStamp)); - } - - public AckCommand ToTimeStamp(long endTimeStamp) - { - return new AckCommand(this.Argument("tots", endTimeStamp)); - } - - public AckCommand ReadAck() - { - return new AckCommand(this.Argument("read", true)); - } - } -} diff --git a/RTM/Source/Internal/Command/ConversationCommand.cs b/RTM/Source/Internal/Command/ConversationCommand.cs deleted file mode 100644 index ab4de2d..0000000 --- a/RTM/Source/Internal/Command/ConversationCommand.cs +++ /dev/null @@ -1,129 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace LeanCloud.Realtime.Internal -{ - internal class ConversationCommand : AVIMCommand - { - protected IList members; - public ConversationCommand() - : base(cmd: "conv") - { - - } - - public ConversationCommand(AVIMCommand source) - : base(source: source) - { - } - - public ConversationCommand Member(string clientId) - { - if (members == null) - { - members = new List(); - } - members.Add(clientId); - return Members(members); - } - - public ConversationCommand Members(IEnumerable members) - { - this.members = members.ToList(); - return new ConversationCommand(this.Argument("m", members)); - } - - public ConversationCommand Transient(bool isTransient) - { - return new ConversationCommand(this.Argument("transient", isTransient)); - } - - public ConversationCommand Unique(bool isUnique) - { - return new ConversationCommand(this.Argument("unique", isUnique)); - } - - public ConversationCommand Temporary(bool isTemporary) - { - return new ConversationCommand(this.Argument("tempConv", isTemporary)); - } - - public ConversationCommand TempConvTTL(double tempConvTTL) - { - return new ConversationCommand(this.Argument("tempConvTTL", tempConvTTL)); - } - - public ConversationCommand Attr(IDictionary attr) - { - return new ConversationCommand(this.Argument("attr", attr)); - } - - public ConversationCommand Set(string key, object value) - { - return new ConversationCommand(this.Argument(key, value)); - } - - public ConversationCommand ConversationId(string conversationId) - { - return new ConversationCommand(this.Argument("cid", conversationId)); - } - - public ConversationCommand Generate(AVIMConversation conversation) - { - var attr = conversation.EncodeAttributes(); - var cmd = new ConversationCommand() - .ConversationId(conversation.ConversationId) - .Attr(attr) - .Members(conversation.MemberIds) - .Transient(conversation.IsTransient) - .Temporary(conversation.IsTemporary); - - if (conversation.IsTemporary) - { - var ttl = (conversation.expiredAt.Value - DateTime.Now).TotalSeconds; - cmd = cmd.TempConvTTL(ttl); - } - - return cmd; - } - - public ConversationCommand Where(object encodedQueryString) - { - return new ConversationCommand(this.Argument("where", encodedQueryString)); - } - - public ConversationCommand Limit(int limit) - { - return new ConversationCommand(this.Argument("limit", limit)); - } - - public ConversationCommand Skip(int skip) - { - return new ConversationCommand(this.Argument("skip", skip)); - } - - public ConversationCommand Count() - { - return new ConversationCommand(this.Argument("count", 1)); - } - - public ConversationCommand Sort(string sort) - { - return new ConversationCommand(this.Argument("sort", sort)); - } - - public ConversationCommand TargetClientId(string targetClientId) - { - return new ConversationCommand(this.Argument("targetClientId", targetClientId)); - } - - public ConversationCommand QueryAllMembers(bool queryAllMembers) - { - return new ConversationCommand(this.Argument("queryAllMembers", queryAllMembers)); - } - - } -} diff --git a/RTM/Source/Internal/Command/IAVIMCommandRunner.cs b/RTM/Source/Internal/Command/IAVIMCommandRunner.cs deleted file mode 100644 index a904f97..0000000 --- a/RTM/Source/Internal/Command/IAVIMCommandRunner.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -namespace LeanCloud.Realtime.Internal -{ - public interface IAVIMCommandRunner - { - Task>> RunCommandAsync(AVIMCommand command, - CancellationToken cancellationToken = default(CancellationToken)); - - void RunCommand(AVIMCommand command); - } -} diff --git a/RTM/Source/Internal/Command/MessageCommand.cs b/RTM/Source/Internal/Command/MessageCommand.cs deleted file mode 100644 index ec76d94..0000000 --- a/RTM/Source/Internal/Command/MessageCommand.cs +++ /dev/null @@ -1,83 +0,0 @@ -using LeanCloud.Storage.Internal; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace LeanCloud.Realtime.Internal -{ - internal class MessageCommand : AVIMCommand - { - public MessageCommand() - : base(cmd: "direct") - { - - } - - public MessageCommand(AVIMCommand source) - : base(source: source) - { - - } - - public MessageCommand ConvId(string convId) - { - return new MessageCommand(this.Argument("cid", convId)); - } - - public MessageCommand Receipt(bool receipt) - { - return new MessageCommand(this.Argument("r", receipt)); - } - - public MessageCommand Transient(bool transient) - { - if (transient) return new MessageCommand(this.Argument("transient", transient)); - return new MessageCommand(this); - } - public MessageCommand Priority(int priority) - { - if (priority > 1) return new MessageCommand(this.Argument("level", priority)); - return new MessageCommand(this); - } - public MessageCommand Will(bool will) - { - if (will) return new MessageCommand(this.Argument("will", will)); - return new MessageCommand(this); - } - public MessageCommand Distinct(string token) - { - return new MessageCommand(this.Argument("dt", token)); - } - public MessageCommand Message(string msg) - { - return new MessageCommand(this.Argument("msg", msg)); - } - public MessageCommand BinaryEncode(bool binaryEncode) - { - return new MessageCommand(this.Argument("bin", binaryEncode)); - } - - public MessageCommand PushData(IDictionary pushData) - { - return new MessageCommand(this.Argument("pushData", Json.Encode(pushData))); - } - - public MessageCommand Mention(IEnumerable clientIds) - { - var mentionedMembers = clientIds.ToList(); - return new MessageCommand(this.Argument("mentionPids", mentionedMembers)); - } - - public MessageCommand MentionAll(bool mentionAll) - { - return new MessageCommand(this.Argument("mentionAll", mentionAll)); - } - - public MessageCommand Binary(byte[] data) - { - return new MessageCommand(this.Argument("binaryMsg", data)); - } - } -} diff --git a/RTM/Source/Internal/Command/PatchCommand.cs b/RTM/Source/Internal/Command/PatchCommand.cs deleted file mode 100644 index 113a0db..0000000 --- a/RTM/Source/Internal/Command/PatchCommand.cs +++ /dev/null @@ -1,98 +0,0 @@ -using LeanCloud.Storage.Internal; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace LeanCloud.Realtime.Internal -{ - internal class PatchCommand : AVIMCommand - { - - internal struct Patch - { - public string MessageId { get; set; } - public string ConvId { get; set; } - public string From { get; set; } - public long MetaTimestamp { get; set; } - public long PatchTimestamp { get; set; } - public string PatchData { get; set; } - public bool Recall { get; set; } - public byte[] BinaryData { get; set; } - public bool MentionAll { get; set; } - public IEnumerable MentionIds { get; set; } - - public IDictionary Encode() - { - return new Dictionary() - { - { "cid",this.ConvId}, - { "mid",this.MessageId}, - { "from",this.From}, - { "timestamp",this.MetaTimestamp}, - { "recall",this.Recall}, - { "data",this.PatchData}, - { "patchTimestamp",this.PatchTimestamp}, - { "binaryMsg",this.BinaryData}, - { "mentionAll",this.MentionAll}, - { "meintonPids",this.MentionIds} - } as IDictionary; - } - } - - public PatchCommand() - : base(cmd: "patch", op: "modify") - { - this.Patches = new List(); - } - - public PatchCommand(AVIMCommand source, ICollection sourcePatchs) - : base(source: source) - { - this.Patches = sourcePatchs; - } - - public ICollection Patches { get; set; } - - public IList> EncodePatches() - { - return this.Patches.Select(p => p.Encode().Trim()).ToList(); - } - - public PatchCommand Recall(IAVIMMessage message) - { - var patch = new Patch() - { - ConvId = message.ConversationId, - From = message.FromClientId, - MessageId = message.Id, - MetaTimestamp = message.ServerTimestamp, - Recall = true, - PatchTimestamp = DateTime.Now.ToUnixTimeStamp() - }; - - this.Patches.Add(patch); - this.Argument("patches", this.EncodePatches()); - return new PatchCommand(this, this.Patches); - } - - public PatchCommand Modify(IAVIMMessage oldMessage, IAVIMMessage newMessage) - { - var patch = new Patch() - { - ConvId = oldMessage.ConversationId, - From = oldMessage.FromClientId, - MessageId = oldMessage.Id, - MetaTimestamp = oldMessage.ServerTimestamp, - Recall = false, - PatchTimestamp = DateTime.Now.ToUnixTimeStamp(), - PatchData = newMessage.Serialize() - }; - - this.Patches.Add(patch); - this.Argument("patches", this.EncodePatches()); - return new PatchCommand(this, this.Patches); - } - } -} diff --git a/RTM/Source/Internal/Command/ReadCommand.cs b/RTM/Source/Internal/Command/ReadCommand.cs deleted file mode 100644 index a627d00..0000000 --- a/RTM/Source/Internal/Command/ReadCommand.cs +++ /dev/null @@ -1,91 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace LeanCloud.Realtime.Internal -{ - internal class ReadCommand : AVIMCommand - { - internal class ConvRead - { - internal string ConvId { get; set; } - internal string MessageId { get; set; } - internal long Timestamp { get; set; } - public override bool Equals(object obj) - { - ConvRead cr = obj as ConvRead; - return cr.ConvId == this.ConvId; - } - public override int GetHashCode() - { - return this.ConvId.GetHashCode() ^ this.MessageId.GetHashCode() ^ this.Timestamp.GetHashCode(); - } - } - - public ReadCommand() - : base(cmd: "read") - { - - } - - public ReadCommand(AVIMCommand source) - : base(source) - { - - } - - public ReadCommand ConvId(string convId) - { - return new ReadCommand(this.Argument("cid", convId)); - } - - public ReadCommand ConvIds(IEnumerable convIds) - { - if (convIds != null) - { - if (convIds.Count() > 0) - { - return new ReadCommand(this.Argument("cids", convIds.ToList())); - } - } - return this; - - } - - public ReadCommand Conv(ConvRead conv) - { - return Convs(new ConvRead[] { conv }); - } - - public ReadCommand Convs(IEnumerable convReads) - { - if (convReads != null) - { - if (convReads.Count() > 0) - { - IList> payload = new List>(); - - foreach (var convRead in convReads) - { - var convDic = new Dictionary(); - convDic.Add("cid", convRead.ConvId); - if (!string.IsNullOrEmpty(convRead.MessageId)) - { - convDic.Add("mid", convRead.MessageId); - } - if (convRead.Timestamp != 0) - { - convDic.Add("timestamp", convRead.Timestamp); - } - payload.Add(convDic); - } - - return new ReadCommand(this.Argument("convs", payload)); - } - } - return this; - } - } -} diff --git a/RTM/Source/Internal/Command/SessionCommand.cs b/RTM/Source/Internal/Command/SessionCommand.cs deleted file mode 100644 index f18b7b9..0000000 --- a/RTM/Source/Internal/Command/SessionCommand.cs +++ /dev/null @@ -1,57 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace LeanCloud.Realtime.Internal -{ - internal class SessionCommand : AVIMCommand - { - static readonly int MESSAGE_RECALL_AND_MODIFY = 0x1; - - public SessionCommand() - : base(cmd: "session") - { - arguments.Add("configBitmap", MESSAGE_RECALL_AND_MODIFY); - } - - public SessionCommand(AVIMCommand source) - :base(source: source) - { - - } - - public SessionCommand UA(string ua) - { - return new SessionCommand(this.Argument("ua", ua)); - } - - public SessionCommand Tag(string tag) - { - if (string.IsNullOrEmpty(tag)) return new SessionCommand(this); - return new SessionCommand(this.Argument("tag", tag)); - } - - public SessionCommand DeviceId(string deviceId) - { - if (string.IsNullOrEmpty(deviceId)) return new SessionCommand(this); - return new SessionCommand(this.Argument("deviceId", deviceId)); - } - - public SessionCommand R(int r) - { - return new SessionCommand(this.Argument("r", r)); - } - - public SessionCommand SessionToken(string st) - { - return new SessionCommand(this.Argument("st", st)); - } - - public SessionCommand SessionPeerIds(IEnumerable sessionPeerIds) - { - return new SessionCommand(this.Argument("sessionPeerIds", sessionPeerIds.ToList())); - } - } -} diff --git a/RTM/Source/Internal/DataEngine/Controller/DateTimeEngine.cs b/RTM/Source/Internal/DataEngine/Controller/DateTimeEngine.cs deleted file mode 100644 index 25c920a..0000000 --- a/RTM/Source/Internal/DataEngine/Controller/DateTimeEngine.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace LeanCloud.Realtime.Internal -{ - internal enum UnixTimeStampUnit - { - Second = 1, - Milisecond = 1000, - } - internal static class DateTimeEngine - { - public static long ToUnixTimeStamp(this DateTime date, UnixTimeStampUnit unit = UnixTimeStampUnit.Milisecond) - { - long unixTimestamp = (long)(date.ToUniversalTime().Subtract(new DateTime(1970, 1, 1))).TotalSeconds; - return (unixTimestamp * (int)unit); - } - - public static DateTime ToDateTime(this long timestamp, UnixTimeStampUnit unit = UnixTimeStampUnit.Milisecond) - { - var timespan = timestamp * 1000 / (int)(unit); - DateTime dtDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); - dtDateTime = dtDateTime.AddMilliseconds(timespan).ToLocalTime(); - return dtDateTime; - } - } -} diff --git a/RTM/Source/Internal/DataEngine/Controller/DictionaryEngine.cs b/RTM/Source/Internal/DataEngine/Controller/DictionaryEngine.cs deleted file mode 100644 index a1da600..0000000 --- a/RTM/Source/Internal/DataEngine/Controller/DictionaryEngine.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace LeanCloud.Realtime.Internal -{ - internal static class DictionaryEngine - { - internal static IDictionary Merge(this IDictionary dataLeft, IDictionary dataRight) - { - if (dataRight == null) - return dataLeft; - foreach (var kv in dataRight) - { - if (dataLeft.ContainsKey(kv.Key)) - { - dataLeft[kv.Key] = kv.Value; - } - else - { - dataLeft.Add(kv); - } - } - return dataLeft; - } - - internal static object Grab(this IDictionary data, string path) - { - var keys = path.Split('.').ToList(); - if (keys.Count == 1) return data[keys[0]]; - - var deep = data[keys[0]] as IDictionary; - - keys.RemoveAt(0); - string deepPath = string.Join(".", keys.ToArray()); - - return Grab(deep, deepPath); - } - - internal static IDictionary Trim(this IDictionary data) - { - return data.Where(kvp => kvp.Value != null).ToDictionary(k => k.Key, v => v.Value); - } - } -} diff --git a/RTM/Source/Internal/DataEngine/Controller/StringEngine.cs b/RTM/Source/Internal/DataEngine/Controller/StringEngine.cs deleted file mode 100644 index 62e902a..0000000 --- a/RTM/Source/Internal/DataEngine/Controller/StringEngine.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; -using System.Linq; -using System.Collections.Generic; -using System.Linq.Expressions; -using System.Text; - -namespace LeanCloud.Realtime.Internal -{ - internal static class StringEngine - { - internal static string Random(this string str, int length) - { - const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz"; - var random = new Random(); - return new string(Enumerable.Repeat(chars, length) - .Select(s => s[random.Next(s.Length)]).ToArray()); - } - - internal static string TempConvId(this IEnumerable objs) - { - var orderedBase64Strs = objs.Select(obj => Encoding.UTF8.ToBase64(obj.ToString())).OrderBy(a => a, StringComparer.Ordinal).ToArray(); - return "_tmp:" + string.Join("$", orderedBase64Strs); - } - - internal static string ToBase64(this System.Text.Encoding encoding, string text) - { - if (text == null) - { - return null; - } - - byte[] textAsBytes = encoding.GetBytes(text); - return Convert.ToBase64String(textAsBytes); - } - } -} diff --git a/RTM/Source/Internal/IAVIMPlatformHooks.cs b/RTM/Source/Internal/IAVIMPlatformHooks.cs deleted file mode 100644 index 53d737c..0000000 --- a/RTM/Source/Internal/IAVIMPlatformHooks.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace LeanCloud.Realtime.Internal -{ - interface IAVIMPlatformHooks - { - IWebSocketClient WebSocketClient { get; } - - string ua { get; } - } -} diff --git a/RTM/Source/Internal/Message/Subclassing/FreeStyleMessageClassInfo.cs b/RTM/Source/Internal/Message/Subclassing/FreeStyleMessageClassInfo.cs deleted file mode 100644 index e1a1e56..0000000 --- a/RTM/Source/Internal/Message/Subclassing/FreeStyleMessageClassInfo.cs +++ /dev/null @@ -1,75 +0,0 @@ -using LeanCloud.Storage.Internal; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using System.Text; - -namespace LeanCloud.Realtime.Internal -{ - internal class FreeStyleMessageClassInfo - { - public TypeInfo TypeInfo { get; private set; } - public IDictionary PropertyMappings { get; private set; } - private ConstructorInfo Constructor { get; set; } - //private MethodInfo ValidateMethod { get; set; } - - public int TypeInt { get; set; } - - public FreeStyleMessageClassInfo(Type type, ConstructorInfo constructor) - { - TypeInfo = type.GetTypeInfo(); - Constructor = constructor; - PropertyMappings = ReflectionHelpers.GetProperties(type) - .Select(prop => Tuple.Create(prop, prop.GetCustomAttribute(true))) - .Where(t => t.Item2 != null) - .Select(t => Tuple.Create(t.Item1, t.Item2.FieldName)) - .ToDictionary(t => t.Item1.Name, t => t.Item2); - } - public bool Validate(string msgStr) - { - var instance = Instantiate(msgStr); - if (instance is AVIMTypedMessage) - { - try - { - var msgDic = Json.Parse(msgStr) as IDictionary; - if (msgDic != null) - { - if (msgDic.ContainsKey(AVIMProtocol.LCTYPE)) - { - return msgDic[AVIMProtocol.LCTYPE].ToString() == TypeInt.ToString(); - } - } - } - catch (Exception ex) - { - if (ex is ArgumentException) - { - return instance.Validate(msgStr); - } - } - - } - return instance.Validate(msgStr); - } - - public IAVIMMessage Instantiate(string msgStr) - { - var rtn = (IAVIMMessage)Constructor.Invoke(null); - return rtn; - } - - public static string GetMessageClassName(TypeInfo type) - { - var attribute = type.GetCustomAttribute(); - return attribute != null ? attribute.ClassName : null; - } - - public static int GetTypedInteger(TypeInfo type) - { - var attribute = type.GetCustomAttribute(); - return attribute != null ? attribute.TypeInteger : 0; - } - } -} diff --git a/RTM/Source/Internal/Message/Subclassing/FreeStyleMessageClassingController.cs b/RTM/Source/Internal/Message/Subclassing/FreeStyleMessageClassingController.cs deleted file mode 100644 index 04bd105..0000000 --- a/RTM/Source/Internal/Message/Subclassing/FreeStyleMessageClassingController.cs +++ /dev/null @@ -1,210 +0,0 @@ -using LeanCloud.Storage.Internal; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using System.Text; -using System.Threading; - -namespace LeanCloud.Realtime.Internal -{ - internal class FreeStyleMessageClassingController : IFreeStyleMessageClassingController - { - private static readonly string messageClassName = "_AVIMMessage"; - private readonly IDictionary registeredInterfaces; - private readonly ReaderWriterLockSlim mutex; - - public FreeStyleMessageClassingController() - { - mutex = new ReaderWriterLockSlim(); - registeredInterfaces = new Dictionary(); - } - - public Type GetType(IDictionary msg) - { - throw new NotImplementedException(); - } - - public IAVIMMessage Instantiate(string msgStr, IDictionary buildInData) - { - FreeStyleMessageClassInfo info = null; - mutex.EnterReadLock(); - bool bin = false; - if (buildInData.ContainsKey("bin")) - { - bool.TryParse(buildInData["bin"].ToString(), out bin); - } - - if (bin) - { - var binMessage = new AVIMBinaryMessage(); - this.DecodeProperties(binMessage, buildInData); - return binMessage; - } - - var reverse = registeredInterfaces.Values.Reverse(); - foreach (var subInterface in reverse) - { - if (subInterface.Validate(msgStr)) - { - info = subInterface; - break; - } - } - - mutex.ExitReadLock(); - - var message = info != null ? info.Instantiate(msgStr) : new AVIMMessage(); - - this.DecodeProperties(message, buildInData); - - message.Deserialize(msgStr); - - return message; - } - - public IAVIMMessage DecodeProperties(IAVIMMessage message, IDictionary buildInData) - { - long timestamp; - if (buildInData.ContainsKey("timestamp")) - { - if (long.TryParse(buildInData["timestamp"].ToString(), out timestamp)) - { - message.ServerTimestamp = timestamp; - } - } - long ackAt; - if (buildInData.ContainsKey("ackAt")) - { - if (long.TryParse(buildInData["ackAt"].ToString(), out ackAt)) - { - message.RcpTimestamp = ackAt; - } - } - - if (buildInData.ContainsKey("from")) - { - message.FromClientId = buildInData["from"].ToString(); - } - if (buildInData.ContainsKey("msgId")) - { - message.Id = buildInData["msgId"].ToString(); - } - if (buildInData.ContainsKey("cid")) - { - message.ConversationId = buildInData["cid"].ToString(); - } - if (buildInData.ContainsKey("fromPeerId")) - { - message.FromClientId = buildInData["fromPeerId"].ToString(); - } - if (buildInData.ContainsKey("id")) - { - message.Id = buildInData["id"].ToString(); - } - if (buildInData.ContainsKey("mid")) - { - message.Id = buildInData["mid"].ToString(); - } - if (buildInData.ContainsKey("mentionPids")) - { - message.MentionList = AVDecoder.Instance.DecodeList(buildInData["mentionPids"]); - } - if (buildInData.TryGetValue("patchTimestamp", out object patchTimestampObj)) { - if (long.TryParse(patchTimestampObj.ToString(), out long patchTimestamp)) { - message.UpdatedAt = patchTimestamp; - } - } - - bool mentionAll; - if (buildInData.ContainsKey("mentionAll")) - { - if (bool.TryParse(buildInData["mentionAll"].ToString(), out mentionAll)) - { - message.MentionAll = mentionAll; - } - } - return message; - } - - public IDictionary EncodeProperties(IAVIMMessage subclass) - { - var type = subclass.GetType(); - var result = new Dictionary(); - var className = GetClassName(type); - var typeInt = GetTypeInt(type); - var propertMappings = GetPropertyMappings(className); - foreach (var propertyPair in propertMappings) - { - var propertyInfo = ReflectionHelpers.GetProperty(type, propertyPair.Key); - var operation = propertyInfo.GetValue(subclass, null); - if (operation != null) - result[propertyPair.Value] = PointerOrLocalIdEncoder.Instance.Encode(operation); - } - if (typeInt != 0) - { - result[AVIMProtocol.LCTYPE] = typeInt; - } - return result; - } - - public bool IsTypeValid(IDictionary msg, Type type) - { - return true; - } - - public void RegisterSubclass(Type type) - { - TypeInfo typeInfo = type.GetTypeInfo(); - - if (!typeof(IAVIMMessage).GetTypeInfo().IsAssignableFrom(typeInfo)) - { - throw new ArgumentException("Cannot register a type that is not a implementation of IAVIMMessage"); - } - var className = GetClassName(type); - var typeInt = GetTypeInt(type); - try - { - mutex.EnterWriteLock(); - ConstructorInfo constructor = type.FindConstructor(); - if (constructor == null) - { - throw new ArgumentException("Cannot register a type that does not implement the default constructor!"); - } - var classInfo = new FreeStyleMessageClassInfo(type, constructor); - if (typeInt != 0) - { - classInfo.TypeInt = typeInt; - } - registeredInterfaces[className] = classInfo; - } - finally - { - mutex.ExitWriteLock(); - } - } - public String GetClassName(Type type) - { - return type == typeof(IAVIMMessage) - ? messageClassName - : FreeStyleMessageClassInfo.GetMessageClassName(type.GetTypeInfo()); - } - public int GetTypeInt(Type type) - { - return type == typeof(AVIMTypedMessage) ? 0 : FreeStyleMessageClassInfo.GetTypedInteger(type.GetTypeInfo()); - } - public IDictionary GetPropertyMappings(String className) - { - FreeStyleMessageClassInfo info = null; - mutex.EnterReadLock(); - registeredInterfaces.TryGetValue(className, out info); - if (info == null) - { - registeredInterfaces.TryGetValue(messageClassName, out info); - } - mutex.ExitReadLock(); - - return info.PropertyMappings; - } - } -} diff --git a/RTM/Source/Internal/Message/Subclassing/IFreeStyleMessageClassingController.cs b/RTM/Source/Internal/Message/Subclassing/IFreeStyleMessageClassingController.cs deleted file mode 100644 index 0fc3912..0000000 --- a/RTM/Source/Internal/Message/Subclassing/IFreeStyleMessageClassingController.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace LeanCloud.Realtime.Internal -{ - interface IFreeStyleMessageClassingController - { - bool IsTypeValid(IDictionary msg, Type type); - void RegisterSubclass(Type t); - IAVIMMessage Instantiate(string msgStr,IDictionary buildInData); - IDictionary EncodeProperties(IAVIMMessage subclass); - Type GetType(IDictionary msg); - String GetClassName(Type type); - IDictionary GetPropertyMappings(String className); - } -} diff --git a/RTM/Source/Internal/Protocol/AVIMProtocol.cs b/RTM/Source/Internal/Protocol/AVIMProtocol.cs deleted file mode 100644 index 6c71044..0000000 --- a/RTM/Source/Internal/Protocol/AVIMProtocol.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace LeanCloud.Realtime.Internal -{ - internal class AVIMProtocol - { - #region msg format - static internal readonly string LCTYPE = "_lctype"; - static internal readonly string LCFILE = "_lcfile"; - static internal readonly string LCTEXT = "_lctext"; - static internal readonly string LCATTRS = "_lcattrs"; - static internal readonly string LCLOC = "_lcloc"; - #endregion - } -} diff --git a/RTM/Source/Internal/Router/AVRouterController.cs b/RTM/Source/Internal/Router/AVRouterController.cs deleted file mode 100644 index dc47848..0000000 --- a/RTM/Source/Internal/Router/AVRouterController.cs +++ /dev/null @@ -1,173 +0,0 @@ -using LeanCloud.Storage.Internal; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -namespace LeanCloud.Realtime.Internal -{ - internal class AVRouterController : IAVRouterController - { - const string routerUrl = "http://router.g0.push.leancloud.cn/v1/route?appId={0}"; - const string routerKey = "LeanCloud_RouterState"; - public Task GetAsync(string pushRouter = null, bool secure = true, CancellationToken cancellationToken = default(CancellationToken)) - { - //return Task.FromResult(new PushRouterState() - //{ - // server = "wss://rtm57.leancloud.cn/" - //}); - return LoadAysnc(cancellationToken).OnSuccess(_ => - { - var cache = _.Result; - var task = Task.FromResult(cache); - - if (cache == null || cache.expire < DateTime.Now.ToUnixTimeStamp()) - { - task = QueryAsync(pushRouter, secure, cancellationToken); - } - - return task; - }).Unwrap(); - } - - /// - /// 清理地址缓存 - /// - /// The cache. - public Task ClearCache() { - var tcs = new TaskCompletionSource(); - AVPlugins.Instance.StorageController.LoadAsync().ContinueWith(t => { - if (t.IsFaulted) { - tcs.SetResult(true); - } else { - var storage = t.Result; - if (storage.ContainsKey(routerKey)) { - storage.RemoveAsync(routerKey).ContinueWith(_ => tcs.SetResult(true)); - } else { - tcs.SetResult(true); - } - } - }); - return tcs.Task; - } - - Task LoadAysnc(CancellationToken cancellationToken) - { - try - { - return AVPlugins.Instance.StorageController.LoadAsync().OnSuccess(_ => - { - var currentCache = _.Result; - object routeCacheStr = null; - if (currentCache.TryGetValue(routerKey, out routeCacheStr)) - { - var routeCache = routeCacheStr as IDictionary; - var routerState = new PushRouterState() - { - groupId = routeCache["groupId"] as string, - server = routeCache["server"] as string, - secondary = routeCache["secondary"] as string, - ttl = long.Parse(routeCache["ttl"].ToString()), - expire = long.Parse(routeCache["expire"].ToString()), - source = "localCache" - }; - return routerState; - } - return null; - }); - } - catch - { - return Task.FromResult(null); - } - } - - Task QueryAsync(string pushRouter, bool secure, CancellationToken cancellationToken) - { - var routerHost = pushRouter; - if (routerHost == null) { - var appRouter = AVPlugins.Instance.AppRouterController.Get(); - routerHost = string.Format("https://{0}/v1/route?appId={1}", appRouter.RealtimeRouterServer, AVClient.CurrentConfiguration.ApplicationId) ?? appRouter.RealtimeRouterServer ?? string.Format(routerUrl, AVClient.CurrentConfiguration.ApplicationId); - } - AVRealtime.PrintLog($"router: {routerHost}"); - AVRealtime.PrintLog($"push: {pushRouter}"); - if (!string.IsNullOrEmpty(pushRouter)) - { - var rtmUri = new Uri(pushRouter); - if (!string.IsNullOrEmpty(rtmUri.Scheme)) - { - var url = new Uri(rtmUri, "v1/route").ToString(); - routerHost = string.Format("{0}?appId={1}", url, AVClient.CurrentConfiguration.ApplicationId); - } - else - { - routerHost = string.Format("https://{0}/v1/route?appId={1}", pushRouter, AVClient.CurrentConfiguration.ApplicationId); - } - } - if (secure) - { - routerHost += "&secure=1"; - } - - AVRealtime.PrintLog("use push router url:" + routerHost); - - return AVClient.RequestAsync(uri: new Uri(routerHost), - method: "GET", - headers: null, - data: null, - contentType: "application/json", - cancellationToken: CancellationToken.None).ContinueWith(t => - { - if (t.Exception != null) - { - var innnerException = t.Exception.InnerException; - AVRealtime.PrintLog(innnerException.Message); - throw innnerException; - } - var httpStatus = (int)t.Result.Item1; - if (httpStatus != 200) - { - return null; - } - try - { - var result = t.Result.Item2; - - var routerState = Json.Parse(result) as IDictionary; - if (routerState.Keys.Count == 0) - { - throw new KeyNotFoundException("Can not get websocket url from server,please check the appId."); - } - var ttl = long.Parse(routerState["ttl"].ToString()); - var expire = DateTime.Now.AddSeconds(ttl); - routerState["expire"] = expire.ToUnixTimeStamp(); - - //save to local cache async. - AVPlugins.Instance.StorageController.LoadAsync().OnSuccess(storage => storage.Result.AddAsync(routerKey, routerState)); - var routerStateObj = new PushRouterState() - { - groupId = routerState["groupId"] as string, - server = routerState["server"] as string, - secondary = routerState["secondary"] as string, - ttl = long.Parse(routerState["ttl"].ToString()), - expire = expire.ToUnixTimeStamp(), - source = "online" - }; - - return routerStateObj; - } - catch (Exception e) - { - if (e is KeyNotFoundException) - { - throw e; - } - return null; - } - - }); - } - } -} diff --git a/RTM/Source/Internal/Router/IAVRouterController.cs b/RTM/Source/Internal/Router/IAVRouterController.cs deleted file mode 100644 index b7eebfb..0000000 --- a/RTM/Source/Internal/Router/IAVRouterController.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.IO; -using System.Threading; -using System.Threading.Tasks; - -namespace LeanCloud.Realtime.Internal -{ - interface IAVRouterController - { - Task GetAsync(string pushRouter, bool secure, CancellationToken cancellationToken = default(CancellationToken)); - Task ClearCache(); - } -} diff --git a/RTM/Source/Internal/Router/State/RouterState.cs b/RTM/Source/Internal/Router/State/RouterState.cs deleted file mode 100644 index 66eaea9..0000000 --- a/RTM/Source/Internal/Router/State/RouterState.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace LeanCloud.Realtime.Internal -{ - internal class PushRouterState - { - public string groupId { get; internal set; } - public string server { get; internal set; } - public long ttl { get; internal set; } - public long expire { get; internal set; } - public string secondary { get; internal set; } - public string groupUrl { get; internal set; } - - public string source { get; internal set; } - } -} diff --git a/RTM/Source/Internal/Timer/IAVTimer.cs b/RTM/Source/Internal/Timer/IAVTimer.cs deleted file mode 100644 index 5573041..0000000 --- a/RTM/Source/Internal/Timer/IAVTimer.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System; -namespace LeanCloud.Realtime.Internal -{ - public interface IAVTimer - { - /// - /// Start this timer. - /// - void Start(); - - /// - /// Stop this timer. - /// - void Stop(); - - bool Enabled { get; set; } - - /// - /// The number of milliseconds between timer events. - /// - /// The interval. - double Interval { get; set; } - - /// - /// 已经执行了多少次 - /// - long Executed { get; } - - /// - /// Occurs when elapsed. - /// - event EventHandler Elapsed; - } - /// - /// Timer event arguments. - /// - public class TimerEventArgs : EventArgs - { - public TimerEventArgs(DateTime signalTime) - { - SignalTime = signalTime; - } - public DateTime SignalTime - { - get; - private set; - } - } -} diff --git a/RTM/Source/Internal/Timer/Portable/AVTimer.Portable.cs b/RTM/Source/Internal/Timer/Portable/AVTimer.Portable.cs deleted file mode 100644 index e981dbd..0000000 --- a/RTM/Source/Internal/Timer/Portable/AVTimer.Portable.cs +++ /dev/null @@ -1,107 +0,0 @@ -using System; -using System.Threading.Tasks; -using System.Threading; - -namespace LeanCloud.Realtime.Internal -{ - internal delegate void TimerCallback(); - - internal sealed class Timer : CancellationTokenSource, IDisposable - { - TimerCallback exe; - int Interval { get; set; } - - internal Timer(TimerCallback callback, int interval, bool enable) - { - exe = callback; - Interval = interval; - - Enabled = enable; - Execute(); - } - - Task Execute() - { - if (Enabled) - return Task.Delay(Interval).ContinueWith(t => - { - if (!Enabled) - return null; - exe(); - return this.Execute(); - }); - else - return Task.FromResult(0); - } - - volatile bool enabled; - public bool Enabled - { - get { - return enabled; - } set { - enabled = value; - } - } - } - - public class AVTimer : IAVTimer - { - public AVTimer() - { - - } - - Timer timer; - - public bool Enabled - { - get - { - return timer.Enabled; - } - set - { - timer.Enabled = value; - } - } - - public double Interval - { - get; set; - } - - long executed; - - public long Executed - { - get - { - return executed; - } - - internal set - { - executed = value; - } - } - - public void Start() - { - if (timer == null) - { - timer = new Timer(() => - { - Elapsed(this, new TimerEventArgs(DateTime.Now)); - }, (int)Interval, true); - } - } - - public void Stop() - { - if (timer != null) timer.Enabled = false; - } - - public event EventHandler Elapsed; - } -} diff --git a/RTM/Source/Internal/Timer/Unity/AVTimer.Unity.cs b/RTM/Source/Internal/Timer/Unity/AVTimer.Unity.cs deleted file mode 100644 index 8298433..0000000 --- a/RTM/Source/Internal/Timer/Unity/AVTimer.Unity.cs +++ /dev/null @@ -1,82 +0,0 @@ -using System; -using System.Timers; - -namespace LeanCloud.Realtime.Internal -{ - public class AVTimer : IAVTimer - { - public AVTimer() - { - timer = new Timer(); - } - - Timer timer; - - public bool Enabled - { - get - { - return timer.Enabled; - } - set - { - timer.Enabled = value; - } - } - - public double Interval - { - get - { - return timer.Interval; - } - set - { - timer.Interval = value; - } - } - - long executed; - - public long Executed - { - get - { - return executed; - } - - internal set - { - executed = value; - } - } - - public void Start() - { - timer.Start(); - } - - public void Stop() - { - timer.Stop(); - } - - public event EventHandler Elapsed - { - add - { - timer.Elapsed += (object sender, ElapsedEventArgs e) => - { - value(this, new TimerEventArgs(e.SignalTime)); - }; - } - remove - { - timer.Elapsed -= (object sender, ElapsedEventArgs e) => - { - value(this, new TimerEventArgs(e.SignalTime)); - }; ; - } - } - } -} diff --git a/RTM/Source/Internal/WebSocket/IWebSocketClient.cs b/RTM/Source/Internal/WebSocket/IWebSocketClient.cs deleted file mode 100644 index 175ffa0..0000000 --- a/RTM/Source/Internal/WebSocket/IWebSocketClient.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -namespace LeanCloud.Realtime.Internal -{ - /// - /// LeanCloud WebSocket 客户端接口 - /// - public interface IWebSocketClient - { - /// - /// 客户端 WebSocket 长连接是否打开 - /// - bool IsOpen { get; } - - /// - /// WebSocket 长连接关闭时触发的事件回调 - /// - event Action OnClosed; - - /// - /// 云端发送数据包给客户端,WebSocket 接受到时触发的事件回调 - /// - event Action OnMessage; - - /// - /// 客户端 WebSocket 长连接成功打开时,触发的事件回调 - /// - event Action OnOpened; - - /// - /// 主动关闭连接 - /// - void Close(); - - void Disconnect(); - - /// - /// 打开连接 - /// - /// wss 地址 - /// 子协议 - void Open(string url, string protocol = null); - /// - /// 发送数据包的接口 - /// - /// - void Send(string message); - - Task Connect(string url, string protocol = null); - } -} diff --git a/RTM/Source/Internal/WebSocket/NetCore/DefaultWebSocketClient.NetCore.cs b/RTM/Source/Internal/WebSocket/NetCore/DefaultWebSocketClient.NetCore.cs deleted file mode 100644 index bf27232..0000000 --- a/RTM/Source/Internal/WebSocket/NetCore/DefaultWebSocketClient.NetCore.cs +++ /dev/null @@ -1,174 +0,0 @@ -using System; -using System.Net.WebSockets; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -namespace LeanCloud.Realtime.Internal -{ - public class DefaultWebSocketClient : IWebSocketClient - { - private const int ReceiveChunkSize = 1024; - private const int SendChunkSize = 1024; - - private ClientWebSocket _ws; - private Uri _uri; - private readonly CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource(); - private readonly CancellationToken _cancellationToken; - - /// - /// Occurs when on closed. - /// - public event Action OnClosed; - /// - /// Occurs when on error. - /// - public event Action OnError; - /// - /// Occurs when on log. - /// - public event Action OnLog; - /// - /// Occurs when on opened. - /// - public event Action OnOpened; - - public bool IsOpen => _ws.State == WebSocketState.Open; - - public DefaultWebSocketClient() - { - _ws = NewWebSocket(); - _cancellationToken = _cancellationTokenSource.Token; - } - - public event Action OnMessage; - - private async void StartListen() - { - var buffer = new byte[8192]; - - try - { - while (_ws.State == WebSocketState.Open) - { - var stringResult = new StringBuilder(); - - WebSocketReceiveResult result; - do - { - result = await _ws.ReceiveAsync(new ArraySegment(buffer), _cancellationToken); - - if (result.MessageType == WebSocketMessageType.Close) - { - await - _ws.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None); - CallOnDisconnected(); - } - else - { - var str = Encoding.UTF8.GetString(buffer, 0, result.Count); - stringResult.Append(str); - } - - } while (!result.EndOfMessage); - - CallOnMessage(stringResult); - - } - } - catch (Exception) - { - CallOnDisconnected(); - } - finally - { - _ws.Dispose(); - } - } - - private void CallOnMessage(StringBuilder stringResult) - { - if (OnMessage != null) - RunInTask(() => OnMessage(stringResult.ToString())); - } - - private void CallOnDisconnected() - { - AVRealtime.PrintLog("PCL websocket closed without parameters."); - if (OnClosed != null) - RunInTask(() => this.OnClosed(0, "", "")); - } - - private void CallOnConnected() - { - if (OnOpened != null) - RunInTask(() => this.OnOpened()); - } - - private static void RunInTask(Action action) - { - Task.Factory.StartNew(action); - } - - public async void Close() - { - if (_ws != null) - { - try - { - await _ws.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None); - CallOnDisconnected(); - } - catch (Exception ex) - { - CallOnDisconnected(); - } - } - } - - public void Disconnect() { - _ws?.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None); - } - - public async void Open(string url, string protocol = null) - { - _uri = new Uri(url); - if (_ws.State == WebSocketState.Open || _ws.State == WebSocketState.Connecting) - { - _ws = NewWebSocket(); - } - try - { - await _ws.ConnectAsync(_uri, _cancellationToken); - CallOnConnected(); - StartListen(); - } - catch (Exception ex) - { - if (ex is ObjectDisposedException) - { - OnError($"can NOT connect server with url: {url}"); - } - } - } - - public async void Send(string message) - { - if (_ws.State != WebSocketState.Open) - { - throw new Exception("Connection is not open."); - } - - var encoded = Encoding.UTF8.GetBytes(message); - var buffer = new ArraySegment(encoded, 0, encoded.Length); - await _ws.SendAsync(buffer, WebSocketMessageType.Text, true, _cancellationToken); - } - - ClientWebSocket NewWebSocket() - { - var result = new ClientWebSocket(); - result.Options.KeepAliveInterval = TimeSpan.FromSeconds(20); - return result; - } - } -} \ No newline at end of file diff --git a/RTM/Source/Internal/WebSocket/NetFx45/WebSocketClient.NetFx45.cs b/RTM/Source/Internal/WebSocket/NetFx45/WebSocketClient.NetFx45.cs deleted file mode 100644 index dfa5ac9..0000000 --- a/RTM/Source/Internal/WebSocket/NetFx45/WebSocketClient.NetFx45.cs +++ /dev/null @@ -1,80 +0,0 @@ -using System; -using Websockets; -using System.Net.WebSockets; -using LeanCloud.Realtime.Internal; - -namespace LeanCloud.Realtime -{ - public class WebSocketClient: IWebSocketClient - { - internal readonly IWebSocketConnection connection; - public WebSocketClient() - { - Websockets.Net.WebsocketConnection.Link(); - connection = WebSocketFactory.Create(); - } - - public event Action OnClosed; - public event Action OnError; - public event Action OnLog; - - public event Action OnOpened - { - add - { - connection.OnOpened += value; - } - remove - { - connection.OnOpened -= value; - } - } - - public event Action OnMessage - { - add - { - connection.OnMessage += value; - } - remove - { - connection.OnMessage -= value; - } - } - - public bool IsOpen - { - get - { - return connection.IsOpen; - } - } - - public void Close() - { - if (connection != null) - { - connection.Close(); - } - } - - public void Open(string url, string protocol = null) - { - if (connection != null) - { - connection.Open(url, protocol); - } - } - - public void Send(string message) - { - if (connection != null) - { - if (this.IsOpen) - { - connection.Send(message); - } - } - } - } -} diff --git a/RTM/Source/Internal/WebSocket/Portable/DefaultWebSocketClient.Portable.cs b/RTM/Source/Internal/WebSocket/Portable/DefaultWebSocketClient.Portable.cs deleted file mode 100644 index 85face2..0000000 --- a/RTM/Source/Internal/WebSocket/Portable/DefaultWebSocketClient.Portable.cs +++ /dev/null @@ -1,164 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Websockets; - -namespace LeanCloud.Realtime.Internal -{ - /// - /// LeanCloud Realtime SDK for .NET Portable 内置默认的 WebSocketClient - /// - public class DefaultWebSocketClient : IWebSocketClient - { - internal IWebSocketConnection connection; - /// - /// LeanCluod .NET Realtime SDK 内置默认的 WebSocketClient - /// 开发者可以在初始化的时候指定自定义的 WebSocketClient - /// - public DefaultWebSocketClient() - { - - } - - public event Action OnClosed; - public event Action OnOpened; - public event Action OnMessage; - - public bool IsOpen - { - get - { - return connection != null && connection.IsOpen; - } - } - - public void Close() - { - if (connection != null) - { - connection.OnOpened -= Connection_OnOpened; - connection.OnMessage -= Connection_OnMessage; - connection.OnClosed -= Connection_OnClosed; - connection.OnError -= Connection_OnError; - try { - connection.Close(); - } catch (Exception e) { - AVRealtime.PrintLog(string.Format("close websocket error: {0}", e.Message)); - } - } - } - - public void Disconnect() { - connection?.Close(); - } - - public void Open(string url, string protocol = null) - { - // 在每次打开时,重新创建 WebSocket 对象 - connection = WebSocketFactory.Create(); - connection.OnOpened += Connection_OnOpened; - connection.OnMessage += Connection_OnMessage; - connection.OnClosed += Connection_OnClosed; - connection.OnError += Connection_OnError; - if (!string.IsNullOrEmpty(protocol)) - { - url = string.Format("{0}?subprotocol={1}", url, protocol); - } - connection.Open(url, protocol); - } - - private void Connection_OnOpened() - { - OnOpened?.Invoke(); - } - - private void Connection_OnMessage(string obj) - { - AVRealtime.PrintLog("websocket<=" + obj); - OnMessage?.Invoke(obj); - } - - private void Connection_OnClosed() - { - AVRealtime.PrintLog("PCL websocket closed without parameters.."); - OnClosed?.Invoke(0, "", ""); - } - - private void Connection_OnError(string obj) - { - AVRealtime.PrintLog($"PCL websocket error: {obj}"); - connection?.Close(); - } - - public void Send(string message) - { - if (connection != null) - { - if (this.IsOpen) - { - connection.Send(message); - } - else - { - var log = "Connection is NOT open when send message"; - AVRealtime.PrintLog(log); - connection?.Close(); - } - } - else { - AVRealtime.PrintLog("Connection is NULL"); - } - } - - public Task Connect(string url, string protocol = null) { - var tcs = new TaskCompletionSource(); - Action onOpen = null; - Action onClose = null; - Action onError = null; - onOpen = () => { - AVRealtime.PrintLog("PCL websocket opened"); - connection.OnOpened -= onOpen; - connection.OnClosed -= onClose; - connection.OnError -= onError; - // 注册事件 - connection.OnMessage += Connection_OnMessage; - connection.OnClosed += Connection_OnClosed; - connection.OnError += Connection_OnError; - tcs.SetResult(true); - }; - onClose = () => { - connection.OnOpened -= onOpen; - connection.OnClosed -= onClose; - connection.OnError -= onError; - tcs.SetException(new Exception("连接关闭")); - }; - onError = (err) => { - AVRealtime.PrintLog(string.Format("连接错误:{0}", err)); - connection.OnOpened -= onOpen; - connection.OnClosed -= onClose; - connection.OnError -= onError; - try { - connection.Close(); - } catch (Exception e) { - AVRealtime.PrintLog(string.Format("关闭错误的 WebSocket 异常:{0}", e.Message)); - } finally { - tcs.SetException(new Exception(string.Format("连接错误:{0}", err))); - } - }; - - // 在每次打开时,重新创建 WebSocket 对象 - connection = WebSocketFactory.Create(); - connection.OnOpened += onOpen; - connection.OnClosed += onClose; - connection.OnError += onError; - // - if (!string.IsNullOrEmpty(protocol)) { - url = string.Format("{0}?subprotocol={1}", url, protocol); - } - connection.Open(url, protocol); - return tcs.Task; - } - } -} diff --git a/RTM/Source/Internal/WebSocket/Unity/DefaultWebSocketClient.Unity.cs b/RTM/Source/Internal/WebSocket/Unity/DefaultWebSocketClient.Unity.cs deleted file mode 100644 index c0769b4..0000000 --- a/RTM/Source/Internal/WebSocket/Unity/DefaultWebSocketClient.Unity.cs +++ /dev/null @@ -1,149 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using WebSocketSharp; -using System.Threading.Tasks; - -namespace LeanCloud.Realtime.Internal -{ - - /// - /// LeanCluod Unity Realtime SDK 内置默认的 WebSocketClient - /// 开发者可以在初始化的时候指定自定义的 WebSocketClient - /// - public class DefaultWebSocketClient : IWebSocketClient - { - WebSocket ws; - public bool IsOpen - { - get - { - if (ws == null) { return false; } - return ws.IsAlive; - } - } - - public event Action OnClosed; - public event Action OnMessage - { - add - { - onMesssageCount++; - AVRealtime.PrintLog("DefaultWebSocketClient.OnMessage event add with " + onMesssageCount + " times"); - m_OnMessage += value; - - } - remove - { - onMesssageCount--; - AVRealtime.PrintLog("DefaultWebSocketClient.OnMessage event remove with " + onMesssageCount + " times"); - m_OnMessage -= value; - } - } - private Action m_OnMessage; - private int onMesssageCount = 0; - public event Action OnOpened; - - public void Close() - { - ws.CloseAsync(); - ws.OnOpen -= OnOpen; - ws.OnMessage -= OnWebSokectMessage; - ws.OnClose -= OnClose; - } - - public void Disconnect() { - ws.CloseAsync(); - } - - public void Open(string url, string protocol = null) - { - if (!string.IsNullOrEmpty(protocol)) - { - url = string.Format("{0}?subprotocol={1}", url, protocol); - } - ws = new WebSocket(url); - ws.OnOpen += OnOpen; - ws.OnMessage += OnWebSokectMessage; - ws.OnClose += OnClose; - ws.ConnectAsync(); - } - - private void OnWebSokectMessage(object sender, MessageEventArgs e) - { - AVRealtime.PrintLog("websocket<=" + e.Data); - m_OnMessage?.Invoke(e.Data); - } - - private void OnClose(object sender, CloseEventArgs e) { - AVRealtime.PrintLog(string.Format("Unity websocket closed with {0}, {1}", e.Code, e.Reason)); - OnClosed?.Invoke(e.Code, e.Reason, null); - } - - void OnWebSocketError(object sender, ErrorEventArgs e) { - AVRealtime.PrintLog($"PCL websocket error: {e.Message}"); - ws?.Close(); - } - - private void OnOpen(object sender, EventArgs e) { - OnOpened?.Invoke(); - } - - public void Send(string message) - { - ws.SendAsync(message, (b) => - { - - }); - } - - public Task Connect(string url, string protocol = null) { - var tcs = new TaskCompletionSource(); - EventHandler onOpen = null; - EventHandler onClose = null; - EventHandler onError = null; - onOpen = (sender, e) => { - AVRealtime.PrintLog("PCL websocket opened"); - ws.OnOpen -= onOpen; - ws.OnClose -= onClose; - ws.OnError -= onError; - // 注册事件 - ws.OnMessage += OnWebSokectMessage; - ws.OnClose += OnClose; - ws.OnError += OnWebSocketError; - tcs.SetResult(true); - }; - onClose = (sender, e) => { - ws.OnOpen -= onOpen; - ws.OnClose -= onClose; - ws.OnError -= onError; - tcs.SetException(new Exception("连接关闭")); - }; - onError = (sender, e) => { - AVRealtime.PrintLog(string.Format("连接错误:{0}", e.Message)); - ws.OnOpen -= onOpen; - ws.OnClose -= onClose; - ws.OnError -= onError; - try { - ws.Close(); - } catch (Exception ex) { - AVRealtime.PrintLog(string.Format("关闭错误的 WebSocket 异常:{0}", ex.Message)); - } finally { - tcs.SetException(new Exception(string.Format("连接错误:{0}", e.Message))); - } - }; - - // 在每次打开时,重新创建 WebSocket 对象 - if (!string.IsNullOrEmpty(protocol)) { - url = string.Format("{0}?subprotocol={1}", url, protocol); - } - ws = new WebSocket(url); - ws.OnOpen += onOpen; - ws.OnClose += onClose; - ws.OnError += onError; - ws.ConnectAsync(); - return tcs.Task; - } - } -} diff --git a/RTM/Source/Internal/WebSocket/Unity/websocket-sharp.dll b/RTM/Source/Internal/WebSocket/Unity/websocket-sharp.dll deleted file mode 100644 index 06740f7..0000000 Binary files a/RTM/Source/Internal/WebSocket/Unity/websocket-sharp.dll and /dev/null differ diff --git a/RTM/Source/Public/AVIMAudioMessage.cs b/RTM/Source/Public/AVIMAudioMessage.cs deleted file mode 100644 index 3c0907e..0000000 --- a/RTM/Source/Public/AVIMAudioMessage.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace LeanCloud.Realtime -{ - /// - /// Audio message. - /// - [AVIMMessageClassName("_AVIMAudioMessage")] - [AVIMTypedMessageTypeInt(-3)] - public class AVIMAudioMessage : AVIMFileMessage - { - - } - - /// - /// Video message. - /// - [AVIMMessageClassName("_AVIMVideoMessage")] - [AVIMTypedMessageTypeInt(-4)] - public class AVIMVideoMessage: AVIMFileMessage - { - - } -} diff --git a/RTM/Source/Public/AVIMBinaryMessage.cs b/RTM/Source/Public/AVIMBinaryMessage.cs deleted file mode 100644 index 103d4b3..0000000 --- a/RTM/Source/Public/AVIMBinaryMessage.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System; -using LeanCloud.Realtime.Internal; - -namespace LeanCloud.Realtime -{ - /// - /// 基于二进制数据的消息类型,可以直接发送 Byte 数组 - /// - [AVIMMessageClassName("_AVIMBinaryMessage")] - public class AVIMBinaryMessage : AVIMMessage - { - - /// - /// Initializes a new instance of the class. - /// - public AVIMBinaryMessage() - { - - } - /// - /// create new instance of AVIMBinnaryMessage - /// - /// - public AVIMBinaryMessage(byte[] data) - { - this.BinaryData = data; - } - - /// - /// Gets or sets the binary data. - /// - /// The binary data. - public byte[] BinaryData { get; set; } - - internal override MessageCommand BeforeSend(MessageCommand cmd) - { - var result = base.BeforeSend(cmd); - result = result.Binary(this.BinaryData); - return result; - } - } -} diff --git a/RTM/Source/Public/AVIMClient.cs b/RTM/Source/Public/AVIMClient.cs deleted file mode 100644 index 4715c07..0000000 --- a/RTM/Source/Public/AVIMClient.cs +++ /dev/null @@ -1,1195 +0,0 @@ -using LeanCloud; -using LeanCloud.Storage.Internal; -using LeanCloud.Realtime.Internal; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -namespace LeanCloud.Realtime -{ - /// - /// 代表一个实时通信的终端用户 - /// - public class AVIMClient - { - private readonly string clientId; - private readonly AVRealtime _realtime; - internal readonly object mutex = new object(); - internal readonly object patchMutex = new object(); - - /// - /// 一些可变的配置选项,便于应对各种需求场景 - /// - public struct Configuration - { - /// - /// Gets or sets a value indicating whether this - /// auto read. - /// - /// true if auto read; otherwise, false. - public bool AutoRead { get; set; } - } - - /// - /// Gets or sets the current configuration. - /// - /// The current configuration. - public Configuration CurrentConfiguration - { - get; set; - } - - internal AVRealtime LinkedRealtime - { - get { return _realtime; } - } - - /// - /// 单点登录所使用的 Tag - /// - public string Tag - { - get; - private set; - } - - /// - /// 客户端的标识,在一个 Application 内唯一。 - /// - public string ClientId - { - get { return clientId; } - } - - //private EventHandler m_OnNoticeReceived; - ///// - ///// 接收到服务器的命令时触发的事件 - ///// - //public event EventHandler OnNoticeReceived - //{ - // add - // { - // m_OnNoticeReceived += value; - // } - // remove - // { - // m_OnNoticeReceived -= value; - // } - //} - - private int onMessageReceivedCount = 0; - private EventHandler m_OnMessageReceived; - /// - /// 接收到聊天消息的事件通知 - /// - public event EventHandler OnMessageReceived - { - add - { - onMessageReceivedCount++; - AVRealtime.PrintLog("AVIMClient.OnMessageReceived event add with " + onMessageReceivedCount + " times"); - m_OnMessageReceived += value; - } - remove - { - onMessageReceivedCount--; - AVRealtime.PrintLog("AVIMClient.OnMessageReceived event remove with" + onMessageReceivedCount + " times"); - m_OnMessageReceived -= value; - } - } - - /// - /// Occurs when on members joined. - /// - public event EventHandler OnMembersJoined; - - /// - /// Occurs when on members left. - /// - public event EventHandler OnMembersLeft; - - /// - /// Occurs when on kicked. - /// - public event EventHandler OnKicked; - - /// - /// Occurs when on invited. - /// - public event EventHandler OnInvited; - - internal event EventHandler OnOfflineMessageReceived; - - private EventHandler m_OnSessionClosed; - /// - /// 当前打开的链接被迫关闭时触发的事件回调 - /// 可能的原因有单点登录冲突,或者被 REST API 强制踢下线 - /// - public event EventHandler OnSessionClosed - { - add - { - m_OnSessionClosed += value; - } - remove - { - m_OnSessionClosed -= value; - } - } - - /// - /// 创建 AVIMClient 对象 - /// - /// - /// - internal AVIMClient(string clientId, AVRealtime realtime) - : this(clientId, null, realtime) - { - - } - - /// - /// - /// - /// - /// - /// - internal AVIMClient(string clientId, string tag, AVRealtime realtime) - { - this.clientId = clientId; - Tag = tag ?? tag; - _realtime = realtime; - - #region sdk 强制在接收到消息之后一定要向服务端回发 ack - var ackListener = new AVIMMessageListener(); - ackListener.OnMessageReceived += AckListener_OnMessageReceieved; - //this.RegisterListener(ackListener); - #endregion - - #region 默认要为当前 client 绑定一个消息的监听器,用作消息的事件通知 - var messageListener = new AVIMMessageListener(); - messageListener.OnMessageReceived += MessageListener_OnMessageReceived; - this.RegisterListener(messageListener); - #endregion - - #region 默认要为当前 client 绑定一个 session close 的监听器,用来监测单点登录冲突的事件通知 - var sessionListener = new SessionListener(); - sessionListener.OnSessionClosed += SessionListener_OnSessionClosed; - this.RegisterListener(sessionListener); - #endregion - - #region 默认要为当前 client 监听 Ta 所出的对话中的人员变动的被动消息通知 - var membersJoinedListener = new AVIMMembersJoinListener(); - membersJoinedListener.OnMembersJoined += MembersJoinedListener_OnMembersJoined; - this.RegisterListener(membersJoinedListener); - - var membersLeftListener = new AVIMMembersLeftListener(); - membersLeftListener.OnMembersLeft += MembersLeftListener_OnMembersLeft; - this.RegisterListener(membersLeftListener); - - var invitedListener = new AVIMInvitedListener(); - invitedListener.OnInvited += InvitedListener_OnInvited; - this.RegisterListener(invitedListener); - - var kickedListener = new AVIMKickedListener(); - kickedListener.OnKicked += KickedListener_OnKicked; - this.RegisterListener(kickedListener); - #endregion - - #region 当前 client id 离线的时间内,TA 所在的对话产生的普通消息会以离线消息的方式送达到 TA 下一次登录的客户端 - var offlineMessageListener = new OfflineMessageListener(); - offlineMessageListener.OnOfflineMessageReceived += OfflineMessageListener_OnOfflineMessageReceived; - this.RegisterListener(offlineMessageListener); - #endregion - - #region 当前 client 离线期间内产生的未读消息可以通过之后调用 Conversation.SyncStateAsync 获取一下离线期间内的未读状态 - var unreadListener = new ConversationUnreadListener(); - this.RegisterListener(unreadListener); - #endregion - - #region 消息补丁(修改或者撤回) - var messagePatchListener = new MessagePatchListener(); - messagePatchListener.OnReceived = (messages) => - { - foreach (var message in messages) { - if (message is AVIMRecalledMessage) { - m_OnMessageRecalled?.Invoke(this, new AVIMMessagePatchEventArgs(message)); - } else { - m_OnMessageUpdated?.Invoke(this, new AVIMMessagePatchEventArgs(message)); - } - } - }; - this.RegisterListener(messagePatchListener); - #endregion - - #region configuration - CurrentConfiguration = new Configuration() - { - AutoRead = true, - }; - #endregion - - } - - private void OfflineMessageListener_OnOfflineMessageReceived(object sender, AVIMMessageEventArgs e) - { - if (OnOfflineMessageReceived != null) - { - OnOfflineMessageReceived(this, e); - } - this.AckListener_OnMessageReceieved(sender, e); - } - - private void KickedListener_OnKicked(object sender, AVIMOnKickedEventArgs e) - { - if (OnKicked != null) - OnKicked(this, e); - } - - private void InvitedListener_OnInvited(object sender, AVIMOnInvitedEventArgs e) - { - if (OnInvited != null) - OnInvited(this, e); - } - - private void MembersLeftListener_OnMembersLeft(object sender, AVIMOnMembersLeftEventArgs e) - { - if (OnMembersLeft != null) - OnMembersLeft(this, e); - } - - private void MembersJoinedListener_OnMembersJoined(object sender, AVIMOnMembersJoinedEventArgs e) - { - if (OnMembersJoined != null) - OnMembersJoined(this, e); - } - - private void SessionListener_OnSessionClosed(int arg1, string arg2, string arg3) - { - if (m_OnSessionClosed != null) - { - var args = new AVIMSessionClosedEventArgs() - { - Code = arg1, - Reason = arg2, - Detail = arg3 - }; - if (args.Code == 4115 || args.Code == 4111) - { - this._realtime.sessionConflict = true; - } - - m_OnSessionClosed(this, args); - } - AVRealtime.PrintLog("SessionListener_OnSessionClosed invoked."); - //this.LinkedRealtime.LogOut(); - } - - private void MessageListener_OnMessageReceived(object sender, AVIMMessageEventArgs e) - { - if (this.m_OnMessageReceived != null) - { - this.m_OnMessageReceived.Invoke(this, e); - } - this.AckListener_OnMessageReceieved(sender, e); - } - - private void AckListener_OnMessageReceieved(object sender, AVIMMessageEventArgs e) - { - lock (mutex) - { - var ackCommand = new AckCommand().MessageId(e.Message.Id) - .ConversationId(e.Message.ConversationId); - - // 在 v.2 协议下,只要在线收到消息,就默认是已读的,下次上线不会再把当前消息当做未读消息 - if (this.LinkedRealtime.CurrentConfiguration.OfflineMessageStrategy == AVRealtime.OfflineMessageStrategy.UnreadNotice) - { - ackCommand = ackCommand.ReadAck(); - } - - this.RunCommandAsync(ackCommand); - } - } - - private void UpdateUnreadNotice(object sender, AVIMMessageEventArgs e) - { - ConversationUnreadListener.UpdateNotice(e.Message); - } - - #region listener - - /// - /// 注册 IAVIMListener - /// - /// - /// - public void RegisterListener(IAVIMListener listener, Func runtimeHook = null) - { - _realtime.SubscribeNoticeReceived(listener, runtimeHook); - } - - #region get client instance - /// - /// Get the specified clientId. - /// - /// The get. - /// Client identifier. - public static AVIMClient Get(string clientId) - { - if (AVRealtime.clients == null || !AVRealtime.clients.ContainsKey(clientId)) throw new Exception(string.Format("no client found with a id in {0}", clientId)); - - return AVRealtime.clients[clientId]; - } - #endregion - - #endregion - /// - /// 创建对话 - /// - /// 对话 - /// 是否创建唯一对话,当 isUnique 为 true 时,如果当前已经有相同成员的对话存在则返回该对话,否则会创建新的对话。该值默认为 false。 - /// - internal Task CreateConversationAsync(AVIMConversation conversation, bool isUnique = true) - { - var cmd = new ConversationCommand() - .Generate(conversation) - .Unique(isUnique); - - var convCmd = cmd.Option("start") - .PeerId(clientId); - - return LinkedRealtime.AttachSignature(convCmd, LinkedRealtime.SignatureFactory.CreateStartConversationSignature(this.clientId, conversation.MemberIds)).OnSuccess(_ => - { - return this.RunCommandAsync(convCmd).OnSuccess(t => - { - var result = t.Result; - if (result.Item1 < 1) - { - var members = conversation.MemberIds.ToList(); - members.Add(ClientId); - conversation.MemberIds = members; - conversation.MergeFromPushServer(result.Item2); - } - - return conversation; - }); - }).Unwrap(); - } - - /// - /// 创建与目标成员的对话. - /// - /// 返回对话实例. - /// 目标成员. - /// 目标成员列表. - /// 对话名称. - /// 是否是系统对话. - /// 是否为暂态对话(聊天室). - /// 是否是唯一对话. - /// 自定义属性. - public Task CreateConversationAsync(string member = null, - IEnumerable members = null, - string name = "", - bool isSystem = false, - bool isTransient = false, - bool isUnique = true, - bool isTemporary = false, - int ttl = 86400, - IDictionary options = null) - { - if (member == null) member = ClientId; - var membersAsList = Concat(member, members, "创建对话时被操作的 member(s) 不可以为空。"); - var conversation = new AVIMConversation(members: membersAsList, - name: name, - isUnique: isUnique, - isSystem: isSystem, - isTransient: isTransient, - isTemporary: isTemporary, - ttl: ttl, - client: this); - if (options != null) - { - foreach (var key in options.Keys) - { - conversation[key] = options[key]; - } - } - return CreateConversationAsync(conversation, isUnique); - } - - /// - /// Creates the conversation async. - /// - /// The conversation async. - /// Builder. - public Task CreateConversationAsync(IAVIMConversatioBuilder builder) - { - var conversation = builder.Build(); - return CreateConversationAsync(conversation, conversation.IsUnique); - } - - /// - /// Gets the conversatio builder. - /// - /// The conversatio builder. - public AVIMConversationBuilder GetConversationBuilder() - { - var builder = AVIMConversationBuilder.CreateDefaultBuilder(); - builder.Client = this; - return builder; - } - - /// - /// 创建虚拟对话,对话 id 是由本地直接生成,云端根据规则消息发送给指定的 client id(s) - /// - /// - /// - /// 过期时间,默认是一天(86400 秒),单位是秒 - /// - public Task CreateTemporaryConversationAsync(string member = null, - IEnumerable members = null, int ttl = 86400) - { - if (member == null) member = ClientId; - var membersAsList = Concat(member, members, "创建对话时被操作的 member(s) 不可以为空。"); - return CreateConversationAsync(member, membersAsList, isTemporary: true, ttl: ttl); - } - - /// - /// 创建聊天室(即:暂态对话) - /// - /// 聊天室名称 - /// - public Task CreateChatRoomAsync(string chatroomName) - { - return CreateConversationAsync(name: chatroomName, isTransient: true); - } - - /// - /// 获取一个对话 - /// - /// 对话的 ID - /// 从服务器获取 - /// - public Task GetConversationAsync(string id, bool noCache = true) - { - if (!noCache) return Task.FromResult(new AVIMConversation(this) { ConversationId = id }); - else - { - return this.GetQuery().WhereEqualTo("objectId", id).FirstAsync(); - } - } - - #region send message - /// - /// 向目标对话发送消息 - /// - /// 目标对话 - /// 消息体 - /// - public Task SendMessageAsync( - AVIMConversation conversation, - IAVIMMessage message) - { - return this.SendMessageAsync(conversation, message, new AVIMSendOptions() - { - Receipt = true, - Transient = false, - Priority = 1, - Will = false, - PushData = null, - }); - } - - /// - /// 向目标对话发送消息 - /// - /// 目标对话 - /// 消息体 - /// 消息的发送选项,包含了一些特殊的标记 - /// - public Task SendMessageAsync( - AVIMConversation conversation, - IAVIMMessage message, - AVIMSendOptions options) - { - if (this.LinkedRealtime.State != AVRealtime.Status.Online) throw new Exception("未能连接到服务器,无法发送消息。"); - - var messageBody = message.Serialize(); - - message.ConversationId = conversation.ConversationId; - message.FromClientId = this.ClientId; - - var cmd = new MessageCommand() - .Message(messageBody) - .ConvId(conversation.ConversationId) - .Receipt(options.Receipt) - .Transient(options.Transient) - .Priority(options.Priority) - .Will(options.Will) - .MentionAll(message.MentionAll); - - if (message is AVIMMessage) - { - cmd = ((AVIMMessage)message).BeforeSend(cmd); - } - - if (options.PushData != null) - { - cmd = cmd.PushData(options.PushData); - } - - if (message.MentionList != null) - { - cmd = cmd.Mention(message.MentionList); - } - - var directCmd = cmd.PeerId(this.ClientId); - - return this.RunCommandAsync(directCmd).OnSuccess(t => - { - var response = t.Result.Item2; - - message.Id = response["uid"].ToString(); - message.ServerTimestamp = long.Parse(response["t"].ToString()); - - return message; - - }); - } - - - #endregion - - #region mute & unmute - /// - /// 当前用户对目标对话进行静音操作 - /// - /// - /// - public Task MuteConversationAsync(AVIMConversation conversation) - { - var convCmd = new ConversationCommand() - .ConversationId(conversation.ConversationId) - .Option("mute") - .PeerId(this.ClientId); - - return this.RunCommandAsync(convCmd); - } - /// - /// 当前用户对目标对话取消静音,恢复该对话的离线消息推送 - /// - /// - /// - public Task UnmuteConversationAsync(AVIMConversation conversation) - { - var convCmd = new ConversationCommand() - .ConversationId(conversation.ConversationId) - .Option("unmute") - .PeerId(this.ClientId); - - return this.RunCommandAsync(convCmd); - } - #endregion - - #region Conversation members operations - internal Task OperateMembersAsync(AVIMConversation conversation, string action, string member = null, IEnumerable members = null) - { - if (string.IsNullOrEmpty(conversation.ConversationId)) - { - throw new Exception("conversation id 不可以为空。"); - } - - var membersAsList = Concat(member, members, "加人或者踢人的时候,被操作的 member(s) 不可以为空。"); - - var cmd = new ConversationCommand().ConversationId(conversation.ConversationId) - .Members(membersAsList) - .Option(action) - .PeerId(clientId); - - return this.LinkedRealtime.AttachSignature(cmd, LinkedRealtime.SignatureFactory.CreateConversationSignature(conversation.ConversationId, ClientId, membersAsList, ConversationSignatureAction.Add)).OnSuccess(_ => - { - return this.RunCommandAsync(cmd).OnSuccess(t => - { - var result = t.Result; - if (!conversation.IsTransient) - { - if (conversation.MemberIds == null) conversation.MemberIds = new List(); - conversation.MemberIds = conversation.MemberIds.Concat(membersAsList); - } - return result; - }); - }).Unwrap(); - } - internal IEnumerable Concat(T single, IEnumerable collection, string exString = null) - { - List asList = null; - if (collection == null) - { - collection = new List(); - } - asList = collection.ToList(); - if (asList.Count == 0 && single == null) - { - exString = exString ?? "can not cancat a collection with a null value."; - throw new ArgumentNullException(exString); - } - asList.Add(single); - return asList; - } - - #region Join - /// - /// 当前用户加入到目标的对话中 - /// - /// 目标对话 - /// - public Task JoinAsync(AVIMConversation conversation) - { - return this.OperateMembersAsync(conversation, "add", this.ClientId); - } - #endregion - - #region Invite - /// - /// 直接将其他人加入到目标对话 - /// 被操作的人会在客户端会触发 OnInvited 事件,而已经存在于对话的用户会触发 OnMembersJoined 事件 - /// - /// 目标对话 - /// 单个的 Client Id - /// Client Id 集合 - /// - public Task InviteAsync(AVIMConversation conversation, string member = null, IEnumerable members = null) - { - return this.OperateMembersAsync(conversation, "add", member, members); - } - #endregion - - #region Left - /// - /// 当前 Client 离开目标对话 - /// 可以理解为是 QQ 群的退群操作 - /// - /// - /// 目标对话 - /// - [Obsolete("use LeaveAsync instead.")] - public Task LeftAsync(AVIMConversation conversation) - { - return this.OperateMembersAsync(conversation, "remove", this.ClientId); - } - - /// - /// Leaves the conversation async. - /// - /// The async. - /// Conversation. - public Task LeaveAsync(AVIMConversation conversation) - { - return this.OperateMembersAsync(conversation, "remove", this.ClientId); - } - #endregion - - #region Kick - /// - /// 从目标对话中剔除成员 - /// - /// 目标对话 - /// 被剔除的单个成员 - /// 被剔除的成员列表 - /// - public Task KickAsync(AVIMConversation conversation, string member = null, IEnumerable members = null) - { - return this.OperateMembersAsync(conversation, "remove", member, members); - } - #endregion - - #endregion - - #region Query && Message history && ack - - /// - /// Get conversation query. - /// - /// - public AVIMConversationQuery GetQuery() - { - return GetConversationQuery(); - } - - /// - /// Get conversation query. - /// - /// The conversation query. - public AVIMConversationQuery GetConversationQuery() - { - return new AVIMConversationQuery(this); - } - - #region load message history - - /// - /// 查询目标对话的历史消息 - /// 不支持聊天室(暂态对话) - /// - /// 目标对话 - /// 从 beforeMessageId 开始向前查询(和 beforeTimeStampPoint 共同使用,为防止某毫秒时刻有重复消息) - /// 截止到某个 afterMessageId (不包含) - /// 从 beforeTimeStampPoint 开始向前查询 - /// 拉取截止到 afterTimeStampPoint 时间戳(不包含) - /// 查询方向,默认是 1,如果是 1 表示从新消息往旧消息方向, 0 则相反,其他值无效 - /// 拉取消息条数,默认值 20 条,可设置为 1 - 1000 之间的任意整数 - /// - public Task> QueryMessageAsync(AVIMConversation conversation, - string beforeMessageId = null, - string afterMessageId = null, - DateTime? beforeTimeStampPoint = null, - DateTime? afterTimeStampPoint = null, - int direction = 1, - int limit = 20) - where T : IAVIMMessage - { - var maxLimit = 1000; - var actualLimit = limit > maxLimit ? maxLimit : limit; - var logsCmd = new AVIMCommand() - .Command("logs") - .Argument("cid", conversation.ConversationId) - .Argument("l", actualLimit); - - if (beforeMessageId != null) - { - logsCmd = logsCmd.Argument("mid", beforeMessageId); - } - - if (afterMessageId != null) - { - logsCmd = logsCmd.Argument("tmid", afterMessageId); - } - - if (beforeTimeStampPoint != null && beforeTimeStampPoint.Value != DateTime.MinValue) - { - logsCmd = logsCmd.Argument("t", beforeTimeStampPoint.Value.ToUnixTimeStamp()); - } - - if (afterTimeStampPoint != null && afterTimeStampPoint.Value != DateTime.MinValue) - { - logsCmd = logsCmd.Argument("tt", afterTimeStampPoint.Value.ToUnixTimeStamp()); - } - - if (direction == 0) - { - logsCmd = logsCmd.Argument("direction", "NEW"); - } - - var subMessageType = typeof(T); - var subTypeInteger = subMessageType == typeof(AVIMTypedMessage) ? 0 : FreeStyleMessageClassInfo.GetTypedInteger(subMessageType.GetTypeInfo()); - - if (subTypeInteger != 0) - { - logsCmd = logsCmd.Argument("lctype", subTypeInteger); - } - - return this.RunCommandAsync(logsCmd).OnSuccess(t => - { - var rtn = new List(); - var result = t.Result.Item2; - var logs = result["logs"] as List; - if (logs != null) - { - foreach (var log in logs) - { - var logMap = log as IDictionary; - if (logMap != null) - { - var msgStr = logMap["data"].ToString(); - var messageObj = AVRealtime.FreeStyleMessageClassingController.Instantiate(msgStr, logMap); - messageObj.ConversationId = conversation.ConversationId; - rtn.Add(messageObj); - } - } - } - - conversation.OnMessageLoad(rtn); - - return rtn.AsEnumerable().OfType(); - }); - } - #endregion - - - //public Task MarkAsReadAsync(string conversationId = null, string messageId = null, AVIMConversation conversation = null, AVIMMessage message = null) - //{ - // var msgId = messageId != null ? messageId : message.Id; - // var convId = conversationId != null ? conversationId : conversation.ConversationId; - // if (convId == null && msgId == null) throw new ArgumentNullException("发送已读回执的时候,必须指定 conversation id 或者 message id"); - // lock (mutex) - // { - // var ackCommand = new AckCommand() - // .ReadAck().MessageId(msgId) - // .ConversationId(convId) - // .PeerId(this.ClientId); - - // return this.RunCommandAsync(ackCommand); - // } - //} - #region 查询对话中对方的接收状态,也就是已读回执 - private Task> FetchAllReceiptTimestampsAsync(string targetClientId = null, string conversationId = null, AVIMConversation conversation = null, bool queryAllMembers = false) - { - var convId = conversationId != null ? conversationId : conversation.ConversationId; - if (convId == null) throw new ArgumentNullException("conversationId 和 conversation 不可以同时为 null"); - - var cmd = new ConversationCommand().ConversationId(convId) - .TargetClientId(targetClientId) - .QueryAllMembers(queryAllMembers) - .Option("max-read") - .PeerId(clientId); - - return this.RunCommandAsync(cmd).OnSuccess(t => - { - var result = t.Result; - long maxReadTimestamp = -1; - long maxAckTimestamp = -1; - - if (result.Item2.ContainsKey("maxReadTimestamp")) - { - long.TryParse(result.Item2["maxReadTimestamp"].ToString(), out maxReadTimestamp); - } - if (result.Item2.ContainsKey("maxAckTimestamp")) - { - long.TryParse(result.Item2["maxAckTimestamp"].ToString(), out maxAckTimestamp); - } - return new Tuple(maxAckTimestamp, maxReadTimestamp); - - }); - } - #endregion - - #region 查询对方是否在线 - /// - /// 查询对方 client Id 是否在线 - /// - /// 单个 client Id - /// 多个 client Id 集合 - /// - public Task>> PingAsync(string targetClientId = null, IEnumerable targetClientIds = null) - { - List queryIds = null; - if (targetClientIds != null) queryIds = targetClientIds.ToList(); - if (queryIds == null && string.IsNullOrEmpty(targetClientId)) throw new ArgumentNullException("必须查询至少一个 client id 的状态,targetClientId 和 targetClientIds 不可以同时为空"); - queryIds.Add(targetClientId); - - var cmd = new SessionCommand() - .SessionPeerIds(queryIds) - .Option("query"); - - return this.RunCommandAsync(cmd).OnSuccess(t => - { - var result = t.Result; - List> rtn = new List>(); - var onlineSessionPeerIds = AVDecoder.Instance.DecodeList(result.Item2["onlineSessionPeerIds"]); - foreach (var peerId in targetClientIds) - { - rtn.Add(new Tuple(peerId, onlineSessionPeerIds.Contains(peerId))); - } - return rtn.AsEnumerable(); - }); - } - #endregion - #region 获取暂态对话在线人数 - /// - /// 获取暂态对话(聊天室)在线人数,依赖缓存,并不一定 100% 与真实数据一致。 - /// - /// - /// - public Task CountOnlineClientsAsync(string chatroomId) - { - var command = new AVCommand(relativeUri: "rtm/transient_group/onlines?gid=" + chatroomId, method: "GET", - sessionToken: null, - headers: null, - data: null); - - return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).OnSuccess(t => - { - var result = t.Result.Item2; - if (result.ContainsKey("result")) - { - return int.Parse(result["result"].ToString()); - } - return -1; - }); - } - #endregion - #endregion - - #region mark as read - - /// - /// - /// - /// - /// - /// - /// - public Task ReadAsync(AVIMConversation conversation, IAVIMMessage message = null, DateTime? readAt = null) - { - var convRead = new ReadCommand.ConvRead() - { - ConvId = conversation.ConversationId, - }; - - if (message != null) - { - convRead.MessageId = message.Id; - convRead.Timestamp = message.ServerTimestamp; - } - - if (readAt != null && readAt.Value != DateTime.MinValue) - { - convRead.Timestamp = readAt.Value.ToUnixTimeStamp(); - } - - var readCmd = new ReadCommand().Conv(convRead).PeerId(this.ClientId); - - this.RunCommandAsync(readCmd); - - return Task.FromResult(true); - } - - /// - /// mark the conversation as read with conversation id. - /// - /// conversation id - /// - public Task ReadAsync(string conversationId) - { - var conv = AVIMConversation.CreateWithoutData(conversationId, this); - return this.ReadAsync(conv); - } - - /// - /// mark all conversations as read. - /// - /// - public Task ReadAllAsync() - { - var cids = ConversationUnreadListener.FindAllConvIds(); - var readCmd = new ReadCommand().ConvIds(cids).PeerId(this.ClientId); - return this.RunCommandAsync(readCmd); - } - #endregion - - #region recall & modify - - /// - /// Recalls the async. - /// - /// The async. - /// Message. - public Task RecallAsync(IAVIMMessage message) - { - var tcs = new TaskCompletionSource(); - var patchCmd = new PatchCommand().Recall(message); - RunCommandAsync(patchCmd) - .OnSuccess(t => { - var recalledMsg = new AVIMRecalledMessage(); - AVIMMessage.CopyMetaData(message, recalledMsg); - tcs.SetResult(recalledMsg); - }); - return tcs.Task; - } - - /// - /// Modifies the aysnc. - /// - /// The aysnc. - /// 要修改的消息对象 - /// 新的消息对象 - public Task UpdateAsync(IAVIMMessage oldMessage, IAVIMMessage newMessage) - { - var tcs = new TaskCompletionSource(); - var patchCmd = new PatchCommand().Modify(oldMessage, newMessage); - this.RunCommandAsync(patchCmd) - .OnSuccess(t => { - // 从旧消息对象中拷贝数据 - AVIMMessage.CopyMetaData(oldMessage, newMessage); - // 获取更新时间戳 - var response = t.Result.Item2; - if (response.TryGetValue("lastPatchTime", out object updatedAtObj) && - long.TryParse(updatedAtObj.ToString(), out long updatedAt)) { - newMessage.UpdatedAt = updatedAt; - } - tcs.SetResult(newMessage); - }); - return tcs.Task; - } - - internal EventHandler m_OnMessageRecalled; - /// - /// Occurs when on message recalled. - /// - public event EventHandler OnMessageRecalled - { - add - { - this.m_OnMessageRecalled += value; - } - remove - { - this.m_OnMessageRecalled -= value; - } - } - internal EventHandler m_OnMessageUpdated; - /// - /// Occurs when on message modified. - /// - public event EventHandler OnMessageUpdated - { - add - { - this.m_OnMessageUpdated += value; - } - remove - { - this.m_OnMessageUpdated -= value; - } - } - - #endregion - - #region log out - /// - /// 退出登录或者切换账号 - /// - /// - public Task CloseAsync() - { - var cmd = new SessionCommand().Option("close"); - return this.RunCommandAsync(cmd).ContinueWith(t => - { - m_OnSessionClosed(this, null); - }); - } - #endregion - - /// - /// Run command async. - /// - /// The command async. - /// Command. - public Task>> RunCommandAsync(AVIMCommand command) - { - command.PeerId(this.ClientId); - return this.LinkedRealtime.RunCommandAsync(command); - } - - /// - /// Run command. - /// - /// Command. - public void RunCommand(AVIMCommand command) - { - command.PeerId(this.ClientId); - this.LinkedRealtime.RunCommand(command); - } - } - - /// - /// AVIMClient extensions. - /// - public static class AVIMClientExtensions - { - /// - /// Create conversation async. - /// - /// The conversation async. - /// Client. - /// Members. - public static Task CreateConversationAsync(this AVIMClient client, IEnumerable members) - { - return client.CreateConversationAsync(members: members); - } - - public static Task CreateConversationAsync(this AVIMClient client, IEnumerable members, string conversationName) - { - return client.CreateConversationAsync(members: members, name: conversationName); - } - - /// - /// Get conversation. - /// - /// The conversation. - /// Client. - /// Conversation identifier. - public static AVIMConversation GetConversation(this AVIMClient client, string conversationId) - { - return AVIMConversation.CreateWithoutData(conversationId, client); - } - - /// - /// Join conversation async. - /// - /// The async. - /// Client. - /// Conversation identifier. - public static Task JoinAsync(this AVIMClient client, string conversationId) - { - var conversation = client.GetConversation(conversationId); - return client.JoinAsync(conversation); - } - - /// - /// Leave conversation async. - /// - /// The async. - /// Client. - /// Conversation identifier. - public static Task LeaveAsync(this AVIMClient client, string conversationId) - { - var conversation = client.GetConversation(conversationId); - return client.LeaveAsync(conversation); - } - - /// - /// Query messages. - /// - /// The message async. - /// Client. - /// Conversation. - /// Before message identifier. - /// After message identifier. - /// Before time stamp point. - /// After time stamp point. - /// Direction. - /// Limit. - public static Task> QueryMessageAsync(this AVIMClient client, - AVIMConversation conversation, - string beforeMessageId = null, - string afterMessageId = null, - DateTime? beforeTimeStampPoint = null, - DateTime? afterTimeStampPoint = null, - int direction = 1, - int limit = 20) - { - return client.QueryMessageAsync(conversation, - beforeMessageId, - afterMessageId, - beforeTimeStampPoint, - afterTimeStampPoint, - direction, - limit); - } - - /// - /// Get the chat room query. - /// - /// The chat room query. - /// Client. - public static AVIMConversationQuery GetChatRoomQuery(this AVIMClient client) - { - return client.GetQuery().WhereEqualTo("tr", true); - } - } -} diff --git a/RTM/Source/Public/AVIMConversation.cs b/RTM/Source/Public/AVIMConversation.cs deleted file mode 100644 index 1bdf1cf..0000000 --- a/RTM/Source/Public/AVIMConversation.cs +++ /dev/null @@ -1,1545 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using LeanCloud.Realtime.Internal; -using LeanCloud; -using LeanCloud.Storage.Internal; -using System.Collections; -using System.IO; - -namespace LeanCloud.Realtime -{ - /// - /// 对话 - /// - public class AVIMConversation : IEnumerable>, IAVObject - { - private DateTime? updatedAt; - - private DateTime? createdAt; - - private DateTime? lastMessageAt; - - internal DateTime? expiredAt; - - private string name; - - private AVObject convState; - - internal readonly Object mutex = new Object(); - //private readonly IDictionary estimatedData = new Dictionary(); - - internal AVIMClient _currentClient; - - IEnumerator> IEnumerable>.GetEnumerator() - { - lock (mutex) - { - return ((IEnumerable>)convState).GetEnumerator(); - } - } - - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() - { - lock (mutex) - { - return ((IEnumerable>)convState).GetEnumerator(); - } - } - - virtual public object this[string key] - { - get - { - return convState[key]; - } - set - { - convState[key] = value; - } - } - public ICollection Keys - { - get - { - lock (mutex) - { - return convState.Keys; - } - } - } - public T Get(string key) - { - return this.convState.Get(key); - } - public bool ContainsKey(string key) - { - return this.convState.ContainsKey(key); - } - - internal IDictionary EncodeAttributes() - { - var currentOperations = convState.StartSave(); - var jsonToSave = AVObject.ToJSONObjectForSaving(currentOperations); - return jsonToSave; - } - - internal void MergeFromPushServer(IDictionary json) - { - if (json.Keys.Contains("cdate")) - { - createdAt = DateTime.Parse(json["cdate"].ToString()); - updatedAt = DateTime.Parse(json["cdate"].ToString()); - json.Remove("cdate"); - } - if (json.Keys.Contains("lm")) - { - var ts = long.Parse(json["lm"].ToString()); - updatedAt = ts.ToDateTime(); - lastMessageAt = ts.ToDateTime(); - json.Remove("lm"); - } - if (json.Keys.Contains("c")) - { - Creator = json["c"].ToString(); - json.Remove("c"); - } - if (json.Keys.Contains("m")) - { - MemberIds = json["m"] as IList; - json.Remove("m"); - } - if (json.Keys.Contains("mu")) - { - MuteMemberIds = json["mu"] as IList; - json.Remove("mu"); - } - if (json.Keys.Contains("tr")) - { - IsTransient = bool.Parse(json["tr"].ToString()); - json.Remove("tr"); - } - if (json.Keys.Contains("sys")) - { - IsSystem = bool.Parse(json["sys"].ToString()); - json.Remove("sys"); - } - if (json.Keys.Contains("cid")) - { - ConversationId = json["cid"].ToString(); - json.Remove("cid"); - } - - if (json.Keys.Contains("name")) - { - Name = json["name"].ToString(); - json.Remove("name"); - } - } - - /// - /// 当前的AVIMClient,一个对话理论上只存在一个AVIMClient。 - /// - public AVIMClient CurrentClient - { - get - { - if (_currentClient == null) throw new NullReferenceException("当前对话没有关联有效的 AVIMClient。"); - return _currentClient; - } - //set - //{ - // _currentClient = value; - //} - } - /// - /// 对话的唯一ID - /// - public string ConversationId { get; internal set; } - - /// - /// 对话在全局的唯一的名字 - /// - public string Name - { - get - { - if (convState.ContainsKey("name")) - { - name = this.convState.Get("name"); - } - return name; - } - set - { - if (value == null) - this["name"] = ""; - else - { - this["name"] = value; - } - } - } - - /// - /// 对话中存在的 Client 的 ClientId 列表 - /// - public IEnumerable MemberIds { get; internal set; } - - /// - /// 对该对话静音的成员列表 - /// - /// 对该对话设置了静音的成员,将不会收到离线消息的推送。 - /// - /// - public IEnumerable MuteMemberIds { get; internal set; } - - /// - /// 对话的创建者 - /// - public string Creator { get; private set; } - - /// - /// 是否为聊天室 - /// - public bool IsTransient { get; internal set; } - - /// - /// 是否系统对话 - /// - public bool IsSystem { get; internal set; } - - /// - /// 是否是唯一对话 - /// - public bool IsUnique { get; internal set; } - - /// - /// 对话是否为虚拟对话 - /// - public bool IsTemporary { get; internal set; } - - /// - /// 对话创建的时间 - /// - public DateTime? CreatedAt - { - get - { - DateTime? nullable; - lock (this.mutex) - { - nullable = this.createdAt; - } - return nullable; - } - private set - { - lock (this.mutex) - { - this.createdAt = value; - } - } - } - - /// - /// 对话更新的时间 - /// - public DateTime? UpdatedAt - { - get - { - DateTime? nullable; - lock (this.mutex) - { - nullable = this.updatedAt; - } - return nullable; - } - private set - { - lock (this.mutex) - { - this.updatedAt = value; - } - } - } - - /// - /// 对话中最后一条消息的时间,可以用此判断对话的最后活跃时间 - /// - public DateTime? LastMessageAt - { - get - { - DateTime? nullable; - lock (this.mutex) - { - nullable = this.lastMessageAt; - } - return nullable; - } - private set - { - lock (this.mutex) - { - this.lastMessageAt = value; - } - } - } - - /// - /// 已知 id,在本地构建一个 AVIMConversation 对象 - /// - public AVIMConversation(string id) - : this(id, null) - { - - } - - /// - /// 已知 id 在本地构建一个对话 - /// - /// 对话 id - /// AVIMClient 实例,必须是登陆成功的 - public AVIMConversation(string id, AVIMClient client) : this(client) - { - this.ConversationId = id; - } - - internal AVIMConversation(AVIMClient client) - { - this._currentClient = client; - this.CurrentClient.OnMessageReceived += CurrentClient_OnMessageReceived; - } - - /// - /// AVIMConversation Build 驱动器 - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - internal AVIMConversation(AVIMConversation source = null, - string name = null, - string creator = null, - IEnumerable members = null, - IEnumerable muteMembers = null, - bool isTransient = false, - bool isSystem = false, - IEnumerable> attributes = null, - AVObject state = null, - bool isUnique = true, - bool isTemporary = false, - int ttl = 86400, - AVIMClient client = null) : - this(client) - { - convState = source != null ? source.convState : new AVObject("_Conversation"); - - - this.Name = source?.Name; - this.MemberIds = source?.MemberIds; - this.Creator = source?.Creator; - this.MuteMemberIds = source?.MuteMemberIds; - - if (!string.IsNullOrEmpty(name)) - { - this.Name = name; - } - if (!string.IsNullOrEmpty(creator)) - { - this.Creator = creator; - } - if (members != null) - { - this.MemberIds = members.ToList(); - } - if (muteMembers != null) - { - this.MuteMemberIds = muteMembers.ToList(); - } - - this.IsTransient = isTransient; - this.IsSystem = isSystem; - this.IsUnique = isUnique; - this.IsTemporary = isTemporary; - this.expiredAt = DateTime.Now + new TimeSpan(0, 0, ttl); - - if (state != null) - { - convState = state; - this.ConversationId = state.ObjectId; - this.CreatedAt = state.CreatedAt; - this.UpdatedAt = state.UpdatedAt; - this.MergeMagicFields(state.ToDictionary(x => x.Key, x => x.Value)); - } - - if (attributes != null) - { - this.MergeMagicFields(attributes.ToDictionary(x => x.Key, x => x.Value)); - } - } - - /// - /// 从本地构建一个对话 - /// - /// 对话的 objectId - /// - /// - public static AVIMConversation CreateWithoutData(string convId, AVIMClient client) - { - return new AVIMConversation(client) - { - ConversationId = convId, - }; - } - - /// - /// - /// - /// - /// - /// - public static AVIMConversation CreateWithData(IEnumerable> magicFields, AVIMClient client) - { - if (magicFields is AVObject) - { - return new AVIMConversation(state: (AVObject)magicFields, client: client); - } - return new AVIMConversation(attributes: magicFields, client: client); - } - - #region save to cloud - /// - /// 将修改保存到云端 - /// - /// - public Task SaveAsync() - { - var cmd = new ConversationCommand() - .Generate(this); - - var convCmd = cmd.Option("update") - .PeerId(this.CurrentClient.ClientId); - - return this.CurrentClient.RunCommandAsync(convCmd); - } - #endregion - - #region send message - /// - /// 向该对话发送消息。 - /// - /// 消息体 - /// 是否需要送达回执 - /// 是否是暂态消息,暂态消息不返回送达回执(ack),不保留离线消息,不触发离线推送 - /// 消息等级,默认是1,可选值还有 2 ,3 - /// 标记该消息是否为下线通知消息 - /// 如果消息的接收者已经下线了,这个字段的内容就会被离线推送到接收者 - /// 例如,一张图片消息的离线消息内容可以类似于:[您收到一条图片消息,点击查看] 这样的推送内容,参照微信的做法 - /// - /// - public Task SendMessageAsync(IAVIMMessage avMessage, - bool receipt = true, - bool transient = false, - int priority = 1, - bool will = false, - IDictionary pushData = null) - { - return this.SendMessageAsync(avMessage, new AVIMSendOptions() - { - Receipt = receipt, - Transient = transient, - Priority = priority, - Will = will, - PushData = pushData - }); - } - - /// - /// 发送消息 - /// - /// 消息体 - /// 消息的发送选项,包含了一些特殊的标记 - /// - public Task SendMessageAsync(IAVIMMessage avMessage, AVIMSendOptions options) - { - if (this.CurrentClient == null) throw new Exception("当前对话未指定有效 AVIMClient,无法发送消息。"); - return this.CurrentClient.SendMessageAsync(this, avMessage, options); - } - #endregion - - #region recall message - - #endregion - - #region message listener and event notify - - /// - /// Registers the listener. - /// - /// Listener. - public void RegisterListener(IAVIMListener listener) - { - this.CurrentClient.RegisterListener(listener, this.ConversationIdHook); - } - - internal bool ConversationIdHook(AVIMNotice notice) - { - if (!notice.RawData.ContainsKey("cid")) return false; - return notice.RawData["cid"].ToString() == this.ConversationId; - } - #endregion - - #region mute && unmute - /// - /// 当前用户针对对话做静音操作 - /// - /// - public Task MuteAsync() - { - return this.CurrentClient.MuteConversationAsync(this); - } - /// - /// 当前用户取消对话的静音,恢复该对话的离线消息推送 - /// - /// - public Task UnmuteAsync() - { - return this.CurrentClient.UnmuteConversationAsync(this); - } - #endregion - - #region 成员操作相关接口 - - /// - /// Joins the async. - /// - /// The async. - public Task JoinAsync() - { - return AddMembersAsync(CurrentClient.ClientId); - } - - - /// - /// Adds the members async. - /// - /// The members async. - /// Client identifier. - /// Client identifiers. - public Task AddMembersAsync(string clientId = null, IEnumerable clientIds = null) - { - return this.CurrentClient.InviteAsync(this, clientId, clientIds); - } - - /// - /// Removes the members async. - /// - /// The members async. - /// Client identifier. - /// Client identifiers. - public Task RemoveMembersAsync(string clientId = null, IEnumerable clientIds = null) - { - return this.CurrentClient.KickAsync(this, clientId, clientIds); - } - - /// - /// Quits the async. - /// - /// The async. - public Task QuitAsync() - { - return RemoveMembersAsync(CurrentClient.ClientId); - } - #endregion - - #region load message history - /// - /// 获取当前对话的历史消息 - /// 不支持聊天室(暂态对话) - /// - /// 从 beforeMessageId 开始向前查询(和 beforeTimeStampPoint 共同使用,为防止某毫秒时刻有重复消息) - /// 截止到某个 afterMessageId (不包含) - /// 从 beforeTimeStampPoint 开始向前查询 - /// 拉取截止到 afterTimeStampPoint 时间戳(不包含) - /// 查询方向,默认是 1,如果是 1 表示从新消息往旧消息方向, 0 则相反,其他值无效 - /// 获取的消息数量 - /// - public Task> QueryMessageAsync( - string beforeMessageId = null, - string afterMessageId = null, - DateTime? beforeTimeStampPoint = null, - DateTime? afterTimeStampPoint = null, - int direction = 1, - int limit = 20) - where T : IAVIMMessage - { - return this.CurrentClient.QueryMessageAsync(this, beforeMessageId, afterMessageId, beforeTimeStampPoint, afterTimeStampPoint, direction, limit) - .OnSuccess(t => - { - //OnMessageLoad(t.Result); - return t.Result; - }); - } - - /// - /// Gets the message query. - /// - /// The message query. - public AVIMMessageQuery GetMessageQuery() - { - return new AVIMMessageQuery(this); - } - - /// - /// Gets the message pager. - /// - /// The message pager. - public AVIMMessagePager GetMessagePager() - { - return new AVIMMessagePager(this); - } - - #endregion - - #region 字典与对象之间的转换 - internal virtual void MergeMagicFields(IDictionary data) - { - lock (this.mutex) - { - if (data.ContainsKey("objectId")) - { - this.ConversationId = (data["objectId"] as String); - data.Remove("objectId"); - } - if (data.ContainsKey("createdAt")) - { - this.CreatedAt = AVDecoder.ParseDate(data["createdAt"] as string); - data.Remove("createdAt"); - } - if (data.ContainsKey("updatedAt")) - { - this.updatedAt = AVDecoder.ParseDate(data["updatedAt"] as string); - data.Remove("updatedAt"); - } - if (data.ContainsKey("name")) - { - this.Name = (data["name"] as String); - data.Remove("name"); - } - if (data.ContainsKey("lm")) - { - this.LastMessageAt = AVDecoder.Instance.Decode(data["lm"]) as DateTime?; - data.Remove("lm"); - } - if (data.ContainsKey("m")) - { - this.MemberIds = AVDecoder.Instance.DecodeList(data["m"]); - data.Remove("m"); - } - if (data.ContainsKey("mu")) - { - this.MuteMemberIds = AVDecoder.Instance.DecodeList(data["mu"]); - data.Remove("mu"); - } - if (data.ContainsKey("c")) - { - this.Creator = data["c"].ToString(); - data.Remove("c"); - } - if (data.ContainsKey("unique")) - { - if (data["unique"] is bool) - { - this.IsUnique = (bool)data["unique"]; - } - data.Remove("unique"); - } - foreach (var kv in data) - { - this[kv.Key] = kv.Value; - } - } - } - #endregion - - #region SyncStateAsync & unread & mark as read - /// - /// sync state from server.suhc unread state .etc; - /// - /// - public Task SyncStateAsync() - { - lock (mutex) - { - var rtn = new AggregatedState(); - rtn.Unread = GetUnreadStateFromLocal(); - return Task.FromResult(rtn); - } - } - - private UnreadState _unread; - private UnreadState _lastUnreadWhenOpenSession; - public UnreadState Unread - { - get - { - _lastUnreadWhenOpenSession = GetUnreadStateFromLocal(); - - // v.2 协议,只给出上次离线之后的未读消息,本次在线的收到的消息均视为已读 - if (this.CurrentClient.LinkedRealtime.CurrentConfiguration.OfflineMessageStrategy == AVRealtime.OfflineMessageStrategy.UnreadNotice) - { - _unread = _lastUnreadWhenOpenSession; - } - else if (this.CurrentClient.LinkedRealtime.CurrentConfiguration.OfflineMessageStrategy == AVRealtime.OfflineMessageStrategy.UnreadAck) - { - if (_lastUnreadWhenOpenSession == null) _unread = new UnreadState().MergeReceived(this.Received); - else _unread = _lastUnreadWhenOpenSession.MergeReceived(this.Received); - } - - return _unread; - } - - internal set - { - _unread = value; - } - } - - private readonly object receivedMutex = new object(); - public ReceivedState Received - { - get; set; - } - public ReadState Read - { - get; set; - } - - UnreadState GetUnreadStateFromLocal() - { - lock (mutex) - { - var notice = ConversationUnreadListener.Get(this.ConversationId); - if (notice != null) - { - var unreadState = new UnreadState() - { - LastMessage = notice.LastUnreadMessage, - SyncdAt = ConversationUnreadListener.NotifTime, - Count = notice.UnreadCount - }; - return unreadState; - } - - return null; - } - } - - internal void OnMessageLoad(IEnumerable messages) - { - var lastestInCollection = messages.OrderByDescending(m => m.ServerTimestamp).FirstOrDefault(); - if (lastestInCollection != null) - { - if (CurrentClient.CurrentConfiguration.AutoRead) - { - this.ReadAsync(lastestInCollection); - } - } - } - - /// - /// mark this conversation as read - /// - /// - public Task ReadAsync(IAVIMMessage message = null, DateTime? readAt = null) - { - // 标记已读必须至少是从上一次离线产生的最后一条消息开始,否则无法计算 Count - if (_lastUnreadWhenOpenSession != null) - { - if (_lastUnreadWhenOpenSession.LastMessage != null) - { - message = _lastUnreadWhenOpenSession.LastMessage; - } - } - return this.CurrentClient.ReadAsync(this, message, readAt).OnSuccess(t => - { - Received = null; - _lastUnreadWhenOpenSession = null; - Read = new ReadState() - { - ReadAt = readAt != null ? readAt.Value.ToUnixTimeStamp() : 0, - LastMessage = message, - SyncdAt = DateTime.Now.ToUnixTimeStamp() - }; - - }); - } - - /// - /// aggregated state for the conversation - /// - public class AggregatedState - { - /// - /// Unread state - /// - public UnreadState Unread { get; internal set; } - } - - /// - /// UnreadState recoder for the conversation - /// - public class UnreadState - { - /// - /// unread count - /// - public int Count { get; internal set; } - /// - /// last unread message - /// - public IAVIMMessage LastMessage { get; internal set; } - - /// - /// last sync timestamp - /// - public long SyncdAt { get; internal set; } - - internal UnreadState MergeReceived(ReceivedState receivedState) - { - if (receivedState == null) return this; - var count = Count + receivedState.Count; - var lastMessage = this.LastMessage; - if (receivedState.LastMessage != null) - { - lastMessage = receivedState.LastMessage; - } - var syncdAt = this.SyncdAt > receivedState.SyncdAt ? this.SyncdAt : receivedState.SyncdAt; - return new UnreadState() - { - Count = count, - LastMessage = lastMessage, - SyncdAt = syncdAt - }; - } - } - - public class ReceivedState - { - public int Count { get; internal set; } - /// - /// last received message - /// - public IAVIMMessage LastMessage { get; internal set; } - - /// - /// last sync timestamp - /// - public long SyncdAt { get; internal set; } - } - - public class ReadState - { - public long ReadAt { get; set; } - public IAVIMMessage LastMessage { get; internal set; } - public long SyncdAt { get; internal set; } - } - - #endregion - - #region on client message received to update unread - private void CurrentClient_OnMessageReceived(object sender, AVIMMessageEventArgs e) - { - if (this.CurrentClient.CurrentConfiguration.AutoRead) - { - this.ReadAsync(e.Message); - return; - } - lock (receivedMutex) - { - if (this.Received == null) this.Received = new ReceivedState(); - this.Received.Count++; - this.Received.LastMessage = e.Message; - this.Received.SyncdAt = DateTime.Now.ToUnixTimeStamp(); - } - } - #endregion - } - - /// - /// AVIMConversation extensions. - /// - public static class AVIMConversationExtensions - { - - /// - /// Send message async. - /// - /// The async. - /// Conversation. - /// Message. - /// Options. - public static Task SendAsync(this AVIMConversation conversation, IAVIMMessage message, AVIMSendOptions options) - { - return conversation.SendMessageAsync(message, options); - } - - /// - /// Send message async. - /// - /// The async. - /// Conversation. - /// Message. - /// Options. - /// The 1st type parameter. - public static Task SendAsync(this AVIMConversation conversation, T message, AVIMSendOptions options) - where T : IAVIMMessage - { - return conversation.SendMessageAsync(message, options).OnSuccess(t => - { - return (T)t.Result; - }); - } - - /// - /// Send message async. - /// - /// The async. - /// Conversation. - /// Message. - /// The 1st type parameter. - public static Task SendAsync(this AVIMConversation conversation, T message) - where T : IAVIMMessage - { - return conversation.SendMessageAsync(message).OnSuccess(t => - { - return (T)t.Result; - }); - } - - /// - /// Send text message. - /// - /// The text async. - /// Conversation. - /// Text. - public static Task SendTextAsync(this AVIMConversation conversation, string text) - { - return conversation.SendAsync(new AVIMTextMessage(text)); - } - - #region Image messages - - /// - /// Send image message async. - /// - /// The image async. - /// Conversation. - /// URL. - /// Name. - /// Text title. - /// Custom attributes. - public static Task SendImageAsync(this AVIMConversation conversation, string url, string name = null, string textTitle = null, IDictionary customAttributes = null) - { - return conversation.SendFileMessageAsync(url, name, textTitle, customAttributes); - } - - /// - /// Send image message async. - /// - /// The image async. - /// Conversation. - /// File name. - /// Data. - /// MIME type. - /// Text title. - /// Meta data. - /// Custom attributes. - public static Task SendImageAsync(this AVIMConversation conversation, string fileName, Stream data, string mimeType = null, string textTitle = null, IDictionary metaData = null, IDictionary customAttributes = null) - { - return conversation.SendFileMessageAsync(fileName, data, mimeType, textTitle, metaData, customAttributes); - } - - /// - /// Send image message async. - /// - /// The image async. - /// Conversation. - /// File name. - /// Data. - /// MIME type. - /// Text title. - /// Meta data. - /// Custom attributes. - public static Task SendImageAsync(this AVIMConversation conversation, string fileName, byte[] data, string mimeType = null, string textTitle = null, IDictionary metaData = null, IDictionary customAttributes = null) - { - return conversation.SendFileMessageAsync(fileName, data, mimeType, textTitle, metaData, customAttributes); - } - #endregion - - #region audio message - - /// - /// Send audio message async. - /// - /// The audio async. - /// Conversation. - /// URL. - /// Name. - /// Text title. - /// Custom attributes. - public static Task SendAudioAsync(this AVIMConversation conversation, string url, string name = null, string textTitle = null, IDictionary customAttributes = null) - { - return conversation.SendFileMessageAsync(name, url, textTitle, customAttributes); - } - - /// - /// Send audio message async. - /// - /// The audio async. - /// Conversation. - /// File name. - /// Data. - /// MIME type. - /// Text title. - /// Meta data. - /// Custom attributes. - public static Task SendAudioAsync(this AVIMConversation conversation, string fileName, Stream data, string mimeType = null, string textTitle = null, IDictionary metaData = null, IDictionary customAttributes = null) - { - return conversation.SendFileMessageAsync(fileName, data, mimeType, textTitle, metaData, customAttributes); - } - - /// - /// Send audio message async. - /// - /// The audio async. - /// Conversation. - /// File name. - /// Data. - /// MIME type. - /// Text title. - /// Meta data. - /// Custom attributes. - public static Task SendAudioAsync(this AVIMConversation conversation, string fileName, byte[] data, string mimeType = null, string textTitle = null, IDictionary metaData = null, IDictionary customAttributes = null) - { - return conversation.SendFileMessageAsync(fileName, data, mimeType, textTitle, metaData, customAttributes); - } - #endregion - - #region video message - /// - /// Send video message async. - /// - /// The video async. - /// Conversation. - /// URL. - /// Name. - /// Text title. - /// Custom attributes. - public static Task SendVideoAsync(this AVIMConversation conversation, string url, string name = null, string textTitle = null, IDictionary customAttributes = null) - { - return conversation.SendFileMessageAsync(name, url, textTitle, customAttributes); - } - /// - /// Send video message async. - /// - /// The video async. - /// Conversation. - /// File name. - /// Data. - /// MIME type. - /// Text title. - /// Meta data. - /// Custom attributes. - public static Task SendVideoAsync(this AVIMConversation conversation, string fileName, Stream data, string mimeType = null, string textTitle = null, IDictionary metaData = null, IDictionary customAttributes = null) - { - return conversation.SendFileMessageAsync(fileName, data, mimeType, textTitle, metaData, customAttributes); - } - - /// - /// Send video message async. - /// - /// The video async. - /// Conversation. - /// File name. - /// Data. - /// MIME type. - /// Text title. - /// Meta data. - /// Custom attributes. - public static Task SendVideoAsync(this AVIMConversation conversation, string fileName, byte[] data, string mimeType = null, string textTitle = null, IDictionary metaData = null, IDictionary customAttributes = null) - { - return conversation.SendFileMessageAsync(fileName, data, mimeType, textTitle, metaData, customAttributes); - } - #endregion - - /// - /// Send file message async. - /// - /// The file message async. - /// Conversation. - /// URL. - /// Name. - /// Text title. - /// Custom attributes. - /// The 1st type parameter. - public static Task SendFileMessageAsync(this AVIMConversation conversation, string url, string name = null, string textTitle = null, IDictionary customAttributes = null) - where T : AVIMFileMessage, new() - { - var fileMessage = AVIMFileMessage.FromUrl(name, url, textTitle, customAttributes); - return conversation.SendAsync(fileMessage); - } - - /// - /// Send file message async. - /// - /// The file message async. - /// Conversation. - /// File name. - /// Data. - /// MIME type. - /// Text title. - /// Meta data. - /// Custom attributes. - /// The 1st type parameter. - public static Task SendFileMessageAsync(this AVIMConversation conversation, string fileName, Stream data, string mimeType = null, string textTitle = null, IDictionary metaData = null, IDictionary customAttributes = null) - where T : AVIMFileMessage, new() - { - var fileMessage = AVIMFileMessage.FromStream(fileName, data, mimeType, textTitle, metaData, customAttributes); - - return fileMessage.File.SaveAsync().OnSuccess(fileUploaded => - { - return conversation.SendAsync(fileMessage); - }).Unwrap(); - } - - /// - /// Send file message async. - /// - /// The file message async. - /// Conversation. - /// File name. - /// Data. - /// MIME type. - /// Text title. - /// Meta data. - /// Custom attributes. - /// The 1st type parameter. - public static Task SendFileMessageAsync(this AVIMConversation conversation, string fileName, byte[] data, string mimeType = null, string textTitle = null, IDictionary metaData = null, IDictionary customAttributes = null) - where T : AVIMFileMessage, new() - { - var fileMessage = AVIMFileMessage.FromStream(fileName, new MemoryStream(data), mimeType, textTitle, metaData, customAttributes); - - return conversation.SendFileMessageAsync(fileName, new MemoryStream(data), mimeType, textTitle, metaData, customAttributes); - } - - /// - /// Send location async. - /// - /// The location async. - /// Conversation. - /// Point. - public static Task SendLocationAsync(this AVIMConversation conversation, AVGeoPoint point) - { - var locationMessage = new AVIMLocationMessage(point); - return conversation.SendAsync(locationMessage); - } - - /// - /// Query the message async. - /// - /// The message async. - /// Conversation. - /// Before message identifier. - /// After message identifier. - /// Before time stamp. - /// After time stamp. - /// Direction. - /// Limit. - public static Task> QueryMessageAsync( - this AVIMConversation conversation, - string beforeMessageId = null, - string afterMessageId = null, - long? beforeTimeStamp = null, - long? afterTimeStamp = null, - int direction = 1, - int limit = 20) - { - - return conversation.QueryMessageAsync(beforeMessageId, - afterMessageId, - beforeTimeStamp, - afterTimeStamp, - direction, - limit); - } - - /// - /// Query message with speciafic subclassing type. - /// - /// The message async. - /// Conversation. - /// Before message identifier. - /// After message identifier. - /// Before time stamp. - /// After time stamp. - /// Direction. - /// Limit. - /// The 1st type parameter. - public static Task> QueryMessageAsync( - this AVIMConversation conversation, - string beforeMessageId = null, - string afterMessageId = null, - long? beforeTimeStamp = null, - long? afterTimeStamp = null, - int direction = 1, - int limit = 20) - where T : IAVIMMessage - { - - return conversation.QueryMessageAsync(beforeMessageId, - afterMessageId, - beforeTimeStampPoint: beforeTimeStamp.HasValue ? beforeTimeStamp.Value.ToDateTime() : DateTime.MinValue, - afterTimeStampPoint: afterTimeStamp.HasValue ? afterTimeStamp.Value.ToDateTime() : DateTime.MinValue, - direction: direction, - limit: limit); - } - - /// - /// Query message record before the given message async. - /// - /// The message before async. - /// Conversation. - /// Message. - /// Limit. - public static Task> QueryMessageBeforeAsync( - this AVIMConversation conversation, - IAVIMMessage message, - int limit = 20) - { - return conversation.QueryMessageAsync(beforeMessageId: message.Id, beforeTimeStamp: message.ServerTimestamp, limit: limit); - } - - /// - /// Query message record after the given message async. - /// - /// The message after async. - /// Conversation. - /// Message. - /// Limit. - public static Task> QueryMessageAfterAsync( - this AVIMConversation conversation, - IAVIMMessage message, - int limit = 20) - { - return conversation.QueryMessageAsync(afterMessageId: message.Id, afterTimeStamp: message.ServerTimestamp, limit: limit); - } - - /// - /// Query messages after conversation created. - /// - /// The message after async. - /// Conversation. - /// Limit. - public static Task> QueryMessageFromOldToNewAsync( - this AVIMConversation conversation, - int limit = 20) - { - return conversation.QueryMessageAsync(afterTimeStamp: conversation.CreatedAt.Value.ToUnixTimeStamp(), limit: limit); - } - - - /// - /// Query messages in interval async. - /// - /// The message interval async. - /// Conversation. - /// Start. - /// End. - /// Limit. - public static Task> QueryMessageInIntervalAsync( - this AVIMConversation conversation, - IAVIMMessage start, - IAVIMMessage end, - int limit = 20) - { - return conversation.QueryMessageAsync( - beforeMessageId: end.Id, - beforeTimeStamp: end.ServerTimestamp, - afterMessageId: start.Id, - afterTimeStamp: start.ServerTimestamp, - limit: limit); - } - - /// - /// Recall message async. - /// - /// The async. - /// Conversation. - /// Message. - public static Task RecallAsync(this AVIMConversation conversation, IAVIMMessage message) - { - return conversation.CurrentClient.RecallAsync(message); - } - - /// - /// Modifiy message async. - /// - /// The async. - /// Conversation. - /// 要修改的消息对象 - /// 新的消息对象 - public static Task UpdateAsync(this AVIMConversation conversation, IAVIMMessage oldMessage, IAVIMMessage newMessage) - { - return conversation.CurrentClient.UpdateAsync(oldMessage, newMessage); - } - } - - /// - /// AVIMConversatio builder. - /// - public interface IAVIMConversatioBuilder - { - /// - /// Build this instance. - /// - /// The build. - AVIMConversation Build(); - } - - /// - /// AVIMConversation builder. - /// - public class AVIMConversationBuilder : IAVIMConversatioBuilder - { - /// - /// Gets or sets the client. - /// - /// The client. - public AVIMClient Client { get; internal set; } - private bool isUnique; - private Dictionary properties; - - private string name; - private bool isTransient; - private bool isSystem; - private List members; - - - internal static AVIMConversationBuilder CreateDefaultBuilder() - { - return new AVIMConversationBuilder(); - } - - /// - /// Build this instance. - /// - /// The build. - public AVIMConversation Build() - { - var result = new AVIMConversation( - members: members, - name: name, - isUnique: isUnique, - isSystem: isSystem, - isTransient: isTransient, - client: Client); - - if (properties != null) - { - foreach (var key in properties.Keys) - { - result[key] = properties[key]; - } - } - - return result; - } - - /// - /// Sets the unique. - /// - /// The unique. - /// If set to true toggle. - public AVIMConversationBuilder SetUnique(bool toggle = true) - { - this.isUnique = toggle; - return this; - } - - /// - /// Sets the system. - /// - /// The system. - /// If set to true toggle. - public AVIMConversationBuilder SetSystem(bool toggle = true) - { - this.isSystem = toggle; - return this; - } - - /// - /// Sets the transient. - /// - /// The transient. - /// If set to true toggle. - public AVIMConversationBuilder SetTransient(bool toggle = true) - { - this.isTransient = toggle; - return this; - } - - /// - /// Sets the name. - /// - /// The name. - /// Name. - public AVIMConversationBuilder SetName(string name) - { - this.name = name; - return this; - } - - /// - /// Sets the members. - /// - /// The members. - /// Member client identifiers. - public AVIMConversationBuilder SetMembers(IEnumerable memberClientIds) - { - this.members = memberClientIds.ToList(); - return this; - } - - /// - /// Adds the member. - /// - /// The member. - /// Member client identifier. - public AVIMConversationBuilder AddMember(string memberClientId) - { - return AddMembers(new string[] { memberClientId }); - } - - /// - /// Adds the members. - /// - /// The members. - /// Member client identifiers. - public AVIMConversationBuilder AddMembers(IEnumerable memberClientIds) - { - if (this.members == null) this.members = new List(); - this.members.AddRange(memberClientIds); - return this; - } - - /// - /// Sets the property. - /// - /// The property. - /// Key. - /// Value. - public AVIMConversationBuilder SetProperty(string key, object value) - { - if (this.properties == null) this.properties = new Dictionary(); - this.properties[key] = value; - return this; - } - } - - /// - /// AVIMM essage emitter builder. - /// - public class AVIMMessageEmitterBuilder - { - private AVIMConversation _conversation; - /// - /// Sets the conversation. - /// - /// The conversation. - /// Conversation. - public AVIMMessageEmitterBuilder SetConversation(AVIMConversation conversation) - { - _conversation = conversation; - return this; - } - /// - /// Gets the conversation. - /// - /// The conversation. - public AVIMConversation Conversation - { - get - { - return _conversation; - } - } - - private AVIMSendOptions _sendOptions; - /// - /// Gets the send options. - /// - /// The send options. - public AVIMSendOptions SendOptions - { - get - { - return _sendOptions; - } - } - /// - /// Sets the send options. - /// - /// The send options. - /// Send options. - public AVIMMessageEmitterBuilder SetSendOptions(AVIMSendOptions sendOptions) - { - _sendOptions = sendOptions; - return this; - } - - private IAVIMMessage _message; - /// - /// Gets the message. - /// - /// The message. - public IAVIMMessage Message - { - get - { - return _message; - } - } - /// - /// Sets the message. - /// - /// The message. - /// Message. - public AVIMMessageEmitterBuilder SetMessage(IAVIMMessage message) - { - _message = message; - return this; - } - - /// - /// Send async. - /// - /// The async. - public Task SendAsync() - { - return this.Conversation.SendAsync(this.Message, this.SendOptions); - } - } -} diff --git a/RTM/Source/Public/AVIMConversationQuery.cs b/RTM/Source/Public/AVIMConversationQuery.cs deleted file mode 100644 index cbb0f5f..0000000 --- a/RTM/Source/Public/AVIMConversationQuery.cs +++ /dev/null @@ -1,181 +0,0 @@ -using LeanCloud.Realtime.Internal; -using LeanCloud.Storage.Internal; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -namespace LeanCloud.Realtime -{ - /// - /// 对话查询类 - /// - public class AVIMConversationQuery : AVQueryPair, IAVQuery - { - internal AVIMClient CurrentClient { get; set; } - internal AVIMConversationQuery(AVIMClient _currentClient) - : base() - { - CurrentClient = _currentClient; - } - - bool compact; - bool withLastMessageRefreshed; - - private AVIMConversationQuery(AVIMConversationQuery source, - IDictionary where = null, - IEnumerable replacementOrderBy = null, - IEnumerable thenBy = null, - int? skip = null, - int? limit = null, - IEnumerable includes = null, - IEnumerable selectedKeys = null, - String redirectClassNameForKey = null) - : base(source, where, replacementOrderBy, thenBy, skip, limit, includes, selectedKeys, redirectClassNameForKey) - { - - } - - /// - /// Creates the instance. - /// - /// The instance. - /// Where. - /// Replacement order by. - /// Then by. - /// Skip. - /// Limit. - /// Includes. - /// Selected keys. - /// Redirect class name for key. - public override AVIMConversationQuery CreateInstance( - IDictionary where = null, - IEnumerable replacementOrderBy = null, - IEnumerable thenBy = null, - int? skip = null, - int? limit = null, - IEnumerable includes = null, - IEnumerable selectedKeys = null, - String redirectClassNameForKey = null) - { - var rtn = new AVIMConversationQuery(this, where, replacementOrderBy, thenBy, skip, limit, includes); - rtn.CurrentClient = this.CurrentClient; - rtn.compact = this.compact; - rtn.withLastMessageRefreshed = this.withLastMessageRefreshed; - return rtn; - } - - /// - /// Withs the last message refreshed. - /// - /// The last message refreshed. - /// If set to true enabled. - public AVIMConversationQuery WithLastMessageRefreshed(bool enabled) - { - this.withLastMessageRefreshed = enabled; - return this; - } - - public AVIMConversationQuery Compact(bool enabled) - { - this.compact = enabled; - return this; - } - - - internal ConversationCommand GenerateQueryCommand() - { - var cmd = new ConversationCommand(); - - var queryParameters = this.BuildParameters(false); - if (queryParameters != null) - { - if (queryParameters.Keys.Contains("where")) - cmd.Where(queryParameters["where"]); - - if (queryParameters.Keys.Contains("skip")) - cmd.Skip(int.Parse(queryParameters["skip"].ToString())); - - if (queryParameters.Keys.Contains("limit")) - cmd.Limit(int.Parse(queryParameters["limit"].ToString())); - - if (queryParameters.Keys.Contains("sort")) - cmd.Sort(queryParameters["order"].ToString()); - } - - return cmd; - } - - public override Task CountAsync(CancellationToken cancellationToken) - { - var convCmd = this.GenerateQueryCommand(); - convCmd.Count(); - convCmd.Limit(0); - var cmd = convCmd.Option("query"); - return CurrentClient.RunCommandAsync(convCmd).OnSuccess(t => - { - var result = t.Result.Item2; - - if (result.ContainsKey("count")) - { - return int.Parse(result["count"].ToString()); - } - return 0; - }); - } - - - /// - /// 查找符合条件的对话 - /// - /// - /// - public override Task> FindAsync(CancellationToken cancellationToken) - { - var convCmd = this.GenerateQueryCommand().Option("query"); - return CurrentClient.RunCommandAsync(convCmd).OnSuccess(t => - { - var result = t.Result.Item2; - - IList rtn = new List(); - var conList = result["results"] as IList; - if (conList != null) - { - foreach (var c in conList) - { - var cData = c as IDictionary; - if (cData != null) - { - var con = AVIMConversation.CreateWithData(cData, CurrentClient); - rtn.Add(con); - } - } - } - return rtn.AsEnumerable(); - }); - } - - public override Task FirstAsync(CancellationToken cancellationToken) - { - return this.FirstOrDefaultAsync(); - } - - public override Task FirstOrDefaultAsync(CancellationToken cancellationToken) - { - var firstQuery = this.Limit(1); - return firstQuery.FindAsync().OnSuccess(t => - { - return t.Result.FirstOrDefault(); - }); - } - - public override Task GetAsync(string objectId, CancellationToken cancellationToken) - { - var idQuery = this.WhereEqualTo("objectId", objectId); - return idQuery.FirstAsync(); - } - } - -} diff --git a/RTM/Source/Public/AVIMEnumerator.cs b/RTM/Source/Public/AVIMEnumerator.cs deleted file mode 100644 index d9368bc..0000000 --- a/RTM/Source/Public/AVIMEnumerator.cs +++ /dev/null @@ -1,248 +0,0 @@ -using LeanCloud.Storage.Internal; -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using LeanCloud.Realtime.Internal; - -namespace LeanCloud.Realtime -{ - - /// - /// AVIMM essage pager. - /// - public class AVIMMessagePager - { - /// - /// Gets the query. - /// - /// The query. - public AVIMMessageQuery Query { get; private set; } - - /// - /// Gets the size of the page. - /// - /// The size of the page. - public int PageSize - { - get - { - return Query.Limit; - } - - private set - { - Query.Limit = value; - } - } - - /// - /// Gets the current message identifier flag. - /// - /// The current message identifier flag. - public string CurrentMessageIdFlag - { - get - { - return Query.StartMessageId; - } - private set - { - Query.StartMessageId = value; - } - } - - /// - /// Gets the current date time flag. - /// - /// The current date time flag. - public DateTime CurrentDateTimeFlag - { - get - { - return Query.From; - } - private set - { - Query.From = value; - } - } - - internal AVIMMessagePager() - { - - } - - /// - /// Initializes a new instance of the class. - /// - /// Conversation. - public AVIMMessagePager(AVIMConversation conversation) - : this() - { - Query = conversation.GetMessageQuery(); - PageSize = 20; - CurrentDateTimeFlag = DateTime.Now; - } - - /// - /// Sets the size of the page. - /// - /// The page size. - /// Page size. - public AVIMMessagePager SetPageSize(int pageSize) - { - PageSize = pageSize; - return this; - } - - /// - /// Previouses the async. - /// - /// The async. - public Task> PreviousAsync() - { - return Query.FindAsync().OnSuccess(t => - { - var headerMessage = t.Result.FirstOrDefault(); - if (headerMessage != null) - { - CurrentMessageIdFlag = headerMessage.Id; - CurrentDateTimeFlag = headerMessage.ServerTimestamp.ToDateTime(); - } - return t.Result; - }); - } - - /// - /// from previous to lastest. - /// - /// - public Task> NextAsync() - { - return Query.ReverseFindAsync().OnSuccess(t => - { - var tailMessage = t.Result.LastOrDefault(); - if (tailMessage != null) - { - CurrentMessageIdFlag = tailMessage.Id; - CurrentDateTimeFlag = tailMessage.ServerTimestamp.ToDateTime(); - } - return t.Result; - }); - } - } - - /// - /// history message interator. - /// - public class AVIMMessageQuery - { - /// - /// Gets or sets the convsersation. - /// - /// The convsersation. - public AVIMConversation Convsersation { get; set; } - /// - /// Gets or sets the limit. - /// - /// The limit. - public int Limit { get; set; } - /// - /// Gets or sets from. - /// - /// From. - public DateTime From { get; set; } - /// - /// Gets or sets to. - /// - /// To. - public DateTime To { get; set; } - /// - /// Gets or sets the end message identifier. - /// - /// The end message identifier. - public string EndMessageId { get; set; } - /// - /// Gets or sets the start message identifier. - /// - /// The start message identifier. - public string StartMessageId { get; set; } - - - internal AVIMMessageQuery() - { - Limit = 20; - From = DateTime.Now; - } - - /// - /// Initializes a new instance of the class. - /// - /// Conversation. - public AVIMMessageQuery(AVIMConversation conversation) - : this() - { - Convsersation = conversation; - } - - /// - /// Sets the limit. - /// - /// The limit. - /// Limit. - public AVIMMessageQuery SetLimit(int limit) - { - Limit = limit; - return this; - } - - /// - /// from lastest to previous. - /// - /// - public Task> FindAsync() - { - return FindAsync(); - } - - /// - /// from lastest to previous. - /// - /// - public Task> ReverseFindAsync() - { - return ReverseFindAsync(); - } - - /// - /// Finds the async. - /// - /// The async. - /// set direction to reverse,it means query direct is from old to new. - /// The 1st type parameter. - public Task> FindAsync(bool reverse = false) - where T : IAVIMMessage - { - return Convsersation.QueryMessageAsync( - beforeTimeStampPoint: From, - afterTimeStampPoint: To, - limit: Limit, - afterMessageId: EndMessageId, - beforeMessageId: StartMessageId, - direction: reverse ? 0 : 1); - } - - /// - /// from previous to lastest. - /// - /// - public Task> ReverseFindAsync() - where T : IAVIMMessage - { - return FindAsync(true); - } - } -} diff --git a/RTM/Source/Public/AVIMEventArgs.cs b/RTM/Source/Public/AVIMEventArgs.cs deleted file mode 100644 index 2b91b23..0000000 --- a/RTM/Source/Public/AVIMEventArgs.cs +++ /dev/null @@ -1,251 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; - -namespace LeanCloud.Realtime -{ - /// - /// - /// - public class AVIMEventArgs : EventArgs - { - public AVIMEventArgs() - { - - } - public AVIMException.ErrorCode ErrorCode { get; internal set; } - /// - /// LeanCloud 服务端发往客户端消息通知 - /// - public string Message { get; set; } - } - - public class AVIMDisconnectEventArgs : EventArgs - { - public int Code { get; private set; } - - public string Reason { get; private set; } - - public string Detail { get; private set; } - - public AVIMDisconnectEventArgs() - { - - } - public AVIMDisconnectEventArgs(int _code, string _reason, string _detail) - { - this.Code = _code; - this.Reason = _reason; - this.Detail = _detail; - } - } - - /// - /// 开始重连之后触发正在重连的事件通知,提供给监听者的事件参数 - /// - public class AVIMReconnectingEventArgs : EventArgs - { - /// - /// 是否由 SDK 内部机制启动的自动重连 - /// - public bool IsAuto { get; set; } - - /// - /// 重连的 client Id - /// - public string ClientId { get; set; } - - /// - /// 重连时使用的 SessionToken - /// - public string SessionToken { get; set; } - } - - /// - /// 重连成功之后的事件回调 - /// - public class AVIMReconnectedEventArgs : EventArgs - { - /// - /// 是否由 SDK 内部机制启动的自动重连 - /// - public bool IsAuto { get; set; } - - /// - /// 重连的 client Id - /// - public string ClientId { get; set; } - - /// - /// 重连时使用的 SessionToken - /// - public string SessionToken { get; set; } - } - - /// - /// 重连失败之后的事件回调参数 - /// - public class AVIMReconnectFailedArgs : EventArgs - { - /// - /// 是否由 SDK 内部机制启动的自动重连 - /// - public bool IsAuto { get; set; } - - /// - /// 重连的 client Id - /// - public string ClientId { get; set; } - - /// - /// 重连时使用的 SessionToken - /// - public string SessionToken { get; set; } - - /// - /// 失败的原因 - /// 0. 客户端网络断开 - /// 1. sessionToken 错误或者失效,需要重新创建 client - /// - public int FailedCode { get; set; } - } - - /// - /// AVIMM essage event arguments. - /// - public class AVIMMessageEventArgs : EventArgs - { - /// - /// Initializes a new instance of the class. - /// - /// I message. - public AVIMMessageEventArgs(IAVIMMessage iMessage) - { - Message = iMessage; - } - /// - /// Gets or sets the message. - /// - /// The message. - public IAVIMMessage Message { get; internal set; } - } - - /// - /// AVIMMessage event arguments. - /// - public class AVIMMessagePatchEventArgs : EventArgs - { - public AVIMMessagePatchEventArgs(IAVIMMessage message) - { - Message = message; - } - - /// - /// Gets or sets the message. - /// - /// The message. - public IAVIMMessage Message { get; internal set; } - } - - /// - /// AVIMT ext message event arguments. - /// - public class AVIMTextMessageEventArgs : EventArgs - { - /// - /// Initializes a new instance of the class. - /// - /// Raw. - public AVIMTextMessageEventArgs(AVIMTextMessage raw) - { - TextMessage = raw; - } - /// - /// Gets or sets the text message. - /// - /// The text message. - public AVIMTextMessage TextMessage { get; internal set; } - } - - /// - /// 当对话中有人加入时,触发 时所携带的事件参数 - /// - public class AVIMOnMembersJoinedEventArgs : EventArgs - { - /// - /// 加入到对话的 Client Id(s) - /// - public IEnumerable JoinedMembers { get; internal set; } - - /// - /// 邀请的操作人 - /// - public string InvitedBy { get; internal set; } - - /// - /// 此次操作针对的对话 Id - /// - public string ConversationId { get; internal set; } - } - - /// - /// 当对话中有人加入时,触发 AVIMMembersJoinListener 时所携带的事件参数 - /// - public class AVIMOnMembersLeftEventArgs : EventArgs - { - /// - /// 离开对话的 Client Id(s) - /// - public IEnumerable LeftMembers { get; internal set; } - - /// - /// 踢出的操作人 - /// - public string KickedBy { get; internal set; } - - /// - /// 此次操作针对的对话 Id - /// - public string ConversationId { get; internal set; } - } - /// - /// 当前用户被邀请加入到对话 - /// - public class AVIMOnInvitedEventArgs : EventArgs - { - /// - /// 邀请的操作人 - /// - public string InvitedBy { get; internal set; } - - /// - /// 此次操作针对的对话 Id - /// - public string ConversationId { get; internal set; } - } - - /// - /// 当前用户被他人从对话中踢出 - /// - public class AVIMOnKickedEventArgs : EventArgs - { - /// - /// 踢出的操作人 - /// - public string KickedBy { get; internal set; } - - /// - /// 此次操作针对的对话 Id - /// - public string ConversationId { get; internal set; } - } - - public class AVIMSessionClosedEventArgs : EventArgs - { - public int Code { get; internal set; } - - public string Reason { get; internal set; } - - public string Detail { get; internal set; } - } -} diff --git a/RTM/Source/Public/AVIMException.cs b/RTM/Source/Public/AVIMException.cs deleted file mode 100644 index f473746..0000000 --- a/RTM/Source/Public/AVIMException.cs +++ /dev/null @@ -1,235 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace LeanCloud.Realtime -{ - /// - /// 实时通信的异常 - /// - public class AVIMException : Exception - { - /// - /// 错误代码 - /// - public enum ErrorCode - { - /// - /// Error code indicating that an unknown error or an error unrelated to LeanCloud - /// occurred. - /// - OtherCause = -1, - - /// - /// 服务端错误 - /// - FromServer = 4000, - - - /// - /// websocket 连接非正常关闭,通常见于路由器配置对长连接限制的情况。SDK 会自动重连,无需人工干预。 - /// - UnknownError = 1006, - - /// - /// 应用不存在或应用禁用了实时通信服务 - /// - APP_NOT_AVAILABLE = 4100, - - - /// - /// 登录签名验证失败 - /// - SIGNATURE_FAILED = 4102, - - /// - /// Client ClientId 格式错误,超过 64 个字符。 - /// - INVALID_LOGIN = 4103, - - /// - /// Session 没有打开就发送消息,或执行其他操作。常见的错误场景是调用 open session 后直接发送消息,正确的用法是在 Session 打开的回调里执行。 - /// - SESSION_REQUIRED = 4105, - - /// - /// 读超时,服务器端长时间没有收到客户端的数据,切断连接。SDK 包装了心跳包的机制,出现此错误通常是网络问题。SDK 会自动重连,无需人工干预。 - /// - READ_TIMEOUT = 4107, - - /// - /// 登录超时,连接后长时间没有完成 session open。通常是登录被拒绝等原因,出现此问题可能是使用方式有误,可以 创建工单,由我们技术顾问来给出建议。 - /// - LOGIN_TIMEOUT = 4108, - - /// - /// 包过长。消息大小超过 5 KB,请缩短消息或者拆分消息。 - /// - FRAME_TOO_LONG = 4109, - - /// - /// 设置安全域名后,当前登录的域名与安全域名不符合。 - /// - INVALID_ORIGIN = 4110, - - - /// - /// 设置单设备登录后,客户端被其他设备挤下线。 - /// - SESSION_CONFLICT = 4111, - - /// - /// 应用容量超限,当天登录用户数已经超过应用设定的最大值。 - /// - APP_QUOTA_EXCEEDED = 4113, - - /// - /// 客户端发送的序列化数据服务器端无法解析。 - /// - UNPARSEABLE_RAW_MESSAGE = 4114, - - /// - /// 客户端被 REST API 管理接口强制下线。 - /// - KICKED_BY_APP = 4115, - - /// - /// 应用单位时间内发送消息量超过限制,消息被拒绝。 - /// - MESSAGE_SENT_QUOTA_EXCEEDED = 4116, - - /// - /// 服务器内部错误,如果反复出现请收集相关线索并 创建工单,我们会尽快解决。 - /// - INTERNAL_ERROR = 4200, - - /// - /// 通过 API 发送消息超时 - /// - SEND_MESSAGE_TIMEOUT = 4201, - - /// - /// 上游 API 调用异常,请查看报错信息了解错误详情 - /// - CONVERSATION_API_FAILED = 4301, - - /// - /// 对话相关操作签名错误 - /// - CONVERSATION_SIGNATURE_FAILED = 4302, - - /// - /// 发送消息,或邀请等操作对应的对话不存在。 - /// - CONVERSATION_NOT_FOUND = 4303, - - /// - /// 对话成员已满,不能再添加。 - /// - CONVERSATION_FULL = 4304, - - /// - /// 对话操作被应用的云引擎 Hook 拒绝 - /// - CONVERSATION_REJECTED_BY_APP = 4305, - - /// - /// 更新对话操作失败 - /// - CONVERSATION_UPDATE_FAILED = 4306, - - /// - /// 该对话为只读,不能更新或增删成员。 - /// - CONVERSATION_READ_ONLY = 4307, - - /// - /// 该对话禁止当前用户发送消息 - /// - CONVERSATION_NOT_ALLOWED = 4308, - - /// - /// 更新对话的请求被拒绝,当前用户不在对话中 - /// - CONVERSATION_UPDATE_REJECT = 4309, - - /// - /// 查询对话失败,常见于慢查询导致的超时或受其他慢查询导致的数据库响应慢 - /// - CONVERSATION_QUERY_FAILED = 4310, - - /// - /// 拉取对话消息记录失败,常见与超时的情况 - /// - CONVERSATION_LOG_FAILED = 4311, - - /// - /// 拉去对话消息记录被拒绝,当前用户不再对话中 - /// - CONVERSATION_LOG_REJECT = 4312, - - /// - /// 该功能仅对系统对话有效 - /// - SYSTEM_CONVERSATION_REQUIRED = 4313, - - - /// - /// 该功能仅对普通对话有效。 - /// - NORMAL_CONVERSATION_REQUIRED = 4314, - - - /// - /// 当前用户被加入此对话的黑名单,无法发送消息。 - /// - CONVERSATION_BLACKLISTED = 4315, - - - /// - /// 该功能仅对暂态对话有效。 - /// - TRANSIENT_CONVERSATION_REQUIRED = 4316, - - /// - /// 发送消息的对话不存在,或当前用户不在对话中 - /// - INVALID_MESSAGING_TARGET = 4401, - - /// - /// 发送的消息被应用的云引擎 Hook 拒绝 - /// - MESSAGE_REJECTED_BY_APP = 4402, - - /// - /// 客户端无法通过 WebSocket 发送数据包 - /// - CAN_NOT_EXCUTE_COMMAND = 1002, - - } - /// - /// 用户云代码返回的错误码 - /// - public int AppCode { get; private set; } - - - internal AVIMException(ErrorCode code, string message, Exception cause = null) - : base(message, cause) - { - this.Code = code; - } - - internal AVIMException(int code, int appCode, string message, Exception cause = null) - : this((ErrorCode)code, message, cause) - { - this.AppCode = appCode; - } - - /// - /// The LeanCloud error code associated with the exception. - /// - public ErrorCode Code { get; private set; } - } -} diff --git a/RTM/Source/Public/AVIMImageMessage.cs b/RTM/Source/Public/AVIMImageMessage.cs deleted file mode 100644 index 9e00b67..0000000 --- a/RTM/Source/Public/AVIMImageMessage.cs +++ /dev/null @@ -1,246 +0,0 @@ -using LeanCloud; -using LeanCloud.Storage.Internal; -using LeanCloud.Realtime.Internal; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.IO; - -namespace LeanCloud.Realtime -{ - /// - /// 图像消息 - /// - [AVIMMessageClassName("_AVIMImageMessage")] - [AVIMTypedMessageTypeInt(-2)] - public class AVIMImageMessage : AVIMFileMessage - { - - } - - /// - /// File message. - /// - [AVIMMessageClassName("_AVIMFileMessage")] - [AVIMTypedMessageTypeInt(-6)] - public class AVIMFileMessage : AVIMMessageDecorator - { - /// - /// Initializes a new instance of the class. - /// - public AVIMFileMessage() - : base(new AVIMTypedMessage()) - { - - } - - /// - /// Initializes a new instance of the class. - /// - /// Message. - public AVIMFileMessage(AVIMTypedMessage message) - : base(message) - { - - } - - /// - /// Gets or sets the file. - /// - /// The file. - public AVFile File { get; set; } - - /// - /// Froms the URL. - /// - /// The URL. - /// URL. - /// The 1st type parameter. - public static T FromUrl(string url) where T : AVIMFileMessage, new() - { - return FromUrl(string.Empty.Random(8), url, null); - } - - /// - /// From the URL. - /// - /// The URL. - /// File name. - /// External URL. - /// Text title. - /// Custom attributes. - /// The 1st type parameter. - public static T FromUrl(string fileName, string externalUrl, string textTitle, IDictionary customAttributes = null) where T : AVIMFileMessage, new() - { - T message = new T(); - message.File = new AVFile(fileName, externalUrl); - message.TextContent = textTitle; - message.MergeCustomAttributes(customAttributes); - return message; - } - - /// - /// From the stream. - /// - /// The stream. - /// File name. - /// Data. - /// MIME type. - /// Text title. - /// Meta data. - /// Custom attributes. - /// The 1st type parameter. - public static T FromStream(string fileName, Stream data, string mimeType, string textTitle, IDictionary metaData, IDictionary customAttributes = null) where T : AVIMFileMessage, new() - { - T message = new T(); - message.File = new AVFile(fileName, data, mimeType, metaData); - message.TextContent = textTitle; - message.MergeCustomAttributes(customAttributes); - return message; - } - - /// - /// Encodes the decorator. - /// - /// The decorator. - public override IDictionary EncodeDecorator() - { - if (File.Url == null) throw new InvalidOperationException("File.Url can not be null before it can be sent."); - File.MetaData["name"] = File.Name; - File.MetaData["format"] = File.MimeType; - var fileData = new Dictionary - { - { "url", File.Url.ToString()}, - { "objId", File.ObjectId }, - { "metaData", File.MetaData } - }; - - return new Dictionary - { - { AVIMProtocol.LCFILE, fileData } - }; - } - - /// - /// Deserialize the specified msgStr. - /// - /// The deserialize. - /// Message string. - public override IAVIMMessage Deserialize(string msgStr) - { - var msg = Json.Parse(msgStr) as IDictionary; - var fileData = msg[AVIMProtocol.LCFILE] as IDictionary; - string mimeType = null; - string url = null; - string name = null; - string objId = null; - IDictionary metaData = null; - if (fileData != null) - { - object metaDataObj = null; - - if (fileData.TryGetValue("metaData", out metaDataObj)) - { - metaData = metaDataObj as IDictionary; - object fileNameObj = null; - if (metaData != null) - { - if (metaData.TryGetValue("name", out fileNameObj)) - { - name = fileNameObj.ToString(); - } - } - object mimeTypeObj = null; - if (metaData != null) - { - if (metaData.TryGetValue("format", out mimeTypeObj)) - { - if (mimeTypeObj != null) - mimeType = mimeTypeObj.ToString(); - } - } - } - - object objIdObj = null; - if (fileData.TryGetValue("objId", out objIdObj)) - { - if (objIdObj != null) - objId = objIdObj.ToString(); - } - - object urlObj = null; - if (fileData.TryGetValue("url", out urlObj)) - { - url = urlObj.ToString(); - } - File = AVFile.CreateWithData(objId, name, url, metaData); - } - - return base.Deserialize(msgStr); - } - } - - /// - /// Location message. - /// - [AVIMMessageClassName("_AVIMMessageClassName")] - [AVIMTypedMessageTypeInt(-5)] - public class AVIMLocationMessage : AVIMMessageDecorator - { - /// - /// Initializes a new instance of the class. - /// - public AVIMLocationMessage() - : base(new AVIMTypedMessage()) - { - - } - - /// - /// Gets or sets the location. - /// - /// The location. - public AVGeoPoint Location { get; set; } - - public AVIMLocationMessage(AVGeoPoint location) - : this() - { - Location = location; - } - - /// - /// Encodes the decorator. - /// - /// The decorator. - public override IDictionary EncodeDecorator() - { - var locationData = new Dictionary - { - { "longitude", Location.Longitude}, - { "latitude", Location.Latitude } - }; - return new Dictionary - { - { AVIMProtocol.LCLOC, locationData } - }; - } - - /// - /// Deserialize the specified msgStr. - /// - /// The deserialize. - /// Message string. - public override IAVIMMessage Deserialize(string msgStr) - { - var msg = Json.Parse(msgStr) as IDictionary; - var locationData = msg[AVIMProtocol.LCLOC] as IDictionary; - if (locationData != null) - { - Location = new AVGeoPoint(double.Parse(locationData["latitude"].ToString()), double.Parse(locationData["longitude"].ToString())); - } - return base.Deserialize(msgStr); - } - } -} diff --git a/RTM/Source/Public/AVIMMessage.cs b/RTM/Source/Public/AVIMMessage.cs deleted file mode 100644 index 21fb38d..0000000 --- a/RTM/Source/Public/AVIMMessage.cs +++ /dev/null @@ -1,162 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using LeanCloud; -using System.Reflection; -using LeanCloud.Storage.Internal; -using System.Threading; -using System.Collections; -using LeanCloud.Realtime.Internal; - -namespace LeanCloud.Realtime -{ - /// - /// 实时消息的核心基类,它是 Json schema 消息的父类 - /// - [AVIMMessageClassName("_AVIMMessage")] - public class AVIMMessage : IAVIMMessage - { - /// - /// 默认的构造函数 - /// - public AVIMMessage() - { - - } - internal readonly object mutex = new object(); - - /// - /// 对话的Id - /// - public string ConversationId { get; set; } - - /// - /// 发送消息的 ClientId - /// - public string FromClientId { get; set; } - - /// - /// 消息在全局的唯一标识Id - /// - public string Id { get; set; } - - /// - /// 服务器端的时间戳 - /// - public long ServerTimestamp { get; set; } - - /// - /// Gets or sets the content. - /// - /// The content. - public string Content { get; set; } - - /// - /// 对方收到消息的时间戳,如果是多人聊天,那以最早收到消息的人回发的 ACK 为准 - /// - public long RcpTimestamp { get; set; } - - public long UpdatedAt { get; set; } - - internal string cmdId { get; set; } - - #region - /// - /// Gets or sets a value indicating whether this mention all. - /// - /// true if mention all; otherwise, false. - public bool MentionAll { get; set; } - - /// - /// Gets or sets the mention list. - /// - /// The mention list. - public IEnumerable MentionList { get; set; } - - #endregion - - #region register convertor for custom typed message - - /// - /// Serialize this message. - /// - /// The serialize. - public virtual string Serialize() - { - return Content; - } - - /// - /// Validate the specified msgStr. - /// - /// The validate. - /// Message string. - public virtual bool Validate(string msgStr) - { - return true; - } - - /// - /// Deserialize the specified msgStr to message subclass instance - /// - /// The deserialize. - /// Message string. - public virtual IAVIMMessage Deserialize(string msgStr) - { - Content = msgStr; - return this; - } - - internal virtual MessageCommand BeforeSend(MessageCommand cmd) - { - return cmd; - } - - internal static IAVIMMessage CopyMetaData(IAVIMMessage srcMsg, IAVIMMessage desMsg) { - if (srcMsg == null) - return desMsg; - - desMsg.ConversationId = srcMsg.ConversationId; - desMsg.FromClientId = srcMsg.FromClientId; - desMsg.Id = srcMsg.Id; - desMsg.ServerTimestamp = srcMsg.ServerTimestamp; - desMsg.RcpTimestamp = srcMsg.RcpTimestamp; - desMsg.UpdatedAt = srcMsg.UpdatedAt; - return desMsg; - } - - #endregion - } - - - /// - /// 消息的发送选项 - /// - public struct AVIMSendOptions - { - /// - /// 是否需要送达回执 - /// - public bool Receipt; - /// - /// 是否是暂态消息,暂态消息不返回送达回执(ack),不保留离线消息,不触发离线推送 - /// - public bool Transient; - /// - /// 消息的优先级,默认是1,可选值还有 2|3 - /// - public int Priority; - /// - /// 是否为 Will 类型的消息,这条消息会被缓存在服务端,一旦当前客户端下线,这条消息会被发送到对话内的其他成员 - /// - public bool Will; - - /// - /// 如果消息的接收者已经下线了,这个字段的内容就会被离线推送到接收者 - ///例如,一张图片消息的离线消息内容可以类似于:[您收到一条图片消息,点击查看] 这样的推送内容,参照微信的做法 - /// - public IDictionary PushData; - } -} diff --git a/RTM/Source/Public/AVIMMessageClassNameAttribute.cs b/RTM/Source/Public/AVIMMessageClassNameAttribute.cs deleted file mode 100644 index e4d7228..0000000 --- a/RTM/Source/Public/AVIMMessageClassNameAttribute.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace LeanCloud.Realtime -{ - [AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = false)] - public sealed class AVIMMessageClassNameAttribute: Attribute - { - public AVIMMessageClassNameAttribute(string className) - { - this.ClassName = className; - } - public string ClassName { get; private set; } - - } -} diff --git a/RTM/Source/Public/AVIMMessageFieldNameAttribute.cs b/RTM/Source/Public/AVIMMessageFieldNameAttribute.cs deleted file mode 100644 index 0e155b5..0000000 --- a/RTM/Source/Public/AVIMMessageFieldNameAttribute.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace LeanCloud.Realtime -{ - [AttributeUsage(AttributeTargets.Property, Inherited = true, AllowMultiple = false)] - public sealed class AVIMMessageFieldNameAttribute: Attribute - { - public AVIMMessageFieldNameAttribute(string fieldName) - { - FieldName = fieldName; - } - - public string FieldName { get; private set; } - } -} diff --git a/RTM/Source/Public/AVIMMessageListener.cs b/RTM/Source/Public/AVIMMessageListener.cs deleted file mode 100644 index d0d91cf..0000000 --- a/RTM/Source/Public/AVIMMessageListener.cs +++ /dev/null @@ -1,143 +0,0 @@ -using LeanCloud.Realtime.Internal; -using LeanCloud.Storage.Internal; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace LeanCloud.Realtime -{ - /// - /// 默认的消息监听器,它主要承担的指责是回执的发送与用户自定义的监听器不冲突 - /// - public class AVIMMessageListener : IAVIMListener - { - /// - /// 默认的 AVIMMessageListener 只会监听 direct 协议,但是并不会触发针对消息类型的判断的监听器 - /// - public AVIMMessageListener() - { - - } - - /// - /// Protocols the hook. - /// - /// true, if hook was protocoled, false otherwise. - /// Notice. - public virtual bool ProtocolHook(AVIMNotice notice) - { - if (notice.CommandName != "direct") return false; - if (notice.RawData.ContainsKey("offline")) return false; - return true; - } - - private EventHandler m_OnMessageReceived; - /// - /// 接收到聊天消息的事件通知 - /// - public event EventHandler OnMessageReceived - { - add - { - m_OnMessageReceived += value; - } - remove - { - m_OnMessageReceived -= value; - } - } - internal virtual void OnMessage(AVIMNotice notice) - { - if (m_OnMessageReceived != null) - { - var msgStr = notice.RawData["msg"].ToString(); - var iMessage = AVRealtime.FreeStyleMessageClassingController.Instantiate(msgStr, notice.RawData); - //var messageNotice = new AVIMMessageNotice(notice.RawData); - //var messaegObj = AVIMMessage.Create(messageNotice); - var args = new AVIMMessageEventArgs(iMessage); - m_OnMessageReceived.Invoke(this, args); - } - } - - /// - /// Ons the notice received. - /// - /// Notice. - public virtual void OnNoticeReceived(AVIMNotice notice) - { - this.OnMessage(notice); - } - - } - - /// - /// 文本消息监听器 - /// - public class AVIMTextMessageListener : IAVIMListener - { - /// - /// 构建默认的文本消息监听器 - /// - public AVIMTextMessageListener() - { - - } - - /// - /// 构建文本消息监听者 - /// - /// - public AVIMTextMessageListener(Action textMessageReceived) - { - OnTextMessageReceived += (sender, textMessage) => - { - textMessageReceived(textMessage.TextMessage); - }; - } - - private EventHandler m_OnTextMessageReceived; - public event EventHandler OnTextMessageReceived - { - add - { - m_OnTextMessageReceived += value; - } - remove - { - m_OnTextMessageReceived -= value; - } - } - - public virtual bool ProtocolHook(AVIMNotice notice) - { - if (notice.CommandName != "direct") return false; - try - { - var msg = Json.Parse(notice.RawData["msg"].ToString()) as IDictionary; - if (!msg.Keys.Contains(AVIMProtocol.LCTYPE)) return false; - var typInt = 0; - int.TryParse(msg[AVIMProtocol.LCTYPE].ToString(), out typInt); - if (typInt != -1) return false; - return true; - } - catch(ArgumentException) - { - - } - return false; - - } - - public virtual void OnNoticeReceived(AVIMNotice notice) - { - if (m_OnTextMessageReceived != null) - { - var textMessage = new AVIMTextMessage(); - textMessage.Deserialize(notice.RawData["msg"].ToString()); - m_OnTextMessageReceived(this, new AVIMTextMessageEventArgs(textMessage)); - } - } - } -} diff --git a/RTM/Source/Public/AVIMNotice.cs b/RTM/Source/Public/AVIMNotice.cs deleted file mode 100644 index 65f4053..0000000 --- a/RTM/Source/Public/AVIMNotice.cs +++ /dev/null @@ -1,57 +0,0 @@ -using LeanCloud; -using LeanCloud.Realtime.Internal; -using LeanCloud.Storage.Internal; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using System.Text; -using System.Threading.Tasks; - -namespace LeanCloud.Realtime -{ - /// - /// - /// - public interface IAVIMNotice - { - /// - /// - /// - /// - /// - AVIMNotice Restore(IDictionary estimatedData); - } - /// - /// 从服务端接受到的通知 - /// 通知泛指消息,对话信息变更(例如加人和被踢等),服务器的 ACK,消息回执等 - /// - public class AVIMNotice : EventArgs - { - /// - /// Initializes a new instance of the class. - /// - public AVIMNotice() - { - - } - - /// - /// The name of the command. - /// - public readonly string CommandName; - public readonly IDictionary RawData; - public AVIMNotice(IDictionary estimatedData) - { - this.RawData = estimatedData; - this.CommandName = estimatedData["cmd"].ToString(); - } - - public static bool IsValidLeanCloudProtocol(IDictionary estimatedData) - { - if (estimatedData == null) return false; - if (estimatedData.Count == 0) return false; - return true; - } - } -} diff --git a/RTM/Source/Public/AVIMRecalledMessage.cs b/RTM/Source/Public/AVIMRecalledMessage.cs deleted file mode 100644 index 1e863fd..0000000 --- a/RTM/Source/Public/AVIMRecalledMessage.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; - -namespace LeanCloud.Realtime { - /// - /// 撤回消息 - /// - [AVIMMessageClassName("_AVIMRecalledMessagee")] - [AVIMTypedMessageTypeInt(-127)] - public class AVIMRecalledMessage : AVIMTypedMessage { - - } -} diff --git a/RTM/Source/Public/AVIMSignature.cs b/RTM/Source/Public/AVIMSignature.cs deleted file mode 100644 index c5bd0d3..0000000 --- a/RTM/Source/Public/AVIMSignature.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace LeanCloud.Realtime -{ - /// - /// 签名 - /// - public class AVIMSignature - { - /// - /// 经过 SHA1 以及相关操作参数计算出来的加密字符串 - /// - public string SignatureContent { get; set; } - - /// - /// 服务端时间戳 - /// - public long Timestamp { get; set; } - - /// - /// 随机字符串 - /// - public string Nonce { get; set; } - - /// - /// 构造一个签名 - /// - /// - /// - /// - public AVIMSignature(string s,long t,string n) - { - this.Nonce = n; - this.SignatureContent = s; - this.Timestamp = t; - } - } -} diff --git a/RTM/Source/Public/AVIMTemporaryConversation.cs b/RTM/Source/Public/AVIMTemporaryConversation.cs deleted file mode 100644 index 1e06769..0000000 --- a/RTM/Source/Public/AVIMTemporaryConversation.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace LeanCloud.Realtime -{ - /// - /// Temporary conversation. - /// - public class AVIMTemporaryConversation : AVIMConversation - { - public DateTime ExpiredAt - { - get - { - if (expiredAt == null) - return DateTime.Now.AddDays(1); - return expiredAt.Value; - } - - set - { - expiredAt = value; - } - } - - internal AVIMTemporaryConversation(long ttl) - : base(isTemporary: true) - { - this.expiredAt = DateTime.Now.AddDays(1); - } - } - - -} diff --git a/RTM/Source/Public/AVIMTextMessage.cs b/RTM/Source/Public/AVIMTextMessage.cs deleted file mode 100644 index 7bc1d34..0000000 --- a/RTM/Source/Public/AVIMTextMessage.cs +++ /dev/null @@ -1,47 +0,0 @@ -using LeanCloud.Realtime.Internal; -using LeanCloud.Storage.Internal; -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace LeanCloud.Realtime -{ - /// - /// 纯文本信息 - /// - [AVIMMessageClassName("_AVIMTextMessage")] - [AVIMTypedMessageTypeInt(-1)] - public class AVIMTextMessage : AVIMTypedMessage - { - /// - /// 构建一个文本信息 class. - /// - public AVIMTextMessage() - { - - } - - /// - /// 文本类型标记 - /// - [Obsolete("LCType is deprecated, please use AVIMTypedMessageTypeInt instead.")] - [AVIMMessageFieldName("_lctype")] - public int LCType - { - get; set; - } - - /// - /// 构造一个纯文本信息 - /// - /// - public AVIMTextMessage(string textContent) - : this() - { - TextContent = textContent; - } - } -} diff --git a/RTM/Source/Public/AVIMTypedMessage.cs b/RTM/Source/Public/AVIMTypedMessage.cs deleted file mode 100644 index c756e1f..0000000 --- a/RTM/Source/Public/AVIMTypedMessage.cs +++ /dev/null @@ -1,205 +0,0 @@ -using LeanCloud.Storage.Internal; -using LeanCloud.Realtime.Internal; -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace LeanCloud.Realtime -{ - /// - /// - /// - [AVIMMessageClassName("_AVIMTypedMessage")] - [AVIMTypedMessageTypeInt(0)] - public class AVIMTypedMessage : AVIMMessage, IEnumerable> - { - /// - /// Initializes a new instance of the class. - /// - public AVIMTypedMessage() - { - - } - - /// - /// 文本内容 - /// - [AVIMMessageFieldName("_lctext")] - public string TextContent - { - get; set; - } - - private IDictionary estimatedData = new Dictionary(); - /// - /// Serialize this instance. - /// - /// The serialize. - public override string Serialize() - { - var result = Encode(); - var resultStr = Json.Encode(result); - this.Content = resultStr; - return resultStr; - } - - /// - /// Encode this instance. - /// - /// The encode. - public virtual IDictionary Encode() - { - var result = AVRealtime.FreeStyleMessageClassingController.EncodeProperties(this); - var encodedAttrs = PointerOrLocalIdEncoder.Instance.Encode(estimatedData); - result[AVIMProtocol.LCATTRS] = estimatedData; - return result; - } - - /// - /// Validate the specified msgStr. - /// - /// The validate. - /// Message string. - public override bool Validate(string msgStr) - { - try - { - var msg = Json.Parse(msgStr) as IDictionary; - return msg.ContainsKey(AVIMProtocol.LCTYPE); - } - catch - { - - } - return false; - } - - /// - /// Deserialize the specified msgStr. - /// - /// The deserialize. - /// Message string. - public override IAVIMMessage Deserialize(string msgStr) - { - var msg = Json.Parse(msgStr) as IDictionary; - var className = AVRealtime.FreeStyleMessageClassingController.GetClassName(this.GetType()); - var PropertyMappings = AVRealtime.FreeStyleMessageClassingController.GetPropertyMappings(className); - var messageFieldProperties = PropertyMappings.Where(prop => msg.ContainsKey(prop.Value)) - .Select(prop => Tuple.Create(ReflectionHelpers.GetProperty(this.GetType(), prop.Key), msg[prop.Value])); - - foreach (var property in messageFieldProperties) - { - property.Item1.SetValue(this, property.Item2, null); - } - - if (msg.ContainsKey(AVIMProtocol.LCATTRS)) - { - object attrs = msg[AVIMProtocol.LCATTRS]; - this.estimatedData = AVDecoder.Instance.Decode(attrs) as Dictionary; - } - - return base.Deserialize(msgStr); - } - - /// - /// Gets or sets the with the specified key. - /// - /// Key. - public virtual object this[string key] - { - get - { - if (estimatedData.TryGetValue(key, out object value)) { - return value; - } - return null; - } - set - { - estimatedData[key] = value; - } - } - - /// - /// Merges the custom attributes. - /// - /// Custom attributes. - public void MergeCustomAttributes(IDictionary customAttributes) - { - this.estimatedData = this.estimatedData.Merge(customAttributes); - } - - /// - /// Gets the enumerator. - /// - /// The enumerator. - public IEnumerator> GetEnumerator() - { - return estimatedData.GetEnumerator(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - return ((IEnumerable>)this).GetEnumerator(); - } - } - - /// - /// AVIMMessage decorator. - /// - public abstract class AVIMMessageDecorator : AVIMTypedMessage - { - /// - /// Gets or sets the message. - /// - /// The message. - public AVIMTypedMessage Message { get; set; } - - /// - /// Initializes a new instance of the class. - /// - /// Message. - protected AVIMMessageDecorator(AVIMTypedMessage message) - { - this.Message = message; - } - - /// - /// Gets or sets the content of the message. - /// - /// The content of the message. - public virtual IDictionary MessageContent { get; set; } - - /// - /// Encodes the decorated. - /// - /// The decorated. - public virtual IDictionary EncodeDecorated() - { - return Message.Encode(); - } - - /// - /// Encode this instance. - /// - /// The encode. - public override IDictionary Encode() - { - var decoratedMessageEncoded = EncodeDecorated(); - var selfEncoded = base.Encode(); - var decoratoEncoded = this.EncodeDecorator(); - var resultEncoed = decoratedMessageEncoded.Merge(selfEncoded).Merge(decoratoEncoded); - return resultEncoed; - } - - /// - /// Encodes the decorator. - /// - /// The decorator. - public abstract IDictionary EncodeDecorator(); - } - - -} diff --git a/RTM/Source/Public/AVIMTypedMessageTypeIntAttribute.cs b/RTM/Source/Public/AVIMTypedMessageTypeIntAttribute.cs deleted file mode 100644 index 49c4b76..0000000 --- a/RTM/Source/Public/AVIMTypedMessageTypeIntAttribute.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -namespace LeanCloud.Realtime -{ - [AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = false)] - public sealed class AVIMTypedMessageTypeIntAttribute : Attribute - { - public AVIMTypedMessageTypeIntAttribute(int typeInt) - { - this.TypeInteger = typeInt; - } - - public int TypeInteger { get; private set; } - } -} diff --git a/RTM/Source/Public/AVRealtime.cs b/RTM/Source/Public/AVRealtime.cs deleted file mode 100644 index 49bd9ec..0000000 --- a/RTM/Source/Public/AVRealtime.cs +++ /dev/null @@ -1,1282 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Linq.Expressions; -using System.Text; -using System.Threading.Tasks; -using LeanCloud; -using System.Reflection; -using LeanCloud.Realtime.Internal; -using LeanCloud.Storage.Internal; -using System.Threading; - -#if UNITY -using UnityEngine; -#endif -namespace LeanCloud.Realtime -{ - - /// - /// 实时消息的框架类 - /// 包含了 WebSocket 连接以及事件通知的管理 - /// - public class AVRealtime - { - internal static IDictionary clients = null; - - private static readonly object mutex = new object(); - private string _wss; - private string _secondaryWss; - private string _sesstionToken; - private long _sesstionTokenExpire; - private string _clientId; - private string _deviceId; - private bool _secure; - private string _tag; - private string subprotocolPrefix = "lc.json."; - - static readonly int RECONNECT_DELAY = 5 * 1000; - static readonly int RECONNECT_USE_SECONDARY_TIMES = 6; - static readonly int RECONNECT_FROM_APP_ROUTER = 12; - - int reconnectTimes; - - public bool IsSesstionTokenExpired - { - get - { - return DateTime.Now.ToUnixTimeStamp() > _sesstionTokenExpire; - } - } - - - - private IAVIMCommandRunner avIMCommandRunner; - - - /// - /// - /// - public IAVIMCommandRunner AVIMCommandRunner - { - get - { - lock (mutex) - { - avIMCommandRunner = avIMCommandRunner ?? new AVIMCommandRunner(this.AVWebSocketClient); - return avIMCommandRunner; - } - } - } - - private IWebSocketClient webSocketController; - internal IWebSocketClient AVWebSocketClient - { - get - { - lock (mutex) - { - webSocketController = webSocketController ?? new DefaultWebSocketClient(); - return webSocketController; - } - } - set - { - lock (mutex) - { - webSocketController = value; - } - } - } - - internal static IAVRouterController RouterController - { - get - { - return AVIMCorePlugins.Instance.RouterController; - } - } - - internal static IFreeStyleMessageClassingController FreeStyleMessageClassingController - { - get - { - return AVIMCorePlugins.Instance.FreeStyleClassingController; - } - } - - /// - /// - /// - public event EventHandler OnOfflineMessageReceived; - - /// - /// 与云端通讯的状态 - /// - public enum Status - { - /// - /// 未初始化 - /// - None = -1, - - /// - /// 正在连接 - /// - Connecting = 0, - - /// - /// 已连接 - /// - Online = 1, - - /// - /// 连接已断开 - /// - Offline = 2, - - /// - /// 正在重连 - /// - Reconnecting = 3, - - /// - /// websocket 连接已被打开 - /// - Opened = 98, - - /// - /// 已主动关闭 - /// - Closed = 99, - } - - private AVRealtime.Status state = Status.None; - public AVRealtime.Status State - { - get - { - return state; - } - private set - { - state = value; - } - } - - private struct NetworkStateOptions - { - public bool Available { get; set; } - } - - private NetworkStateOptions NetworkState { get; set; } - - private struct WebSocketStateOptions - { - public int ClosedCode { get; set; } - } - - private WebSocketStateOptions WebSocketState { get; set; } - - /// - /// - /// - public struct AVIMReconnectOptions - { - /// - /// 重连的时间间隔,单位是秒 - /// - public long Interval { get; set; } - - /// - /// 重连的次数 - /// - public int Retry { get; set; } - } - - internal string Subprotocol - { - get - { - return subprotocolPrefix + (int)CurrentConfiguration.OfflineMessageStrategy; - } - } - - /// - /// 重连选项 - /// - public AVIMReconnectOptions ReconnectOptions { get; set; } - - private ISignatureFactory _signatureFactory; - - /// - /// 签名接口 - /// - public ISignatureFactory SignatureFactory - { - get - { - _signatureFactory = _signatureFactory ?? new DefaulSiganatureFactory(); - return _signatureFactory; - } - set - { - _signatureFactory = value; - } - } - - private bool useLeanEngineSignaturFactory; - /// - /// 启用 LeanEngine 云函数签名 - /// - public void UseLeanEngineSignatureFactory() - { - useLeanEngineSignaturFactory = true; - this.SignatureFactory = new LeanEngineSignatureFactory(); - } - - private EventHandler m_OnDisconnected; - /// - /// 连接断开触发的事件 - /// 如果其他客户端使用了相同的 Tag 登录,就会导致当前用户被服务端断开 - /// - public event EventHandler OnDisconnected - { - add - { - m_OnDisconnected += value; - } - remove - { - m_OnDisconnected -= value; - } - } - - private EventHandler m_OnReconnecting; - /// - /// 正在重连时触发的事件 - /// - public event EventHandler OnReconnecting - { - add - { - m_OnReconnecting += value; - } - remove - { - m_OnReconnecting -= value; - } - } - - private EventHandler m_OnReconnected; - /// - /// 重连之后触发的事件 - /// - public event EventHandler OnReconnected - { - add - { - m_OnReconnected += value; - } - remove - { - m_OnReconnected -= value; - } - } - - private EventHandler m_OnReconnectFailed; - - /// - /// 重连失败之后触发的事件 - /// - public event EventHandler OnReconnectFailed - { - add - { - m_OnReconnectFailed += value; - } - remove - { - m_OnReconnectFailed -= value; - } - } - - /// - /// Invokes the state of the network. - /// - /// If set to true broken. - internal void InvokeNetworkState(bool available = false) - { - if (this.NetworkState.Available == available) return; - SetNetworkState(available); - PrintLog(string.Format("network connectivity is {0} now", available)); - // 如果断线产生的原因是客户端掉线而不是服务端踢下线,则应该开始自动重连 - var reasonShouldReconnect = new int[] { 0, 1006, 4107 }; - if (this.NetworkState.Available && reasonShouldReconnect.Contains(this.WebSocketState.ClosedCode)) - { - StartAutoReconnect(); - } - } - - internal void SetNetworkState(bool available = true) - { - this.NetworkState = new NetworkStateOptions() - { - Available = available - }; - } - - private EventHandler m_NoticeReceived; - public event EventHandler NoticeReceived - { - add - { - m_NoticeReceived += value; - } - remove - { - m_NoticeReceived -= value; - } - } - - private void WebSocketClient_OnMessage(string obj) - { - try - { - var estimatedData = Json.Parse(obj) as IDictionary; - var validator = AVIMNotice.IsValidLeanCloudProtocol(estimatedData); - if (validator) - { - var notice = new AVIMNotice(estimatedData); - m_NoticeReceived?.Invoke(this, notice); - } - } - catch (Exception ex) - { - if (ex.InnerException != null) - { - PrintLog(ex.InnerException.Source); - } - if (ex.Source != null) - { - PrintLog(ex.Source); - } - - PrintLog(ex.Message); - } - } - - /// - /// 设定监听者 - /// - /// - /// - public void SubscribeNoticeReceived(IAVIMListener listener, Func runtimeHook = null) - { - this.NoticeReceived += new EventHandler((sender, notice) => - { - var approved = runtimeHook == null ? listener.ProtocolHook(notice) : runtimeHook(notice) && listener.ProtocolHook(notice); - if (approved) - { - listener.OnNoticeReceived(notice); - } - }); - } - - /// - /// 初始化配置项 - /// - public struct Configuration - { - /// - /// 签名工厂 - /// - public ISignatureFactory SignatureFactory { get; set; } - /// - /// 自定义 WebSocket 客户端 - /// - public IWebSocketClient WebSocketClient { get; set; } - /// - /// LeanCloud App Id - /// - public string ApplicationId { get; set; } - /// - /// LeanCloud App Key - /// - public string ApplicationKey { get; set; } - - /// - /// 登录的时候告知服务器,本次登录所使用的离线消息策略 - /// - public OfflineMessageStrategy OfflineMessageStrategy { get; set; } - } - - /// - ///登录时的离线消息下发策略 - /// - public enum OfflineMessageStrategy - { - /// - /// 服务器将所有离线消息一次性在登录之后马上下发下来 - /// - Default = 1, - - /// - /// 不再下发未读消息,而是下发对话的未读通知,告知客户端有哪些对话处于未读状态 - /// - [Obsolete("该策略已被废弃,请使用 UnreadAck")] - UnreadNotice = 2, - - /// - /// ack 和 read 分离, ack 不会清理未读消息 - /// - UnreadAck = 3 - } - - /// - /// 当前配置 - /// - public Configuration CurrentConfiguration { get; internal set; } - /// - /// 初始化实时消息客户端 - /// - /// - public AVRealtime(Configuration config) - { - lock (mutex) - { - if ((int)config.OfflineMessageStrategy == 0) - { - config.OfflineMessageStrategy = OfflineMessageStrategy.UnreadAck; - } - - CurrentConfiguration = config; - if (CurrentConfiguration.WebSocketClient != null) - { - webSocketController = CurrentConfiguration.WebSocketClient; - } - if (CurrentConfiguration.SignatureFactory != null) - { - this.SignatureFactory = CurrentConfiguration.SignatureFactory; - } - ReconnectOptions = new AVIMReconnectOptions() - { - Interval = 5, - Retry = 120 - }; - - - RegisterMessageType(); - RegisterMessageType(); - RegisterMessageType(); - RegisterMessageType(); - RegisterMessageType(); - RegisterMessageType(); - RegisterMessageType(); - RegisterMessageType(); - RegisterMessageType(); - - // 注册服务端 goaway 指令 - var goAwayListener = new GoAwayListener(); - goAwayListener.OnGoAway += () => { - RouterController.ClearCache().ContinueWith(_ => { - reborn = true; - // 关闭 WebSocket - AVWebSocketClient.Disconnect(); - }); - }; - SubscribeNoticeReceived(goAwayListener); - - reconnectTimes = 0; - } - } - - /// - /// 初始化实时消息客户端 - /// - /// - /// - public AVRealtime(string applicationId, string applicationKey) - : this(new Configuration() - { - ApplicationId = applicationId, - ApplicationKey = applicationKey, - OfflineMessageStrategy = OfflineMessageStrategy.UnreadAck - }) - { - - } - - #region websocket log - internal static Action LogTracker { get; private set; } - /// - /// 打开 WebSocket 日志 - /// - /// - public static void WebSocketLog(Action trace) - { - LogTracker = trace; - } - public static void PrintLog(string log) - { - if (AVRealtime.LogTracker != null) - { - AVRealtime.LogTracker(log); - } - } - #endregion - - /// - /// 创建 Client - /// - /// - /// - /// 设备唯一的 Id。如果是 iOS 设备,需要将 iOS 推送使用的 DeviceToken 作为 deviceId 传入 - /// 是否强制加密 wss 链接 - /// - /// - public Task CreateClientAsync(string clientId, - string tag = null, - string deviceId = null, - bool secure = true, - CancellationToken cancellationToken = default(CancellationToken)) - { - lock (mutex) - { - var client = PreLogIn(clientId, tag, deviceId); - - AVRealtime.PrintLog("begin OpenAsync."); - return OpenAsync(secure, Subprotocol, true, cancellationToken).OnSuccess(t => - { - if (!t.Result) - { - return Task.FromResult(null); - } - AVRealtime.PrintLog("websocket server connected, begin to open sesstion."); - SetNetworkState(); - var cmd = new SessionCommand() - .UA(VersionString) - .Tag(tag) - .DeviceId(deviceId) - .Option("open") - .PeerId(clientId); - - ToggleNotification(true); - return AttachSignature(cmd, this.SignatureFactory.CreateConnectSignature(clientId)); - - }).Unwrap().OnSuccess(x => - { - var cmd = x.Result; - if (cmd == null) - { - return Task.FromResult>>(null); - } - return this.RunCommandAsync(cmd); - }).Unwrap().OnSuccess(s => - { - if (s.Result == null) - { - return null; - } - AVRealtime.PrintLog("sesstion opened."); - state = Status.Online; - ToggleHeartBeating(true); - var response = s.Result.Item2; - if (response.ContainsKey("st")) - { - _sesstionToken = response["st"] as string; - } - if (response.ContainsKey("stTtl")) - { - var stTtl = long.Parse(response["stTtl"].ToString()); - _sesstionTokenExpire = DateTime.Now.ToUnixTimeStamp() + stTtl * 1000; - } - AfterLogIn(client); - return client; - }); - } - } - - - - /// - /// Creates the client async. - /// - /// The client async. - /// User. - /// Tag. - /// Device identifier. - /// If set to true secure. - public Task CreateClientAsync(AVUser user = null, - string tag = null, - string deviceId = null, - bool secure = true, - CancellationToken cancellationToken = default(CancellationToken)) - { - AVIMClient client = null; - AVRealtime.PrintLog("begin OpenAsync."); - return OpenAsync(secure, Subprotocol, true, cancellationToken).OnSuccess(openTask => - { - AVRealtime.PrintLog("OpenAsync OnSuccess. begin send open sesstion cmd."); - var userTask = Task.FromResult(user); - if (user == null) - userTask = AVUser.GetCurrentUserAsync(); - - return userTask; - }).Unwrap().OnSuccess(u => - { - var theUser = u.Result; - return AVCloud.RequestRealtimeSignatureAsync(theUser); - }).Unwrap().OnSuccess(signTask => - { - var signResult = signTask.Result; - var clientId = signResult.ClientId; - var nonce = signResult.Nonce; - var singnature = signResult.Signature; - var ts = signResult.Timestamp; - - client = PreLogIn(clientId, tag, deviceId); - ToggleNotification(true); - return this.OpenSessionAsync(clientId, tag, deviceId, nonce, ts, singnature, secure); - }).Unwrap().OnSuccess(s => - { - ToggleHeartBeating(true); - AfterLogIn(client); - return client; - }); - } - - #region pre-login - internal AVIMClient PreLogIn(string clientId, - string tag = null, - string deviceId = null) - { - var client = new AVIMClient(clientId, tag, this); - if (this.OnOfflineMessageReceived != null) - { - client.OnOfflineMessageReceived += this.OnOfflineMessageReceived; - } - _clientId = clientId; - _tag = tag; - _deviceId = deviceId; - if (_tag != null) - { - if (deviceId == null) - throw new ArgumentNullException(deviceId, "当 tag 不为空时,必须传入当前设备不变的唯一 id(deviceId)"); - } - - if (string.IsNullOrEmpty(clientId)) throw new Exception("当前 ClientId 为空,无法登录服务器。"); - - return client; - } - - internal void AfterLogIn(AVIMClient client) - { - if (clients == null) clients = new Dictionary(); - client.OnSessionClosed += (sender, e) => { - string clientId = (sender as AVIMClient).ClientId; - clients.Remove(clientId); - if (clients.Count == 0) { - LogOut(); - } - }; - clients[client.ClientId] = client; - } - - #endregion - - #region after-login - - - #endregion - - /// - /// 创建 Client - /// - /// - /// - /// 设备唯一的 Id。如果是 iOS 设备,需要将 iOS 推送使用的 DeviceToken 作为 deviceId 传入 - /// 是否强制加密 wss 链接 - /// - /// - [Obsolete("CreateClient is deprecated, please use CreateClientAsync instead.")] - public Task CreateClient( - string clientId, - string tag = null, - string deviceId = null, - bool secure = true, - CancellationToken cancellationToken = default(CancellationToken)) - { - return this.CreateClientAsync(clientId, tag, deviceId, secure, cancellationToken); - } - - private bool _listening = false; - /// - /// websocket 事件的监听的开关 - /// - /// 是否打开 - public void ToggleNotification(bool toggle) - { - AVRealtime.PrintLog("ToggleNotification| toggle:" + toggle + "|listening: " + _listening); - if (toggle && !_listening) - { - AVWebSocketClient.OnClosed += WebsocketClient_OnClosed; - AVWebSocketClient.OnMessage += WebSocketClient_OnMessage; - _listening = true; - } - else if (!toggle && _listening) - { - AVWebSocketClient.OnClosed -= WebsocketClient_OnClosed; - AVWebSocketClient.OnMessage -= WebSocketClient_OnMessage; - _listening = false; - } - } - - //public void ToggleOfflineNotification(bool toggle) - //{ - // if (toggle) - // { - // PCLWebsocketClient.OnMessage += WebSocketClient_OnMessage_On_Session_Opening; - // } - // else - // { - // PCLWebsocketClient.OnMessage -= WebSocketClient_OnMessage_On_Session_Opening; - // } - //} - - //private void WebSocketClient_OnMessage_On_Session_Opening(string obj) - //{ - // AVRealtime.PrintLog("offline<=" + obj); - //} - - - string _beatPacket = "{}"; - bool _heartBeatingToggle = true; - IAVTimer _heartBeatingTimer; - /// - /// 主动发送心跳包 - /// - /// 是否开启 - /// 时间间隔 - /// 心跳包的内容,默认是个空的 {} - public void ToggleHeartBeating(bool toggle = true, double interval = 60000, string beatPacket = "{}") - { - this._heartBeatingToggle = toggle; - if (!string.Equals(_beatPacket, beatPacket)) _beatPacket = beatPacket; - - if (_heartBeatingTimer == null && this._heartBeatingToggle) - { - _heartBeatingTimer = new AVTimer(); - _heartBeatingTimer.Elapsed += SendHeartBeatingPacket; - _heartBeatingTimer.Interval = interval; - _heartBeatingTimer.Start(); - PrintLog("auto heart beating started."); - } - if (!this._heartBeatingToggle && _heartBeatingTimer != null) - { - _heartBeatingTimer.Stop(); - _heartBeatingTimer = null; - } - } - - void SendHeartBeatingPacket(object sender, TimerEventArgs e) - { - PrintLog("auto heart beating ticked by timer."); -#if MONO || UNITY - Dispatcher.Instance.Post(() => - { - KeepAlive(); - }); -#else - KeepAlive(); -#endif - } - - /// - /// Keeps the alive. - /// - public void KeepAlive() - { - try - { - var cmd = new AVIMCommand(); - RunCommandAsync(cmd).ContinueWith(t => - { - if (t.IsCanceled || t.IsFaulted || t.Exception != null) - { - InvokeNetworkState(); - } - }); - } - catch (Exception) - { - InvokeNetworkState(); - } - } - - internal bool sessionConflict = false; - internal bool loggedOut = false; - - internal bool CanReconnect - { - get - { - return !sessionConflict && !loggedOut && state == Status.Offline; - } - } - - /// - /// 开始自动重连 - /// - public void StartAutoReconnect() - { - - } - internal bool useSecondary = false; - internal bool reborn = false; - - internal Task LogInAsync(string clientId, - string tag = null, - string deviceId = null, - bool secure = true, - CancellationToken cancellationToken = default(CancellationToken)) - { - lock (mutex) - { - var cmd = new SessionCommand() - .UA(VersionString) - .Tag(tag) - .DeviceId(deviceId) - .Option("open") - .PeerId(clientId); - - var result = AttachSignature(cmd, this.SignatureFactory.CreateConnectSignature(clientId)).OnSuccess(_ => - { - return RunCommandAsync(cmd); - }).Unwrap().OnSuccess(t => - { - AVRealtime.PrintLog("sesstion opened."); - if (t.Exception != null) - { - var imException = t.Exception.InnerException as AVIMException; - throw imException; - } - state = Status.Online; - var response = t.Result.Item2; - if (response.ContainsKey("st")) - { - _sesstionToken = response["st"] as string; - } - if (response.ContainsKey("stTtl")) - { - var stTtl = long.Parse(response["stTtl"].ToString()); - _sesstionTokenExpire = DateTime.Now.ToUnixTimeStamp() + stTtl * 1000; - } - return t.Result; - }); - - return result; - } - - } - - internal Task OpenSessionAsync(string clientId, - string tag = null, - string deviceId = null, - string nonce = null, - long timestamp = 0, - string signature = null, - bool secure = true) - { - var cmd = new SessionCommand() - .UA(VersionString) - .Tag(tag) - .DeviceId(deviceId) - .Option("open") - .PeerId(clientId) - .Argument("n", nonce) - .Argument("t", timestamp) - .Argument("s", signature); - - return RunCommandAsync(cmd).OnSuccess(t => - { - AVRealtime.PrintLog("sesstion opened."); - if (t.Exception != null) - { - var imException = t.Exception.InnerException as AVIMException; - throw imException; - } - state = Status.Online; - var response = t.Result.Item2; - if (response.ContainsKey("st")) - { - _sesstionToken = response["st"] as string; - } - if (response.ContainsKey("stTtl")) - { - var stTtl = long.Parse(response["stTtl"].ToString()); - _sesstionTokenExpire = DateTime.Now.ToUnixTimeStamp() + stTtl * 1000; - } - return t.Result; - }); - - } - - /// - /// 自动重连 - /// - /// - Task AutoReconnect() - { - AVRealtime.PrintLog("AutoReconnect started."); - var reconnectingArgs = new AVIMReconnectingEventArgs() - { - ClientId = _clientId, - IsAuto = true, - SessionToken = _sesstionToken - }; - m_OnReconnecting?.Invoke(this, reconnectingArgs); - - var tcs = new TaskCompletionSource(); - Task task; - if (reborn) - { - AVRealtime.PrintLog("both preferred and secondary websockets are expired, so try to request RTM router to get a new pair"); - task = OpenAsync(this._secure, Subprotocol, true); - } else { - var websocketServer = _wss; - if (useSecondary) { - AVRealtime.PrintLog(string.Format("preferred websocket server ({0}) network broken, take secondary server({1}) :", _wss, _secondaryWss)); - websocketServer = _secondaryWss; - } - task = OpenAsync(websocketServer, Subprotocol, true); - } - - task.ContinueWith(t => - { - if (t.IsFaulted || t.IsCanceled) { - state = Status.Reconnecting; - var reconnectFailedArgs = new AVIMReconnectFailedArgs() { - ClientId = _clientId, - IsAuto = true, - SessionToken = _sesstionToken, - FailedCode = 0// network broken. - }; - m_OnReconnectFailed?.Invoke(this, reconnectFailedArgs); - state = Status.Offline; - tcs.SetException(t.Exception); - throw t.Exception; - } else { - state = Status.Opened; - SetNetworkState(); - - void onClose(int code, string reason, string detail) { - AVRealtime.PrintLog("disconnect when open session"); - var ex = new Exception("connection is closed"); - tcs.SetException(ex); - AVWebSocketClient.OnClosed -= onClose; - throw ex; - }; - AVWebSocketClient.OnClosed += onClose; - - if (this.IsSesstionTokenExpired) { - AVRealtime.PrintLog("session is expired, auto relogin with clientId :" + _clientId); - return this.LogInAsync(_clientId, this._tag, this._deviceId, this._secure).ContinueWith(o => { - AVWebSocketClient.OnClosed -= onClose; - return !o.IsFaulted; - }); - } else { - var sessionCMD = new SessionCommand().UA(VersionString).R(1); - - if (string.IsNullOrEmpty(_tag)) { - sessionCMD = sessionCMD.Tag(_tag).SessionToken(this._sesstionToken); - } - - var cmd = sessionCMD.Option("open") - .PeerId(_clientId); - - AVRealtime.PrintLog("reopen session with session token :" + _sesstionToken); - return RunCommandAsync(cmd).ContinueWith(o => { - AVWebSocketClient.OnClosed -= onClose; - return !o.IsFaulted; - }); - } - } - }).Unwrap().ContinueWith(s => - { - if (s.IsFaulted || s.Exception != null) - { - var reconnectFailedArgs = new AVIMReconnectFailedArgs() - { - ClientId = _clientId, - IsAuto = true, - SessionToken = _sesstionToken, - FailedCode = 1 - }; - m_OnReconnectFailed?.Invoke(this, reconnectFailedArgs); - state = Status.Offline; - tcs.SetException(s.Exception); - } - else - { - var reconnectedArgs = new AVIMReconnectedEventArgs() { - ClientId = _clientId, - IsAuto = true, - SessionToken = _sesstionToken, - }; - state = Status.Online; - m_OnReconnected?.Invoke(this, reconnectedArgs); - ToggleNotification(true); - ToggleHeartBeating(true); - tcs.SetResult(true); - } - }); - - return tcs.Task; - } - - - - #region register IAVIMMessage - /// - /// Registers the subtype of the message. - /// - /// The 1st type parameter. - public void RegisterMessageType() where T : IAVIMMessage - { - AVIMCorePlugins.Instance.FreeStyleClassingController.RegisterSubclass(typeof(T)); - } - #endregion - - /// - /// open websocket with default configurations. - /// - /// - public Task OpenAsync(bool secure = true) - { - return this.OpenAsync(secure, null); - } - - /// - /// Open websocket connection. - /// - /// The async. - /// If set to true secure. - /// Subprotocol. - /// If set to true enforce. - /// Cancellation token. - public Task OpenAsync(bool secure, string subprotocol = null, bool enforce = false, CancellationToken cancellationToken = default(CancellationToken)) - { - _secure = secure; - if (state == Status.Online && !enforce) - { - AVRealtime.PrintLog("state is Status.Online."); - return Task.FromResult(true); - } - - if (AVClient.CurrentConfiguration.RealtimeServer != null) - { - _wss = AVClient.CurrentConfiguration.RealtimeServer; - AVRealtime.PrintLog("use configuration realtime server with url: " + _wss); - return OpenAsync(_wss, subprotocol, enforce); - } - var routerUrl = AVClient.CurrentConfiguration.RTMServer; - return RouterController.GetAsync(routerUrl, secure, cancellationToken).OnSuccess(r => - { - var routerState = r.Result; - if (routerState == null) - { - return Task.FromResult(false); - } - _wss = routerState.server; - _secondaryWss = routerState.secondary; - state = Status.Connecting; - AVRealtime.PrintLog("push router give a url :" + _wss); - return OpenAsync(routerState.server, subprotocol, enforce); - }).Unwrap(); - } - - /// - /// open webcoket connection with cloud. - /// - /// wss address - /// subprotocol for websocket - /// - /// - public Task OpenAsync(string url, string subprotocol = null, bool enforce = false, CancellationToken cancellationToken = default(CancellationToken)) - { - if (AVWebSocketClient.IsOpen && !enforce) - { - AVRealtime.PrintLog(url + "is already connectd."); - return Task.FromResult(true); - } - - AVRealtime.PrintLog("websocket try to connect url :" + url + " with subprotocol: " + subprotocol); - AVRealtime.PrintLog(url + " \tconnecting..."); - - return AVWebSocketClient.Connect(url, subprotocol); - } - - /// - /// send websocket command to Realtime server. - /// - /// - /// - public Task>> RunCommandAsync(AVIMCommand command) - { - command.AppId(AVClient.CurrentConfiguration.ApplicationId); - return this.AVIMCommandRunner.RunCommandAsync(command); - } - - /// - /// - /// - /// - public void RunCommand(AVIMCommand command) - { - command.AppId(AVClient.CurrentConfiguration.ApplicationId); - this.AVIMCommandRunner.RunCommand(command); - } - - internal Task AttachSignature(AVIMCommand command, Task SignatureTask) - { - AVRealtime.PrintLog("begin to attach singature."); - var tcs = new TaskCompletionSource(); - if (SignatureTask == null) - { - tcs.SetResult(command); - return tcs.Task; - } - return SignatureTask.OnSuccess(_ => - { - if (_.Result != null) - { - var signature = _.Result; - command.Argument("t", signature.Timestamp); - command.Argument("n", signature.Nonce); - command.Argument("s", signature.SignatureContent); - AVRealtime.PrintLog("AttachSignature ended.t:" + signature.Timestamp + ";n:" + signature.Nonce + ";s:" + signature.SignatureContent); - } - return command; - }); - } - - #region log out and clean event subscribtion - private void WebsocketClient_OnClosed(int errorCode, string reason, string detail) - { - PrintLog(string.Format("websocket closed with code is {0},reason is {1} and detail is {2}", errorCode, reason, detail)); - state = Status.Offline; - - ToggleNotification(false); - ToggleHeartBeating(false); - - var disconnectEventArgs = new AVIMDisconnectEventArgs(errorCode, reason, detail); - m_OnDisconnected?.Invoke(this, disconnectEventArgs); - - this.WebSocketState = new WebSocketStateOptions() - { - ClosedCode = errorCode - }; - PrepareReconnect(); - } - - private void WebsocketClient_OnError(string obj) - { - PrintLog("error:" + obj); - // 如果遇到 WebSocket 错误之后,先关闭,再按断线处理 - AVWebSocketClient.Close(); - WebsocketClient_OnClosed(0, obj, string.Empty); - } - - void PrepareReconnect() { - AVRealtime.PrintLog("Prepare Reconnect"); - Task.Delay(RECONNECT_DELAY).ContinueWith(_ => { - // 开启重连 - AutoReconnect().ContinueWith(t => { - if (t.IsFaulted) { - // 重连失败,延迟再次重连 - reconnectTimes++; - AVRealtime.PrintLog(String.Format("reconnect {0} times", reconnectTimes)); - if (reconnectTimes >= RECONNECT_FROM_APP_ROUTER) { - // 如果大于当前服务地址的最大重连次数,则清空 Router 后重新重连 - RouterController.ClearCache().ContinueWith(__ => { - reborn = true; - PrepareReconnect(); - }); - - } else if (reconnectTimes >= RECONNECT_USE_SECONDARY_TIMES) { - // 如果大于单台 IM 服务器的重连次数,则启用备用服务器 - useSecondary = true; - PrepareReconnect(); - } else { - PrepareReconnect(); - } - } else { - // 重连成功 - reconnectTimes = 0; - reborn = false; - useSecondary = false; - } - }); - }); - } - - internal void LogOut() - { - State = Status.Closed; - loggedOut = true; - Dispose(); - AVWebSocketClient.Close(); - } - - internal void Dispose() - { - var toggle = false; - ToggleNotification(toggle); - ToggleHeartBeating(toggle); - - if (m_NoticeReceived != null) - { - foreach (Delegate d in m_NoticeReceived.GetInvocationList()) - { - m_NoticeReceived -= (EventHandler)d; - } - } - if (m_OnDisconnected != null) - { - foreach (Delegate d in m_OnDisconnected.GetInvocationList()) - { - m_OnDisconnected -= (EventHandler)d; - } - } - } - #endregion - - static AVRealtime() - { -#if MONO || UNITY - versionString = "net-unity/" + Version; -#else - versionString = "net-universal/" + Version; -#endif - } - - private static readonly string versionString; - internal static string VersionString - { - get - { - return versionString; - } - } - - internal static System.Version Version - { - get - { - AssemblyName assemblyName = new AssemblyName(typeof(AVRealtime).GetTypeInfo().Assembly.FullName); - return assemblyName.Version; - } - } - } -} diff --git a/RTM/Source/Public/IAVIMListener.cs b/RTM/Source/Public/IAVIMListener.cs deleted file mode 100644 index 366f4a2..0000000 --- a/RTM/Source/Public/IAVIMListener.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace LeanCloud.Realtime -{ - /// - /// WebSocket 监听服务端事件通知的接口 - /// 所有基于协议层的事件监听都需要实现这个接口,然后自定义监听协议。 - /// - public interface IAVIMListener - { - /// - /// 监听的协议 Hook - /// 例如,消息的协议是 direct 命令,因此消息监听需要判断 == "direct" 才可以调用 - /// - /// - /// - bool ProtocolHook(AVIMNotice notice); - - ///// - ///// 如果 返回 true,则会启动 NoticeAction 里面的回调逻辑 - ///// - //Action NoticeAction { get; set; } - - /// - /// 如果 返回 true,则会启动 NoticeAction 里面的回调逻辑 - /// - void OnNoticeReceived(AVIMNotice notice); - } -} diff --git a/RTM/Source/Public/IAVIMMessage.cs b/RTM/Source/Public/IAVIMMessage.cs deleted file mode 100644 index f797485..0000000 --- a/RTM/Source/Public/IAVIMMessage.cs +++ /dev/null @@ -1,83 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace LeanCloud.Realtime -{ - /// - /// 消息接口 - /// 所有消息必须实现这个接口 - /// - public interface IAVIMMessage - { - /// - /// Serialize this instance. - /// - /// The serialize. - string Serialize(); - - /// - /// Validate the specified msgStr. - /// - /// The validate. - /// Message string. - bool Validate(string msgStr); - - /// - /// Deserialize the specified msgStr. - /// - /// The deserialize. - /// Message string. - IAVIMMessage Deserialize(string msgStr); - - /// - /// Gets or sets the conversation identifier. - /// - /// The conversation identifier. - string ConversationId { get; set; } - - /// - /// Gets or sets from client identifier. - /// - /// From client identifier. - string FromClientId { get; set; } - - /// - /// Gets or sets the identifier. - /// - /// The identifier. - string Id { get; set; } - - /// - /// Gets or sets the server timestamp. - /// - /// The server timestamp. - long ServerTimestamp { get; set; } - - /// - /// Gets or sets the rcp timestamp. - /// - /// The rcp timestamp. - long RcpTimestamp { get; set; } - - long UpdatedAt { get; set; } - - - #region mention features. - /// - /// Gets or sets a value indicating whether this mention all. - /// - /// true if mention all; otherwise, false. - bool MentionAll { get; set; } - - /// - /// Gets or sets the mention list. - /// - /// The mention list. - IEnumerable MentionList { get; set; } - #endregion - - } -} diff --git a/RTM/Source/Public/ICacheEngine.cs b/RTM/Source/Public/ICacheEngine.cs deleted file mode 100644 index 1c20ec7..0000000 --- a/RTM/Source/Public/ICacheEngine.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace LeanCloud.Realtime -{ - public interface ISQLStorage - { - - } -} diff --git a/RTM/Source/Public/ISignatureFactory.cs b/RTM/Source/Public/ISignatureFactory.cs deleted file mode 100644 index ffda11a..0000000 --- a/RTM/Source/Public/ISignatureFactory.cs +++ /dev/null @@ -1,131 +0,0 @@ -using LeanCloud; -using LeanCloud.Storage.Internal; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - - -namespace LeanCloud.Realtime -{ - /// - /// 对话操作的签名类型,比如讲一个 client id 加入到对话中 - /// - /// - public enum ConversationSignatureAction - { - /// - /// add 加入对话和邀请对方加入对话 - /// - Add, - /// - /// remove 当前 client Id 离开对话和将其他人踢出对话 - /// - Remove - } - - /// - /// - /// - public interface ISignatureFactory - { - - /// - /// 构建登录签名 - /// - /// 需要登录到云端服务器的 client Id - /// - Task CreateConnectSignature(string clientId); - - /// - /// - /// - /// - /// - /// - Task CreateStartConversationSignature(string clientId, IEnumerable targetIds); - - /// - /// - /// - /// - /// - /// - /// 需要签名的操作 - /// - Task CreateConversationSignature(string conversationId, string clientId, IEnumerable targetIds, ConversationSignatureAction action); - } - - internal class DefaulSiganatureFactory : ISignatureFactory - { - Task ISignatureFactory.CreateConnectSignature(string clientId) - { - return Task.FromResult(null); - } - - Task ISignatureFactory.CreateConversationSignature(string conversationId, string clientId, IEnumerable targetIds, ConversationSignatureAction action) - { - return Task.FromResult(null); - } - - Task ISignatureFactory.CreateStartConversationSignature(string clientId, IEnumerable targetIds) - { - return Task.FromResult(null); - } - } - - public class LeanEngineSignatureFactory : ISignatureFactory - { - public Task CreateConnectSignature(string clientId) - { - var data = new Dictionary(); - data.Add("client_id", clientId); - return AVCloud.CallFunctionAsync>("connect", data).OnSuccess(_ => - { - var jsonData = _.Result; - var s = jsonData["signature"].ToString(); - var n = jsonData["nonce"].ToString(); - var t = long.Parse(jsonData["timestamp"].ToString()); - var signature = new AVIMSignature(s, t, n); - return signature; - }); - } - - public Task CreateStartConversationSignature(string clientId, IEnumerable targetIds) - { - var data = new Dictionary(); - data.Add("client_id", clientId); - data.Add("members", targetIds.ToList()); - return AVCloud.CallFunctionAsync>("startConversation", data).OnSuccess(_ => - { - var jsonData = _.Result; - var s = jsonData["signature"].ToString(); - var n = jsonData["nonce"].ToString(); - var t = long.Parse(jsonData["timestamp"].ToString()); - var signature = new AVIMSignature(s, t, n); - return signature; - }); - } - - public Task CreateConversationSignature(string conversationId, string clientId, IEnumerable targetIds, ConversationSignatureAction action) - { - var actionList = new string[] { "invite", "kick" }; - var data = new Dictionary(); - data.Add("client_id", clientId); - data.Add("conv_id", conversationId); - data.Add("members", targetIds.ToList()); - data.Add("action", actionList[(int)action]); - return AVCloud.CallFunctionAsync>("oprateConversation", data).OnSuccess(_ => - { - var jsonData = _.Result; - var s = jsonData["signature"].ToString(); - var n = jsonData["nonce"].ToString(); - var t = long.Parse(jsonData["timestamp"].ToString()); - var signature = new AVIMSignature(s, t, n); - return signature; - }); - } - - } -} diff --git a/RTM/Source/Public/Listener/AVIMConversationListener.cs b/RTM/Source/Public/Listener/AVIMConversationListener.cs deleted file mode 100644 index 77f931a..0000000 --- a/RTM/Source/Public/Listener/AVIMConversationListener.cs +++ /dev/null @@ -1,256 +0,0 @@ -using LeanCloud.Storage.Internal; -using LeanCloud.Realtime.Internal; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace LeanCloud.Realtime -{ - /// - /// 对话中成员变动的事件参数,它提供被操作的对话(Conversation),操作类型(AffectedType) - /// 受影响的成员列表(AffectedMembers) - /// - public class AVIMOnMembersChangedEventArgs : EventArgs - { - /// - /// 本次成员变动中被操作的具体对话(AVIMConversation)的对象 - /// - public AVIMConversation Conversation { get; set; } - - /// - /// 变动的类型 - /// - public AVIMConversationEventType AffectedType { get; internal set; } - - /// - /// 受影响的成员的 Client Ids - /// - public IList AffectedMembers { get; set; } - - /// - /// 操作人的 Client ClientId - /// - public string Oprator { get; set; } - - /// - /// 操作的时间,已转化为本地时间 - /// - public DateTime OpratedTime { get; set; } - } - - /// - /// 变动的类型,目前支持如下: - /// 1、Joined:当前 Client 主动加入,案例:当 A 主动加入到对话,A 将收到 Joined 事件响应,其余的成员收到 MembersJoined 事件响应 - /// 2、Left:当前 Client 主动退出,案例:当 A 从对话中退出,A 将收到 Left 事件响应,其余的成员收到 MembersLeft 事件响应 - /// 3、MembersJoined:某个成员加入(区别于Joined和Kicked),案例:当 A 把 B 加入到对话中,C 将收到 MembersJoined 事件响应 - /// 4、MembersLeft:某个成员加入(区别于Joined和Kicked),案例:当 A 把 B 从对话中剔除,C 将收到 MembersLeft 事件响应 - /// 5、Invited:当前 Client 被邀请加入,案例:当 A 被 B 邀请加入到对话中,A 将收到 Invited 事件响应,B 将收到 Joined ,其余的成员收到 MembersJoined 事件响应 - /// 6、Kicked:当前 Client 被剔除,案例:当 A 被 B 从对话中剔除,A 将收到 Kicked 事件响应,B 将收到 Left,其余的成员收到 MembersLeft 事件响应 - /// - public enum AVIMConversationEventType - { - /// - /// 自身主动加入 - /// - Joined = 1, - /// - /// 自身主动离开 - /// - Left, - /// - /// 他人加入 - /// - MembersJoined, - /// - /// 他人离开 - /// - MembersLeft, - /// - /// 自身被邀请加入 - /// - Invited, - /// - /// 自身被他人剔除 - /// - Kicked - } - - #region AVIMMembersJoinListener - //when Members joined or invited by member,this listener will invoke AVIMOnMembersJoinedEventArgs event. - /// - /// 对话中有成员加入的时候,在改对话中的其他成员都会触发 事件 - /// - public class AVIMMembersJoinListener : IAVIMListener - { - - private EventHandler m_OnMembersJoined; - /// - /// 有成员加入到对话时,触发的事件 - /// - public event EventHandler OnMembersJoined - { - add - { - m_OnMembersJoined += value; - } - remove - { - m_OnMembersJoined -= value; - } - } - - public virtual void OnNoticeReceived(AVIMNotice notice) - { - if (m_OnMembersJoined != null) - { - var joinedMembers = AVDecoder.Instance.DecodeList(notice.RawData["m"]); - var ivitedBy = notice.RawData["initBy"].ToString(); - var conersationId = notice.RawData["cid"].ToString(); - var args = new AVIMOnMembersJoinedEventArgs() - { - ConversationId = conersationId, - InvitedBy = ivitedBy, - JoinedMembers = joinedMembers - }; - m_OnMembersJoined.Invoke(this, args); - } - } - - public virtual bool ProtocolHook(AVIMNotice notice) - { - if (notice.CommandName != "conv") return false; - if (!notice.RawData.ContainsKey("op")) return false; - var op = notice.RawData["op"].ToString(); - if (!op.Equals("members-joined")) return false; - return true; - } - } - #endregion - - #region AVIMMembersLeftListener - // when Members left or kicked by member,this listener will invoke AVIMOnMembersJoinedEventArgs event. - /// - /// 对话中有成员加入的时候,在改对话中的其他成员都会触发 OnMembersJoined 事件 - /// - public class AVIMMembersLeftListener : IAVIMListener - { - private EventHandler m_OnMembersLeft; - /// - /// 有成员加入到对话时,触发的事件 - /// - public event EventHandler OnMembersLeft - { - add - { - m_OnMembersLeft += value; - } - remove - { - m_OnMembersLeft -= value; - } - } - public virtual void OnNoticeReceived(AVIMNotice notice) - { - if (m_OnMembersLeft != null) - { - var leftMembers = AVDecoder.Instance.DecodeList(notice.RawData["m"]); - var kickedBy = notice.RawData["initBy"].ToString(); - var conersationId = notice.RawData["cid"].ToString(); - var args = new AVIMOnMembersLeftEventArgs() - { - ConversationId = conersationId, - KickedBy = kickedBy, - LeftMembers = leftMembers - }; - m_OnMembersLeft.Invoke(this, args); - } - } - - public virtual bool ProtocolHook(AVIMNotice notice) - { - if (notice.CommandName != "conv") return false; - if (!notice.RawData.ContainsKey("op")) return false; - var op = notice.RawData["op"].ToString(); - if (!op.Equals("members-left")) return false; - return true; - } - } - #endregion - - #region AVIMInvitedListener - public class AVIMInvitedListener : IAVIMListener - { - private EventHandler m_OnInvited; - public event EventHandler OnInvited { - add { - m_OnInvited += value; - } remove { - m_OnInvited -= value; - } - } - public void OnNoticeReceived(AVIMNotice notice) - { - if (m_OnInvited != null) - { - var ivitedBy = notice.RawData["initBy"].ToString(); - var conersationId = notice.RawData["cid"].ToString(); - var args = new AVIMOnInvitedEventArgs() - { - ConversationId = conersationId, - InvitedBy = ivitedBy, - }; - m_OnInvited.Invoke(this, args); - } - } - - public bool ProtocolHook(AVIMNotice notice) - { - if (notice.CommandName != "conv") return false; - if (!notice.RawData.ContainsKey("op")) return false; - var op = notice.RawData["op"].ToString(); - if (!op.Equals("joined")) return false; - return true; - } - } - #endregion - - #region AVIMKickedListener - public class AVIMKickedListener : IAVIMListener - { - private EventHandler m_OnKicked; - public event EventHandler OnKicked { - add { - m_OnKicked += value; - } remove { - m_OnKicked -= value; - } - } - public void OnNoticeReceived(AVIMNotice notice) - { - if (m_OnKicked != null) - { - var kickcdBy = notice.RawData["initBy"].ToString(); - var conersationId = notice.RawData["cid"].ToString(); - var args = new AVIMOnKickedEventArgs() - { - ConversationId = conersationId, - KickedBy = kickcdBy, - }; - m_OnKicked.Invoke(this, args); - } - } - - public bool ProtocolHook(AVIMNotice notice) - { - if (notice.CommandName != "conv") return false; - if (!notice.RawData.ContainsKey("op")) return false; - var op = notice.RawData["op"].ToString(); - if (!op.Equals("left")) return false; - return true; - } - } - #endregion - -} diff --git a/RTM/Source/Public/Listener/ConversationUnreadListener.cs b/RTM/Source/Public/Listener/ConversationUnreadListener.cs deleted file mode 100644 index bd48b89..0000000 --- a/RTM/Source/Public/Listener/ConversationUnreadListener.cs +++ /dev/null @@ -1,145 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using LeanCloud.Realtime.Internal; - -namespace LeanCloud.Realtime -{ - internal class ConversationUnreadListener : IAVIMListener - { - internal class UnreadConversationNotice : IEqualityComparer - { - internal readonly object mutex = new object(); - internal IAVIMMessage LastUnreadMessage { get; set; } - internal string ConvId { get; set; } - internal int UnreadCount { get; set; } - - public bool Equals(UnreadConversationNotice x, UnreadConversationNotice y) - { - return x.ConvId == y.ConvId; - } - - public int GetHashCode(UnreadConversationNotice obj) - { - return obj.ConvId.GetHashCode(); - } - - internal void AutomicIncrement() - { - lock (mutex) - { - UnreadCount++; - } - } - } - internal static readonly object sMutex = new object(); - internal static long NotifTime; - internal static HashSet UnreadConversations; - static ConversationUnreadListener() - { - UnreadConversations = new HashSet(new UnreadConversationNotice()); - NotifTime = DateTime.Now.ToUnixTimeStamp(); - } - - internal static void UpdateNotice(IAVIMMessage message) - { - lock (sMutex) - { - var convValidators = UnreadConversations.Where(c => c.ConvId == message.ConversationId); - if (convValidators != null) - { - if (convValidators.Count() > 0) - { - var currentNotice = convValidators.FirstOrDefault(); - currentNotice.AutomicIncrement(); - currentNotice.LastUnreadMessage = message; - } - else - { - var currentThread = new UnreadConversationNotice(); - currentThread.ConvId = message.ConversationId; - currentThread.LastUnreadMessage = message; - currentThread.AutomicIncrement(); - UnreadConversations.Add(currentThread); - } - } - } - } - internal static void ClearUnread(string convId) - { - UnreadConversations.Remove(Get(convId)); - } - internal static IEnumerable FindAllConvIds() - { - lock (sMutex) - { - return ConversationUnreadListener.UnreadConversations.Select(c => c.ConvId); - } - } - - internal static UnreadConversationNotice Get(string convId) - { - lock (sMutex) - { - var unreadValidator = ConversationUnreadListener.UnreadConversations.Where(c => c.ConvId == convId); - if (unreadValidator != null) - { - if (unreadValidator.Count() > 0) - { - var notice = unreadValidator.FirstOrDefault(); - return notice; - } - } - return null; - } - } - - public void OnNoticeReceived(AVIMNotice notice) - { - lock (sMutex) - { - if (notice.RawData.ContainsKey("convs")) - { - var unreadRawData = notice.RawData["convs"] as List; - if (notice.RawData.ContainsKey("notifTime")) - { - long.TryParse(notice.RawData["notifTime"].ToString(), out NotifTime); - } - foreach (var data in unreadRawData) - { - var dataMap = data as IDictionary; - if (dataMap != null) - { - var convId = dataMap["cid"].ToString(); - var ucn = Get(convId); - if (ucn == null) ucn = new UnreadConversationNotice(); - - ucn.ConvId = convId; - var unreadCount = 0; - Int32.TryParse(dataMap["unread"].ToString(), out unreadCount); - ucn.UnreadCount = unreadCount; - - #region restore last message for the conversation - if (dataMap.ContainsKey("data")) - { - var msgStr = dataMap["data"].ToString(); - var messageObj = AVRealtime.FreeStyleMessageClassingController.Instantiate(msgStr, dataMap); - ucn.LastUnreadMessage = messageObj; - } - - UnreadConversations.Add(ucn); - #endregion - } - } - } - } - } - - public bool ProtocolHook(AVIMNotice notice) - { - return notice.CommandName == "unread"; - } - } -} diff --git a/RTM/Source/Public/Listener/GoAwayListener.cs b/RTM/Source/Public/Listener/GoAwayListener.cs deleted file mode 100644 index 57ecb62..0000000 --- a/RTM/Source/Public/Listener/GoAwayListener.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; - -namespace LeanCloud.Realtime { - /// - /// 强制被踢下线处理 - /// - internal class GoAwayListener : IAVIMListener { - Action onGoAway; - - public event Action OnGoAway { - add { - onGoAway += value; - } - remove { - onGoAway -= value; - } - } - - public void OnNoticeReceived(AVIMNotice notice) { - // TODO 退出并清理路由缓存 - onGoAway?.Invoke(); - } - - public bool ProtocolHook(AVIMNotice notice) { - return notice.CommandName == "goaway"; - } - } -} diff --git a/RTM/Source/Public/Listener/MessagePatchListener.cs b/RTM/Source/Public/Listener/MessagePatchListener.cs deleted file mode 100644 index b588190..0000000 --- a/RTM/Source/Public/Listener/MessagePatchListener.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace LeanCloud.Realtime -{ - internal delegate void OnMessagePatch(IEnumerable messages); - internal class MessagePatchListener : IAVIMListener - { - public OnMessagePatch OnReceived { get; set; } - - public void OnNoticeReceived(AVIMNotice notice) - { - ICollection patchedMessages = new List(); - var msgObjs = notice.RawData["patches"] as IList; - if (msgObjs != null) - { - foreach (var msgObj in msgObjs) - { - var msgData = msgObj as IDictionary; - if (msgData != null) - { - var msgStr = msgData["data"] as string; - var message = AVRealtime.FreeStyleMessageClassingController.Instantiate(msgStr, msgData); - patchedMessages.Add(message); - } - } - } - if (OnReceived != null) - { - if (patchedMessages.Count > 0) - { - this.OnReceived(patchedMessages); - } - } - } - - public bool ProtocolHook(AVIMNotice notice) - { - if (notice.CommandName != "patch") return false; - if (!notice.RawData.ContainsKey("op")) return false; - if (notice.RawData["op"].ToString() != "modify") return false; - return true; - } - } -} diff --git a/RTM/Source/Public/Listener/OfflineMessageListener.cs b/RTM/Source/Public/Listener/OfflineMessageListener.cs deleted file mode 100644 index 983ad8a..0000000 --- a/RTM/Source/Public/Listener/OfflineMessageListener.cs +++ /dev/null @@ -1,42 +0,0 @@ -using LeanCloud.Storage.Internal; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace LeanCloud.Realtime -{ - internal class OfflineMessageListener : IAVIMListener - { - private EventHandler m_OnOfflineMessageReceived; - public event EventHandler OnOfflineMessageReceived - { - add - { - m_OnOfflineMessageReceived += value; - } - remove - { - m_OnOfflineMessageReceived -= value; - } - } - public void OnNoticeReceived(AVIMNotice notice) - { - if (m_OnOfflineMessageReceived != null) - { - var msgStr = notice.RawData["msg"].ToString(); - var iMessage = AVRealtime.FreeStyleMessageClassingController.Instantiate(msgStr, notice.RawData); - var args = new AVIMMessageEventArgs(iMessage); - m_OnOfflineMessageReceived.Invoke(this, args); - } - - } - - public bool ProtocolHook(AVIMNotice notice) - { - if (notice.CommandName != "direct") return false; - if (!notice.RawData.ContainsKey("offline")) return false; - return true; - } - } -} diff --git a/RTM/Source/Public/Listener/SessionListener.cs b/RTM/Source/Public/Listener/SessionListener.cs deleted file mode 100644 index aad4c54..0000000 --- a/RTM/Source/Public/Listener/SessionListener.cs +++ /dev/null @@ -1,58 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace LeanCloud.Realtime -{ - internal class SessionListener : IAVIMListener - { - private Action _onSessionClosed; - public event Action OnSessionClosed - { - add - { - _onSessionClosed += value; - } - remove - { - _onSessionClosed -= value; - } - } - public void OnNoticeReceived(AVIMNotice notice) - { - var code = 0; - if (notice.RawData.ContainsKey("code")) - { - int.TryParse(notice.RawData["code"].ToString(), out code); - } - - var reason = ""; - if (notice.RawData.ContainsKey("reason")) - { - reason = notice.RawData["reason"].ToString(); - } - - var detail = ""; - if (notice.RawData.ContainsKey("detail")) - { - detail = notice.RawData["detail"].ToString(); - } - - if (_onSessionClosed != null) - { - _onSessionClosed(code, reason, detail); - } - } - - public bool ProtocolHook(AVIMNotice notice) - { - if (notice.CommandName != "session") return false; - if (!notice.RawData.ContainsKey("op")) return false; - if (notice.RawData.ContainsKey("i")) return false; - if (notice.RawData["op"].ToString() != "closed") return false; - - return true; - } - } -} diff --git a/RTM/Source/Public/Unity/AVRealtimeBehavior.cs b/RTM/Source/Public/Unity/AVRealtimeBehavior.cs deleted file mode 100644 index fe84b52..0000000 --- a/RTM/Source/Public/Unity/AVRealtimeBehavior.cs +++ /dev/null @@ -1,101 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using LeanCloud.Realtime.Internal; -using LeanCloud.Storage.Internal; -using UnityEngine; -using UnityEngine.Networking; - -namespace LeanCloud.Realtime -{ - /// - /// AVRealtime initialize behavior. - /// - public class AVRealtimeBehavior : AVInitializeBehaviour - { - public string RTMRouter = null; - - //void OnApplicationQuit() - //{ - // if (AVRealtime.clients != null) - // { - // foreach (var item in AVRealtime.clients) - // { - // item.Value.LinkedRealtime.LogOut(); - // } - // } - //} - - //private void Update() - //{ - // var available = Application.internetReachability != NetworkReachability.NotReachable; - // if (AVRealtime.clients != null) - // foreach (var item in AVRealtime.clients) - // { - // if (item.Value != null) - // if (item.Value.LinkedRealtime != null) - // item.Value.LinkedRealtime.InvokeNetworkState(available); - // } - //} - - //public override void Awake() - //{ - // base.Awake(); - // StartCoroutine(InitializeRealtime()); - // gameObject.name = "AVRealtimeInitializeBehavior"; - //} - - //public IEnumerator InitializeRealtime() - //{ - // if (isRealtimeInitialized) - // { - // yield break; - // } - // isRealtimeInitialized = true; - // yield return FetchRouter(); - //} - - - //[SerializeField] - //public bool secure; - //private static bool isRealtimeInitialized = false; - //public string Server; - //private IDictionary routerState; - - //public IEnumerator FetchRouter() - //{ - // var router = RTMRouter; - // if (string.IsNullOrEmpty(router)) { - // var state = AVPlugins.Instance.AppRouterController.Get(); - // router = state.RealtimeRouterServer; - // } - // var url = string.Format("https://{0}/v1/route?appId={1}", router, applicationID); - // if (secure) - // { - // url += "&secure=1"; - // } - - // var request = new UnityWebRequest(url); - // request.downloadHandler = new DownloadHandlerBuffer(); - // yield return request.Send(); - - // if (request.isError) - // { - // throw new AVException(AVException.ErrorCode.ConnectionFailed, "can not reach router.", null); - // } - - // var result = request.downloadHandler.text; - // routerState = Json.Parse(result) as IDictionary; - // if (routerState.Keys.Count == 0) - // { - // throw new KeyNotFoundException("Can not get websocket url from server,please check the appId."); - // } - // var ttl = long.Parse(routerState["ttl"].ToString()); - // var expire = DateTime.Now.AddSeconds(ttl); - // routerState["expire"] = expire.ToUnixTimeStamp(UnixTimeStampUnit.Second); - // Server = routerState["server"].ToString(); - //} - - - } -} diff --git a/Realtime/Conversation/LCIMChatRoom.cs b/Realtime/Conversation/LCIMChatRoom.cs new file mode 100644 index 0000000..e5f89b3 --- /dev/null +++ b/Realtime/Conversation/LCIMChatRoom.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Threading.Tasks; + +namespace LeanCloud.Realtime { + /// + /// 聊天室 + /// + public class LCIMChatRoom : LCIMConversation { + public LCIMChatRoom(LCIMClient client) : + base(client) { + } + + /// + /// 获取在线用户数量 + /// + /// + public async Task GetOnlineMembersCount() { + return await GetMembersCount(); + } + + /// + /// 获取在线用户 + /// + /// + /// + public async Task> GetOnlineMembers(int limit = 50) { + return await Client.ConversationController.GetOnlineMembers(Id, limit); + } + + public override Task AddMembers(IEnumerable clientIds) { + throw new Exception("Add members is not allowed in chat room."); + } + } +} diff --git a/Realtime/Conversation/LCIMConversation.cs b/Realtime/Conversation/LCIMConversation.cs new file mode 100644 index 0000000..fb6c9a0 --- /dev/null +++ b/Realtime/Conversation/LCIMConversation.cs @@ -0,0 +1,517 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using System.Linq; +using System.Collections.ObjectModel; +using LeanCloud.Storage; + +namespace LeanCloud.Realtime { + /// + /// 普通对话 + /// + public class LCIMConversation { + /// + /// 对话 Id + /// + public string Id { + get; internal set; + } + + /// + /// 是否唯一 + /// + public bool Unique { + get; internal set; + } + + /// + /// 唯一 Id + /// + public string UniqueId { + get; internal set; + } + + /// + /// 对话名称 + /// + public string Name { + get { + return this["name"] as string; + } + internal set { + this["name"] = value; + } + } + + /// + /// 创建者 Id + /// + public string CreatorId { + get; set; + } + + /// + /// 成员 Id + /// + public ReadOnlyCollection MemberIds { + get { + return new ReadOnlyCollection(ids.ToList()); + } + } + + /// + /// 静音成员 Id + /// + public ReadOnlyCollection MutedMemberIds { + get { + return new ReadOnlyCollection(mutedIds.ToList()); + } + } + + /// + /// 未读消息数量 + /// + public int Unread { + get; internal set; + } + + /// + /// 最新的一条消息 + /// + public LCIMMessage LastMessage { + get; internal set; + } + + /// + /// 创建时间 + /// + public DateTime CreatedAt { + get; internal set; + } + + /// + /// 更新时间 + /// + public DateTime UpdatedAt { + get; internal set; + } + + /// + /// 最新送达消息时间戳 + /// + public long LastDeliveredTimestamp { + get; internal set; + } + + /// + /// 最新送达消息时间 + /// + public DateTime LastDeliveredAt { + get { + DateTimeOffset dateTimeOffset = DateTimeOffset.FromUnixTimeMilliseconds(LastDeliveredTimestamp); + return dateTimeOffset.DateTime; + } + } + + /// + /// 最新已读消息时间戳 + /// + public long LastReadTimestamp { + get; internal set; + } + + /// + /// 最新已读消息时间 + /// + public DateTime LastReadAt { + get { + DateTimeOffset dateTimeOffset = DateTimeOffset.FromUnixTimeMilliseconds(LastReadTimestamp); + return dateTimeOffset.DateTime; + } + } + + /// + /// 设置/获取对话属性 + /// + /// + /// + public object this[string key] { + get { + return customProperties[key]; + } + set { + customProperties[key] = value; + } + } + + /// + /// 是否已静音 + /// + public bool IsMute { + get; private set; + } + + protected LCIMClient Client { + get; private set; + } + + private readonly Dictionary customProperties; + + internal HashSet ids; + + internal HashSet mutedIds; + + internal LCIMConversation(LCIMClient client) { + Client = client; + customProperties = new Dictionary(); + ids = new HashSet(); + mutedIds = new HashSet(); + customProperties = new Dictionary(); + } + + /// + /// 获取对话人数,或暂态对话的在线人数 + /// + /// + public async Task GetMembersCount() { + return await Client.ConversationController.GetMembersCount(Id); + } + + /// + /// 将该会话标记为已读 + /// + /// + /// + public async Task Read() { + if (LastMessage == null) { + return; + } + await Client.MessageController.Read(Id, LastMessage); + Unread = 0; + } + + /// + /// 修改对话属性 + /// + /// + /// + public async Task UpdateInfo(Dictionary attributes) { + if (attributes == null || attributes.Count == 0) { + throw new ArgumentNullException(nameof(attributes)); + } + Dictionary updatedAttr = await Client.ConversationController.UpdateInfo(Id, attributes); + if (updatedAttr != null) { + MergeInfo(updatedAttr); + } + } + + /// + /// 添加用户到对话 + /// + /// 用户 Id + /// + public virtual async Task AddMembers(IEnumerable clientIds) { + if (clientIds == null || clientIds.Count() == 0) { + throw new ArgumentNullException(nameof(clientIds)); + } + LCIMPartiallySuccessResult result = await Client.ConversationController.AddMembers(Id, clientIds); + ids.UnionWith(result.SuccessfulClientIdList); + return result; + } + + /// + /// 删除用户 + /// + /// 用户 Id + /// + public async Task RemoveMembers(IEnumerable removeIds) { + if (removeIds == null || removeIds.Count() == 0) { + throw new ArgumentNullException(nameof(removeIds)); + } + LCIMPartiallySuccessResult result = await Client.ConversationController.RemoveMembers(Id, removeIds); + ids.RemoveWhere(id => result.SuccessfulClientIdList.Contains(id)); + return result; + } + + /// + /// 加入对话 + /// + /// + public async Task Join() { + LCIMPartiallySuccessResult result = await Client.ConversationController.AddMembers(Id, + new string[] { Client.Id }); + if (result.IsSuccess) { + ids.UnionWith(result.SuccessfulClientIdList); + } else { + LCIMOperationFailure error = result.FailureList[0]; + throw new LCException(error.Code, error.Reason); + } + } + + /// + /// 离开对话 + /// + /// + public async Task Quit() { + LCIMPartiallySuccessResult result = await RemoveMembers(new string[] { Client.Id }); + if (!result.IsSuccess) { + LCIMOperationFailure error = result.FailureList[0]; + throw new LCException(error.Code, error.Reason); + } + } + + /// + /// 发送消息 + /// + /// + /// + public async Task Send(LCIMMessage message, + LCIMMessageSendOptions options = null) { + if (message == null) { + throw new ArgumentNullException(nameof(message)); + } + if (options == null) { + options = LCIMMessageSendOptions.Default; + } + await Client.MessageController.Send(Id, message, options); + LastMessage = message; + return message; + } + + /// + /// 静音 + /// + /// + public async Task Mute() { + await Client.ConversationController.Mute(Id); + IsMute = true; + } + + /// + /// 取消静音 + /// + /// + public async Task Unmute() { + await Client.ConversationController.Unmute(Id); + IsMute = false; + } + + /// + /// 禁言 + /// + /// + /// + public async Task MuteMembers(IEnumerable clientIds) { + if (clientIds == null || clientIds.Count() == 0) { + throw new ArgumentNullException(nameof(clientIds)); + } + LCIMPartiallySuccessResult result = await Client.ConversationController.MuteMembers(Id, clientIds); + if (result.SuccessfulClientIdList != null) { + mutedIds.UnionWith(result.SuccessfulClientIdList); + } + return result; + } + + /// + /// 取消禁言 + /// + /// + /// + public async Task UnmuteMembers(IEnumerable clientIds) { + if (clientIds == null || clientIds.Count() == 0) { + throw new ArgumentNullException(nameof(clientIds)); + } + LCIMPartiallySuccessResult result = await Client.ConversationController.UnmuteMembers(Id, clientIds); + if (result.SuccessfulClientIdList != null) { + mutedIds.RemoveWhere(id => result.SuccessfulClientIdList.Contains(id)); + } + return result; + } + + /// + /// 将用户加入黑名单 + /// + /// + /// + public async Task BlockMembers(IEnumerable clientIds) { + if (clientIds == null || clientIds.Count() == 0) { + throw new ArgumentNullException(nameof(clientIds)); + } + return await Client.ConversationController.BlockMembers(Id, clientIds); + } + + /// + /// 将用户移除黑名单 + /// + /// + /// + public async Task UnblockMembers(IEnumerable clientIds) { + if (clientIds == null || clientIds.Count() == 0) { + throw new ArgumentNullException(nameof(clientIds)); + } + return await Client.ConversationController.UnblockMembers(Id, clientIds); + } + + /// + /// 撤回消息 + /// + /// + /// + public async Task RecallMessage(LCIMMessage message) { + if (message == null) { + throw new ArgumentNullException(nameof(message)); + } + await Client.MessageController.RecallMessage(Id, message); + } + + /// + /// 修改消息 + /// + /// + /// + /// + public async Task UpdateMessage(LCIMMessage oldMessage, LCIMMessage newMessage) { + if (oldMessage == null) { + throw new ArgumentNullException(nameof(oldMessage)); + } + if (newMessage == null) { + throw new ArgumentNullException(nameof(newMessage)); + } + await Client.MessageController.UpdateMessage(Id, oldMessage, newMessage); + } + + /// + /// 更新对话中成员的角色 + /// + /// + /// + /// + 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"); + } + await Client.ConversationController.UpdateMemberRole(Id, memberId, role); + } + + /// + /// 获取对话中成员的角色(只返回管理员) + /// + /// + public async Task> GetAllMemberInfo() { + return await Client.ConversationController.GetAllMemberInfo(Id); + } + + /// + /// 获取对话中指定成员的角色 + /// + /// + /// + public async Task GetMemberInfo(string memberId) { + if (string.IsNullOrEmpty(memberId)) { + throw new ArgumentNullException(nameof(memberId)); + } + ReadOnlyCollection members = await GetAllMemberInfo(); + foreach (LCIMConversationMemberInfo member in members) { + if (member.MemberId == memberId) { + return member; + } + } + return null; + } + + /// + /// 查询禁言用户 + /// + /// + /// + /// + public async Task QueryMutedMembers(int limit = 10, + string next = null) { + return await Client.ConversationController.QueryMutedMembers(Id, limit, next); + } + + /// + /// 查询黑名单用户 + /// + /// 限制 + /// 其实用户 Id + /// + public async Task QueryBlockedMembers(int limit = 10, + string next = null) { + return await Client.ConversationController.QueryBlockedMembers(Id, limit, next); + } + + /// + /// 查询聊天记录 + /// + /// 起点 + /// 终点 + /// 查找方向 + /// 限制 + /// 消息类型 + /// + public async Task> QueryMessages(LCIMMessageQueryEndpoint start = null, + LCIMMessageQueryEndpoint end = null, + LCIMMessageQueryDirection direction = LCIMMessageQueryDirection.NewToOld, + int limit = 20, + int messageType = 0) { + return await Client.MessageController.QueryMessages(Id, start, end, direction, limit, messageType); + } + + /// + /// 获取会话已收/已读时间戳 + /// + /// + public async Task FetchReciptTimestamps() { + await Client.ConversationController.FetchReciptTimestamp(Id); + } + + internal static bool IsTemporayConversation(string convId) { + return convId.StartsWith("_tmp:"); + } + + internal void MergeFrom(Dictionary conv) { + if (conv.TryGetValue("objectId", out object idObj)) { + Id = idObj as string; + } + if (conv.TryGetValue("unique", out object uniqueObj)) { + Unique = (bool)uniqueObj; + } + if (conv.TryGetValue("uniqueId", out object uniqueIdObj)) { + UniqueId = uniqueIdObj as string; + } + if (conv.TryGetValue("createdAt", out object createdAtObj)) { + CreatedAt = DateTime.Parse(createdAtObj.ToString()); + } + if (conv.TryGetValue("updatedAt", out object updatedAtObj)) { + UpdatedAt = DateTime.Parse(updatedAtObj.ToString()); + } + if (conv.TryGetValue("c", out object co)) { + CreatorId = co as string; + } + if (conv.TryGetValue("m", out object mo)) { + IEnumerable ids = (mo as IList).Cast(); + this.ids = new HashSet(ids); + } + if (conv.TryGetValue("mu", out object muo)) { + IEnumerable ids = (muo as IList).Cast(); + mutedIds = new HashSet(ids); + } + //if (conv.TryGetValue("lm", out object lmo)) { + // LastMessageAt = (DateTime)LCDecoder.Decode(lmo); + //} + } + + internal void MergeInfo(Dictionary attr) { + if (attr == null || attr.Count == 0) { + return; + } + foreach (KeyValuePair kv in attr) { + customProperties[kv.Key] = kv.Value; + } + } + } +} diff --git a/Realtime/Conversation/LCIMConversationMemberInfo.cs b/Realtime/Conversation/LCIMConversationMemberInfo.cs new file mode 100644 index 0000000..5809dec --- /dev/null +++ b/Realtime/Conversation/LCIMConversationMemberInfo.cs @@ -0,0 +1,42 @@ +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; + } + + public string MemberId { + 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/Conversation/LCIMConversationQuery.cs b/Realtime/Conversation/LCIMConversationQuery.cs new file mode 100644 index 0000000..5904ab1 --- /dev/null +++ b/Realtime/Conversation/LCIMConversationQuery.cs @@ -0,0 +1,253 @@ +using System.Threading.Tasks; +using System.Collections; +using System.Collections.ObjectModel; +using LeanCloud.Storage.Internal.Query; + +namespace LeanCloud.Realtime { + public class LCIMConversationQuery { + internal LCCompositionalCondition Condition { + get; private set; + } + + private readonly LCIMClient client; + + public LCIMConversationQuery(LCIMClient client) { + Condition = new LCCompositionalCondition(); + this.client = client; + } + + /// + /// 等于 + /// + /// + /// + /// + public LCIMConversationQuery WhereEqualTo(string key, + object value) { + Condition.WhereEqualTo(key, value); + return this; + } + + /// + /// 不等于 + /// + /// + /// + /// + public LCIMConversationQuery WhereNotEqualTo(string key, + object value) { + Condition.WhereNotEqualTo(key, value); + return this; + } + + /// + /// 包含 + /// + /// + /// + /// + public LCIMConversationQuery WhereContainedIn(string key, + IEnumerable values) { + Condition.WhereContainedIn(key, values); + return this; + } + + /// + /// 包含全部 + /// + /// + /// + /// + public LCIMConversationQuery WhereContainsAll(string key, + IEnumerable values) { + Condition.WhereContainsAll(key, values); + return this; + } + + /// + /// 存在 + /// + /// + /// + public LCIMConversationQuery WhereExists(string key) { + Condition.WhereExists(key); + return this; + } + + /// + /// 不存在 + /// + /// + /// + public LCIMConversationQuery WhereDoesNotExist(string key) { + Condition.WhereDoesNotExist(key); + return this; + } + + /// + /// 长度等于 + /// + /// + /// + /// + public LCIMConversationQuery WhereSizeEqualTo(string key, + int size) { + Condition.WhereSizeEqualTo(key, size); + return this; + } + + /// + /// 大于 + /// + /// + /// + /// + public LCIMConversationQuery WhereGreaterThan(string key, + object value) { + Condition.WhereGreaterThan(key, value); + return this; + } + + /// + /// 大于等于 + /// + /// + /// + /// + public LCIMConversationQuery WhereGreaterThanOrEqualTo(string key, + object value) { + Condition.WhereGreaterThanOrEqualTo(key, value); + return this; + } + + /// + /// 小于 + /// + /// + /// + /// + public LCIMConversationQuery WhereLessThan(string key, + object value) { + Condition.WhereLessThan(key, value); + return this; + } + + /// + /// 小于等于 + /// + /// + /// + /// + public LCIMConversationQuery WhereLessThanOrEqualTo(string key, + object value) { + Condition.WhereLessThanOrEqualTo(key, value); + return this; + } + + /// + /// 前缀 + /// + /// + /// + /// + public LCIMConversationQuery WhereStartsWith(string key, + string prefix) { + Condition.WhereStartsWith(key, prefix); + return this; + } + + /// + /// 后缀 + /// + /// + /// + /// + public LCIMConversationQuery WhereEndsWith(string key, string suffix) { + Condition.WhereEndsWith(key, suffix); + return this; + } + + /// + /// 字符串包含 + /// + /// + /// + /// + public LCIMConversationQuery WhereContains(string key, string subString) { + Condition.WhereContains(key, subString); + return this; + } + + /// + /// 按 key 升序 + /// + /// + /// + public LCIMConversationQuery OrderBy(string key) { + Condition.OrderBy(key); + return this; + } + + /// + /// 按 key 降序 + /// + /// + /// + public LCIMConversationQuery OrderByDescending(string key) { + Condition.OrderByDescending(key); + return this; + } + + /// + /// 拉取 key 的完整对象 + /// + /// + /// + public LCIMConversationQuery Include(string key) { + Condition.Include(key); + return this; + } + + /// + /// 包含 key + /// + /// + /// + public LCIMConversationQuery Select(string key) { + Condition.Select(key); + return this; + } + + /// + /// 跳过 + /// + /// + /// + public LCIMConversationQuery Skip(int value) { + Condition.Skip = value; + return this; + } + + /// + /// 限制数量 + /// + /// + /// + public LCIMConversationQuery Limit(int value) { + Condition.Limit = value; + return this; + } + + public bool WithLastMessageRefreshed { + get; set; + } + + /// + /// 查找 + /// + /// + public async Task> Find() { + return await client.ConversationController.Find(this); + } + } +} diff --git a/Realtime/Conversation/LCIMMessageQueryOptions.cs b/Realtime/Conversation/LCIMMessageQueryOptions.cs new file mode 100644 index 0000000..c936feb --- /dev/null +++ b/Realtime/Conversation/LCIMMessageQueryOptions.cs @@ -0,0 +1,26 @@ +using System; + +namespace LeanCloud.Realtime { + public class LCIMMessageQueryEndpoint { + public string MessageId { + get; set; + } + + public long SentTimestamp { + get; set; + } + + public bool IsClosed { + get; set; + } + + public LCIMMessageQueryEndpoint() { + + } + } + + public enum LCIMMessageQueryDirection { + NewToOld, + OldToNew + } +} diff --git a/Realtime/Conversation/LCIMServiceConversation.cs b/Realtime/Conversation/LCIMServiceConversation.cs new file mode 100644 index 0000000..93e8da2 --- /dev/null +++ b/Realtime/Conversation/LCIMServiceConversation.cs @@ -0,0 +1,24 @@ +using System; +using System.Threading.Tasks; + +namespace LeanCloud.Realtime { + /// + /// 系统对话 + /// + public class LCIMServiceConversation : LCIMConversation { + public LCIMServiceConversation(LCIMClient client) : base(client) { + } + + public async Task Subscribe() { + await Join(); + } + + public async Task Unsubscribe() { + await Quit(); + } + + public async Task CheckSubscription() { + return await Client.ConversationController.CheckSubscription(Id); + } + } +} diff --git a/Realtime/Conversation/LCIMTemporaryConversation.cs b/Realtime/Conversation/LCIMTemporaryConversation.cs new file mode 100644 index 0000000..01f20ad --- /dev/null +++ b/Realtime/Conversation/LCIMTemporaryConversation.cs @@ -0,0 +1,27 @@ +using System; + +namespace LeanCloud.Realtime { + /// + /// 临时对话 + /// + public class LCIMTemporaryConversation : LCIMConversation { + /// + /// 过期时间 + /// + public DateTime ExpiredAt { + get; + } + + /// + /// 是否过期 + /// + public bool IsExpired { + get { + return DateTime.Now > ExpiredAt; + } + } + + public LCIMTemporaryConversation(LCIMClient client) : base(client) { + } + } +} diff --git a/Realtime/Internal/Connection/LCConnection.cs b/Realtime/Internal/Connection/LCConnection.cs new file mode 100644 index 0000000..2add3be --- /dev/null +++ b/Realtime/Internal/Connection/LCConnection.cs @@ -0,0 +1,239 @@ +using System; +using System.Text; +using System.Collections.Generic; +using System.Threading.Tasks; +using Google.Protobuf; +using LeanCloud.Realtime.Internal.Router; +using LeanCloud.Realtime.Internal.WebSocket; +using LeanCloud.Realtime.Internal.Protocol; +using LeanCloud.Storage; + +namespace LeanCloud.Realtime.Internal.Connection { + /// + /// 连接层,只与数据协议相关 + /// + internal class LCConnection { + /// + /// 发送超时 + /// + private const int SEND_TIMEOUT = 10000; + + /// + /// 最大重连次数,超过后重置 Router 缓存后再次尝试重连 + /// + private const int MAX_RECONNECT_TIMES = 10; + + /// + /// 重连间隔 + /// + private const int RECONNECT_INTERVAL = 10000; + + /// + /// 心跳间隔 + /// + private const int HEART_BEAT_INTERVAL = 30000; + + /// + /// 通知事件 + /// + internal Action OnNotification; + + /// + /// 断线事件 + /// + internal Action OnDisconnect; + + /// + /// 重连成功事件 + /// + internal Action OnReconnected; + + internal string id; + + /// + /// 请求回调缓存 + /// + private readonly Dictionary> responses; + + private int requestI = 1; + + private LCRTMRouter router; + + private LCHeartBeat heartBeat; + + private LCWebSocketClient client; + + internal LCConnection(string id) { + this.id = id; + responses = new Dictionary>(); + heartBeat = new LCHeartBeat(this, HEART_BEAT_INTERVAL, HEART_BEAT_INTERVAL); + router = new LCRTMRouter(); + client = new LCWebSocketClient { + OnMessage = OnClientMessage, + OnClose = OnClientDisconnect + }; + } + + internal async Task Connect() { + try { + LCRTMServer rtmServer = await router.GetServer(); + try { + LCLogger.Debug($"Primary Server"); + await client.Connect(rtmServer.Primary); + } catch (Exception e) { + LCLogger.Error(e); + LCLogger.Debug($"Secondary Server"); + await client.Connect(rtmServer.Secondary); + } + } catch (Exception e) { + throw e; + } + } + + /// + /// 重置连接 + /// + /// + internal async Task Reset() { + // 关闭就连接 + await client.Close(); + // 重新创建连接组件 + heartBeat = new LCHeartBeat(this, HEART_BEAT_INTERVAL, HEART_BEAT_INTERVAL); + router = new LCRTMRouter(); + client = new LCWebSocketClient { + OnMessage = OnClientMessage, + OnClose = OnClientDisconnect + }; + await Reconnect(); + } + + /// + /// 发送请求,会在收到应答后返回 + /// + /// + /// + internal async Task SendRequest(GenericCommand request) { + TaskCompletionSource tcs = new TaskCompletionSource(); + request.I = requestI++; + responses.Add(request.I, tcs); + try { + await SendCommand(request); + } catch (Exception e) { + tcs.TrySetException(e); + } + return await tcs.Task; + } + + /// + /// 发送命令 + /// + /// + /// + internal async Task SendCommand(GenericCommand command) { + LCLogger.Debug($"{id} => {FormatCommand(command)}"); + byte[] bytes = command.ToByteArray(); + Task sendTask = client.Send(bytes); + if (await Task.WhenAny(sendTask, Task.Delay(SEND_TIMEOUT)) == sendTask) { + await sendTask; + } else { + throw new TimeoutException("Send request"); + } + } + + /// + /// 关闭连接 + /// + /// + internal async Task Close() { + OnNotification = null; + OnDisconnect = null; + OnReconnected = null; + heartBeat.Stop(); + await client.Close(); + } + + private void OnClientMessage(byte[] bytes) { + _ = heartBeat.Refresh(OnPingTimeout); + try { + GenericCommand command = GenericCommand.Parser.ParseFrom(bytes); + LCLogger.Debug($"{id} <= {FormatCommand(command)}"); + if (command.HasI) { + // 应答 + int requestIndex = command.I; + if (responses.TryGetValue(requestIndex, out TaskCompletionSource tcs)) { + if (command.HasErrorMessage) { + // 错误 + ErrorCommand error = command.ErrorMessage; + int code = error.Code; + string detail = error.Detail; + // 包装成异常抛出 + LCException exception = new LCException(code, detail); + tcs.TrySetException(exception); + } else { + tcs.TrySetResult(command); + } + responses.Remove(requestIndex); + } else { + LCLogger.Error($"No request for {requestIndex}"); + } + } else { + // 通知 + OnNotification?.Invoke(command); + } + } catch (Exception e) { + LCLogger.Error(e); + } + } + + private void OnClientDisconnect() { + heartBeat.Stop(); + OnDisconnect?.Invoke(); + // 重连 + _ = Reconnect(); + } + + private async void OnPingTimeout() { + await client.Close(); + OnClientDisconnect(); + } + + private async Task Reconnect() { + while (true) { + int reconnectCount = 0; + // 重连策略 + while (reconnectCount < MAX_RECONNECT_TIMES) { + try { + LCLogger.Debug($"Reconnecting... {reconnectCount}"); + await Connect(); + break; + } catch (Exception e) { + reconnectCount++; + LCLogger.Error(e); + LCLogger.Debug($"Reconnect after {RECONNECT_INTERVAL}ms"); + await Task.Delay(RECONNECT_INTERVAL); + } + } + if (reconnectCount < MAX_RECONNECT_TIMES) { + // 重连成功 + LCLogger.Debug("Reconnected"); + client.OnMessage = OnClientMessage; + client.OnClose = OnClientDisconnect; + OnReconnected?.Invoke(); + break; + } else { + // 重置 Router,继续尝试重连 + router = new LCRTMRouter(); + } + } + } + + private static string FormatCommand(GenericCommand command) { + StringBuilder sb = new StringBuilder($"{command.Cmd}"); + if (command.HasOp) { + sb.Append($"/{command.Op}"); + } + sb.Append($"\n{command}"); + return sb.ToString(); + } + } +} diff --git a/Realtime/Internal/Connection/LCHeartBeat.cs b/Realtime/Internal/Connection/LCHeartBeat.cs new file mode 100644 index 0000000..6e7853c --- /dev/null +++ b/Realtime/Internal/Connection/LCHeartBeat.cs @@ -0,0 +1,80 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using LeanCloud.Realtime.Internal.Protocol; + +namespace LeanCloud.Realtime.Internal.Connection { + /// + /// 心跳控制器,由于 .Net Standard 2.0 不支持发送 ping frame,所以需要发送逻辑心跳 + /// 1. 每次接收到消息后开始监听,如果在 pingInterval 时间内没有再次接收到消息,则发送 ping 请求; + /// 2. 发送后等待 pongInterval 时间,如果在此时间内接收到了任何消息,则取消并重新开始监听 1; + /// 3. 如果没收到消息,则认为超时并回调,连接层接收回调后放弃当前连接,以断线逻辑处理 + /// + internal class LCHeartBeat { + private readonly LCConnection connection; + + /// + /// ping 间隔 + /// + private readonly int pingInterval; + + /// + /// pong 间隔 + /// + private readonly int pongInterval; + + private CancellationTokenSource pingCTS; + private CancellationTokenSource pongCTS; + + internal LCHeartBeat(LCConnection connection, + int pingInterval, + int pongInterval) { + this.connection = connection; + this.pingInterval = pingInterval; + this.pongInterval = pongInterval; + } + + /// + /// 更新心跳监听 + /// + /// + internal async Task Refresh(Action onTimeout) { + LCLogger.Debug("HeartBeat refresh"); + pingCTS?.Cancel(); + pongCTS?.Cancel(); + + // 计时准备 ping + pingCTS = new CancellationTokenSource(); + Task delayTask = Task.Delay(pingInterval, pingCTS.Token); + await delayTask; + if (delayTask.IsCanceled) { + return; + } + // 发送 ping 包 + LCLogger.Debug("Ping ~~~"); + GenericCommand command = new GenericCommand { + Cmd = CommandType.Echo, + AppId = LCApplication.AppId, + PeerId = connection.id + }; + _ = connection.SendRequest(command); + pongCTS = new CancellationTokenSource(); + Task timeoutTask = Task.Delay(pongInterval, pongCTS.Token); + await timeoutTask; + if (timeoutTask.IsCanceled) { + return; + } + // timeout + LCLogger.Error("Ping timeout"); + onTimeout.Invoke(); + } + + /// + /// 停止心跳监听 + /// + internal void Stop() { + pingCTS?.Cancel(); + pongCTS?.Cancel(); + } + } +} diff --git a/Realtime/Internal/Controller/LCIMController.cs b/Realtime/Internal/Controller/LCIMController.cs new file mode 100644 index 0000000..598a526 --- /dev/null +++ b/Realtime/Internal/Controller/LCIMController.cs @@ -0,0 +1,37 @@ +using System.Threading.Tasks; +using LeanCloud.Realtime.Internal.Protocol; +using LeanCloud.Realtime.Internal.Connection; + +namespace LeanCloud.Realtime.Internal.Controller { + internal abstract class LCIMController { + protected LCIMClient Client { + get; set; + } + + internal LCIMController(LCIMClient client) { + Client = client; + } + + internal abstract Task OnNotification(GenericCommand notification); + + protected LCConnection Connection { + get { + return Client.Connection; + } + } + + protected GenericCommand NewCommand(CommandType cmd, OpType op) { + GenericCommand command = NewCommand(cmd); + command.Op = op; + return command; + } + + protected GenericCommand NewCommand(CommandType cmd) { + return new GenericCommand { + Cmd = cmd, + AppId = LCApplication.AppId, + PeerId = Client.Id, + }; + } + } +} diff --git a/Realtime/Internal/Controller/LCIMConversationController.cs b/Realtime/Internal/Controller/LCIMConversationController.cs new file mode 100644 index 0000000..cd7836a --- /dev/null +++ b/Realtime/Internal/Controller/LCIMConversationController.cs @@ -0,0 +1,824 @@ +using System; +using System.Linq; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Threading.Tasks; +using Newtonsoft.Json; +using LeanCloud.Realtime.Internal.Protocol; +using LeanCloud.Storage.Internal; +using LeanCloud.Storage.Internal.Codec; +using LeanCloud.Common; + +namespace LeanCloud.Realtime.Internal.Controller { + internal class LCIMConversationController : LCIMController { + internal LCIMConversationController(LCIMClient client) : base(client) { + + } + + #region 内部接口 + + /// + /// 创建对话 + /// + /// + /// + /// + /// + /// + /// + /// + /// + internal async Task CreateConv( + IEnumerable members = null, + string name = null, + bool transient = false, + bool unique = true, + bool temporary = false, + int temporaryTtl = 86400, + Dictionary properties = null) { + GenericCommand request = NewCommand(CommandType.Conv, OpType.Start); + ConvCommand conv = new ConvCommand { + Transient = transient, + Unique = unique, + }; + if (members != null) { + conv.M.AddRange(members); + } + if (!string.IsNullOrEmpty(name)) { + conv.N = name; + } + if (temporary) { + conv.TempConv = temporary; + conv.TempConvTTL = temporaryTtl; + } + if (properties != null) { + conv.Attr = new JsonObjectMessage { + Data = JsonConvert.SerializeObject(LCEncoder.Encode(properties)) + }; + } + if (Client.SignatureFactory != null) { + LCIMSignature signature = await Client.SignatureFactory.CreateStartConversationSignature(Client.Id, members); + conv.S = signature.Signature; + conv.T = signature.Timestamp; + conv.N = signature.Nonce; + } + request.ConvMessage = conv; + GenericCommand response = await Connection.SendRequest(request); + string convId = response.ConvMessage.Cid; + if (!Client.ConversationDict.TryGetValue(convId, out LCIMConversation conversation)) { + if (transient) { + conversation = new LCIMChatRoom(Client); + } else if (temporary) { + conversation = new LCIMTemporaryConversation(Client); + } else if (properties != null && properties.ContainsKey("system")) { + conversation = new LCIMServiceConversation(Client); + } else { + conversation = new LCIMConversation(Client); + } + Client.ConversationDict[convId] = conversation; + } + // 合并请求数据 + conversation.Id = convId; + conversation.Unique = unique; + conversation.UniqueId = response.ConvMessage.UniqueId; + conversation.Name = name; + conversation.CreatorId = Client.Id; + conversation.ids = members != null ? + new HashSet(members) : new HashSet(); + conversation.CreatedAt = DateTime.Parse(response.ConvMessage.Cdate); + conversation.UpdatedAt = conversation.CreatedAt; + return conversation; + } + + /// + /// 查询成员数量 + /// + /// + /// + internal async Task GetMembersCount(string convId) { + ConvCommand conv = new ConvCommand { + Cid = convId, + }; + GenericCommand command = NewCommand(CommandType.Conv, OpType.Count); + command.ConvMessage = conv; + GenericCommand response = await Connection.SendRequest(command); + return response.ConvMessage.Count; + } + + /// + /// 更新对话属性 + /// + /// + /// + /// + internal async Task> UpdateInfo(string convId, + Dictionary attributes) { + ConvCommand conv = new ConvCommand { + Cid = convId, + }; + conv.Attr = new JsonObjectMessage { + Data = JsonConvert.SerializeObject(attributes) + }; + GenericCommand request = NewCommand(CommandType.Conv, OpType.Update); + request.ConvMessage = conv; + GenericCommand response = await Client.Connection.SendRequest(request); + JsonObjectMessage attr = response.ConvMessage.AttrModified; + // 更新自定义属性 + if (attr != null) { + Dictionary updatedAttr = JsonConvert.DeserializeObject>(attr.Data); + return updatedAttr; + } + return null; + } + + /// + /// 增加成员 + /// + /// + /// + /// + internal async Task AddMembers(string convId, + IEnumerable clientIds) { + ConvCommand conv = new ConvCommand { + Cid = convId, + }; + conv.M.AddRange(clientIds); + // 签名参数 + if (Client.SignatureFactory != null) { + LCIMSignature signature = await Client.SignatureFactory.CreateConversationSignature(convId, + Client.Id, + clientIds, + LCIMSignatureAction.Invite); + conv.S = signature.Signature; + conv.T = signature.Timestamp; + conv.N = signature.Nonce; + } + GenericCommand request = NewCommand(CommandType.Conv, OpType.Add); + request.ConvMessage = conv; + GenericCommand response = await Client.Connection.SendRequest(request); + List allowedIds = response.ConvMessage.AllowedPids.ToList(); + List errors = response.ConvMessage.FailedPids.ToList(); + return NewPartiallySuccessResult(allowedIds, errors); + } + + /// + /// 移除成员 + /// + /// + /// + /// + internal async Task RemoveMembers(string convId, + IEnumerable removeIds) { + ConvCommand conv = new ConvCommand { + Cid = convId, + }; + conv.M.AddRange(removeIds); + // 签名参数 + if (Client.SignatureFactory != null) { + LCIMSignature signature = await Client.SignatureFactory.CreateConversationSignature(convId, + Client.Id, + removeIds, + LCIMSignatureAction.Kick); + conv.S = signature.Signature; + conv.T = signature.Timestamp; + conv.N = signature.Nonce; + } + GenericCommand request = NewCommand(CommandType.Conv, OpType.Remove); + request.ConvMessage = conv; + GenericCommand response = await Client.Connection.SendRequest(request); + List allowedIds = response.ConvMessage.AllowedPids.ToList(); + List errors = response.ConvMessage.FailedPids.ToList(); + return NewPartiallySuccessResult(allowedIds, errors); + } + + /// + /// 静音 + /// + /// + /// + internal async Task Mute(string convId) { + ConvCommand conv = new ConvCommand { + Cid = convId + }; + GenericCommand request = NewCommand(CommandType.Conv, OpType.Mute); + request.ConvMessage = conv; + await Client.Connection.SendRequest(request); + } + + /// + /// 解除静音 + /// + /// + /// + internal async Task Unmute(string convId) { + ConvCommand conv = new ConvCommand { + Cid = convId + }; + GenericCommand request = NewCommand(CommandType.Conv, OpType.Unmute); + request.ConvMessage = conv; + await Client.Connection.SendRequest(request); + } + + /// + /// 禁言用户 + /// + /// + /// + /// + internal async Task MuteMembers(string convId, + IEnumerable clientIds) { + if (clientIds == null || clientIds.Count() == 0) { + throw new ArgumentNullException(nameof(clientIds)); + } + ConvCommand conv = new ConvCommand { + Cid = convId + }; + conv.M.AddRange(clientIds); + GenericCommand request = NewCommand(CommandType.Conv, OpType.AddShutup); + request.ConvMessage = conv; + GenericCommand response = await Client.Connection.SendRequest(request); + return NewPartiallySuccessResult(response.ConvMessage.AllowedPids, response.ConvMessage.FailedPids); + } + + /// + /// 解除用户禁言 + /// + /// + /// + /// + internal async Task UnmuteMembers(string convId, + IEnumerable clientIds) { + ConvCommand conv = new ConvCommand { + Cid = convId + }; + conv.M.AddRange(clientIds); + GenericCommand request = NewCommand(CommandType.Conv, OpType.RemoveShutup); + request.ConvMessage = conv; + GenericCommand response = await Client.Connection.SendRequest(request); + return NewPartiallySuccessResult(response.ConvMessage.AllowedPids, response.ConvMessage.FailedPids); + } + + /// + /// 拉黑成员 + /// + /// + /// + /// + internal async Task BlockMembers(string convId, + IEnumerable clientIds) { + BlacklistCommand blacklist = new BlacklistCommand { + SrcCid = convId, + }; + blacklist.ToPids.AddRange(clientIds); + if (Client.SignatureFactory != null) { + LCIMSignature signature = await Client.SignatureFactory.CreateBlacklistSignature(convId, + Client.Id, + clientIds, + LCIMSignatureAction.ConversationBlockClients); + blacklist.S = signature.Signature; + blacklist.T = signature.Timestamp; + blacklist.N = signature.Nonce; + } + GenericCommand request = NewCommand(CommandType.Blacklist, OpType.Block); + request.BlacklistMessage = blacklist; + GenericCommand response = await Client.Connection.SendRequest(request); + return NewPartiallySuccessResult(response.BlacklistMessage.AllowedPids, response.BlacklistMessage.FailedPids); + } + + /// + /// 移除成员黑名单 + /// + /// + /// + /// + internal async Task UnblockMembers(string convId, + IEnumerable clientIds) { + BlacklistCommand blacklist = new BlacklistCommand { + SrcCid = convId, + }; + blacklist.ToPids.AddRange(clientIds); + if (Client.SignatureFactory != null) { + LCIMSignature signature = await Client.SignatureFactory.CreateBlacklistSignature(convId, + Client.Id, + clientIds, + LCIMSignatureAction.ConversationUnblockClients); + blacklist.S = signature.Signature; + blacklist.T = signature.Timestamp; + blacklist.N = signature.Nonce; + } + GenericCommand request = NewCommand(CommandType.Blacklist, OpType.Unblock); + request.BlacklistMessage = blacklist; + GenericCommand response = await Client.Connection.SendRequest(request); + return NewPartiallySuccessResult(response.BlacklistMessage.AllowedPids, response.BlacklistMessage.FailedPids); + } + + /// + /// 修改成员角色 + /// + /// + /// + /// + /// + internal async Task UpdateMemberRole(string convId, + string memberId, + string role) { + ConvCommand conv = new ConvCommand { + Cid = convId, + TargetClientId = memberId, + Info = new ConvMemberInfo { + Pid = memberId, + Role = role + } + }; + GenericCommand request = NewCommand(CommandType.Conv, OpType.MemberInfoUpdate); + request.ConvMessage = conv; + GenericCommand response = await Client.Connection.SendRequest(request); + } + + /// + /// 获取所有成员角色 + /// + /// + /// + internal async Task> GetAllMemberInfo(string convId) { + string path = "classes/_ConversationMemberInfo"; + string token = await Client.SessionController.GetToken(); + Dictionary headers = new Dictionary { + { "X-LC-IM-Session-Token", token } + }; + Dictionary queryParams = new Dictionary { + { "client_id", Client.Id }, + { "cid", convId } + }; + Dictionary response = await LCApplication.HttpClient.Get>(path, + headers: headers, queryParams: queryParams); + List results = response["results"] as List; + return results.Select(item => { + Dictionary memberInfo = item as Dictionary; + return new LCIMConversationMemberInfo { + ConversationId = memberInfo["cid"] as string, + MemberId = memberInfo["clientId"] as string, + Role = memberInfo["role"] as string + }; + }).ToList().AsReadOnly(); + } + + /// + /// 查询禁言成员 + /// + /// + /// + /// + /// + internal async Task QueryMutedMembers(string convId, + int limit = 10, + string next = null) { + ConvCommand conv = new ConvCommand { + Cid = convId, + Limit = limit + }; + if (next != null) { + conv.Next = next; + } + GenericCommand request = NewCommand(CommandType.Conv, OpType.QueryShutup); + request.ConvMessage = conv; + GenericCommand response = await Client.Connection.SendRequest(request); + return new LCIMPageResult { + Results = new ReadOnlyCollection(response.ConvMessage.M), + Next = response.ConvMessage.Next + }; + } + + /// + /// 查询黑名单用户 + /// + /// + /// + /// + /// + internal async Task QueryBlockedMembers(string convId, + int limit = 10, + string next = null) { + BlacklistCommand black = new BlacklistCommand { + SrcCid = convId, + Limit = limit + }; + if (next != null) { + black.Next = next; + } + GenericCommand request = NewCommand(CommandType.Blacklist, OpType.Query); + request.BlacklistMessage = black; + GenericCommand response = await Client.Connection.SendRequest(request); + return new LCIMPageResult { + Results = new ReadOnlyCollection(response.BlacklistMessage.BlockedPids), + Next = response.BlacklistMessage.Next + }; + } + + /// + /// 查找 + /// + /// + /// + internal async Task> Find(LCIMConversationQuery query) { + GenericCommand command = new GenericCommand { + Cmd = CommandType.Conv, + Op = OpType.Query, + AppId = LCApplication.AppId, + PeerId = Client.Id, + }; + ConvCommand convMessage = new ConvCommand(); + string where = query.Condition.BuildWhere(); + if (!string.IsNullOrEmpty(where)) { + try { + convMessage.Where = new JsonObjectMessage { + Data = where + }; + } catch (Exception e) { + LCLogger.Error(e); + } + } + command.ConvMessage = convMessage; + GenericCommand response = await Connection.SendRequest(command); + JsonObjectMessage results = response.ConvMessage.Results; + List convs = JsonConvert.DeserializeObject>(results.Data, new LCJsonConverter()); + return convs.Select(item => { + Dictionary conv = item as Dictionary; + string convId = conv["objectId"] as string; + if (!Client.ConversationDict.TryGetValue(convId, out LCIMConversation conversation)) { + // 解析是哪种类型的对话 + if (conv.TryGetValue("tr", out object transient) && (bool)transient == true) { + conversation = new LCIMChatRoom(Client); + } else if (conv.ContainsKey("tempConv") && conv.ContainsKey("tempConvTTL")) { + conversation = new LCIMTemporaryConversation(Client); + } else if (conv.TryGetValue("sys", out object sys) && (bool)sys == true) { + conversation = new LCIMServiceConversation(Client); + } else { + conversation = new LCIMConversation(Client); + } + Client.ConversationDict[convId] = conversation; + } + conversation.MergeFrom(conv); + return conversation; + }).ToList().AsReadOnly(); + } + + /// + /// 获取临时对话 + /// + /// + /// + internal async Task> GetTemporaryConversations(IEnumerable convIds) { + if (convIds == null || convIds.Count() == 0) { + return null; + } + ConvCommand convMessage = new ConvCommand(); + convMessage.TempConvIds.AddRange(convIds); + GenericCommand request = NewCommand(CommandType.Conv, OpType.Query); + request.ConvMessage = convMessage; + GenericCommand response = await Connection.SendRequest(request); + JsonObjectMessage results = response.ConvMessage.Results; + List convs = JsonConvert.DeserializeObject>(results.Data, new LCJsonConverter()); + List convList = convs.Select(item => { + LCIMTemporaryConversation temporaryConversation = new LCIMTemporaryConversation(Client); + temporaryConversation.MergeFrom(item as Dictionary); + return temporaryConversation; + }).ToList(); + return convList; + } + + /// + /// 拉取对话接收/已读情况 + /// + /// + /// + internal async Task FetchReciptTimestamp(string convId) { + ConvCommand convCommand = new ConvCommand { + Cid = convId + }; + GenericCommand request = NewCommand(CommandType.Conv, OpType.MaxRead); + request.ConvMessage = convCommand; + GenericCommand response = await Connection.SendRequest(request); + convCommand = response.ConvMessage; + LCIMConversation conversation = await Client.GetOrQueryConversation(convCommand.Cid); + conversation.LastDeliveredTimestamp = convCommand.MaxAckTimestamp; + conversation.LastReadTimestamp = convCommand.MaxReadTimestamp; + } + + /// + /// 获取在线成员 + /// + /// + /// + /// + internal async Task> GetOnlineMembers(string convId, + int limit) { + ConvCommand conv = new ConvCommand { + Cid = convId, + Limit = limit + }; + GenericCommand request = NewCommand(CommandType.Conv, OpType.Members); + request.ConvMessage = conv; + GenericCommand response = await Client.Connection.SendRequest(request); + ReadOnlyCollection members = response.ConvMessage.M + .ToList().AsReadOnly(); + return members; + } + + /// + /// 查询是否订阅 + /// + /// + /// + internal async Task CheckSubscription(string convId) { + ConvCommand conv = new ConvCommand(); + conv.Cids.Add(convId); + GenericCommand request = NewCommand(CommandType.Conv, OpType.IsMember); + request.ConvMessage = conv; + GenericCommand response = await Client.Connection.SendRequest(request); + JsonObjectMessage jsonObj = response.ConvMessage.Results; + Dictionary result = JsonConvert.DeserializeObject>(jsonObj.Data); + if (result.TryGetValue(convId, out object obj)) { + return (bool)obj; + } + return false; + } + + 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) { + LCIMOperationFailure failure = new LCIMOperationFailure { + Code = error.Code, + Reason = error.Reason, + IdList = error.Pids?.ToList() + }; + result.FailureList.Add(failure); + } + } + return result; + } + + #endregion + + #region 消息处理 + + internal override async Task OnNotification(GenericCommand notification) { + if (notification.Cmd == CommandType.Conv) { + await OnConversation(notification); + } else if (notification.Cmd == CommandType.Unread) { + await OnUnread(notification); + } + } + + private async Task OnUnread(GenericCommand notification) { + UnreadCommand unread = notification.UnreadMessage; + + IEnumerable convIds = unread.Convs + .Select(conv => conv.Cid); + Dictionary conversationDict = (await Client.GetConversationList(convIds)) + .ToDictionary(item => item.Id); + ReadOnlyCollection conversations = unread.Convs.Select(conv => { + // 设置对话中的未读数据 + LCIMConversation conversation = conversationDict[conv.Cid]; + conversation.Unread = conv.Unread; + if (conv.HasData || conv.HasBinaryMsg) { + // 如果有消息,则反序列化 + LCIMMessage message = null; + if (conv.HasBinaryMsg) { + // 二进制消息 + byte[] bytes = conv.BinaryMsg.ToByteArray(); + message = LCIMBinaryMessage.Deserialize(bytes); + } else { + // 类型消息 + message = LCIMTypedMessage.Deserialize(conv.Data); + } + // 填充消息数据 + message.ConversationId = conv.Cid; + message.Id = conv.Mid; + message.FromClientId = conv.From; + message.SentTimestamp = conv.Timestamp; + message.Mentioned = conv.Mentioned; + conversation.LastMessage = message; + } + return conversation; + }).ToList().AsReadOnly(); + Client.OnUnreadMessagesCountUpdated?.Invoke(conversations); + } + + private async Task OnConversation(GenericCommand notification) { + ConvCommand convMessage = notification.ConvMessage; + switch (notification.Op) { + case OpType.Joined: + await OnJoined(convMessage); + break; + case OpType.MembersJoined: + await OnMembersJoined(convMessage); + break; + case OpType.Left: + await OnLeft(convMessage); + break; + case OpType.MembersLeft: + await OnMemberLeft(convMessage); + break; + case OpType.Blocked: + await OnBlocked(convMessage); + break; + case OpType.Unblocked: + await OnUnblocked(convMessage); + break; + case OpType.MembersBlocked: + await OnMembersBlocked(convMessage); + break; + case OpType.MembersUnblocked: + await OnMembersUnblocked(convMessage); + break; + case OpType.Shutuped: + await OnMuted(convMessage); + break; + case OpType.Unshutuped: + await OnUnmuted(convMessage); + break; + case OpType.MembersShutuped: + await OnMembersMuted(convMessage); + break; + case OpType.MembersUnshutuped: + await OnMembersUnmuted(convMessage); + break; + case OpType.Updated: + await OnPropertiesUpdated(convMessage); + break; + case OpType.MemberInfoChanged: + await OnMemberInfoChanged(convMessage); + break; + default: + break; + } + } + + /// + /// 当前用户加入会话 + /// + /// + /// + private async Task OnJoined(ConvCommand convMessage) { + LCIMConversation conversation = await Client.GetOrQueryConversation(convMessage.Cid); + Client.OnInvited?.Invoke(conversation, convMessage.InitBy); + } + + /// + /// 有用户加入会话 + /// + /// + /// + private async Task OnMembersJoined(ConvCommand convMessage) { + LCIMConversation conversation = await Client.GetOrQueryConversation(convMessage.Cid); + ReadOnlyCollection joinedIds = new ReadOnlyCollection(convMessage.M); + conversation.ids.UnionWith(joinedIds); + Client.OnMembersJoined?.Invoke(conversation, joinedIds, convMessage.InitBy); + } + + /// + /// 当前用户离开会话 + /// + /// + /// + private async Task OnLeft(ConvCommand convMessage) { + LCIMConversation conversation = await Client.GetOrQueryConversation(convMessage.Cid); + // TODO 从内存中清除对话 + + Client.OnKicked?.Invoke(conversation, convMessage.InitBy); + } + + /// + /// 有成员离开会话 + /// + /// + /// + private async Task OnMemberLeft(ConvCommand convMessage) { + LCIMConversation conversation = await Client.GetOrQueryConversation(convMessage.Cid); + ReadOnlyCollection leftIdList = new ReadOnlyCollection(convMessage.M); + conversation.ids.RemoveWhere(item => leftIdList.Contains(item)); + Client.OnMembersLeft?.Invoke(conversation, leftIdList, convMessage.InitBy); + } + + /// + /// 当前用户被禁言 + /// + /// + /// + private async Task OnMuted(ConvCommand convMessage) { + LCIMConversation conversation = await Client.GetOrQueryConversation(convMessage.Cid); + Client.OnMuted?.Invoke(conversation, convMessage.InitBy); + } + + /// + /// 当前用户被解除禁言 + /// + /// + /// + private async Task OnUnmuted(ConvCommand convMessage) { + LCIMConversation conversation = await Client.GetOrQueryConversation(convMessage.Cid); + Client.OnUnmuted?.Invoke(conversation, convMessage.InitBy); + } + + /// + /// 有成员被禁言 + /// + /// + /// + private async Task OnMembersMuted(ConvCommand convMessage) { + LCIMConversation conversation = await Client.GetOrQueryConversation(convMessage.Cid); + ReadOnlyCollection mutedMemberIds = new ReadOnlyCollection(convMessage.M); + conversation.mutedIds.UnionWith(mutedMemberIds); + Client.OnMembersMuted?.Invoke(conversation, mutedMemberIds, convMessage.InitBy); + } + + /// + /// 有成员被解除禁言 + /// + /// + /// + private async Task OnMembersUnmuted(ConvCommand convMessage) { + LCIMConversation conversation = await Client.GetOrQueryConversation(convMessage.Cid); + ReadOnlyCollection unmutedMemberIds = new ReadOnlyCollection(convMessage.M); + conversation.mutedIds.RemoveWhere(id => unmutedMemberIds.Contains(id)); + Client.OnMembersUnmuted?.Invoke(conversation, unmutedMemberIds, convMessage.InitBy); + } + + /// + /// 当前用户被拉黑 + /// + /// + /// + private async Task OnBlocked(ConvCommand convMessage) { + LCIMConversation conversation = await Client.GetOrQueryConversation(convMessage.Cid); + Client.OnBlocked?.Invoke(conversation, convMessage.InitBy); + } + + /// + /// 当前用户被解除黑名单 + /// + /// + /// + private async Task OnUnblocked(ConvCommand convMessage) { + LCIMConversation conversation = await Client.GetOrQueryConversation(convMessage.Cid); + Client.OnUnblocked?.Invoke(conversation, convMessage.InitBy); + } + + /// + /// 有用户被拉黑 + /// + /// + /// + private async Task OnMembersBlocked(ConvCommand convMessage) { + LCIMConversation conversation = await Client.GetOrQueryConversation(convMessage.Cid); + ReadOnlyCollection blockedMemberIds = convMessage.M.ToList().AsReadOnly(); + Client.OnMembersBlocked?.Invoke(conversation, blockedMemberIds, convMessage.InitBy); + } + + /// + /// 有用户被移除黑名单 + /// + /// + /// + private async Task OnMembersUnblocked(ConvCommand convMessage) { + LCIMConversation conversation = await Client.GetOrQueryConversation(convMessage.Cid); + ReadOnlyCollection unblockedMemberIds = convMessage.M.ToList().AsReadOnly(); + Client.OnMembersUnblocked?.Invoke(conversation, unblockedMemberIds, convMessage.InitBy); + } + + /// + /// 对话属性被修改 + /// + /// + /// + private async Task OnPropertiesUpdated(ConvCommand conv) { + LCIMConversation conversation = await Client.GetOrQueryConversation(conv.Cid); + Dictionary updatedAttr = JsonConvert.DeserializeObject>(conv.AttrModified.Data, + new LCJsonConverter()); + // 更新内存数据 + conversation.MergeInfo(updatedAttr); + Client.OnConversationInfoUpdated?.Invoke(conversation, + new ReadOnlyDictionary(updatedAttr), + conv.InitBy); + } + + /// + /// 用户角色被修改 + /// + /// + /// + private async Task OnMemberInfoChanged(ConvCommand conv) { + LCIMConversation conversation = await Client.GetOrQueryConversation(conv.Cid); + ConvMemberInfo memberInfo = conv.Info; + Client.OnMemberInfoUpdated?.Invoke(conversation, memberInfo.Pid, memberInfo.Role, conv.InitBy); + } + + #endregion + } +} diff --git a/Realtime/Internal/Controller/LCIMGoAwayController.cs b/Realtime/Internal/Controller/LCIMGoAwayController.cs new file mode 100644 index 0000000..1bcb57d --- /dev/null +++ b/Realtime/Internal/Controller/LCIMGoAwayController.cs @@ -0,0 +1,19 @@ +using System.Threading.Tasks; +using LeanCloud.Realtime.Internal.Protocol; + +namespace LeanCloud.Realtime.Internal.Controller { + internal class LCIMGoAwayController : LCIMController { + internal LCIMGoAwayController(LCIMClient client) : base(client) { + + } + + #region 消息处理 + + internal override async Task OnNotification(GenericCommand notification) { + // 清空缓存,断开连接,等待重新连接 + await Connection.Reset(); + } + + #endregion + } +} diff --git a/Realtime/Internal/Controller/LCIMMessageController.cs b/Realtime/Internal/Controller/LCIMMessageController.cs new file mode 100644 index 0000000..784a895 --- /dev/null +++ b/Realtime/Internal/Controller/LCIMMessageController.cs @@ -0,0 +1,344 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using System.Collections.ObjectModel; +using Newtonsoft.Json; +using Google.Protobuf; +using LeanCloud.Realtime.Internal.Protocol; + +namespace LeanCloud.Realtime.Internal.Controller { + internal class LCIMMessageController : LCIMController { + internal LCIMMessageController(LCIMClient client) : base(client) { + + } + + #region 内部接口 + + /// + /// 发送消息 + /// + /// + /// + /// + internal async Task Send(string convId, + LCIMMessage message, + LCIMMessageSendOptions options) { + DirectCommand direct = new DirectCommand { + FromPeerId = Client.Id, + Cid = convId, + }; + if (message is LCIMTypedMessage typedMessage) { + direct.Msg = JsonConvert.SerializeObject(typedMessage.Encode()); + } else if (message is LCIMBinaryMessage binaryMessage) { + direct.BinaryMsg = ByteString.CopyFrom(binaryMessage.Data); + } else { + throw new ArgumentException("Message MUST be LCIMTypedMessage or LCIMBinaryMessage."); + } + // 暂态消息 + if (options.Transient) { + direct.Transient = options.Transient; + } + // 消息接收回执 + if (options.Receipt) { + direct.R = options.Receipt; + } + // 遗愿消息 + if (options.Will) { + direct.Will = options.Will; + } + // 推送数据 + if (options.PushData != null) { + direct.PushData = JsonConvert.SerializeObject(options.PushData); + } + // 提醒所有人 + if (message.MentionAll) { + direct.MentionAll = message.MentionAll; + } + // 提醒用户列表 + if (message.MentionIdList != null && + message.MentionIdList.Count > 0) { + direct.MentionPids.AddRange(message.MentionIdList); + } + GenericCommand command = NewCommand(CommandType.Direct); + command.DirectMessage = direct; + // 优先级 + if (command.Priority > 0) { + command.Priority = (int)options.Priority; + } + GenericCommand response = await Client.Connection.SendRequest(command); + // 消息发送应答 + AckCommand ack = response.AckMessage; + message.Id = ack.Uid; + message.SentTimestamp = ack.T; + return message; + } + + /// + /// 撤回消息 + /// + /// + /// + /// + internal async Task RecallMessage(string convId, + LCIMMessage message) { + PatchCommand patch = new PatchCommand(); + PatchItem item = new PatchItem { + Cid = convId, + Mid = message.Id, + From = Client.Id, + Recall = true, + Timestamp = message.SentTimestamp, + PatchTimestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), + }; + patch.Patches.Add(item); + GenericCommand request = NewCommand(CommandType.Patch, OpType.Modify); + request.PatchMessage = patch; + await Client.Connection.SendRequest(request); + } + + /// + /// 修改消息 + /// + /// + /// + /// + /// + internal async Task UpdateMessage(string convId, + LCIMMessage oldMessage, + LCIMMessage newMessage) { + PatchCommand patch = new PatchCommand(); + PatchItem item = new PatchItem { + Cid = convId, + Mid = oldMessage.Id, + From = Client.Id, + Recall = false, + Timestamp = oldMessage.SentTimestamp, + PatchTimestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), + }; + if (newMessage is LCIMTypedMessage typedMessage) { + item.Data = JsonConvert.SerializeObject(typedMessage.Encode()); + } else if (newMessage is LCIMBinaryMessage binaryMessage) { + item.BinaryMsg = ByteString.CopyFrom(binaryMessage.Data); + } + if (newMessage.MentionIdList != null) { + item.MentionPids.AddRange(newMessage.MentionIdList); + } + if (newMessage.MentionAll) { + item.MentionAll = newMessage.MentionAll; + } + patch.Patches.Add(item); + GenericCommand request = NewCommand(CommandType.Patch, OpType.Modify); + request.PatchMessage = patch; + GenericCommand response = await Client.Connection.SendRequest(request); + } + + /// + /// 查询消息 + /// + /// + /// + /// + /// + /// + /// + /// + internal async Task> QueryMessages(string convId, + LCIMMessageQueryEndpoint start = null, + LCIMMessageQueryEndpoint end = null, + LCIMMessageQueryDirection direction = LCIMMessageQueryDirection.NewToOld, + int limit = 20, + int messageType = 0) { + LogsCommand logs = new LogsCommand { + Cid = convId + }; + if (start != null) { + logs.T = start.SentTimestamp; + logs.Mid = start.MessageId; + logs.TIncluded = start.IsClosed; + } + if (end != null) { + logs.Tt = end.SentTimestamp; + logs.Tmid = end.MessageId; + logs.TtIncluded = end.IsClosed; + } + logs.Direction = direction == LCIMMessageQueryDirection.NewToOld ? + LogsCommand.Types.QueryDirection.Old : LogsCommand.Types.QueryDirection.New; + logs.Limit = limit; + if (messageType != 0) { + logs.Lctype = messageType; + } + GenericCommand request = NewCommand(CommandType.Logs, OpType.Open); + request.LogsMessage = logs; + GenericCommand response = await Client.Connection.SendRequest(request); + // 反序列化聊天记录 + return response.LogsMessage.Logs.Select(item => { + LCIMMessage message; + if (item.Bin) { + // 二进制消息 + byte[] bytes = Convert.FromBase64String(item.Data); + message = LCIMBinaryMessage.Deserialize(bytes); + } else { + // 类型消息 + message = LCIMTypedMessage.Deserialize(item.Data); + } + message.ConversationId = convId; + message.Id = item.MsgId; + message.FromClientId = item.From; + message.SentTimestamp = item.Timestamp; + message.DeliveredTimestamp = item.AckAt; + message.ReadTimestamp = item.ReadAt; + message.PatchedTimestamp = item.PatchTimestamp; + message.MentionAll = item.MentionAll; + message.MentionIdList = item.MentionPids.ToList(); + message.Mentioned = message.MentionAll || + message.MentionIdList.Contains(Client.Id); + return message; + }).ToList().AsReadOnly(); + } + + /// + /// 确认收到消息 + /// + /// + /// + /// + internal async Task Ack(string convId, + string msgId) { + AckCommand ack = new AckCommand { + Cid = convId, + Mid = msgId + }; + GenericCommand command = NewCommand(CommandType.Ack); + command.AckMessage = ack; + await Client.Connection.SendCommand(command); + } + + /// + /// 确认已读消息 + /// + /// + /// + /// + internal async Task Read(string convId, + LCIMMessage msg) { + ReadCommand read = new ReadCommand(); + ReadTuple tuple = new ReadTuple { + Cid = convId, + Mid = msg.Id, + Timestamp = msg.SentTimestamp + }; + read.Convs.Add(tuple); + GenericCommand command = NewCommand(CommandType.Read); + command.ReadMessage = read; + await Client.Connection.SendCommand(command); + } + + #endregion + + #region 消息处理 + + internal override async Task OnNotification(GenericCommand notification) { + if (notification.Cmd == CommandType.Direct) { + await OnMessaage(notification); + } else if (notification.Cmd == CommandType.Patch) { + await OnMessagePatched(notification); + } else if (notification.Cmd == CommandType.Rcp) { + await OnMessageReceipt(notification); + } + } + + /// + /// 接收消息事件 + /// + /// + /// + private async Task OnMessaage(GenericCommand notification) { + DirectCommand direct = notification.DirectMessage; + // 反序列化消息 + LCIMMessage message; + if (direct.HasBinaryMsg) { + // 二进制消息 + byte[] bytes = direct.BinaryMsg.ToByteArray(); + message = LCIMBinaryMessage.Deserialize(bytes); + } else { + // 类型消息 + message = LCIMTypedMessage.Deserialize(direct.Msg); + } + // 填充消息数据 + message.ConversationId = direct.Cid; + message.Id = direct.Id; + message.FromClientId = direct.FromPeerId; + message.SentTimestamp = direct.Timestamp; + message.MentionAll = direct.MentionAll; + message.MentionIdList = direct.MentionPids.ToList(); + message.Mentioned = message.MentionAll || + message.MentionIdList.Contains(Client.Id); + message.PatchedTimestamp = direct.PatchTimestamp; + message.IsTransient = direct.Transient; + // 通知服务端已接收 + if (!message.IsTransient) { + // 只有非暂态消息才需要发送 ack + _ = Ack(message.ConversationId, message.Id); + } + // 获取对话 + LCIMConversation conversation = await Client.GetOrQueryConversation(direct.Cid); + conversation.Unread++; + conversation.LastMessage = message; + Client.OnMessage?.Invoke(conversation, message); + } + + /// + /// 消息被修改事件 + /// + /// + /// + private async Task OnMessagePatched(GenericCommand notification) { + PatchCommand patchMessage = notification.PatchMessage; + foreach (PatchItem patch in patchMessage.Patches) { + // 获取对话 + LCIMConversation conversation = await Client.GetOrQueryConversation(patch.Cid); + LCIMMessage message; + if (patch.HasBinaryMsg) { + byte[] bytes = patch.BinaryMsg.ToByteArray(); + message = LCIMBinaryMessage.Deserialize(bytes); + } else { + message = LCIMTypedMessage.Deserialize(patch.Data); + } + message.ConversationId = patch.Cid; + message.Id = patch.Mid; + message.FromClientId = patch.From; + message.SentTimestamp = patch.Timestamp; + message.PatchedTimestamp = patch.PatchTimestamp; + if (message is LCIMRecalledMessage recalledMessage) { + // 消息撤回 + Client.OnMessageRecalled?.Invoke(conversation, recalledMessage); + } else { + // 消息修改 + Client.OnMessageUpdated?.Invoke(conversation, message); + } + } + } + + /// + /// 消息回执事件 + /// + /// + /// + private async Task OnMessageReceipt(GenericCommand notification) { + RcpCommand rcp = notification.RcpMessage; + string convId = rcp.Cid; + string msgId = rcp.Id; + long timestamp = rcp.T; + bool isRead = rcp.Read; + string fromId = rcp.From; + LCIMConversation conversation = await Client.GetOrQueryConversation(convId); + if (isRead) { + Client.OnMessageRead?.Invoke(conversation, msgId); + } else { + Client.OnMessageDelivered?.Invoke(conversation, msgId); + } + } + + #endregion + } +} diff --git a/Realtime/Internal/Controller/LCIMSessionController.cs b/Realtime/Internal/Controller/LCIMSessionController.cs new file mode 100644 index 0000000..28b913c --- /dev/null +++ b/Realtime/Internal/Controller/LCIMSessionController.cs @@ -0,0 +1,148 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using LeanCloud.Realtime.Internal.Protocol; + +namespace LeanCloud.Realtime.Internal.Controller { + internal class LCIMSessionController : LCIMController { + private string token; + private DateTimeOffset expiredAt; + + internal LCIMSessionController(LCIMClient client) + : base(client) { + + } + + #region 内部接口 + + /// + /// 打开会话 + /// + /// + internal async Task Open(bool force) { + SessionCommand session = await NewSessionCommand(); + session.R = !force; + session.ConfigBitmap = 0x2B; + GenericCommand request = NewCommand(CommandType.Session, OpType.Open); + request.SessionMessage = session; + GenericCommand response = await Client.Connection.SendRequest(request); + UpdateSession(response.SessionMessage); + } + + /// + /// 重新打开会话,重连时调用 + /// + /// + internal async Task Reopen() { + SessionCommand session = await NewSessionCommand(); + session.R = true; + GenericCommand request = NewCommand(CommandType.Session, OpType.Open); + request.SessionMessage = session; + GenericCommand response = await Client.Connection.SendRequest(request); + if (response.Op == OpType.Opened) { + UpdateSession(response.SessionMessage); + } else if (response.Op == OpType.Closed) { + await OnClosed(response.SessionMessage); + } + } + + /// + /// 关闭会话 + /// + /// + internal async Task Close() { + GenericCommand request = NewCommand(CommandType.Session, OpType.Close); + await Client.Connection.SendRequest(request); + } + + /// + /// 获取可用 token + /// + /// + internal async Task GetToken() { + if (IsExpired) { + await Refresh(); + } + return token; + } + + #endregion + + private async Task Refresh() { + SessionCommand session = await NewSessionCommand(); + GenericCommand request = NewCommand(CommandType.Session, OpType.Refresh); + request.SessionMessage = session; + GenericCommand response = await Client.Connection.SendRequest(request); + UpdateSession(response.SessionMessage); + } + + private async Task NewSessionCommand() { + SessionCommand session = new SessionCommand(); + if (Client.Tag != null) { + session.Tag = Client.Tag; + } + if (Client.DeviceId != null) { + session.DeviceId = Client.DeviceId; + } + LCIMSignature signature = null; + if (Client.SignatureFactory != null) { + signature = await Client.SignatureFactory.CreateConnectSignature(Client.Id); + } + if (signature == null && !string.IsNullOrEmpty(Client.SessionToken)) { + Dictionary ret = await LCApplication.HttpClient.Post>("rtm/sign", data: new Dictionary { + { "session_token", Client.SessionToken } + }); + signature = new LCIMSignature { + Signature = ret["signature"] as string, + Timestamp = (long)ret["timestamp"], + Nonce = ret["nonce"] as string + }; + } + if (signature != null) { + session.S = signature.Signature; + session.T = signature.Timestamp; + session.N = signature.Nonce; + } + return session; + } + + private void UpdateSession(SessionCommand session) { + token = session.St; + int ttl = session.StTtl; + expiredAt = DateTimeOffset.Now + TimeSpan.FromSeconds(ttl); + } + + private bool IsExpired { + get { + return DateTimeOffset.Now > expiredAt; + } + } + + #region 消息处理 + + internal override async Task OnNotification(GenericCommand notification) { + switch (notification.Op) { + case OpType.Closed: + await OnClosed(notification.SessionMessage); + break; + default: + break; + } + } + + /// + /// 被关闭 + /// + /// + /// + private async Task OnClosed(SessionCommand session) { + int code = session.Code; + string reason = session.Reason; + string detail = session.Detail; + await Connection.Close(); + Client.OnClose?.Invoke(code, reason); + } + + #endregion + } +} diff --git a/Realtime/Internal/Protocol/Messages2Proto.cs b/Realtime/Internal/Protocol/Messages2Proto.cs new file mode 100644 index 0000000..030e37f --- /dev/null +++ b/Realtime/Internal/Protocol/Messages2Proto.cs @@ -0,0 +1,12581 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: messages2.proto.orig +// +#pragma warning disable 1591, 0612, 3021 +#region Designer generated code + +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; +using scg = global::System.Collections.Generic; +namespace LeanCloud.Realtime.Internal.Protocol { + + /// Holder for reflection information generated from messages2.proto.orig + public static partial class Messages2ProtoReflection { + + #region Descriptor + /// File descriptor for messages2.proto.orig + public static pbr::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static Messages2ProtoReflection() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "ChRtZXNzYWdlczIucHJvdG8ub3JpZxIVcHVzaF9zZXJ2ZXIubWVzc2FnZXMy", + "ImEKD1NlbWFudGljVmVyc2lvbhINCgVtYWpvchgBIAEoBRINCgVtaW5vchgC", + "IAEoBRINCgVwYXRjaBgDIAEoBRISCgpwcmVSZWxlYXNlGAQgASgJEg0KBWJ1", + "aWxkGAUgASgJIjQKDkFuZHJvaWRWZXJzaW9uEhAKCGNvZGVuYW1lGAEgASgJ", + "EhAKCGFwaUxldmVsGAIgASgJItEBCgpTeXN0ZW1JbmZvEjUKCmRldmljZVR5", + "cGUYASABKA4yIS5wdXNoX3NlcnZlci5tZXNzYWdlczIuRGV2aWNlVHlwZRI5", + "Cglvc1ZlcnNpb24YAiABKAsyJi5wdXNoX3NlcnZlci5tZXNzYWdlczIuU2Vt", + "YW50aWNWZXJzaW9uEj0KDmFuZHJvaWRWZXJzaW9uGAMgASgLMiUucHVzaF9z", + "ZXJ2ZXIubWVzc2FnZXMyLkFuZHJvaWRWZXJzaW9uEhIKCmlzRW11bGF0b3IY", + "BCABKAgiIQoRSnNvbk9iamVjdE1lc3NhZ2USDAoEZGF0YRgBIAIoCSK2AQoL", + "VW5yZWFkVHVwbGUSCwoDY2lkGAEgAigJEg4KBnVucmVhZBgCIAIoBRILCgNt", + "aWQYAyABKAkSEQoJdGltZXN0YW1wGAQgASgDEgwKBGZyb20YBSABKAkSDAoE", + "ZGF0YRgGIAEoCRIWCg5wYXRjaFRpbWVzdGFtcBgHIAEoAxIRCgltZW50aW9u", + "ZWQYCCABKAgSEQoJYmluYXJ5TXNnGAkgASgMEhAKCGNvbnZUeXBlGAogASgF", + "IsYBCgdMb2dJdGVtEgwKBGZyb20YASABKAkSDAoEZGF0YRgCIAEoCRIRCgl0", + "aW1lc3RhbXAYAyABKAMSDQoFbXNnSWQYBCABKAkSDQoFYWNrQXQYBSABKAMS", + "DgoGcmVhZEF0GAYgASgDEhYKDnBhdGNoVGltZXN0YW1wGAcgASgDEhIKCm1l", + "bnRpb25BbGwYCCABKAgSEwoLbWVudGlvblBpZHMYCSADKAkSCwoDYmluGAog", + "ASgIEhAKCGNvbnZUeXBlGAsgASgFIjsKDkNvbnZNZW1iZXJJbmZvEgsKA3Bp", + "ZBgBIAEoCRIMCgRyb2xlGAIgASgJEg4KBmluZm9JZBgDIAEoCSJFCgxMb2dp", + "bkNvbW1hbmQSNQoKc3lzdGVtSW5mbxgBIAEoCzIhLnB1c2hfc2VydmVyLm1l", + "c3NhZ2VzMi5TeXN0ZW1JbmZvIicKD0xvZ2dlZGluQ29tbWFuZBIUCgxwdXNo", + "RGlzYWJsZWQYASABKAgiYgoLRGF0YUNvbW1hbmQSCwoDaWRzGAEgAygJEjUK", + "A21zZxgCIAMoCzIoLnB1c2hfc2VydmVyLm1lc3NhZ2VzMi5Kc29uT2JqZWN0", + "TWVzc2FnZRIPCgdvZmZsaW5lGAMgASgIIogDCg5TZXNzaW9uQ29tbWFuZBIJ", + "CgF0GAEgASgDEgkKAW4YAiABKAkSCQoBcxgDIAEoCRIKCgJ1YRgEIAEoCRIJ", + "CgFyGAUgASgIEgsKA3RhZxgGIAEoCRIQCghkZXZpY2VJZBgHIAEoCRIWCg5z", + "ZXNzaW9uUGVlcklkcxgIIAMoCRIcChRvbmxpbmVTZXNzaW9uUGVlcklkcxgJ", + "IAMoCRIKCgJzdBgKIAEoCRINCgVzdFR0bBgLIAEoBRIMCgRjb2RlGAwgASgF", + "Eg4KBnJlYXNvbhgNIAEoCRITCgtkZXZpY2VUb2tlbhgOIAEoCRIKCgJzcBgP", + "IAEoCBIOCgZkZXRhaWwYECABKAkSGwoTbGFzdFVucmVhZE5vdGlmVGltZRgR", + "IAEoAxIVCg1sYXN0UGF0Y2hUaW1lGBIgASgDEhQKDGNvbmZpZ0JpdG1hcBgT", + "IAEoAxI1CgpzeXN0ZW1JbmZvGBQgASgLMiEucHVzaF9zZXJ2ZXIubWVzc2Fn", + "ZXMyLlN5c3RlbUluZm8iawoMRXJyb3JDb21tYW5kEgwKBGNvZGUYASACKAUS", + "DgoGcmVhc29uGAIgAigJEg8KB2FwcENvZGUYAyABKAUSDgoGZGV0YWlsGAQg", + "ASgJEgwKBHBpZHMYBSADKAkSDgoGYXBwTXNnGAYgASgJIt4CCg1EaXJlY3RD", + "b21tYW5kEgsKA21zZxgBIAEoCRILCgN1aWQYAiABKAkSEgoKZnJvbVBlZXJJ", + "ZBgDIAEoCRIRCgl0aW1lc3RhbXAYBCABKAMSDwoHb2ZmbGluZRgFIAEoCBIP", + "CgdoYXNNb3JlGAYgASgIEhEKCXRvUGVlcklkcxgHIAMoCRIJCgFyGAogASgI", + "EgsKA2NpZBgLIAEoCRIKCgJpZBgMIAEoCRIRCgl0cmFuc2llbnQYDSABKAgS", + "CgoCZHQYDiABKAkSDgoGcm9vbUlkGA8gASgJEhAKCHB1c2hEYXRhGBAgASgJ", + "EgwKBHdpbGwYESABKAgSFgoOcGF0Y2hUaW1lc3RhbXAYEiABKAMSEQoJYmlu", + "YXJ5TXNnGBMgASgMEhMKC21lbnRpb25QaWRzGBQgAygJEhIKCm1lbnRpb25B", + "bGwYFSABKAgSEAoIY29udlR5cGUYFiABKAUitgEKCkFja0NvbW1hbmQSDAoE", + "Y29kZRgBIAEoBRIOCgZyZWFzb24YAiABKAkSCwoDbWlkGAMgASgJEgsKA2Np", + "ZBgEIAEoCRIJCgF0GAUgASgDEgsKA3VpZBgGIAEoCRIOCgZmcm9tdHMYByAB", + "KAMSDAoEdG90cxgIIAEoAxIMCgR0eXBlGAkgASgJEgsKA2lkcxgKIAMoCRIP", + "CgdhcHBDb2RlGAsgASgFEg4KBmFwcE1zZxgMIAEoCSJVCg1VbnJlYWRDb21t", + "YW5kEjEKBWNvbnZzGAEgAygLMiIucHVzaF9zZXJ2ZXIubWVzc2FnZXMyLlVu", + "cmVhZFR1cGxlEhEKCW5vdGlmVGltZRgCIAEoAyKRBwoLQ29udkNvbW1hbmQS", + "CQoBbRgBIAMoCRIRCgl0cmFuc2llbnQYAiABKAgSDgoGdW5pcXVlGAMgASgI", + "EgsKA2NpZBgEIAEoCRINCgVjZGF0ZRgFIAEoCRIOCgZpbml0QnkYBiABKAkS", + "DAoEc29ydBgHIAEoCRINCgVsaW1pdBgIIAEoBRIMCgRza2lwGAkgASgFEgwK", + "BGZsYWcYCiABKAUSDQoFY291bnQYCyABKAUSDQoFdWRhdGUYDCABKAkSCQoB", + "dBgNIAEoAxIJCgFuGA4gASgJEgkKAXMYDyABKAkSEQoJc3RhdHVzU3ViGBAg", + "ASgIEhEKCXN0YXR1c1B1YhgRIAEoCBIRCglzdGF0dXNUVEwYEiABKAUSEAoI", + "dW5pcXVlSWQYEyABKAkSFgoOdGFyZ2V0Q2xpZW50SWQYFCABKAkSGAoQbWF4", + "UmVhZFRpbWVzdGFtcBgVIAEoAxIXCg9tYXhBY2tUaW1lc3RhbXAYFiABKAMS", + "FwoPcXVlcnlBbGxNZW1iZXJzGBcgASgIEjoKDW1heFJlYWRUdXBsZXMYGCAD", + "KAsyIy5wdXNoX3NlcnZlci5tZXNzYWdlczIuTWF4UmVhZFR1cGxlEgwKBGNp", + "ZHMYGSADKAkSMwoEaW5mbxgaIAEoCzIlLnB1c2hfc2VydmVyLm1lc3NhZ2Vz", + "Mi5Db252TWVtYmVySW5mbxIQCgh0ZW1wQ29udhgbIAEoCBITCgt0ZW1wQ29u", + "dlRUTBgcIAEoBRITCgt0ZW1wQ29udklkcxgdIAMoCRITCgthbGxvd2VkUGlk", + "cxgeIAMoCRI3CgpmYWlsZWRQaWRzGB8gAygLMiMucHVzaF9zZXJ2ZXIubWVz", + "c2FnZXMyLkVycm9yQ29tbWFuZBIMCgRuZXh0GCggASgJEjkKB3Jlc3VsdHMY", + "ZCABKAsyKC5wdXNoX3NlcnZlci5tZXNzYWdlczIuSnNvbk9iamVjdE1lc3Nh", + "Z2USNwoFd2hlcmUYZSABKAsyKC5wdXNoX3NlcnZlci5tZXNzYWdlczIuSnNv", + "bk9iamVjdE1lc3NhZ2USNgoEYXR0chhnIAEoCzIoLnB1c2hfc2VydmVyLm1l", + "c3NhZ2VzMi5Kc29uT2JqZWN0TWVzc2FnZRI+CgxhdHRyTW9kaWZpZWQYaCAB", + "KAsyKC5wdXNoX3NlcnZlci5tZXNzYWdlczIuSnNvbk9iamVjdE1lc3NhZ2Ui", + "eAoLUm9vbUNvbW1hbmQSDgoGcm9vbUlkGAEgASgJEgkKAXMYAiABKAkSCQoB", + "dBgDIAEoAxIJCgFuGAQgASgJEhEKCXRyYW5zaWVudBgFIAEoCBITCgtyb29t", + "UGVlcklkcxgGIAMoCRIQCghieVBlZXJJZBgHIAEoCSLcAgoLTG9nc0NvbW1h", + "bmQSCwoDY2lkGAEgASgJEgkKAWwYAiABKAUSDQoFbGltaXQYAyABKAUSCQoB", + "dBgEIAEoAxIKCgJ0dBgFIAEoAxIMCgR0bWlkGAYgASgJEgsKA21pZBgHIAEo", + "CRIQCghjaGVja3N1bRgIIAEoCRIOCgZzdG9yZWQYCSABKAgSSQoJZGlyZWN0", + "aW9uGAogASgOMjEucHVzaF9zZXJ2ZXIubWVzc2FnZXMyLkxvZ3NDb21tYW5k", + "LlF1ZXJ5RGlyZWN0aW9uOgNPTEQSEQoJdEluY2x1ZGVkGAsgASgIEhIKCnR0", + "SW5jbHVkZWQYDCABKAgSDgoGbGN0eXBlGA0gASgFEiwKBGxvZ3MYaSADKAsy", + "Hi5wdXNoX3NlcnZlci5tZXNzYWdlczIuTG9nSXRlbSIiCg5RdWVyeURpcmVj", + "dGlvbhIHCgNPTEQQARIHCgNORVcQAiJMCgpSY3BDb21tYW5kEgoKAmlkGAEg", + "ASgJEgsKA2NpZBgCIAEoCRIJCgF0GAMgASgDEgwKBHJlYWQYBCABKAgSDAoE", + "ZnJvbRgFIAEoCSI4CglSZWFkVHVwbGUSCwoDY2lkGAEgAigJEhEKCXRpbWVz", + "dGFtcBgCIAEoAxILCgNtaWQYAyABKAkiTgoMTWF4UmVhZFR1cGxlEgsKA3Bp", + "ZBgBIAEoCRIXCg9tYXhBY2tUaW1lc3RhbXAYAiABKAMSGAoQbWF4UmVhZFRp", + "bWVzdGFtcBgDIAEoAyJZCgtSZWFkQ29tbWFuZBILCgNjaWQYASABKAkSDAoE", + "Y2lkcxgCIAMoCRIvCgVjb252cxgDIAMoCzIgLnB1c2hfc2VydmVyLm1lc3Nh", + "Z2VzMi5SZWFkVHVwbGUiaQoPUHJlc2VuY2VDb21tYW5kEjEKBnN0YXR1cxgB", + "IAEoDjIhLnB1c2hfc2VydmVyLm1lc3NhZ2VzMi5TdGF0dXNUeXBlEhYKDnNl", + "c3Npb25QZWVySWRzGAIgAygJEgsKA2NpZBgDIAEoCSI/Cg1SZXBvcnRDb21t", + "YW5kEhIKCmluaXRpYXRpdmUYASABKAgSDAoEdHlwZRgCIAEoCRIMCgRkYXRh", + "GAMgASgJIuABCglQYXRjaEl0ZW0SCwoDY2lkGAEgASgJEgsKA21pZBgCIAEo", + "CRIRCgl0aW1lc3RhbXAYAyABKAMSDgoGcmVjYWxsGAQgASgIEgwKBGRhdGEY", + "BSABKAkSFgoOcGF0Y2hUaW1lc3RhbXAYBiABKAMSDAoEZnJvbRgHIAEoCRIR", + "CgliaW5hcnlNc2cYCCABKAwSEgoKbWVudGlvbkFsbBgJIAEoCBITCgttZW50", + "aW9uUGlkcxgKIAMoCRIRCglwYXRjaENvZGUYCyABKAMSEwoLcGF0Y2hSZWFz", + "b24YDCABKAkiWAoMUGF0Y2hDb21tYW5kEjEKB3BhdGNoZXMYASADKAsyIC5w", + "dXNoX3NlcnZlci5tZXNzYWdlczIuUGF0Y2hJdGVtEhUKDWxhc3RQYXRjaFRp", + "bWUYAiABKAMiqQEKDVB1YnN1YkNvbW1hbmQSCwoDY2lkGAEgASgJEgwKBGNp", + "ZHMYAiADKAkSDQoFdG9waWMYAyABKAkSEAoIc3VidG9waWMYBCABKAkSDgoG", + "dG9waWNzGAUgAygJEhEKCXN1YnRvcGljcxgGIAMoCRI5CgdyZXN1bHRzGAcg", + "ASgLMigucHVzaF9zZXJ2ZXIubWVzc2FnZXMyLkpzb25PYmplY3RNZXNzYWdl", + "IogCChBCbGFja2xpc3RDb21tYW5kEg4KBnNyY0NpZBgBIAEoCRIOCgZ0b1Bp", + "ZHMYAiADKAkSDgoGc3JjUGlkGAMgASgJEg4KBnRvQ2lkcxgEIAMoCRINCgVs", + "aW1pdBgFIAEoBRIMCgRuZXh0GAYgASgJEhMKC2Jsb2NrZWRQaWRzGAggAygJ", + "EhMKC2Jsb2NrZWRDaWRzGAkgAygJEhMKC2FsbG93ZWRQaWRzGAogAygJEjcK", + "CmZhaWxlZFBpZHMYCyADKAsyIy5wdXNoX3NlcnZlci5tZXNzYWdlczIuRXJy", + "b3JDb21tYW5kEgkKAXQYDCABKAMSCQoBbhgNIAEoCRIJCgFzGA4gASgJIsMK", + "Cg5HZW5lcmljQ29tbWFuZBIvCgNjbWQYASABKA4yIi5wdXNoX3NlcnZlci5t", + "ZXNzYWdlczIuQ29tbWFuZFR5cGUSKQoCb3AYAiABKA4yHS5wdXNoX3NlcnZl", + "ci5tZXNzYWdlczIuT3BUeXBlEg0KBWFwcElkGAMgASgJEg4KBnBlZXJJZBgE", + "IAEoCRIJCgFpGAUgASgFEhYKDmluc3RhbGxhdGlvbklkGAYgASgJEhAKCHBy", + "aW9yaXR5GAcgASgFEg8KB3NlcnZpY2UYCCABKAUSEAoIc2VydmVyVHMYCSAB", + "KAMSEAoIY2xpZW50VHMYCiABKAMSGAoQbm90aWZpY2F0aW9uVHlwZRgLIAEo", + "BRI5Cgxsb2dpbk1lc3NhZ2UYZCABKAsyIy5wdXNoX3NlcnZlci5tZXNzYWdl", + "czIuTG9naW5Db21tYW5kEjcKC2RhdGFNZXNzYWdlGGUgASgLMiIucHVzaF9z", + "ZXJ2ZXIubWVzc2FnZXMyLkRhdGFDb21tYW5kEj0KDnNlc3Npb25NZXNzYWdl", + "GGYgASgLMiUucHVzaF9zZXJ2ZXIubWVzc2FnZXMyLlNlc3Npb25Db21tYW5k", + "EjkKDGVycm9yTWVzc2FnZRhnIAEoCzIjLnB1c2hfc2VydmVyLm1lc3NhZ2Vz", + "Mi5FcnJvckNvbW1hbmQSOwoNZGlyZWN0TWVzc2FnZRhoIAEoCzIkLnB1c2hf", + "c2VydmVyLm1lc3NhZ2VzMi5EaXJlY3RDb21tYW5kEjUKCmFja01lc3NhZ2UY", + "aSABKAsyIS5wdXNoX3NlcnZlci5tZXNzYWdlczIuQWNrQ29tbWFuZBI7Cg11", + "bnJlYWRNZXNzYWdlGGogASgLMiQucHVzaF9zZXJ2ZXIubWVzc2FnZXMyLlVu", + "cmVhZENvbW1hbmQSNwoLcmVhZE1lc3NhZ2UYayABKAsyIi5wdXNoX3NlcnZl", + "ci5tZXNzYWdlczIuUmVhZENvbW1hbmQSNQoKcmNwTWVzc2FnZRhsIAEoCzIh", + "LnB1c2hfc2VydmVyLm1lc3NhZ2VzMi5SY3BDb21tYW5kEjcKC2xvZ3NNZXNz", + "YWdlGG0gASgLMiIucHVzaF9zZXJ2ZXIubWVzc2FnZXMyLkxvZ3NDb21tYW5k", + "EjcKC2NvbnZNZXNzYWdlGG4gASgLMiIucHVzaF9zZXJ2ZXIubWVzc2FnZXMy", + "LkNvbnZDb21tYW5kEjcKC3Jvb21NZXNzYWdlGG8gASgLMiIucHVzaF9zZXJ2", + "ZXIubWVzc2FnZXMyLlJvb21Db21tYW5kEj8KD3ByZXNlbmNlTWVzc2FnZRhw", + "IAEoCzImLnB1c2hfc2VydmVyLm1lc3NhZ2VzMi5QcmVzZW5jZUNvbW1hbmQS", + "OwoNcmVwb3J0TWVzc2FnZRhxIAEoCzIkLnB1c2hfc2VydmVyLm1lc3NhZ2Vz", + "Mi5SZXBvcnRDb21tYW5kEjkKDHBhdGNoTWVzc2FnZRhyIAEoCzIjLnB1c2hf", + "c2VydmVyLm1lc3NhZ2VzMi5QYXRjaENvbW1hbmQSOwoNcHVic3ViTWVzc2Fn", + "ZRhzIAEoCzIkLnB1c2hfc2VydmVyLm1lc3NhZ2VzMi5QdWJzdWJDb21tYW5k", + "EkEKEGJsYWNrbGlzdE1lc3NhZ2UYdCABKAsyJy5wdXNoX3NlcnZlci5tZXNz", + "YWdlczIuQmxhY2tsaXN0Q29tbWFuZBI/Cg9sb2dnZWRpbk1lc3NhZ2UYdSAB", + "KAsyJi5wdXNoX3NlcnZlci5tZXNzYWdlczIuTG9nZ2VkaW5Db21tYW5kKosC", + "CgtDb21tYW5kVHlwZRILCgdzZXNzaW9uEAASCAoEY29udhABEgoKBmRpcmVj", + "dBACEgcKA2FjaxADEgcKA3JjcBAEEgoKBnVucmVhZBAFEggKBGxvZ3MQBhIJ", + "CgVlcnJvchAHEgkKBWxvZ2luEAgSCAoEZGF0YRAJEggKBHJvb20QChIICgRy", + "ZWFkEAsSDAoIcHJlc2VuY2UQDBIKCgZyZXBvcnQQDRIICgRlY2hvEA4SDAoI", + "bG9nZ2VkaW4QDxIKCgZsb2dvdXQQEBINCglsb2dnZWRvdXQQERIJCgVwYXRj", + "aBASEgoKBnB1YnN1YhATEg0KCWJsYWNrbGlzdBAUEgoKBmdvYXdheRAVKo0I", + "CgZPcFR5cGUSCAoEb3BlbhABEgcKA2FkZBACEgoKBnJlbW92ZRADEgkKBWNs", + "b3NlEAQSCgoGb3BlbmVkEAUSCgoGY2xvc2VkEAYSCQoFcXVlcnkQBxIQCgxx", + "dWVyeV9yZXN1bHQQCBIMCghjb25mbGljdBAJEgkKBWFkZGVkEAoSCwoHcmVt", + "b3ZlZBALEgsKB3JlZnJlc2gQDBINCglyZWZyZXNoZWQQDRIJCgVzdGFydBAe", + "EgsKB3N0YXJ0ZWQQHxIKCgZqb2luZWQQIBISCg5tZW1iZXJzX2pvaW5lZBAh", + "EggKBGxlZnQQJxIQCgxtZW1iZXJzX2xlZnQQKBILCgdyZXN1bHRzECoSCQoF", + "Y291bnQQKxIKCgZyZXN1bHQQLBIKCgZ1cGRhdGUQLRILCgd1cGRhdGVkEC4S", + "CAoEbXV0ZRAvEgoKBnVubXV0ZRAwEgoKBnN0YXR1cxAxEgsKB21lbWJlcnMQ", + "MhIMCghtYXhfcmVhZBAzEg0KCWlzX21lbWJlchA0EhYKEm1lbWJlcl9pbmZv", + "X3VwZGF0ZRA1EhcKE21lbWJlcl9pbmZvX3VwZGF0ZWQQNhIXChNtZW1iZXJf", + "aW5mb19jaGFuZ2VkEDcSCAoEam9pbhBQEgoKBmludml0ZRBREgkKBWxlYXZl", + "EFISCAoEa2ljaxBTEgoKBnJlamVjdBBUEgsKB2ludml0ZWQQVRIKCgZraWNr", + "ZWQQVhIKCgZ1cGxvYWQQZBIMCgh1cGxvYWRlZBBlEg0KCXN1YnNjcmliZRB4", + "Eg4KCnN1YnNjcmliZWQQeRIPCgt1bnN1YnNjcmliZRB6EhAKDHVuc3Vic2Ny", + "aWJlZBB7EhEKDWlzX3N1YnNjcmliZWQQfBILCgZtb2RpZnkQlgESDQoIbW9k", + "aWZpZWQQlwESCgoFYmxvY2sQqgESDAoHdW5ibG9jaxCrARIMCgdibG9ja2Vk", + "EKwBEg4KCXVuYmxvY2tlZBCtARIUCg9tZW1iZXJzX2Jsb2NrZWQQrgESFgoR", + "bWVtYmVyc191bmJsb2NrZWQQrwESEAoLY2hlY2tfYmxvY2sQsAESEQoMY2hl", + "Y2tfcmVzdWx0ELEBEg8KCmFkZF9zaHV0dXAQtAESEgoNcmVtb3ZlX3NodXR1", + "cBC1ARIRCgxxdWVyeV9zaHV0dXAQtgESEQoMc2h1dHVwX2FkZGVkELcBEhMK", + "DnNodXR1cF9yZW1vdmVkELgBEhIKDXNodXR1cF9yZXN1bHQQuQESDQoIc2h1", + "dHVwZWQQugESDwoKdW5zaHV0dXBlZBC7ARIVChBtZW1iZXJzX3NodXR1cGVk", + "ELwBEhcKEm1lbWJlcnNfdW5zaHV0dXBlZBC9ARIRCgxjaGVja19zaHV0dXAQ", + "vgEqHQoKU3RhdHVzVHlwZRIGCgJvbhABEgcKA29mZhACKi8KCkRldmljZVR5", + "cGUSCwoHdW5rbm93bhAAEgsKB2FuZHJvaWQQARIHCgNpb3MQAkIuogIEQVZJ", + "TaoCJExlYW5DbG91ZC5SZWFsdGltZS5JbnRlcm5hbC5Qcm90b2NvbA==")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, + new pbr::FileDescriptor[] { }, + new pbr::GeneratedClrTypeInfo(new[] {typeof(global::LeanCloud.Realtime.Internal.Protocol.CommandType), typeof(global::LeanCloud.Realtime.Internal.Protocol.OpType), typeof(global::LeanCloud.Realtime.Internal.Protocol.StatusType), typeof(global::LeanCloud.Realtime.Internal.Protocol.DeviceType), }, null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::LeanCloud.Realtime.Internal.Protocol.SemanticVersion), global::LeanCloud.Realtime.Internal.Protocol.SemanticVersion.Parser, new[]{ "Major", "Minor", "Patch", "PreRelease", "Build" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::LeanCloud.Realtime.Internal.Protocol.AndroidVersion), global::LeanCloud.Realtime.Internal.Protocol.AndroidVersion.Parser, new[]{ "Codename", "ApiLevel" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::LeanCloud.Realtime.Internal.Protocol.SystemInfo), global::LeanCloud.Realtime.Internal.Protocol.SystemInfo.Parser, new[]{ "DeviceType", "OsVersion", "AndroidVersion", "IsEmulator" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::LeanCloud.Realtime.Internal.Protocol.JsonObjectMessage), global::LeanCloud.Realtime.Internal.Protocol.JsonObjectMessage.Parser, new[]{ "Data" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::LeanCloud.Realtime.Internal.Protocol.UnreadTuple), global::LeanCloud.Realtime.Internal.Protocol.UnreadTuple.Parser, new[]{ "Cid", "Unread", "Mid", "Timestamp", "From", "Data", "PatchTimestamp", "Mentioned", "BinaryMsg", "ConvType" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::LeanCloud.Realtime.Internal.Protocol.LogItem), global::LeanCloud.Realtime.Internal.Protocol.LogItem.Parser, new[]{ "From", "Data", "Timestamp", "MsgId", "AckAt", "ReadAt", "PatchTimestamp", "MentionAll", "MentionPids", "Bin", "ConvType" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::LeanCloud.Realtime.Internal.Protocol.ConvMemberInfo), global::LeanCloud.Realtime.Internal.Protocol.ConvMemberInfo.Parser, new[]{ "Pid", "Role", "InfoId" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::LeanCloud.Realtime.Internal.Protocol.LoginCommand), global::LeanCloud.Realtime.Internal.Protocol.LoginCommand.Parser, new[]{ "SystemInfo" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::LeanCloud.Realtime.Internal.Protocol.LoggedinCommand), global::LeanCloud.Realtime.Internal.Protocol.LoggedinCommand.Parser, new[]{ "PushDisabled" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::LeanCloud.Realtime.Internal.Protocol.DataCommand), global::LeanCloud.Realtime.Internal.Protocol.DataCommand.Parser, new[]{ "Ids", "Msg", "Offline" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::LeanCloud.Realtime.Internal.Protocol.SessionCommand), global::LeanCloud.Realtime.Internal.Protocol.SessionCommand.Parser, new[]{ "T", "N", "S", "Ua", "R", "Tag", "DeviceId", "SessionPeerIds", "OnlineSessionPeerIds", "St", "StTtl", "Code", "Reason", "DeviceToken", "Sp", "Detail", "LastUnreadNotifTime", "LastPatchTime", "ConfigBitmap", "SystemInfo" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::LeanCloud.Realtime.Internal.Protocol.ErrorCommand), global::LeanCloud.Realtime.Internal.Protocol.ErrorCommand.Parser, new[]{ "Code", "Reason", "AppCode", "Detail", "Pids", "AppMsg" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::LeanCloud.Realtime.Internal.Protocol.DirectCommand), global::LeanCloud.Realtime.Internal.Protocol.DirectCommand.Parser, new[]{ "Msg", "Uid", "FromPeerId", "Timestamp", "Offline", "HasMore", "ToPeerIds", "R", "Cid", "Id", "Transient", "Dt", "RoomId", "PushData", "Will", "PatchTimestamp", "BinaryMsg", "MentionPids", "MentionAll", "ConvType" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::LeanCloud.Realtime.Internal.Protocol.AckCommand), global::LeanCloud.Realtime.Internal.Protocol.AckCommand.Parser, new[]{ "Code", "Reason", "Mid", "Cid", "T", "Uid", "Fromts", "Tots", "Type", "Ids", "AppCode", "AppMsg" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::LeanCloud.Realtime.Internal.Protocol.UnreadCommand), global::LeanCloud.Realtime.Internal.Protocol.UnreadCommand.Parser, new[]{ "Convs", "NotifTime" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::LeanCloud.Realtime.Internal.Protocol.ConvCommand), global::LeanCloud.Realtime.Internal.Protocol.ConvCommand.Parser, new[]{ "M", "Transient", "Unique", "Cid", "Cdate", "InitBy", "Sort", "Limit", "Skip", "Flag", "Count", "Udate", "T", "N", "S", "StatusSub", "StatusPub", "StatusTTL", "UniqueId", "TargetClientId", "MaxReadTimestamp", "MaxAckTimestamp", "QueryAllMembers", "MaxReadTuples", "Cids", "Info", "TempConv", "TempConvTTL", "TempConvIds", "AllowedPids", "FailedPids", "Next", "Results", "Where", "Attr", "AttrModified" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::LeanCloud.Realtime.Internal.Protocol.RoomCommand), global::LeanCloud.Realtime.Internal.Protocol.RoomCommand.Parser, new[]{ "RoomId", "S", "T", "N", "Transient", "RoomPeerIds", "ByPeerId" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::LeanCloud.Realtime.Internal.Protocol.LogsCommand), global::LeanCloud.Realtime.Internal.Protocol.LogsCommand.Parser, new[]{ "Cid", "L", "Limit", "T", "Tt", "Tmid", "Mid", "Checksum", "Stored", "Direction", "TIncluded", "TtIncluded", "Lctype", "Logs" }, null, new[]{ typeof(global::LeanCloud.Realtime.Internal.Protocol.LogsCommand.Types.QueryDirection) }, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::LeanCloud.Realtime.Internal.Protocol.RcpCommand), global::LeanCloud.Realtime.Internal.Protocol.RcpCommand.Parser, new[]{ "Id", "Cid", "T", "Read", "From" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::LeanCloud.Realtime.Internal.Protocol.ReadTuple), global::LeanCloud.Realtime.Internal.Protocol.ReadTuple.Parser, new[]{ "Cid", "Timestamp", "Mid" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::LeanCloud.Realtime.Internal.Protocol.MaxReadTuple), global::LeanCloud.Realtime.Internal.Protocol.MaxReadTuple.Parser, new[]{ "Pid", "MaxAckTimestamp", "MaxReadTimestamp" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::LeanCloud.Realtime.Internal.Protocol.ReadCommand), global::LeanCloud.Realtime.Internal.Protocol.ReadCommand.Parser, new[]{ "Cid", "Cids", "Convs" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::LeanCloud.Realtime.Internal.Protocol.PresenceCommand), global::LeanCloud.Realtime.Internal.Protocol.PresenceCommand.Parser, new[]{ "Status", "SessionPeerIds", "Cid" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::LeanCloud.Realtime.Internal.Protocol.ReportCommand), global::LeanCloud.Realtime.Internal.Protocol.ReportCommand.Parser, new[]{ "Initiative", "Type", "Data" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::LeanCloud.Realtime.Internal.Protocol.PatchItem), global::LeanCloud.Realtime.Internal.Protocol.PatchItem.Parser, new[]{ "Cid", "Mid", "Timestamp", "Recall", "Data", "PatchTimestamp", "From", "BinaryMsg", "MentionAll", "MentionPids", "PatchCode", "PatchReason" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::LeanCloud.Realtime.Internal.Protocol.PatchCommand), global::LeanCloud.Realtime.Internal.Protocol.PatchCommand.Parser, new[]{ "Patches", "LastPatchTime" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::LeanCloud.Realtime.Internal.Protocol.PubsubCommand), global::LeanCloud.Realtime.Internal.Protocol.PubsubCommand.Parser, new[]{ "Cid", "Cids", "Topic", "Subtopic", "Topics", "Subtopics", "Results" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::LeanCloud.Realtime.Internal.Protocol.BlacklistCommand), global::LeanCloud.Realtime.Internal.Protocol.BlacklistCommand.Parser, new[]{ "SrcCid", "ToPids", "SrcPid", "ToCids", "Limit", "Next", "BlockedPids", "BlockedCids", "AllowedPids", "FailedPids", "T", "N", "S" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::LeanCloud.Realtime.Internal.Protocol.GenericCommand), global::LeanCloud.Realtime.Internal.Protocol.GenericCommand.Parser, new[]{ "Cmd", "Op", "AppId", "PeerId", "I", "InstallationId", "Priority", "Service", "ServerTs", "ClientTs", "NotificationType", "LoginMessage", "DataMessage", "SessionMessage", "ErrorMessage", "DirectMessage", "AckMessage", "UnreadMessage", "ReadMessage", "RcpMessage", "LogsMessage", "ConvMessage", "RoomMessage", "PresenceMessage", "ReportMessage", "PatchMessage", "PubsubMessage", "BlacklistMessage", "LoggedinMessage" }, null, null, null, null) + })); + } + #endregion + + } + #region Enums + public enum CommandType { + [pbr::OriginalName("session")] Session = 0, + [pbr::OriginalName("conv")] Conv = 1, + [pbr::OriginalName("direct")] Direct = 2, + [pbr::OriginalName("ack")] Ack = 3, + [pbr::OriginalName("rcp")] Rcp = 4, + [pbr::OriginalName("unread")] Unread = 5, + [pbr::OriginalName("logs")] Logs = 6, + [pbr::OriginalName("error")] Error = 7, + [pbr::OriginalName("login")] Login = 8, + [pbr::OriginalName("data")] Data = 9, + [pbr::OriginalName("room")] Room = 10, + [pbr::OriginalName("read")] Read = 11, + [pbr::OriginalName("presence")] Presence = 12, + [pbr::OriginalName("report")] Report = 13, + [pbr::OriginalName("echo")] Echo = 14, + [pbr::OriginalName("loggedin")] Loggedin = 15, + [pbr::OriginalName("logout")] Logout = 16, + [pbr::OriginalName("loggedout")] Loggedout = 17, + [pbr::OriginalName("patch")] Patch = 18, + [pbr::OriginalName("pubsub")] Pubsub = 19, + [pbr::OriginalName("blacklist")] Blacklist = 20, + [pbr::OriginalName("goaway")] Goaway = 21, + } + + public enum OpType { + /// + /// session + /// + [pbr::OriginalName("open")] Open = 1, + [pbr::OriginalName("add")] Add = 2, + [pbr::OriginalName("remove")] Remove = 3, + [pbr::OriginalName("close")] Close = 4, + [pbr::OriginalName("opened")] Opened = 5, + [pbr::OriginalName("closed")] Closed = 6, + [pbr::OriginalName("query")] Query = 7, + [pbr::OriginalName("query_result")] QueryResult = 8, + [pbr::OriginalName("conflict")] Conflict = 9, + [pbr::OriginalName("added")] Added = 10, + [pbr::OriginalName("removed")] Removed = 11, + [pbr::OriginalName("refresh")] Refresh = 12, + [pbr::OriginalName("refreshed")] Refreshed = 13, + /// + /// conv + /// + [pbr::OriginalName("start")] Start = 30, + [pbr::OriginalName("started")] Started = 31, + [pbr::OriginalName("joined")] Joined = 32, + [pbr::OriginalName("members_joined")] MembersJoined = 33, + /// + /// add = 34; reuse session.add + /// added = 35; reuse session.added + /// remove = 37; reuse session.remove + /// removed = 38; reuse session.removed + /// + [pbr::OriginalName("left")] Left = 39, + [pbr::OriginalName("members_left")] MembersLeft = 40, + /// + /// query = 41; reuse session.query + /// + [pbr::OriginalName("results")] Results = 42, + [pbr::OriginalName("count")] Count = 43, + [pbr::OriginalName("result")] Result = 44, + [pbr::OriginalName("update")] Update = 45, + [pbr::OriginalName("updated")] Updated = 46, + [pbr::OriginalName("mute")] Mute = 47, + [pbr::OriginalName("unmute")] Unmute = 48, + [pbr::OriginalName("status")] Status = 49, + [pbr::OriginalName("members")] Members = 50, + [pbr::OriginalName("max_read")] MaxRead = 51, + [pbr::OriginalName("is_member")] IsMember = 52, + [pbr::OriginalName("member_info_update")] MemberInfoUpdate = 53, + [pbr::OriginalName("member_info_updated")] MemberInfoUpdated = 54, + [pbr::OriginalName("member_info_changed")] MemberInfoChanged = 55, + /// + /// room + /// + [pbr::OriginalName("join")] Join = 80, + [pbr::OriginalName("invite")] Invite = 81, + [pbr::OriginalName("leave")] Leave = 82, + [pbr::OriginalName("kick")] Kick = 83, + [pbr::OriginalName("reject")] Reject = 84, + [pbr::OriginalName("invited")] Invited = 85, + /// + /// joined = 32; reuse the value in conv section + /// left = 39; reuse the value in conv section + /// + [pbr::OriginalName("kicked")] Kicked = 86, + /// + /// report + /// + [pbr::OriginalName("upload")] Upload = 100, + [pbr::OriginalName("uploaded")] Uploaded = 101, + /// + /// pubsub + /// + [pbr::OriginalName("subscribe")] Subscribe = 120, + [pbr::OriginalName("subscribed")] Subscribed = 121, + [pbr::OriginalName("unsubscribe")] Unsubscribe = 122, + [pbr::OriginalName("unsubscribed")] Unsubscribed = 123, + [pbr::OriginalName("is_subscribed")] IsSubscribed = 124, + /// + /// patch + /// + [pbr::OriginalName("modify")] Modify = 150, + [pbr::OriginalName("modified")] Modified = 151, + /// + /// blacklist, query, query_result defined with 7, 8 + /// + [pbr::OriginalName("block")] Block = 170, + [pbr::OriginalName("unblock")] Unblock = 171, + [pbr::OriginalName("blocked")] Blocked = 172, + [pbr::OriginalName("unblocked")] Unblocked = 173, + [pbr::OriginalName("members_blocked")] MembersBlocked = 174, + [pbr::OriginalName("members_unblocked")] MembersUnblocked = 175, + [pbr::OriginalName("check_block")] CheckBlock = 176, + [pbr::OriginalName("check_result")] CheckResult = 177, + [pbr::OriginalName("add_shutup")] AddShutup = 180, + [pbr::OriginalName("remove_shutup")] RemoveShutup = 181, + [pbr::OriginalName("query_shutup")] QueryShutup = 182, + [pbr::OriginalName("shutup_added")] ShutupAdded = 183, + [pbr::OriginalName("shutup_removed")] ShutupRemoved = 184, + [pbr::OriginalName("shutup_result")] ShutupResult = 185, + [pbr::OriginalName("shutuped")] Shutuped = 186, + [pbr::OriginalName("unshutuped")] Unshutuped = 187, + [pbr::OriginalName("members_shutuped")] MembersShutuped = 188, + [pbr::OriginalName("members_unshutuped")] MembersUnshutuped = 189, + /// + /// check_result define in 177 + /// + [pbr::OriginalName("check_shutup")] CheckShutup = 190, + } + + public enum StatusType { + [pbr::OriginalName("on")] On = 1, + [pbr::OriginalName("off")] Off = 2, + } + + public enum DeviceType { + [pbr::OriginalName("unknown")] Unknown = 0, + [pbr::OriginalName("android")] Android = 1, + [pbr::OriginalName("ios")] Ios = 2, + } + + #endregion + + #region Messages + public sealed partial class SemanticVersion : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new SemanticVersion()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::LeanCloud.Realtime.Internal.Protocol.Messages2ProtoReflection.Descriptor.MessageTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public SemanticVersion() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public SemanticVersion(SemanticVersion other) : this() { + _hasBits0 = other._hasBits0; + major_ = other.major_; + minor_ = other.minor_; + patch_ = other.patch_; + preRelease_ = other.preRelease_; + build_ = other.build_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public SemanticVersion Clone() { + return new SemanticVersion(this); + } + + /// Field number for the "major" field. + public const int MajorFieldNumber = 1; + private readonly static int MajorDefaultValue = 0; + + private int major_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Major { + get { if ((_hasBits0 & 1) != 0) { return major_; } else { return MajorDefaultValue; } } + set { + _hasBits0 |= 1; + major_ = value; + } + } + /// Gets whether the "major" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasMajor { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "major" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearMajor() { + _hasBits0 &= ~1; + } + + /// Field number for the "minor" field. + public const int MinorFieldNumber = 2; + private readonly static int MinorDefaultValue = 0; + + private int minor_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Minor { + get { if ((_hasBits0 & 2) != 0) { return minor_; } else { return MinorDefaultValue; } } + set { + _hasBits0 |= 2; + minor_ = value; + } + } + /// Gets whether the "minor" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasMinor { + get { return (_hasBits0 & 2) != 0; } + } + /// Clears the value of the "minor" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearMinor() { + _hasBits0 &= ~2; + } + + /// Field number for the "patch" field. + public const int PatchFieldNumber = 3; + private readonly static int PatchDefaultValue = 0; + + private int patch_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Patch { + get { if ((_hasBits0 & 4) != 0) { return patch_; } else { return PatchDefaultValue; } } + set { + _hasBits0 |= 4; + patch_ = value; + } + } + /// Gets whether the "patch" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasPatch { + get { return (_hasBits0 & 4) != 0; } + } + /// Clears the value of the "patch" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearPatch() { + _hasBits0 &= ~4; + } + + /// Field number for the "preRelease" field. + public const int PreReleaseFieldNumber = 4; + private readonly static string PreReleaseDefaultValue = ""; + + private string preRelease_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string PreRelease { + get { return preRelease_ ?? PreReleaseDefaultValue; } + set { + preRelease_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "preRelease" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasPreRelease { + get { return preRelease_ != null; } + } + /// Clears the value of the "preRelease" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearPreRelease() { + preRelease_ = null; + } + + /// Field number for the "build" field. + public const int BuildFieldNumber = 5; + private readonly static string BuildDefaultValue = ""; + + private string build_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Build { + get { return build_ ?? BuildDefaultValue; } + set { + build_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "build" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasBuild { + get { return build_ != null; } + } + /// Clears the value of the "build" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearBuild() { + build_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as SemanticVersion); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(SemanticVersion other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Major != other.Major) return false; + if (Minor != other.Minor) return false; + if (Patch != other.Patch) return false; + if (PreRelease != other.PreRelease) return false; + if (Build != other.Build) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasMajor) hash ^= Major.GetHashCode(); + if (HasMinor) hash ^= Minor.GetHashCode(); + if (HasPatch) hash ^= Patch.GetHashCode(); + if (HasPreRelease) hash ^= PreRelease.GetHashCode(); + if (HasBuild) hash ^= Build.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (HasMajor) { + output.WriteRawTag(8); + output.WriteInt32(Major); + } + if (HasMinor) { + output.WriteRawTag(16); + output.WriteInt32(Minor); + } + if (HasPatch) { + output.WriteRawTag(24); + output.WriteInt32(Patch); + } + if (HasPreRelease) { + output.WriteRawTag(34); + output.WriteString(PreRelease); + } + if (HasBuild) { + output.WriteRawTag(42); + output.WriteString(Build); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasMajor) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Major); + } + if (HasMinor) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Minor); + } + if (HasPatch) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Patch); + } + if (HasPreRelease) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(PreRelease); + } + if (HasBuild) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Build); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(SemanticVersion other) { + if (other == null) { + return; + } + if (other.HasMajor) { + Major = other.Major; + } + if (other.HasMinor) { + Minor = other.Minor; + } + if (other.HasPatch) { + Patch = other.Patch; + } + if (other.HasPreRelease) { + PreRelease = other.PreRelease; + } + if (other.HasBuild) { + Build = other.Build; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + Major = input.ReadInt32(); + break; + } + case 16: { + Minor = input.ReadInt32(); + break; + } + case 24: { + Patch = input.ReadInt32(); + break; + } + case 34: { + PreRelease = input.ReadString(); + break; + } + case 42: { + Build = input.ReadString(); + break; + } + } + } + } + + } + + public sealed partial class AndroidVersion : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new AndroidVersion()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::LeanCloud.Realtime.Internal.Protocol.Messages2ProtoReflection.Descriptor.MessageTypes[1]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public AndroidVersion() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public AndroidVersion(AndroidVersion other) : this() { + codename_ = other.codename_; + apiLevel_ = other.apiLevel_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public AndroidVersion Clone() { + return new AndroidVersion(this); + } + + /// Field number for the "codename" field. + public const int CodenameFieldNumber = 1; + private readonly static string CodenameDefaultValue = ""; + + private string codename_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Codename { + get { return codename_ ?? CodenameDefaultValue; } + set { + codename_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "codename" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasCodename { + get { return codename_ != null; } + } + /// Clears the value of the "codename" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearCodename() { + codename_ = null; + } + + /// Field number for the "apiLevel" field. + public const int ApiLevelFieldNumber = 2; + private readonly static string ApiLevelDefaultValue = ""; + + private string apiLevel_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string ApiLevel { + get { return apiLevel_ ?? ApiLevelDefaultValue; } + set { + apiLevel_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "apiLevel" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasApiLevel { + get { return apiLevel_ != null; } + } + /// Clears the value of the "apiLevel" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearApiLevel() { + apiLevel_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as AndroidVersion); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(AndroidVersion other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Codename != other.Codename) return false; + if (ApiLevel != other.ApiLevel) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasCodename) hash ^= Codename.GetHashCode(); + if (HasApiLevel) hash ^= ApiLevel.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (HasCodename) { + output.WriteRawTag(10); + output.WriteString(Codename); + } + if (HasApiLevel) { + output.WriteRawTag(18); + output.WriteString(ApiLevel); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasCodename) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Codename); + } + if (HasApiLevel) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(ApiLevel); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(AndroidVersion other) { + if (other == null) { + return; + } + if (other.HasCodename) { + Codename = other.Codename; + } + if (other.HasApiLevel) { + ApiLevel = other.ApiLevel; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + Codename = input.ReadString(); + break; + } + case 18: { + ApiLevel = input.ReadString(); + break; + } + } + } + } + + } + + public sealed partial class SystemInfo : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new SystemInfo()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::LeanCloud.Realtime.Internal.Protocol.Messages2ProtoReflection.Descriptor.MessageTypes[2]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public SystemInfo() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public SystemInfo(SystemInfo other) : this() { + _hasBits0 = other._hasBits0; + deviceType_ = other.deviceType_; + osVersion_ = other.HasOsVersion ? other.osVersion_.Clone() : null; + androidVersion_ = other.HasAndroidVersion ? other.androidVersion_.Clone() : null; + isEmulator_ = other.isEmulator_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public SystemInfo Clone() { + return new SystemInfo(this); + } + + /// Field number for the "deviceType" field. + public const int DeviceTypeFieldNumber = 1; + private readonly static global::LeanCloud.Realtime.Internal.Protocol.DeviceType DeviceTypeDefaultValue = global::LeanCloud.Realtime.Internal.Protocol.DeviceType.Unknown; + + private global::LeanCloud.Realtime.Internal.Protocol.DeviceType deviceType_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::LeanCloud.Realtime.Internal.Protocol.DeviceType DeviceType { + get { if ((_hasBits0 & 1) != 0) { return deviceType_; } else { return DeviceTypeDefaultValue; } } + set { + _hasBits0 |= 1; + deviceType_ = value; + } + } + /// Gets whether the "deviceType" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDeviceType { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "deviceType" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDeviceType() { + _hasBits0 &= ~1; + } + + /// Field number for the "osVersion" field. + public const int OsVersionFieldNumber = 2; + private global::LeanCloud.Realtime.Internal.Protocol.SemanticVersion osVersion_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::LeanCloud.Realtime.Internal.Protocol.SemanticVersion OsVersion { + get { return osVersion_; } + set { + osVersion_ = value; + } + } + /// Gets whether the osVersion field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOsVersion { + get { return osVersion_ != null; } + } + /// Clears the value of the osVersion field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOsVersion() { + osVersion_ = null; + } + + /// Field number for the "androidVersion" field. + public const int AndroidVersionFieldNumber = 3; + private global::LeanCloud.Realtime.Internal.Protocol.AndroidVersion androidVersion_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::LeanCloud.Realtime.Internal.Protocol.AndroidVersion AndroidVersion { + get { return androidVersion_; } + set { + androidVersion_ = value; + } + } + /// Gets whether the androidVersion field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasAndroidVersion { + get { return androidVersion_ != null; } + } + /// Clears the value of the androidVersion field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearAndroidVersion() { + androidVersion_ = null; + } + + /// Field number for the "isEmulator" field. + public const int IsEmulatorFieldNumber = 4; + private readonly static bool IsEmulatorDefaultValue = false; + + private bool isEmulator_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool IsEmulator { + get { if ((_hasBits0 & 2) != 0) { return isEmulator_; } else { return IsEmulatorDefaultValue; } } + set { + _hasBits0 |= 2; + isEmulator_ = value; + } + } + /// Gets whether the "isEmulator" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasIsEmulator { + get { return (_hasBits0 & 2) != 0; } + } + /// Clears the value of the "isEmulator" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearIsEmulator() { + _hasBits0 &= ~2; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as SystemInfo); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(SystemInfo other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (DeviceType != other.DeviceType) return false; + if (!object.Equals(OsVersion, other.OsVersion)) return false; + if (!object.Equals(AndroidVersion, other.AndroidVersion)) return false; + if (IsEmulator != other.IsEmulator) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasDeviceType) hash ^= DeviceType.GetHashCode(); + if (HasOsVersion) hash ^= OsVersion.GetHashCode(); + if (HasAndroidVersion) hash ^= AndroidVersion.GetHashCode(); + if (HasIsEmulator) hash ^= IsEmulator.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (HasDeviceType) { + output.WriteRawTag(8); + output.WriteEnum((int) DeviceType); + } + if (HasOsVersion) { + output.WriteRawTag(18); + output.WriteMessage(OsVersion); + } + if (HasAndroidVersion) { + output.WriteRawTag(26); + output.WriteMessage(AndroidVersion); + } + if (HasIsEmulator) { + output.WriteRawTag(32); + output.WriteBool(IsEmulator); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasDeviceType) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) DeviceType); + } + if (HasOsVersion) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(OsVersion); + } + if (HasAndroidVersion) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(AndroidVersion); + } + if (HasIsEmulator) { + size += 1 + 1; + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(SystemInfo other) { + if (other == null) { + return; + } + if (other.HasDeviceType) { + DeviceType = other.DeviceType; + } + if (other.HasOsVersion) { + if (!HasOsVersion) { + OsVersion = new global::LeanCloud.Realtime.Internal.Protocol.SemanticVersion(); + } + OsVersion.MergeFrom(other.OsVersion); + } + if (other.HasAndroidVersion) { + if (!HasAndroidVersion) { + AndroidVersion = new global::LeanCloud.Realtime.Internal.Protocol.AndroidVersion(); + } + AndroidVersion.MergeFrom(other.AndroidVersion); + } + if (other.HasIsEmulator) { + IsEmulator = other.IsEmulator; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + DeviceType = (global::LeanCloud.Realtime.Internal.Protocol.DeviceType) input.ReadEnum(); + break; + } + case 18: { + if (!HasOsVersion) { + OsVersion = new global::LeanCloud.Realtime.Internal.Protocol.SemanticVersion(); + } + input.ReadMessage(OsVersion); + break; + } + case 26: { + if (!HasAndroidVersion) { + AndroidVersion = new global::LeanCloud.Realtime.Internal.Protocol.AndroidVersion(); + } + input.ReadMessage(AndroidVersion); + break; + } + case 32: { + IsEmulator = input.ReadBool(); + break; + } + } + } + } + + } + + public sealed partial class JsonObjectMessage : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new JsonObjectMessage()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::LeanCloud.Realtime.Internal.Protocol.Messages2ProtoReflection.Descriptor.MessageTypes[3]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public JsonObjectMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public JsonObjectMessage(JsonObjectMessage other) : this() { + data_ = other.data_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public JsonObjectMessage Clone() { + return new JsonObjectMessage(this); + } + + /// Field number for the "data" field. + public const int DataFieldNumber = 1; + private readonly static string DataDefaultValue = ""; + + private string data_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Data { + get { return data_ ?? DataDefaultValue; } + set { + data_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "data" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasData { + get { return data_ != null; } + } + /// Clears the value of the "data" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearData() { + data_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as JsonObjectMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(JsonObjectMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Data != other.Data) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasData) hash ^= Data.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (HasData) { + output.WriteRawTag(10); + output.WriteString(Data); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasData) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Data); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(JsonObjectMessage other) { + if (other == null) { + return; + } + if (other.HasData) { + Data = other.Data; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + Data = input.ReadString(); + break; + } + } + } + } + + } + + public sealed partial class UnreadTuple : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new UnreadTuple()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::LeanCloud.Realtime.Internal.Protocol.Messages2ProtoReflection.Descriptor.MessageTypes[4]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public UnreadTuple() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public UnreadTuple(UnreadTuple other) : this() { + _hasBits0 = other._hasBits0; + cid_ = other.cid_; + unread_ = other.unread_; + mid_ = other.mid_; + timestamp_ = other.timestamp_; + from_ = other.from_; + data_ = other.data_; + patchTimestamp_ = other.patchTimestamp_; + mentioned_ = other.mentioned_; + binaryMsg_ = other.binaryMsg_; + convType_ = other.convType_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public UnreadTuple Clone() { + return new UnreadTuple(this); + } + + /// Field number for the "cid" field. + public const int CidFieldNumber = 1; + private readonly static string CidDefaultValue = ""; + + private string cid_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Cid { + get { return cid_ ?? CidDefaultValue; } + set { + cid_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "cid" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasCid { + get { return cid_ != null; } + } + /// Clears the value of the "cid" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearCid() { + cid_ = null; + } + + /// Field number for the "unread" field. + public const int UnreadFieldNumber = 2; + private readonly static int UnreadDefaultValue = 0; + + private int unread_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Unread { + get { if ((_hasBits0 & 1) != 0) { return unread_; } else { return UnreadDefaultValue; } } + set { + _hasBits0 |= 1; + unread_ = value; + } + } + /// Gets whether the "unread" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasUnread { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "unread" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearUnread() { + _hasBits0 &= ~1; + } + + /// Field number for the "mid" field. + public const int MidFieldNumber = 3; + private readonly static string MidDefaultValue = ""; + + private string mid_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Mid { + get { return mid_ ?? MidDefaultValue; } + set { + mid_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "mid" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasMid { + get { return mid_ != null; } + } + /// Clears the value of the "mid" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearMid() { + mid_ = null; + } + + /// Field number for the "timestamp" field. + public const int TimestampFieldNumber = 4; + private readonly static long TimestampDefaultValue = 0L; + + private long timestamp_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long Timestamp { + get { if ((_hasBits0 & 2) != 0) { return timestamp_; } else { return TimestampDefaultValue; } } + set { + _hasBits0 |= 2; + timestamp_ = value; + } + } + /// Gets whether the "timestamp" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasTimestamp { + get { return (_hasBits0 & 2) != 0; } + } + /// Clears the value of the "timestamp" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearTimestamp() { + _hasBits0 &= ~2; + } + + /// Field number for the "from" field. + public const int FromFieldNumber = 5; + private readonly static string FromDefaultValue = ""; + + private string from_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string From { + get { return from_ ?? FromDefaultValue; } + set { + from_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "from" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasFrom { + get { return from_ != null; } + } + /// Clears the value of the "from" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearFrom() { + from_ = null; + } + + /// Field number for the "data" field. + public const int DataFieldNumber = 6; + private readonly static string DataDefaultValue = ""; + + private string data_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Data { + get { return data_ ?? DataDefaultValue; } + set { + data_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "data" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasData { + get { return data_ != null; } + } + /// Clears the value of the "data" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearData() { + data_ = null; + } + + /// Field number for the "patchTimestamp" field. + public const int PatchTimestampFieldNumber = 7; + private readonly static long PatchTimestampDefaultValue = 0L; + + private long patchTimestamp_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long PatchTimestamp { + get { if ((_hasBits0 & 4) != 0) { return patchTimestamp_; } else { return PatchTimestampDefaultValue; } } + set { + _hasBits0 |= 4; + patchTimestamp_ = value; + } + } + /// Gets whether the "patchTimestamp" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasPatchTimestamp { + get { return (_hasBits0 & 4) != 0; } + } + /// Clears the value of the "patchTimestamp" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearPatchTimestamp() { + _hasBits0 &= ~4; + } + + /// Field number for the "mentioned" field. + public const int MentionedFieldNumber = 8; + private readonly static bool MentionedDefaultValue = false; + + private bool mentioned_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Mentioned { + get { if ((_hasBits0 & 8) != 0) { return mentioned_; } else { return MentionedDefaultValue; } } + set { + _hasBits0 |= 8; + mentioned_ = value; + } + } + /// Gets whether the "mentioned" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasMentioned { + get { return (_hasBits0 & 8) != 0; } + } + /// Clears the value of the "mentioned" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearMentioned() { + _hasBits0 &= ~8; + } + + /// Field number for the "binaryMsg" field. + public const int BinaryMsgFieldNumber = 9; + private readonly static pb::ByteString BinaryMsgDefaultValue = pb::ByteString.Empty; + + private pb::ByteString binaryMsg_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pb::ByteString BinaryMsg { + get { return binaryMsg_ ?? BinaryMsgDefaultValue; } + set { + binaryMsg_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "binaryMsg" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasBinaryMsg { + get { return binaryMsg_ != null; } + } + /// Clears the value of the "binaryMsg" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearBinaryMsg() { + binaryMsg_ = null; + } + + /// Field number for the "convType" field. + public const int ConvTypeFieldNumber = 10; + private readonly static int ConvTypeDefaultValue = 0; + + private int convType_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int ConvType { + get { if ((_hasBits0 & 16) != 0) { return convType_; } else { return ConvTypeDefaultValue; } } + set { + _hasBits0 |= 16; + convType_ = value; + } + } + /// Gets whether the "convType" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasConvType { + get { return (_hasBits0 & 16) != 0; } + } + /// Clears the value of the "convType" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearConvType() { + _hasBits0 &= ~16; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as UnreadTuple); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(UnreadTuple other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Cid != other.Cid) return false; + if (Unread != other.Unread) return false; + if (Mid != other.Mid) return false; + if (Timestamp != other.Timestamp) return false; + if (From != other.From) return false; + if (Data != other.Data) return false; + if (PatchTimestamp != other.PatchTimestamp) return false; + if (Mentioned != other.Mentioned) return false; + if (BinaryMsg != other.BinaryMsg) return false; + if (ConvType != other.ConvType) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasCid) hash ^= Cid.GetHashCode(); + if (HasUnread) hash ^= Unread.GetHashCode(); + if (HasMid) hash ^= Mid.GetHashCode(); + if (HasTimestamp) hash ^= Timestamp.GetHashCode(); + if (HasFrom) hash ^= From.GetHashCode(); + if (HasData) hash ^= Data.GetHashCode(); + if (HasPatchTimestamp) hash ^= PatchTimestamp.GetHashCode(); + if (HasMentioned) hash ^= Mentioned.GetHashCode(); + if (HasBinaryMsg) hash ^= BinaryMsg.GetHashCode(); + if (HasConvType) hash ^= ConvType.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (HasCid) { + output.WriteRawTag(10); + output.WriteString(Cid); + } + if (HasUnread) { + output.WriteRawTag(16); + output.WriteInt32(Unread); + } + if (HasMid) { + output.WriteRawTag(26); + output.WriteString(Mid); + } + if (HasTimestamp) { + output.WriteRawTag(32); + output.WriteInt64(Timestamp); + } + if (HasFrom) { + output.WriteRawTag(42); + output.WriteString(From); + } + if (HasData) { + output.WriteRawTag(50); + output.WriteString(Data); + } + if (HasPatchTimestamp) { + output.WriteRawTag(56); + output.WriteInt64(PatchTimestamp); + } + if (HasMentioned) { + output.WriteRawTag(64); + output.WriteBool(Mentioned); + } + if (HasBinaryMsg) { + output.WriteRawTag(74); + output.WriteBytes(BinaryMsg); + } + if (HasConvType) { + output.WriteRawTag(80); + output.WriteInt32(ConvType); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasCid) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Cid); + } + if (HasUnread) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Unread); + } + if (HasMid) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Mid); + } + if (HasTimestamp) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(Timestamp); + } + if (HasFrom) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(From); + } + if (HasData) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Data); + } + if (HasPatchTimestamp) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(PatchTimestamp); + } + if (HasMentioned) { + size += 1 + 1; + } + if (HasBinaryMsg) { + size += 1 + pb::CodedOutputStream.ComputeBytesSize(BinaryMsg); + } + if (HasConvType) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(ConvType); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(UnreadTuple other) { + if (other == null) { + return; + } + if (other.HasCid) { + Cid = other.Cid; + } + if (other.HasUnread) { + Unread = other.Unread; + } + if (other.HasMid) { + Mid = other.Mid; + } + if (other.HasTimestamp) { + Timestamp = other.Timestamp; + } + if (other.HasFrom) { + From = other.From; + } + if (other.HasData) { + Data = other.Data; + } + if (other.HasPatchTimestamp) { + PatchTimestamp = other.PatchTimestamp; + } + if (other.HasMentioned) { + Mentioned = other.Mentioned; + } + if (other.HasBinaryMsg) { + BinaryMsg = other.BinaryMsg; + } + if (other.HasConvType) { + ConvType = other.ConvType; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + Cid = input.ReadString(); + break; + } + case 16: { + Unread = input.ReadInt32(); + break; + } + case 26: { + Mid = input.ReadString(); + break; + } + case 32: { + Timestamp = input.ReadInt64(); + break; + } + case 42: { + From = input.ReadString(); + break; + } + case 50: { + Data = input.ReadString(); + break; + } + case 56: { + PatchTimestamp = input.ReadInt64(); + break; + } + case 64: { + Mentioned = input.ReadBool(); + break; + } + case 74: { + BinaryMsg = input.ReadBytes(); + break; + } + case 80: { + ConvType = input.ReadInt32(); + break; + } + } + } + } + + } + + public sealed partial class LogItem : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new LogItem()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::LeanCloud.Realtime.Internal.Protocol.Messages2ProtoReflection.Descriptor.MessageTypes[5]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public LogItem() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public LogItem(LogItem other) : this() { + _hasBits0 = other._hasBits0; + from_ = other.from_; + data_ = other.data_; + timestamp_ = other.timestamp_; + msgId_ = other.msgId_; + ackAt_ = other.ackAt_; + readAt_ = other.readAt_; + patchTimestamp_ = other.patchTimestamp_; + mentionAll_ = other.mentionAll_; + mentionPids_ = other.mentionPids_.Clone(); + bin_ = other.bin_; + convType_ = other.convType_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public LogItem Clone() { + return new LogItem(this); + } + + /// Field number for the "from" field. + public const int FromFieldNumber = 1; + private readonly static string FromDefaultValue = ""; + + private string from_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string From { + get { return from_ ?? FromDefaultValue; } + set { + from_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "from" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasFrom { + get { return from_ != null; } + } + /// Clears the value of the "from" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearFrom() { + from_ = null; + } + + /// Field number for the "data" field. + public const int DataFieldNumber = 2; + private readonly static string DataDefaultValue = ""; + + private string data_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Data { + get { return data_ ?? DataDefaultValue; } + set { + data_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "data" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasData { + get { return data_ != null; } + } + /// Clears the value of the "data" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearData() { + data_ = null; + } + + /// Field number for the "timestamp" field. + public const int TimestampFieldNumber = 3; + private readonly static long TimestampDefaultValue = 0L; + + private long timestamp_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long Timestamp { + get { if ((_hasBits0 & 1) != 0) { return timestamp_; } else { return TimestampDefaultValue; } } + set { + _hasBits0 |= 1; + timestamp_ = value; + } + } + /// Gets whether the "timestamp" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasTimestamp { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "timestamp" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearTimestamp() { + _hasBits0 &= ~1; + } + + /// Field number for the "msgId" field. + public const int MsgIdFieldNumber = 4; + private readonly static string MsgIdDefaultValue = ""; + + private string msgId_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string MsgId { + get { return msgId_ ?? MsgIdDefaultValue; } + set { + msgId_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "msgId" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasMsgId { + get { return msgId_ != null; } + } + /// Clears the value of the "msgId" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearMsgId() { + msgId_ = null; + } + + /// Field number for the "ackAt" field. + public const int AckAtFieldNumber = 5; + private readonly static long AckAtDefaultValue = 0L; + + private long ackAt_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long AckAt { + get { if ((_hasBits0 & 2) != 0) { return ackAt_; } else { return AckAtDefaultValue; } } + set { + _hasBits0 |= 2; + ackAt_ = value; + } + } + /// Gets whether the "ackAt" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasAckAt { + get { return (_hasBits0 & 2) != 0; } + } + /// Clears the value of the "ackAt" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearAckAt() { + _hasBits0 &= ~2; + } + + /// Field number for the "readAt" field. + public const int ReadAtFieldNumber = 6; + private readonly static long ReadAtDefaultValue = 0L; + + private long readAt_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long ReadAt { + get { if ((_hasBits0 & 4) != 0) { return readAt_; } else { return ReadAtDefaultValue; } } + set { + _hasBits0 |= 4; + readAt_ = value; + } + } + /// Gets whether the "readAt" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasReadAt { + get { return (_hasBits0 & 4) != 0; } + } + /// Clears the value of the "readAt" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearReadAt() { + _hasBits0 &= ~4; + } + + /// Field number for the "patchTimestamp" field. + public const int PatchTimestampFieldNumber = 7; + private readonly static long PatchTimestampDefaultValue = 0L; + + private long patchTimestamp_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long PatchTimestamp { + get { if ((_hasBits0 & 8) != 0) { return patchTimestamp_; } else { return PatchTimestampDefaultValue; } } + set { + _hasBits0 |= 8; + patchTimestamp_ = value; + } + } + /// Gets whether the "patchTimestamp" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasPatchTimestamp { + get { return (_hasBits0 & 8) != 0; } + } + /// Clears the value of the "patchTimestamp" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearPatchTimestamp() { + _hasBits0 &= ~8; + } + + /// Field number for the "mentionAll" field. + public const int MentionAllFieldNumber = 8; + private readonly static bool MentionAllDefaultValue = false; + + private bool mentionAll_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool MentionAll { + get { if ((_hasBits0 & 16) != 0) { return mentionAll_; } else { return MentionAllDefaultValue; } } + set { + _hasBits0 |= 16; + mentionAll_ = value; + } + } + /// Gets whether the "mentionAll" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasMentionAll { + get { return (_hasBits0 & 16) != 0; } + } + /// Clears the value of the "mentionAll" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearMentionAll() { + _hasBits0 &= ~16; + } + + /// Field number for the "mentionPids" field. + public const int MentionPidsFieldNumber = 9; + private static readonly pb::FieldCodec _repeated_mentionPids_codec + = pb::FieldCodec.ForString(74); + private readonly pbc::RepeatedField mentionPids_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField MentionPids { + get { return mentionPids_; } + } + + /// Field number for the "bin" field. + public const int BinFieldNumber = 10; + private readonly static bool BinDefaultValue = false; + + private bool bin_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Bin { + get { if ((_hasBits0 & 32) != 0) { return bin_; } else { return BinDefaultValue; } } + set { + _hasBits0 |= 32; + bin_ = value; + } + } + /// Gets whether the "bin" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasBin { + get { return (_hasBits0 & 32) != 0; } + } + /// Clears the value of the "bin" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearBin() { + _hasBits0 &= ~32; + } + + /// Field number for the "convType" field. + public const int ConvTypeFieldNumber = 11; + private readonly static int ConvTypeDefaultValue = 0; + + private int convType_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int ConvType { + get { if ((_hasBits0 & 64) != 0) { return convType_; } else { return ConvTypeDefaultValue; } } + set { + _hasBits0 |= 64; + convType_ = value; + } + } + /// Gets whether the "convType" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasConvType { + get { return (_hasBits0 & 64) != 0; } + } + /// Clears the value of the "convType" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearConvType() { + _hasBits0 &= ~64; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as LogItem); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(LogItem other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (From != other.From) return false; + if (Data != other.Data) return false; + if (Timestamp != other.Timestamp) return false; + if (MsgId != other.MsgId) return false; + if (AckAt != other.AckAt) return false; + if (ReadAt != other.ReadAt) return false; + if (PatchTimestamp != other.PatchTimestamp) return false; + if (MentionAll != other.MentionAll) return false; + if(!mentionPids_.Equals(other.mentionPids_)) return false; + if (Bin != other.Bin) return false; + if (ConvType != other.ConvType) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasFrom) hash ^= From.GetHashCode(); + if (HasData) hash ^= Data.GetHashCode(); + if (HasTimestamp) hash ^= Timestamp.GetHashCode(); + if (HasMsgId) hash ^= MsgId.GetHashCode(); + if (HasAckAt) hash ^= AckAt.GetHashCode(); + if (HasReadAt) hash ^= ReadAt.GetHashCode(); + if (HasPatchTimestamp) hash ^= PatchTimestamp.GetHashCode(); + if (HasMentionAll) hash ^= MentionAll.GetHashCode(); + hash ^= mentionPids_.GetHashCode(); + if (HasBin) hash ^= Bin.GetHashCode(); + if (HasConvType) hash ^= ConvType.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (HasFrom) { + output.WriteRawTag(10); + output.WriteString(From); + } + if (HasData) { + output.WriteRawTag(18); + output.WriteString(Data); + } + if (HasTimestamp) { + output.WriteRawTag(24); + output.WriteInt64(Timestamp); + } + if (HasMsgId) { + output.WriteRawTag(34); + output.WriteString(MsgId); + } + if (HasAckAt) { + output.WriteRawTag(40); + output.WriteInt64(AckAt); + } + if (HasReadAt) { + output.WriteRawTag(48); + output.WriteInt64(ReadAt); + } + if (HasPatchTimestamp) { + output.WriteRawTag(56); + output.WriteInt64(PatchTimestamp); + } + if (HasMentionAll) { + output.WriteRawTag(64); + output.WriteBool(MentionAll); + } + mentionPids_.WriteTo(output, _repeated_mentionPids_codec); + if (HasBin) { + output.WriteRawTag(80); + output.WriteBool(Bin); + } + if (HasConvType) { + output.WriteRawTag(88); + output.WriteInt32(ConvType); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasFrom) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(From); + } + if (HasData) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Data); + } + if (HasTimestamp) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(Timestamp); + } + if (HasMsgId) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(MsgId); + } + if (HasAckAt) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(AckAt); + } + if (HasReadAt) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(ReadAt); + } + if (HasPatchTimestamp) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(PatchTimestamp); + } + if (HasMentionAll) { + size += 1 + 1; + } + size += mentionPids_.CalculateSize(_repeated_mentionPids_codec); + if (HasBin) { + size += 1 + 1; + } + if (HasConvType) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(ConvType); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(LogItem other) { + if (other == null) { + return; + } + if (other.HasFrom) { + From = other.From; + } + if (other.HasData) { + Data = other.Data; + } + if (other.HasTimestamp) { + Timestamp = other.Timestamp; + } + if (other.HasMsgId) { + MsgId = other.MsgId; + } + if (other.HasAckAt) { + AckAt = other.AckAt; + } + if (other.HasReadAt) { + ReadAt = other.ReadAt; + } + if (other.HasPatchTimestamp) { + PatchTimestamp = other.PatchTimestamp; + } + if (other.HasMentionAll) { + MentionAll = other.MentionAll; + } + mentionPids_.Add(other.mentionPids_); + if (other.HasBin) { + Bin = other.Bin; + } + if (other.HasConvType) { + ConvType = other.ConvType; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + From = input.ReadString(); + break; + } + case 18: { + Data = input.ReadString(); + break; + } + case 24: { + Timestamp = input.ReadInt64(); + break; + } + case 34: { + MsgId = input.ReadString(); + break; + } + case 40: { + AckAt = input.ReadInt64(); + break; + } + case 48: { + ReadAt = input.ReadInt64(); + break; + } + case 56: { + PatchTimestamp = input.ReadInt64(); + break; + } + case 64: { + MentionAll = input.ReadBool(); + break; + } + case 74: { + mentionPids_.AddEntriesFrom(input, _repeated_mentionPids_codec); + break; + } + case 80: { + Bin = input.ReadBool(); + break; + } + case 88: { + ConvType = input.ReadInt32(); + break; + } + } + } + } + + } + + public sealed partial class ConvMemberInfo : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ConvMemberInfo()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::LeanCloud.Realtime.Internal.Protocol.Messages2ProtoReflection.Descriptor.MessageTypes[6]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ConvMemberInfo() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ConvMemberInfo(ConvMemberInfo other) : this() { + pid_ = other.pid_; + role_ = other.role_; + infoId_ = other.infoId_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ConvMemberInfo Clone() { + return new ConvMemberInfo(this); + } + + /// Field number for the "pid" field. + public const int PidFieldNumber = 1; + private readonly static string PidDefaultValue = ""; + + private string pid_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Pid { + get { return pid_ ?? PidDefaultValue; } + set { + pid_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "pid" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasPid { + get { return pid_ != null; } + } + /// Clears the value of the "pid" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearPid() { + pid_ = null; + } + + /// Field number for the "role" field. + public const int RoleFieldNumber = 2; + private readonly static string RoleDefaultValue = ""; + + private string role_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Role { + get { return role_ ?? RoleDefaultValue; } + set { + role_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "role" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasRole { + get { return role_ != null; } + } + /// Clears the value of the "role" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearRole() { + role_ = null; + } + + /// Field number for the "infoId" field. + public const int InfoIdFieldNumber = 3; + private readonly static string InfoIdDefaultValue = ""; + + private string infoId_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string InfoId { + get { return infoId_ ?? InfoIdDefaultValue; } + set { + infoId_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "infoId" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasInfoId { + get { return infoId_ != null; } + } + /// Clears the value of the "infoId" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearInfoId() { + infoId_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as ConvMemberInfo); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(ConvMemberInfo other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Pid != other.Pid) return false; + if (Role != other.Role) return false; + if (InfoId != other.InfoId) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasPid) hash ^= Pid.GetHashCode(); + if (HasRole) hash ^= Role.GetHashCode(); + if (HasInfoId) hash ^= InfoId.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (HasPid) { + output.WriteRawTag(10); + output.WriteString(Pid); + } + if (HasRole) { + output.WriteRawTag(18); + output.WriteString(Role); + } + if (HasInfoId) { + output.WriteRawTag(26); + output.WriteString(InfoId); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasPid) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Pid); + } + if (HasRole) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Role); + } + if (HasInfoId) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(InfoId); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(ConvMemberInfo other) { + if (other == null) { + return; + } + if (other.HasPid) { + Pid = other.Pid; + } + if (other.HasRole) { + Role = other.Role; + } + if (other.HasInfoId) { + InfoId = other.InfoId; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + Pid = input.ReadString(); + break; + } + case 18: { + Role = input.ReadString(); + break; + } + case 26: { + InfoId = input.ReadString(); + break; + } + } + } + } + + } + + public sealed partial class LoginCommand : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new LoginCommand()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::LeanCloud.Realtime.Internal.Protocol.Messages2ProtoReflection.Descriptor.MessageTypes[7]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public LoginCommand() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public LoginCommand(LoginCommand other) : this() { + systemInfo_ = other.HasSystemInfo ? other.systemInfo_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public LoginCommand Clone() { + return new LoginCommand(this); + } + + /// Field number for the "systemInfo" field. + public const int SystemInfoFieldNumber = 1; + private global::LeanCloud.Realtime.Internal.Protocol.SystemInfo systemInfo_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::LeanCloud.Realtime.Internal.Protocol.SystemInfo SystemInfo { + get { return systemInfo_; } + set { + systemInfo_ = value; + } + } + /// Gets whether the systemInfo field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasSystemInfo { + get { return systemInfo_ != null; } + } + /// Clears the value of the systemInfo field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearSystemInfo() { + systemInfo_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as LoginCommand); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(LoginCommand other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(SystemInfo, other.SystemInfo)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasSystemInfo) hash ^= SystemInfo.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (HasSystemInfo) { + output.WriteRawTag(10); + output.WriteMessage(SystemInfo); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasSystemInfo) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(SystemInfo); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(LoginCommand other) { + if (other == null) { + return; + } + if (other.HasSystemInfo) { + if (!HasSystemInfo) { + SystemInfo = new global::LeanCloud.Realtime.Internal.Protocol.SystemInfo(); + } + SystemInfo.MergeFrom(other.SystemInfo); + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + if (!HasSystemInfo) { + SystemInfo = new global::LeanCloud.Realtime.Internal.Protocol.SystemInfo(); + } + input.ReadMessage(SystemInfo); + break; + } + } + } + } + + } + + public sealed partial class LoggedinCommand : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new LoggedinCommand()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::LeanCloud.Realtime.Internal.Protocol.Messages2ProtoReflection.Descriptor.MessageTypes[8]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public LoggedinCommand() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public LoggedinCommand(LoggedinCommand other) : this() { + _hasBits0 = other._hasBits0; + pushDisabled_ = other.pushDisabled_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public LoggedinCommand Clone() { + return new LoggedinCommand(this); + } + + /// Field number for the "pushDisabled" field. + public const int PushDisabledFieldNumber = 1; + private readonly static bool PushDisabledDefaultValue = false; + + private bool pushDisabled_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool PushDisabled { + get { if ((_hasBits0 & 1) != 0) { return pushDisabled_; } else { return PushDisabledDefaultValue; } } + set { + _hasBits0 |= 1; + pushDisabled_ = value; + } + } + /// Gets whether the "pushDisabled" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasPushDisabled { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "pushDisabled" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearPushDisabled() { + _hasBits0 &= ~1; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as LoggedinCommand); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(LoggedinCommand other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (PushDisabled != other.PushDisabled) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasPushDisabled) hash ^= PushDisabled.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (HasPushDisabled) { + output.WriteRawTag(8); + output.WriteBool(PushDisabled); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasPushDisabled) { + size += 1 + 1; + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(LoggedinCommand other) { + if (other == null) { + return; + } + if (other.HasPushDisabled) { + PushDisabled = other.PushDisabled; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + PushDisabled = input.ReadBool(); + break; + } + } + } + } + + } + + public sealed partial class DataCommand : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new DataCommand()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::LeanCloud.Realtime.Internal.Protocol.Messages2ProtoReflection.Descriptor.MessageTypes[9]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public DataCommand() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public DataCommand(DataCommand other) : this() { + _hasBits0 = other._hasBits0; + ids_ = other.ids_.Clone(); + msg_ = other.msg_.Clone(); + offline_ = other.offline_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public DataCommand Clone() { + return new DataCommand(this); + } + + /// Field number for the "ids" field. + public const int IdsFieldNumber = 1; + private static readonly pb::FieldCodec _repeated_ids_codec + = pb::FieldCodec.ForString(10); + private readonly pbc::RepeatedField ids_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField Ids { + get { return ids_; } + } + + /// Field number for the "msg" field. + public const int MsgFieldNumber = 2; + private static readonly pb::FieldCodec _repeated_msg_codec + = pb::FieldCodec.ForMessage(18, global::LeanCloud.Realtime.Internal.Protocol.JsonObjectMessage.Parser); + private readonly pbc::RepeatedField msg_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField Msg { + get { return msg_; } + } + + /// Field number for the "offline" field. + public const int OfflineFieldNumber = 3; + private readonly static bool OfflineDefaultValue = false; + + private bool offline_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Offline { + get { if ((_hasBits0 & 1) != 0) { return offline_; } else { return OfflineDefaultValue; } } + set { + _hasBits0 |= 1; + offline_ = value; + } + } + /// Gets whether the "offline" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOffline { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "offline" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOffline() { + _hasBits0 &= ~1; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as DataCommand); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(DataCommand other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if(!ids_.Equals(other.ids_)) return false; + if(!msg_.Equals(other.msg_)) return false; + if (Offline != other.Offline) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + hash ^= ids_.GetHashCode(); + hash ^= msg_.GetHashCode(); + if (HasOffline) hash ^= Offline.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + ids_.WriteTo(output, _repeated_ids_codec); + msg_.WriteTo(output, _repeated_msg_codec); + if (HasOffline) { + output.WriteRawTag(24); + output.WriteBool(Offline); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + size += ids_.CalculateSize(_repeated_ids_codec); + size += msg_.CalculateSize(_repeated_msg_codec); + if (HasOffline) { + size += 1 + 1; + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(DataCommand other) { + if (other == null) { + return; + } + ids_.Add(other.ids_); + msg_.Add(other.msg_); + if (other.HasOffline) { + Offline = other.Offline; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + ids_.AddEntriesFrom(input, _repeated_ids_codec); + break; + } + case 18: { + msg_.AddEntriesFrom(input, _repeated_msg_codec); + break; + } + case 24: { + Offline = input.ReadBool(); + break; + } + } + } + } + + } + + public sealed partial class SessionCommand : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new SessionCommand()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::LeanCloud.Realtime.Internal.Protocol.Messages2ProtoReflection.Descriptor.MessageTypes[10]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public SessionCommand() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public SessionCommand(SessionCommand other) : this() { + _hasBits0 = other._hasBits0; + t_ = other.t_; + n_ = other.n_; + s_ = other.s_; + ua_ = other.ua_; + r_ = other.r_; + tag_ = other.tag_; + deviceId_ = other.deviceId_; + sessionPeerIds_ = other.sessionPeerIds_.Clone(); + onlineSessionPeerIds_ = other.onlineSessionPeerIds_.Clone(); + st_ = other.st_; + stTtl_ = other.stTtl_; + code_ = other.code_; + reason_ = other.reason_; + deviceToken_ = other.deviceToken_; + sp_ = other.sp_; + detail_ = other.detail_; + lastUnreadNotifTime_ = other.lastUnreadNotifTime_; + lastPatchTime_ = other.lastPatchTime_; + configBitmap_ = other.configBitmap_; + systemInfo_ = other.HasSystemInfo ? other.systemInfo_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public SessionCommand Clone() { + return new SessionCommand(this); + } + + /// Field number for the "t" field. + public const int TFieldNumber = 1; + private readonly static long TDefaultValue = 0L; + + private long t_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long T { + get { if ((_hasBits0 & 1) != 0) { return t_; } else { return TDefaultValue; } } + set { + _hasBits0 |= 1; + t_ = value; + } + } + /// Gets whether the "t" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasT { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "t" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearT() { + _hasBits0 &= ~1; + } + + /// Field number for the "n" field. + public const int NFieldNumber = 2; + private readonly static string NDefaultValue = ""; + + private string n_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string N { + get { return n_ ?? NDefaultValue; } + set { + n_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "n" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasN { + get { return n_ != null; } + } + /// Clears the value of the "n" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearN() { + n_ = null; + } + + /// Field number for the "s" field. + public const int SFieldNumber = 3; + private readonly static string SDefaultValue = ""; + + private string s_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string S { + get { return s_ ?? SDefaultValue; } + set { + s_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "s" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasS { + get { return s_ != null; } + } + /// Clears the value of the "s" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearS() { + s_ = null; + } + + /// Field number for the "ua" field. + public const int UaFieldNumber = 4; + private readonly static string UaDefaultValue = ""; + + private string ua_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Ua { + get { return ua_ ?? UaDefaultValue; } + set { + ua_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "ua" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasUa { + get { return ua_ != null; } + } + /// Clears the value of the "ua" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearUa() { + ua_ = null; + } + + /// Field number for the "r" field. + public const int RFieldNumber = 5; + private readonly static bool RDefaultValue = false; + + private bool r_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool R { + get { if ((_hasBits0 & 2) != 0) { return r_; } else { return RDefaultValue; } } + set { + _hasBits0 |= 2; + r_ = value; + } + } + /// Gets whether the "r" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasR { + get { return (_hasBits0 & 2) != 0; } + } + /// Clears the value of the "r" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearR() { + _hasBits0 &= ~2; + } + + /// Field number for the "tag" field. + public const int TagFieldNumber = 6; + private readonly static string TagDefaultValue = ""; + + private string tag_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Tag { + get { return tag_ ?? TagDefaultValue; } + set { + tag_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "tag" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasTag { + get { return tag_ != null; } + } + /// Clears the value of the "tag" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearTag() { + tag_ = null; + } + + /// Field number for the "deviceId" field. + public const int DeviceIdFieldNumber = 7; + private readonly static string DeviceIdDefaultValue = ""; + + private string deviceId_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string DeviceId { + get { return deviceId_ ?? DeviceIdDefaultValue; } + set { + deviceId_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "deviceId" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDeviceId { + get { return deviceId_ != null; } + } + /// Clears the value of the "deviceId" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDeviceId() { + deviceId_ = null; + } + + /// Field number for the "sessionPeerIds" field. + public const int SessionPeerIdsFieldNumber = 8; + private static readonly pb::FieldCodec _repeated_sessionPeerIds_codec + = pb::FieldCodec.ForString(66); + private readonly pbc::RepeatedField sessionPeerIds_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField SessionPeerIds { + get { return sessionPeerIds_; } + } + + /// Field number for the "onlineSessionPeerIds" field. + public const int OnlineSessionPeerIdsFieldNumber = 9; + private static readonly pb::FieldCodec _repeated_onlineSessionPeerIds_codec + = pb::FieldCodec.ForString(74); + private readonly pbc::RepeatedField onlineSessionPeerIds_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField OnlineSessionPeerIds { + get { return onlineSessionPeerIds_; } + } + + /// Field number for the "st" field. + public const int StFieldNumber = 10; + private readonly static string StDefaultValue = ""; + + private string st_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string St { + get { return st_ ?? StDefaultValue; } + set { + st_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "st" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasSt { + get { return st_ != null; } + } + /// Clears the value of the "st" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearSt() { + st_ = null; + } + + /// Field number for the "stTtl" field. + public const int StTtlFieldNumber = 11; + private readonly static int StTtlDefaultValue = 0; + + private int stTtl_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int StTtl { + get { if ((_hasBits0 & 4) != 0) { return stTtl_; } else { return StTtlDefaultValue; } } + set { + _hasBits0 |= 4; + stTtl_ = value; + } + } + /// Gets whether the "stTtl" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasStTtl { + get { return (_hasBits0 & 4) != 0; } + } + /// Clears the value of the "stTtl" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearStTtl() { + _hasBits0 &= ~4; + } + + /// Field number for the "code" field. + public const int CodeFieldNumber = 12; + private readonly static int CodeDefaultValue = 0; + + private int code_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Code { + get { if ((_hasBits0 & 8) != 0) { return code_; } else { return CodeDefaultValue; } } + set { + _hasBits0 |= 8; + code_ = value; + } + } + /// Gets whether the "code" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasCode { + get { return (_hasBits0 & 8) != 0; } + } + /// Clears the value of the "code" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearCode() { + _hasBits0 &= ~8; + } + + /// Field number for the "reason" field. + public const int ReasonFieldNumber = 13; + private readonly static string ReasonDefaultValue = ""; + + private string reason_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Reason { + get { return reason_ ?? ReasonDefaultValue; } + set { + reason_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "reason" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasReason { + get { return reason_ != null; } + } + /// Clears the value of the "reason" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearReason() { + reason_ = null; + } + + /// Field number for the "deviceToken" field. + public const int DeviceTokenFieldNumber = 14; + private readonly static string DeviceTokenDefaultValue = ""; + + private string deviceToken_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string DeviceToken { + get { return deviceToken_ ?? DeviceTokenDefaultValue; } + set { + deviceToken_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "deviceToken" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDeviceToken { + get { return deviceToken_ != null; } + } + /// Clears the value of the "deviceToken" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDeviceToken() { + deviceToken_ = null; + } + + /// Field number for the "sp" field. + public const int SpFieldNumber = 15; + private readonly static bool SpDefaultValue = false; + + private bool sp_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Sp { + get { if ((_hasBits0 & 16) != 0) { return sp_; } else { return SpDefaultValue; } } + set { + _hasBits0 |= 16; + sp_ = value; + } + } + /// Gets whether the "sp" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasSp { + get { return (_hasBits0 & 16) != 0; } + } + /// Clears the value of the "sp" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearSp() { + _hasBits0 &= ~16; + } + + /// Field number for the "detail" field. + public const int DetailFieldNumber = 16; + private readonly static string DetailDefaultValue = ""; + + private string detail_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Detail { + get { return detail_ ?? DetailDefaultValue; } + set { + detail_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "detail" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDetail { + get { return detail_ != null; } + } + /// Clears the value of the "detail" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDetail() { + detail_ = null; + } + + /// Field number for the "lastUnreadNotifTime" field. + public const int LastUnreadNotifTimeFieldNumber = 17; + private readonly static long LastUnreadNotifTimeDefaultValue = 0L; + + private long lastUnreadNotifTime_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long LastUnreadNotifTime { + get { if ((_hasBits0 & 32) != 0) { return lastUnreadNotifTime_; } else { return LastUnreadNotifTimeDefaultValue; } } + set { + _hasBits0 |= 32; + lastUnreadNotifTime_ = value; + } + } + /// Gets whether the "lastUnreadNotifTime" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasLastUnreadNotifTime { + get { return (_hasBits0 & 32) != 0; } + } + /// Clears the value of the "lastUnreadNotifTime" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearLastUnreadNotifTime() { + _hasBits0 &= ~32; + } + + /// Field number for the "lastPatchTime" field. + public const int LastPatchTimeFieldNumber = 18; + private readonly static long LastPatchTimeDefaultValue = 0L; + + private long lastPatchTime_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long LastPatchTime { + get { if ((_hasBits0 & 64) != 0) { return lastPatchTime_; } else { return LastPatchTimeDefaultValue; } } + set { + _hasBits0 |= 64; + lastPatchTime_ = value; + } + } + /// Gets whether the "lastPatchTime" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasLastPatchTime { + get { return (_hasBits0 & 64) != 0; } + } + /// Clears the value of the "lastPatchTime" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearLastPatchTime() { + _hasBits0 &= ~64; + } + + /// Field number for the "configBitmap" field. + public const int ConfigBitmapFieldNumber = 19; + private readonly static long ConfigBitmapDefaultValue = 0L; + + private long configBitmap_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long ConfigBitmap { + get { if ((_hasBits0 & 128) != 0) { return configBitmap_; } else { return ConfigBitmapDefaultValue; } } + set { + _hasBits0 |= 128; + configBitmap_ = value; + } + } + /// Gets whether the "configBitmap" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasConfigBitmap { + get { return (_hasBits0 & 128) != 0; } + } + /// Clears the value of the "configBitmap" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearConfigBitmap() { + _hasBits0 &= ~128; + } + + /// Field number for the "systemInfo" field. + public const int SystemInfoFieldNumber = 20; + private global::LeanCloud.Realtime.Internal.Protocol.SystemInfo systemInfo_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::LeanCloud.Realtime.Internal.Protocol.SystemInfo SystemInfo { + get { return systemInfo_; } + set { + systemInfo_ = value; + } + } + /// Gets whether the systemInfo field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasSystemInfo { + get { return systemInfo_ != null; } + } + /// Clears the value of the systemInfo field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearSystemInfo() { + systemInfo_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as SessionCommand); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(SessionCommand other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (T != other.T) return false; + if (N != other.N) return false; + if (S != other.S) return false; + if (Ua != other.Ua) return false; + if (R != other.R) return false; + if (Tag != other.Tag) return false; + if (DeviceId != other.DeviceId) return false; + if(!sessionPeerIds_.Equals(other.sessionPeerIds_)) return false; + if(!onlineSessionPeerIds_.Equals(other.onlineSessionPeerIds_)) return false; + if (St != other.St) return false; + if (StTtl != other.StTtl) return false; + if (Code != other.Code) return false; + if (Reason != other.Reason) return false; + if (DeviceToken != other.DeviceToken) return false; + if (Sp != other.Sp) return false; + if (Detail != other.Detail) return false; + if (LastUnreadNotifTime != other.LastUnreadNotifTime) return false; + if (LastPatchTime != other.LastPatchTime) return false; + if (ConfigBitmap != other.ConfigBitmap) return false; + if (!object.Equals(SystemInfo, other.SystemInfo)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasT) hash ^= T.GetHashCode(); + if (HasN) hash ^= N.GetHashCode(); + if (HasS) hash ^= S.GetHashCode(); + if (HasUa) hash ^= Ua.GetHashCode(); + if (HasR) hash ^= R.GetHashCode(); + if (HasTag) hash ^= Tag.GetHashCode(); + if (HasDeviceId) hash ^= DeviceId.GetHashCode(); + hash ^= sessionPeerIds_.GetHashCode(); + hash ^= onlineSessionPeerIds_.GetHashCode(); + if (HasSt) hash ^= St.GetHashCode(); + if (HasStTtl) hash ^= StTtl.GetHashCode(); + if (HasCode) hash ^= Code.GetHashCode(); + if (HasReason) hash ^= Reason.GetHashCode(); + if (HasDeviceToken) hash ^= DeviceToken.GetHashCode(); + if (HasSp) hash ^= Sp.GetHashCode(); + if (HasDetail) hash ^= Detail.GetHashCode(); + if (HasLastUnreadNotifTime) hash ^= LastUnreadNotifTime.GetHashCode(); + if (HasLastPatchTime) hash ^= LastPatchTime.GetHashCode(); + if (HasConfigBitmap) hash ^= ConfigBitmap.GetHashCode(); + if (HasSystemInfo) hash ^= SystemInfo.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (HasT) { + output.WriteRawTag(8); + output.WriteInt64(T); + } + if (HasN) { + output.WriteRawTag(18); + output.WriteString(N); + } + if (HasS) { + output.WriteRawTag(26); + output.WriteString(S); + } + if (HasUa) { + output.WriteRawTag(34); + output.WriteString(Ua); + } + if (HasR) { + output.WriteRawTag(40); + output.WriteBool(R); + } + if (HasTag) { + output.WriteRawTag(50); + output.WriteString(Tag); + } + if (HasDeviceId) { + output.WriteRawTag(58); + output.WriteString(DeviceId); + } + sessionPeerIds_.WriteTo(output, _repeated_sessionPeerIds_codec); + onlineSessionPeerIds_.WriteTo(output, _repeated_onlineSessionPeerIds_codec); + if (HasSt) { + output.WriteRawTag(82); + output.WriteString(St); + } + if (HasStTtl) { + output.WriteRawTag(88); + output.WriteInt32(StTtl); + } + if (HasCode) { + output.WriteRawTag(96); + output.WriteInt32(Code); + } + if (HasReason) { + output.WriteRawTag(106); + output.WriteString(Reason); + } + if (HasDeviceToken) { + output.WriteRawTag(114); + output.WriteString(DeviceToken); + } + if (HasSp) { + output.WriteRawTag(120); + output.WriteBool(Sp); + } + if (HasDetail) { + output.WriteRawTag(130, 1); + output.WriteString(Detail); + } + if (HasLastUnreadNotifTime) { + output.WriteRawTag(136, 1); + output.WriteInt64(LastUnreadNotifTime); + } + if (HasLastPatchTime) { + output.WriteRawTag(144, 1); + output.WriteInt64(LastPatchTime); + } + if (HasConfigBitmap) { + output.WriteRawTag(152, 1); + output.WriteInt64(ConfigBitmap); + } + if (HasSystemInfo) { + output.WriteRawTag(162, 1); + output.WriteMessage(SystemInfo); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasT) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(T); + } + if (HasN) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(N); + } + if (HasS) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(S); + } + if (HasUa) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Ua); + } + if (HasR) { + size += 1 + 1; + } + if (HasTag) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Tag); + } + if (HasDeviceId) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(DeviceId); + } + size += sessionPeerIds_.CalculateSize(_repeated_sessionPeerIds_codec); + size += onlineSessionPeerIds_.CalculateSize(_repeated_onlineSessionPeerIds_codec); + if (HasSt) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(St); + } + if (HasStTtl) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(StTtl); + } + if (HasCode) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Code); + } + if (HasReason) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Reason); + } + if (HasDeviceToken) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(DeviceToken); + } + if (HasSp) { + size += 1 + 1; + } + if (HasDetail) { + size += 2 + pb::CodedOutputStream.ComputeStringSize(Detail); + } + if (HasLastUnreadNotifTime) { + size += 2 + pb::CodedOutputStream.ComputeInt64Size(LastUnreadNotifTime); + } + if (HasLastPatchTime) { + size += 2 + pb::CodedOutputStream.ComputeInt64Size(LastPatchTime); + } + if (HasConfigBitmap) { + size += 2 + pb::CodedOutputStream.ComputeInt64Size(ConfigBitmap); + } + if (HasSystemInfo) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(SystemInfo); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(SessionCommand other) { + if (other == null) { + return; + } + if (other.HasT) { + T = other.T; + } + if (other.HasN) { + N = other.N; + } + if (other.HasS) { + S = other.S; + } + if (other.HasUa) { + Ua = other.Ua; + } + if (other.HasR) { + R = other.R; + } + if (other.HasTag) { + Tag = other.Tag; + } + if (other.HasDeviceId) { + DeviceId = other.DeviceId; + } + sessionPeerIds_.Add(other.sessionPeerIds_); + onlineSessionPeerIds_.Add(other.onlineSessionPeerIds_); + if (other.HasSt) { + St = other.St; + } + if (other.HasStTtl) { + StTtl = other.StTtl; + } + if (other.HasCode) { + Code = other.Code; + } + if (other.HasReason) { + Reason = other.Reason; + } + if (other.HasDeviceToken) { + DeviceToken = other.DeviceToken; + } + if (other.HasSp) { + Sp = other.Sp; + } + if (other.HasDetail) { + Detail = other.Detail; + } + if (other.HasLastUnreadNotifTime) { + LastUnreadNotifTime = other.LastUnreadNotifTime; + } + if (other.HasLastPatchTime) { + LastPatchTime = other.LastPatchTime; + } + if (other.HasConfigBitmap) { + ConfigBitmap = other.ConfigBitmap; + } + if (other.HasSystemInfo) { + if (!HasSystemInfo) { + SystemInfo = new global::LeanCloud.Realtime.Internal.Protocol.SystemInfo(); + } + SystemInfo.MergeFrom(other.SystemInfo); + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + T = input.ReadInt64(); + break; + } + case 18: { + N = input.ReadString(); + break; + } + case 26: { + S = input.ReadString(); + break; + } + case 34: { + Ua = input.ReadString(); + break; + } + case 40: { + R = input.ReadBool(); + break; + } + case 50: { + Tag = input.ReadString(); + break; + } + case 58: { + DeviceId = input.ReadString(); + break; + } + case 66: { + sessionPeerIds_.AddEntriesFrom(input, _repeated_sessionPeerIds_codec); + break; + } + case 74: { + onlineSessionPeerIds_.AddEntriesFrom(input, _repeated_onlineSessionPeerIds_codec); + break; + } + case 82: { + St = input.ReadString(); + break; + } + case 88: { + StTtl = input.ReadInt32(); + break; + } + case 96: { + Code = input.ReadInt32(); + break; + } + case 106: { + Reason = input.ReadString(); + break; + } + case 114: { + DeviceToken = input.ReadString(); + break; + } + case 120: { + Sp = input.ReadBool(); + break; + } + case 130: { + Detail = input.ReadString(); + break; + } + case 136: { + LastUnreadNotifTime = input.ReadInt64(); + break; + } + case 144: { + LastPatchTime = input.ReadInt64(); + break; + } + case 152: { + ConfigBitmap = input.ReadInt64(); + break; + } + case 162: { + if (!HasSystemInfo) { + SystemInfo = new global::LeanCloud.Realtime.Internal.Protocol.SystemInfo(); + } + input.ReadMessage(SystemInfo); + break; + } + } + } + } + + } + + public sealed partial class ErrorCommand : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ErrorCommand()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::LeanCloud.Realtime.Internal.Protocol.Messages2ProtoReflection.Descriptor.MessageTypes[11]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ErrorCommand() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ErrorCommand(ErrorCommand other) : this() { + _hasBits0 = other._hasBits0; + code_ = other.code_; + reason_ = other.reason_; + appCode_ = other.appCode_; + detail_ = other.detail_; + pids_ = other.pids_.Clone(); + appMsg_ = other.appMsg_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ErrorCommand Clone() { + return new ErrorCommand(this); + } + + /// Field number for the "code" field. + public const int CodeFieldNumber = 1; + private readonly static int CodeDefaultValue = 0; + + private int code_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Code { + get { if ((_hasBits0 & 1) != 0) { return code_; } else { return CodeDefaultValue; } } + set { + _hasBits0 |= 1; + code_ = value; + } + } + /// Gets whether the "code" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasCode { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "code" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearCode() { + _hasBits0 &= ~1; + } + + /// Field number for the "reason" field. + public const int ReasonFieldNumber = 2; + private readonly static string ReasonDefaultValue = ""; + + private string reason_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Reason { + get { return reason_ ?? ReasonDefaultValue; } + set { + reason_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "reason" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasReason { + get { return reason_ != null; } + } + /// Clears the value of the "reason" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearReason() { + reason_ = null; + } + + /// Field number for the "appCode" field. + public const int AppCodeFieldNumber = 3; + private readonly static int AppCodeDefaultValue = 0; + + private int appCode_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int AppCode { + get { if ((_hasBits0 & 2) != 0) { return appCode_; } else { return AppCodeDefaultValue; } } + set { + _hasBits0 |= 2; + appCode_ = value; + } + } + /// Gets whether the "appCode" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasAppCode { + get { return (_hasBits0 & 2) != 0; } + } + /// Clears the value of the "appCode" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearAppCode() { + _hasBits0 &= ~2; + } + + /// Field number for the "detail" field. + public const int DetailFieldNumber = 4; + private readonly static string DetailDefaultValue = ""; + + private string detail_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Detail { + get { return detail_ ?? DetailDefaultValue; } + set { + detail_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "detail" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDetail { + get { return detail_ != null; } + } + /// Clears the value of the "detail" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDetail() { + detail_ = null; + } + + /// Field number for the "pids" field. + public const int PidsFieldNumber = 5; + private static readonly pb::FieldCodec _repeated_pids_codec + = pb::FieldCodec.ForString(42); + private readonly pbc::RepeatedField pids_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField Pids { + get { return pids_; } + } + + /// Field number for the "appMsg" field. + public const int AppMsgFieldNumber = 6; + private readonly static string AppMsgDefaultValue = ""; + + private string appMsg_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string AppMsg { + get { return appMsg_ ?? AppMsgDefaultValue; } + set { + appMsg_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "appMsg" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasAppMsg { + get { return appMsg_ != null; } + } + /// Clears the value of the "appMsg" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearAppMsg() { + appMsg_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as ErrorCommand); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(ErrorCommand other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Code != other.Code) return false; + if (Reason != other.Reason) return false; + if (AppCode != other.AppCode) return false; + if (Detail != other.Detail) return false; + if(!pids_.Equals(other.pids_)) return false; + if (AppMsg != other.AppMsg) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasCode) hash ^= Code.GetHashCode(); + if (HasReason) hash ^= Reason.GetHashCode(); + if (HasAppCode) hash ^= AppCode.GetHashCode(); + if (HasDetail) hash ^= Detail.GetHashCode(); + hash ^= pids_.GetHashCode(); + if (HasAppMsg) hash ^= AppMsg.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (HasCode) { + output.WriteRawTag(8); + output.WriteInt32(Code); + } + if (HasReason) { + output.WriteRawTag(18); + output.WriteString(Reason); + } + if (HasAppCode) { + output.WriteRawTag(24); + output.WriteInt32(AppCode); + } + if (HasDetail) { + output.WriteRawTag(34); + output.WriteString(Detail); + } + pids_.WriteTo(output, _repeated_pids_codec); + if (HasAppMsg) { + output.WriteRawTag(50); + output.WriteString(AppMsg); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasCode) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Code); + } + if (HasReason) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Reason); + } + if (HasAppCode) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(AppCode); + } + if (HasDetail) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Detail); + } + size += pids_.CalculateSize(_repeated_pids_codec); + if (HasAppMsg) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(AppMsg); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(ErrorCommand other) { + if (other == null) { + return; + } + if (other.HasCode) { + Code = other.Code; + } + if (other.HasReason) { + Reason = other.Reason; + } + if (other.HasAppCode) { + AppCode = other.AppCode; + } + if (other.HasDetail) { + Detail = other.Detail; + } + pids_.Add(other.pids_); + if (other.HasAppMsg) { + AppMsg = other.AppMsg; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + Code = input.ReadInt32(); + break; + } + case 18: { + Reason = input.ReadString(); + break; + } + case 24: { + AppCode = input.ReadInt32(); + break; + } + case 34: { + Detail = input.ReadString(); + break; + } + case 42: { + pids_.AddEntriesFrom(input, _repeated_pids_codec); + break; + } + case 50: { + AppMsg = input.ReadString(); + break; + } + } + } + } + + } + + public sealed partial class DirectCommand : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new DirectCommand()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::LeanCloud.Realtime.Internal.Protocol.Messages2ProtoReflection.Descriptor.MessageTypes[12]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public DirectCommand() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public DirectCommand(DirectCommand other) : this() { + _hasBits0 = other._hasBits0; + msg_ = other.msg_; + uid_ = other.uid_; + fromPeerId_ = other.fromPeerId_; + timestamp_ = other.timestamp_; + offline_ = other.offline_; + hasMore_ = other.hasMore_; + toPeerIds_ = other.toPeerIds_.Clone(); + r_ = other.r_; + cid_ = other.cid_; + id_ = other.id_; + transient_ = other.transient_; + dt_ = other.dt_; + roomId_ = other.roomId_; + pushData_ = other.pushData_; + will_ = other.will_; + patchTimestamp_ = other.patchTimestamp_; + binaryMsg_ = other.binaryMsg_; + mentionPids_ = other.mentionPids_.Clone(); + mentionAll_ = other.mentionAll_; + convType_ = other.convType_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public DirectCommand Clone() { + return new DirectCommand(this); + } + + /// Field number for the "msg" field. + public const int MsgFieldNumber = 1; + private readonly static string MsgDefaultValue = ""; + + private string msg_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Msg { + get { return msg_ ?? MsgDefaultValue; } + set { + msg_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "msg" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasMsg { + get { return msg_ != null; } + } + /// Clears the value of the "msg" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearMsg() { + msg_ = null; + } + + /// Field number for the "uid" field. + public const int UidFieldNumber = 2; + private readonly static string UidDefaultValue = ""; + + private string uid_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Uid { + get { return uid_ ?? UidDefaultValue; } + set { + uid_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "uid" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasUid { + get { return uid_ != null; } + } + /// Clears the value of the "uid" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearUid() { + uid_ = null; + } + + /// Field number for the "fromPeerId" field. + public const int FromPeerIdFieldNumber = 3; + private readonly static string FromPeerIdDefaultValue = ""; + + private string fromPeerId_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string FromPeerId { + get { return fromPeerId_ ?? FromPeerIdDefaultValue; } + set { + fromPeerId_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "fromPeerId" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasFromPeerId { + get { return fromPeerId_ != null; } + } + /// Clears the value of the "fromPeerId" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearFromPeerId() { + fromPeerId_ = null; + } + + /// Field number for the "timestamp" field. + public const int TimestampFieldNumber = 4; + private readonly static long TimestampDefaultValue = 0L; + + private long timestamp_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long Timestamp { + get { if ((_hasBits0 & 1) != 0) { return timestamp_; } else { return TimestampDefaultValue; } } + set { + _hasBits0 |= 1; + timestamp_ = value; + } + } + /// Gets whether the "timestamp" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasTimestamp { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "timestamp" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearTimestamp() { + _hasBits0 &= ~1; + } + + /// Field number for the "offline" field. + public const int OfflineFieldNumber = 5; + private readonly static bool OfflineDefaultValue = false; + + private bool offline_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Offline { + get { if ((_hasBits0 & 2) != 0) { return offline_; } else { return OfflineDefaultValue; } } + set { + _hasBits0 |= 2; + offline_ = value; + } + } + /// Gets whether the "offline" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOffline { + get { return (_hasBits0 & 2) != 0; } + } + /// Clears the value of the "offline" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOffline() { + _hasBits0 &= ~2; + } + + /// Field number for the "hasMore" field. + public const int HasMoreFieldNumber = 6; + private readonly static bool HasMoreDefaultValue = false; + + private bool hasMore_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasMore { + get { if ((_hasBits0 & 4) != 0) { return hasMore_; } else { return HasMoreDefaultValue; } } + set { + _hasBits0 |= 4; + hasMore_ = value; + } + } + /// Gets whether the "hasMore" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasHasMore { + get { return (_hasBits0 & 4) != 0; } + } + /// Clears the value of the "hasMore" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearHasMore() { + _hasBits0 &= ~4; + } + + /// Field number for the "toPeerIds" field. + public const int ToPeerIdsFieldNumber = 7; + private static readonly pb::FieldCodec _repeated_toPeerIds_codec + = pb::FieldCodec.ForString(58); + private readonly pbc::RepeatedField toPeerIds_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField ToPeerIds { + get { return toPeerIds_; } + } + + /// Field number for the "r" field. + public const int RFieldNumber = 10; + private readonly static bool RDefaultValue = false; + + private bool r_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool R { + get { if ((_hasBits0 & 8) != 0) { return r_; } else { return RDefaultValue; } } + set { + _hasBits0 |= 8; + r_ = value; + } + } + /// Gets whether the "r" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasR { + get { return (_hasBits0 & 8) != 0; } + } + /// Clears the value of the "r" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearR() { + _hasBits0 &= ~8; + } + + /// Field number for the "cid" field. + public const int CidFieldNumber = 11; + private readonly static string CidDefaultValue = ""; + + private string cid_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Cid { + get { return cid_ ?? CidDefaultValue; } + set { + cid_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "cid" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasCid { + get { return cid_ != null; } + } + /// Clears the value of the "cid" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearCid() { + cid_ = null; + } + + /// Field number for the "id" field. + public const int IdFieldNumber = 12; + private readonly static string IdDefaultValue = ""; + + private string id_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Id { + get { return id_ ?? IdDefaultValue; } + set { + id_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "id" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasId { + get { return id_ != null; } + } + /// Clears the value of the "id" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearId() { + id_ = null; + } + + /// Field number for the "transient" field. + public const int TransientFieldNumber = 13; + private readonly static bool TransientDefaultValue = false; + + private bool transient_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Transient { + get { if ((_hasBits0 & 16) != 0) { return transient_; } else { return TransientDefaultValue; } } + set { + _hasBits0 |= 16; + transient_ = value; + } + } + /// Gets whether the "transient" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasTransient { + get { return (_hasBits0 & 16) != 0; } + } + /// Clears the value of the "transient" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearTransient() { + _hasBits0 &= ~16; + } + + /// Field number for the "dt" field. + public const int DtFieldNumber = 14; + private readonly static string DtDefaultValue = ""; + + private string dt_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Dt { + get { return dt_ ?? DtDefaultValue; } + set { + dt_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "dt" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDt { + get { return dt_ != null; } + } + /// Clears the value of the "dt" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDt() { + dt_ = null; + } + + /// Field number for the "roomId" field. + public const int RoomIdFieldNumber = 15; + private readonly static string RoomIdDefaultValue = ""; + + private string roomId_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string RoomId { + get { return roomId_ ?? RoomIdDefaultValue; } + set { + roomId_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "roomId" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasRoomId { + get { return roomId_ != null; } + } + /// Clears the value of the "roomId" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearRoomId() { + roomId_ = null; + } + + /// Field number for the "pushData" field. + public const int PushDataFieldNumber = 16; + private readonly static string PushDataDefaultValue = ""; + + private string pushData_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string PushData { + get { return pushData_ ?? PushDataDefaultValue; } + set { + pushData_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "pushData" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasPushData { + get { return pushData_ != null; } + } + /// Clears the value of the "pushData" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearPushData() { + pushData_ = null; + } + + /// Field number for the "will" field. + public const int WillFieldNumber = 17; + private readonly static bool WillDefaultValue = false; + + private bool will_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Will { + get { if ((_hasBits0 & 32) != 0) { return will_; } else { return WillDefaultValue; } } + set { + _hasBits0 |= 32; + will_ = value; + } + } + /// Gets whether the "will" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasWill { + get { return (_hasBits0 & 32) != 0; } + } + /// Clears the value of the "will" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearWill() { + _hasBits0 &= ~32; + } + + /// Field number for the "patchTimestamp" field. + public const int PatchTimestampFieldNumber = 18; + private readonly static long PatchTimestampDefaultValue = 0L; + + private long patchTimestamp_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long PatchTimestamp { + get { if ((_hasBits0 & 64) != 0) { return patchTimestamp_; } else { return PatchTimestampDefaultValue; } } + set { + _hasBits0 |= 64; + patchTimestamp_ = value; + } + } + /// Gets whether the "patchTimestamp" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasPatchTimestamp { + get { return (_hasBits0 & 64) != 0; } + } + /// Clears the value of the "patchTimestamp" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearPatchTimestamp() { + _hasBits0 &= ~64; + } + + /// Field number for the "binaryMsg" field. + public const int BinaryMsgFieldNumber = 19; + private readonly static pb::ByteString BinaryMsgDefaultValue = pb::ByteString.Empty; + + private pb::ByteString binaryMsg_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pb::ByteString BinaryMsg { + get { return binaryMsg_ ?? BinaryMsgDefaultValue; } + set { + binaryMsg_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "binaryMsg" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasBinaryMsg { + get { return binaryMsg_ != null; } + } + /// Clears the value of the "binaryMsg" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearBinaryMsg() { + binaryMsg_ = null; + } + + /// Field number for the "mentionPids" field. + public const int MentionPidsFieldNumber = 20; + private static readonly pb::FieldCodec _repeated_mentionPids_codec + = pb::FieldCodec.ForString(162); + private readonly pbc::RepeatedField mentionPids_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField MentionPids { + get { return mentionPids_; } + } + + /// Field number for the "mentionAll" field. + public const int MentionAllFieldNumber = 21; + private readonly static bool MentionAllDefaultValue = false; + + private bool mentionAll_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool MentionAll { + get { if ((_hasBits0 & 128) != 0) { return mentionAll_; } else { return MentionAllDefaultValue; } } + set { + _hasBits0 |= 128; + mentionAll_ = value; + } + } + /// Gets whether the "mentionAll" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasMentionAll { + get { return (_hasBits0 & 128) != 0; } + } + /// Clears the value of the "mentionAll" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearMentionAll() { + _hasBits0 &= ~128; + } + + /// Field number for the "convType" field. + public const int ConvTypeFieldNumber = 22; + private readonly static int ConvTypeDefaultValue = 0; + + private int convType_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int ConvType { + get { if ((_hasBits0 & 256) != 0) { return convType_; } else { return ConvTypeDefaultValue; } } + set { + _hasBits0 |= 256; + convType_ = value; + } + } + /// Gets whether the "convType" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasConvType { + get { return (_hasBits0 & 256) != 0; } + } + /// Clears the value of the "convType" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearConvType() { + _hasBits0 &= ~256; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as DirectCommand); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(DirectCommand other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Msg != other.Msg) return false; + if (Uid != other.Uid) return false; + if (FromPeerId != other.FromPeerId) return false; + if (Timestamp != other.Timestamp) return false; + if (Offline != other.Offline) return false; + if (HasMore != other.HasMore) return false; + if(!toPeerIds_.Equals(other.toPeerIds_)) return false; + if (R != other.R) return false; + if (Cid != other.Cid) return false; + if (Id != other.Id) return false; + if (Transient != other.Transient) return false; + if (Dt != other.Dt) return false; + if (RoomId != other.RoomId) return false; + if (PushData != other.PushData) return false; + if (Will != other.Will) return false; + if (PatchTimestamp != other.PatchTimestamp) return false; + if (BinaryMsg != other.BinaryMsg) return false; + if(!mentionPids_.Equals(other.mentionPids_)) return false; + if (MentionAll != other.MentionAll) return false; + if (ConvType != other.ConvType) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasMsg) hash ^= Msg.GetHashCode(); + if (HasUid) hash ^= Uid.GetHashCode(); + if (HasFromPeerId) hash ^= FromPeerId.GetHashCode(); + if (HasTimestamp) hash ^= Timestamp.GetHashCode(); + if (HasOffline) hash ^= Offline.GetHashCode(); + if (HasHasMore) hash ^= HasMore.GetHashCode(); + hash ^= toPeerIds_.GetHashCode(); + if (HasR) hash ^= R.GetHashCode(); + if (HasCid) hash ^= Cid.GetHashCode(); + if (HasId) hash ^= Id.GetHashCode(); + if (HasTransient) hash ^= Transient.GetHashCode(); + if (HasDt) hash ^= Dt.GetHashCode(); + if (HasRoomId) hash ^= RoomId.GetHashCode(); + if (HasPushData) hash ^= PushData.GetHashCode(); + if (HasWill) hash ^= Will.GetHashCode(); + if (HasPatchTimestamp) hash ^= PatchTimestamp.GetHashCode(); + if (HasBinaryMsg) hash ^= BinaryMsg.GetHashCode(); + hash ^= mentionPids_.GetHashCode(); + if (HasMentionAll) hash ^= MentionAll.GetHashCode(); + if (HasConvType) hash ^= ConvType.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (HasMsg) { + output.WriteRawTag(10); + output.WriteString(Msg); + } + if (HasUid) { + output.WriteRawTag(18); + output.WriteString(Uid); + } + if (HasFromPeerId) { + output.WriteRawTag(26); + output.WriteString(FromPeerId); + } + if (HasTimestamp) { + output.WriteRawTag(32); + output.WriteInt64(Timestamp); + } + if (HasOffline) { + output.WriteRawTag(40); + output.WriteBool(Offline); + } + if (HasHasMore) { + output.WriteRawTag(48); + output.WriteBool(HasMore); + } + toPeerIds_.WriteTo(output, _repeated_toPeerIds_codec); + if (HasR) { + output.WriteRawTag(80); + output.WriteBool(R); + } + if (HasCid) { + output.WriteRawTag(90); + output.WriteString(Cid); + } + if (HasId) { + output.WriteRawTag(98); + output.WriteString(Id); + } + if (HasTransient) { + output.WriteRawTag(104); + output.WriteBool(Transient); + } + if (HasDt) { + output.WriteRawTag(114); + output.WriteString(Dt); + } + if (HasRoomId) { + output.WriteRawTag(122); + output.WriteString(RoomId); + } + if (HasPushData) { + output.WriteRawTag(130, 1); + output.WriteString(PushData); + } + if (HasWill) { + output.WriteRawTag(136, 1); + output.WriteBool(Will); + } + if (HasPatchTimestamp) { + output.WriteRawTag(144, 1); + output.WriteInt64(PatchTimestamp); + } + if (HasBinaryMsg) { + output.WriteRawTag(154, 1); + output.WriteBytes(BinaryMsg); + } + mentionPids_.WriteTo(output, _repeated_mentionPids_codec); + if (HasMentionAll) { + output.WriteRawTag(168, 1); + output.WriteBool(MentionAll); + } + if (HasConvType) { + output.WriteRawTag(176, 1); + output.WriteInt32(ConvType); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasMsg) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Msg); + } + if (HasUid) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Uid); + } + if (HasFromPeerId) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(FromPeerId); + } + if (HasTimestamp) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(Timestamp); + } + if (HasOffline) { + size += 1 + 1; + } + if (HasHasMore) { + size += 1 + 1; + } + size += toPeerIds_.CalculateSize(_repeated_toPeerIds_codec); + if (HasR) { + size += 1 + 1; + } + if (HasCid) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Cid); + } + if (HasId) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Id); + } + if (HasTransient) { + size += 1 + 1; + } + if (HasDt) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Dt); + } + if (HasRoomId) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(RoomId); + } + if (HasPushData) { + size += 2 + pb::CodedOutputStream.ComputeStringSize(PushData); + } + if (HasWill) { + size += 2 + 1; + } + if (HasPatchTimestamp) { + size += 2 + pb::CodedOutputStream.ComputeInt64Size(PatchTimestamp); + } + if (HasBinaryMsg) { + size += 2 + pb::CodedOutputStream.ComputeBytesSize(BinaryMsg); + } + size += mentionPids_.CalculateSize(_repeated_mentionPids_codec); + if (HasMentionAll) { + size += 2 + 1; + } + if (HasConvType) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(ConvType); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(DirectCommand other) { + if (other == null) { + return; + } + if (other.HasMsg) { + Msg = other.Msg; + } + if (other.HasUid) { + Uid = other.Uid; + } + if (other.HasFromPeerId) { + FromPeerId = other.FromPeerId; + } + if (other.HasTimestamp) { + Timestamp = other.Timestamp; + } + if (other.HasOffline) { + Offline = other.Offline; + } + if (other.HasHasMore) { + HasMore = other.HasMore; + } + toPeerIds_.Add(other.toPeerIds_); + if (other.HasR) { + R = other.R; + } + if (other.HasCid) { + Cid = other.Cid; + } + if (other.HasId) { + Id = other.Id; + } + if (other.HasTransient) { + Transient = other.Transient; + } + if (other.HasDt) { + Dt = other.Dt; + } + if (other.HasRoomId) { + RoomId = other.RoomId; + } + if (other.HasPushData) { + PushData = other.PushData; + } + if (other.HasWill) { + Will = other.Will; + } + if (other.HasPatchTimestamp) { + PatchTimestamp = other.PatchTimestamp; + } + if (other.HasBinaryMsg) { + BinaryMsg = other.BinaryMsg; + } + mentionPids_.Add(other.mentionPids_); + if (other.HasMentionAll) { + MentionAll = other.MentionAll; + } + if (other.HasConvType) { + ConvType = other.ConvType; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + Msg = input.ReadString(); + break; + } + case 18: { + Uid = input.ReadString(); + break; + } + case 26: { + FromPeerId = input.ReadString(); + break; + } + case 32: { + Timestamp = input.ReadInt64(); + break; + } + case 40: { + Offline = input.ReadBool(); + break; + } + case 48: { + HasMore = input.ReadBool(); + break; + } + case 58: { + toPeerIds_.AddEntriesFrom(input, _repeated_toPeerIds_codec); + break; + } + case 80: { + R = input.ReadBool(); + break; + } + case 90: { + Cid = input.ReadString(); + break; + } + case 98: { + Id = input.ReadString(); + break; + } + case 104: { + Transient = input.ReadBool(); + break; + } + case 114: { + Dt = input.ReadString(); + break; + } + case 122: { + RoomId = input.ReadString(); + break; + } + case 130: { + PushData = input.ReadString(); + break; + } + case 136: { + Will = input.ReadBool(); + break; + } + case 144: { + PatchTimestamp = input.ReadInt64(); + break; + } + case 154: { + BinaryMsg = input.ReadBytes(); + break; + } + case 162: { + mentionPids_.AddEntriesFrom(input, _repeated_mentionPids_codec); + break; + } + case 168: { + MentionAll = input.ReadBool(); + break; + } + case 176: { + ConvType = input.ReadInt32(); + break; + } + } + } + } + + } + + public sealed partial class AckCommand : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new AckCommand()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::LeanCloud.Realtime.Internal.Protocol.Messages2ProtoReflection.Descriptor.MessageTypes[13]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public AckCommand() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public AckCommand(AckCommand other) : this() { + _hasBits0 = other._hasBits0; + code_ = other.code_; + reason_ = other.reason_; + mid_ = other.mid_; + cid_ = other.cid_; + t_ = other.t_; + uid_ = other.uid_; + fromts_ = other.fromts_; + tots_ = other.tots_; + type_ = other.type_; + ids_ = other.ids_.Clone(); + appCode_ = other.appCode_; + appMsg_ = other.appMsg_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public AckCommand Clone() { + return new AckCommand(this); + } + + /// Field number for the "code" field. + public const int CodeFieldNumber = 1; + private readonly static int CodeDefaultValue = 0; + + private int code_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Code { + get { if ((_hasBits0 & 1) != 0) { return code_; } else { return CodeDefaultValue; } } + set { + _hasBits0 |= 1; + code_ = value; + } + } + /// Gets whether the "code" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasCode { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "code" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearCode() { + _hasBits0 &= ~1; + } + + /// Field number for the "reason" field. + public const int ReasonFieldNumber = 2; + private readonly static string ReasonDefaultValue = ""; + + private string reason_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Reason { + get { return reason_ ?? ReasonDefaultValue; } + set { + reason_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "reason" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasReason { + get { return reason_ != null; } + } + /// Clears the value of the "reason" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearReason() { + reason_ = null; + } + + /// Field number for the "mid" field. + public const int MidFieldNumber = 3; + private readonly static string MidDefaultValue = ""; + + private string mid_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Mid { + get { return mid_ ?? MidDefaultValue; } + set { + mid_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "mid" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasMid { + get { return mid_ != null; } + } + /// Clears the value of the "mid" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearMid() { + mid_ = null; + } + + /// Field number for the "cid" field. + public const int CidFieldNumber = 4; + private readonly static string CidDefaultValue = ""; + + private string cid_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Cid { + get { return cid_ ?? CidDefaultValue; } + set { + cid_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "cid" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasCid { + get { return cid_ != null; } + } + /// Clears the value of the "cid" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearCid() { + cid_ = null; + } + + /// Field number for the "t" field. + public const int TFieldNumber = 5; + private readonly static long TDefaultValue = 0L; + + private long t_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long T { + get { if ((_hasBits0 & 2) != 0) { return t_; } else { return TDefaultValue; } } + set { + _hasBits0 |= 2; + t_ = value; + } + } + /// Gets whether the "t" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasT { + get { return (_hasBits0 & 2) != 0; } + } + /// Clears the value of the "t" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearT() { + _hasBits0 &= ~2; + } + + /// Field number for the "uid" field. + public const int UidFieldNumber = 6; + private readonly static string UidDefaultValue = ""; + + private string uid_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Uid { + get { return uid_ ?? UidDefaultValue; } + set { + uid_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "uid" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasUid { + get { return uid_ != null; } + } + /// Clears the value of the "uid" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearUid() { + uid_ = null; + } + + /// Field number for the "fromts" field. + public const int FromtsFieldNumber = 7; + private readonly static long FromtsDefaultValue = 0L; + + private long fromts_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long Fromts { + get { if ((_hasBits0 & 4) != 0) { return fromts_; } else { return FromtsDefaultValue; } } + set { + _hasBits0 |= 4; + fromts_ = value; + } + } + /// Gets whether the "fromts" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasFromts { + get { return (_hasBits0 & 4) != 0; } + } + /// Clears the value of the "fromts" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearFromts() { + _hasBits0 &= ~4; + } + + /// Field number for the "tots" field. + public const int TotsFieldNumber = 8; + private readonly static long TotsDefaultValue = 0L; + + private long tots_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long Tots { + get { if ((_hasBits0 & 8) != 0) { return tots_; } else { return TotsDefaultValue; } } + set { + _hasBits0 |= 8; + tots_ = value; + } + } + /// Gets whether the "tots" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasTots { + get { return (_hasBits0 & 8) != 0; } + } + /// Clears the value of the "tots" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearTots() { + _hasBits0 &= ~8; + } + + /// Field number for the "type" field. + public const int TypeFieldNumber = 9; + private readonly static string TypeDefaultValue = ""; + + private string type_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Type { + get { return type_ ?? TypeDefaultValue; } + set { + type_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "type" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasType { + get { return type_ != null; } + } + /// Clears the value of the "type" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearType() { + type_ = null; + } + + /// Field number for the "ids" field. + public const int IdsFieldNumber = 10; + private static readonly pb::FieldCodec _repeated_ids_codec + = pb::FieldCodec.ForString(82); + private readonly pbc::RepeatedField ids_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField Ids { + get { return ids_; } + } + + /// Field number for the "appCode" field. + public const int AppCodeFieldNumber = 11; + private readonly static int AppCodeDefaultValue = 0; + + private int appCode_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int AppCode { + get { if ((_hasBits0 & 16) != 0) { return appCode_; } else { return AppCodeDefaultValue; } } + set { + _hasBits0 |= 16; + appCode_ = value; + } + } + /// Gets whether the "appCode" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasAppCode { + get { return (_hasBits0 & 16) != 0; } + } + /// Clears the value of the "appCode" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearAppCode() { + _hasBits0 &= ~16; + } + + /// Field number for the "appMsg" field. + public const int AppMsgFieldNumber = 12; + private readonly static string AppMsgDefaultValue = ""; + + private string appMsg_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string AppMsg { + get { return appMsg_ ?? AppMsgDefaultValue; } + set { + appMsg_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "appMsg" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasAppMsg { + get { return appMsg_ != null; } + } + /// Clears the value of the "appMsg" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearAppMsg() { + appMsg_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as AckCommand); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(AckCommand other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Code != other.Code) return false; + if (Reason != other.Reason) return false; + if (Mid != other.Mid) return false; + if (Cid != other.Cid) return false; + if (T != other.T) return false; + if (Uid != other.Uid) return false; + if (Fromts != other.Fromts) return false; + if (Tots != other.Tots) return false; + if (Type != other.Type) return false; + if(!ids_.Equals(other.ids_)) return false; + if (AppCode != other.AppCode) return false; + if (AppMsg != other.AppMsg) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasCode) hash ^= Code.GetHashCode(); + if (HasReason) hash ^= Reason.GetHashCode(); + if (HasMid) hash ^= Mid.GetHashCode(); + if (HasCid) hash ^= Cid.GetHashCode(); + if (HasT) hash ^= T.GetHashCode(); + if (HasUid) hash ^= Uid.GetHashCode(); + if (HasFromts) hash ^= Fromts.GetHashCode(); + if (HasTots) hash ^= Tots.GetHashCode(); + if (HasType) hash ^= Type.GetHashCode(); + hash ^= ids_.GetHashCode(); + if (HasAppCode) hash ^= AppCode.GetHashCode(); + if (HasAppMsg) hash ^= AppMsg.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (HasCode) { + output.WriteRawTag(8); + output.WriteInt32(Code); + } + if (HasReason) { + output.WriteRawTag(18); + output.WriteString(Reason); + } + if (HasMid) { + output.WriteRawTag(26); + output.WriteString(Mid); + } + if (HasCid) { + output.WriteRawTag(34); + output.WriteString(Cid); + } + if (HasT) { + output.WriteRawTag(40); + output.WriteInt64(T); + } + if (HasUid) { + output.WriteRawTag(50); + output.WriteString(Uid); + } + if (HasFromts) { + output.WriteRawTag(56); + output.WriteInt64(Fromts); + } + if (HasTots) { + output.WriteRawTag(64); + output.WriteInt64(Tots); + } + if (HasType) { + output.WriteRawTag(74); + output.WriteString(Type); + } + ids_.WriteTo(output, _repeated_ids_codec); + if (HasAppCode) { + output.WriteRawTag(88); + output.WriteInt32(AppCode); + } + if (HasAppMsg) { + output.WriteRawTag(98); + output.WriteString(AppMsg); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasCode) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Code); + } + if (HasReason) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Reason); + } + if (HasMid) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Mid); + } + if (HasCid) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Cid); + } + if (HasT) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(T); + } + if (HasUid) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Uid); + } + if (HasFromts) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(Fromts); + } + if (HasTots) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(Tots); + } + if (HasType) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Type); + } + size += ids_.CalculateSize(_repeated_ids_codec); + if (HasAppCode) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(AppCode); + } + if (HasAppMsg) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(AppMsg); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(AckCommand other) { + if (other == null) { + return; + } + if (other.HasCode) { + Code = other.Code; + } + if (other.HasReason) { + Reason = other.Reason; + } + if (other.HasMid) { + Mid = other.Mid; + } + if (other.HasCid) { + Cid = other.Cid; + } + if (other.HasT) { + T = other.T; + } + if (other.HasUid) { + Uid = other.Uid; + } + if (other.HasFromts) { + Fromts = other.Fromts; + } + if (other.HasTots) { + Tots = other.Tots; + } + if (other.HasType) { + Type = other.Type; + } + ids_.Add(other.ids_); + if (other.HasAppCode) { + AppCode = other.AppCode; + } + if (other.HasAppMsg) { + AppMsg = other.AppMsg; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + Code = input.ReadInt32(); + break; + } + case 18: { + Reason = input.ReadString(); + break; + } + case 26: { + Mid = input.ReadString(); + break; + } + case 34: { + Cid = input.ReadString(); + break; + } + case 40: { + T = input.ReadInt64(); + break; + } + case 50: { + Uid = input.ReadString(); + break; + } + case 56: { + Fromts = input.ReadInt64(); + break; + } + case 64: { + Tots = input.ReadInt64(); + break; + } + case 74: { + Type = input.ReadString(); + break; + } + case 82: { + ids_.AddEntriesFrom(input, _repeated_ids_codec); + break; + } + case 88: { + AppCode = input.ReadInt32(); + break; + } + case 98: { + AppMsg = input.ReadString(); + break; + } + } + } + } + + } + + public sealed partial class UnreadCommand : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new UnreadCommand()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::LeanCloud.Realtime.Internal.Protocol.Messages2ProtoReflection.Descriptor.MessageTypes[14]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public UnreadCommand() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public UnreadCommand(UnreadCommand other) : this() { + _hasBits0 = other._hasBits0; + convs_ = other.convs_.Clone(); + notifTime_ = other.notifTime_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public UnreadCommand Clone() { + return new UnreadCommand(this); + } + + /// Field number for the "convs" field. + public const int ConvsFieldNumber = 1; + private static readonly pb::FieldCodec _repeated_convs_codec + = pb::FieldCodec.ForMessage(10, global::LeanCloud.Realtime.Internal.Protocol.UnreadTuple.Parser); + private readonly pbc::RepeatedField convs_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField Convs { + get { return convs_; } + } + + /// Field number for the "notifTime" field. + public const int NotifTimeFieldNumber = 2; + private readonly static long NotifTimeDefaultValue = 0L; + + private long notifTime_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long NotifTime { + get { if ((_hasBits0 & 1) != 0) { return notifTime_; } else { return NotifTimeDefaultValue; } } + set { + _hasBits0 |= 1; + notifTime_ = value; + } + } + /// Gets whether the "notifTime" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasNotifTime { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "notifTime" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearNotifTime() { + _hasBits0 &= ~1; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as UnreadCommand); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(UnreadCommand other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if(!convs_.Equals(other.convs_)) return false; + if (NotifTime != other.NotifTime) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + hash ^= convs_.GetHashCode(); + if (HasNotifTime) hash ^= NotifTime.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + convs_.WriteTo(output, _repeated_convs_codec); + if (HasNotifTime) { + output.WriteRawTag(16); + output.WriteInt64(NotifTime); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + size += convs_.CalculateSize(_repeated_convs_codec); + if (HasNotifTime) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(NotifTime); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(UnreadCommand other) { + if (other == null) { + return; + } + convs_.Add(other.convs_); + if (other.HasNotifTime) { + NotifTime = other.NotifTime; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + convs_.AddEntriesFrom(input, _repeated_convs_codec); + break; + } + case 16: { + NotifTime = input.ReadInt64(); + break; + } + } + } + } + + } + + public sealed partial class ConvCommand : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ConvCommand()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::LeanCloud.Realtime.Internal.Protocol.Messages2ProtoReflection.Descriptor.MessageTypes[15]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ConvCommand() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ConvCommand(ConvCommand other) : this() { + _hasBits0 = other._hasBits0; + m_ = other.m_.Clone(); + transient_ = other.transient_; + unique_ = other.unique_; + cid_ = other.cid_; + cdate_ = other.cdate_; + initBy_ = other.initBy_; + sort_ = other.sort_; + limit_ = other.limit_; + skip_ = other.skip_; + flag_ = other.flag_; + count_ = other.count_; + udate_ = other.udate_; + t_ = other.t_; + n_ = other.n_; + s_ = other.s_; + statusSub_ = other.statusSub_; + statusPub_ = other.statusPub_; + statusTTL_ = other.statusTTL_; + uniqueId_ = other.uniqueId_; + targetClientId_ = other.targetClientId_; + maxReadTimestamp_ = other.maxReadTimestamp_; + maxAckTimestamp_ = other.maxAckTimestamp_; + queryAllMembers_ = other.queryAllMembers_; + maxReadTuples_ = other.maxReadTuples_.Clone(); + cids_ = other.cids_.Clone(); + info_ = other.HasInfo ? other.info_.Clone() : null; + tempConv_ = other.tempConv_; + tempConvTTL_ = other.tempConvTTL_; + tempConvIds_ = other.tempConvIds_.Clone(); + allowedPids_ = other.allowedPids_.Clone(); + failedPids_ = other.failedPids_.Clone(); + next_ = other.next_; + results_ = other.HasResults ? other.results_.Clone() : null; + where_ = other.HasWhere ? other.where_.Clone() : null; + attr_ = other.HasAttr ? other.attr_.Clone() : null; + attrModified_ = other.HasAttrModified ? other.attrModified_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ConvCommand Clone() { + return new ConvCommand(this); + } + + /// Field number for the "m" field. + public const int MFieldNumber = 1; + private static readonly pb::FieldCodec _repeated_m_codec + = pb::FieldCodec.ForString(10); + private readonly pbc::RepeatedField m_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField M { + get { return m_; } + } + + /// Field number for the "transient" field. + public const int TransientFieldNumber = 2; + private readonly static bool TransientDefaultValue = false; + + private bool transient_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Transient { + get { if ((_hasBits0 & 1) != 0) { return transient_; } else { return TransientDefaultValue; } } + set { + _hasBits0 |= 1; + transient_ = value; + } + } + /// Gets whether the "transient" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasTransient { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "transient" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearTransient() { + _hasBits0 &= ~1; + } + + /// Field number for the "unique" field. + public const int UniqueFieldNumber = 3; + private readonly static bool UniqueDefaultValue = false; + + private bool unique_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Unique { + get { if ((_hasBits0 & 2) != 0) { return unique_; } else { return UniqueDefaultValue; } } + set { + _hasBits0 |= 2; + unique_ = value; + } + } + /// Gets whether the "unique" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasUnique { + get { return (_hasBits0 & 2) != 0; } + } + /// Clears the value of the "unique" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearUnique() { + _hasBits0 &= ~2; + } + + /// Field number for the "cid" field. + public const int CidFieldNumber = 4; + private readonly static string CidDefaultValue = ""; + + private string cid_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Cid { + get { return cid_ ?? CidDefaultValue; } + set { + cid_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "cid" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasCid { + get { return cid_ != null; } + } + /// Clears the value of the "cid" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearCid() { + cid_ = null; + } + + /// Field number for the "cdate" field. + public const int CdateFieldNumber = 5; + private readonly static string CdateDefaultValue = ""; + + private string cdate_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Cdate { + get { return cdate_ ?? CdateDefaultValue; } + set { + cdate_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "cdate" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasCdate { + get { return cdate_ != null; } + } + /// Clears the value of the "cdate" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearCdate() { + cdate_ = null; + } + + /// Field number for the "initBy" field. + public const int InitByFieldNumber = 6; + private readonly static string InitByDefaultValue = ""; + + private string initBy_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string InitBy { + get { return initBy_ ?? InitByDefaultValue; } + set { + initBy_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "initBy" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasInitBy { + get { return initBy_ != null; } + } + /// Clears the value of the "initBy" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearInitBy() { + initBy_ = null; + } + + /// Field number for the "sort" field. + public const int SortFieldNumber = 7; + private readonly static string SortDefaultValue = ""; + + private string sort_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Sort { + get { return sort_ ?? SortDefaultValue; } + set { + sort_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "sort" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasSort { + get { return sort_ != null; } + } + /// Clears the value of the "sort" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearSort() { + sort_ = null; + } + + /// Field number for the "limit" field. + public const int LimitFieldNumber = 8; + private readonly static int LimitDefaultValue = 0; + + private int limit_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Limit { + get { if ((_hasBits0 & 4) != 0) { return limit_; } else { return LimitDefaultValue; } } + set { + _hasBits0 |= 4; + limit_ = value; + } + } + /// Gets whether the "limit" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasLimit { + get { return (_hasBits0 & 4) != 0; } + } + /// Clears the value of the "limit" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearLimit() { + _hasBits0 &= ~4; + } + + /// Field number for the "skip" field. + public const int SkipFieldNumber = 9; + private readonly static int SkipDefaultValue = 0; + + private int skip_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Skip { + get { if ((_hasBits0 & 8) != 0) { return skip_; } else { return SkipDefaultValue; } } + set { + _hasBits0 |= 8; + skip_ = value; + } + } + /// Gets whether the "skip" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasSkip { + get { return (_hasBits0 & 8) != 0; } + } + /// Clears the value of the "skip" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearSkip() { + _hasBits0 &= ~8; + } + + /// Field number for the "flag" field. + public const int FlagFieldNumber = 10; + private readonly static int FlagDefaultValue = 0; + + private int flag_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Flag { + get { if ((_hasBits0 & 16) != 0) { return flag_; } else { return FlagDefaultValue; } } + set { + _hasBits0 |= 16; + flag_ = value; + } + } + /// Gets whether the "flag" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasFlag { + get { return (_hasBits0 & 16) != 0; } + } + /// Clears the value of the "flag" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearFlag() { + _hasBits0 &= ~16; + } + + /// Field number for the "count" field. + public const int CountFieldNumber = 11; + private readonly static int CountDefaultValue = 0; + + private int count_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Count { + get { if ((_hasBits0 & 32) != 0) { return count_; } else { return CountDefaultValue; } } + set { + _hasBits0 |= 32; + count_ = value; + } + } + /// Gets whether the "count" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasCount { + get { return (_hasBits0 & 32) != 0; } + } + /// Clears the value of the "count" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearCount() { + _hasBits0 &= ~32; + } + + /// Field number for the "udate" field. + public const int UdateFieldNumber = 12; + private readonly static string UdateDefaultValue = ""; + + private string udate_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Udate { + get { return udate_ ?? UdateDefaultValue; } + set { + udate_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "udate" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasUdate { + get { return udate_ != null; } + } + /// Clears the value of the "udate" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearUdate() { + udate_ = null; + } + + /// Field number for the "t" field. + public const int TFieldNumber = 13; + private readonly static long TDefaultValue = 0L; + + private long t_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long T { + get { if ((_hasBits0 & 64) != 0) { return t_; } else { return TDefaultValue; } } + set { + _hasBits0 |= 64; + t_ = value; + } + } + /// Gets whether the "t" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasT { + get { return (_hasBits0 & 64) != 0; } + } + /// Clears the value of the "t" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearT() { + _hasBits0 &= ~64; + } + + /// Field number for the "n" field. + public const int NFieldNumber = 14; + private readonly static string NDefaultValue = ""; + + private string n_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string N { + get { return n_ ?? NDefaultValue; } + set { + n_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "n" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasN { + get { return n_ != null; } + } + /// Clears the value of the "n" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearN() { + n_ = null; + } + + /// Field number for the "s" field. + public const int SFieldNumber = 15; + private readonly static string SDefaultValue = ""; + + private string s_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string S { + get { return s_ ?? SDefaultValue; } + set { + s_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "s" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasS { + get { return s_ != null; } + } + /// Clears the value of the "s" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearS() { + s_ = null; + } + + /// Field number for the "statusSub" field. + public const int StatusSubFieldNumber = 16; + private readonly static bool StatusSubDefaultValue = false; + + private bool statusSub_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool StatusSub { + get { if ((_hasBits0 & 128) != 0) { return statusSub_; } else { return StatusSubDefaultValue; } } + set { + _hasBits0 |= 128; + statusSub_ = value; + } + } + /// Gets whether the "statusSub" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasStatusSub { + get { return (_hasBits0 & 128) != 0; } + } + /// Clears the value of the "statusSub" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearStatusSub() { + _hasBits0 &= ~128; + } + + /// Field number for the "statusPub" field. + public const int StatusPubFieldNumber = 17; + private readonly static bool StatusPubDefaultValue = false; + + private bool statusPub_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool StatusPub { + get { if ((_hasBits0 & 256) != 0) { return statusPub_; } else { return StatusPubDefaultValue; } } + set { + _hasBits0 |= 256; + statusPub_ = value; + } + } + /// Gets whether the "statusPub" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasStatusPub { + get { return (_hasBits0 & 256) != 0; } + } + /// Clears the value of the "statusPub" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearStatusPub() { + _hasBits0 &= ~256; + } + + /// Field number for the "statusTTL" field. + public const int StatusTTLFieldNumber = 18; + private readonly static int StatusTTLDefaultValue = 0; + + private int statusTTL_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int StatusTTL { + get { if ((_hasBits0 & 512) != 0) { return statusTTL_; } else { return StatusTTLDefaultValue; } } + set { + _hasBits0 |= 512; + statusTTL_ = value; + } + } + /// Gets whether the "statusTTL" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasStatusTTL { + get { return (_hasBits0 & 512) != 0; } + } + /// Clears the value of the "statusTTL" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearStatusTTL() { + _hasBits0 &= ~512; + } + + /// Field number for the "uniqueId" field. + public const int UniqueIdFieldNumber = 19; + private readonly static string UniqueIdDefaultValue = ""; + + private string uniqueId_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string UniqueId { + get { return uniqueId_ ?? UniqueIdDefaultValue; } + set { + uniqueId_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "uniqueId" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasUniqueId { + get { return uniqueId_ != null; } + } + /// Clears the value of the "uniqueId" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearUniqueId() { + uniqueId_ = null; + } + + /// Field number for the "targetClientId" field. + public const int TargetClientIdFieldNumber = 20; + private readonly static string TargetClientIdDefaultValue = ""; + + private string targetClientId_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string TargetClientId { + get { return targetClientId_ ?? TargetClientIdDefaultValue; } + set { + targetClientId_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "targetClientId" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasTargetClientId { + get { return targetClientId_ != null; } + } + /// Clears the value of the "targetClientId" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearTargetClientId() { + targetClientId_ = null; + } + + /// Field number for the "maxReadTimestamp" field. + public const int MaxReadTimestampFieldNumber = 21; + private readonly static long MaxReadTimestampDefaultValue = 0L; + + private long maxReadTimestamp_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long MaxReadTimestamp { + get { if ((_hasBits0 & 1024) != 0) { return maxReadTimestamp_; } else { return MaxReadTimestampDefaultValue; } } + set { + _hasBits0 |= 1024; + maxReadTimestamp_ = value; + } + } + /// Gets whether the "maxReadTimestamp" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasMaxReadTimestamp { + get { return (_hasBits0 & 1024) != 0; } + } + /// Clears the value of the "maxReadTimestamp" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearMaxReadTimestamp() { + _hasBits0 &= ~1024; + } + + /// Field number for the "maxAckTimestamp" field. + public const int MaxAckTimestampFieldNumber = 22; + private readonly static long MaxAckTimestampDefaultValue = 0L; + + private long maxAckTimestamp_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long MaxAckTimestamp { + get { if ((_hasBits0 & 2048) != 0) { return maxAckTimestamp_; } else { return MaxAckTimestampDefaultValue; } } + set { + _hasBits0 |= 2048; + maxAckTimestamp_ = value; + } + } + /// Gets whether the "maxAckTimestamp" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasMaxAckTimestamp { + get { return (_hasBits0 & 2048) != 0; } + } + /// Clears the value of the "maxAckTimestamp" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearMaxAckTimestamp() { + _hasBits0 &= ~2048; + } + + /// Field number for the "queryAllMembers" field. + public const int QueryAllMembersFieldNumber = 23; + private readonly static bool QueryAllMembersDefaultValue = false; + + private bool queryAllMembers_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool QueryAllMembers { + get { if ((_hasBits0 & 4096) != 0) { return queryAllMembers_; } else { return QueryAllMembersDefaultValue; } } + set { + _hasBits0 |= 4096; + queryAllMembers_ = value; + } + } + /// Gets whether the "queryAllMembers" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasQueryAllMembers { + get { return (_hasBits0 & 4096) != 0; } + } + /// Clears the value of the "queryAllMembers" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearQueryAllMembers() { + _hasBits0 &= ~4096; + } + + /// Field number for the "maxReadTuples" field. + public const int MaxReadTuplesFieldNumber = 24; + private static readonly pb::FieldCodec _repeated_maxReadTuples_codec + = pb::FieldCodec.ForMessage(194, global::LeanCloud.Realtime.Internal.Protocol.MaxReadTuple.Parser); + private readonly pbc::RepeatedField maxReadTuples_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField MaxReadTuples { + get { return maxReadTuples_; } + } + + /// Field number for the "cids" field. + public const int CidsFieldNumber = 25; + private static readonly pb::FieldCodec _repeated_cids_codec + = pb::FieldCodec.ForString(202); + private readonly pbc::RepeatedField cids_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField Cids { + get { return cids_; } + } + + /// Field number for the "info" field. + public const int InfoFieldNumber = 26; + private global::LeanCloud.Realtime.Internal.Protocol.ConvMemberInfo info_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::LeanCloud.Realtime.Internal.Protocol.ConvMemberInfo Info { + get { return info_; } + set { + info_ = value; + } + } + /// Gets whether the info field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasInfo { + get { return info_ != null; } + } + /// Clears the value of the info field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearInfo() { + info_ = null; + } + + /// Field number for the "tempConv" field. + public const int TempConvFieldNumber = 27; + private readonly static bool TempConvDefaultValue = false; + + private bool tempConv_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool TempConv { + get { if ((_hasBits0 & 8192) != 0) { return tempConv_; } else { return TempConvDefaultValue; } } + set { + _hasBits0 |= 8192; + tempConv_ = value; + } + } + /// Gets whether the "tempConv" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasTempConv { + get { return (_hasBits0 & 8192) != 0; } + } + /// Clears the value of the "tempConv" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearTempConv() { + _hasBits0 &= ~8192; + } + + /// Field number for the "tempConvTTL" field. + public const int TempConvTTLFieldNumber = 28; + private readonly static int TempConvTTLDefaultValue = 0; + + private int tempConvTTL_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int TempConvTTL { + get { if ((_hasBits0 & 16384) != 0) { return tempConvTTL_; } else { return TempConvTTLDefaultValue; } } + set { + _hasBits0 |= 16384; + tempConvTTL_ = value; + } + } + /// Gets whether the "tempConvTTL" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasTempConvTTL { + get { return (_hasBits0 & 16384) != 0; } + } + /// Clears the value of the "tempConvTTL" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearTempConvTTL() { + _hasBits0 &= ~16384; + } + + /// Field number for the "tempConvIds" field. + public const int TempConvIdsFieldNumber = 29; + private static readonly pb::FieldCodec _repeated_tempConvIds_codec + = pb::FieldCodec.ForString(234); + private readonly pbc::RepeatedField tempConvIds_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField TempConvIds { + get { return tempConvIds_; } + } + + /// Field number for the "allowedPids" field. + public const int AllowedPidsFieldNumber = 30; + private static readonly pb::FieldCodec _repeated_allowedPids_codec + = pb::FieldCodec.ForString(242); + private readonly pbc::RepeatedField allowedPids_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField AllowedPids { + get { return allowedPids_; } + } + + /// Field number for the "failedPids" field. + public const int FailedPidsFieldNumber = 31; + private static readonly pb::FieldCodec _repeated_failedPids_codec + = pb::FieldCodec.ForMessage(250, global::LeanCloud.Realtime.Internal.Protocol.ErrorCommand.Parser); + private readonly pbc::RepeatedField failedPids_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField FailedPids { + get { return failedPids_; } + } + + /// Field number for the "next" field. + public const int NextFieldNumber = 40; + private readonly static string NextDefaultValue = ""; + + private string next_; + /// + /// used in shutup query + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Next { + get { return next_ ?? NextDefaultValue; } + set { + next_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "next" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasNext { + get { return next_ != null; } + } + /// Clears the value of the "next" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearNext() { + next_ = null; + } + + /// Field number for the "results" field. + public const int ResultsFieldNumber = 100; + private global::LeanCloud.Realtime.Internal.Protocol.JsonObjectMessage results_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::LeanCloud.Realtime.Internal.Protocol.JsonObjectMessage Results { + get { return results_; } + set { + results_ = value; + } + } + /// Gets whether the results field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasResults { + get { return results_ != null; } + } + /// Clears the value of the results field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearResults() { + results_ = null; + } + + /// Field number for the "where" field. + public const int WhereFieldNumber = 101; + private global::LeanCloud.Realtime.Internal.Protocol.JsonObjectMessage where_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::LeanCloud.Realtime.Internal.Protocol.JsonObjectMessage Where { + get { return where_; } + set { + where_ = value; + } + } + /// Gets whether the where field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasWhere { + get { return where_ != null; } + } + /// Clears the value of the where field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearWhere() { + where_ = null; + } + + /// Field number for the "attr" field. + public const int AttrFieldNumber = 103; + private global::LeanCloud.Realtime.Internal.Protocol.JsonObjectMessage attr_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::LeanCloud.Realtime.Internal.Protocol.JsonObjectMessage Attr { + get { return attr_; } + set { + attr_ = value; + } + } + /// Gets whether the attr field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasAttr { + get { return attr_ != null; } + } + /// Clears the value of the attr field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearAttr() { + attr_ = null; + } + + /// Field number for the "attrModified" field. + public const int AttrModifiedFieldNumber = 104; + private global::LeanCloud.Realtime.Internal.Protocol.JsonObjectMessage attrModified_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::LeanCloud.Realtime.Internal.Protocol.JsonObjectMessage AttrModified { + get { return attrModified_; } + set { + attrModified_ = value; + } + } + /// Gets whether the attrModified field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasAttrModified { + get { return attrModified_ != null; } + } + /// Clears the value of the attrModified field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearAttrModified() { + attrModified_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as ConvCommand); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(ConvCommand other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if(!m_.Equals(other.m_)) return false; + if (Transient != other.Transient) return false; + if (Unique != other.Unique) return false; + if (Cid != other.Cid) return false; + if (Cdate != other.Cdate) return false; + if (InitBy != other.InitBy) return false; + if (Sort != other.Sort) return false; + if (Limit != other.Limit) return false; + if (Skip != other.Skip) return false; + if (Flag != other.Flag) return false; + if (Count != other.Count) return false; + if (Udate != other.Udate) return false; + if (T != other.T) return false; + if (N != other.N) return false; + if (S != other.S) return false; + if (StatusSub != other.StatusSub) return false; + if (StatusPub != other.StatusPub) return false; + if (StatusTTL != other.StatusTTL) return false; + if (UniqueId != other.UniqueId) return false; + if (TargetClientId != other.TargetClientId) return false; + if (MaxReadTimestamp != other.MaxReadTimestamp) return false; + if (MaxAckTimestamp != other.MaxAckTimestamp) return false; + if (QueryAllMembers != other.QueryAllMembers) return false; + if(!maxReadTuples_.Equals(other.maxReadTuples_)) return false; + if(!cids_.Equals(other.cids_)) return false; + if (!object.Equals(Info, other.Info)) return false; + if (TempConv != other.TempConv) return false; + if (TempConvTTL != other.TempConvTTL) return false; + if(!tempConvIds_.Equals(other.tempConvIds_)) return false; + if(!allowedPids_.Equals(other.allowedPids_)) return false; + if(!failedPids_.Equals(other.failedPids_)) return false; + if (Next != other.Next) return false; + if (!object.Equals(Results, other.Results)) return false; + if (!object.Equals(Where, other.Where)) return false; + if (!object.Equals(Attr, other.Attr)) return false; + if (!object.Equals(AttrModified, other.AttrModified)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + hash ^= m_.GetHashCode(); + if (HasTransient) hash ^= Transient.GetHashCode(); + if (HasUnique) hash ^= Unique.GetHashCode(); + if (HasCid) hash ^= Cid.GetHashCode(); + if (HasCdate) hash ^= Cdate.GetHashCode(); + if (HasInitBy) hash ^= InitBy.GetHashCode(); + if (HasSort) hash ^= Sort.GetHashCode(); + if (HasLimit) hash ^= Limit.GetHashCode(); + if (HasSkip) hash ^= Skip.GetHashCode(); + if (HasFlag) hash ^= Flag.GetHashCode(); + if (HasCount) hash ^= Count.GetHashCode(); + if (HasUdate) hash ^= Udate.GetHashCode(); + if (HasT) hash ^= T.GetHashCode(); + if (HasN) hash ^= N.GetHashCode(); + if (HasS) hash ^= S.GetHashCode(); + if (HasStatusSub) hash ^= StatusSub.GetHashCode(); + if (HasStatusPub) hash ^= StatusPub.GetHashCode(); + if (HasStatusTTL) hash ^= StatusTTL.GetHashCode(); + if (HasUniqueId) hash ^= UniqueId.GetHashCode(); + if (HasTargetClientId) hash ^= TargetClientId.GetHashCode(); + if (HasMaxReadTimestamp) hash ^= MaxReadTimestamp.GetHashCode(); + if (HasMaxAckTimestamp) hash ^= MaxAckTimestamp.GetHashCode(); + if (HasQueryAllMembers) hash ^= QueryAllMembers.GetHashCode(); + hash ^= maxReadTuples_.GetHashCode(); + hash ^= cids_.GetHashCode(); + if (HasInfo) hash ^= Info.GetHashCode(); + if (HasTempConv) hash ^= TempConv.GetHashCode(); + if (HasTempConvTTL) hash ^= TempConvTTL.GetHashCode(); + hash ^= tempConvIds_.GetHashCode(); + hash ^= allowedPids_.GetHashCode(); + hash ^= failedPids_.GetHashCode(); + if (HasNext) hash ^= Next.GetHashCode(); + if (HasResults) hash ^= Results.GetHashCode(); + if (HasWhere) hash ^= Where.GetHashCode(); + if (HasAttr) hash ^= Attr.GetHashCode(); + if (HasAttrModified) hash ^= AttrModified.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + m_.WriteTo(output, _repeated_m_codec); + if (HasTransient) { + output.WriteRawTag(16); + output.WriteBool(Transient); + } + if (HasUnique) { + output.WriteRawTag(24); + output.WriteBool(Unique); + } + if (HasCid) { + output.WriteRawTag(34); + output.WriteString(Cid); + } + if (HasCdate) { + output.WriteRawTag(42); + output.WriteString(Cdate); + } + if (HasInitBy) { + output.WriteRawTag(50); + output.WriteString(InitBy); + } + if (HasSort) { + output.WriteRawTag(58); + output.WriteString(Sort); + } + if (HasLimit) { + output.WriteRawTag(64); + output.WriteInt32(Limit); + } + if (HasSkip) { + output.WriteRawTag(72); + output.WriteInt32(Skip); + } + if (HasFlag) { + output.WriteRawTag(80); + output.WriteInt32(Flag); + } + if (HasCount) { + output.WriteRawTag(88); + output.WriteInt32(Count); + } + if (HasUdate) { + output.WriteRawTag(98); + output.WriteString(Udate); + } + if (HasT) { + output.WriteRawTag(104); + output.WriteInt64(T); + } + if (HasN) { + output.WriteRawTag(114); + output.WriteString(N); + } + if (HasS) { + output.WriteRawTag(122); + output.WriteString(S); + } + if (HasStatusSub) { + output.WriteRawTag(128, 1); + output.WriteBool(StatusSub); + } + if (HasStatusPub) { + output.WriteRawTag(136, 1); + output.WriteBool(StatusPub); + } + if (HasStatusTTL) { + output.WriteRawTag(144, 1); + output.WriteInt32(StatusTTL); + } + if (HasUniqueId) { + output.WriteRawTag(154, 1); + output.WriteString(UniqueId); + } + if (HasTargetClientId) { + output.WriteRawTag(162, 1); + output.WriteString(TargetClientId); + } + if (HasMaxReadTimestamp) { + output.WriteRawTag(168, 1); + output.WriteInt64(MaxReadTimestamp); + } + if (HasMaxAckTimestamp) { + output.WriteRawTag(176, 1); + output.WriteInt64(MaxAckTimestamp); + } + if (HasQueryAllMembers) { + output.WriteRawTag(184, 1); + output.WriteBool(QueryAllMembers); + } + maxReadTuples_.WriteTo(output, _repeated_maxReadTuples_codec); + cids_.WriteTo(output, _repeated_cids_codec); + if (HasInfo) { + output.WriteRawTag(210, 1); + output.WriteMessage(Info); + } + if (HasTempConv) { + output.WriteRawTag(216, 1); + output.WriteBool(TempConv); + } + if (HasTempConvTTL) { + output.WriteRawTag(224, 1); + output.WriteInt32(TempConvTTL); + } + tempConvIds_.WriteTo(output, _repeated_tempConvIds_codec); + allowedPids_.WriteTo(output, _repeated_allowedPids_codec); + failedPids_.WriteTo(output, _repeated_failedPids_codec); + if (HasNext) { + output.WriteRawTag(194, 2); + output.WriteString(Next); + } + if (HasResults) { + output.WriteRawTag(162, 6); + output.WriteMessage(Results); + } + if (HasWhere) { + output.WriteRawTag(170, 6); + output.WriteMessage(Where); + } + if (HasAttr) { + output.WriteRawTag(186, 6); + output.WriteMessage(Attr); + } + if (HasAttrModified) { + output.WriteRawTag(194, 6); + output.WriteMessage(AttrModified); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + size += m_.CalculateSize(_repeated_m_codec); + if (HasTransient) { + size += 1 + 1; + } + if (HasUnique) { + size += 1 + 1; + } + if (HasCid) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Cid); + } + if (HasCdate) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Cdate); + } + if (HasInitBy) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(InitBy); + } + if (HasSort) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Sort); + } + if (HasLimit) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Limit); + } + if (HasSkip) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Skip); + } + if (HasFlag) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Flag); + } + if (HasCount) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Count); + } + if (HasUdate) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Udate); + } + if (HasT) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(T); + } + if (HasN) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(N); + } + if (HasS) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(S); + } + if (HasStatusSub) { + size += 2 + 1; + } + if (HasStatusPub) { + size += 2 + 1; + } + if (HasStatusTTL) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(StatusTTL); + } + if (HasUniqueId) { + size += 2 + pb::CodedOutputStream.ComputeStringSize(UniqueId); + } + if (HasTargetClientId) { + size += 2 + pb::CodedOutputStream.ComputeStringSize(TargetClientId); + } + if (HasMaxReadTimestamp) { + size += 2 + pb::CodedOutputStream.ComputeInt64Size(MaxReadTimestamp); + } + if (HasMaxAckTimestamp) { + size += 2 + pb::CodedOutputStream.ComputeInt64Size(MaxAckTimestamp); + } + if (HasQueryAllMembers) { + size += 2 + 1; + } + size += maxReadTuples_.CalculateSize(_repeated_maxReadTuples_codec); + size += cids_.CalculateSize(_repeated_cids_codec); + if (HasInfo) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(Info); + } + if (HasTempConv) { + size += 2 + 1; + } + if (HasTempConvTTL) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(TempConvTTL); + } + size += tempConvIds_.CalculateSize(_repeated_tempConvIds_codec); + size += allowedPids_.CalculateSize(_repeated_allowedPids_codec); + size += failedPids_.CalculateSize(_repeated_failedPids_codec); + if (HasNext) { + size += 2 + pb::CodedOutputStream.ComputeStringSize(Next); + } + if (HasResults) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(Results); + } + if (HasWhere) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(Where); + } + if (HasAttr) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(Attr); + } + if (HasAttrModified) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(AttrModified); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(ConvCommand other) { + if (other == null) { + return; + } + m_.Add(other.m_); + if (other.HasTransient) { + Transient = other.Transient; + } + if (other.HasUnique) { + Unique = other.Unique; + } + if (other.HasCid) { + Cid = other.Cid; + } + if (other.HasCdate) { + Cdate = other.Cdate; + } + if (other.HasInitBy) { + InitBy = other.InitBy; + } + if (other.HasSort) { + Sort = other.Sort; + } + if (other.HasLimit) { + Limit = other.Limit; + } + if (other.HasSkip) { + Skip = other.Skip; + } + if (other.HasFlag) { + Flag = other.Flag; + } + if (other.HasCount) { + Count = other.Count; + } + if (other.HasUdate) { + Udate = other.Udate; + } + if (other.HasT) { + T = other.T; + } + if (other.HasN) { + N = other.N; + } + if (other.HasS) { + S = other.S; + } + if (other.HasStatusSub) { + StatusSub = other.StatusSub; + } + if (other.HasStatusPub) { + StatusPub = other.StatusPub; + } + if (other.HasStatusTTL) { + StatusTTL = other.StatusTTL; + } + if (other.HasUniqueId) { + UniqueId = other.UniqueId; + } + if (other.HasTargetClientId) { + TargetClientId = other.TargetClientId; + } + if (other.HasMaxReadTimestamp) { + MaxReadTimestamp = other.MaxReadTimestamp; + } + if (other.HasMaxAckTimestamp) { + MaxAckTimestamp = other.MaxAckTimestamp; + } + if (other.HasQueryAllMembers) { + QueryAllMembers = other.QueryAllMembers; + } + maxReadTuples_.Add(other.maxReadTuples_); + cids_.Add(other.cids_); + if (other.HasInfo) { + if (!HasInfo) { + Info = new global::LeanCloud.Realtime.Internal.Protocol.ConvMemberInfo(); + } + Info.MergeFrom(other.Info); + } + if (other.HasTempConv) { + TempConv = other.TempConv; + } + if (other.HasTempConvTTL) { + TempConvTTL = other.TempConvTTL; + } + tempConvIds_.Add(other.tempConvIds_); + allowedPids_.Add(other.allowedPids_); + failedPids_.Add(other.failedPids_); + if (other.HasNext) { + Next = other.Next; + } + if (other.HasResults) { + if (!HasResults) { + Results = new global::LeanCloud.Realtime.Internal.Protocol.JsonObjectMessage(); + } + Results.MergeFrom(other.Results); + } + if (other.HasWhere) { + if (!HasWhere) { + Where = new global::LeanCloud.Realtime.Internal.Protocol.JsonObjectMessage(); + } + Where.MergeFrom(other.Where); + } + if (other.HasAttr) { + if (!HasAttr) { + Attr = new global::LeanCloud.Realtime.Internal.Protocol.JsonObjectMessage(); + } + Attr.MergeFrom(other.Attr); + } + if (other.HasAttrModified) { + if (!HasAttrModified) { + AttrModified = new global::LeanCloud.Realtime.Internal.Protocol.JsonObjectMessage(); + } + AttrModified.MergeFrom(other.AttrModified); + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + m_.AddEntriesFrom(input, _repeated_m_codec); + break; + } + case 16: { + Transient = input.ReadBool(); + break; + } + case 24: { + Unique = input.ReadBool(); + break; + } + case 34: { + Cid = input.ReadString(); + break; + } + case 42: { + Cdate = input.ReadString(); + break; + } + case 50: { + InitBy = input.ReadString(); + break; + } + case 58: { + Sort = input.ReadString(); + break; + } + case 64: { + Limit = input.ReadInt32(); + break; + } + case 72: { + Skip = input.ReadInt32(); + break; + } + case 80: { + Flag = input.ReadInt32(); + break; + } + case 88: { + Count = input.ReadInt32(); + break; + } + case 98: { + Udate = input.ReadString(); + break; + } + case 104: { + T = input.ReadInt64(); + break; + } + case 114: { + N = input.ReadString(); + break; + } + case 122: { + S = input.ReadString(); + break; + } + case 128: { + StatusSub = input.ReadBool(); + break; + } + case 136: { + StatusPub = input.ReadBool(); + break; + } + case 144: { + StatusTTL = input.ReadInt32(); + break; + } + case 154: { + UniqueId = input.ReadString(); + break; + } + case 162: { + TargetClientId = input.ReadString(); + break; + } + case 168: { + MaxReadTimestamp = input.ReadInt64(); + break; + } + case 176: { + MaxAckTimestamp = input.ReadInt64(); + break; + } + case 184: { + QueryAllMembers = input.ReadBool(); + break; + } + case 194: { + maxReadTuples_.AddEntriesFrom(input, _repeated_maxReadTuples_codec); + break; + } + case 202: { + cids_.AddEntriesFrom(input, _repeated_cids_codec); + break; + } + case 210: { + if (!HasInfo) { + Info = new global::LeanCloud.Realtime.Internal.Protocol.ConvMemberInfo(); + } + input.ReadMessage(Info); + break; + } + case 216: { + TempConv = input.ReadBool(); + break; + } + case 224: { + TempConvTTL = input.ReadInt32(); + break; + } + case 234: { + tempConvIds_.AddEntriesFrom(input, _repeated_tempConvIds_codec); + break; + } + case 242: { + allowedPids_.AddEntriesFrom(input, _repeated_allowedPids_codec); + break; + } + case 250: { + failedPids_.AddEntriesFrom(input, _repeated_failedPids_codec); + break; + } + case 322: { + Next = input.ReadString(); + break; + } + case 802: { + if (!HasResults) { + Results = new global::LeanCloud.Realtime.Internal.Protocol.JsonObjectMessage(); + } + input.ReadMessage(Results); + break; + } + case 810: { + if (!HasWhere) { + Where = new global::LeanCloud.Realtime.Internal.Protocol.JsonObjectMessage(); + } + input.ReadMessage(Where); + break; + } + case 826: { + if (!HasAttr) { + Attr = new global::LeanCloud.Realtime.Internal.Protocol.JsonObjectMessage(); + } + input.ReadMessage(Attr); + break; + } + case 834: { + if (!HasAttrModified) { + AttrModified = new global::LeanCloud.Realtime.Internal.Protocol.JsonObjectMessage(); + } + input.ReadMessage(AttrModified); + break; + } + } + } + } + + } + + public sealed partial class RoomCommand : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new RoomCommand()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::LeanCloud.Realtime.Internal.Protocol.Messages2ProtoReflection.Descriptor.MessageTypes[16]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public RoomCommand() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public RoomCommand(RoomCommand other) : this() { + _hasBits0 = other._hasBits0; + roomId_ = other.roomId_; + s_ = other.s_; + t_ = other.t_; + n_ = other.n_; + transient_ = other.transient_; + roomPeerIds_ = other.roomPeerIds_.Clone(); + byPeerId_ = other.byPeerId_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public RoomCommand Clone() { + return new RoomCommand(this); + } + + /// Field number for the "roomId" field. + public const int RoomIdFieldNumber = 1; + private readonly static string RoomIdDefaultValue = ""; + + private string roomId_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string RoomId { + get { return roomId_ ?? RoomIdDefaultValue; } + set { + roomId_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "roomId" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasRoomId { + get { return roomId_ != null; } + } + /// Clears the value of the "roomId" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearRoomId() { + roomId_ = null; + } + + /// Field number for the "s" field. + public const int SFieldNumber = 2; + private readonly static string SDefaultValue = ""; + + private string s_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string S { + get { return s_ ?? SDefaultValue; } + set { + s_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "s" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasS { + get { return s_ != null; } + } + /// Clears the value of the "s" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearS() { + s_ = null; + } + + /// Field number for the "t" field. + public const int TFieldNumber = 3; + private readonly static long TDefaultValue = 0L; + + private long t_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long T { + get { if ((_hasBits0 & 1) != 0) { return t_; } else { return TDefaultValue; } } + set { + _hasBits0 |= 1; + t_ = value; + } + } + /// Gets whether the "t" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasT { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "t" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearT() { + _hasBits0 &= ~1; + } + + /// Field number for the "n" field. + public const int NFieldNumber = 4; + private readonly static string NDefaultValue = ""; + + private string n_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string N { + get { return n_ ?? NDefaultValue; } + set { + n_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "n" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasN { + get { return n_ != null; } + } + /// Clears the value of the "n" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearN() { + n_ = null; + } + + /// Field number for the "transient" field. + public const int TransientFieldNumber = 5; + private readonly static bool TransientDefaultValue = false; + + private bool transient_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Transient { + get { if ((_hasBits0 & 2) != 0) { return transient_; } else { return TransientDefaultValue; } } + set { + _hasBits0 |= 2; + transient_ = value; + } + } + /// Gets whether the "transient" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasTransient { + get { return (_hasBits0 & 2) != 0; } + } + /// Clears the value of the "transient" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearTransient() { + _hasBits0 &= ~2; + } + + /// Field number for the "roomPeerIds" field. + public const int RoomPeerIdsFieldNumber = 6; + private static readonly pb::FieldCodec _repeated_roomPeerIds_codec + = pb::FieldCodec.ForString(50); + private readonly pbc::RepeatedField roomPeerIds_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RoomPeerIds { + get { return roomPeerIds_; } + } + + /// Field number for the "byPeerId" field. + public const int ByPeerIdFieldNumber = 7; + private readonly static string ByPeerIdDefaultValue = ""; + + private string byPeerId_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string ByPeerId { + get { return byPeerId_ ?? ByPeerIdDefaultValue; } + set { + byPeerId_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "byPeerId" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasByPeerId { + get { return byPeerId_ != null; } + } + /// Clears the value of the "byPeerId" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearByPeerId() { + byPeerId_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as RoomCommand); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(RoomCommand other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (RoomId != other.RoomId) return false; + if (S != other.S) return false; + if (T != other.T) return false; + if (N != other.N) return false; + if (Transient != other.Transient) return false; + if(!roomPeerIds_.Equals(other.roomPeerIds_)) return false; + if (ByPeerId != other.ByPeerId) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasRoomId) hash ^= RoomId.GetHashCode(); + if (HasS) hash ^= S.GetHashCode(); + if (HasT) hash ^= T.GetHashCode(); + if (HasN) hash ^= N.GetHashCode(); + if (HasTransient) hash ^= Transient.GetHashCode(); + hash ^= roomPeerIds_.GetHashCode(); + if (HasByPeerId) hash ^= ByPeerId.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (HasRoomId) { + output.WriteRawTag(10); + output.WriteString(RoomId); + } + if (HasS) { + output.WriteRawTag(18); + output.WriteString(S); + } + if (HasT) { + output.WriteRawTag(24); + output.WriteInt64(T); + } + if (HasN) { + output.WriteRawTag(34); + output.WriteString(N); + } + if (HasTransient) { + output.WriteRawTag(40); + output.WriteBool(Transient); + } + roomPeerIds_.WriteTo(output, _repeated_roomPeerIds_codec); + if (HasByPeerId) { + output.WriteRawTag(58); + output.WriteString(ByPeerId); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasRoomId) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(RoomId); + } + if (HasS) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(S); + } + if (HasT) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(T); + } + if (HasN) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(N); + } + if (HasTransient) { + size += 1 + 1; + } + size += roomPeerIds_.CalculateSize(_repeated_roomPeerIds_codec); + if (HasByPeerId) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(ByPeerId); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(RoomCommand other) { + if (other == null) { + return; + } + if (other.HasRoomId) { + RoomId = other.RoomId; + } + if (other.HasS) { + S = other.S; + } + if (other.HasT) { + T = other.T; + } + if (other.HasN) { + N = other.N; + } + if (other.HasTransient) { + Transient = other.Transient; + } + roomPeerIds_.Add(other.roomPeerIds_); + if (other.HasByPeerId) { + ByPeerId = other.ByPeerId; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + RoomId = input.ReadString(); + break; + } + case 18: { + S = input.ReadString(); + break; + } + case 24: { + T = input.ReadInt64(); + break; + } + case 34: { + N = input.ReadString(); + break; + } + case 40: { + Transient = input.ReadBool(); + break; + } + case 50: { + roomPeerIds_.AddEntriesFrom(input, _repeated_roomPeerIds_codec); + break; + } + case 58: { + ByPeerId = input.ReadString(); + break; + } + } + } + } + + } + + public sealed partial class LogsCommand : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new LogsCommand()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::LeanCloud.Realtime.Internal.Protocol.Messages2ProtoReflection.Descriptor.MessageTypes[17]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public LogsCommand() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public LogsCommand(LogsCommand other) : this() { + _hasBits0 = other._hasBits0; + cid_ = other.cid_; + l_ = other.l_; + limit_ = other.limit_; + t_ = other.t_; + tt_ = other.tt_; + tmid_ = other.tmid_; + mid_ = other.mid_; + checksum_ = other.checksum_; + stored_ = other.stored_; + direction_ = other.direction_; + tIncluded_ = other.tIncluded_; + ttIncluded_ = other.ttIncluded_; + lctype_ = other.lctype_; + logs_ = other.logs_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public LogsCommand Clone() { + return new LogsCommand(this); + } + + /// Field number for the "cid" field. + public const int CidFieldNumber = 1; + private readonly static string CidDefaultValue = ""; + + private string cid_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Cid { + get { return cid_ ?? CidDefaultValue; } + set { + cid_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "cid" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasCid { + get { return cid_ != null; } + } + /// Clears the value of the "cid" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearCid() { + cid_ = null; + } + + /// Field number for the "l" field. + public const int LFieldNumber = 2; + private readonly static int LDefaultValue = 0; + + private int l_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int L { + get { if ((_hasBits0 & 1) != 0) { return l_; } else { return LDefaultValue; } } + set { + _hasBits0 |= 1; + l_ = value; + } + } + /// Gets whether the "l" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasL { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "l" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearL() { + _hasBits0 &= ~1; + } + + /// Field number for the "limit" field. + public const int LimitFieldNumber = 3; + private readonly static int LimitDefaultValue = 0; + + private int limit_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Limit { + get { if ((_hasBits0 & 2) != 0) { return limit_; } else { return LimitDefaultValue; } } + set { + _hasBits0 |= 2; + limit_ = value; + } + } + /// Gets whether the "limit" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasLimit { + get { return (_hasBits0 & 2) != 0; } + } + /// Clears the value of the "limit" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearLimit() { + _hasBits0 &= ~2; + } + + /// Field number for the "t" field. + public const int TFieldNumber = 4; + private readonly static long TDefaultValue = 0L; + + private long t_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long T { + get { if ((_hasBits0 & 4) != 0) { return t_; } else { return TDefaultValue; } } + set { + _hasBits0 |= 4; + t_ = value; + } + } + /// Gets whether the "t" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasT { + get { return (_hasBits0 & 4) != 0; } + } + /// Clears the value of the "t" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearT() { + _hasBits0 &= ~4; + } + + /// Field number for the "tt" field. + public const int TtFieldNumber = 5; + private readonly static long TtDefaultValue = 0L; + + private long tt_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long Tt { + get { if ((_hasBits0 & 8) != 0) { return tt_; } else { return TtDefaultValue; } } + set { + _hasBits0 |= 8; + tt_ = value; + } + } + /// Gets whether the "tt" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasTt { + get { return (_hasBits0 & 8) != 0; } + } + /// Clears the value of the "tt" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearTt() { + _hasBits0 &= ~8; + } + + /// Field number for the "tmid" field. + public const int TmidFieldNumber = 6; + private readonly static string TmidDefaultValue = ""; + + private string tmid_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Tmid { + get { return tmid_ ?? TmidDefaultValue; } + set { + tmid_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "tmid" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasTmid { + get { return tmid_ != null; } + } + /// Clears the value of the "tmid" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearTmid() { + tmid_ = null; + } + + /// Field number for the "mid" field. + public const int MidFieldNumber = 7; + private readonly static string MidDefaultValue = ""; + + private string mid_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Mid { + get { return mid_ ?? MidDefaultValue; } + set { + mid_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "mid" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasMid { + get { return mid_ != null; } + } + /// Clears the value of the "mid" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearMid() { + mid_ = null; + } + + /// Field number for the "checksum" field. + public const int ChecksumFieldNumber = 8; + private readonly static string ChecksumDefaultValue = ""; + + private string checksum_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Checksum { + get { return checksum_ ?? ChecksumDefaultValue; } + set { + checksum_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "checksum" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasChecksum { + get { return checksum_ != null; } + } + /// Clears the value of the "checksum" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearChecksum() { + checksum_ = null; + } + + /// Field number for the "stored" field. + public const int StoredFieldNumber = 9; + private readonly static bool StoredDefaultValue = false; + + private bool stored_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Stored { + get { if ((_hasBits0 & 16) != 0) { return stored_; } else { return StoredDefaultValue; } } + set { + _hasBits0 |= 16; + stored_ = value; + } + } + /// Gets whether the "stored" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasStored { + get { return (_hasBits0 & 16) != 0; } + } + /// Clears the value of the "stored" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearStored() { + _hasBits0 &= ~16; + } + + /// Field number for the "direction" field. + public const int DirectionFieldNumber = 10; + private readonly static global::LeanCloud.Realtime.Internal.Protocol.LogsCommand.Types.QueryDirection DirectionDefaultValue = global::LeanCloud.Realtime.Internal.Protocol.LogsCommand.Types.QueryDirection.Old; + + private global::LeanCloud.Realtime.Internal.Protocol.LogsCommand.Types.QueryDirection direction_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::LeanCloud.Realtime.Internal.Protocol.LogsCommand.Types.QueryDirection Direction { + get { if ((_hasBits0 & 32) != 0) { return direction_; } else { return DirectionDefaultValue; } } + set { + _hasBits0 |= 32; + direction_ = value; + } + } + /// Gets whether the "direction" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDirection { + get { return (_hasBits0 & 32) != 0; } + } + /// Clears the value of the "direction" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDirection() { + _hasBits0 &= ~32; + } + + /// Field number for the "tIncluded" field. + public const int TIncludedFieldNumber = 11; + private readonly static bool TIncludedDefaultValue = false; + + private bool tIncluded_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool TIncluded { + get { if ((_hasBits0 & 64) != 0) { return tIncluded_; } else { return TIncludedDefaultValue; } } + set { + _hasBits0 |= 64; + tIncluded_ = value; + } + } + /// Gets whether the "tIncluded" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasTIncluded { + get { return (_hasBits0 & 64) != 0; } + } + /// Clears the value of the "tIncluded" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearTIncluded() { + _hasBits0 &= ~64; + } + + /// Field number for the "ttIncluded" field. + public const int TtIncludedFieldNumber = 12; + private readonly static bool TtIncludedDefaultValue = false; + + private bool ttIncluded_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool TtIncluded { + get { if ((_hasBits0 & 128) != 0) { return ttIncluded_; } else { return TtIncludedDefaultValue; } } + set { + _hasBits0 |= 128; + ttIncluded_ = value; + } + } + /// Gets whether the "ttIncluded" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasTtIncluded { + get { return (_hasBits0 & 128) != 0; } + } + /// Clears the value of the "ttIncluded" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearTtIncluded() { + _hasBits0 &= ~128; + } + + /// Field number for the "lctype" field. + public const int LctypeFieldNumber = 13; + private readonly static int LctypeDefaultValue = 0; + + private int lctype_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Lctype { + get { if ((_hasBits0 & 256) != 0) { return lctype_; } else { return LctypeDefaultValue; } } + set { + _hasBits0 |= 256; + lctype_ = value; + } + } + /// Gets whether the "lctype" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasLctype { + get { return (_hasBits0 & 256) != 0; } + } + /// Clears the value of the "lctype" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearLctype() { + _hasBits0 &= ~256; + } + + /// Field number for the "logs" field. + public const int LogsFieldNumber = 105; + private static readonly pb::FieldCodec _repeated_logs_codec + = pb::FieldCodec.ForMessage(842, global::LeanCloud.Realtime.Internal.Protocol.LogItem.Parser); + private readonly pbc::RepeatedField logs_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField Logs { + get { return logs_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as LogsCommand); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(LogsCommand other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Cid != other.Cid) return false; + if (L != other.L) return false; + if (Limit != other.Limit) return false; + if (T != other.T) return false; + if (Tt != other.Tt) return false; + if (Tmid != other.Tmid) return false; + if (Mid != other.Mid) return false; + if (Checksum != other.Checksum) return false; + if (Stored != other.Stored) return false; + if (Direction != other.Direction) return false; + if (TIncluded != other.TIncluded) return false; + if (TtIncluded != other.TtIncluded) return false; + if (Lctype != other.Lctype) return false; + if(!logs_.Equals(other.logs_)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasCid) hash ^= Cid.GetHashCode(); + if (HasL) hash ^= L.GetHashCode(); + if (HasLimit) hash ^= Limit.GetHashCode(); + if (HasT) hash ^= T.GetHashCode(); + if (HasTt) hash ^= Tt.GetHashCode(); + if (HasTmid) hash ^= Tmid.GetHashCode(); + if (HasMid) hash ^= Mid.GetHashCode(); + if (HasChecksum) hash ^= Checksum.GetHashCode(); + if (HasStored) hash ^= Stored.GetHashCode(); + if (HasDirection) hash ^= Direction.GetHashCode(); + if (HasTIncluded) hash ^= TIncluded.GetHashCode(); + if (HasTtIncluded) hash ^= TtIncluded.GetHashCode(); + if (HasLctype) hash ^= Lctype.GetHashCode(); + hash ^= logs_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (HasCid) { + output.WriteRawTag(10); + output.WriteString(Cid); + } + if (HasL) { + output.WriteRawTag(16); + output.WriteInt32(L); + } + if (HasLimit) { + output.WriteRawTag(24); + output.WriteInt32(Limit); + } + if (HasT) { + output.WriteRawTag(32); + output.WriteInt64(T); + } + if (HasTt) { + output.WriteRawTag(40); + output.WriteInt64(Tt); + } + if (HasTmid) { + output.WriteRawTag(50); + output.WriteString(Tmid); + } + if (HasMid) { + output.WriteRawTag(58); + output.WriteString(Mid); + } + if (HasChecksum) { + output.WriteRawTag(66); + output.WriteString(Checksum); + } + if (HasStored) { + output.WriteRawTag(72); + output.WriteBool(Stored); + } + if (HasDirection) { + output.WriteRawTag(80); + output.WriteEnum((int) Direction); + } + if (HasTIncluded) { + output.WriteRawTag(88); + output.WriteBool(TIncluded); + } + if (HasTtIncluded) { + output.WriteRawTag(96); + output.WriteBool(TtIncluded); + } + if (HasLctype) { + output.WriteRawTag(104); + output.WriteInt32(Lctype); + } + logs_.WriteTo(output, _repeated_logs_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasCid) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Cid); + } + if (HasL) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(L); + } + if (HasLimit) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Limit); + } + if (HasT) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(T); + } + if (HasTt) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(Tt); + } + if (HasTmid) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Tmid); + } + if (HasMid) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Mid); + } + if (HasChecksum) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Checksum); + } + if (HasStored) { + size += 1 + 1; + } + if (HasDirection) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Direction); + } + if (HasTIncluded) { + size += 1 + 1; + } + if (HasTtIncluded) { + size += 1 + 1; + } + if (HasLctype) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Lctype); + } + size += logs_.CalculateSize(_repeated_logs_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(LogsCommand other) { + if (other == null) { + return; + } + if (other.HasCid) { + Cid = other.Cid; + } + if (other.HasL) { + L = other.L; + } + if (other.HasLimit) { + Limit = other.Limit; + } + if (other.HasT) { + T = other.T; + } + if (other.HasTt) { + Tt = other.Tt; + } + if (other.HasTmid) { + Tmid = other.Tmid; + } + if (other.HasMid) { + Mid = other.Mid; + } + if (other.HasChecksum) { + Checksum = other.Checksum; + } + if (other.HasStored) { + Stored = other.Stored; + } + if (other.HasDirection) { + Direction = other.Direction; + } + if (other.HasTIncluded) { + TIncluded = other.TIncluded; + } + if (other.HasTtIncluded) { + TtIncluded = other.TtIncluded; + } + if (other.HasLctype) { + Lctype = other.Lctype; + } + logs_.Add(other.logs_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + Cid = input.ReadString(); + break; + } + case 16: { + L = input.ReadInt32(); + break; + } + case 24: { + Limit = input.ReadInt32(); + break; + } + case 32: { + T = input.ReadInt64(); + break; + } + case 40: { + Tt = input.ReadInt64(); + break; + } + case 50: { + Tmid = input.ReadString(); + break; + } + case 58: { + Mid = input.ReadString(); + break; + } + case 66: { + Checksum = input.ReadString(); + break; + } + case 72: { + Stored = input.ReadBool(); + break; + } + case 80: { + Direction = (global::LeanCloud.Realtime.Internal.Protocol.LogsCommand.Types.QueryDirection) input.ReadEnum(); + break; + } + case 88: { + TIncluded = input.ReadBool(); + break; + } + case 96: { + TtIncluded = input.ReadBool(); + break; + } + case 104: { + Lctype = input.ReadInt32(); + break; + } + case 842: { + logs_.AddEntriesFrom(input, _repeated_logs_codec); + break; + } + } + } + } + + #region Nested types + /// Container for nested types declared in the LogsCommand message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static partial class Types { + public enum QueryDirection { + [pbr::OriginalName("OLD")] Old = 1, + [pbr::OriginalName("NEW")] New = 2, + } + + } + #endregion + + } + + public sealed partial class RcpCommand : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new RcpCommand()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::LeanCloud.Realtime.Internal.Protocol.Messages2ProtoReflection.Descriptor.MessageTypes[18]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public RcpCommand() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public RcpCommand(RcpCommand other) : this() { + _hasBits0 = other._hasBits0; + id_ = other.id_; + cid_ = other.cid_; + t_ = other.t_; + read_ = other.read_; + from_ = other.from_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public RcpCommand Clone() { + return new RcpCommand(this); + } + + /// Field number for the "id" field. + public const int IdFieldNumber = 1; + private readonly static string IdDefaultValue = ""; + + private string id_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Id { + get { return id_ ?? IdDefaultValue; } + set { + id_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "id" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasId { + get { return id_ != null; } + } + /// Clears the value of the "id" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearId() { + id_ = null; + } + + /// Field number for the "cid" field. + public const int CidFieldNumber = 2; + private readonly static string CidDefaultValue = ""; + + private string cid_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Cid { + get { return cid_ ?? CidDefaultValue; } + set { + cid_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "cid" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasCid { + get { return cid_ != null; } + } + /// Clears the value of the "cid" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearCid() { + cid_ = null; + } + + /// Field number for the "t" field. + public const int TFieldNumber = 3; + private readonly static long TDefaultValue = 0L; + + private long t_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long T { + get { if ((_hasBits0 & 1) != 0) { return t_; } else { return TDefaultValue; } } + set { + _hasBits0 |= 1; + t_ = value; + } + } + /// Gets whether the "t" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasT { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "t" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearT() { + _hasBits0 &= ~1; + } + + /// Field number for the "read" field. + public const int ReadFieldNumber = 4; + private readonly static bool ReadDefaultValue = false; + + private bool read_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Read { + get { if ((_hasBits0 & 2) != 0) { return read_; } else { return ReadDefaultValue; } } + set { + _hasBits0 |= 2; + read_ = value; + } + } + /// Gets whether the "read" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasRead { + get { return (_hasBits0 & 2) != 0; } + } + /// Clears the value of the "read" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearRead() { + _hasBits0 &= ~2; + } + + /// Field number for the "from" field. + public const int FromFieldNumber = 5; + private readonly static string FromDefaultValue = ""; + + private string from_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string From { + get { return from_ ?? FromDefaultValue; } + set { + from_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "from" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasFrom { + get { return from_ != null; } + } + /// Clears the value of the "from" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearFrom() { + from_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as RcpCommand); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(RcpCommand other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Id != other.Id) return false; + if (Cid != other.Cid) return false; + if (T != other.T) return false; + if (Read != other.Read) return false; + if (From != other.From) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasId) hash ^= Id.GetHashCode(); + if (HasCid) hash ^= Cid.GetHashCode(); + if (HasT) hash ^= T.GetHashCode(); + if (HasRead) hash ^= Read.GetHashCode(); + if (HasFrom) hash ^= From.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (HasId) { + output.WriteRawTag(10); + output.WriteString(Id); + } + if (HasCid) { + output.WriteRawTag(18); + output.WriteString(Cid); + } + if (HasT) { + output.WriteRawTag(24); + output.WriteInt64(T); + } + if (HasRead) { + output.WriteRawTag(32); + output.WriteBool(Read); + } + if (HasFrom) { + output.WriteRawTag(42); + output.WriteString(From); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasId) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Id); + } + if (HasCid) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Cid); + } + if (HasT) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(T); + } + if (HasRead) { + size += 1 + 1; + } + if (HasFrom) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(From); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(RcpCommand other) { + if (other == null) { + return; + } + if (other.HasId) { + Id = other.Id; + } + if (other.HasCid) { + Cid = other.Cid; + } + if (other.HasT) { + T = other.T; + } + if (other.HasRead) { + Read = other.Read; + } + if (other.HasFrom) { + From = other.From; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + Id = input.ReadString(); + break; + } + case 18: { + Cid = input.ReadString(); + break; + } + case 24: { + T = input.ReadInt64(); + break; + } + case 32: { + Read = input.ReadBool(); + break; + } + case 42: { + From = input.ReadString(); + break; + } + } + } + } + + } + + public sealed partial class ReadTuple : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ReadTuple()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::LeanCloud.Realtime.Internal.Protocol.Messages2ProtoReflection.Descriptor.MessageTypes[19]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ReadTuple() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ReadTuple(ReadTuple other) : this() { + _hasBits0 = other._hasBits0; + cid_ = other.cid_; + timestamp_ = other.timestamp_; + mid_ = other.mid_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ReadTuple Clone() { + return new ReadTuple(this); + } + + /// Field number for the "cid" field. + public const int CidFieldNumber = 1; + private readonly static string CidDefaultValue = ""; + + private string cid_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Cid { + get { return cid_ ?? CidDefaultValue; } + set { + cid_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "cid" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasCid { + get { return cid_ != null; } + } + /// Clears the value of the "cid" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearCid() { + cid_ = null; + } + + /// Field number for the "timestamp" field. + public const int TimestampFieldNumber = 2; + private readonly static long TimestampDefaultValue = 0L; + + private long timestamp_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long Timestamp { + get { if ((_hasBits0 & 1) != 0) { return timestamp_; } else { return TimestampDefaultValue; } } + set { + _hasBits0 |= 1; + timestamp_ = value; + } + } + /// Gets whether the "timestamp" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasTimestamp { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "timestamp" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearTimestamp() { + _hasBits0 &= ~1; + } + + /// Field number for the "mid" field. + public const int MidFieldNumber = 3; + private readonly static string MidDefaultValue = ""; + + private string mid_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Mid { + get { return mid_ ?? MidDefaultValue; } + set { + mid_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "mid" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasMid { + get { return mid_ != null; } + } + /// Clears the value of the "mid" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearMid() { + mid_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as ReadTuple); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(ReadTuple other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Cid != other.Cid) return false; + if (Timestamp != other.Timestamp) return false; + if (Mid != other.Mid) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasCid) hash ^= Cid.GetHashCode(); + if (HasTimestamp) hash ^= Timestamp.GetHashCode(); + if (HasMid) hash ^= Mid.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (HasCid) { + output.WriteRawTag(10); + output.WriteString(Cid); + } + if (HasTimestamp) { + output.WriteRawTag(16); + output.WriteInt64(Timestamp); + } + if (HasMid) { + output.WriteRawTag(26); + output.WriteString(Mid); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasCid) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Cid); + } + if (HasTimestamp) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(Timestamp); + } + if (HasMid) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Mid); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(ReadTuple other) { + if (other == null) { + return; + } + if (other.HasCid) { + Cid = other.Cid; + } + if (other.HasTimestamp) { + Timestamp = other.Timestamp; + } + if (other.HasMid) { + Mid = other.Mid; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + Cid = input.ReadString(); + break; + } + case 16: { + Timestamp = input.ReadInt64(); + break; + } + case 26: { + Mid = input.ReadString(); + break; + } + } + } + } + + } + + public sealed partial class MaxReadTuple : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new MaxReadTuple()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::LeanCloud.Realtime.Internal.Protocol.Messages2ProtoReflection.Descriptor.MessageTypes[20]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public MaxReadTuple() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public MaxReadTuple(MaxReadTuple other) : this() { + _hasBits0 = other._hasBits0; + pid_ = other.pid_; + maxAckTimestamp_ = other.maxAckTimestamp_; + maxReadTimestamp_ = other.maxReadTimestamp_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public MaxReadTuple Clone() { + return new MaxReadTuple(this); + } + + /// Field number for the "pid" field. + public const int PidFieldNumber = 1; + private readonly static string PidDefaultValue = ""; + + private string pid_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Pid { + get { return pid_ ?? PidDefaultValue; } + set { + pid_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "pid" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasPid { + get { return pid_ != null; } + } + /// Clears the value of the "pid" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearPid() { + pid_ = null; + } + + /// Field number for the "maxAckTimestamp" field. + public const int MaxAckTimestampFieldNumber = 2; + private readonly static long MaxAckTimestampDefaultValue = 0L; + + private long maxAckTimestamp_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long MaxAckTimestamp { + get { if ((_hasBits0 & 1) != 0) { return maxAckTimestamp_; } else { return MaxAckTimestampDefaultValue; } } + set { + _hasBits0 |= 1; + maxAckTimestamp_ = value; + } + } + /// Gets whether the "maxAckTimestamp" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasMaxAckTimestamp { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "maxAckTimestamp" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearMaxAckTimestamp() { + _hasBits0 &= ~1; + } + + /// Field number for the "maxReadTimestamp" field. + public const int MaxReadTimestampFieldNumber = 3; + private readonly static long MaxReadTimestampDefaultValue = 0L; + + private long maxReadTimestamp_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long MaxReadTimestamp { + get { if ((_hasBits0 & 2) != 0) { return maxReadTimestamp_; } else { return MaxReadTimestampDefaultValue; } } + set { + _hasBits0 |= 2; + maxReadTimestamp_ = value; + } + } + /// Gets whether the "maxReadTimestamp" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasMaxReadTimestamp { + get { return (_hasBits0 & 2) != 0; } + } + /// Clears the value of the "maxReadTimestamp" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearMaxReadTimestamp() { + _hasBits0 &= ~2; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as MaxReadTuple); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(MaxReadTuple other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Pid != other.Pid) return false; + if (MaxAckTimestamp != other.MaxAckTimestamp) return false; + if (MaxReadTimestamp != other.MaxReadTimestamp) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasPid) hash ^= Pid.GetHashCode(); + if (HasMaxAckTimestamp) hash ^= MaxAckTimestamp.GetHashCode(); + if (HasMaxReadTimestamp) hash ^= MaxReadTimestamp.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (HasPid) { + output.WriteRawTag(10); + output.WriteString(Pid); + } + if (HasMaxAckTimestamp) { + output.WriteRawTag(16); + output.WriteInt64(MaxAckTimestamp); + } + if (HasMaxReadTimestamp) { + output.WriteRawTag(24); + output.WriteInt64(MaxReadTimestamp); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasPid) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Pid); + } + if (HasMaxAckTimestamp) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(MaxAckTimestamp); + } + if (HasMaxReadTimestamp) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(MaxReadTimestamp); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(MaxReadTuple other) { + if (other == null) { + return; + } + if (other.HasPid) { + Pid = other.Pid; + } + if (other.HasMaxAckTimestamp) { + MaxAckTimestamp = other.MaxAckTimestamp; + } + if (other.HasMaxReadTimestamp) { + MaxReadTimestamp = other.MaxReadTimestamp; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + Pid = input.ReadString(); + break; + } + case 16: { + MaxAckTimestamp = input.ReadInt64(); + break; + } + case 24: { + MaxReadTimestamp = input.ReadInt64(); + break; + } + } + } + } + + } + + public sealed partial class ReadCommand : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ReadCommand()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::LeanCloud.Realtime.Internal.Protocol.Messages2ProtoReflection.Descriptor.MessageTypes[21]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ReadCommand() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ReadCommand(ReadCommand other) : this() { + cid_ = other.cid_; + cids_ = other.cids_.Clone(); + convs_ = other.convs_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ReadCommand Clone() { + return new ReadCommand(this); + } + + /// Field number for the "cid" field. + public const int CidFieldNumber = 1; + private readonly static string CidDefaultValue = ""; + + private string cid_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Cid { + get { return cid_ ?? CidDefaultValue; } + set { + cid_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "cid" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasCid { + get { return cid_ != null; } + } + /// Clears the value of the "cid" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearCid() { + cid_ = null; + } + + /// Field number for the "cids" field. + public const int CidsFieldNumber = 2; + private static readonly pb::FieldCodec _repeated_cids_codec + = pb::FieldCodec.ForString(18); + private readonly pbc::RepeatedField cids_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField Cids { + get { return cids_; } + } + + /// Field number for the "convs" field. + public const int ConvsFieldNumber = 3; + private static readonly pb::FieldCodec _repeated_convs_codec + = pb::FieldCodec.ForMessage(26, global::LeanCloud.Realtime.Internal.Protocol.ReadTuple.Parser); + private readonly pbc::RepeatedField convs_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField Convs { + get { return convs_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as ReadCommand); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(ReadCommand other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Cid != other.Cid) return false; + if(!cids_.Equals(other.cids_)) return false; + if(!convs_.Equals(other.convs_)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasCid) hash ^= Cid.GetHashCode(); + hash ^= cids_.GetHashCode(); + hash ^= convs_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (HasCid) { + output.WriteRawTag(10); + output.WriteString(Cid); + } + cids_.WriteTo(output, _repeated_cids_codec); + convs_.WriteTo(output, _repeated_convs_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasCid) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Cid); + } + size += cids_.CalculateSize(_repeated_cids_codec); + size += convs_.CalculateSize(_repeated_convs_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(ReadCommand other) { + if (other == null) { + return; + } + if (other.HasCid) { + Cid = other.Cid; + } + cids_.Add(other.cids_); + convs_.Add(other.convs_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + Cid = input.ReadString(); + break; + } + case 18: { + cids_.AddEntriesFrom(input, _repeated_cids_codec); + break; + } + case 26: { + convs_.AddEntriesFrom(input, _repeated_convs_codec); + break; + } + } + } + } + + } + + public sealed partial class PresenceCommand : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new PresenceCommand()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::LeanCloud.Realtime.Internal.Protocol.Messages2ProtoReflection.Descriptor.MessageTypes[22]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public PresenceCommand() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public PresenceCommand(PresenceCommand other) : this() { + _hasBits0 = other._hasBits0; + status_ = other.status_; + sessionPeerIds_ = other.sessionPeerIds_.Clone(); + cid_ = other.cid_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public PresenceCommand Clone() { + return new PresenceCommand(this); + } + + /// Field number for the "status" field. + public const int StatusFieldNumber = 1; + private readonly static global::LeanCloud.Realtime.Internal.Protocol.StatusType StatusDefaultValue = global::LeanCloud.Realtime.Internal.Protocol.StatusType.On; + + private global::LeanCloud.Realtime.Internal.Protocol.StatusType status_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::LeanCloud.Realtime.Internal.Protocol.StatusType Status { + get { if ((_hasBits0 & 1) != 0) { return status_; } else { return StatusDefaultValue; } } + set { + _hasBits0 |= 1; + status_ = value; + } + } + /// Gets whether the "status" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasStatus { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "status" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearStatus() { + _hasBits0 &= ~1; + } + + /// Field number for the "sessionPeerIds" field. + public const int SessionPeerIdsFieldNumber = 2; + private static readonly pb::FieldCodec _repeated_sessionPeerIds_codec + = pb::FieldCodec.ForString(18); + private readonly pbc::RepeatedField sessionPeerIds_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField SessionPeerIds { + get { return sessionPeerIds_; } + } + + /// Field number for the "cid" field. + public const int CidFieldNumber = 3; + private readonly static string CidDefaultValue = ""; + + private string cid_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Cid { + get { return cid_ ?? CidDefaultValue; } + set { + cid_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "cid" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasCid { + get { return cid_ != null; } + } + /// Clears the value of the "cid" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearCid() { + cid_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as PresenceCommand); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(PresenceCommand other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Status != other.Status) return false; + if(!sessionPeerIds_.Equals(other.sessionPeerIds_)) return false; + if (Cid != other.Cid) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasStatus) hash ^= Status.GetHashCode(); + hash ^= sessionPeerIds_.GetHashCode(); + if (HasCid) hash ^= Cid.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (HasStatus) { + output.WriteRawTag(8); + output.WriteEnum((int) Status); + } + sessionPeerIds_.WriteTo(output, _repeated_sessionPeerIds_codec); + if (HasCid) { + output.WriteRawTag(26); + output.WriteString(Cid); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasStatus) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Status); + } + size += sessionPeerIds_.CalculateSize(_repeated_sessionPeerIds_codec); + if (HasCid) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Cid); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(PresenceCommand other) { + if (other == null) { + return; + } + if (other.HasStatus) { + Status = other.Status; + } + sessionPeerIds_.Add(other.sessionPeerIds_); + if (other.HasCid) { + Cid = other.Cid; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + Status = (global::LeanCloud.Realtime.Internal.Protocol.StatusType) input.ReadEnum(); + break; + } + case 18: { + sessionPeerIds_.AddEntriesFrom(input, _repeated_sessionPeerIds_codec); + break; + } + case 26: { + Cid = input.ReadString(); + break; + } + } + } + } + + } + + public sealed partial class ReportCommand : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ReportCommand()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::LeanCloud.Realtime.Internal.Protocol.Messages2ProtoReflection.Descriptor.MessageTypes[23]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ReportCommand() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ReportCommand(ReportCommand other) : this() { + _hasBits0 = other._hasBits0; + initiative_ = other.initiative_; + type_ = other.type_; + data_ = other.data_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ReportCommand Clone() { + return new ReportCommand(this); + } + + /// Field number for the "initiative" field. + public const int InitiativeFieldNumber = 1; + private readonly static bool InitiativeDefaultValue = false; + + private bool initiative_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Initiative { + get { if ((_hasBits0 & 1) != 0) { return initiative_; } else { return InitiativeDefaultValue; } } + set { + _hasBits0 |= 1; + initiative_ = value; + } + } + /// Gets whether the "initiative" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasInitiative { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "initiative" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearInitiative() { + _hasBits0 &= ~1; + } + + /// Field number for the "type" field. + public const int TypeFieldNumber = 2; + private readonly static string TypeDefaultValue = ""; + + private string type_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Type { + get { return type_ ?? TypeDefaultValue; } + set { + type_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "type" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasType { + get { return type_ != null; } + } + /// Clears the value of the "type" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearType() { + type_ = null; + } + + /// Field number for the "data" field. + public const int DataFieldNumber = 3; + private readonly static string DataDefaultValue = ""; + + private string data_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Data { + get { return data_ ?? DataDefaultValue; } + set { + data_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "data" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasData { + get { return data_ != null; } + } + /// Clears the value of the "data" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearData() { + data_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as ReportCommand); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(ReportCommand other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Initiative != other.Initiative) return false; + if (Type != other.Type) return false; + if (Data != other.Data) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasInitiative) hash ^= Initiative.GetHashCode(); + if (HasType) hash ^= Type.GetHashCode(); + if (HasData) hash ^= Data.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (HasInitiative) { + output.WriteRawTag(8); + output.WriteBool(Initiative); + } + if (HasType) { + output.WriteRawTag(18); + output.WriteString(Type); + } + if (HasData) { + output.WriteRawTag(26); + output.WriteString(Data); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasInitiative) { + size += 1 + 1; + } + if (HasType) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Type); + } + if (HasData) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Data); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(ReportCommand other) { + if (other == null) { + return; + } + if (other.HasInitiative) { + Initiative = other.Initiative; + } + if (other.HasType) { + Type = other.Type; + } + if (other.HasData) { + Data = other.Data; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + Initiative = input.ReadBool(); + break; + } + case 18: { + Type = input.ReadString(); + break; + } + case 26: { + Data = input.ReadString(); + break; + } + } + } + } + + } + + public sealed partial class PatchItem : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new PatchItem()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::LeanCloud.Realtime.Internal.Protocol.Messages2ProtoReflection.Descriptor.MessageTypes[24]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public PatchItem() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public PatchItem(PatchItem other) : this() { + _hasBits0 = other._hasBits0; + cid_ = other.cid_; + mid_ = other.mid_; + timestamp_ = other.timestamp_; + recall_ = other.recall_; + data_ = other.data_; + patchTimestamp_ = other.patchTimestamp_; + from_ = other.from_; + binaryMsg_ = other.binaryMsg_; + mentionAll_ = other.mentionAll_; + mentionPids_ = other.mentionPids_.Clone(); + patchCode_ = other.patchCode_; + patchReason_ = other.patchReason_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public PatchItem Clone() { + return new PatchItem(this); + } + + /// Field number for the "cid" field. + public const int CidFieldNumber = 1; + private readonly static string CidDefaultValue = ""; + + private string cid_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Cid { + get { return cid_ ?? CidDefaultValue; } + set { + cid_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "cid" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasCid { + get { return cid_ != null; } + } + /// Clears the value of the "cid" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearCid() { + cid_ = null; + } + + /// Field number for the "mid" field. + public const int MidFieldNumber = 2; + private readonly static string MidDefaultValue = ""; + + private string mid_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Mid { + get { return mid_ ?? MidDefaultValue; } + set { + mid_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "mid" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasMid { + get { return mid_ != null; } + } + /// Clears the value of the "mid" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearMid() { + mid_ = null; + } + + /// Field number for the "timestamp" field. + public const int TimestampFieldNumber = 3; + private readonly static long TimestampDefaultValue = 0L; + + private long timestamp_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long Timestamp { + get { if ((_hasBits0 & 1) != 0) { return timestamp_; } else { return TimestampDefaultValue; } } + set { + _hasBits0 |= 1; + timestamp_ = value; + } + } + /// Gets whether the "timestamp" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasTimestamp { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "timestamp" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearTimestamp() { + _hasBits0 &= ~1; + } + + /// Field number for the "recall" field. + public const int RecallFieldNumber = 4; + private readonly static bool RecallDefaultValue = false; + + private bool recall_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Recall { + get { if ((_hasBits0 & 2) != 0) { return recall_; } else { return RecallDefaultValue; } } + set { + _hasBits0 |= 2; + recall_ = value; + } + } + /// Gets whether the "recall" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasRecall { + get { return (_hasBits0 & 2) != 0; } + } + /// Clears the value of the "recall" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearRecall() { + _hasBits0 &= ~2; + } + + /// Field number for the "data" field. + public const int DataFieldNumber = 5; + private readonly static string DataDefaultValue = ""; + + private string data_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Data { + get { return data_ ?? DataDefaultValue; } + set { + data_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "data" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasData { + get { return data_ != null; } + } + /// Clears the value of the "data" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearData() { + data_ = null; + } + + /// Field number for the "patchTimestamp" field. + public const int PatchTimestampFieldNumber = 6; + private readonly static long PatchTimestampDefaultValue = 0L; + + private long patchTimestamp_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long PatchTimestamp { + get { if ((_hasBits0 & 4) != 0) { return patchTimestamp_; } else { return PatchTimestampDefaultValue; } } + set { + _hasBits0 |= 4; + patchTimestamp_ = value; + } + } + /// Gets whether the "patchTimestamp" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasPatchTimestamp { + get { return (_hasBits0 & 4) != 0; } + } + /// Clears the value of the "patchTimestamp" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearPatchTimestamp() { + _hasBits0 &= ~4; + } + + /// Field number for the "from" field. + public const int FromFieldNumber = 7; + private readonly static string FromDefaultValue = ""; + + private string from_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string From { + get { return from_ ?? FromDefaultValue; } + set { + from_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "from" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasFrom { + get { return from_ != null; } + } + /// Clears the value of the "from" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearFrom() { + from_ = null; + } + + /// Field number for the "binaryMsg" field. + public const int BinaryMsgFieldNumber = 8; + private readonly static pb::ByteString BinaryMsgDefaultValue = pb::ByteString.Empty; + + private pb::ByteString binaryMsg_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pb::ByteString BinaryMsg { + get { return binaryMsg_ ?? BinaryMsgDefaultValue; } + set { + binaryMsg_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "binaryMsg" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasBinaryMsg { + get { return binaryMsg_ != null; } + } + /// Clears the value of the "binaryMsg" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearBinaryMsg() { + binaryMsg_ = null; + } + + /// Field number for the "mentionAll" field. + public const int MentionAllFieldNumber = 9; + private readonly static bool MentionAllDefaultValue = false; + + private bool mentionAll_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool MentionAll { + get { if ((_hasBits0 & 8) != 0) { return mentionAll_; } else { return MentionAllDefaultValue; } } + set { + _hasBits0 |= 8; + mentionAll_ = value; + } + } + /// Gets whether the "mentionAll" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasMentionAll { + get { return (_hasBits0 & 8) != 0; } + } + /// Clears the value of the "mentionAll" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearMentionAll() { + _hasBits0 &= ~8; + } + + /// Field number for the "mentionPids" field. + public const int MentionPidsFieldNumber = 10; + private static readonly pb::FieldCodec _repeated_mentionPids_codec + = pb::FieldCodec.ForString(82); + private readonly pbc::RepeatedField mentionPids_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField MentionPids { + get { return mentionPids_; } + } + + /// Field number for the "patchCode" field. + public const int PatchCodeFieldNumber = 11; + private readonly static long PatchCodeDefaultValue = 0L; + + private long patchCode_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long PatchCode { + get { if ((_hasBits0 & 16) != 0) { return patchCode_; } else { return PatchCodeDefaultValue; } } + set { + _hasBits0 |= 16; + patchCode_ = value; + } + } + /// Gets whether the "patchCode" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasPatchCode { + get { return (_hasBits0 & 16) != 0; } + } + /// Clears the value of the "patchCode" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearPatchCode() { + _hasBits0 &= ~16; + } + + /// Field number for the "patchReason" field. + public const int PatchReasonFieldNumber = 12; + private readonly static string PatchReasonDefaultValue = ""; + + private string patchReason_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string PatchReason { + get { return patchReason_ ?? PatchReasonDefaultValue; } + set { + patchReason_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "patchReason" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasPatchReason { + get { return patchReason_ != null; } + } + /// Clears the value of the "patchReason" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearPatchReason() { + patchReason_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as PatchItem); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(PatchItem other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Cid != other.Cid) return false; + if (Mid != other.Mid) return false; + if (Timestamp != other.Timestamp) return false; + if (Recall != other.Recall) return false; + if (Data != other.Data) return false; + if (PatchTimestamp != other.PatchTimestamp) return false; + if (From != other.From) return false; + if (BinaryMsg != other.BinaryMsg) return false; + if (MentionAll != other.MentionAll) return false; + if(!mentionPids_.Equals(other.mentionPids_)) return false; + if (PatchCode != other.PatchCode) return false; + if (PatchReason != other.PatchReason) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasCid) hash ^= Cid.GetHashCode(); + if (HasMid) hash ^= Mid.GetHashCode(); + if (HasTimestamp) hash ^= Timestamp.GetHashCode(); + if (HasRecall) hash ^= Recall.GetHashCode(); + if (HasData) hash ^= Data.GetHashCode(); + if (HasPatchTimestamp) hash ^= PatchTimestamp.GetHashCode(); + if (HasFrom) hash ^= From.GetHashCode(); + if (HasBinaryMsg) hash ^= BinaryMsg.GetHashCode(); + if (HasMentionAll) hash ^= MentionAll.GetHashCode(); + hash ^= mentionPids_.GetHashCode(); + if (HasPatchCode) hash ^= PatchCode.GetHashCode(); + if (HasPatchReason) hash ^= PatchReason.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (HasCid) { + output.WriteRawTag(10); + output.WriteString(Cid); + } + if (HasMid) { + output.WriteRawTag(18); + output.WriteString(Mid); + } + if (HasTimestamp) { + output.WriteRawTag(24); + output.WriteInt64(Timestamp); + } + if (HasRecall) { + output.WriteRawTag(32); + output.WriteBool(Recall); + } + if (HasData) { + output.WriteRawTag(42); + output.WriteString(Data); + } + if (HasPatchTimestamp) { + output.WriteRawTag(48); + output.WriteInt64(PatchTimestamp); + } + if (HasFrom) { + output.WriteRawTag(58); + output.WriteString(From); + } + if (HasBinaryMsg) { + output.WriteRawTag(66); + output.WriteBytes(BinaryMsg); + } + if (HasMentionAll) { + output.WriteRawTag(72); + output.WriteBool(MentionAll); + } + mentionPids_.WriteTo(output, _repeated_mentionPids_codec); + if (HasPatchCode) { + output.WriteRawTag(88); + output.WriteInt64(PatchCode); + } + if (HasPatchReason) { + output.WriteRawTag(98); + output.WriteString(PatchReason); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasCid) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Cid); + } + if (HasMid) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Mid); + } + if (HasTimestamp) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(Timestamp); + } + if (HasRecall) { + size += 1 + 1; + } + if (HasData) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Data); + } + if (HasPatchTimestamp) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(PatchTimestamp); + } + if (HasFrom) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(From); + } + if (HasBinaryMsg) { + size += 1 + pb::CodedOutputStream.ComputeBytesSize(BinaryMsg); + } + if (HasMentionAll) { + size += 1 + 1; + } + size += mentionPids_.CalculateSize(_repeated_mentionPids_codec); + if (HasPatchCode) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(PatchCode); + } + if (HasPatchReason) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(PatchReason); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(PatchItem other) { + if (other == null) { + return; + } + if (other.HasCid) { + Cid = other.Cid; + } + if (other.HasMid) { + Mid = other.Mid; + } + if (other.HasTimestamp) { + Timestamp = other.Timestamp; + } + if (other.HasRecall) { + Recall = other.Recall; + } + if (other.HasData) { + Data = other.Data; + } + if (other.HasPatchTimestamp) { + PatchTimestamp = other.PatchTimestamp; + } + if (other.HasFrom) { + From = other.From; + } + if (other.HasBinaryMsg) { + BinaryMsg = other.BinaryMsg; + } + if (other.HasMentionAll) { + MentionAll = other.MentionAll; + } + mentionPids_.Add(other.mentionPids_); + if (other.HasPatchCode) { + PatchCode = other.PatchCode; + } + if (other.HasPatchReason) { + PatchReason = other.PatchReason; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + Cid = input.ReadString(); + break; + } + case 18: { + Mid = input.ReadString(); + break; + } + case 24: { + Timestamp = input.ReadInt64(); + break; + } + case 32: { + Recall = input.ReadBool(); + break; + } + case 42: { + Data = input.ReadString(); + break; + } + case 48: { + PatchTimestamp = input.ReadInt64(); + break; + } + case 58: { + From = input.ReadString(); + break; + } + case 66: { + BinaryMsg = input.ReadBytes(); + break; + } + case 72: { + MentionAll = input.ReadBool(); + break; + } + case 82: { + mentionPids_.AddEntriesFrom(input, _repeated_mentionPids_codec); + break; + } + case 88: { + PatchCode = input.ReadInt64(); + break; + } + case 98: { + PatchReason = input.ReadString(); + break; + } + } + } + } + + } + + public sealed partial class PatchCommand : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new PatchCommand()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::LeanCloud.Realtime.Internal.Protocol.Messages2ProtoReflection.Descriptor.MessageTypes[25]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public PatchCommand() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public PatchCommand(PatchCommand other) : this() { + _hasBits0 = other._hasBits0; + patches_ = other.patches_.Clone(); + lastPatchTime_ = other.lastPatchTime_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public PatchCommand Clone() { + return new PatchCommand(this); + } + + /// Field number for the "patches" field. + public const int PatchesFieldNumber = 1; + private static readonly pb::FieldCodec _repeated_patches_codec + = pb::FieldCodec.ForMessage(10, global::LeanCloud.Realtime.Internal.Protocol.PatchItem.Parser); + private readonly pbc::RepeatedField patches_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField Patches { + get { return patches_; } + } + + /// Field number for the "lastPatchTime" field. + public const int LastPatchTimeFieldNumber = 2; + private readonly static long LastPatchTimeDefaultValue = 0L; + + private long lastPatchTime_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long LastPatchTime { + get { if ((_hasBits0 & 1) != 0) { return lastPatchTime_; } else { return LastPatchTimeDefaultValue; } } + set { + _hasBits0 |= 1; + lastPatchTime_ = value; + } + } + /// Gets whether the "lastPatchTime" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasLastPatchTime { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "lastPatchTime" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearLastPatchTime() { + _hasBits0 &= ~1; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as PatchCommand); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(PatchCommand other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if(!patches_.Equals(other.patches_)) return false; + if (LastPatchTime != other.LastPatchTime) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + hash ^= patches_.GetHashCode(); + if (HasLastPatchTime) hash ^= LastPatchTime.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + patches_.WriteTo(output, _repeated_patches_codec); + if (HasLastPatchTime) { + output.WriteRawTag(16); + output.WriteInt64(LastPatchTime); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + size += patches_.CalculateSize(_repeated_patches_codec); + if (HasLastPatchTime) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(LastPatchTime); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(PatchCommand other) { + if (other == null) { + return; + } + patches_.Add(other.patches_); + if (other.HasLastPatchTime) { + LastPatchTime = other.LastPatchTime; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + patches_.AddEntriesFrom(input, _repeated_patches_codec); + break; + } + case 16: { + LastPatchTime = input.ReadInt64(); + break; + } + } + } + } + + } + + public sealed partial class PubsubCommand : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new PubsubCommand()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::LeanCloud.Realtime.Internal.Protocol.Messages2ProtoReflection.Descriptor.MessageTypes[26]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public PubsubCommand() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public PubsubCommand(PubsubCommand other) : this() { + cid_ = other.cid_; + cids_ = other.cids_.Clone(); + topic_ = other.topic_; + subtopic_ = other.subtopic_; + topics_ = other.topics_.Clone(); + subtopics_ = other.subtopics_.Clone(); + results_ = other.HasResults ? other.results_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public PubsubCommand Clone() { + return new PubsubCommand(this); + } + + /// Field number for the "cid" field. + public const int CidFieldNumber = 1; + private readonly static string CidDefaultValue = ""; + + private string cid_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Cid { + get { return cid_ ?? CidDefaultValue; } + set { + cid_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "cid" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasCid { + get { return cid_ != null; } + } + /// Clears the value of the "cid" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearCid() { + cid_ = null; + } + + /// Field number for the "cids" field. + public const int CidsFieldNumber = 2; + private static readonly pb::FieldCodec _repeated_cids_codec + = pb::FieldCodec.ForString(18); + private readonly pbc::RepeatedField cids_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField Cids { + get { return cids_; } + } + + /// Field number for the "topic" field. + public const int TopicFieldNumber = 3; + private readonly static string TopicDefaultValue = ""; + + private string topic_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Topic { + get { return topic_ ?? TopicDefaultValue; } + set { + topic_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "topic" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasTopic { + get { return topic_ != null; } + } + /// Clears the value of the "topic" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearTopic() { + topic_ = null; + } + + /// Field number for the "subtopic" field. + public const int SubtopicFieldNumber = 4; + private readonly static string SubtopicDefaultValue = ""; + + private string subtopic_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Subtopic { + get { return subtopic_ ?? SubtopicDefaultValue; } + set { + subtopic_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "subtopic" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasSubtopic { + get { return subtopic_ != null; } + } + /// Clears the value of the "subtopic" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearSubtopic() { + subtopic_ = null; + } + + /// Field number for the "topics" field. + public const int TopicsFieldNumber = 5; + private static readonly pb::FieldCodec _repeated_topics_codec + = pb::FieldCodec.ForString(42); + private readonly pbc::RepeatedField topics_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField Topics { + get { return topics_; } + } + + /// Field number for the "subtopics" field. + public const int SubtopicsFieldNumber = 6; + private static readonly pb::FieldCodec _repeated_subtopics_codec + = pb::FieldCodec.ForString(50); + private readonly pbc::RepeatedField subtopics_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField Subtopics { + get { return subtopics_; } + } + + /// Field number for the "results" field. + public const int ResultsFieldNumber = 7; + private global::LeanCloud.Realtime.Internal.Protocol.JsonObjectMessage results_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::LeanCloud.Realtime.Internal.Protocol.JsonObjectMessage Results { + get { return results_; } + set { + results_ = value; + } + } + /// Gets whether the results field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasResults { + get { return results_ != null; } + } + /// Clears the value of the results field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearResults() { + results_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as PubsubCommand); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(PubsubCommand other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Cid != other.Cid) return false; + if(!cids_.Equals(other.cids_)) return false; + if (Topic != other.Topic) return false; + if (Subtopic != other.Subtopic) return false; + if(!topics_.Equals(other.topics_)) return false; + if(!subtopics_.Equals(other.subtopics_)) return false; + if (!object.Equals(Results, other.Results)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasCid) hash ^= Cid.GetHashCode(); + hash ^= cids_.GetHashCode(); + if (HasTopic) hash ^= Topic.GetHashCode(); + if (HasSubtopic) hash ^= Subtopic.GetHashCode(); + hash ^= topics_.GetHashCode(); + hash ^= subtopics_.GetHashCode(); + if (HasResults) hash ^= Results.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (HasCid) { + output.WriteRawTag(10); + output.WriteString(Cid); + } + cids_.WriteTo(output, _repeated_cids_codec); + if (HasTopic) { + output.WriteRawTag(26); + output.WriteString(Topic); + } + if (HasSubtopic) { + output.WriteRawTag(34); + output.WriteString(Subtopic); + } + topics_.WriteTo(output, _repeated_topics_codec); + subtopics_.WriteTo(output, _repeated_subtopics_codec); + if (HasResults) { + output.WriteRawTag(58); + output.WriteMessage(Results); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasCid) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Cid); + } + size += cids_.CalculateSize(_repeated_cids_codec); + if (HasTopic) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Topic); + } + if (HasSubtopic) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Subtopic); + } + size += topics_.CalculateSize(_repeated_topics_codec); + size += subtopics_.CalculateSize(_repeated_subtopics_codec); + if (HasResults) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Results); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(PubsubCommand other) { + if (other == null) { + return; + } + if (other.HasCid) { + Cid = other.Cid; + } + cids_.Add(other.cids_); + if (other.HasTopic) { + Topic = other.Topic; + } + if (other.HasSubtopic) { + Subtopic = other.Subtopic; + } + topics_.Add(other.topics_); + subtopics_.Add(other.subtopics_); + if (other.HasResults) { + if (!HasResults) { + Results = new global::LeanCloud.Realtime.Internal.Protocol.JsonObjectMessage(); + } + Results.MergeFrom(other.Results); + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + Cid = input.ReadString(); + break; + } + case 18: { + cids_.AddEntriesFrom(input, _repeated_cids_codec); + break; + } + case 26: { + Topic = input.ReadString(); + break; + } + case 34: { + Subtopic = input.ReadString(); + break; + } + case 42: { + topics_.AddEntriesFrom(input, _repeated_topics_codec); + break; + } + case 50: { + subtopics_.AddEntriesFrom(input, _repeated_subtopics_codec); + break; + } + case 58: { + if (!HasResults) { + Results = new global::LeanCloud.Realtime.Internal.Protocol.JsonObjectMessage(); + } + input.ReadMessage(Results); + break; + } + } + } + } + + } + + public sealed partial class BlacklistCommand : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new BlacklistCommand()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::LeanCloud.Realtime.Internal.Protocol.Messages2ProtoReflection.Descriptor.MessageTypes[27]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public BlacklistCommand() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public BlacklistCommand(BlacklistCommand other) : this() { + _hasBits0 = other._hasBits0; + srcCid_ = other.srcCid_; + toPids_ = other.toPids_.Clone(); + srcPid_ = other.srcPid_; + toCids_ = other.toCids_.Clone(); + limit_ = other.limit_; + next_ = other.next_; + blockedPids_ = other.blockedPids_.Clone(); + blockedCids_ = other.blockedCids_.Clone(); + allowedPids_ = other.allowedPids_.Clone(); + failedPids_ = other.failedPids_.Clone(); + t_ = other.t_; + n_ = other.n_; + s_ = other.s_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public BlacklistCommand Clone() { + return new BlacklistCommand(this); + } + + /// Field number for the "srcCid" field. + public const int SrcCidFieldNumber = 1; + private readonly static string SrcCidDefaultValue = ""; + + private string srcCid_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string SrcCid { + get { return srcCid_ ?? SrcCidDefaultValue; } + set { + srcCid_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "srcCid" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasSrcCid { + get { return srcCid_ != null; } + } + /// Clears the value of the "srcCid" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearSrcCid() { + srcCid_ = null; + } + + /// Field number for the "toPids" field. + public const int ToPidsFieldNumber = 2; + private static readonly pb::FieldCodec _repeated_toPids_codec + = pb::FieldCodec.ForString(18); + private readonly pbc::RepeatedField toPids_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField ToPids { + get { return toPids_; } + } + + /// Field number for the "srcPid" field. + public const int SrcPidFieldNumber = 3; + private readonly static string SrcPidDefaultValue = ""; + + private string srcPid_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string SrcPid { + get { return srcPid_ ?? SrcPidDefaultValue; } + set { + srcPid_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "srcPid" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasSrcPid { + get { return srcPid_ != null; } + } + /// Clears the value of the "srcPid" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearSrcPid() { + srcPid_ = null; + } + + /// Field number for the "toCids" field. + public const int ToCidsFieldNumber = 4; + private static readonly pb::FieldCodec _repeated_toCids_codec + = pb::FieldCodec.ForString(34); + private readonly pbc::RepeatedField toCids_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField ToCids { + get { return toCids_; } + } + + /// Field number for the "limit" field. + public const int LimitFieldNumber = 5; + private readonly static int LimitDefaultValue = 0; + + private int limit_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Limit { + get { if ((_hasBits0 & 1) != 0) { return limit_; } else { return LimitDefaultValue; } } + set { + _hasBits0 |= 1; + limit_ = value; + } + } + /// Gets whether the "limit" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasLimit { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "limit" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearLimit() { + _hasBits0 &= ~1; + } + + /// Field number for the "next" field. + public const int NextFieldNumber = 6; + private readonly static string NextDefaultValue = ""; + + private string next_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Next { + get { return next_ ?? NextDefaultValue; } + set { + next_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "next" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasNext { + get { return next_ != null; } + } + /// Clears the value of the "next" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearNext() { + next_ = null; + } + + /// Field number for the "blockedPids" field. + public const int BlockedPidsFieldNumber = 8; + private static readonly pb::FieldCodec _repeated_blockedPids_codec + = pb::FieldCodec.ForString(66); + private readonly pbc::RepeatedField blockedPids_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField BlockedPids { + get { return blockedPids_; } + } + + /// Field number for the "blockedCids" field. + public const int BlockedCidsFieldNumber = 9; + private static readonly pb::FieldCodec _repeated_blockedCids_codec + = pb::FieldCodec.ForString(74); + private readonly pbc::RepeatedField blockedCids_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField BlockedCids { + get { return blockedCids_; } + } + + /// Field number for the "allowedPids" field. + public const int AllowedPidsFieldNumber = 10; + private static readonly pb::FieldCodec _repeated_allowedPids_codec + = pb::FieldCodec.ForString(82); + private readonly pbc::RepeatedField allowedPids_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField AllowedPids { + get { return allowedPids_; } + } + + /// Field number for the "failedPids" field. + public const int FailedPidsFieldNumber = 11; + private static readonly pb::FieldCodec _repeated_failedPids_codec + = pb::FieldCodec.ForMessage(90, global::LeanCloud.Realtime.Internal.Protocol.ErrorCommand.Parser); + private readonly pbc::RepeatedField failedPids_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField FailedPids { + get { return failedPids_; } + } + + /// Field number for the "t" field. + public const int TFieldNumber = 12; + private readonly static long TDefaultValue = 0L; + + private long t_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long T { + get { if ((_hasBits0 & 2) != 0) { return t_; } else { return TDefaultValue; } } + set { + _hasBits0 |= 2; + t_ = value; + } + } + /// Gets whether the "t" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasT { + get { return (_hasBits0 & 2) != 0; } + } + /// Clears the value of the "t" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearT() { + _hasBits0 &= ~2; + } + + /// Field number for the "n" field. + public const int NFieldNumber = 13; + private readonly static string NDefaultValue = ""; + + private string n_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string N { + get { return n_ ?? NDefaultValue; } + set { + n_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "n" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasN { + get { return n_ != null; } + } + /// Clears the value of the "n" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearN() { + n_ = null; + } + + /// Field number for the "s" field. + public const int SFieldNumber = 14; + private readonly static string SDefaultValue = ""; + + private string s_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string S { + get { return s_ ?? SDefaultValue; } + set { + s_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "s" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasS { + get { return s_ != null; } + } + /// Clears the value of the "s" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearS() { + s_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as BlacklistCommand); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(BlacklistCommand other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (SrcCid != other.SrcCid) return false; + if(!toPids_.Equals(other.toPids_)) return false; + if (SrcPid != other.SrcPid) return false; + if(!toCids_.Equals(other.toCids_)) return false; + if (Limit != other.Limit) return false; + if (Next != other.Next) return false; + if(!blockedPids_.Equals(other.blockedPids_)) return false; + if(!blockedCids_.Equals(other.blockedCids_)) return false; + if(!allowedPids_.Equals(other.allowedPids_)) return false; + if(!failedPids_.Equals(other.failedPids_)) return false; + if (T != other.T) return false; + if (N != other.N) return false; + if (S != other.S) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasSrcCid) hash ^= SrcCid.GetHashCode(); + hash ^= toPids_.GetHashCode(); + if (HasSrcPid) hash ^= SrcPid.GetHashCode(); + hash ^= toCids_.GetHashCode(); + if (HasLimit) hash ^= Limit.GetHashCode(); + if (HasNext) hash ^= Next.GetHashCode(); + hash ^= blockedPids_.GetHashCode(); + hash ^= blockedCids_.GetHashCode(); + hash ^= allowedPids_.GetHashCode(); + hash ^= failedPids_.GetHashCode(); + if (HasT) hash ^= T.GetHashCode(); + if (HasN) hash ^= N.GetHashCode(); + if (HasS) hash ^= S.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (HasSrcCid) { + output.WriteRawTag(10); + output.WriteString(SrcCid); + } + toPids_.WriteTo(output, _repeated_toPids_codec); + if (HasSrcPid) { + output.WriteRawTag(26); + output.WriteString(SrcPid); + } + toCids_.WriteTo(output, _repeated_toCids_codec); + if (HasLimit) { + output.WriteRawTag(40); + output.WriteInt32(Limit); + } + if (HasNext) { + output.WriteRawTag(50); + output.WriteString(Next); + } + blockedPids_.WriteTo(output, _repeated_blockedPids_codec); + blockedCids_.WriteTo(output, _repeated_blockedCids_codec); + allowedPids_.WriteTo(output, _repeated_allowedPids_codec); + failedPids_.WriteTo(output, _repeated_failedPids_codec); + if (HasT) { + output.WriteRawTag(96); + output.WriteInt64(T); + } + if (HasN) { + output.WriteRawTag(106); + output.WriteString(N); + } + if (HasS) { + output.WriteRawTag(114); + output.WriteString(S); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasSrcCid) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(SrcCid); + } + size += toPids_.CalculateSize(_repeated_toPids_codec); + if (HasSrcPid) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(SrcPid); + } + size += toCids_.CalculateSize(_repeated_toCids_codec); + if (HasLimit) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Limit); + } + if (HasNext) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Next); + } + size += blockedPids_.CalculateSize(_repeated_blockedPids_codec); + size += blockedCids_.CalculateSize(_repeated_blockedCids_codec); + size += allowedPids_.CalculateSize(_repeated_allowedPids_codec); + size += failedPids_.CalculateSize(_repeated_failedPids_codec); + if (HasT) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(T); + } + if (HasN) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(N); + } + if (HasS) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(S); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(BlacklistCommand other) { + if (other == null) { + return; + } + if (other.HasSrcCid) { + SrcCid = other.SrcCid; + } + toPids_.Add(other.toPids_); + if (other.HasSrcPid) { + SrcPid = other.SrcPid; + } + toCids_.Add(other.toCids_); + if (other.HasLimit) { + Limit = other.Limit; + } + if (other.HasNext) { + Next = other.Next; + } + blockedPids_.Add(other.blockedPids_); + blockedCids_.Add(other.blockedCids_); + allowedPids_.Add(other.allowedPids_); + failedPids_.Add(other.failedPids_); + if (other.HasT) { + T = other.T; + } + if (other.HasN) { + N = other.N; + } + if (other.HasS) { + S = other.S; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + SrcCid = input.ReadString(); + break; + } + case 18: { + toPids_.AddEntriesFrom(input, _repeated_toPids_codec); + break; + } + case 26: { + SrcPid = input.ReadString(); + break; + } + case 34: { + toCids_.AddEntriesFrom(input, _repeated_toCids_codec); + break; + } + case 40: { + Limit = input.ReadInt32(); + break; + } + case 50: { + Next = input.ReadString(); + break; + } + case 66: { + blockedPids_.AddEntriesFrom(input, _repeated_blockedPids_codec); + break; + } + case 74: { + blockedCids_.AddEntriesFrom(input, _repeated_blockedCids_codec); + break; + } + case 82: { + allowedPids_.AddEntriesFrom(input, _repeated_allowedPids_codec); + break; + } + case 90: { + failedPids_.AddEntriesFrom(input, _repeated_failedPids_codec); + break; + } + case 96: { + T = input.ReadInt64(); + break; + } + case 106: { + N = input.ReadString(); + break; + } + case 114: { + S = input.ReadString(); + break; + } + } + } + } + + } + + public sealed partial class GenericCommand : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new GenericCommand()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::LeanCloud.Realtime.Internal.Protocol.Messages2ProtoReflection.Descriptor.MessageTypes[28]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public GenericCommand() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public GenericCommand(GenericCommand other) : this() { + _hasBits0 = other._hasBits0; + cmd_ = other.cmd_; + op_ = other.op_; + appId_ = other.appId_; + peerId_ = other.peerId_; + i_ = other.i_; + installationId_ = other.installationId_; + priority_ = other.priority_; + service_ = other.service_; + serverTs_ = other.serverTs_; + clientTs_ = other.clientTs_; + notificationType_ = other.notificationType_; + loginMessage_ = other.HasLoginMessage ? other.loginMessage_.Clone() : null; + dataMessage_ = other.HasDataMessage ? other.dataMessage_.Clone() : null; + sessionMessage_ = other.HasSessionMessage ? other.sessionMessage_.Clone() : null; + errorMessage_ = other.HasErrorMessage ? other.errorMessage_.Clone() : null; + directMessage_ = other.HasDirectMessage ? other.directMessage_.Clone() : null; + ackMessage_ = other.HasAckMessage ? other.ackMessage_.Clone() : null; + unreadMessage_ = other.HasUnreadMessage ? other.unreadMessage_.Clone() : null; + readMessage_ = other.HasReadMessage ? other.readMessage_.Clone() : null; + rcpMessage_ = other.HasRcpMessage ? other.rcpMessage_.Clone() : null; + logsMessage_ = other.HasLogsMessage ? other.logsMessage_.Clone() : null; + convMessage_ = other.HasConvMessage ? other.convMessage_.Clone() : null; + roomMessage_ = other.HasRoomMessage ? other.roomMessage_.Clone() : null; + presenceMessage_ = other.HasPresenceMessage ? other.presenceMessage_.Clone() : null; + reportMessage_ = other.HasReportMessage ? other.reportMessage_.Clone() : null; + patchMessage_ = other.HasPatchMessage ? other.patchMessage_.Clone() : null; + pubsubMessage_ = other.HasPubsubMessage ? other.pubsubMessage_.Clone() : null; + blacklistMessage_ = other.HasBlacklistMessage ? other.blacklistMessage_.Clone() : null; + loggedinMessage_ = other.HasLoggedinMessage ? other.loggedinMessage_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public GenericCommand Clone() { + return new GenericCommand(this); + } + + /// Field number for the "cmd" field. + public const int CmdFieldNumber = 1; + private readonly static global::LeanCloud.Realtime.Internal.Protocol.CommandType CmdDefaultValue = global::LeanCloud.Realtime.Internal.Protocol.CommandType.Session; + + private global::LeanCloud.Realtime.Internal.Protocol.CommandType cmd_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::LeanCloud.Realtime.Internal.Protocol.CommandType Cmd { + get { if ((_hasBits0 & 1) != 0) { return cmd_; } else { return CmdDefaultValue; } } + set { + _hasBits0 |= 1; + cmd_ = value; + } + } + /// Gets whether the "cmd" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasCmd { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "cmd" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearCmd() { + _hasBits0 &= ~1; + } + + /// Field number for the "op" field. + public const int OpFieldNumber = 2; + private readonly static global::LeanCloud.Realtime.Internal.Protocol.OpType OpDefaultValue = global::LeanCloud.Realtime.Internal.Protocol.OpType.Open; + + private global::LeanCloud.Realtime.Internal.Protocol.OpType op_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::LeanCloud.Realtime.Internal.Protocol.OpType Op { + get { if ((_hasBits0 & 2) != 0) { return op_; } else { return OpDefaultValue; } } + set { + _hasBits0 |= 2; + op_ = value; + } + } + /// Gets whether the "op" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOp { + get { return (_hasBits0 & 2) != 0; } + } + /// Clears the value of the "op" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOp() { + _hasBits0 &= ~2; + } + + /// Field number for the "appId" field. + public const int AppIdFieldNumber = 3; + private readonly static string AppIdDefaultValue = ""; + + private string appId_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string AppId { + get { return appId_ ?? AppIdDefaultValue; } + set { + appId_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "appId" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasAppId { + get { return appId_ != null; } + } + /// Clears the value of the "appId" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearAppId() { + appId_ = null; + } + + /// Field number for the "peerId" field. + public const int PeerIdFieldNumber = 4; + private readonly static string PeerIdDefaultValue = ""; + + private string peerId_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string PeerId { + get { return peerId_ ?? PeerIdDefaultValue; } + set { + peerId_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "peerId" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasPeerId { + get { return peerId_ != null; } + } + /// Clears the value of the "peerId" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearPeerId() { + peerId_ = null; + } + + /// Field number for the "i" field. + public const int IFieldNumber = 5; + private readonly static int IDefaultValue = 0; + + private int i_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int I { + get { if ((_hasBits0 & 4) != 0) { return i_; } else { return IDefaultValue; } } + set { + _hasBits0 |= 4; + i_ = value; + } + } + /// Gets whether the "i" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasI { + get { return (_hasBits0 & 4) != 0; } + } + /// Clears the value of the "i" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearI() { + _hasBits0 &= ~4; + } + + /// Field number for the "installationId" field. + public const int InstallationIdFieldNumber = 6; + private readonly static string InstallationIdDefaultValue = ""; + + private string installationId_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string InstallationId { + get { return installationId_ ?? InstallationIdDefaultValue; } + set { + installationId_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "installationId" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasInstallationId { + get { return installationId_ != null; } + } + /// Clears the value of the "installationId" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearInstallationId() { + installationId_ = null; + } + + /// Field number for the "priority" field. + public const int PriorityFieldNumber = 7; + private readonly static int PriorityDefaultValue = 0; + + private int priority_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Priority { + get { if ((_hasBits0 & 8) != 0) { return priority_; } else { return PriorityDefaultValue; } } + set { + _hasBits0 |= 8; + priority_ = value; + } + } + /// Gets whether the "priority" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasPriority { + get { return (_hasBits0 & 8) != 0; } + } + /// Clears the value of the "priority" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearPriority() { + _hasBits0 &= ~8; + } + + /// Field number for the "service" field. + public const int ServiceFieldNumber = 8; + private readonly static int ServiceDefaultValue = 0; + + private int service_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Service { + get { if ((_hasBits0 & 16) != 0) { return service_; } else { return ServiceDefaultValue; } } + set { + _hasBits0 |= 16; + service_ = value; + } + } + /// Gets whether the "service" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasService { + get { return (_hasBits0 & 16) != 0; } + } + /// Clears the value of the "service" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearService() { + _hasBits0 &= ~16; + } + + /// Field number for the "serverTs" field. + public const int ServerTsFieldNumber = 9; + private readonly static long ServerTsDefaultValue = 0L; + + private long serverTs_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long ServerTs { + get { if ((_hasBits0 & 32) != 0) { return serverTs_; } else { return ServerTsDefaultValue; } } + set { + _hasBits0 |= 32; + serverTs_ = value; + } + } + /// Gets whether the "serverTs" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasServerTs { + get { return (_hasBits0 & 32) != 0; } + } + /// Clears the value of the "serverTs" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearServerTs() { + _hasBits0 &= ~32; + } + + /// Field number for the "clientTs" field. + public const int ClientTsFieldNumber = 10; + private readonly static long ClientTsDefaultValue = 0L; + + private long clientTs_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long ClientTs { + get { if ((_hasBits0 & 64) != 0) { return clientTs_; } else { return ClientTsDefaultValue; } } + set { + _hasBits0 |= 64; + clientTs_ = value; + } + } + /// Gets whether the "clientTs" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasClientTs { + get { return (_hasBits0 & 64) != 0; } + } + /// Clears the value of the "clientTs" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearClientTs() { + _hasBits0 &= ~64; + } + + /// Field number for the "notificationType" field. + public const int NotificationTypeFieldNumber = 11; + private readonly static int NotificationTypeDefaultValue = 0; + + private int notificationType_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int NotificationType { + get { if ((_hasBits0 & 128) != 0) { return notificationType_; } else { return NotificationTypeDefaultValue; } } + set { + _hasBits0 |= 128; + notificationType_ = value; + } + } + /// Gets whether the "notificationType" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasNotificationType { + get { return (_hasBits0 & 128) != 0; } + } + /// Clears the value of the "notificationType" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearNotificationType() { + _hasBits0 &= ~128; + } + + /// Field number for the "loginMessage" field. + public const int LoginMessageFieldNumber = 100; + private global::LeanCloud.Realtime.Internal.Protocol.LoginCommand loginMessage_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::LeanCloud.Realtime.Internal.Protocol.LoginCommand LoginMessage { + get { return loginMessage_; } + set { + loginMessage_ = value; + } + } + /// Gets whether the loginMessage field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasLoginMessage { + get { return loginMessage_ != null; } + } + /// Clears the value of the loginMessage field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearLoginMessage() { + loginMessage_ = null; + } + + /// Field number for the "dataMessage" field. + public const int DataMessageFieldNumber = 101; + private global::LeanCloud.Realtime.Internal.Protocol.DataCommand dataMessage_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::LeanCloud.Realtime.Internal.Protocol.DataCommand DataMessage { + get { return dataMessage_; } + set { + dataMessage_ = value; + } + } + /// Gets whether the dataMessage field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDataMessage { + get { return dataMessage_ != null; } + } + /// Clears the value of the dataMessage field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDataMessage() { + dataMessage_ = null; + } + + /// Field number for the "sessionMessage" field. + public const int SessionMessageFieldNumber = 102; + private global::LeanCloud.Realtime.Internal.Protocol.SessionCommand sessionMessage_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::LeanCloud.Realtime.Internal.Protocol.SessionCommand SessionMessage { + get { return sessionMessage_; } + set { + sessionMessage_ = value; + } + } + /// Gets whether the sessionMessage field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasSessionMessage { + get { return sessionMessage_ != null; } + } + /// Clears the value of the sessionMessage field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearSessionMessage() { + sessionMessage_ = null; + } + + /// Field number for the "errorMessage" field. + public const int ErrorMessageFieldNumber = 103; + private global::LeanCloud.Realtime.Internal.Protocol.ErrorCommand errorMessage_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::LeanCloud.Realtime.Internal.Protocol.ErrorCommand ErrorMessage { + get { return errorMessage_; } + set { + errorMessage_ = value; + } + } + /// Gets whether the errorMessage field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasErrorMessage { + get { return errorMessage_ != null; } + } + /// Clears the value of the errorMessage field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearErrorMessage() { + errorMessage_ = null; + } + + /// Field number for the "directMessage" field. + public const int DirectMessageFieldNumber = 104; + private global::LeanCloud.Realtime.Internal.Protocol.DirectCommand directMessage_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::LeanCloud.Realtime.Internal.Protocol.DirectCommand DirectMessage { + get { return directMessage_; } + set { + directMessage_ = value; + } + } + /// Gets whether the directMessage field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDirectMessage { + get { return directMessage_ != null; } + } + /// Clears the value of the directMessage field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDirectMessage() { + directMessage_ = null; + } + + /// Field number for the "ackMessage" field. + public const int AckMessageFieldNumber = 105; + private global::LeanCloud.Realtime.Internal.Protocol.AckCommand ackMessage_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::LeanCloud.Realtime.Internal.Protocol.AckCommand AckMessage { + get { return ackMessage_; } + set { + ackMessage_ = value; + } + } + /// Gets whether the ackMessage field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasAckMessage { + get { return ackMessage_ != null; } + } + /// Clears the value of the ackMessage field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearAckMessage() { + ackMessage_ = null; + } + + /// Field number for the "unreadMessage" field. + public const int UnreadMessageFieldNumber = 106; + private global::LeanCloud.Realtime.Internal.Protocol.UnreadCommand unreadMessage_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::LeanCloud.Realtime.Internal.Protocol.UnreadCommand UnreadMessage { + get { return unreadMessage_; } + set { + unreadMessage_ = value; + } + } + /// Gets whether the unreadMessage field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasUnreadMessage { + get { return unreadMessage_ != null; } + } + /// Clears the value of the unreadMessage field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearUnreadMessage() { + unreadMessage_ = null; + } + + /// Field number for the "readMessage" field. + public const int ReadMessageFieldNumber = 107; + private global::LeanCloud.Realtime.Internal.Protocol.ReadCommand readMessage_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::LeanCloud.Realtime.Internal.Protocol.ReadCommand ReadMessage { + get { return readMessage_; } + set { + readMessage_ = value; + } + } + /// Gets whether the readMessage field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasReadMessage { + get { return readMessage_ != null; } + } + /// Clears the value of the readMessage field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearReadMessage() { + readMessage_ = null; + } + + /// Field number for the "rcpMessage" field. + public const int RcpMessageFieldNumber = 108; + private global::LeanCloud.Realtime.Internal.Protocol.RcpCommand rcpMessage_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::LeanCloud.Realtime.Internal.Protocol.RcpCommand RcpMessage { + get { return rcpMessage_; } + set { + rcpMessage_ = value; + } + } + /// Gets whether the rcpMessage field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasRcpMessage { + get { return rcpMessage_ != null; } + } + /// Clears the value of the rcpMessage field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearRcpMessage() { + rcpMessage_ = null; + } + + /// Field number for the "logsMessage" field. + public const int LogsMessageFieldNumber = 109; + private global::LeanCloud.Realtime.Internal.Protocol.LogsCommand logsMessage_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::LeanCloud.Realtime.Internal.Protocol.LogsCommand LogsMessage { + get { return logsMessage_; } + set { + logsMessage_ = value; + } + } + /// Gets whether the logsMessage field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasLogsMessage { + get { return logsMessage_ != null; } + } + /// Clears the value of the logsMessage field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearLogsMessage() { + logsMessage_ = null; + } + + /// Field number for the "convMessage" field. + public const int ConvMessageFieldNumber = 110; + private global::LeanCloud.Realtime.Internal.Protocol.ConvCommand convMessage_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::LeanCloud.Realtime.Internal.Protocol.ConvCommand ConvMessage { + get { return convMessage_; } + set { + convMessage_ = value; + } + } + /// Gets whether the convMessage field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasConvMessage { + get { return convMessage_ != null; } + } + /// Clears the value of the convMessage field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearConvMessage() { + convMessage_ = null; + } + + /// Field number for the "roomMessage" field. + public const int RoomMessageFieldNumber = 111; + private global::LeanCloud.Realtime.Internal.Protocol.RoomCommand roomMessage_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::LeanCloud.Realtime.Internal.Protocol.RoomCommand RoomMessage { + get { return roomMessage_; } + set { + roomMessage_ = value; + } + } + /// Gets whether the roomMessage field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasRoomMessage { + get { return roomMessage_ != null; } + } + /// Clears the value of the roomMessage field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearRoomMessage() { + roomMessage_ = null; + } + + /// Field number for the "presenceMessage" field. + public const int PresenceMessageFieldNumber = 112; + private global::LeanCloud.Realtime.Internal.Protocol.PresenceCommand presenceMessage_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::LeanCloud.Realtime.Internal.Protocol.PresenceCommand PresenceMessage { + get { return presenceMessage_; } + set { + presenceMessage_ = value; + } + } + /// Gets whether the presenceMessage field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasPresenceMessage { + get { return presenceMessage_ != null; } + } + /// Clears the value of the presenceMessage field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearPresenceMessage() { + presenceMessage_ = null; + } + + /// Field number for the "reportMessage" field. + public const int ReportMessageFieldNumber = 113; + private global::LeanCloud.Realtime.Internal.Protocol.ReportCommand reportMessage_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::LeanCloud.Realtime.Internal.Protocol.ReportCommand ReportMessage { + get { return reportMessage_; } + set { + reportMessage_ = value; + } + } + /// Gets whether the reportMessage field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasReportMessage { + get { return reportMessage_ != null; } + } + /// Clears the value of the reportMessage field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearReportMessage() { + reportMessage_ = null; + } + + /// Field number for the "patchMessage" field. + public const int PatchMessageFieldNumber = 114; + private global::LeanCloud.Realtime.Internal.Protocol.PatchCommand patchMessage_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::LeanCloud.Realtime.Internal.Protocol.PatchCommand PatchMessage { + get { return patchMessage_; } + set { + patchMessage_ = value; + } + } + /// Gets whether the patchMessage field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasPatchMessage { + get { return patchMessage_ != null; } + } + /// Clears the value of the patchMessage field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearPatchMessage() { + patchMessage_ = null; + } + + /// Field number for the "pubsubMessage" field. + public const int PubsubMessageFieldNumber = 115; + private global::LeanCloud.Realtime.Internal.Protocol.PubsubCommand pubsubMessage_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::LeanCloud.Realtime.Internal.Protocol.PubsubCommand PubsubMessage { + get { return pubsubMessage_; } + set { + pubsubMessage_ = value; + } + } + /// Gets whether the pubsubMessage field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasPubsubMessage { + get { return pubsubMessage_ != null; } + } + /// Clears the value of the pubsubMessage field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearPubsubMessage() { + pubsubMessage_ = null; + } + + /// Field number for the "blacklistMessage" field. + public const int BlacklistMessageFieldNumber = 116; + private global::LeanCloud.Realtime.Internal.Protocol.BlacklistCommand blacklistMessage_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::LeanCloud.Realtime.Internal.Protocol.BlacklistCommand BlacklistMessage { + get { return blacklistMessage_; } + set { + blacklistMessage_ = value; + } + } + /// Gets whether the blacklistMessage field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasBlacklistMessage { + get { return blacklistMessage_ != null; } + } + /// Clears the value of the blacklistMessage field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearBlacklistMessage() { + blacklistMessage_ = null; + } + + /// Field number for the "loggedinMessage" field. + public const int LoggedinMessageFieldNumber = 117; + private global::LeanCloud.Realtime.Internal.Protocol.LoggedinCommand loggedinMessage_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::LeanCloud.Realtime.Internal.Protocol.LoggedinCommand LoggedinMessage { + get { return loggedinMessage_; } + set { + loggedinMessage_ = value; + } + } + /// Gets whether the loggedinMessage field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasLoggedinMessage { + get { return loggedinMessage_ != null; } + } + /// Clears the value of the loggedinMessage field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearLoggedinMessage() { + loggedinMessage_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as GenericCommand); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(GenericCommand other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Cmd != other.Cmd) return false; + if (Op != other.Op) return false; + if (AppId != other.AppId) return false; + if (PeerId != other.PeerId) return false; + if (I != other.I) return false; + if (InstallationId != other.InstallationId) return false; + if (Priority != other.Priority) return false; + if (Service != other.Service) return false; + if (ServerTs != other.ServerTs) return false; + if (ClientTs != other.ClientTs) return false; + if (NotificationType != other.NotificationType) return false; + if (!object.Equals(LoginMessage, other.LoginMessage)) return false; + if (!object.Equals(DataMessage, other.DataMessage)) return false; + if (!object.Equals(SessionMessage, other.SessionMessage)) return false; + if (!object.Equals(ErrorMessage, other.ErrorMessage)) return false; + if (!object.Equals(DirectMessage, other.DirectMessage)) return false; + if (!object.Equals(AckMessage, other.AckMessage)) return false; + if (!object.Equals(UnreadMessage, other.UnreadMessage)) return false; + if (!object.Equals(ReadMessage, other.ReadMessage)) return false; + if (!object.Equals(RcpMessage, other.RcpMessage)) return false; + if (!object.Equals(LogsMessage, other.LogsMessage)) return false; + if (!object.Equals(ConvMessage, other.ConvMessage)) return false; + if (!object.Equals(RoomMessage, other.RoomMessage)) return false; + if (!object.Equals(PresenceMessage, other.PresenceMessage)) return false; + if (!object.Equals(ReportMessage, other.ReportMessage)) return false; + if (!object.Equals(PatchMessage, other.PatchMessage)) return false; + if (!object.Equals(PubsubMessage, other.PubsubMessage)) return false; + if (!object.Equals(BlacklistMessage, other.BlacklistMessage)) return false; + if (!object.Equals(LoggedinMessage, other.LoggedinMessage)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasCmd) hash ^= Cmd.GetHashCode(); + if (HasOp) hash ^= Op.GetHashCode(); + if (HasAppId) hash ^= AppId.GetHashCode(); + if (HasPeerId) hash ^= PeerId.GetHashCode(); + if (HasI) hash ^= I.GetHashCode(); + if (HasInstallationId) hash ^= InstallationId.GetHashCode(); + if (HasPriority) hash ^= Priority.GetHashCode(); + if (HasService) hash ^= Service.GetHashCode(); + if (HasServerTs) hash ^= ServerTs.GetHashCode(); + if (HasClientTs) hash ^= ClientTs.GetHashCode(); + if (HasNotificationType) hash ^= NotificationType.GetHashCode(); + if (HasLoginMessage) hash ^= LoginMessage.GetHashCode(); + if (HasDataMessage) hash ^= DataMessage.GetHashCode(); + if (HasSessionMessage) hash ^= SessionMessage.GetHashCode(); + if (HasErrorMessage) hash ^= ErrorMessage.GetHashCode(); + if (HasDirectMessage) hash ^= DirectMessage.GetHashCode(); + if (HasAckMessage) hash ^= AckMessage.GetHashCode(); + if (HasUnreadMessage) hash ^= UnreadMessage.GetHashCode(); + if (HasReadMessage) hash ^= ReadMessage.GetHashCode(); + if (HasRcpMessage) hash ^= RcpMessage.GetHashCode(); + if (HasLogsMessage) hash ^= LogsMessage.GetHashCode(); + if (HasConvMessage) hash ^= ConvMessage.GetHashCode(); + if (HasRoomMessage) hash ^= RoomMessage.GetHashCode(); + if (HasPresenceMessage) hash ^= PresenceMessage.GetHashCode(); + if (HasReportMessage) hash ^= ReportMessage.GetHashCode(); + if (HasPatchMessage) hash ^= PatchMessage.GetHashCode(); + if (HasPubsubMessage) hash ^= PubsubMessage.GetHashCode(); + if (HasBlacklistMessage) hash ^= BlacklistMessage.GetHashCode(); + if (HasLoggedinMessage) hash ^= LoggedinMessage.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (HasCmd) { + output.WriteRawTag(8); + output.WriteEnum((int) Cmd); + } + if (HasOp) { + output.WriteRawTag(16); + output.WriteEnum((int) Op); + } + if (HasAppId) { + output.WriteRawTag(26); + output.WriteString(AppId); + } + if (HasPeerId) { + output.WriteRawTag(34); + output.WriteString(PeerId); + } + if (HasI) { + output.WriteRawTag(40); + output.WriteInt32(I); + } + if (HasInstallationId) { + output.WriteRawTag(50); + output.WriteString(InstallationId); + } + if (HasPriority) { + output.WriteRawTag(56); + output.WriteInt32(Priority); + } + if (HasService) { + output.WriteRawTag(64); + output.WriteInt32(Service); + } + if (HasServerTs) { + output.WriteRawTag(72); + output.WriteInt64(ServerTs); + } + if (HasClientTs) { + output.WriteRawTag(80); + output.WriteInt64(ClientTs); + } + if (HasNotificationType) { + output.WriteRawTag(88); + output.WriteInt32(NotificationType); + } + if (HasLoginMessage) { + output.WriteRawTag(162, 6); + output.WriteMessage(LoginMessage); + } + if (HasDataMessage) { + output.WriteRawTag(170, 6); + output.WriteMessage(DataMessage); + } + if (HasSessionMessage) { + output.WriteRawTag(178, 6); + output.WriteMessage(SessionMessage); + } + if (HasErrorMessage) { + output.WriteRawTag(186, 6); + output.WriteMessage(ErrorMessage); + } + if (HasDirectMessage) { + output.WriteRawTag(194, 6); + output.WriteMessage(DirectMessage); + } + if (HasAckMessage) { + output.WriteRawTag(202, 6); + output.WriteMessage(AckMessage); + } + if (HasUnreadMessage) { + output.WriteRawTag(210, 6); + output.WriteMessage(UnreadMessage); + } + if (HasReadMessage) { + output.WriteRawTag(218, 6); + output.WriteMessage(ReadMessage); + } + if (HasRcpMessage) { + output.WriteRawTag(226, 6); + output.WriteMessage(RcpMessage); + } + if (HasLogsMessage) { + output.WriteRawTag(234, 6); + output.WriteMessage(LogsMessage); + } + if (HasConvMessage) { + output.WriteRawTag(242, 6); + output.WriteMessage(ConvMessage); + } + if (HasRoomMessage) { + output.WriteRawTag(250, 6); + output.WriteMessage(RoomMessage); + } + if (HasPresenceMessage) { + output.WriteRawTag(130, 7); + output.WriteMessage(PresenceMessage); + } + if (HasReportMessage) { + output.WriteRawTag(138, 7); + output.WriteMessage(ReportMessage); + } + if (HasPatchMessage) { + output.WriteRawTag(146, 7); + output.WriteMessage(PatchMessage); + } + if (HasPubsubMessage) { + output.WriteRawTag(154, 7); + output.WriteMessage(PubsubMessage); + } + if (HasBlacklistMessage) { + output.WriteRawTag(162, 7); + output.WriteMessage(BlacklistMessage); + } + if (HasLoggedinMessage) { + output.WriteRawTag(170, 7); + output.WriteMessage(LoggedinMessage); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasCmd) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Cmd); + } + if (HasOp) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Op); + } + if (HasAppId) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(AppId); + } + if (HasPeerId) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(PeerId); + } + if (HasI) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(I); + } + if (HasInstallationId) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(InstallationId); + } + if (HasPriority) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Priority); + } + if (HasService) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Service); + } + if (HasServerTs) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(ServerTs); + } + if (HasClientTs) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(ClientTs); + } + if (HasNotificationType) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(NotificationType); + } + if (HasLoginMessage) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(LoginMessage); + } + if (HasDataMessage) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(DataMessage); + } + if (HasSessionMessage) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(SessionMessage); + } + if (HasErrorMessage) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(ErrorMessage); + } + if (HasDirectMessage) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(DirectMessage); + } + if (HasAckMessage) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(AckMessage); + } + if (HasUnreadMessage) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(UnreadMessage); + } + if (HasReadMessage) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(ReadMessage); + } + if (HasRcpMessage) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(RcpMessage); + } + if (HasLogsMessage) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(LogsMessage); + } + if (HasConvMessage) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(ConvMessage); + } + if (HasRoomMessage) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(RoomMessage); + } + if (HasPresenceMessage) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(PresenceMessage); + } + if (HasReportMessage) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(ReportMessage); + } + if (HasPatchMessage) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(PatchMessage); + } + if (HasPubsubMessage) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(PubsubMessage); + } + if (HasBlacklistMessage) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(BlacklistMessage); + } + if (HasLoggedinMessage) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(LoggedinMessage); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(GenericCommand other) { + if (other == null) { + return; + } + if (other.HasCmd) { + Cmd = other.Cmd; + } + if (other.HasOp) { + Op = other.Op; + } + if (other.HasAppId) { + AppId = other.AppId; + } + if (other.HasPeerId) { + PeerId = other.PeerId; + } + if (other.HasI) { + I = other.I; + } + if (other.HasInstallationId) { + InstallationId = other.InstallationId; + } + if (other.HasPriority) { + Priority = other.Priority; + } + if (other.HasService) { + Service = other.Service; + } + if (other.HasServerTs) { + ServerTs = other.ServerTs; + } + if (other.HasClientTs) { + ClientTs = other.ClientTs; + } + if (other.HasNotificationType) { + NotificationType = other.NotificationType; + } + if (other.HasLoginMessage) { + if (!HasLoginMessage) { + LoginMessage = new global::LeanCloud.Realtime.Internal.Protocol.LoginCommand(); + } + LoginMessage.MergeFrom(other.LoginMessage); + } + if (other.HasDataMessage) { + if (!HasDataMessage) { + DataMessage = new global::LeanCloud.Realtime.Internal.Protocol.DataCommand(); + } + DataMessage.MergeFrom(other.DataMessage); + } + if (other.HasSessionMessage) { + if (!HasSessionMessage) { + SessionMessage = new global::LeanCloud.Realtime.Internal.Protocol.SessionCommand(); + } + SessionMessage.MergeFrom(other.SessionMessage); + } + if (other.HasErrorMessage) { + if (!HasErrorMessage) { + ErrorMessage = new global::LeanCloud.Realtime.Internal.Protocol.ErrorCommand(); + } + ErrorMessage.MergeFrom(other.ErrorMessage); + } + if (other.HasDirectMessage) { + if (!HasDirectMessage) { + DirectMessage = new global::LeanCloud.Realtime.Internal.Protocol.DirectCommand(); + } + DirectMessage.MergeFrom(other.DirectMessage); + } + if (other.HasAckMessage) { + if (!HasAckMessage) { + AckMessage = new global::LeanCloud.Realtime.Internal.Protocol.AckCommand(); + } + AckMessage.MergeFrom(other.AckMessage); + } + if (other.HasUnreadMessage) { + if (!HasUnreadMessage) { + UnreadMessage = new global::LeanCloud.Realtime.Internal.Protocol.UnreadCommand(); + } + UnreadMessage.MergeFrom(other.UnreadMessage); + } + if (other.HasReadMessage) { + if (!HasReadMessage) { + ReadMessage = new global::LeanCloud.Realtime.Internal.Protocol.ReadCommand(); + } + ReadMessage.MergeFrom(other.ReadMessage); + } + if (other.HasRcpMessage) { + if (!HasRcpMessage) { + RcpMessage = new global::LeanCloud.Realtime.Internal.Protocol.RcpCommand(); + } + RcpMessage.MergeFrom(other.RcpMessage); + } + if (other.HasLogsMessage) { + if (!HasLogsMessage) { + LogsMessage = new global::LeanCloud.Realtime.Internal.Protocol.LogsCommand(); + } + LogsMessage.MergeFrom(other.LogsMessage); + } + if (other.HasConvMessage) { + if (!HasConvMessage) { + ConvMessage = new global::LeanCloud.Realtime.Internal.Protocol.ConvCommand(); + } + ConvMessage.MergeFrom(other.ConvMessage); + } + if (other.HasRoomMessage) { + if (!HasRoomMessage) { + RoomMessage = new global::LeanCloud.Realtime.Internal.Protocol.RoomCommand(); + } + RoomMessage.MergeFrom(other.RoomMessage); + } + if (other.HasPresenceMessage) { + if (!HasPresenceMessage) { + PresenceMessage = new global::LeanCloud.Realtime.Internal.Protocol.PresenceCommand(); + } + PresenceMessage.MergeFrom(other.PresenceMessage); + } + if (other.HasReportMessage) { + if (!HasReportMessage) { + ReportMessage = new global::LeanCloud.Realtime.Internal.Protocol.ReportCommand(); + } + ReportMessage.MergeFrom(other.ReportMessage); + } + if (other.HasPatchMessage) { + if (!HasPatchMessage) { + PatchMessage = new global::LeanCloud.Realtime.Internal.Protocol.PatchCommand(); + } + PatchMessage.MergeFrom(other.PatchMessage); + } + if (other.HasPubsubMessage) { + if (!HasPubsubMessage) { + PubsubMessage = new global::LeanCloud.Realtime.Internal.Protocol.PubsubCommand(); + } + PubsubMessage.MergeFrom(other.PubsubMessage); + } + if (other.HasBlacklistMessage) { + if (!HasBlacklistMessage) { + BlacklistMessage = new global::LeanCloud.Realtime.Internal.Protocol.BlacklistCommand(); + } + BlacklistMessage.MergeFrom(other.BlacklistMessage); + } + if (other.HasLoggedinMessage) { + if (!HasLoggedinMessage) { + LoggedinMessage = new global::LeanCloud.Realtime.Internal.Protocol.LoggedinCommand(); + } + LoggedinMessage.MergeFrom(other.LoggedinMessage); + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + Cmd = (global::LeanCloud.Realtime.Internal.Protocol.CommandType) input.ReadEnum(); + break; + } + case 16: { + Op = (global::LeanCloud.Realtime.Internal.Protocol.OpType) input.ReadEnum(); + break; + } + case 26: { + AppId = input.ReadString(); + break; + } + case 34: { + PeerId = input.ReadString(); + break; + } + case 40: { + I = input.ReadInt32(); + break; + } + case 50: { + InstallationId = input.ReadString(); + break; + } + case 56: { + Priority = input.ReadInt32(); + break; + } + case 64: { + Service = input.ReadInt32(); + break; + } + case 72: { + ServerTs = input.ReadInt64(); + break; + } + case 80: { + ClientTs = input.ReadInt64(); + break; + } + case 88: { + NotificationType = input.ReadInt32(); + break; + } + case 802: { + if (!HasLoginMessage) { + LoginMessage = new global::LeanCloud.Realtime.Internal.Protocol.LoginCommand(); + } + input.ReadMessage(LoginMessage); + break; + } + case 810: { + if (!HasDataMessage) { + DataMessage = new global::LeanCloud.Realtime.Internal.Protocol.DataCommand(); + } + input.ReadMessage(DataMessage); + break; + } + case 818: { + if (!HasSessionMessage) { + SessionMessage = new global::LeanCloud.Realtime.Internal.Protocol.SessionCommand(); + } + input.ReadMessage(SessionMessage); + break; + } + case 826: { + if (!HasErrorMessage) { + ErrorMessage = new global::LeanCloud.Realtime.Internal.Protocol.ErrorCommand(); + } + input.ReadMessage(ErrorMessage); + break; + } + case 834: { + if (!HasDirectMessage) { + DirectMessage = new global::LeanCloud.Realtime.Internal.Protocol.DirectCommand(); + } + input.ReadMessage(DirectMessage); + break; + } + case 842: { + if (!HasAckMessage) { + AckMessage = new global::LeanCloud.Realtime.Internal.Protocol.AckCommand(); + } + input.ReadMessage(AckMessage); + break; + } + case 850: { + if (!HasUnreadMessage) { + UnreadMessage = new global::LeanCloud.Realtime.Internal.Protocol.UnreadCommand(); + } + input.ReadMessage(UnreadMessage); + break; + } + case 858: { + if (!HasReadMessage) { + ReadMessage = new global::LeanCloud.Realtime.Internal.Protocol.ReadCommand(); + } + input.ReadMessage(ReadMessage); + break; + } + case 866: { + if (!HasRcpMessage) { + RcpMessage = new global::LeanCloud.Realtime.Internal.Protocol.RcpCommand(); + } + input.ReadMessage(RcpMessage); + break; + } + case 874: { + if (!HasLogsMessage) { + LogsMessage = new global::LeanCloud.Realtime.Internal.Protocol.LogsCommand(); + } + input.ReadMessage(LogsMessage); + break; + } + case 882: { + if (!HasConvMessage) { + ConvMessage = new global::LeanCloud.Realtime.Internal.Protocol.ConvCommand(); + } + input.ReadMessage(ConvMessage); + break; + } + case 890: { + if (!HasRoomMessage) { + RoomMessage = new global::LeanCloud.Realtime.Internal.Protocol.RoomCommand(); + } + input.ReadMessage(RoomMessage); + break; + } + case 898: { + if (!HasPresenceMessage) { + PresenceMessage = new global::LeanCloud.Realtime.Internal.Protocol.PresenceCommand(); + } + input.ReadMessage(PresenceMessage); + break; + } + case 906: { + if (!HasReportMessage) { + ReportMessage = new global::LeanCloud.Realtime.Internal.Protocol.ReportCommand(); + } + input.ReadMessage(ReportMessage); + break; + } + case 914: { + if (!HasPatchMessage) { + PatchMessage = new global::LeanCloud.Realtime.Internal.Protocol.PatchCommand(); + } + input.ReadMessage(PatchMessage); + break; + } + case 922: { + if (!HasPubsubMessage) { + PubsubMessage = new global::LeanCloud.Realtime.Internal.Protocol.PubsubCommand(); + } + input.ReadMessage(PubsubMessage); + break; + } + case 930: { + if (!HasBlacklistMessage) { + BlacklistMessage = new global::LeanCloud.Realtime.Internal.Protocol.BlacklistCommand(); + } + input.ReadMessage(BlacklistMessage); + break; + } + case 938: { + if (!HasLoggedinMessage) { + LoggedinMessage = new global::LeanCloud.Realtime.Internal.Protocol.LoggedinCommand(); + } + input.ReadMessage(LoggedinMessage); + break; + } + } + } + } + + } + + #endregion + +} + +#endregion Designer generated code diff --git a/Realtime/Internal/Router/LCRTMRouter.cs b/Realtime/Internal/Router/LCRTMRouter.cs new file mode 100644 index 0000000..418ddb7 --- /dev/null +++ b/Realtime/Internal/Router/LCRTMRouter.cs @@ -0,0 +1,61 @@ +using System; +using System.Threading.Tasks; +using System.Net.Http; +using LeanCloud.Storage.Internal; +using LeanCloud.Common; +using Newtonsoft.Json; + +namespace LeanCloud.Realtime.Internal.Router { + /// + /// RTM Router + /// + internal class LCRTMRouter { + /// + /// 请求超时 + /// + private const int REQUEST_TIMEOUT = 10000; + + private LCRTMServer rtmServer; + + internal LCRTMRouter() { + } + + /// + /// 获取服务器地址 + /// + /// + internal async Task GetServer() { + if (rtmServer == null || !rtmServer.IsValid) { + await Fetch(); + } + return rtmServer; + } + + async Task Fetch() { + string server = await LCApplication.AppRouter.GetRealtimeServer(); + string url = $"{server}/v1/route?appId={LCApplication.AppId}&secure=1"; + + HttpRequestMessage request = new HttpRequestMessage { + RequestUri = new Uri(url), + Method = HttpMethod.Get + }; + HttpClient client = new HttpClient(); + LCHttpUtils.PrintRequest(client, request); + + Task requestTask = client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead); + if (await Task.WhenAny(requestTask, Task.Delay(REQUEST_TIMEOUT)) != requestTask) { + throw new TimeoutException("Request timeout."); + } + + HttpResponseMessage response = await requestTask; + request.Dispose(); + string resultString = await response.Content.ReadAsStringAsync(); + response.Dispose(); + LCHttpUtils.PrintResponse(response, resultString); + + rtmServer = JsonConvert.DeserializeObject(resultString, new LCJsonConverter()); + + return rtmServer; + } + } +} diff --git a/Realtime/Internal/Router/LCRTMServer.cs b/Realtime/Internal/Router/LCRTMServer.cs new file mode 100644 index 0000000..45a5176 --- /dev/null +++ b/Realtime/Internal/Router/LCRTMServer.cs @@ -0,0 +1,39 @@ +using System; +using Newtonsoft.Json; + +namespace LeanCloud.Realtime.Internal.Router { + internal class LCRTMServer { + [JsonProperty("groupId")] + internal string GroupId { + get; set; + } + + [JsonProperty("groupUrl")] + internal string GroupUrl { + get; set; + } + + [JsonProperty("server")] + internal string Primary { + get; set; + } + + [JsonProperty("secondary")] + internal string Secondary { + get; set; + } + + [JsonProperty("ttl")] + internal int Ttl { + get; set; + } + + DateTimeOffset createdAt; + + internal LCRTMServer() { + createdAt = DateTimeOffset.Now; + } + + internal bool IsValid => DateTimeOffset.Now < createdAt + TimeSpan.FromSeconds(Ttl); + } +} diff --git a/Realtime/Internal/WebSocket/LCWebSocketClient.cs b/Realtime/Internal/WebSocket/LCWebSocketClient.cs new file mode 100644 index 0000000..09d599e --- /dev/null +++ b/Realtime/Internal/WebSocket/LCWebSocketClient.cs @@ -0,0 +1,150 @@ +using System; +using System.Threading.Tasks; +using System.Net.WebSockets; + +namespace LeanCloud.Realtime.Internal.WebSocket { + /// + /// WebSocket 客户端,负责底层连接和事件,只与通信协议相关 + /// + internal class LCWebSocketClient { + // .net standard 2.0 好像在拼合 Frame 时有 bug,所以将这个值调整大一些 + private const int RECV_BUFFER_SIZE = 1024 * 5; + + /// + /// 关闭超时 + /// + private const int CLOSE_TIMEOUT = 5000; + + /// + /// 连接超时 + /// + private const int CONNECT_TIMEOUT = 10000; + + /// + /// 消息事件 + /// + internal Action OnMessage; + + /// + /// 连接关闭 + /// + internal Action OnClose; + + private ClientWebSocket ws; + + /// + /// 连接指定 ws 服务器 + /// + /// + /// + internal async Task Connect(string server) { + LCLogger.Debug($"Connecting WebSocket: {server}"); + Task timeoutTask = Task.Delay(CONNECT_TIMEOUT); + ws = new ClientWebSocket(); + ws.Options.AddSubProtocol("lc.protobuf2.3"); + Task connectTask = ws.ConnectAsync(new Uri(server), default); + if (await Task.WhenAny(connectTask, timeoutTask) == connectTask) { + LCLogger.Debug($"Connected WebSocket: {server}"); + await connectTask; + // 接收 + _ = StartReceive(); + } else { + throw new TimeoutException("Connect timeout"); + } + } + + /// + /// 主动关闭连接 + /// + /// + internal async Task Close() { + LCLogger.Debug("Closing WebSocket"); + OnMessage = null; + OnClose = null; + try { + // 发送关闭帧可能会很久,所以增加超时 + // 主动挥手关闭,不会再收到 Close Frame + Task closeTask = ws.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, default); + Task delayTask = Task.Delay(CLOSE_TIMEOUT); + await Task.WhenAny(closeTask, delayTask); + } catch (Exception e) { + LCLogger.Error(e); + } finally { + ws.Abort(); + ws.Dispose(); + LCLogger.Debug("Closed WebSocket"); + } + } + + /// + /// 发送数据 + /// + /// + /// + internal async Task Send(byte[] data) { + ArraySegment bytes = new ArraySegment(data); + if (ws.State == WebSocketState.Open) { + try { + await ws.SendAsync(bytes, WebSocketMessageType.Binary, true, default); + } catch (Exception e) { + LCLogger.Error(e); + throw e; + } + } else { + string message = $"Error Websocket state: {ws.State}"; + LCLogger.Error(message); + throw new Exception(message); + } + } + + /// + /// 接收数据 + /// + /// + private async Task StartReceive() { + byte[] buffer = new byte[RECV_BUFFER_SIZE]; + try { + while (ws.State == WebSocketState.Open) { + WebSocketReceiveResult result = await ws.ReceiveAsync(new ArraySegment(buffer), default); + if (result.MessageType == WebSocketMessageType.Close) { + LCLogger.Debug($"Receive Closed: {result.CloseStatus}"); + if (ws.State == WebSocketState.CloseReceived) { + // 如果是服务端主动关闭,则挥手关闭,并认为是断线 + try { + Task closeTask = ws.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, default); + await Task.WhenAny(closeTask, Task.Delay(CLOSE_TIMEOUT)); + } catch (Exception e) { + LCLogger.Error(e); + } finally { + HandleExceptionClose(); + } + } + } else if (result.MessageType == WebSocketMessageType.Binary) { + // 拼合 WebSocket Message + int length = result.Count; + byte[] data = new byte[length]; + Array.Copy(buffer, data, length); + OnMessage?.Invoke(data); + } else { + LCLogger.Error($"Error message type: {result.MessageType}"); + } + } + } catch (Exception e) { + // 客户端网络异常 + LCLogger.Error(e); + HandleExceptionClose(); + } + } + + private void HandleExceptionClose() { + try { + ws.Abort(); + ws.Dispose(); + } catch (Exception e) { + LCLogger.Error(e); + } finally { + OnClose?.Invoke(); + } + } + } +} diff --git a/Realtime/LCIMClient.cs b/Realtime/LCIMClient.cs new file mode 100644 index 0000000..4799c4a --- /dev/null +++ b/Realtime/LCIMClient.cs @@ -0,0 +1,492 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using System.Linq; +using System.Collections.ObjectModel; +using LeanCloud.Common; +using LeanCloud.Storage; +using LeanCloud.Realtime.Internal.Protocol; +using LeanCloud.Realtime.Internal.Controller; +using LeanCloud.Realtime.Internal.Connection; + +namespace LeanCloud.Realtime { + /// + /// 通信客户端 + /// + public class LCIMClient { + internal Dictionary ConversationDict; + + public string Id { + get; private set; + } + + public string Tag { + get; private set; + } + + public string DeviceId { + get; private set; + } + + internal string SessionToken { + get; private set; + } + + #region 事件 + + #region 连接状态事件 + + /// + /// 客户端连接断开 + /// + public Action OnPaused { + get; set; + } + + /// + /// 客户端连接恢复正常 + /// + public Action OnResume { + get; set; + } + + /// + /// 当前客户端被服务端强行下线 + /// + public Action OnClose { + get; set; + } + + #endregion + + #region 对话事件 + + /// + /// 当前用户被加入某个对话的黑名单 + /// + public Action OnBlocked { + get; set; + } + + /// + /// 当用户被解除黑名单 + /// + public Action OnUnblocked { + get; set; + } + + /// + /// 当前用户在某个对话中被禁言 + /// + public Action OnMuted; + + /// + /// 当前用户在某个对话中被解除禁言 + /// + public Action OnUnmuted; + + /// + /// 该对话信息被更新 + /// + public Action, string> OnConversationInfoUpdated; + + /// + /// 当前用户被添加至某个对话 + /// + public Action OnInvited { + get; set; + } + + /// + /// 当前用户被从某个对话中移除 + /// + public Action OnKicked { + get; set; + } + + /// + /// 有用户被添加至某个对话 + /// + public Action, string> OnMembersJoined { + get; set; + } + + /// + /// 有成员被从某个对话中移除 + /// + public Action, string> OnMembersLeft { + get; set; + } + + /// + /// 有成员被加入某个对话的黑名单 + /// + public Action, string> OnMembersBlocked { + get; set; + } + + /// + /// 有成员被移出某个对话的黑名单 + /// + public Action, string> OnMembersUnblocked { + get; set; + } + + /// + /// 有成员在某个对话中被禁言 + /// + public Action, string> OnMembersMuted { + get; set; + } + + /// + /// 有成员被移出某个对话的黑名单 + /// + public Action, string> OnMembersUnmuted { + get; set; + } + + /// + /// 有成员的对话信息被更新 + /// + public Action OnMemberInfoUpdated; + + #endregion + + #region 消息事件 + + /// + /// 当前用户收到消息 + /// + public Action OnMessage { + get; set; + } + + /// + /// 消息被撤回 + /// + public Action OnMessageRecalled { + get; set; + } + + /// + /// 消息被修改 + /// + public Action OnMessageUpdated { + get; set; + } + + /// + /// 消息已送达 + /// + public Action OnMessageDelivered { + get; set; + } + + /// + /// 消息已读 + /// + public Action OnMessageRead { + get; set; + } + + /// + /// 未读消息数目更新 + /// + public Action> OnUnreadMessagesCountUpdated { + get; set; + } + + /// + /// 最近分发消息更新 + /// + public Action OnLastDeliveredAtUpdated { + get; set; + } + + /// + /// 最近已读消息更新 + /// + public Action OnLastReadAtUpdated { + get; set; + } + + #endregion + + #endregion + + internal ILCIMSignatureFactory SignatureFactory { + get; private set; + } + + internal LCConnection Connection { + get; set; + } + + internal LCIMSessionController SessionController { + get; private set; + } + + internal LCIMMessageController MessageController { + get; private set; + } + + internal LCIMGoAwayController GoAwayController { + get; private set; + } + + internal LCIMConversationController ConversationController { + get; private set; + } + + #region 接口 + + public LCIMClient(string clientId, + string tag = null, + string deviceId = null, + ILCIMSignatureFactory signatureFactory = null) { + if (string.IsNullOrEmpty(clientId)) { + throw new ArgumentNullException(nameof(clientId)); + } + SetUpClient(clientId, tag, deviceId, signatureFactory); + } + + public LCIMClient(LCUser user, + string tag = null, + string deviceId = null, + ILCIMSignatureFactory signatureFactory = null) { + if (user == null) { + throw new ArgumentNullException(nameof(user)); + } + if (string.IsNullOrEmpty(user.ObjectId) || + string.IsNullOrEmpty(user.SessionToken)) { + throw new ArgumentException("User must be authenticacted."); + } + SetUpClient(user.ObjectId, tag, deviceId, signatureFactory); + SessionToken = user.SessionToken; + } + + private void SetUpClient(string clientId, + string tag, + string deviceId, + ILCIMSignatureFactory signatureFactory) { + Id = clientId; + Tag = tag; + DeviceId = deviceId; + SignatureFactory = signatureFactory; + + ConversationDict = new Dictionary(); + + // 模块 + SessionController = new LCIMSessionController(this); + ConversationController = new LCIMConversationController(this); + MessageController = new LCIMMessageController(this); + GoAwayController = new LCIMGoAwayController(this); + + Connection = new LCConnection(Id) { + OnNotification = OnConnectionNotification, + OnDisconnect = OnConnectionDisconnect, + OnReconnected = OnConnectionReconnect + }; + } + + /// + /// 登录 + /// + /// 是否强制登录 + /// + public async Task Open(bool force = true) { + await Connection.Connect(); + try { + // 打开 Session + await SessionController.Open(force); + } catch (Exception e) { + LCLogger.Error(e); + // 如果 session 阶段异常,则关闭连接 + await Connection.Close(); + throw e; + } + } + + /// + /// 关闭 + /// + /// + public async Task Close() { + // 关闭 session + await SessionController.Close(); + await Connection.Close(); + } + + /// + /// 创建普通对话 + /// + /// + /// + /// + /// + /// + public async Task CreateConversation( + IEnumerable members, + string name = null, + bool unique = true, + Dictionary properties = null) { + return await ConversationController.CreateConv(members: members, + name: name, + unique: unique, + properties: properties); + } + + /// + /// 创建聊天室 + /// + /// + /// + /// + public async Task CreateChatRoom( + string name, + Dictionary properties = null) { + LCIMChatRoom chatRoom = await ConversationController.CreateConv(name: name, + transient: true, + properties: properties) as LCIMChatRoom; + return chatRoom; + } + + /// + /// 创建临时对话 + /// + /// + /// + /// + /// + public async Task CreateTemporaryConversation( + IEnumerable members, + int ttl = 86400, + Dictionary properties = null) { + LCIMTemporaryConversation tempConversation = await ConversationController.CreateConv(members: members, + temporary: true, + temporaryTtl: ttl, + properties: properties) as LCIMTemporaryConversation; + return tempConversation; + } + + /// + /// 根据 id 获取对话 + /// + /// + /// + public async Task GetConversation(string id) { + if (string.IsNullOrEmpty(id)) { + throw new ArgumentNullException(nameof(id)); + } + if (LCIMConversation.IsTemporayConversation(id)) { + List temporaryConversationList = await ConversationController.GetTemporaryConversations(new string[] { id }); + if (temporaryConversationList == null || temporaryConversationList.Count < 1) { + return null; + } + return temporaryConversationList[0]; + } + LCIMConversationQuery query = GetQuery() + .WhereEqualTo("objectId", id) + .Limit(1); + ReadOnlyCollection results = await ConversationController.Find(query); + if (results == null || results.Count < 1) { + return null; + } + return results[0]; + } + + /// + /// 获取某些特定的对话 + /// + /// + /// + public async Task> GetConversationList(IEnumerable ids) { + if (ids == null || ids.Count() == 0) { + throw new ArgumentNullException(nameof(ids)); + } + // 区分临时对话 + IEnumerable tempConvIds = ids.Where(item => { + return LCIMConversation.IsTemporayConversation(item); + }); + IEnumerable convIds = ids.Where(item => { + return !tempConvIds.Contains(item); + }); + List conversationList = new List(); + if (tempConvIds.Count() > 0) { + List temporaryConversations = await ConversationController.GetTemporaryConversations(tempConvIds); + conversationList.AddRange(temporaryConversations); + } + if (convIds.Count() > 0) { + LCIMConversationQuery query = GetQuery() + .WhereContainedIn("objectId", convIds) + .Limit(convIds.Count()); + ReadOnlyCollection conversations = await ConversationController.Find(query); + conversationList.AddRange(conversations); + } + return conversationList.AsReadOnly(); + } + + /// + /// 获取对话查询对象 + /// + /// + public LCIMConversationQuery GetQuery() { + return new LCIMConversationQuery(this); + } + + #endregion + + private void OnConnectionNotification(GenericCommand notification) { + switch (notification.Cmd) { + case CommandType.Session: + _ = SessionController.OnNotification(notification); + break; + case CommandType.Conv: + case CommandType.Unread: + _ = ConversationController.OnNotification(notification); + break; + case CommandType.Direct: + case CommandType.Patch: + case CommandType.Rcp: + _ = MessageController.OnNotification(notification); + break; + case CommandType.Goaway: + _ = GoAwayController.OnNotification(notification); + break; + default: + break; + } + } + + private void OnConnectionDisconnect() { + OnPaused?.Invoke(); + } + + private void OnConnectionReconnect() { + _ = HandleReconnected(); + } + + private async Task HandleReconnected() { + try { + // 打开 Session + await SessionController.Reopen(); + // 回调用户 + OnResume?.Invoke(); + } catch (Exception e) { + LCLogger.Error(e); + await Connection.Close(); + // TODO 告知 + OnClose?.Invoke(0, string.Empty); + } + } + + internal async Task GetOrQueryConversation(string convId) { + if (ConversationDict.TryGetValue(convId, out LCIMConversation conversation)) { + return conversation; + } + conversation = await GetConversation(convId); + return conversation; + } + } +} diff --git a/Realtime/Message/LCIMAudioMessage.cs b/Realtime/Message/LCIMAudioMessage.cs new file mode 100644 index 0000000..830459f --- /dev/null +++ b/Realtime/Message/LCIMAudioMessage.cs @@ -0,0 +1,48 @@ +using System.Collections.Generic; +using LeanCloud.Storage; + +namespace LeanCloud.Realtime { + /// + /// 音频消息 + /// + public class LCIMAudioMessage : LCIMFileMessage { + /// + /// 时长 + /// + public double Duration { + get; private set; + } + + internal LCIMAudioMessage() { + } + + public LCIMAudioMessage(LCFile file) : base(file) { + + } + + internal override Dictionary Encode() { + Dictionary data = base.Encode(); + Dictionary fileData = data[MessageFileKey] as Dictionary; + Dictionary metaData = fileData[MessageDataMetaDataKey] as Dictionary; + if (File.MetaData != null && + File.MetaData.TryGetValue(MessageDataMetaDurationKey, out object duration)) { + metaData[MessageDataMetaDurationKey] = duration; + } + return data; + } + + internal override void Decode(Dictionary msgData) { + base.Decode(msgData); + + if (File.MetaData == null) { + return; + } + if (File.MetaData.TryGetValue(MessageDataMetaDurationKey, out object duration) && + double.TryParse(duration as string, out double d)) { + Duration = d; + } + } + + public override int MessageType => AudioMessageType; + } +} diff --git a/Realtime/Message/LCIMBinaryMessage.cs b/Realtime/Message/LCIMBinaryMessage.cs new file mode 100644 index 0000000..d8d76fa --- /dev/null +++ b/Realtime/Message/LCIMBinaryMessage.cs @@ -0,0 +1,21 @@ +namespace LeanCloud.Realtime { + /// + /// 二进制消息 + /// + public class LCIMBinaryMessage : LCIMMessage { + /// + /// 消息数据 + /// + public byte[] Data { + get; internal set; + } + + public LCIMBinaryMessage(byte[] data) { + Data = data; + } + + internal static LCIMBinaryMessage Deserialize(byte[] bytes) { + return new LCIMBinaryMessage(bytes); + } + } +} diff --git a/Realtime/Message/LCIMFileMessage.cs b/Realtime/Message/LCIMFileMessage.cs new file mode 100644 index 0000000..0cdf93c --- /dev/null +++ b/Realtime/Message/LCIMFileMessage.cs @@ -0,0 +1,135 @@ +using System; +using System.IO; +using System.Collections.Generic; +using LeanCloud.Storage; + +namespace LeanCloud.Realtime { + /// + /// 文件消息 + /// + public class LCIMFileMessage : LCIMTextMessage { + /// + /// 文件 + /// + public LCFile File { + get; set; + } + + /// + /// 文件大小 + /// + public int Size { + get; private set; + } + + /// + /// 文件扩展名 + /// + public string Format { + get; private set; + } + + /// + /// 文件链接 + /// + public string Url { + get { + return File.Url; + } + } + + internal LCIMFileMessage() : base() { + + } + + public LCIMFileMessage(LCFile file) : base() { + File = file; + } + + public override int MessageType => FileMessageType; + + internal override Dictionary Encode() { + if (File == null) { + throw new Exception("File MUST NOT be null before sent."); + } + if (string.IsNullOrEmpty(File.ObjectId)) { + throw new Exception("File MUST be saved before sent."); + } + Dictionary fileData = new Dictionary { + { MessageDataObjectIdKey, File.ObjectId } + }; + // 链接 + if (!string.IsNullOrEmpty(File.Url)) { + fileData[MessageDataUrlKey] = File.Url; + } + // 元数据 + Dictionary metaData = new Dictionary(); + // 文件名 + if (!string.IsNullOrEmpty(File.Name)) { + metaData[MessageDataMetaNameKey] = File.Name; + } + // 文件扩展名 + string format = null; + if (File.MetaData != null && + File.MetaData.TryGetValue(MessageDataMetaFormatKey, out object f)) { + // 优先使用用户设置值 + format = f as string; + } else if (File.Name != null && + !string.IsNullOrEmpty(Path.GetExtension(File.Name))) { + // 根据文件名推测 + format = Path.GetExtension(File.Name)?.Replace(".", string.Empty); + } else if (File.Url != null && + !string.IsNullOrEmpty(Path.GetExtension(File.Url))) { + // 根据 url 推测 + format = Path.GetExtension(File.Url)?.Replace(".", string.Empty); + } + if (!string.IsNullOrEmpty(format)) { + metaData[MessageDataMetaFormatKey] = format; + } + // 文件大小 + if (File.MetaData != null && + File.MetaData.TryGetValue(MessageDataMetaSizeKey, out object size)) { + metaData[MessageDataMetaSizeKey] = size; + } + fileData[MessageDataMetaDataKey] = metaData; + + Dictionary data = base.Encode(); + data[MessageFileKey] = fileData; + return data; + } + + internal override void Decode(Dictionary msgData) { + base.Decode(msgData); + + if (msgData.TryGetValue(MessageFileKey, out object fileDataObject)) { + Dictionary fileData = fileDataObject as Dictionary; + if (fileData == null) { + return; + } + if (fileData.TryGetValue(MessageDataObjectIdKey, out object objectIdObject)) { + string objectId = objectIdObject as string; + File = LCObject.CreateWithoutData(LCFile.CLASS_NAME, objectId) as LCFile; + if (fileData.TryGetValue(MessageDataUrlKey, out object url)) { + File.Url = url as string; + } + if (fileData.TryGetValue(MessageDataMetaDataKey, out object metaData)) { + File.MetaData = metaData as Dictionary; + if (File.MetaData == null) { + return; + } + if (File.MetaData.TryGetValue(MessageDataMetaNameKey, out object name)) { + File.Name = name as string; + } + if (File.MetaData.TryGetValue(MessageDataMetaSizeKey, out object size) && + int.TryParse(size as string, out int s)) { + Size = s; + } + if (File.MetaData.TryGetValue(MessageDataMetaFormatKey, out object format)) { + Format = format as string; + } + } + } + } + } + } +} diff --git a/Realtime/Message/LCIMImageMessage.cs b/Realtime/Message/LCIMImageMessage.cs new file mode 100644 index 0000000..5bc4144 --- /dev/null +++ b/Realtime/Message/LCIMImageMessage.cs @@ -0,0 +1,63 @@ +using System.Collections.Generic; +using LeanCloud.Storage; + +namespace LeanCloud.Realtime { + /// + /// 图像消息 + /// + public class LCIMImageMessage : LCIMFileMessage { + /// + /// 图像宽度 + /// + public int Width { + get; private set; + } + + /// + /// 图像高度 + /// + public int Height { + get; private set; + } + + internal LCIMImageMessage() : base() { + } + + public LCIMImageMessage(LCFile file) : base(file) { + + } + + internal override Dictionary Encode() { + Dictionary data = base.Encode(); + Dictionary fileData = data[MessageFileKey] as Dictionary; + Dictionary metaData = fileData[MessageDataMetaDataKey] as Dictionary; + if (File.MetaData != null) { + if (File.MetaData.TryGetValue(MessageDataMetaWidthKey, out object width)) { + metaData[MessageDataMetaWidthKey] = width; + } + if (File.MetaData.TryGetValue(MessageDataMetaHeightKey, out object height)) { + metaData[MessageDataMetaHeightKey] = height; + } + } + return data; + } + + internal override void Decode(Dictionary msgData) { + base.Decode(msgData); + + if (File.MetaData == null) { + return; + } + if (File.MetaData.TryGetValue(MessageDataMetaWidthKey, out object width) && + int.TryParse(width as string, out int w)) { + Width = w; + } + if (File.MetaData.TryGetValue(MessageDataMetaHeightKey, out object height) && + int.TryParse(height as string, out int h)) { + Height = h; + } + } + + public override int MessageType => ImageMessageType; + } +} diff --git a/Realtime/Message/LCIMLocationMessage.cs b/Realtime/Message/LCIMLocationMessage.cs new file mode 100644 index 0000000..e4454ca --- /dev/null +++ b/Realtime/Message/LCIMLocationMessage.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using LeanCloud.Storage; + +namespace LeanCloud.Realtime { + /// + /// 位置消息 + /// + public class LCIMLocationMessage : LCIMTextMessage { + /// + /// 位置 + /// + public LCGeoPoint Location { + get; set; + } + + internal LCIMLocationMessage() { + } + + public LCIMLocationMessage(LCGeoPoint locaction) : base(null) { + Location = locaction; + } + + internal override Dictionary Encode() { + if (Location == null) { + throw new ArgumentNullException(nameof(Location)); + } + Dictionary data = base.Encode(); + Dictionary locationData = new Dictionary { + { MessageDataLongitudeKey, Location.Longitude }, + { MessageDataLatitudeKey, Location.Latitude } + }; + data[MessageLocationKey] = locationData; + return data; + } + + internal override void Decode(Dictionary msgData) { + base.Decode(msgData); + if (msgData.TryGetValue(MessageLocationKey, out object val)) { + Dictionary locationData = val as Dictionary; + if (locationData == null) { + return; + } + double latitude = 0, longitude = 0; + if (locationData.TryGetValue(MessageDataLatitudeKey, out object lat) && + double.TryParse(lat as string, out double la)) { + latitude = la; + } + if (locationData.TryGetValue(MessageDataLongitudeKey, out object lon) && + double.TryParse(lon as string, out double lo)) { + longitude = lo; + } + Location = new LCGeoPoint(latitude, longitude); + } + } + + public override int MessageType => LocationMessageType; + } +} diff --git a/Realtime/Message/LCIMMessage.cs b/Realtime/Message/LCIMMessage.cs new file mode 100644 index 0000000..e62fbcb --- /dev/null +++ b/Realtime/Message/LCIMMessage.cs @@ -0,0 +1,129 @@ +using System; +using System.Collections.Generic; + +namespace LeanCloud.Realtime { + /// + /// 消息基类 + /// + public abstract class LCIMMessage { + /// + /// 消息所在对话 Id + /// + public string ConversationId { + get; set; + } + + /// + /// 消息 Id + /// + public string Id { + get; set; + } + + /// + /// 发送者 Id + /// + public string FromClientId { + get; set; + } + + /// + /// 发送时间戳 + /// + public long SentTimestamp { + get; internal set; + } + + /// + /// 发送时间 + /// + public DateTime SentAt { + get { + return DateTimeOffset.FromUnixTimeMilliseconds(SentTimestamp) + .LocalDateTime; + } + } + + /// + /// 送达时间戳 + /// + public long DeliveredTimestamp { + get; internal set; + } + + /// + /// 送达时间 + /// + public DateTime DeliveredAt { + get { + return DateTimeOffset.FromUnixTimeMilliseconds(DeliveredTimestamp) + .LocalDateTime; + } + } + + /// + /// 已读时间戳 + /// + public long ReadTimestamp { + get; internal set; + } + + /// + /// 已读时间 + /// + public DateTime ReadAt { + get { + return DateTimeOffset.FromUnixTimeMilliseconds(ReadTimestamp) + .LocalDateTime; + } + } + + /// + /// 修改时间戳 + /// + public long PatchedTimestamp { + get; internal set; + } + + /// + /// 修改时间 + /// + public DateTime PatchedAt { + get { + return DateTimeOffset.FromUnixTimeMilliseconds(PatchedTimestamp) + .LocalDateTime; + } + } + + /// + /// 提醒成员 Id 列表 + /// + public List MentionIdList { + get; set; + } + + /// + /// 是否提醒所有人 + /// + public bool MentionAll { + get; set; + } + + /// + /// 是否提醒当前用户 + /// + public bool Mentioned { + get; internal set; + } + + /// + /// 是否是暂态消息 + /// + public bool IsTransient { + get; internal set; + } + + internal LCIMMessage() { + } + } +} diff --git a/Realtime/Message/LCIMMessageSendOptions.cs b/Realtime/Message/LCIMMessageSendOptions.cs new file mode 100644 index 0000000..4e61efd --- /dev/null +++ b/Realtime/Message/LCIMMessageSendOptions.cs @@ -0,0 +1,51 @@ +using System.Collections.Generic; + +namespace LeanCloud.Realtime { + /// + /// 消息优先级 + /// + public enum LCIMMessagePriority { + Hight = 1, + Normal = 2, + Low = 3 + } + + /// + /// 发送消息选项 + /// + public class LCIMMessageSendOptions { + /// + /// 是否作为暂态消息发送 + /// + public bool Transient { + get; set; + } + + /// + /// 是否需要消息回执,仅在普通对话中有效 + /// + public bool Receipt { + get; set; + } + + /// + /// 是否作为遗愿消息发送 + /// + public bool Will { + get; set; + } + + /// + /// 消息优先级,仅在暂态对话中有效 + /// + public LCIMMessagePriority Priority { + get; set; + } + + public Dictionary PushData { + get; set; + } + + public static LCIMMessageSendOptions Default = new LCIMMessageSendOptions(); + } +} diff --git a/Realtime/Message/LCIMRecalledMessage.cs b/Realtime/Message/LCIMRecalledMessage.cs new file mode 100644 index 0000000..352e585 --- /dev/null +++ b/Realtime/Message/LCIMRecalledMessage.cs @@ -0,0 +1,12 @@ + +namespace LeanCloud.Realtime { + /// + /// 撤回消息 + /// + public class LCIMRecalledMessage : LCIMTypedMessage { + public LCIMRecalledMessage() { + } + + public override int MessageType => RecalledMessageType; + } +} diff --git a/Realtime/Message/LCIMTextMessage.cs b/Realtime/Message/LCIMTextMessage.cs new file mode 100644 index 0000000..2b0fb56 --- /dev/null +++ b/Realtime/Message/LCIMTextMessage.cs @@ -0,0 +1,38 @@ +using System.Collections.Generic; + +namespace LeanCloud.Realtime { + /// + /// 文本消息 + /// + public class LCIMTextMessage : LCIMTypedMessage { + /// + /// 文本 + /// + public string Text { + get; set; + } + + internal LCIMTextMessage() { + } + + public LCIMTextMessage(string text) : base() { + Text = text; + } + + internal override Dictionary Encode() { + Dictionary data = base.Encode(); + if (!string.IsNullOrEmpty(Text)) { + data[MessageTextKey] = Text; + } + return data; + } + + public override int MessageType => TextMessageType; + + internal override void Decode(Dictionary msgData) { + if (msgData.TryGetValue(MessageTextKey, out object value)) { + Text = value as string; + } + } + } +} diff --git a/Realtime/Message/LCIMTypedMessage.cs b/Realtime/Message/LCIMTypedMessage.cs new file mode 100644 index 0000000..d43b40d --- /dev/null +++ b/Realtime/Message/LCIMTypedMessage.cs @@ -0,0 +1,159 @@ +using System; +using System.Collections.Generic; +using Newtonsoft.Json; +using LeanCloud.Storage.Internal.Codec; +using LeanCloud.Storage.Internal; + +namespace LeanCloud.Realtime { + /// + /// 已知类型消息 + /// + public class LCIMTypedMessage : LCIMMessage { + /// + /// 文本消息 + /// + public const int TextMessageType = -1; + /// + /// 图像消息 + /// + public const int ImageMessageType = -2; + /// + /// 音频消息 + /// + public const int AudioMessageType = -3; + /// + /// 视频消息 + /// + public const int VideoMessageType = -4; + /// + /// 位置消息 + /// + public const int LocationMessageType = -5; + /// + /// 文件消息 + /// + public const int FileMessageType = -6; + /// + /// 撤回消息 + /// + public const int RecalledMessageType = -127; + + /// + /// 保留字段 + /// + protected const string MessageTypeKey = "_lctype"; + protected const string MessageAttributesKey = "_lcattrs"; + protected const string MessageTextKey = "_lctext"; + protected const string MessageLocationKey = "_lcloc"; + protected const string MessageFileKey = "_lcfile"; + + protected const string MessageDataLongitudeKey = "longitude"; + protected const string MessageDataLatitudeKey = "latitude"; + + protected const string MessageDataObjectIdKey = "objId"; + protected const string MessageDataUrlKey = "url"; + protected const string MessageDataMetaDataKey = "metaData"; + protected const string MessageDataMetaNameKey = "name"; + protected const string MessageDataMetaFormatKey = "format"; + protected const string MessageDataMetaSizeKey = "size"; + protected const string MessageDataMetaWidthKey = "width"; + protected const string MessageDataMetaHeightKey = "height"; + protected const string MessageDataMetaDurationKey = "duration"; + + + private Dictionary customProperties; + + /// + /// 完整的消息数据 + /// + protected Dictionary data = new Dictionary(); + + /// + /// 消息类型 + /// + public virtual int MessageType { + get; private set; + } + + /// + /// 消息属性访问 + /// + /// + /// + public object this[string key] { + get { + if (customProperties == null) { + return null; + } + return customProperties[key]; + } + set { + if (customProperties == null) { + customProperties = new Dictionary(); + } + customProperties[key] = value; + } + } + + protected LCIMTypedMessage() { + } + + internal virtual Dictionary Encode() { + Dictionary msgData = data != null ? + new Dictionary(data) : new Dictionary(); + msgData[MessageTypeKey] = MessageType; + if (customProperties != null && customProperties.Count > 0) { + msgData[MessageAttributesKey] = LCEncoder.Encode(customProperties); + } + return msgData; + } + + internal virtual void Decode(Dictionary msgData) { + // 直接保存 + data = msgData; + } + + internal static LCIMTypedMessage Deserialize(string json) { + Dictionary msgData = JsonConvert.DeserializeObject>(json, + new LCJsonConverter()); + LCIMTypedMessage message = null; + int msgType = (int)msgData[MessageTypeKey]; + if (customMessageDict.TryGetValue(msgType, out Func msgConstructor)) { + // 已注册的类型消息 + message = msgConstructor.Invoke(); + } else { + // 未注册的类型消息 + message = new LCIMTypedMessage(); + } + // 已知类型消息的固定 + message.MessageType = msgType; + if (msgData.TryGetValue(MessageAttributesKey, out object attrObj)) { + message.customProperties = LCDecoder.Decode(attrObj) as Dictionary; + } + message.Decode(msgData); + return message; + } + + // 内置已知类型消息 + static readonly Dictionary> customMessageDict = new Dictionary> { + { TextMessageType, () => new LCIMTextMessage() }, + { ImageMessageType, () => new LCIMImageMessage() }, + { AudioMessageType, () => new LCIMAudioMessage() }, + { VideoMessageType, () => new LCIMVideoMessage() }, + { LocationMessageType, () => new LCIMLocationMessage() }, + { FileMessageType, () => new LCIMFileMessage() }, + { RecalledMessageType, () => new LCIMRecalledMessage() } + }; + + /// + /// 注册自定义类型消息 + /// + /// + /// + /// + public static void Register(int msgType, Func msgConstructor) + where T : LCIMTypedMessage { + customMessageDict[msgType] = msgConstructor; + } + } +} diff --git a/Realtime/Message/LCIMVideoMessage.cs b/Realtime/Message/LCIMVideoMessage.cs new file mode 100644 index 0000000..fb86337 --- /dev/null +++ b/Realtime/Message/LCIMVideoMessage.cs @@ -0,0 +1,77 @@ +using System.Collections.Generic; +using LeanCloud.Storage; + +namespace LeanCloud.Realtime { + /// + /// 视频消息 + /// + public class LCIMVideoMessage : LCIMFileMessage { + /// + /// 宽度 + /// + public int Width { + get; private set; + } + + /// + /// 高度 + /// + public int Height { + get; private set; + } + + /// + /// 时长 + /// + public double Duration { + get; private set; + } + + internal LCIMVideoMessage() { + } + + public LCIMVideoMessage(LCFile file) : base(file) { + + } + + internal override Dictionary Encode() { + Dictionary data = base.Encode(); + Dictionary fileData = data[MessageFileKey] as Dictionary; + Dictionary metaData = fileData[MessageDataMetaDataKey] as Dictionary; + if (File.MetaData != null) { + if (File.MetaData.TryGetValue(MessageDataMetaWidthKey, out object width)) { + metaData[MessageDataMetaWidthKey] = width; + } + if (File.MetaData.TryGetValue(MessageDataMetaHeightKey, out object height)) { + metaData[MessageDataMetaHeightKey] = height; + } + if (File.MetaData.TryGetValue(MessageDataMetaDurationKey, out object duration)) { + metaData[MessageDataMetaDurationKey] = duration; + } + } + return data; + } + + internal override void Decode(Dictionary msgData) { + base.Decode(msgData); + + if (File.MetaData == null) { + return; + } + if (File.MetaData.TryGetValue(MessageDataMetaWidthKey, out object width) && + int.TryParse(width as string, out int w)) { + Width = w; + } + if (File.MetaData.TryGetValue(MessageDataMetaHeightKey, out object height) && + int.TryParse(height as string, out int h)) { + Height = h; + } + if (File.MetaData.TryGetValue(MessageDataMetaDurationKey, out object duration) && + double.TryParse(duration as string, out double d)) { + Duration = d; + } + } + + public override int MessageType => VideoMessageType; + } +} diff --git a/Realtime/Realtime.csproj b/Realtime/Realtime.csproj new file mode 100644 index 0000000..e9eaffd --- /dev/null +++ b/Realtime/Realtime.csproj @@ -0,0 +1,29 @@ + + + + netstandard2.0 + 0.1.0 + LeanCloud.Realtime + true + + + + + + + + + + + + + + + + + + + + + + diff --git a/Realtime/Result/LCIMOperationFailure.cs b/Realtime/Result/LCIMOperationFailure.cs new file mode 100644 index 0000000..73780e1 --- /dev/null +++ b/Realtime/Result/LCIMOperationFailure.cs @@ -0,0 +1,35 @@ +using System.Collections.Generic; + +namespace LeanCloud.Realtime { + /// + /// 操作失败 + /// + public class LCIMOperationFailure { + /// + /// 失败码 + /// + public int Code { + get; set; + } + + /// + /// 失败原因 + /// + public string Reason { + get; set; + } + + /// + /// 失败数据 + /// + public List IdList { + get; set; + } + + //public LCIMOperationFailure(ErrorCommand error) { + // Code = error.Code; + // Reason = error.Reason; + // MemberList = error.Pids.ToList(); + //} + } +} diff --git a/Realtime/Result/LCIMPageResult.cs b/Realtime/Result/LCIMPageResult.cs new file mode 100644 index 0000000..c0879b5 --- /dev/null +++ b/Realtime/Result/LCIMPageResult.cs @@ -0,0 +1,22 @@ +using System.Collections.ObjectModel; + +namespace LeanCloud.Realtime { + /// + /// 查询分页结果 + /// + public class LCIMPageResult { + /// + /// 当前分页数据集 + /// + public ReadOnlyCollection Results { + get; internal set; + } + + /// + /// 下次请求的数据 + /// + public string Next { + get; internal set; + } + } +} diff --git a/Realtime/Result/LCIMPartiallySuccessResult.cs b/Realtime/Result/LCIMPartiallySuccessResult.cs new file mode 100644 index 0000000..e91f336 --- /dev/null +++ b/Realtime/Result/LCIMPartiallySuccessResult.cs @@ -0,0 +1,27 @@ +using System.Collections.Generic; + +namespace LeanCloud.Realtime { + /// + /// 部分成功结果 + /// + public class LCIMPartiallySuccessResult { + /// + /// 成功数据集 + /// + public List SuccessfulClientIdList { + get; internal set; + } + + /// + /// 失败原因 + /// + public List FailureList { + get; internal set; + } + + public LCIMPartiallySuccessResult() { + } + + public bool IsSuccess => FailureList == null || FailureList.Count == 0; + } +} diff --git a/Realtime/Signature/ILCIMSignatureFactory.cs b/Realtime/Signature/ILCIMSignatureFactory.cs new file mode 100644 index 0000000..4690302 --- /dev/null +++ b/Realtime/Signature/ILCIMSignatureFactory.cs @@ -0,0 +1,42 @@ +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace LeanCloud.Realtime { + /// + /// 签名工程接口 + /// + public interface ILCIMSignatureFactory { + /// + /// 登录签名 + /// + /// + /// + Task CreateConnectSignature(string clientId); + + /// + /// 创建开启对话签名 + /// + /// + Task CreateStartConversationSignature(string clientId, IEnumerable memberIds); + + /// + /// 创建会话相关签名 + /// + /// + /// + /// + /// + /// + Task CreateConversationSignature(string conversationId, string clientId, IEnumerable memberIds, string action); + + /// + /// 创建黑名单相关签名 + /// + /// + /// + /// + /// + /// + Task CreateBlacklistSignature(string conversationId, string clientId, IEnumerable memberIds, string action); + } +} diff --git a/Realtime/Signature/LCIMSignature.cs b/Realtime/Signature/LCIMSignature.cs new file mode 100644 index 0000000..815d246 --- /dev/null +++ b/Realtime/Signature/LCIMSignature.cs @@ -0,0 +1,27 @@ +namespace LeanCloud.Realtime { + /// + /// 签名数据 + /// + public class LCIMSignature { + /// + /// 签名 + /// + public string Signature { + get; set; + } + + /// + /// 时间戳 + /// + public long Timestamp { + get; set; + } + + /// + /// 随机字符串 + /// + public string Nonce { + get; set; + } + } +} diff --git a/Realtime/Signature/LCIMSignatureAction.cs b/Realtime/Signature/LCIMSignatureAction.cs new file mode 100644 index 0000000..013ed5d --- /dev/null +++ b/Realtime/Signature/LCIMSignatureAction.cs @@ -0,0 +1,36 @@ +namespace LeanCloud.Realtime { + /// + /// 支持签名的动作 + /// + public static class LCIMSignatureAction { + /// + /// 邀请 + /// + public const string Invite = "invite"; + + /// + /// 踢出 + /// + public const string Kick = "kick"; + + /// + /// 用户拉黑对话 + /// + public const string ClientBlockConversations = "client-block-conversations"; + + /// + /// 用户解除拉黑对话 + /// + public const string ClientUnblockConversations = "client-unblock-conversations"; + + /// + /// 对话拉黑用户 + /// + public const string ConversationBlockClients = "conversation-block-clients"; + + /// + /// 对话解除拉黑用户 + /// + public const string ConversationUnblockClients = "conversation-unblock-clients"; + } +} diff --git a/Realtime/protobuf/compile-client-proto.sh b/Realtime/protobuf/compile-client-proto.sh new file mode 100644 index 0000000..c19f774 --- /dev/null +++ b/Realtime/protobuf/compile-client-proto.sh @@ -0,0 +1 @@ +protoc --proto_path=. --csharp_out=../Internal/Protocol messages2.proto.orig \ No newline at end of file diff --git a/Realtime/protobuf/messages2.proto.orig b/Realtime/protobuf/messages2.proto.orig new file mode 100644 index 0000000..2786f55 --- /dev/null +++ b/Realtime/protobuf/messages2.proto.orig @@ -0,0 +1,484 @@ +syntax = "proto2"; + +package push_server.messages2; +option csharp_namespace = "LeanCloud.Realtime.Internal.Protocol"; + +// note that this line will be removed by out build script until we +// finally upgraded to protobuffer 3 +option objc_class_prefix = "AVIM"; + +enum CommandType { + session = 0; + conv = 1; + direct = 2; + ack = 3; + rcp = 4; + unread = 5; + logs = 6; + error = 7; + login = 8; + data = 9; + room = 10; + read = 11; + presence = 12; + report = 13; + echo = 14; + loggedin = 15; + logout = 16; + loggedout = 17; + patch = 18; + pubsub = 19; + blacklist = 20; + goaway = 21; +} + +enum OpType { + // session + open = 1; + add = 2; + remove = 3; + close = 4; + opened = 5; + closed = 6; + query = 7; + query_result = 8; + conflict = 9; + added = 10; + removed = 11; + refresh = 12; + refreshed = 13; + + // conv + start = 30; + started = 31; + joined = 32; + members_joined = 33; + // add = 34; reuse session.add + // added = 35; reuse session.added + // remove = 37; reuse session.remove + // removed = 38; reuse session.removed + left = 39; + members_left = 40; + // query = 41; reuse session.query + results = 42; + count = 43; + result = 44; + update = 45; + updated = 46; + mute = 47; + unmute = 48; + status = 49; + members = 50; + max_read = 51; + is_member = 52; + member_info_update = 53; + member_info_updated = 54; + member_info_changed = 55; + + // room + join = 80; + invite = 81; + leave = 82; + kick = 83; + reject = 84; + invited = 85; + // joined = 32; reuse the value in conv section + // left = 39; reuse the value in conv section + kicked = 86; + // members-joined = 33; reuse the value in conv section + // members-left = 40; reuse the value in conv section + + // report + upload = 100; + uploaded = 101; + + // pubsub + subscribe = 120; + subscribed = 121; + unsubscribe = 122; + unsubscribed = 123; + is_subscribed = 124; + + // patch + modify = 150; + modified = 151; + + // blacklist, query, query_result defined with 7, 8 + block = 170; + unblock = 171; + blocked = 172; + unblocked = 173; + members_blocked = 174; + members_unblocked = 175; + check_block = 176; + check_result = 177; + + add_shutup = 180; + remove_shutup = 181; + query_shutup = 182; + shutup_added = 183; + shutup_removed = 184; + shutup_result = 185; + shutuped = 186; + unshutuped = 187; + members_shutuped = 188; + members_unshutuped = 189; + check_shutup = 190; // check_result define in 177 +} + +enum StatusType { + on = 1; + off = 2; +} + +enum DeviceType { + unknown = 0; + android = 1; + ios = 2; +} + +message SemanticVersion { + optional int32 major = 1; + optional int32 minor = 2; + optional int32 patch = 3; + optional string preRelease = 4; + optional string build = 5; +} + +message AndroidVersion { + optional string codename = 1; + optional string apiLevel = 2; +} + +message SystemInfo { + optional DeviceType deviceType = 1; + optional SemanticVersion osVersion = 2; + optional AndroidVersion androidVersion = 3; + optional bool isEmulator = 4; +} + +message JsonObjectMessage { + required string data = 1; +} + +message UnreadTuple { + required string cid = 1; + required int32 unread = 2; + optional string mid = 3; + optional int64 timestamp = 4; + optional string from = 5; + optional string data = 6; + optional int64 patchTimestamp = 7; + optional bool mentioned = 8; + optional bytes binaryMsg = 9; + optional int32 convType = 10; +} + +message LogItem { + optional string from = 1; + optional string data = 2; + optional int64 timestamp = 3; + optional string msgId = 4; + optional int64 ackAt = 5; + optional int64 readAt = 6; + optional int64 patchTimestamp = 7; + optional bool mentionAll = 8; + repeated string mentionPids = 9; + optional bool bin = 10; + optional int32 convType = 11; +} + +message ConvMemberInfo { + optional string pid = 1; + optional string role = 2; + optional string infoId = 3; +} + +message LoginCommand { + optional SystemInfo systemInfo = 1; +} + +message LoggedinCommand { + optional bool pushDisabled = 1; +} + +message DataCommand { + repeated string ids = 1; + repeated JsonObjectMessage msg = 2; + optional bool offline = 3; +} + +message SessionCommand { + optional int64 t = 1; + optional string n = 2; + optional string s = 3; + optional string ua = 4; + optional bool r = 5; + optional string tag = 6; + optional string deviceId = 7; + repeated string sessionPeerIds = 8; + repeated string onlineSessionPeerIds = 9; + optional string st = 10; + optional int32 stTtl = 11; + optional int32 code = 12; + optional string reason = 13; + optional string deviceToken = 14; + optional bool sp = 15; + optional string detail = 16; + optional int64 lastUnreadNotifTime = 17; + optional int64 lastPatchTime = 18; + optional int64 configBitmap = 19; + optional SystemInfo systemInfo = 20; +} + +message ErrorCommand { + required int32 code = 1; + required string reason = 2; + optional int32 appCode = 3; + optional string detail = 4; + repeated string pids = 5; + optional string appMsg = 6; +} + +message DirectCommand { + optional string msg = 1; + optional string uid = 2; + optional string fromPeerId = 3; + optional int64 timestamp = 4; + optional bool offline = 5; + optional bool hasMore = 6; + repeated string toPeerIds = 7; + optional bool r = 10; + optional string cid = 11; + optional string id = 12; + optional bool transient = 13; + optional string dt = 14; + optional string roomId = 15; + optional string pushData = 16; + optional bool will = 17; + optional int64 patchTimestamp = 18; + optional bytes binaryMsg = 19; + repeated string mentionPids = 20; + optional bool mentionAll = 21; + optional int32 convType = 22; +} + +message AckCommand { + optional int32 code = 1; + optional string reason = 2; + optional string mid = 3; + optional string cid = 4; + optional int64 t = 5; + optional string uid = 6; + optional int64 fromts = 7; + optional int64 tots = 8; + optional string type = 9; + repeated string ids = 10; + optional int32 appCode = 11; + optional string appMsg = 12; +} + +message UnreadCommand { + repeated UnreadTuple convs = 1; + optional int64 notifTime = 2; +} + +message ConvCommand { + repeated string m = 1; + optional bool transient = 2; + optional bool unique = 3; + optional string cid = 4; + optional string cdate = 5; + optional string initBy = 6; + optional string sort = 7; + optional int32 limit = 8; + optional int32 skip = 9; + optional int32 flag = 10; + optional int32 count = 11; + optional string udate = 12; + optional int64 t = 13; + optional string n = 14; + optional string s = 15; + + optional bool statusSub = 16; + optional bool statusPub = 17; + optional int32 statusTTL = 18; + optional string uniqueId = 19; + + optional string targetClientId = 20; + optional int64 maxReadTimestamp = 21; + optional int64 maxAckTimestamp = 22; + optional bool queryAllMembers = 23; + repeated MaxReadTuple maxReadTuples = 24; + repeated string cids = 25; + + optional ConvMemberInfo info = 26; + + optional bool tempConv = 27; + optional int32 tempConvTTL = 28; + repeated string tempConvIds = 29; + + repeated string allowedPids = 30; + repeated ErrorCommand failedPids = 31; + + // used in shutup query + optional string next = 40; + + optional JsonObjectMessage results = 100; + optional JsonObjectMessage where = 101; + optional JsonObjectMessage attr = 103; + optional JsonObjectMessage attrModified = 104; +} + +message RoomCommand { + optional string roomId = 1; + optional string s = 2; + optional int64 t = 3; + optional string n = 4; + optional bool transient = 5; + repeated string roomPeerIds = 6; + optional string byPeerId = 7; +} + +message LogsCommand { + optional string cid = 1; + optional int32 l = 2; + optional int32 limit = 3; + optional int64 t = 4; + optional int64 tt = 5; + optional string tmid = 6; + optional string mid = 7; + optional string checksum = 8; + optional bool stored = 9; + enum QueryDirection { + OLD = 1; + NEW = 2; + } + optional QueryDirection direction = 10 [default = OLD]; + optional bool tIncluded = 11; + optional bool ttIncluded = 12; + optional int32 lctype = 13; + + repeated LogItem logs = 105; +} + +message RcpCommand { + optional string id = 1; + optional string cid = 2; + optional int64 t = 3; + optional bool read = 4; + optional string from = 5; +} + +message ReadTuple { + required string cid = 1; + optional int64 timestamp = 2; + optional string mid = 3; +} + +message MaxReadTuple { + optional string pid = 1; + optional int64 maxAckTimestamp = 2; + optional int64 maxReadTimestamp = 3; +} + +message ReadCommand { + optional string cid = 1; + repeated string cids = 2; + repeated ReadTuple convs = 3; +} + +message PresenceCommand { + optional StatusType status = 1; + repeated string sessionPeerIds = 2; + optional string cid = 3; +} + +message ReportCommand { + optional bool initiative = 1; + optional string type = 2; + optional string data = 3; +} + +message PatchItem { + optional string cid = 1; + optional string mid = 2; + optional int64 timestamp = 3; + optional bool recall = 4; + optional string data = 5; + optional int64 patchTimestamp = 6; + optional string from = 7; + optional bytes binaryMsg = 8; + optional bool mentionAll = 9; + repeated string mentionPids = 10; + optional int64 patchCode = 11; + optional string patchReason = 12; +} + +message PatchCommand { + repeated PatchItem patches = 1; + optional int64 lastPatchTime = 2; +} + +message PubsubCommand { + optional string cid = 1; + repeated string cids = 2; + optional string topic = 3; + optional string subtopic = 4; + repeated string topics = 5; + repeated string subtopics = 6; + optional JsonObjectMessage results = 7; +} + +message BlacklistCommand { + optional string srcCid = 1; + repeated string toPids = 2; + optional string srcPid = 3; + repeated string toCids = 4; + optional int32 limit = 5; + optional string next = 6; + + repeated string blockedPids = 8; + repeated string blockedCids = 9; + + repeated string allowedPids = 10; + repeated ErrorCommand failedPids = 11; + + optional int64 t = 12; + optional string n = 13; + optional string s = 14; +} + +message GenericCommand { + optional CommandType cmd = 1; + optional OpType op = 2; + + optional string appId = 3; + optional string peerId = 4; + optional int32 i = 5; + optional string installationId = 6; + optional int32 priority = 7; + optional int32 service = 8; + optional int64 serverTs = 9; + optional int64 clientTs = 10; + optional int32 notificationType = 11; + + optional LoginCommand loginMessage = 100; + optional DataCommand dataMessage = 101; + optional SessionCommand sessionMessage = 102; + optional ErrorCommand errorMessage = 103; + optional DirectCommand directMessage = 104; + optional AckCommand ackMessage = 105; + optional UnreadCommand unreadMessage = 106; + optional ReadCommand readMessage = 107; + optional RcpCommand rcpMessage = 108; + optional LogsCommand logsMessage = 109; + optional ConvCommand convMessage = 110; + optional RoomCommand roomMessage = 111; + optional PresenceCommand presenceMessage = 112; + optional ReportCommand reportMessage = 113; + optional PatchCommand patchMessage = 114; + optional PubsubCommand pubsubMessage = 115; + optional BlacklistCommand blacklistMessage = 116; + optional LoggedinCommand loggedinMessage = 117; +} diff --git a/Storage/Internal/Codec/LCDecoder.cs b/Storage/Internal/Codec/LCDecoder.cs index 06d0a50..b5acfa2 100644 --- a/Storage/Internal/Codec/LCDecoder.cs +++ b/Storage/Internal/Codec/LCDecoder.cs @@ -4,8 +4,8 @@ using System.Collections.Generic; using LeanCloud.Storage.Internal.Object; namespace LeanCloud.Storage.Internal.Codec { - internal static class LCDecoder { - internal static object Decode(object obj) { + public static class LCDecoder { + public static object Decode(object obj) { if (obj is IDictionary dict) { if (dict.Contains("__type")) { string type = dict["__type"].ToString(); diff --git a/Storage/Internal/Codec/LCEncoder.cs b/Storage/Internal/Codec/LCEncoder.cs index efe49c1..5af75bf 100644 --- a/Storage/Internal/Codec/LCEncoder.cs +++ b/Storage/Internal/Codec/LCEncoder.cs @@ -5,8 +5,8 @@ using LeanCloud.Storage.Internal.Operation; using LeanCloud.Storage.Internal.Query; namespace LeanCloud.Storage.Internal.Codec { - internal static class LCEncoder { - internal static object Encode(object obj) { + public static class LCEncoder { + public static object Encode(object obj) { if (obj is DateTime dateTime) { return EncodeDateTime(dateTime); } else if (obj is byte[] bytes) { diff --git a/Storage/Internal/File/LCAWSUploader.cs b/Storage/Internal/File/LCAWSUploader.cs index fba5d99..d5484c9 100644 --- a/Storage/Internal/File/LCAWSUploader.cs +++ b/Storage/Internal/File/LCAWSUploader.cs @@ -33,13 +33,13 @@ namespace LeanCloud.Storage.Internal.File { MaxAge = TimeSpan.FromMilliseconds(31536000) }; request.Content.Headers.ContentType = new MediaTypeHeaderValue(mimeType); - HttpUtils.PrintRequest(client, request); + LCHttpUtils.PrintRequest(client, request); HttpResponseMessage response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead); request.Dispose(); string resultString = await response.Content.ReadAsStringAsync(); response.Dispose(); - HttpUtils.PrintResponse(response, resultString); + LCHttpUtils.PrintResponse(response, resultString); HttpStatusCode statusCode = response.StatusCode; diff --git a/Storage/Internal/File/LCQiniuUploader.cs b/Storage/Internal/File/LCQiniuUploader.cs index 69310ca..69459ff 100644 --- a/Storage/Internal/File/LCQiniuUploader.cs +++ b/Storage/Internal/File/LCQiniuUploader.cs @@ -36,13 +36,13 @@ namespace LeanCloud.Storage.Internal.File { Content = content }; HttpClient client = new HttpClient(); - HttpUtils.PrintRequest(client, request); + LCHttpUtils.PrintRequest(client, request); HttpResponseMessage response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead); request.Dispose(); string resultString = await response.Content.ReadAsStringAsync(); response.Dispose(); - HttpUtils.PrintResponse(response, resultString); + LCHttpUtils.PrintResponse(response, resultString); HttpStatusCode statusCode = response.StatusCode; } diff --git a/Storage/Internal/Http/LCHttpClient.cs b/Storage/Internal/Http/LCHttpClient.cs index 238e416..9e9e306 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; @@ -22,23 +22,19 @@ namespace LeanCloud.Storage.Internal.Http { readonly string apiVersion; - readonly AppRouter appRouter; - readonly HttpClient client; 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; this.sdkVersion = sdkVersion; this.apiVersion = apiVersion; - appRouter = new AppRouter(appId, server); - client = new HttpClient(); - ProductHeaderValue product = new ProductHeaderValue("LeanCloud-CSharp-SDK", LeanCloud.SDKVersion); + ProductHeaderValue product = new ProductHeaderValue("LeanCloud-CSharp-SDK", sdkVersion); client.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue(product)); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); client.DefaultRequestHeaders.Add("X-LC-Id", appId); @@ -46,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); @@ -56,22 +52,22 @@ namespace LeanCloud.Storage.Internal.Http { }; await FillHeaders(request.Headers, headers); - HttpUtils.PrintRequest(client, request); + LCHttpUtils.PrintRequest(client, request); HttpResponseMessage response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead); request.Dispose(); string resultString = await response.Content.ReadAsStringAsync(); response.Dispose(); - HttpUtils.PrintResponse(response, resultString); + LCHttpUtils.PrintResponse(response, resultString); if (response.IsSuccessStatusCode) { - T ret = JsonConvert.DeserializeObject(resultString, new LeanCloudJsonConverter()); + T ret = JsonConvert.DeserializeObject(resultString, new LCJsonConverter()); return ret; } throw HandleErrorResponse(response.StatusCode, resultString); } - internal async Task Post(string path, + public async Task Post(string path, Dictionary headers = null, Dictionary data = null, Dictionary queryParams = null) { @@ -89,22 +85,22 @@ namespace LeanCloud.Storage.Internal.Http { requestContent.Headers.ContentType = new MediaTypeHeaderValue("application/json"); request.Content = requestContent; } - HttpUtils.PrintRequest(client, request, content); + LCHttpUtils.PrintRequest(client, request, content); HttpResponseMessage response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead); request.Dispose(); string resultString = await response.Content.ReadAsStringAsync(); response.Dispose(); - HttpUtils.PrintResponse(response, resultString); + LCHttpUtils.PrintResponse(response, resultString); if (response.IsSuccessStatusCode) { - T ret = JsonConvert.DeserializeObject(resultString, new LeanCloudJsonConverter()); + T ret = JsonConvert.DeserializeObject(resultString, new LCJsonConverter()); return ret; } throw HandleErrorResponse(response.StatusCode, resultString); } - internal async Task Put(string path, + public async Task Put(string path, Dictionary headers = null, Dictionary data = null, Dictionary queryParams = null) { @@ -122,22 +118,22 @@ namespace LeanCloud.Storage.Internal.Http { requestContent.Headers.ContentType = new MediaTypeHeaderValue("application/json"); request.Content = requestContent; } - HttpUtils.PrintRequest(client, request, content); + LCHttpUtils.PrintRequest(client, request, content); HttpResponseMessage response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead); request.Dispose(); string resultString = await response.Content.ReadAsStringAsync(); response.Dispose(); - HttpUtils.PrintResponse(response, resultString); + LCHttpUtils.PrintResponse(response, resultString); if (response.IsSuccessStatusCode) { - T ret = JsonConvert.DeserializeObject(resultString, new LeanCloudJsonConverter()); + T ret = JsonConvert.DeserializeObject(resultString, new LCJsonConverter()); return ret; } throw HandleErrorResponse(response.StatusCode, resultString); } - internal async Task Delete(string path) { + public async Task Delete(string path) { string url = await BuildUrl(path); HttpRequestMessage request = new HttpRequestMessage { RequestUri = new Uri(url), @@ -145,16 +141,16 @@ namespace LeanCloud.Storage.Internal.Http { }; await FillHeaders(request.Headers); - HttpUtils.PrintRequest(client, request); + LCHttpUtils.PrintRequest(client, request); HttpResponseMessage response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead); request.Dispose(); string resultString = await response.Content.ReadAsStringAsync(); response.Dispose(); - HttpUtils.PrintResponse(response, resultString); + LCHttpUtils.PrintResponse(response, resultString); if (response.IsSuccessStatusCode) { - Dictionary ret = JsonConvert.DeserializeObject>(resultString, new LeanCloudJsonConverter()); + Dictionary ret = JsonConvert.DeserializeObject>(resultString, new LCJsonConverter()); return; } throw HandleErrorResponse(response.StatusCode, resultString); @@ -165,17 +161,17 @@ namespace LeanCloud.Storage.Internal.Http { string message = responseContent; try { // 尝试获取 LeanCloud 返回错误信息 - Dictionary error = JsonConvert.DeserializeObject>(responseContent, new LeanCloudJsonConverter()); + Dictionary error = JsonConvert.DeserializeObject>(responseContent, new LCJsonConverter()); code = (int)error["code"]; message = error["error"].ToString(); } catch (Exception e) { - Logger.Error(e.Message); + LCLogger.Error(e); } return new LCException(code, message); } async Task BuildUrl(string path, Dictionary queryParams = null) { - string apiServer = await appRouter.GetApiServer(); + string apiServer = await LCApplication.AppRouter.GetApiServer(); string url = $"{apiServer}/{apiVersion}/{path}"; if (queryParams != null) { IEnumerable queryPairs = queryParams.Select(kv => $"{kv.Key}={kv.Value}"); diff --git a/Storage/Internal/Http/LeanCloudJsonConverter.cs b/Storage/Internal/Http/LCJsonConverter.cs similarity index 95% rename from Storage/Internal/Http/LeanCloudJsonConverter.cs rename to Storage/Internal/Http/LCJsonConverter.cs index ed5fd05..d79bd9d 100644 --- a/Storage/Internal/Http/LeanCloudJsonConverter.cs +++ b/Storage/Internal/Http/LCJsonConverter.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using Newtonsoft.Json; namespace LeanCloud.Storage.Internal { - public class LeanCloudJsonConverter : JsonConverter { + public class LCJsonConverter : JsonConverter { public override bool CanConvert(Type objectType) { return objectType == typeof(object); } diff --git a/Storage/Internal/Query/ILCQueryCondition.cs b/Storage/Internal/Query/ILCQueryCondition.cs index 8dcd68d..a08650f 100644 --- a/Storage/Internal/Query/ILCQueryCondition.cs +++ b/Storage/Internal/Query/ILCQueryCondition.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; namespace LeanCloud.Storage.Internal.Query { - internal interface ILCQueryCondition { + public interface ILCQueryCondition { bool Equals(ILCQueryCondition other); Dictionary Encode(); } diff --git a/Storage/Internal/Query/LCCompositionalCondition.cs b/Storage/Internal/Query/LCCompositionalCondition.cs index 917b2bf..74a8039 100644 --- a/Storage/Internal/Query/LCCompositionalCondition.cs +++ b/Storage/Internal/Query/LCCompositionalCondition.cs @@ -4,9 +4,9 @@ using Newtonsoft.Json; using LeanCloud.Storage.Internal.Codec; namespace LeanCloud.Storage.Internal.Query { - internal class LCCompositionalCondition : ILCQueryCondition { - internal const string And = "$and"; - internal const string Or = "$or"; + public class LCCompositionalCondition : ILCQueryCondition { + public const string And = "$and"; + public const string Or = "$or"; readonly string composition; @@ -16,93 +16,93 @@ namespace LeanCloud.Storage.Internal.Query { HashSet includes; HashSet selectedKeys; - internal int Skip { + public int Skip { get; set; } - internal int Limit { + public int Limit { get; set; } - internal LCCompositionalCondition(string composition = And) { + public LCCompositionalCondition(string composition = And) { this.composition = composition; Skip = 0; Limit = 30; } // 查询条件 - internal void WhereEqualTo(string key, object value) { + public void WhereEqualTo(string key, object value) { Add(new LCEqualCondition(key, value)); } - internal void WhereNotEqualTo(string key, object value) { + public void WhereNotEqualTo(string key, object value) { AddOperation(key, "$ne", value); } - internal void WhereContainedIn(string key, IEnumerable values) { + public void WhereContainedIn(string key, IEnumerable values) { AddOperation(key, "$in", values); } - internal void WhereNotContainedIn(string key, IEnumerable values) { + public void WhereNotContainedIn(string key, IEnumerable values) { AddOperation(key, "nin", values); } - internal void WhereContainsAll(string key, IEnumerable values) { + public void WhereContainsAll(string key, IEnumerable values) { AddOperation(key, "$all", values); } - internal void WhereExists(string key) { + public void WhereExists(string key) { AddOperation(key, "$exists", true); } - internal void WhereDoesNotExist(string key) { + public void WhereDoesNotExist(string key) { AddOperation(key, "$exists", false); } - internal void WhereSizeEqualTo(string key, int size) { + public void WhereSizeEqualTo(string key, int size) { AddOperation(key, "$size", size); } - internal void WhereGreaterThan(string key, object value) { + public void WhereGreaterThan(string key, object value) { AddOperation(key, "$gt", value); } - internal void WhereGreaterThanOrEqualTo(string key, object value) { + public void WhereGreaterThanOrEqualTo(string key, object value) { AddOperation(key, "$gte", value); } - internal void WhereLessThan(string key, object value) { + public void WhereLessThan(string key, object value) { AddOperation(key, "$lt", value); } - internal void WhereLessThanOrEqualTo(string key, object value) { + public void WhereLessThanOrEqualTo(string key, object value) { AddOperation(key, "$lte", value); } - internal void WhereNear(string key, LCGeoPoint point) { + public void WhereNear(string key, LCGeoPoint point) { AddOperation(key, "$nearSphere", point); } - internal void WhereWithinGeoBox(string key, LCGeoPoint southwest, LCGeoPoint northeast) { + public void WhereWithinGeoBox(string key, LCGeoPoint southwest, LCGeoPoint northeast) { Dictionary value = new Dictionary { { "$box", new List { southwest, northeast } } }; AddOperation(key, "$within", value); } - internal void WhereRelatedTo(LCObject parent, string key) { + public void WhereRelatedTo(LCObject parent, string key) { Add(new LCRelatedCondition(parent, key)); } - internal void WhereStartsWith(string key, string prefix) { + public void WhereStartsWith(string key, string prefix) { AddOperation(key, "$regex", $"^{prefix}.*"); } - internal void WhereEndsWith(string key, string suffix) { + public void WhereEndsWith(string key, string suffix) { AddOperation(key, "$regex", $".*{suffix}$"); } - internal void WhereContains(string key, string subString) { + public void WhereContains(string key, string subString) { AddOperation(key, "$regex", $".*{subString}.*"); } @@ -111,7 +111,7 @@ namespace LeanCloud.Storage.Internal.Query { Add(cond); } - internal void Add(ILCQueryCondition cond) { + public void Add(ILCQueryCondition cond) { if (cond == null) { return; } @@ -123,25 +123,25 @@ namespace LeanCloud.Storage.Internal.Query { } // 筛选条件 - internal void OrderBy(string key) { + public void OrderBy(string key) { if (orderByList == null) { orderByList = new List(); } orderByList.Add(key); } - internal void OrderByDescending(string key) { + public void OrderByDescending(string key) { OrderBy($"-{key}"); } - internal void Include(string key) { + public void Include(string key) { if (includes == null) { includes = new HashSet(); } includes.Add(key); } - internal void Select(string key) { + public void Select(string key) { if (selectedKeys == null) { selectedKeys = new HashSet(); } @@ -165,7 +165,7 @@ namespace LeanCloud.Storage.Internal.Query { }; } - internal Dictionary BuildParams() { + public Dictionary BuildParams() { Dictionary dict = new Dictionary { { "skip", Skip }, { "limit", Limit } @@ -185,7 +185,7 @@ namespace LeanCloud.Storage.Internal.Query { return dict; } - internal string BuildWhere() { + public string BuildWhere() { if (conditionList == null || conditionList.Count == 0) { return null; } diff --git a/Storage/Internal/Query/LCEqualCondition.cs b/Storage/Internal/Query/LCEqualCondition.cs index 57dab0d..cefe9a4 100644 --- a/Storage/Internal/Query/LCEqualCondition.cs +++ b/Storage/Internal/Query/LCEqualCondition.cs @@ -2,11 +2,11 @@ using LeanCloud.Storage.Internal.Codec; namespace LeanCloud.Storage.Internal.Query { - internal class LCEqualCondition : ILCQueryCondition { + public class LCEqualCondition : ILCQueryCondition { readonly string key; readonly object value; - internal LCEqualCondition(string key, object value) { + public LCEqualCondition(string key, object value) { this.key = key; this.value = value; } diff --git a/Storage/Internal/Query/LCOperationCondition.cs b/Storage/Internal/Query/LCOperationCondition.cs index 79d5763..1a38c8b 100644 --- a/Storage/Internal/Query/LCOperationCondition.cs +++ b/Storage/Internal/Query/LCOperationCondition.cs @@ -2,12 +2,12 @@ using LeanCloud.Storage.Internal.Codec; namespace LeanCloud.Storage.Internal.Query { - internal class LCOperationCondition : ILCQueryCondition { + public class LCOperationCondition : ILCQueryCondition { readonly string key; readonly string op; readonly object value; - internal LCOperationCondition(string key, string op, object value) { + public LCOperationCondition(string key, string op, object value) { this.key = key; this.op = op; this.value = value; diff --git a/Storage/Internal/Query/LCRelatedCondition.cs b/Storage/Internal/Query/LCRelatedCondition.cs index 6e2d2b1..3dd92d7 100644 --- a/Storage/Internal/Query/LCRelatedCondition.cs +++ b/Storage/Internal/Query/LCRelatedCondition.cs @@ -2,11 +2,11 @@ using LeanCloud.Storage.Internal.Codec; namespace LeanCloud.Storage.Internal.Query { - internal class LCRelatedCondition : ILCQueryCondition { + public class LCRelatedCondition : ILCQueryCondition { readonly LCObject parent; readonly string key; - internal LCRelatedCondition(LCObject parent, string key) { + public LCRelatedCondition(LCObject parent, string key) { this.parent = parent; this.key = key; } diff --git a/Storage/LeanCloud.cs b/Storage/LCApplication.cs similarity index 58% rename from Storage/LeanCloud.cs rename to Storage/LCApplication.cs index fd15751..60e9a9d 100644 --- a/Storage/LeanCloud.cs +++ b/Storage/LCApplication.cs @@ -1,4 +1,5 @@ using System; +using LeanCloud.Common; using LeanCloud.Storage; using LeanCloud.Storage.Internal.Http; @@ -6,18 +7,30 @@ namespace LeanCloud { /// /// LeanCloud 全局接口 /// - public class LeanCloud { + public class LCApplication { // SDK 版本号,用于 User-Agent 统计 internal const string SDKVersion = "0.2.2"; // 接口版本号,用于接口版本管理 internal const string APIVersion = "1.1"; + public static string AppId { + get; private set; + } + + public static string AppKey { + get; private set; + } + public static bool UseProduction { get; set; } - internal static LCHttpClient HttpClient { + public static LCAppRouter AppRouter { + get; private set; + } + + public static LCHttpClient HttpClient { get; private set; } @@ -28,10 +41,16 @@ namespace LeanCloud { if (string.IsNullOrEmpty(appKey)) { throw new ArgumentException(nameof(appKey)); } + + AppId = appId; + AppKey = appKey; + // 注册 LeanCloud 内部子类化类型 - LCObject.RegisterSubclass(LCUser.CLASS_NAME, () => new LCUser()); - LCObject.RegisterSubclass(LCRole.CLASS_NAME, () => new LCRole()); - LCObject.RegisterSubclass(LCFile.CLASS_NAME, () => new LCFile()); + LCObject.RegisterSubclass(LCUser.CLASS_NAME, () => new LCUser()); + LCObject.RegisterSubclass(LCRole.CLASS_NAME, () => new LCRole()); + LCObject.RegisterSubclass(LCFile.CLASS_NAME, () => new LCFile()); + + AppRouter = new LCAppRouter(appId, server); HttpClient = new LCHttpClient(appId, appKey, server, SDKVersion, APIVersion); } diff --git a/Storage/LCCloud.cs b/Storage/LCCloud.cs index 904e959..830c8e0 100644 --- a/Storage/LCCloud.cs +++ b/Storage/LCCloud.cs @@ -15,13 +15,13 @@ namespace LeanCloud.Storage { /// public static async Task> Run(string name, Dictionary parameters = null) { string path = $"functions/{name}"; - Dictionary response = await LeanCloud.HttpClient.Post>(path, data: parameters); + Dictionary response = await LCApplication.HttpClient.Post>(path, data: parameters); return response; } public static async Task RPC(string name, Dictionary parameters = null) { string path = $"call/{name}"; - Dictionary response = await LeanCloud.HttpClient.Post>(path, data: parameters); + Dictionary response = await LCApplication.HttpClient.Post>(path, data: parameters); return LCDecoder.Decode(response["result"]); } } diff --git a/Storage/LCFile.cs b/Storage/LCFile.cs index 7902e11..19e1964 100644 --- a/Storage/LCFile.cs +++ b/Storage/LCFile.cs @@ -101,7 +101,7 @@ namespace LeanCloud.Storage { return; } string path = $"files/{ObjectId}"; - await LeanCloud.HttpClient.Delete(path); + await LCApplication.HttpClient.Delete(path); } public string GetThumbnailUrl(int width, int height, int quality = 100, bool scaleToFit = true, string format = "png") { @@ -117,7 +117,7 @@ namespace LeanCloud.Storage { { "mime_type", MimeType }, { "metaData", MetaData } }; - return await LeanCloud.HttpClient.Post>("fileTokens", data: data); + return await LCApplication.HttpClient.Post>("fileTokens", data: data); } public static LCQuery GetQuery() { diff --git a/Storage/LCObject.cs b/Storage/LCObject.cs index 810ed9b..c61cd33 100644 --- a/Storage/LCObject.cs +++ b/Storage/LCObject.cs @@ -86,7 +86,7 @@ namespace LeanCloud.Storage { if (string.IsNullOrEmpty(objectId)) { throw new ArgumentNullException(nameof(objectId)); } - LCObject obj = new LCObject(className); + LCObject obj = Create(className); obj.data.ObjectId = objectId; obj.isNew = false; return obj; @@ -311,7 +311,7 @@ namespace LeanCloud.Storage { { "requests", LCEncoder.Encode(requestList) } }; - List> results = await LeanCloud.HttpClient.Post>>("batch", data: data); + List> results = await LCApplication.HttpClient.Post>>("batch", data: data); List resultList = results.Select(item => { if (item.TryGetValue("error", out object error)) { Dictionary err = error as Dictionary; @@ -349,8 +349,8 @@ namespace LeanCloud.Storage { queryParams["where"] = query.BuildWhere(); } Dictionary response = ObjectId == null ? - await LeanCloud.HttpClient.Post>(path, data: LCEncoder.Encode(operationDict) as Dictionary, queryParams: queryParams) : - await LeanCloud.HttpClient.Put>(path, data: LCEncoder.Encode(operationDict) as Dictionary, queryParams: queryParams); + await LCApplication.HttpClient.Post>(path, data: LCEncoder.Encode(operationDict) as Dictionary, queryParams: queryParams) : + await LCApplication.HttpClient.Put>(path, data: LCEncoder.Encode(operationDict) as Dictionary, queryParams: queryParams); LCObjectData data = LCObjectData.Decode(response); Merge(data); return this; @@ -375,7 +375,7 @@ namespace LeanCloud.Storage { return; } string path = $"classes/{ClassName}/{ObjectId}"; - await LeanCloud.HttpClient.Delete(path); + await LCApplication.HttpClient.Delete(path); } public static async Task DeleteAll(List objectList) { @@ -385,7 +385,7 @@ namespace LeanCloud.Storage { IEnumerable objects = objectList.Where(item => item.ObjectId != null); HashSet objectSet = new HashSet(objects); List> requestList = objectSet.Select(item => { - string path = $"/{LeanCloud.APIVersion}/classes/{item.ClassName}/{item.ObjectId}"; + string path = $"/{LCApplication.APIVersion}/classes/{item.ClassName}/{item.ObjectId}"; return new Dictionary { { "path", path }, { "method", "DELETE" } @@ -394,7 +394,7 @@ namespace LeanCloud.Storage { Dictionary data = new Dictionary { { "requests", LCEncoder.Encode(requestList) } }; - await LeanCloud.HttpClient.Post>("batch", data: data); + await LCApplication.HttpClient.Post>("batch", data: data); } public async Task Fetch(IEnumerable keys = null, IEnumerable includes = null) { @@ -406,13 +406,13 @@ namespace LeanCloud.Storage { queryParams["include"] = string.Join(",", includes); } string path = $"classes/{ClassName}/{ObjectId}"; - Dictionary response = await LeanCloud.HttpClient.Get>(path, queryParams: queryParams); + Dictionary response = await LCApplication.HttpClient.Get>(path, queryParams: queryParams); LCObjectData objectData = LCObjectData.Decode(response); Merge(objectData); return this; } - public static void RegisterSubclass(string className, Func constructor) where T : LCObject { + public static void RegisterSubclass(string className, Func constructor) where T : LCObject { Type classType = typeof(T); LCSubclassInfo subclassInfo = new LCSubclassInfo(className, classType, constructor); subclassNameDict[className] = subclassInfo; diff --git a/Storage/LCQuery.cs b/Storage/LCQuery.cs index dce8148..78ae9df 100644 --- a/Storage/LCQuery.cs +++ b/Storage/LCQuery.cs @@ -274,7 +274,7 @@ namespace LeanCloud.Storage { Dictionary parameters = BuildParams(); parameters["limit"] = 0; parameters["count"] = 1; - Dictionary ret = await LeanCloud.HttpClient.Get>(path, queryParams: parameters); + Dictionary ret = await LCApplication.HttpClient.Get>(path, queryParams: parameters); return (int)ret["count"]; } @@ -297,7 +297,7 @@ namespace LeanCloud.Storage { public async Task> Find() { string path = $"classes/{ClassName}"; Dictionary parameters = BuildParams(); - Dictionary response = await LeanCloud.HttpClient.Get>(path, queryParams: parameters); + Dictionary response = await LCApplication.HttpClient.Get>(path, queryParams: parameters); List results = response["results"] as List; List list = new List(); foreach (object item in results) { diff --git a/Storage/LCUser.cs b/Storage/LCUser.cs index b8355a6..ae24f13 100644 --- a/Storage/LCUser.cs +++ b/Storage/LCUser.cs @@ -116,7 +116,7 @@ namespace LeanCloud.Storage { Dictionary data = new Dictionary { { "mobilePhoneNumber", mobile } }; - await LeanCloud.HttpClient.Post>("requestLoginSmsCode", data: data); + await LCApplication.HttpClient.Post>("requestLoginSmsCode", data: data); } /// @@ -136,7 +136,7 @@ namespace LeanCloud.Storage { { "mobilePhoneNumber", mobile }, { "smsCode", code } }; - Dictionary response = await LeanCloud.HttpClient.Post>("usersByMobilePhone", data: data); + Dictionary response = await LCApplication.HttpClient.Post>("usersByMobilePhone", data: data); LCObjectData objectData = LCObjectData.Decode(response); currentUser = new LCUser(objectData); return currentUser; @@ -346,7 +346,7 @@ namespace LeanCloud.Storage { Dictionary data = new Dictionary { { "email", email } }; - await LeanCloud.HttpClient.Post>("requestEmailVerify", data: data); + await LCApplication.HttpClient.Post>("requestEmailVerify", data: data); } /// @@ -361,7 +361,7 @@ namespace LeanCloud.Storage { Dictionary data = new Dictionary { { "mobilePhoneNumber", mobile } }; - await LeanCloud.HttpClient.Post>("requestMobilePhoneVerify", data: data); + await LCApplication.HttpClient.Post>("requestMobilePhoneVerify", data: data); } /// @@ -381,7 +381,7 @@ namespace LeanCloud.Storage { Dictionary data = new Dictionary { { "mobilePhoneNumber", mobile } }; - await LeanCloud.HttpClient.Post>(path, data: data); + await LCApplication.HttpClient.Post>(path, data: data); } /// @@ -396,7 +396,7 @@ namespace LeanCloud.Storage { Dictionary headers = new Dictionary { { "X-LC-Session", sessionToken } }; - Dictionary response = await LeanCloud.HttpClient.Get>("users/me", + Dictionary response = await LCApplication.HttpClient.Get>("users/me", headers: headers); LCObjectData objectData = LCObjectData.Decode(response); currentUser = new LCUser(objectData); @@ -415,7 +415,7 @@ namespace LeanCloud.Storage { Dictionary data = new Dictionary { { "email", email } }; - await LeanCloud.HttpClient.Post>("requestPasswordReset", + await LCApplication.HttpClient.Post>("requestPasswordReset", data: data); } @@ -431,7 +431,7 @@ namespace LeanCloud.Storage { Dictionary data = new Dictionary { { "mobilePhoneNumber", mobile } }; - await LeanCloud.HttpClient.Post>("requestPasswordResetBySmsCode", + await LCApplication.HttpClient.Post>("requestPasswordResetBySmsCode", data: data); } @@ -456,7 +456,7 @@ namespace LeanCloud.Storage { { "mobilePhoneNumber", mobile }, { "password", newPassword } }; - await LeanCloud.HttpClient.Put>($"resetPasswordBySmsCode/{code}", + await LCApplication.HttpClient.Put>($"resetPasswordBySmsCode/{code}", data: data); } @@ -477,7 +477,7 @@ namespace LeanCloud.Storage { { "old_password", oldPassword }, { "new_password", newPassword } }; - Dictionary response = await LeanCloud.HttpClient.Put>( + Dictionary response = await LCApplication.HttpClient.Put>( $"users/{ObjectId}/updatePassword", data:data); LCObjectData objectData = LCObjectData.Decode(response); Merge(objectData); @@ -502,7 +502,7 @@ namespace LeanCloud.Storage { return false; } try { - await LeanCloud.HttpClient.Get>("users/me"); + await LCApplication.HttpClient.Get>("users/me"); return true; } catch (Exception) { return false; @@ -525,7 +525,7 @@ namespace LeanCloud.Storage { } static async Task Login(Dictionary data) { - Dictionary response = await LeanCloud.HttpClient.Post>("login", data: data); + Dictionary response = await LCApplication.HttpClient.Post>("login", data: data); LCObjectData objectData = LCObjectData.Decode(response); currentUser = new LCUser(objectData); return currentUser; @@ -536,7 +536,7 @@ namespace LeanCloud.Storage { { authType, data } }; string path = failOnNotExist ? "users?failOnNotExist=true" : "users"; - Dictionary response = await LeanCloud.HttpClient.Post>(path, data: new Dictionary { + Dictionary response = await LCApplication.HttpClient.Post>(path, data: new Dictionary { { "authData", authData } }); LCObjectData objectData = LCObjectData.Decode(response); diff --git a/Test/Realtime.Test/Client.cs b/Test/Realtime.Test/Client.cs new file mode 100644 index 0000000..9669bea --- /dev/null +++ b/Test/Realtime.Test/Client.cs @@ -0,0 +1,135 @@ +using NUnit.Framework; +using System; +using System.Threading.Tasks; +using System.Collections.ObjectModel; +using LeanCloud; +using LeanCloud.Common; +using LeanCloud.Realtime; +using LeanCloud.Storage; + +using static NUnit.Framework.TestContext; + +namespace Realtime.Test { + public class Client { + [SetUp] + public void SetUp() { + LCLogger.LogDelegate += Utils.Print; + LCApplication.Initialize("ikGGdRE2YcVOemAaRbgp1xGJ-gzGzoHsz", "NUKmuRbdAhg1vrb2wexYo1jo", "https://ikggdre2.lc-cn-n1-shared.com"); + } + + [TearDown] + public void TearDown() { + LCLogger.LogDelegate -= Utils.Print; + } + + [Test] + public async Task OpenAndClose() { + LCIMClient client = new LCIMClient("c1"); + await client.Open(); + await client.Close(); + } + + [Test] + public async Task OpenAndCloseByLCUser() { + LCUser user = await LCUser.Login("hello", "world"); + LCIMClient client = new LCIMClient(user); + await client.Open(); + await client.Close(); + } + + [Test] + public async Task CreateConversation() { + TaskCompletionSource tcs = new TaskCompletionSource(); + + string clientId = Guid.NewGuid().ToString(); + LCIMClient client = new LCIMClient(clientId); + + await client.Open(); + + client.OnInvited = (conv, initBy) => { + WriteLine($"on invited: {initBy}"); + WriteLine(conv.CreatorId); + }; + + client.OnMembersJoined = (conv, memberList, initBy) => { + WriteLine($"on members joined: {initBy}"); + foreach (string memberId in conv.MemberIds) { + WriteLine(memberId); + } + tcs.SetResult(null); + }; + + string name = Guid.NewGuid().ToString(); + LCIMConversation conversation = await client.CreateConversation(new string[] { "world" }, name: name, unique: false); + + await tcs.Task; + } + + [Test] + public async Task CreateChatRoom() { + TaskCompletionSource tcs = new TaskCompletionSource(); + + string clientId = Guid.NewGuid().ToString(); + LCIMClient client = new LCIMClient(clientId); + + await client.Open(); + + client.OnInvited = (conv, initBy) => { + WriteLine($"on invited: {initBy}"); + }; + + string name = Guid.NewGuid().ToString(); + LCIMConversation conversation = await client.CreateChatRoom(name); + + string visitorId = Guid.NewGuid().ToString(); + LCIMClient visitor = new LCIMClient(visitorId); + + await visitor.Open(); + visitor.OnInvited = async (conv, initBy) => { + WriteLine($"on invited: {visitor.Id}"); + LCIMTextMessage textMessage = new LCIMTextMessage("hello, world"); + await conversation.Send(textMessage); + tcs.SetResult(null); + }; + + LCIMChatRoom chatRoom = await visitor.GetConversation(conversation.Id) as LCIMChatRoom; + await chatRoom.Join(); + + int count = await chatRoom.GetMembersCount(); + + ReadOnlyCollection onlineMembers = await chatRoom.GetOnlineMembers(); + Assert.GreaterOrEqual(onlineMembers.Count, 1); + foreach (string memberId in onlineMembers) { + WriteLine($"{memberId} online"); + } + + await client.Close(); + await visitor.Close(); + + await tcs.Task; + } + + [Test] + public async Task CreateTemporaryConversation() { + TaskCompletionSource tcs = new TaskCompletionSource(); + + string clientId = Guid.NewGuid().ToString(); + LCIMClient client = new LCIMClient(clientId); + + await client.Open(); + + client.OnInvited = (conv, initBy) => { + WriteLine($"on invited: {initBy}"); + }; + + client.OnMembersJoined = (conv, memberList, initBy) => { + WriteLine($"on members joined: {initBy}"); + tcs.SetResult(null); + }; + + await client.CreateTemporaryConversation(new string[] { "world" }); + + await tcs.Task; + } + } +} diff --git a/Test/Realtime.Test/Conversation.cs b/Test/Realtime.Test/Conversation.cs new file mode 100644 index 0000000..26ebeb6 --- /dev/null +++ b/Test/Realtime.Test/Conversation.cs @@ -0,0 +1,202 @@ +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using LeanCloud; +using LeanCloud.Common; +using LeanCloud.Realtime; + +using static NUnit.Framework.TestContext; + +namespace Realtime.Test { + public class Conversation { + private LCIMClient c1; + private LCIMClient c2; + private LCIMClient lean; + private LCIMConversation conversation; + + [SetUp] + public async Task SetUp() { + LCLogger.LogDelegate += Utils.Print; + LCApplication.Initialize("ikGGdRE2YcVOemAaRbgp1xGJ-gzGzoHsz", "NUKmuRbdAhg1vrb2wexYo1jo", "https://ikggdre2.lc-cn-n1-shared.com"); + c1 = new LCIMClient(Guid.NewGuid().ToString()); + await c1.Open(); + c2 = new LCIMClient(Guid.NewGuid().ToString()); + await c2.Open(); + lean = new LCIMClient("lean"); + await lean.Open(); + conversation = await c1.CreateConversation(new string[] { "lean", "cloud" }); + } + + [TearDown] + public async Task TearDown() { + await c1.Close(); + await c2.Close(); + await lean.Close(); + LCLogger.LogDelegate -= Utils.Print; + } + + [Test] + [Order(0)] + public async Task AddMember() { + TaskCompletionSource tcs = new TaskCompletionSource(); + c2.OnInvited = (conv, initBy) => { + WriteLine($"{c2.Id} is invited by {initBy}"); + tcs.SetResult(null); + }; + await conversation.AddMembers(new string[] { c2.Id }); + Assert.AreEqual(conversation.MemberIds.Count, 4); + await tcs.Task; + } + + [Test] + [Order(1)] + public async Task MuteMembers() { + TaskCompletionSource tcs = new TaskCompletionSource(); + bool f1 = false, f2 = false; + c1.OnMembersMuted = (conv, mutedMembers, initBy) => { + Assert.True(mutedMembers.Contains(lean.Id)); + Assert.True(conversation.MutedMemberIds.Contains(lean.Id)); + f1 = true; + if (f1 && f2) { + tcs.SetResult(null); + } + }; + lean.OnMuted = (conv, initBy) => { + WriteLine($"{lean.Id} is muted by {initBy}"); + f2 = true; + if (f1 && f2) { + tcs.SetResult(null); + } + }; + await conversation.MuteMembers(new string[] { "lean" }); + Assert.True(conversation.MutedMemberIds.Contains("lean")); + await tcs.Task; + } + + [Test] + [Order(2)] + public async Task UnmuteMembers() { + TaskCompletionSource tcs = new TaskCompletionSource(); + bool f1 = false, f2 = false; + c1.OnMembersUnmuted = (conv, unmutedMembers, initBy) => { + Assert.True(unmutedMembers.Contains(lean.Id)); + Assert.False(conversation.MutedMemberIds.Contains(lean.Id)); + f1 = true; + if (f1 && f2) { + tcs.SetResult(null); + } + }; + lean.OnUnmuted = (conv, initBy) => { + WriteLine($"{lean.Id} is unmuted by {initBy}"); + f2 = true; + if (f1 && f2) { + tcs.SetResult(null); + } + }; + await conversation.UnmuteMembers(new string[] { "lean" }); + Assert.False(conversation.MutedMemberIds.Contains("lean")); + await tcs.Task; + } + + [Test] + [Order(3)] + public async Task BlockMembers() { + TaskCompletionSource tcs = new TaskCompletionSource(); + bool f1 = false, f2 = false; + c1.OnMembersBlocked = (conv, blockedMembers, initBy) => { + Assert.True(blockedMembers.Contains(lean.Id)); + f1 = true; + if (f1 && f2) { + tcs.SetResult(null); + } + }; + lean.OnBlocked = (conv, initBy) => { + WriteLine($"{lean.Id} is blocked by {initBy}"); + f2 = true; + if (f1 && f2) { + tcs.SetResult(null); + } + }; + await conversation.BlockMembers(new string[] { "lean" }); + LCIMPageResult result = await conversation.QueryBlockedMembers(); + Assert.True(result.Results.Contains("lean")); + await tcs.Task; + } + + [Test] + [Order(4)] + public async Task UnblockMembers() { + TaskCompletionSource tcs = new TaskCompletionSource(); + bool f1 = false, f2 = false; + c1.OnMembersUnblocked = (conv, blockedMembers, initBy) => { + Assert.True(blockedMembers.Contains(lean.Id)); + f1 = true; + if (f1 && f2) { + tcs.SetResult(null); + } + }; + lean.OnUnblocked = (conv, initBy) => { + WriteLine($"{lean.Id} is unblocked by {initBy}"); + f2 = true; + if (f1 && f2) { + tcs.SetResult(null); + } + }; + await conversation.UnblockMembers(new string[] { "lean" }); + LCIMPageResult result = await conversation.QueryBlockedMembers(); + Assert.False(result.Results.Contains("lean")); + await tcs.Task; + } + + [Test] + [Order(5)] + public async Task UpdateRole() { + TaskCompletionSource tcs = new TaskCompletionSource(); + c1.OnMemberInfoUpdated = (conv, member, role, initBy) => { + WriteLine($"{member} is {role} by {initBy}"); + tcs.SetResult(null); + }; + await conversation.UpdateMemberRole("cloud", LCIMConversationMemberInfo.Manager); + LCIMConversationMemberInfo memberInfo = await conversation.GetMemberInfo("cloud"); + Assert.True(memberInfo.IsManager); + await tcs.Task; + } + + [Test] + [Order(6)] + public async Task RemoveMember() { + TaskCompletionSource tcs = new TaskCompletionSource(); + c2.OnKicked = (conv, initBy) => { + WriteLine($"{c2.Id} is kicked by {initBy}"); + tcs.SetResult(null); + }; + await conversation.RemoveMembers(new string[] { c2.Id }); + Assert.AreEqual(conversation.MemberIds.Count, 3); + await tcs.Task; + } + + [Test] + [Order(7)] + public async Task UpdateInfo() { + TaskCompletionSource tcs = new TaskCompletionSource(); + lean.OnConversationInfoUpdated = (conv, attrs, initBy) => { + Assert.AreEqual(conv.Name, "leancloud"); + Assert.AreEqual(conv["k1"], "v1"); + Assert.AreEqual(conv["k2"], "v2"); + Assert.AreEqual(attrs["k1"], "v1"); + Assert.AreEqual(attrs["k2"], "v2"); + tcs.SetResult(null); + }; + await conversation.UpdateInfo(new Dictionary { + { "name", "leancloud" }, + { "k1", "v1" }, + { "k2", "v2" } + }); + Assert.AreEqual(conversation.Name, "leancloud"); + Assert.AreEqual(conversation["k1"], "v1"); + Assert.AreEqual(conversation["k2"], "v2"); + await tcs.Task; + } + } +} diff --git a/Test/Realtime.Test/ConversationQuery.cs b/Test/Realtime.Test/ConversationQuery.cs new file mode 100644 index 0000000..4741ceb --- /dev/null +++ b/Test/Realtime.Test/ConversationQuery.cs @@ -0,0 +1,49 @@ +using NUnit.Framework; +using System.Collections.ObjectModel; +using System.Threading.Tasks; +using LeanCloud; +using LeanCloud.Common; +using LeanCloud.Realtime; + +namespace Realtime.Test { + public class ConversationQuery { + private string clientId = "hello123"; + private LCIMClient client; + + [SetUp] + public async Task SetUp() { + LCLogger.LogDelegate += Utils.Print; + LCApplication.Initialize("ikGGdRE2YcVOemAaRbgp1xGJ-gzGzoHsz", "NUKmuRbdAhg1vrb2wexYo1jo", "https://ikggdre2.lc-cn-n1-shared.com"); + client = new LCIMClient(clientId); + await client.Open(); + } + + [TearDown] + public async Task TearDown() { + LCLogger.LogDelegate -= Utils.Print; + await client.Close(); + } + + [Test] + public async Task QueryMyConversation() { + LCIMConversationQuery query = new LCIMConversationQuery(client); + ReadOnlyCollection conversations = await query.Find(); + Assert.Greater(conversations.Count, 0); + foreach (LCIMConversation conversation in conversations) { + Assert.True(conversation.MemberIds.Contains(clientId)); + } + } + + [Test] + public async Task QueryMemberConversation() { + string memberId = "cc1"; + LCIMConversationQuery query = new LCIMConversationQuery(client); + query.WhereEqualTo("m", memberId); + ReadOnlyCollection conversations = await query.Find(); + Assert.Greater(conversations.Count, 0); + foreach (LCIMConversation conversation in conversations) { + Assert.True(conversation.MemberIds.Contains(memberId)); + } + } + } +} diff --git a/Test/Realtime.Test/LocalSignatureFactory.cs b/Test/Realtime.Test/LocalSignatureFactory.cs new file mode 100644 index 0000000..db59c8e --- /dev/null +++ b/Test/Realtime.Test/LocalSignatureFactory.cs @@ -0,0 +1,97 @@ +using System; +using System.Text; +using System.Linq; +using System.Threading.Tasks; +using System.Collections.Generic; +using System.Security.Cryptography; +using LeanCloud.Realtime; +using LeanCloud; + +namespace Realtime.Test { + public class LocalSignatureFactory : ILCIMSignatureFactory { + const string MasterKey = "pyvbNSh5jXsuFQ3C8EgnIdhw"; + + public Task CreateConnectSignature(string clientId) { + long timestamp = DateTimeOffset.Now.ToUnixTimeSeconds(); + string nonce = NewNonce(); + string signature = GenerateSignature(LCApplication.AppId, clientId, string.Empty, timestamp.ToString(), nonce); + return Task.FromResult(new LCIMSignature { + Signature = signature, + Timestamp = timestamp, + Nonce = nonce + }); + } + + public Task CreateStartConversationSignature(string clientId, IEnumerable memberIds) { + string sortedMemberIds = string.Empty; + if (memberIds != null) { + List sortedMemberList = memberIds.ToList(); + sortedMemberList.Sort(); + sortedMemberIds = string.Join(":", sortedMemberList); + } + long timestamp = DateTimeOffset.Now.ToUnixTimeSeconds(); + string nonce = NewNonce(); + string signature = GenerateSignature(LCApplication.AppId, clientId, sortedMemberIds, timestamp.ToString(), nonce); + return Task.FromResult(new LCIMSignature { + Signature = signature, + Timestamp = timestamp, + Nonce = nonce + }); + } + + public Task CreateConversationSignature(string conversationId, string clientId, IEnumerable memberIds, string action) { + string sortedMemberIds = string.Empty; + if (memberIds != null) { + List sortedMemberList = memberIds.ToList(); + sortedMemberList.Sort(); + sortedMemberIds = string.Join(":", sortedMemberList); + } + long timestamp = DateTimeOffset.Now.ToUnixTimeSeconds(); + string nonce = NewNonce(); + string signature = GenerateSignature(LCApplication.AppId, clientId, conversationId, sortedMemberIds, timestamp.ToString(), nonce, action); + return Task.FromResult(new LCIMSignature { + Signature = signature, + Timestamp = timestamp, + Nonce = nonce + }); + } + + public Task CreateBlacklistSignature(string conversationId, string clientId, IEnumerable memberIds, string action) { + string sortedMemberIds = string.Empty; + if (memberIds != null) { + List sortedMemberList = memberIds.ToList(); + sortedMemberList.Sort(); + sortedMemberIds = string.Join(":", sortedMemberList); + } + long timestamp = DateTimeOffset.Now.ToUnixTimeSeconds(); + string nonce = NewNonce(); + string signature = GenerateSignature(LCApplication.AppId, clientId, conversationId, sortedMemberIds, timestamp.ToString(), nonce, action); + return Task.FromResult(new LCIMSignature { + Signature = signature, + Timestamp = timestamp, + Nonce = nonce + }); + } + + private static string SignSHA1(string key, string text) { + HMACSHA1 hmac = new HMACSHA1(Encoding.UTF8.GetBytes(key)); + byte[] bytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(text)); + string signature = BitConverter.ToString(bytes).Replace("-", string.Empty); + return signature; + } + + private static string NewNonce() { + byte[] bytes = new byte[10]; + using (RandomNumberGenerator generator = RandomNumberGenerator.Create()) { + generator.GetBytes(bytes); + } + return Convert.ToBase64String(bytes); + } + + private static string GenerateSignature(params string[] args) { + string text = string.Join(":", args); + string signature = SignSHA1(MasterKey, text); + return signature; + } + } +} diff --git a/Test/Realtime.Test/Message.cs b/Test/Realtime.Test/Message.cs new file mode 100644 index 0000000..4efe3aa --- /dev/null +++ b/Test/Realtime.Test/Message.cs @@ -0,0 +1,282 @@ +using NUnit.Framework; +using System; +using System.Collections.ObjectModel; +using System.Threading.Tasks; +using System.Collections.Generic; +using LeanCloud; +using LeanCloud.Common; +using LeanCloud.Storage; +using LeanCloud.Realtime; + +using static NUnit.Framework.TestContext; + +/// +/// Emoji 消息 +/// +class EmojiMessage : LCIMTypedMessage { + public const int EmojiMessageType = 1; + + public override int MessageType => EmojiMessageType; + + public string Ecode { + get { + return data["ecode"] as string; + } set { + data["ecode"] = value; + } + } +} + +namespace Realtime.Test { + public class Message { + private LCIMClient m1; + private LCIMClient m2; + + private LCIMConversation conversation; + + [SetUp] + public async Task SetUp() { + LCLogger.LogDelegate += Utils.Print; + LCApplication.Initialize("ikGGdRE2YcVOemAaRbgp1xGJ-gzGzoHsz", "NUKmuRbdAhg1vrb2wexYo1jo", "https://ikggdre2.lc-cn-n1-shared.com"); + m1 = new LCIMClient("m1"); + m2 = new LCIMClient("m2"); + await m1.Open(); + await m2.Open(); + conversation = await m1.CreateConversation(new string[] { "m2" }); + } + + [TearDown] + public async Task TearDown() { + await m1.Close(); + await m2.Close(); + LCLogger.LogDelegate -= Utils.Print; + } + + [Test] + [Order(0)] + public async Task Send() { + TaskCompletionSource tcs = new TaskCompletionSource(); + + int count = 0; + m2.OnMessage = (conv, msg) => { + WriteLine(msg.Id); + if (msg is LCIMImageMessage imageMsg) { + WriteLine($"-------- url: {imageMsg.Url}"); + count++; + } else if (msg is LCIMFileMessage fileMsg) { + WriteLine($"-------- name: {fileMsg.Format}"); + count++; + } else if (msg is LCIMTextMessage textMsg) { + WriteLine($"-------- text: {textMsg.Text}"); + count++; + } + if (count >= 3) { + tcs.SetResult(null); + } + }; + + LCIMTextMessage textMessage = new LCIMTextMessage("hello, world"); + await conversation.Send(textMessage); + Assert.NotNull(textMessage.Id); + + LCFile image = new LCFile("hello", "../../../../assets/hello.png"); + await image.Save(); + LCIMImageMessage imageMessage = new LCIMImageMessage(image); + await conversation.Send(imageMessage); + Assert.NotNull(imageMessage.Id); + + LCFile file = new LCFile("apk", "../../../../assets/test.apk"); + await file.Save(); + LCIMFileMessage fileMessage = new LCIMFileMessage(file); + await conversation.Send(fileMessage); + Assert.NotNull(fileMessage.Id); + + await tcs.Task; + } + + [Test] + [Order(1)] + public async Task AckAndRead() { + TaskCompletionSource tcs = new TaskCompletionSource(); + m2.OnMessage = async (conv, msg) => { + await conv.Read(); + }; + m1.OnMessageDelivered = (conv, msgId) => { + WriteLine($"{msgId} is delivered."); + }; + m1.OnMessageRead = (conv, msgId) => { + WriteLine($"{msgId} is read."); + tcs.SetResult(null); + }; + LCIMTextMessage textMessage = new LCIMTextMessage("hello"); + LCIMMessageSendOptions options = new LCIMMessageSendOptions { + Receipt = true + }; + await conversation.Send(textMessage, options); + + await tcs.Task; + } + + [Test] + [Order(2)] + public async Task Recall() { + TaskCompletionSource tcs = new TaskCompletionSource(); + m2.OnMessageRecalled = (conv, msgId) => { + WriteLine($"{msgId} is recalled."); + tcs.SetResult(null); + }; + LCIMTextMessage textMessage = new LCIMTextMessage("I will be recalled."); + await conversation.Send(textMessage); + await Task.Delay(1000); + await conversation.RecallMessage(textMessage); + + await tcs.Task; + } + + [Test] + [Order(3)] + public async Task Update() { + TaskCompletionSource tcs = new TaskCompletionSource(); + m2.OnMessageUpdated = (conv, msg) => { + Assert.True(msg is LCIMTextMessage); + LCIMTextMessage textMessage = msg as LCIMTextMessage; + Assert.AreEqual(textMessage.Text, "world"); + WriteLine($"{msg.Id} is updated"); + tcs.SetResult(null); + }; + LCIMTextMessage oldMessage = new LCIMTextMessage("hello"); + await conversation.Send(oldMessage); + await Task.Delay(1000); + LCIMTextMessage newMessage = new LCIMTextMessage("world"); + await conversation.UpdateMessage(oldMessage, newMessage); + + await tcs.Task; + } + + [Test] + [Order(4)] + public async Task Query() { + ReadOnlyCollection messages = await conversation.QueryMessages(); + Assert.Greater(messages.Count, 0); + foreach (LCIMMessage message in messages) { + Assert.AreEqual(message.ConversationId, conversation.Id); + Assert.NotNull(message.Id); + WriteLine(message.Id); + } + } + + [Test] + [Order(5)] + public async Task Unread() { + TaskCompletionSource tcs = new TaskCompletionSource(); + string clientId = Guid.NewGuid().ToString(); + LCIMClient client = new LCIMClient(clientId); + LCIMConversation conversation = await m1.CreateConversation(new string[] { clientId }); + + LCIMTextMessage textMessage = new LCIMTextMessage("hello"); + await conversation.Send(textMessage); + + client.OnUnreadMessagesCountUpdated = (convs) => { + foreach (LCIMConversation conv in convs) { + WriteLine($"unread count: {conv.Unread}"); + //Assert.AreEqual(conv.Unread, 1); + //Assert.True(conv.LastMessage is LCIMTextMessage); + //LCIMTextMessage textMsg = conv.LastMessage as LCIMTextMessage; + //Assert.AreEqual(textMsg.Text, "hello"); + } + }; + await client.Open(); + + client.OnMessage = (conv, msg) => { + WriteLine($"unread count: {conv.Unread}"); + Assert.AreEqual(conv.Unread, 2); + Assert.True(conv.LastMessage is LCIMTextMessage); + LCIMTextMessage textMsg = conv.LastMessage as LCIMTextMessage; + Assert.AreEqual(textMsg.Text, "world"); + tcs.SetResult(true); + }; + textMessage = new LCIMTextMessage("world"); + await conversation.Send(textMessage); + + await tcs.Task; + } + + [Test] + [Order(6)] + public async Task Attributes() { + TaskCompletionSource tcs = new TaskCompletionSource(); + m2.OnMessage = (conv, msg) => { + Assert.True(msg is LCIMTypedMessage); + LCIMTypedMessage typedMsg = msg as LCIMTypedMessage; + Assert.AreEqual(typedMsg["k1"], 123); + Assert.True((bool)typedMsg["k2"]); + Assert.AreEqual(typedMsg["k3"], "code"); + tcs.SetResult(null); + }; + LCIMTextMessage textMsg = new LCIMTextMessage("hi"); + textMsg["k1"] = 123; + textMsg["k2"] = true; + textMsg["k3"] = "code"; + await conversation.Send(textMsg); + + await tcs.Task; + } + + [Test] + [Order(7)] + public async Task Custom() { + TaskCompletionSource tcs = new TaskCompletionSource(); + // 注册自定义类型消息 + LCIMTypedMessage.Register(EmojiMessage.EmojiMessageType, + () => new EmojiMessage()); + m2.OnMessage = (conv, msg) => { + Assert.True(msg is EmojiMessage); + EmojiMessage emojiMsg = msg as EmojiMessage; + Assert.AreEqual(emojiMsg.Ecode, "#0123"); + tcs.SetResult(null); + }; + EmojiMessage emojiMessage = new EmojiMessage { + Ecode = "#0123" + }; + await conversation.Send(emojiMessage); + + await tcs.Task; + } + + [Test] + [Order(8)] + public async Task MentionList() { + TaskCompletionSource tcs = new TaskCompletionSource(); + m2.OnMessage = (conv, msg) => { + Assert.True(msg.Mentioned); + Assert.True(msg.MentionIdList.Contains(m2.Id)); + tcs.SetResult(null); + }; + + LCIMTextMessage textMessage = new LCIMTextMessage("hello") { + MentionIdList = new List { m2.Id } + }; + await conversation.Send(textMessage); + + await tcs.Task; + } + + [Test] + [Order(9)] + public async Task MentionAll() { + TaskCompletionSource tcs = new TaskCompletionSource(); + m2.OnMessage = (conv, msg) => { + Assert.True(msg.Mentioned); + Assert.True(msg.MentionAll); + tcs.SetResult(null); + }; + + LCIMTextMessage textMessage = new LCIMTextMessage("world") { + MentionAll = true + }; + await conversation.Send(textMessage); + + await tcs.Task; + } + } +} diff --git a/Test/Realtime.Test/Protobuf.cs b/Test/Realtime.Test/Protobuf.cs new file mode 100644 index 0000000..fdb8d33 --- /dev/null +++ b/Test/Realtime.Test/Protobuf.cs @@ -0,0 +1,29 @@ +using NUnit.Framework; +using LeanCloud.Realtime.Internal.Protocol; +using Google.Protobuf; + +namespace Realtime.Test { + public class Protobuf { + [Test] + public void Serialize() { + GenericCommand command = new GenericCommand { + Cmd = CommandType.Session, + Op = OpType.Open, + PeerId = "hello" + }; + SessionCommand session = new SessionCommand { + Code = 123 + }; + command.SessionMessage = session; + byte[] bytes = command.ToByteArray(); + TestContext.WriteLine($"length: {bytes.Length}"); + + command = GenericCommand.Parser.ParseFrom(bytes); + Assert.AreEqual(command.Cmd, CommandType.Session); + Assert.AreEqual(command.Op, OpType.Open); + Assert.AreEqual(command.PeerId, "hello"); + Assert.NotNull(command.SessionMessage); + Assert.AreEqual(command.SessionMessage.Code, 123); + } + } +} \ No newline at end of file diff --git a/Test/Realtime.Test/Realtime.Test.csproj b/Test/Realtime.Test/Realtime.Test.csproj new file mode 100644 index 0000000..bb33613 --- /dev/null +++ b/Test/Realtime.Test/Realtime.Test.csproj @@ -0,0 +1,20 @@ + + + + netcoreapp2.2 + + false + 0.1.0 + + + + + + + + + + + + + diff --git a/Test/Realtime.Test/Utils.cs b/Test/Realtime.Test/Utils.cs new file mode 100644 index 0000000..10a85a0 --- /dev/null +++ b/Test/Realtime.Test/Utils.cs @@ -0,0 +1,25 @@ +using System; +using LeanCloud; +using LeanCloud.Common; +using NUnit.Framework; + +namespace Realtime.Test { + public static class Utils { + internal static void Print(LCLogLevel level, string info) { + switch (level) { + case LCLogLevel.Debug: + TestContext.Out.WriteLine($"[DEBUG] {info}\n"); + break; + case LCLogLevel.Warn: + TestContext.Out.WriteLine($"[WARNING] {info}\n"); + break; + case LCLogLevel.Error: + TestContext.Out.WriteLine($"[ERROR] {info}\n"); + break; + default: + TestContext.Out.WriteLine(info); + break; + } + } + } +} diff --git a/Test/RealtimeApp/Program.cs b/Test/RealtimeApp/Program.cs new file mode 100644 index 0000000..01ef348 --- /dev/null +++ b/Test/RealtimeApp/Program.cs @@ -0,0 +1,39 @@ +using System; +using LeanCloud; +using LeanCloud.Realtime; + +using static System.Console; + +namespace RealtimeApp { + class Program { + static void Main(string[] args) { + Console.WriteLine("Hello World!"); + + SingleThreadSynchronizationContext.Run(async () => { + LCLogger.LogDelegate += Print; + LCApplication.Initialize("ikGGdRE2YcVOemAaRbgp1xGJ-gzGzoHsz", "NUKmuRbdAhg1vrb2wexYo1jo", "https://ikggdre2.lc-cn-n1-shared.com"); + + LCIMClient client = new LCIMClient("lean"); + await client.Open(); + //await client.Close(); + }); + } + + static void Print(LCLogLevel level, string info) { + switch (level) { + case LCLogLevel.Debug: + WriteLine($"[DEBUG] {DateTime.Now} {info}\n"); + break; + case LCLogLevel.Warn: + WriteLine($"[WARNING] {DateTime.Now} {info}\n"); + break; + case LCLogLevel.Error: + WriteLine($"[ERROR] {DateTime.Now} {info}\n"); + break; + default: + WriteLine(info); + break; + } + } + } +} diff --git a/Test/RealtimeApp/RealtimeApp.csproj b/Test/RealtimeApp/RealtimeApp.csproj new file mode 100644 index 0000000..075081d --- /dev/null +++ b/Test/RealtimeApp/RealtimeApp.csproj @@ -0,0 +1,13 @@ + + + + Exe + netcoreapp3.0 + + + + + + + + diff --git a/Test/RealtimeApp/SingleThreadSynchronizationContext.cs b/Test/RealtimeApp/SingleThreadSynchronizationContext.cs new file mode 100644 index 0000000..fdfb2c9 --- /dev/null +++ b/Test/RealtimeApp/SingleThreadSynchronizationContext.cs @@ -0,0 +1,43 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using System.Collections.Concurrent; +using System.Collections.Generic; + +namespace RealtimeApp { + /// + /// 单线程环境,用于控制台应用 await 返回 + /// + public class SingleThreadSynchronizationContext : SynchronizationContext { + private readonly BlockingCollection> queue = new BlockingCollection>(); + + public override void Post(SendOrPostCallback d, object state) { + queue.Add(new KeyValuePair(d, state)); + } + + public void RunOnCurrentThread() { + while (queue.TryTake(out KeyValuePair workItem, Timeout.Infinite)) { + workItem.Key(workItem.Value); + } + } + + public void Complete() { + queue.CompleteAdding(); + } + + public static void Run(Func func) { + SynchronizationContext prevContext = Current; + try { + SingleThreadSynchronizationContext syncContext = new SingleThreadSynchronizationContext(); + SetSynchronizationContext(syncContext); + + Task t = func(); + syncContext.RunOnCurrentThread(); + + t.GetAwaiter().GetResult(); + } finally { + SetSynchronizationContext(prevContext); + } + } + } +} diff --git a/Test/Storage.Test/ACLTest.cs b/Test/Storage.Test/ACLTest.cs index eb13f66..967da0c 100644 --- a/Test/Storage.Test/ACLTest.cs +++ b/Test/Storage.Test/ACLTest.cs @@ -1,19 +1,19 @@ using NUnit.Framework; using System.Threading.Tasks; +using LeanCloud; using LeanCloud.Storage; -using LeanCloud.Common; -namespace LeanCloud.Test { +namespace Storage.Test { public class ACLTest { [SetUp] public void SetUp() { - Logger.LogDelegate += Utils.Print; - LeanCloud.Initialize("ikGGdRE2YcVOemAaRbgp1xGJ-gzGzoHsz", "NUKmuRbdAhg1vrb2wexYo1jo", "https://ikggdre2.lc-cn-n1-shared.com"); + LCLogger.LogDelegate += Utils.Print; + LCApplication.Initialize("ikGGdRE2YcVOemAaRbgp1xGJ-gzGzoHsz", "NUKmuRbdAhg1vrb2wexYo1jo", "https://ikggdre2.lc-cn-n1-shared.com"); } [TearDown] public void TearDown() { - Logger.LogDelegate -= Utils.Print; + LCLogger.LogDelegate -= Utils.Print; } [Test] diff --git a/Test/Storage.Test/CloudTest.cs b/Test/Storage.Test/CloudTest.cs index e723fbf..2084a74 100644 --- a/Test/Storage.Test/CloudTest.cs +++ b/Test/Storage.Test/CloudTest.cs @@ -2,20 +2,20 @@ using System.Collections.Generic; using System.Threading.Tasks; using System.Linq; +using LeanCloud; using LeanCloud.Storage; -using LeanCloud.Common; -namespace LeanCloud.Test { +namespace Storage.Test { public class CloudTest { [SetUp] public void SetUp() { - Logger.LogDelegate += Utils.Print; - LeanCloud.Initialize("ikGGdRE2YcVOemAaRbgp1xGJ-gzGzoHsz", "NUKmuRbdAhg1vrb2wexYo1jo", "https://ikggdre2.lc-cn-n1-shared.com"); + LCLogger.LogDelegate += Utils.Print; + LCApplication.Initialize("ikGGdRE2YcVOemAaRbgp1xGJ-gzGzoHsz", "NUKmuRbdAhg1vrb2wexYo1jo", "https://ikggdre2.lc-cn-n1-shared.com"); } [TearDown] public void TearDown() { - Logger.LogDelegate -= Utils.Print; + LCLogger.LogDelegate -= Utils.Print; } [Test] diff --git a/Test/Storage.Test/ExceptionTest.cs b/Test/Storage.Test/ExceptionTest.cs index 2341cb5..83f70b3 100644 --- a/Test/Storage.Test/ExceptionTest.cs +++ b/Test/Storage.Test/ExceptionTest.cs @@ -1,8 +1,7 @@ using NUnit.Framework; using LeanCloud.Storage; -using LeanCloud.Common; -namespace LeanCloud.Test { +namespace Storage.Test { public class ExceptionTest { [Test] public void LeanCloudException() { diff --git a/Test/Storage.Test/FileTest.cs b/Test/Storage.Test/FileTest.cs index 9259f58..4912857 100644 --- a/Test/Storage.Test/FileTest.cs +++ b/Test/Storage.Test/FileTest.cs @@ -2,23 +2,23 @@ using System; using System.Text; using System.Threading.Tasks; +using LeanCloud; using LeanCloud.Storage; -using LeanCloud.Common; -namespace LeanCloud.Test { +namespace Storage.Test { public class FileTest { - static readonly string AvatarFilePath = "../../../assets/hello.png"; - static readonly string APKFilePath = "../../../assets/test.apk"; + static readonly string AvatarFilePath = "../../../../assets/hello.png"; + static readonly string APKFilePath = "../../../../assets/test.apk"; [SetUp] public void SetUp() { - Logger.LogDelegate += Utils.Print; - LeanCloud.Initialize("ikGGdRE2YcVOemAaRbgp1xGJ-gzGzoHsz", "NUKmuRbdAhg1vrb2wexYo1jo", "https://ikggdre2.lc-cn-n1-shared.com"); + LCLogger.LogDelegate += Utils.Print; + LCApplication.Initialize("ikGGdRE2YcVOemAaRbgp1xGJ-gzGzoHsz", "NUKmuRbdAhg1vrb2wexYo1jo", "https://ikggdre2.lc-cn-n1-shared.com"); } [TearDown] public void TearDown() { - Logger.LogDelegate -= Utils.Print; + LCLogger.LogDelegate -= Utils.Print; } [Test] @@ -72,7 +72,7 @@ namespace LeanCloud.Test { [Test] public async Task AWS() { - LeanCloud.Initialize("UlCpyvLm8aMzQsW6KnP6W3Wt-MdYXbMMI", "PyCTYoNoxCVoKKg394PBeS4r"); + LCApplication.Initialize("UlCpyvLm8aMzQsW6KnP6W3Wt-MdYXbMMI", "PyCTYoNoxCVoKKg394PBeS4r"); LCFile file = new LCFile("avatar", AvatarFilePath); await file.Save((count, total) => { TestContext.WriteLine($"progress: {count}/{total}"); diff --git a/Test/Storage.Test/GeoTest.cs b/Test/Storage.Test/GeoTest.cs index 64eacdf..c2e413f 100644 --- a/Test/Storage.Test/GeoTest.cs +++ b/Test/Storage.Test/GeoTest.cs @@ -1,7 +1,7 @@ using NUnit.Framework; using LeanCloud.Storage; -namespace LeanCloud.Test { +namespace Storage.Test { public class GeoTest { [Test] public void Calculate() { diff --git a/Test/Storage.Test/ObjectTest.cs b/Test/Storage.Test/ObjectTest.cs index f94a39f..399f2af 100644 --- a/Test/Storage.Test/ObjectTest.cs +++ b/Test/Storage.Test/ObjectTest.cs @@ -2,20 +2,20 @@ using NUnit.Framework; using System; using System.Threading.Tasks; using System.Collections.Generic; +using LeanCloud; using LeanCloud.Storage; -using LeanCloud.Common; -namespace LeanCloud.Test { +namespace Storage.Test { public class ObjectTest { [SetUp] public void SetUp() { - Logger.LogDelegate += Utils.Print; - LeanCloud.Initialize("ikGGdRE2YcVOemAaRbgp1xGJ-gzGzoHsz", "NUKmuRbdAhg1vrb2wexYo1jo", "https://ikggdre2.lc-cn-n1-shared.com"); + LCLogger.LogDelegate += Utils.Print; + LCApplication.Initialize("ikGGdRE2YcVOemAaRbgp1xGJ-gzGzoHsz", "NUKmuRbdAhg1vrb2wexYo1jo", "https://ikggdre2.lc-cn-n1-shared.com"); } [TearDown] public void TearDown() { - Logger.LogDelegate -= Utils.Print; + LCLogger.LogDelegate -= Utils.Print; } [Test] diff --git a/Test/Storage.Test/OperationTest.cs b/Test/Storage.Test/OperationTest.cs index ececc97..4a82013 100644 --- a/Test/Storage.Test/OperationTest.cs +++ b/Test/Storage.Test/OperationTest.cs @@ -1,20 +1,20 @@ using NUnit.Framework; using System.Collections.Generic; using System.Threading.Tasks; +using LeanCloud; using LeanCloud.Storage; -using LeanCloud.Common; -namespace LeanCloud.Test { +namespace Storage.Test { public class OperationTest { [SetUp] public void SetUp() { - Logger.LogDelegate += Utils.Print; - LeanCloud.Initialize("ikGGdRE2YcVOemAaRbgp1xGJ-gzGzoHsz", "NUKmuRbdAhg1vrb2wexYo1jo", "https://ikggdre2.lc-cn-n1-shared.com"); + LCLogger.LogDelegate += Utils.Print; + LCApplication.Initialize("ikGGdRE2YcVOemAaRbgp1xGJ-gzGzoHsz", "NUKmuRbdAhg1vrb2wexYo1jo", "https://ikggdre2.lc-cn-n1-shared.com"); } [TearDown] public void TearDown() { - Logger.LogDelegate -= Utils.Print; + LCLogger.LogDelegate -= Utils.Print; } [Test] diff --git a/Test/Storage.Test/QueryTest.cs b/Test/Storage.Test/QueryTest.cs index 30c385a..8bd009a 100644 --- a/Test/Storage.Test/QueryTest.cs +++ b/Test/Storage.Test/QueryTest.cs @@ -1,20 +1,20 @@ using NUnit.Framework; using System.Collections.Generic; using System.Threading.Tasks; +using LeanCloud; using LeanCloud.Storage; -using LeanCloud.Common; -namespace LeanCloud.Test { +namespace Storage.Test { public class QueryTest { [SetUp] public void SetUp() { - Logger.LogDelegate += Utils.Print; - LeanCloud.Initialize("ikGGdRE2YcVOemAaRbgp1xGJ-gzGzoHsz", "NUKmuRbdAhg1vrb2wexYo1jo", "https://ikggdre2.lc-cn-n1-shared.com"); + LCLogger.LogDelegate += Utils.Print; + LCApplication.Initialize("ikGGdRE2YcVOemAaRbgp1xGJ-gzGzoHsz", "NUKmuRbdAhg1vrb2wexYo1jo", "https://ikggdre2.lc-cn-n1-shared.com"); } [TearDown] public void TearDown() { - Logger.LogDelegate -= Utils.Print; + LCLogger.LogDelegate -= Utils.Print; } [Test] diff --git a/Test/Storage.Test/RelationTest.cs b/Test/Storage.Test/RelationTest.cs index 433802b..5ba3813 100644 --- a/Test/Storage.Test/RelationTest.cs +++ b/Test/Storage.Test/RelationTest.cs @@ -1,21 +1,20 @@ using NUnit.Framework; using System.Threading.Tasks; using System.Collections.Generic; -using System.Linq; +using LeanCloud; using LeanCloud.Storage; -using LeanCloud.Common; -namespace LeanCloud.Test { +namespace Storage.Test { public class RelationTest { [SetUp] public void SetUp() { - Logger.LogDelegate += Utils.Print; - LeanCloud.Initialize("ikGGdRE2YcVOemAaRbgp1xGJ-gzGzoHsz", "NUKmuRbdAhg1vrb2wexYo1jo", "https://ikggdre2.lc-cn-n1-shared.com"); + LCLogger.LogDelegate += Utils.Print; + LCApplication.Initialize("ikGGdRE2YcVOemAaRbgp1xGJ-gzGzoHsz", "NUKmuRbdAhg1vrb2wexYo1jo", "https://ikggdre2.lc-cn-n1-shared.com"); } [TearDown] public void TearDown() { - Logger.LogDelegate -= Utils.Print; + LCLogger.LogDelegate -= Utils.Print; } [Test] diff --git a/Test/Storage.Test/RoleTest.cs b/Test/Storage.Test/RoleTest.cs index f11da18..51460af 100644 --- a/Test/Storage.Test/RoleTest.cs +++ b/Test/Storage.Test/RoleTest.cs @@ -2,22 +2,21 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; -using System.Linq; +using LeanCloud; using LeanCloud.Storage; -using LeanCloud.Common; -namespace LeanCloud.Test { +namespace Storage.Test { [TestFixture] public class RoleTest { [SetUp] public void SetUp() { - Logger.LogDelegate += Utils.Print; - LeanCloud.Initialize("ikGGdRE2YcVOemAaRbgp1xGJ-gzGzoHsz", "NUKmuRbdAhg1vrb2wexYo1jo", "https://ikggdre2.lc-cn-n1-shared.com"); + LCLogger.LogDelegate += Utils.Print; + LCApplication.Initialize("ikGGdRE2YcVOemAaRbgp1xGJ-gzGzoHsz", "NUKmuRbdAhg1vrb2wexYo1jo", "https://ikggdre2.lc-cn-n1-shared.com"); } [TearDown] public void TearDown() { - Logger.LogDelegate -= Utils.Print; + LCLogger.LogDelegate -= Utils.Print; } [Test] diff --git a/Test/Storage.Test/SubClassTest.cs b/Test/Storage.Test/SubClassTest.cs index 9e1c994..fb599af 100644 --- a/Test/Storage.Test/SubClassTest.cs +++ b/Test/Storage.Test/SubClassTest.cs @@ -1,10 +1,10 @@ using NUnit.Framework; using System.Threading.Tasks; using System.Collections.Generic; +using LeanCloud; using LeanCloud.Storage; -using LeanCloud.Common; -namespace LeanCloud.Test { +namespace Storage.Test { internal class Hello : LCObject { internal World World => this["objectValue"] as World; @@ -39,13 +39,13 @@ namespace LeanCloud.Test { public class SubClassTest { [SetUp] public void SetUp() { - Logger.LogDelegate += Utils.Print; - LeanCloud.Initialize("ikGGdRE2YcVOemAaRbgp1xGJ-gzGzoHsz", "NUKmuRbdAhg1vrb2wexYo1jo", "https://ikggdre2.lc-cn-n1-shared.com"); + LCLogger.LogDelegate += Utils.Print; + LCApplication.Initialize("ikGGdRE2YcVOemAaRbgp1xGJ-gzGzoHsz", "NUKmuRbdAhg1vrb2wexYo1jo", "https://ikggdre2.lc-cn-n1-shared.com"); } [TearDown] public void TearDown() { - Logger.LogDelegate -= Utils.Print; + LCLogger.LogDelegate -= Utils.Print; } [Test] diff --git a/Test/Storage.Test/UserTest.cs b/Test/Storage.Test/UserTest.cs index 83a64e4..53a0cb5 100644 --- a/Test/Storage.Test/UserTest.cs +++ b/Test/Storage.Test/UserTest.cs @@ -2,20 +2,20 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; +using LeanCloud; using LeanCloud.Storage; -using LeanCloud.Common; -namespace LeanCloud.Test { +namespace Storage.Test { public class UserTest { [SetUp] public void SetUp() { - Logger.LogDelegate += Utils.Print; - LeanCloud.Initialize("ikGGdRE2YcVOemAaRbgp1xGJ-gzGzoHsz", "NUKmuRbdAhg1vrb2wexYo1jo", "https://ikggdre2.lc-cn-n1-shared.com"); + LCLogger.LogDelegate += Utils.Print; + LCApplication.Initialize("ikGGdRE2YcVOemAaRbgp1xGJ-gzGzoHsz", "NUKmuRbdAhg1vrb2wexYo1jo", "https://ikggdre2.lc-cn-n1-shared.com"); } [TearDown] public void TearDown() { - Logger.LogDelegate -= Utils.Print; + LCLogger.LogDelegate -= Utils.Print; } [Test] diff --git a/Test/Storage.Test/Utils.cs b/Test/Storage.Test/Utils.cs index 739b4aa..e7e6df2 100644 --- a/Test/Storage.Test/Utils.cs +++ b/Test/Storage.Test/Utils.cs @@ -1,19 +1,17 @@ -using System; +using NUnit.Framework; using LeanCloud; -using LeanCloud.Common; -using NUnit.Framework; -namespace LeanCloud.Test { +namespace Storage.Test { public static class Utils { - internal static void Print(LogLevel level, string info) { + internal static void Print(LCLogLevel level, string info) { switch (level) { - case LogLevel.Debug: + case LCLogLevel.Debug: TestContext.Out.WriteLine($"[DEBUG] {info}"); break; - case LogLevel.Warn: + case LCLogLevel.Warn: TestContext.Out.WriteLine($"[WARNING] {info}"); break; - case LogLevel.Error: + case LCLogLevel.Error: TestContext.Out.WriteLine($"[ERROR] {info}"); break; default: diff --git a/Test/Storage.Test/assets/hello.png b/Test/assets/hello.png similarity index 100% rename from Test/Storage.Test/assets/hello.png rename to Test/assets/hello.png diff --git a/Test/Storage.Test/assets/test.apk b/Test/assets/test.apk similarity index 100% rename from Test/Storage.Test/assets/test.apk rename to Test/assets/test.apk diff --git a/csharp-sdk.sln b/csharp-sdk.sln index 2a42599..166d2e2 100644 --- a/csharp-sdk.sln +++ b/csharp-sdk.sln @@ -9,6 +9,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Storage", "Storage\Storage. EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Storage.Test", "Test\Storage.Test\Storage.Test.csproj", "{531F8181-FFE0-476E-9D0A-93F13CAD1183}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Realtime", "Realtime\Realtime.csproj", "{7084C9BD-6D26-4803-9E7F-A6D2E55D963A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Realtime.Test", "Test\Realtime.Test\Realtime.Test.csproj", "{746B0DE6-C504-4568-BA6D-4A08A91A5E35}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RealtimeApp", "Test\RealtimeApp\RealtimeApp.csproj", "{4CB5E8C3-B1FC-45C3-B882-A9A43DFC6B1C}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -27,9 +33,23 @@ Global {531F8181-FFE0-476E-9D0A-93F13CAD1183}.Debug|Any CPU.Build.0 = Debug|Any CPU {531F8181-FFE0-476E-9D0A-93F13CAD1183}.Release|Any CPU.ActiveCfg = Release|Any CPU {531F8181-FFE0-476E-9D0A-93F13CAD1183}.Release|Any CPU.Build.0 = Release|Any CPU + {7084C9BD-6D26-4803-9E7F-A6D2E55D963A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7084C9BD-6D26-4803-9E7F-A6D2E55D963A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7084C9BD-6D26-4803-9E7F-A6D2E55D963A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7084C9BD-6D26-4803-9E7F-A6D2E55D963A}.Release|Any CPU.Build.0 = Release|Any CPU + {746B0DE6-C504-4568-BA6D-4A08A91A5E35}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {746B0DE6-C504-4568-BA6D-4A08A91A5E35}.Debug|Any CPU.Build.0 = Debug|Any CPU + {746B0DE6-C504-4568-BA6D-4A08A91A5E35}.Release|Any CPU.ActiveCfg = Release|Any CPU + {746B0DE6-C504-4568-BA6D-4A08A91A5E35}.Release|Any CPU.Build.0 = Release|Any CPU + {4CB5E8C3-B1FC-45C3-B882-A9A43DFC6B1C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4CB5E8C3-B1FC-45C3-B882-A9A43DFC6B1C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4CB5E8C3-B1FC-45C3-B882-A9A43DFC6B1C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4CB5E8C3-B1FC-45C3-B882-A9A43DFC6B1C}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {531F8181-FFE0-476E-9D0A-93F13CAD1183} = {C827DA2F-6AB4-48D8-AB5B-6DAB925F8933} + {746B0DE6-C504-4568-BA6D-4A08A91A5E35} = {C827DA2F-6AB4-48D8-AB5B-6DAB925F8933} + {4CB5E8C3-B1FC-45C3-B882-A9A43DFC6B1C} = {C827DA2F-6AB4-48D8-AB5B-6DAB925F8933} EndGlobalSection GlobalSection(MonoDevelopProperties) = preSolution version = 0.1.0