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/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