diff --git a/Rocket.Chat.Net.sln b/Rocket.Chat.Net.sln
index cb76239..d93c809 100644
--- a/Rocket.Chat.Net.sln
+++ b/Rocket.Chat.Net.sln
@@ -1,10 +1,8 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 14
-VisualStudioVersion = 14.0.25123.0
+# Visual Studio Version 17
+VisualStudioVersion = 17.3.32929.385
MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rocket.Chat.Net", "src\Rocket.Chat.Net\Rocket.Chat.Net.csproj", "{A078AEB9-5502-441C-B44A-FF4BBE007551}"
-EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rocket.Chat.Net.Tests", "test\Rocket.Chat.Net.Tests\Rocket.Chat.Net.Tests.csproj", "{55BAE418-9468-4A62-A6FA-F92ECBEAD8A5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rocket.Chat.Net.Example", "src\Rocket.Chat.Net.Example\Rocket.Chat.Net.Example.csproj", "{EFB12AE6-706D-42B5-B2CC-54D60C4DC02B}"
@@ -16,8 +14,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{7B016A
.nuget\packages.config = .nuget\packages.config
EndProjectSection
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rocket.Chat.Net.Bot", "src\Rocket.Chat.Net.Bot\Rocket.Chat.Net.Bot.csproj", "{A6FF1F57-0837-4F1A-9248-1CCE8477295E}"
-EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rocket.Chat.Net.Bot.Tests", "test\Rocket.Chat.Net.Bot.Tests\Rocket.Chat.Net.Bot.Tests.csproj", "{A271F00E-6B4A-4149-9770-57A50E81A3ED}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rocket.Chat.Net.Portability", "src\Portability\Rocket.Chat.Net.Portability\Rocket.Chat.Net.Portability.csproj", "{662CE701-056D-420A-B03B-4F2613EEA044}"
@@ -38,6 +34,10 @@ Project("{FF286327-C783-4F7A-AB73-9BCBAD0D4460}") = "Rocket.Chat.Net.NuGet", "sr
EndProject
Project("{FF286327-C783-4F7A-AB73-9BCBAD0D4460}") = "Rocket.Chat.Net.Bot.NuGet", "src\NuGet\Rocket.Chat.Net.Bot.NuGet\Rocket.Chat.Net.Bot.NuGet.nuproj", "{65631767-93F5-4F5B-875A-AA5FE4F6A80D}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rocket.Chat.Net", "src\Rocket.Chat.Net\Rocket.Chat.Net.csproj", "{7EA92634-49F8-416D-9DBC-661A83EA425C}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rocket.Chat.Net.Bot", "src\Rocket.Chat.Net.Bot\Rocket.Chat.Net.Bot.csproj", "{0C2862BE-2CFB-4890-B154-4B4E7753E11F}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -54,30 +54,6 @@ Global
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {A078AEB9-5502-441C-B44A-FF4BBE007551}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {A078AEB9-5502-441C-B44A-FF4BBE007551}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {A078AEB9-5502-441C-B44A-FF4BBE007551}.Debug|ARM.ActiveCfg = Debug|Any CPU
- {A078AEB9-5502-441C-B44A-FF4BBE007551}.Debug|ARM.Build.0 = Debug|Any CPU
- {A078AEB9-5502-441C-B44A-FF4BBE007551}.Debug|x64.ActiveCfg = Debug|Any CPU
- {A078AEB9-5502-441C-B44A-FF4BBE007551}.Debug|x64.Build.0 = Debug|Any CPU
- {A078AEB9-5502-441C-B44A-FF4BBE007551}.Debug|x86.ActiveCfg = Debug|Any CPU
- {A078AEB9-5502-441C-B44A-FF4BBE007551}.Debug|x86.Build.0 = Debug|Any CPU
- {A078AEB9-5502-441C-B44A-FF4BBE007551}.Mono-4.5|Any CPU.ActiveCfg = Mono-4.5|Any CPU
- {A078AEB9-5502-441C-B44A-FF4BBE007551}.Mono-4.5|Any CPU.Build.0 = Mono-4.5|Any CPU
- {A078AEB9-5502-441C-B44A-FF4BBE007551}.Mono-4.5|ARM.ActiveCfg = Mono-4.5|Any CPU
- {A078AEB9-5502-441C-B44A-FF4BBE007551}.Mono-4.5|ARM.Build.0 = Mono-4.5|Any CPU
- {A078AEB9-5502-441C-B44A-FF4BBE007551}.Mono-4.5|x64.ActiveCfg = Mono-4.5|Any CPU
- {A078AEB9-5502-441C-B44A-FF4BBE007551}.Mono-4.5|x64.Build.0 = Mono-4.5|Any CPU
- {A078AEB9-5502-441C-B44A-FF4BBE007551}.Mono-4.5|x86.ActiveCfg = Mono-4.5|Any CPU
- {A078AEB9-5502-441C-B44A-FF4BBE007551}.Mono-4.5|x86.Build.0 = Mono-4.5|Any CPU
- {A078AEB9-5502-441C-B44A-FF4BBE007551}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {A078AEB9-5502-441C-B44A-FF4BBE007551}.Release|Any CPU.Build.0 = Release|Any CPU
- {A078AEB9-5502-441C-B44A-FF4BBE007551}.Release|ARM.ActiveCfg = Release|Any CPU
- {A078AEB9-5502-441C-B44A-FF4BBE007551}.Release|ARM.Build.0 = Release|Any CPU
- {A078AEB9-5502-441C-B44A-FF4BBE007551}.Release|x64.ActiveCfg = Release|Any CPU
- {A078AEB9-5502-441C-B44A-FF4BBE007551}.Release|x64.Build.0 = Release|Any CPU
- {A078AEB9-5502-441C-B44A-FF4BBE007551}.Release|x86.ActiveCfg = Release|Any CPU
- {A078AEB9-5502-441C-B44A-FF4BBE007551}.Release|x86.Build.0 = Release|Any CPU
{55BAE418-9468-4A62-A6FA-F92ECBEAD8A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{55BAE418-9468-4A62-A6FA-F92ECBEAD8A5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{55BAE418-9468-4A62-A6FA-F92ECBEAD8A5}.Debug|ARM.ActiveCfg = Debug|Any CPU
@@ -126,30 +102,6 @@ Global
{EFB12AE6-706D-42B5-B2CC-54D60C4DC02B}.Release|x64.Build.0 = Release|Any CPU
{EFB12AE6-706D-42B5-B2CC-54D60C4DC02B}.Release|x86.ActiveCfg = Release|Any CPU
{EFB12AE6-706D-42B5-B2CC-54D60C4DC02B}.Release|x86.Build.0 = Release|Any CPU
- {A6FF1F57-0837-4F1A-9248-1CCE8477295E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {A6FF1F57-0837-4F1A-9248-1CCE8477295E}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {A6FF1F57-0837-4F1A-9248-1CCE8477295E}.Debug|ARM.ActiveCfg = Debug|Any CPU
- {A6FF1F57-0837-4F1A-9248-1CCE8477295E}.Debug|ARM.Build.0 = Debug|Any CPU
- {A6FF1F57-0837-4F1A-9248-1CCE8477295E}.Debug|x64.ActiveCfg = Debug|Any CPU
- {A6FF1F57-0837-4F1A-9248-1CCE8477295E}.Debug|x64.Build.0 = Debug|Any CPU
- {A6FF1F57-0837-4F1A-9248-1CCE8477295E}.Debug|x86.ActiveCfg = Debug|Any CPU
- {A6FF1F57-0837-4F1A-9248-1CCE8477295E}.Debug|x86.Build.0 = Debug|Any CPU
- {A6FF1F57-0837-4F1A-9248-1CCE8477295E}.Mono-4.5|Any CPU.ActiveCfg = Release|Any CPU
- {A6FF1F57-0837-4F1A-9248-1CCE8477295E}.Mono-4.5|Any CPU.Build.0 = Release|Any CPU
- {A6FF1F57-0837-4F1A-9248-1CCE8477295E}.Mono-4.5|ARM.ActiveCfg = Release|Any CPU
- {A6FF1F57-0837-4F1A-9248-1CCE8477295E}.Mono-4.5|ARM.Build.0 = Release|Any CPU
- {A6FF1F57-0837-4F1A-9248-1CCE8477295E}.Mono-4.5|x64.ActiveCfg = Release|Any CPU
- {A6FF1F57-0837-4F1A-9248-1CCE8477295E}.Mono-4.5|x64.Build.0 = Release|Any CPU
- {A6FF1F57-0837-4F1A-9248-1CCE8477295E}.Mono-4.5|x86.ActiveCfg = Release|Any CPU
- {A6FF1F57-0837-4F1A-9248-1CCE8477295E}.Mono-4.5|x86.Build.0 = Release|Any CPU
- {A6FF1F57-0837-4F1A-9248-1CCE8477295E}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {A6FF1F57-0837-4F1A-9248-1CCE8477295E}.Release|Any CPU.Build.0 = Release|Any CPU
- {A6FF1F57-0837-4F1A-9248-1CCE8477295E}.Release|ARM.ActiveCfg = Release|Any CPU
- {A6FF1F57-0837-4F1A-9248-1CCE8477295E}.Release|ARM.Build.0 = Release|Any CPU
- {A6FF1F57-0837-4F1A-9248-1CCE8477295E}.Release|x64.ActiveCfg = Release|Any CPU
- {A6FF1F57-0837-4F1A-9248-1CCE8477295E}.Release|x64.Build.0 = Release|Any CPU
- {A6FF1F57-0837-4F1A-9248-1CCE8477295E}.Release|x86.ActiveCfg = Release|Any CPU
- {A6FF1F57-0837-4F1A-9248-1CCE8477295E}.Release|x86.Build.0 = Release|Any CPU
{A271F00E-6B4A-4149-9770-57A50E81A3ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A271F00E-6B4A-4149-9770-57A50E81A3ED}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A271F00E-6B4A-4149-9770-57A50E81A3ED}.Debug|ARM.ActiveCfg = Debug|Any CPU
@@ -342,6 +294,54 @@ Global
{65631767-93F5-4F5B-875A-AA5FE4F6A80D}.Release|x64.Build.0 = Release|Any CPU
{65631767-93F5-4F5B-875A-AA5FE4F6A80D}.Release|x86.ActiveCfg = Release|Any CPU
{65631767-93F5-4F5B-875A-AA5FE4F6A80D}.Release|x86.Build.0 = Release|Any CPU
+ {7EA92634-49F8-416D-9DBC-661A83EA425C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7EA92634-49F8-416D-9DBC-661A83EA425C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7EA92634-49F8-416D-9DBC-661A83EA425C}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {7EA92634-49F8-416D-9DBC-661A83EA425C}.Debug|ARM.Build.0 = Debug|Any CPU
+ {7EA92634-49F8-416D-9DBC-661A83EA425C}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {7EA92634-49F8-416D-9DBC-661A83EA425C}.Debug|x64.Build.0 = Debug|Any CPU
+ {7EA92634-49F8-416D-9DBC-661A83EA425C}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {7EA92634-49F8-416D-9DBC-661A83EA425C}.Debug|x86.Build.0 = Debug|Any CPU
+ {7EA92634-49F8-416D-9DBC-661A83EA425C}.Mono-4.5|Any CPU.ActiveCfg = Debug|Any CPU
+ {7EA92634-49F8-416D-9DBC-661A83EA425C}.Mono-4.5|Any CPU.Build.0 = Debug|Any CPU
+ {7EA92634-49F8-416D-9DBC-661A83EA425C}.Mono-4.5|ARM.ActiveCfg = Debug|Any CPU
+ {7EA92634-49F8-416D-9DBC-661A83EA425C}.Mono-4.5|ARM.Build.0 = Debug|Any CPU
+ {7EA92634-49F8-416D-9DBC-661A83EA425C}.Mono-4.5|x64.ActiveCfg = Debug|Any CPU
+ {7EA92634-49F8-416D-9DBC-661A83EA425C}.Mono-4.5|x64.Build.0 = Debug|Any CPU
+ {7EA92634-49F8-416D-9DBC-661A83EA425C}.Mono-4.5|x86.ActiveCfg = Debug|Any CPU
+ {7EA92634-49F8-416D-9DBC-661A83EA425C}.Mono-4.5|x86.Build.0 = Debug|Any CPU
+ {7EA92634-49F8-416D-9DBC-661A83EA425C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7EA92634-49F8-416D-9DBC-661A83EA425C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7EA92634-49F8-416D-9DBC-661A83EA425C}.Release|ARM.ActiveCfg = Release|Any CPU
+ {7EA92634-49F8-416D-9DBC-661A83EA425C}.Release|ARM.Build.0 = Release|Any CPU
+ {7EA92634-49F8-416D-9DBC-661A83EA425C}.Release|x64.ActiveCfg = Release|Any CPU
+ {7EA92634-49F8-416D-9DBC-661A83EA425C}.Release|x64.Build.0 = Release|Any CPU
+ {7EA92634-49F8-416D-9DBC-661A83EA425C}.Release|x86.ActiveCfg = Release|Any CPU
+ {7EA92634-49F8-416D-9DBC-661A83EA425C}.Release|x86.Build.0 = Release|Any CPU
+ {0C2862BE-2CFB-4890-B154-4B4E7753E11F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {0C2862BE-2CFB-4890-B154-4B4E7753E11F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0C2862BE-2CFB-4890-B154-4B4E7753E11F}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {0C2862BE-2CFB-4890-B154-4B4E7753E11F}.Debug|ARM.Build.0 = Debug|Any CPU
+ {0C2862BE-2CFB-4890-B154-4B4E7753E11F}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {0C2862BE-2CFB-4890-B154-4B4E7753E11F}.Debug|x64.Build.0 = Debug|Any CPU
+ {0C2862BE-2CFB-4890-B154-4B4E7753E11F}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {0C2862BE-2CFB-4890-B154-4B4E7753E11F}.Debug|x86.Build.0 = Debug|Any CPU
+ {0C2862BE-2CFB-4890-B154-4B4E7753E11F}.Mono-4.5|Any CPU.ActiveCfg = Debug|Any CPU
+ {0C2862BE-2CFB-4890-B154-4B4E7753E11F}.Mono-4.5|Any CPU.Build.0 = Debug|Any CPU
+ {0C2862BE-2CFB-4890-B154-4B4E7753E11F}.Mono-4.5|ARM.ActiveCfg = Debug|Any CPU
+ {0C2862BE-2CFB-4890-B154-4B4E7753E11F}.Mono-4.5|ARM.Build.0 = Debug|Any CPU
+ {0C2862BE-2CFB-4890-B154-4B4E7753E11F}.Mono-4.5|x64.ActiveCfg = Debug|Any CPU
+ {0C2862BE-2CFB-4890-B154-4B4E7753E11F}.Mono-4.5|x64.Build.0 = Debug|Any CPU
+ {0C2862BE-2CFB-4890-B154-4B4E7753E11F}.Mono-4.5|x86.ActiveCfg = Debug|Any CPU
+ {0C2862BE-2CFB-4890-B154-4B4E7753E11F}.Mono-4.5|x86.Build.0 = Debug|Any CPU
+ {0C2862BE-2CFB-4890-B154-4B4E7753E11F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0C2862BE-2CFB-4890-B154-4B4E7753E11F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {0C2862BE-2CFB-4890-B154-4B4E7753E11F}.Release|ARM.ActiveCfg = Release|Any CPU
+ {0C2862BE-2CFB-4890-B154-4B4E7753E11F}.Release|ARM.Build.0 = Release|Any CPU
+ {0C2862BE-2CFB-4890-B154-4B4E7753E11F}.Release|x64.ActiveCfg = Release|Any CPU
+ {0C2862BE-2CFB-4890-B154-4B4E7753E11F}.Release|x64.Build.0 = Release|Any CPU
+ {0C2862BE-2CFB-4890-B154-4B4E7753E11F}.Release|x86.ActiveCfg = Release|Any CPU
+ {0C2862BE-2CFB-4890-B154-4B4E7753E11F}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -357,4 +357,7 @@ Global
{094585D5-62DF-445D-A8B3-88CB137B0205} = {C8A58FB6-F539-4E62-93F8-28B51E56D033}
{65631767-93F5-4F5B-875A-AA5FE4F6A80D} = {C8A58FB6-F539-4E62-93F8-28B51E56D033}
EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {6989C4B9-1911-47A5-BA34-36E48C21CE4A}
+ EndGlobalSection
EndGlobal
diff --git a/src/Portability/Rocket.Chat.Net.Portability.Android/Resources/Resource.Designer.cs b/src/Portability/Rocket.Chat.Net.Portability.Android/Resources/Resource.Designer.cs
index e69de29..b8e8393 100644
--- a/src/Portability/Rocket.Chat.Net.Portability.Android/Resources/Resource.Designer.cs
+++ b/src/Portability/Rocket.Chat.Net.Portability.Android/Resources/Resource.Designer.cs
@@ -0,0 +1,59 @@
+#pragma warning disable 1591
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+[assembly: global::Android.Runtime.ResourceDesignerAttribute("Rocket.Chat.Net.Portability.Resource", IsApplication=false)]
+
+namespace Rocket.Chat.Net.Portability
+{
+
+
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "13.1.0.5")]
+ public partial class Resource
+ {
+
+ static Resource()
+ {
+ global::Android.Runtime.ResourceIdManager.UpdateIdValues();
+ }
+
+ public partial class Attribute
+ {
+
+ static Attribute()
+ {
+ global::Android.Runtime.ResourceIdManager.UpdateIdValues();
+ }
+
+ private Attribute()
+ {
+ }
+ }
+
+ public partial class String
+ {
+
+ // aapt resource value: 0x7F010000
+ public static int ApplicationName = 2130771968;
+
+ // aapt resource value: 0x7F010001
+ public static int Hello = 2130771969;
+
+ static String()
+ {
+ global::Android.Runtime.ResourceIdManager.UpdateIdValues();
+ }
+
+ private String()
+ {
+ }
+ }
+ }
+}
+#pragma warning restore 1591
diff --git a/src/Portability/Rocket.Chat.Net.Portability.Android/Rocket.Chat.Net.Portability.Android.csproj b/src/Portability/Rocket.Chat.Net.Portability.Android/Rocket.Chat.Net.Portability.Android.csproj
index 7248848..21bf6d7 100644
--- a/src/Portability/Rocket.Chat.Net.Portability.Android/Rocket.Chat.Net.Portability.Android.csproj
+++ b/src/Portability/Rocket.Chat.Net.Portability.Android/Rocket.Chat.Net.Portability.Android.csproj
@@ -14,8 +14,7 @@
512
Resources\Resource.Designer.cs
Off
- True
- v6.0
+ v13.0
diff --git a/src/Portability/Rocket.Chat.Net.Portability.Net45/Rocket.Chat.Net.Portability.Net45.csproj b/src/Portability/Rocket.Chat.Net.Portability.Net45/Rocket.Chat.Net.Portability.Net45.csproj
index f78229a..8507366 100644
--- a/src/Portability/Rocket.Chat.Net.Portability.Net45/Rocket.Chat.Net.Portability.Net45.csproj
+++ b/src/Portability/Rocket.Chat.Net.Portability.Net45/Rocket.Chat.Net.Portability.Net45.csproj
@@ -9,7 +9,7 @@
Properties
Rocket.Chat.Net.Portability
Rocket.Chat.Net.Portability
- v4.5
+ v4.8
512
diff --git a/src/Rocket.Chat.Net.Bot/Properties/AssemblyInfo.cs b/src/Rocket.Chat.Net.Bot/Properties/AssemblyInfo.cs
deleted file mode 100644
index 43c0476..0000000
--- a/src/Rocket.Chat.Net.Bot/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-using System.Reflection;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("Rocket.Chat.Net.Bot")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("Rocket.Chat.Net.Bot")]
-[assembly: AssemblyCopyright("Copyright © 2016")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// Version information for an assembly consists of the following four values:
-//
-// Major Version
-// Minor Version
-// Build Number
-// Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
-[assembly: AssemblyInformationalVersion("1.0.0.0")]
\ No newline at end of file
diff --git a/src/Rocket.Chat.Net.Bot/Rocket.Chat.Net.Bot.csproj b/src/Rocket.Chat.Net.Bot/Rocket.Chat.Net.Bot.csproj
index 144e8cf..a393af5 100644
--- a/src/Rocket.Chat.Net.Bot/Rocket.Chat.Net.Bot.csproj
+++ b/src/Rocket.Chat.Net.Bot/Rocket.Chat.Net.Bot.csproj
@@ -1,83 +1,15 @@
-
-
-
-
+
+
- Debug
- AnyCPU
- {A6FF1F57-0837-4F1A-9248-1CCE8477295E}
- Library
- Properties
- Rocket.Chat.Net.Bot
- Rocket.Chat.Net.Bot
- v4.5
- 512
-
-
-
- Profile111
- {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ netstandard2.0
-
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
-
-
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
-
-
-
- ..\..\packages\Newtonsoft.Json.8.0.3\lib\portable-net40+sl5+wp80+win8+wpa81\Newtonsoft.Json.dll
- True
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
- {a078aeb9-5502-441c-b44a-ff4bbe007551}
- Rocket.Chat.Net
-
+
+
-
+
-
-
-
- This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
-
-
-
-
-
-
-
\ No newline at end of file
+
+
diff --git a/src/Rocket.Chat.Net.Bot/Rocket.Chat.Net.Bot.v2.ncrunchproject b/src/Rocket.Chat.Net.Bot/Rocket.Chat.Net.Bot.v2.ncrunchproject
deleted file mode 100644
index 30815b1..0000000
--- a/src/Rocket.Chat.Net.Bot/Rocket.Chat.Net.Bot.v2.ncrunchproject
+++ /dev/null
@@ -1,26 +0,0 @@
-
- true
- 1000
- false
- false
- false
- true
- false
- false
- false
- false
- false
- true
- true
- false
- true
- true
- true
- 60000
-
-
-
- AutoDetect
- STA
- x86
-
\ No newline at end of file
diff --git a/src/Rocket.Chat.Net.Bot/RocketChatBot.cs b/src/Rocket.Chat.Net.Bot/RocketChatBot.cs
index ffa35e6..a0a8d86 100644
--- a/src/Rocket.Chat.Net.Bot/RocketChatBot.cs
+++ b/src/Rocket.Chat.Net.Bot/RocketChatBot.cs
@@ -3,12 +3,11 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
-
+ using NLog;
using Rocket.Chat.Net.Bot.Interfaces;
using Rocket.Chat.Net.Bot.Models;
using Rocket.Chat.Net.Driver;
using Rocket.Chat.Net.Interfaces;
- using Rocket.Chat.Net.Loggers;
using Rocket.Chat.Net.Models;
public class RocketChatBot : IDisposable
@@ -23,7 +22,7 @@ public class RocketChatBot : IDisposable
public RocketChatBot(IRocketChatDriver driver, ILogger logger)
{
Driver = driver;
- _logger = logger ?? new DummyLogger();
+ _logger = logger ?? NLog.LogManager.CreateNullLogger();
Driver.MessageReceived += DriverOnMessageReceived;
Driver.DdpReconnect += DriverOnDdpReconnect;
@@ -54,6 +53,9 @@ public async Task LoginAsync(ILoginOption loginOption)
public async Task SubscribeAsync()
{
await Driver.SubscribeToRoomAsync().ConfigureAwait(false);
+ // https://developer.rocket.chat/reference/api/realtime-api/subscriptions/stream-room-messages
+ // subscribe to bot's private direct messages
+ await Driver.SubscribeToRoomAsync("__my_messages__");
}
public async Task ResumeAsync()
@@ -64,7 +66,7 @@ public async Task ResumeAsync()
}
_logger.Info($"Resuming session {LoginToken}.");
- var result = await Driver.LoginResumeAsync(LoginToken).ConfigureAwait(false);
+ var result = await Driver.LoginResumeAsync(new Net.Models.LoginOptions.ResumeLoginOption() { Token = LoginToken }).ConfigureAwait(false);
if (result.HasError)
{
throw new Exception($"Resume failed: {result.Error.Message}.");
@@ -156,7 +158,7 @@ private async Task SendMessageAsync(IMessageResponse response)
else
{
throw new InvalidOperationException(
- $"The result of {nameof(IBotResponse.GetResponse)} is either null or not of a supported type.");
+ $"The result of {nameof(IBotResponse.GetResponse)} is either null or not of a supported type.");
}
}
diff --git a/src/Rocket.Chat.Net.Bot/packages.config b/src/Rocket.Chat.Net.Bot/packages.config
deleted file mode 100644
index 263bd3b..0000000
--- a/src/Rocket.Chat.Net.Bot/packages.config
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/Rocket.Chat.Net.Example/App.config b/src/Rocket.Chat.Net.Example/App.config
index d1428ad..94d1641 100644
--- a/src/Rocket.Chat.Net.Example/App.config
+++ b/src/Rocket.Chat.Net.Example/App.config
@@ -1,6 +1,18 @@
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Rocket.Chat.Net.Example/GiphyResponse.cs b/src/Rocket.Chat.Net.Example/GiphyResponse.cs
index 4910dcb..c50d667 100644
--- a/src/Rocket.Chat.Net.Example/GiphyResponse.cs
+++ b/src/Rocket.Chat.Net.Example/GiphyResponse.cs
@@ -38,7 +38,7 @@ public IEnumerable GetResponse(ResponseContext context, Rocket
private string GetGiphy(string search)
{
- var request = new RestRequest("/v1/gifs/translate", Method.GET);
+ var request = new RestRequest("/v1/gifs/translate", Method.Get);
request.AddQueryParameter("s", search);
request.AddQueryParameter("rating", Rating);
request.AddQueryParameter("api_key", GiphyApiKey);
diff --git a/src/Rocket.Chat.Net.Example/HelloWorldResponse.cs b/src/Rocket.Chat.Net.Example/HelloWorldResponse.cs
new file mode 100644
index 0000000..4ab171e
--- /dev/null
+++ b/src/Rocket.Chat.Net.Example/HelloWorldResponse.cs
@@ -0,0 +1,25 @@
+using Rocket.Chat.Net.Bot;
+using Rocket.Chat.Net.Bot.Interfaces;
+using Rocket.Chat.Net.Bot.Models;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Rocket.Chat.Net.Example
+{
+ public class HelloWorldResponse : IBotResponse
+ {
+ public bool CanRespond(ResponseContext context)
+ {
+ return ! context.Message.IsFromMyself && context.Message.Message.ToLower().StartsWith("hello");
+ }
+
+ public IEnumerable GetResponse(ResponseContext context, RocketChatBot caller)
+ {
+ var message = context.Message;
+ yield return new BasicResponse("Hello world!", context.Message.RoomId);
+ }
+ }
+}
diff --git a/src/Rocket.Chat.Net.Example/Program.cs b/src/Rocket.Chat.Net.Example/Program.cs
index 0c5b535..3142104 100644
--- a/src/Rocket.Chat.Net.Example/Program.cs
+++ b/src/Rocket.Chat.Net.Example/Program.cs
@@ -1,12 +1,12 @@
namespace Rocket.Chat.Net.Example
{
using System;
+ using System.Linq.Expressions;
using System.Threading.Tasks;
-
+ using NLog;
using Rocket.Chat.Net.Bot;
using Rocket.Chat.Net.Bot.Interfaces;
using Rocket.Chat.Net.Interfaces;
- using Rocket.Chat.Net.Loggers;
using Rocket.Chat.Net.Models.LoginOptions;
public static class Program
@@ -17,35 +17,61 @@ public static void Main()
Console.ReadLine();
}
+ public static void SetUpLoggingConfiguration()
+ {
+ var config = new NLog.Config.LoggingConfiguration();
+ config.AddTarget(new NLog.Targets.ConsoleTarget("Console"));
+ config.AddRule(LogLevel.Debug, LogLevel.Fatal, "Console");
+ NLog.LogManager.Configuration = config;
+ }
+
private static async Task MainAsync()
{
- const string username = "m@silvenga.com";
- const string password = "silverlight";
- const string rocketServerUrl = "dev0:3000"; // just the host and port
- const bool useSsl = false; // Basically use ws or wss.
-
+ const string username = "theotest";
+ const string password = "theotheo1234";
+ const string rocketServerUrl = "chat.softbauware.de"; // just the host and port
+ const bool useSsl = true; // Basically use ws or wss.
+
+ SetUpLoggingConfiguration();
+
+ Logger logger = NLog.LogManager.GetCurrentClassLogger();
+ logger.Info("Logger initialized!");
+
// Create the bot - an abstraction of the driver
- RocketChatBot bot = new RocketChatBot(rocketServerUrl, useSsl);
+ RocketChatBot bot = new RocketChatBot(rocketServerUrl, useSsl, logger);
// Connect to Rocket.Chat
await bot.ConnectAsync();
// Login
- ILoginOption loginOption = new EmailLoginOption
+ ILoginOption loginOption = new UsernameLoginOption()
{
- Email = username,
+ Username = username,
Password = password
};
- await bot.LoginAsync(loginOption);
+ try
+ {
+ await bot.LoginAsync(loginOption);
+ Console.WriteLine("Logged in!");
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine(e);
+ }
// Start listening for messages
await bot.SubscribeAsync();
+ await bot.Driver.SetUserPresence("online");
+
// Add possible responses to be checked in order
// This is not thead safe, FYI
IBotResponse giphyResponse = new GiphyResponse();
+ IBotResponse helloWorldResponse = new HelloWorldResponse();
+ bot.AddResponse(helloWorldResponse);
bot.AddResponse(giphyResponse);
+
// And that's it
// Checkout GiphyResponse in the example project for more info.
}
diff --git a/src/Rocket.Chat.Net.Example/Rocket.Chat.Net.Example.csproj b/src/Rocket.Chat.Net.Example/Rocket.Chat.Net.Example.csproj
index f2aa1ae..76c3fa7 100644
--- a/src/Rocket.Chat.Net.Example/Rocket.Chat.Net.Example.csproj
+++ b/src/Rocket.Chat.Net.Example/Rocket.Chat.Net.Example.csproj
@@ -10,7 +10,7 @@
Properties
Rocket.Chat.Net.Example
Rocket.Chat.Net.Example
- v4.5
+ v4.8
512
true
@@ -48,26 +48,138 @@
v4.5
-
- ..\..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll
- True
+
+ ..\..\packages\Microsoft.Bcl.AsyncInterfaces.5.0.0\lib\net461\Microsoft.Bcl.AsyncInterfaces.dll
-
- ..\..\packages\RestSharp.105.2.3\lib\net45\RestSharp.dll
- True
+
+ ..\..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll
+
+
+ ..\..\packages\NLog.5.1.0\lib\net46\NLog.dll
+
+
+ ..\..\packages\Otp.NET.1.3.0\lib\net45\Otp.NET.dll
+
+
+ ..\..\packages\RestSharp.108.0.3\lib\netstandard2.0\RestSharp.dll
+
+
+ ..\..\packages\SuperSocket.ClientEngine.Core.0.10.0\lib\net45\SuperSocket.ClientEngine.dll
+
+ ..\..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll
+
+
+ ..\..\packages\System.Collections.Specialized.4.3.0\lib\net46\System.Collections.Specialized.dll
+ True
+ True
+
+
+
+
+ ..\..\packages\System.IO.4.3.0\lib\net462\System.IO.dll
+ True
+ True
+
+
+
+ ..\..\packages\System.Linq.4.3.0\lib\net463\System.Linq.dll
+ True
+ True
+
+
+ ..\..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll
+
+
+ ..\..\packages\System.Net.NameResolution.4.3.0\lib\net46\System.Net.NameResolution.dll
+ True
+ True
+
+
+ ..\..\packages\System.Net.Security.4.3.0\lib\net46\System.Net.Security.dll
+ True
+ True
+
+
+ ..\..\packages\System.Net.Sockets.4.3.0\lib\net46\System.Net.Sockets.dll
+ True
+ True
+
+
+
+ ..\..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll
+
+
+ ..\..\packages\System.Runtime.4.3.0\lib\net462\System.Runtime.dll
+ True
+ True
+
+
+ ..\..\packages\System.Runtime.CompilerServices.Unsafe.5.0.0\lib\net45\System.Runtime.CompilerServices.Unsafe.dll
+
+
+ ..\..\packages\System.Runtime.Extensions.4.3.0\lib\net462\System.Runtime.Extensions.dll
+ True
+ True
+
+
+ ..\..\packages\System.Runtime.InteropServices.4.3.0\lib\net463\System.Runtime.InteropServices.dll
+ True
+ True
+
+
+ ..\..\packages\System.Security.Cryptography.Algorithms.4.3.0\lib\net463\System.Security.Cryptography.Algorithms.dll
+ True
+ True
+
+
+ ..\..\packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll
+ True
+ True
+
+
+ ..\..\packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll
+ True
+ True
+
+
+ ..\..\packages\System.Security.Cryptography.X509Certificates.4.3.0\lib\net461\System.Security.Cryptography.X509Certificates.dll
+ True
+ True
+
+
+ ..\..\packages\System.Text.Encodings.Web.5.0.0\lib\net461\System.Text.Encodings.Web.dll
+
+
+ ..\..\packages\System.Text.Json.5.0.1\lib\net461\System.Text.Json.dll
+
+
+ ..\..\packages\System.Text.RegularExpressions.4.3.0\lib\net463\System.Text.RegularExpressions.dll
+ True
+ True
+
+
+ ..\..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll
+
+
+ ..\..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll
+
+
+ ..\..\packages\WebSocket4Net.0.15.2\lib\net45\WebSocket4Net.dll
+
+
@@ -81,7 +193,7 @@
Rocket.Chat.Net.Portability.Net45
- {a6ff1f57-0837-4f1a-9248-1cce8477295e}
+ {0c2862be-2cfb-4890-b154-4b4e7753e11f}
Rocket.Chat.Net.Bot
diff --git a/src/Rocket.Chat.Net.Example/packages.config b/src/Rocket.Chat.Net.Example/packages.config
index 5b899f3..6314ebe 100644
--- a/src/Rocket.Chat.Net.Example/packages.config
+++ b/src/Rocket.Chat.Net.Example/packages.config
@@ -1,6 +1,35 @@
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Rocket.Chat.Net/Driver/DdpClient.cs b/src/Rocket.Chat.Net/Driver/DdpClient.cs
index 0b4b959..5773158 100644
--- a/src/Rocket.Chat.Net/Driver/DdpClient.cs
+++ b/src/Rocket.Chat.Net/Driver/DdpClient.cs
@@ -12,7 +12,10 @@
using Rocket.Chat.Net.Interfaces;
using Rocket.Chat.Net.Models;
- using Rocket.Chat.Net.Portability.Websockets;
+ using WebSocket4Net;
+ using SuperSocket.ClientEngine;
+ using System.Security.Authentication;
+ using NLog;
public class DdpClient : IDdpClient
{
@@ -33,8 +36,8 @@ public DdpClient(string baseUrl, bool useSsl, ILogger logger)
var protocol = useSsl ? "wss" : "ws";
Url = $"{protocol}://{baseUrl}/websocket";
-
- _socket = new WebSocketWrapper(new PortableWebSocket(Url));
+
+ _socket = new WebSocketWrapper(new WebSocket(Url, sslProtocols : SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls));
AttachEvents();
}
@@ -59,19 +62,31 @@ private void SocketOnClosed(object sender, EventArgs eventArgs)
_logger.Debug("CLOSE");
if (SessionId != null && !IsDisposed)
{
- ConnectAsync(CancellationToken.None).Wait();
+ // TODO: Fix reconnect
+ try
+ {
+ ConnectAsync(CancellationToken.None).Wait();
+ }
+ catch (Exception ex)
+ {
+ _logger.Error(ex);
+ }
}
}
- private void SocketOnError(object sender, PortableErrorEventArgs errorEventArgs)
+ private void SocketOnError(object sender, ErrorEventArgs errorEventArgs)
{
_logger.Info("ERROR: " + errorEventArgs?.Exception?.Message);
}
- private void SocketOnOpened(object sender, EventArgs eventArgs)
+ private async void SocketOnOpened(object sender, EventArgs eventArgs)
{
_logger.Debug("OPEN");
+ await SendConnectRequest().ConfigureAwait(false);
+ }
+ public async Task SendConnectRequest()
+ {
_logger.Debug("Sending connection request");
const string ddpVersion = "1";
var request = new
@@ -85,14 +100,15 @@ private void SocketOnOpened(object sender, EventArgs eventArgs)
}
};
- SendObjectAsync(request, CancellationToken.None).Wait();
+ await SendObjectAsync(request, CancellationToken.None).ConfigureAwait(false);
}
- private void SocketOnMessage(object sender, PortableMessageReceivedEventArgs messageEventArgs)
+ // TODO: Real time API implementieren
+ private void SocketOnMessage(object sender, MessageReceivedEventArgs messageEventArgs)
{
var json = messageEventArgs.Message;
var data = JObject.Parse(json);
- _logger.Debug($"RECIEVED: {JsonConvert.SerializeObject(data, Formatting.Indented)}");
+ _logger.Debug($"RECEIVED: {JsonConvert.SerializeObject(data, Formatting.Indented)}");
var isRocketMessage = data?["msg"] != null;
if (isRocketMessage)
@@ -195,7 +211,8 @@ public async Task SubscribeAndWaitAsync(string name, CancellationToken t
};
await SendObjectAsync(request, token).ConfigureAwait(false);
- await WaitForIdOrReadyAsync(id, token).ConfigureAwait(false);
+ JObject result = await WaitForIdOrReadyAsync(id, token).ConfigureAwait(false);
+ var subscriptionResult = result.ToObject>();
return id;
}
diff --git a/src/Rocket.Chat.Net/Driver/RestClient.cs b/src/Rocket.Chat.Net/Driver/RestClient.cs
new file mode 100644
index 0000000..4f32f0e
--- /dev/null
+++ b/src/Rocket.Chat.Net/Driver/RestClient.cs
@@ -0,0 +1,208 @@
+using Newtonsoft.Json.Linq;
+using Rocket.Chat.Net.Interfaces;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+
+using RestSharp;
+using NLog;
+using WebSocketSharp;
+using RestSharp.Authenticators;
+using NLog.LayoutRenderers.Wrappers;
+using Rocket.Chat.Net.Models.RestResults;
+using System.IO;
+using Microsoft.CodeAnalysis;
+using System.Runtime.InteropServices.ComTypes;
+using System.Net.Mime;
+using NLog.LayoutRenderers;
+using System.Linq;
+
+namespace Rocket.Chat.Net.Driver
+{
+ public class RestClient : IRestClient
+ {
+ public RestSharp.RestClient _client;
+ private IAuthenticator _authenticator;
+ private bool _isLoggedIn;
+ private string _instanceUrl;
+ private bool _useSsl;
+ ILogger _logger;
+
+ public RestClient(string instanceUrl, bool useSsl, ILogger logger)
+ {
+ _logger = logger;
+ _instanceUrl = instanceUrl;
+ _useSsl = useSsl;
+ _client = new RestSharp.RestClient((useSsl ? "https" : "http") + "://" + instanceUrl + "/api/v1/");
+ }
+
+ private bool disposedValue;
+
+ public string Url => throw new NotImplementedException();
+
+ public bool IsDisposed => throw new NotImplementedException();
+
+ public bool IsLoggedIn { get => _isLoggedIn; }
+
+ ///
+ ///
+ ///
+ /// HTTP method, such as GET, POST, PUT etc.
+ ///
+ ///
+ ///
+ ///
+ public async Task CallAsync(RestSharp.Method method, string path, CancellationToken token, params object[] args)
+ {
+ var request = new RestRequest(path, method);
+ JArray data = JArray.FromObject(args);
+ if (data != null)
+ {
+ request.AddBody(data.ToString());
+ }
+ var response = await _client.ExecuteAsync(request).ConfigureAwait(false);
+ return JObject.Parse(response.Content);
+ }
+
+ ///
+ ///
+ ///
+ /// HTTP method, such as GET, POST, PUT etc.
+ ///
+ ///
+ ///
+ ///
+ public async Task CallAsync(RestSharp.Method method, string path, CancellationToken token, object data)
+ {
+ var request = new RestRequest(path, method);
+ if (data != null)
+ {
+ // TODO default serialization
+ request.AddBody(JObject.FromObject(data).ToString());
+ }
+ var response = await _client.ExecuteAsync(request).ConfigureAwait(false);
+ return JObject.Parse(response.Content);
+ }
+
+ ///
+ ///
+ ///
+ /// HTTP method, such as GET, POST, PUT etc.
+ ///
+ ///
+ ///
+ ///
+ public async Task DownloadAsync(string path, CancellationToken token)
+ {
+ var request = new RestRequest((_useSsl ? "https" : "http") + "://" + _instanceUrl + path, RestSharp.Method.Get);
+ var response = await _client.ExecuteAsync(request).ConfigureAwait(false);
+ if (response.RawBytes != null)
+ {
+ string filename = path.Split('/').Last();
+ string filePath = Path.GetTempPath() + Path.GetRandomFileName() + Path.GetExtension(path);
+
+ // Fallback with random file name
+ while (System.IO.File.Exists(filePath))
+ {
+ filePath = Path.GetTempPath() + Path.GetRandomFileName() + Path.GetExtension(filename);
+ }
+
+ using (var fs = new FileStream(filePath, FileMode.OpenOrCreate))
+ {
+ fs.Write(response.RawBytes, 0, response.RawBytes.Length);
+ }
+
+ return filePath;
+ }
+
+ return null;
+ }
+
+ public async Task UploadAsync(RestSharp.Method method, string path, CancellationToken token, params object[] args)
+ {
+ var request = new RestRequest(path, method);
+ request.AlwaysMultipartFormData = true;
+ for (int i = 0; i < args.Length; i++)
+ {
+ // TODO default serialization
+ if (args[i] is string)
+ request.AddFile("file", args[i].ToString());
+ else if (args[i] is FileStream)
+ {
+ var fs = args[i] as FileStream;
+ request.AddFile("file", () => fs, fs.Name);
+ }
+ }
+ var response = await _client.ExecuteAsync(request).ConfigureAwait(false);
+ return JObject.Parse(response.Content);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (!disposedValue)
+ {
+ if (disposing)
+ {
+ // TODO: Verwalteten Zustand (verwaltete Objekte) bereinigen
+ _client.Dispose();
+ }
+
+ // TODO: Nicht verwaltete Ressourcen (nicht verwaltete Objekte) freigeben und Finalizer überschreiben
+ // TODO: Große Felder auf NULL setzen
+ disposedValue = true;
+ }
+ }
+
+ // // TODO: Finalizer nur überschreiben, wenn "Dispose(bool disposing)" Code für die Freigabe nicht verwalteter Ressourcen enthält
+ // ~RestClient()
+ // {
+ // // Ändern Sie diesen Code nicht. Fügen Sie Bereinigungscode in der Methode "Dispose(bool disposing)" ein.
+ // Dispose(disposing: false);
+ // }
+
+ public void Dispose()
+ {
+ // Ändern Sie diesen Code nicht. Fügen Sie Bereinigungscode in der Methode "Dispose(bool disposing)" ein.
+ Dispose(disposing: true);
+ GC.SuppressFinalize(this);
+ }
+
+ public async Task LoginAsync(object args)
+ {
+ var response = await CallAsync(Method.Post, "login", CancellationToken.None, args).ConfigureAwait(false);
+ var result = response.ToObject>();
+ if (result.Success)
+ {
+ string authToken = result.Data.AuthToken;
+ string userId = result.Data.UserId;
+ _client.Authenticator = new RocketAuthenticator(userId, authToken);
+ _isLoggedIn = true;
+ } else
+ {
+ _logger.Error($"Login Error: {result.Error}");
+ }
+ return result;
+ }
+ }
+
+ public class RocketAuthenticator : IAuthenticator
+ {
+ private string authToken;
+ private string userId;
+
+ public RocketAuthenticator(string userId, string authToken)
+ {
+ this.authToken = authToken;
+ this.userId = userId;
+ }
+
+ public ValueTask Authenticate(RestSharp.RestClient client, RestRequest request)
+ {
+ request.AddHeader("X-Auth-Token", authToken);
+ request.AddHeader("X-User-Id", userId);
+ return new ValueTask();
+ }
+ }
+}
diff --git a/src/Rocket.Chat.Net/Driver/RocketChatDriver.cs b/src/Rocket.Chat.Net/Driver/RocketChatDriver.cs
index fc30fa4..4d30520 100644
--- a/src/Rocket.Chat.Net/Driver/RocketChatDriver.cs
+++ b/src/Rocket.Chat.Net/Driver/RocketChatDriver.cs
@@ -2,6 +2,7 @@
{
using System;
using System.Collections.Generic;
+ using System.ComponentModel.Design;
using System.IO;
using System.Linq;
using System.Threading;
@@ -11,25 +12,26 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
-
+ using NLog;
using Rocket.Chat.Net.Collections;
using Rocket.Chat.Net.Helpers;
using Rocket.Chat.Net.Interfaces;
- using Rocket.Chat.Net.Loggers;
using Rocket.Chat.Net.Models;
using Rocket.Chat.Net.Models.Collections;
using Rocket.Chat.Net.Models.LoginOptions;
using Rocket.Chat.Net.Models.MethodResults;
+ using Rocket.Chat.Net.Models.RestResults;
using Rocket.Chat.Net.Models.SubscriptionResults;
public class RocketChatDriver : IRocketChatDriver
{
- private const string MessageTopic = "stream-messages";
+ private const string MessageTopic = "stream-room-messages";
private const int MessageSubscriptionLimit = 10;
private readonly IStreamCollectionDatabase _collectionDatabase;
private readonly ILogger _logger;
private readonly IDdpClient _client;
+ private readonly IRestClient _restClient;
public event MessageReceived MessageReceived;
public event DdpReconnect DdpReconnect;
@@ -49,7 +51,7 @@ public class RocketChatDriver : IRocketChatDriver
public RocketChatDriver(string url, bool useSsl, ILogger logger = null, bool isBot = true, JsonSerializerSettings jsonSerializerSettings = null)
{
IsBot = isBot;
- _logger = logger ?? new DummyLogger();
+ _logger = logger ?? NLog.LogManager.CreateNullLogger();
_collectionDatabase = new StreamCollectionDatabase();
_logger.Info("Creating client...");
@@ -57,6 +59,8 @@ public RocketChatDriver(string url, bool useSsl, ILogger logger = null, bool isB
_client.DataReceivedRaw += ClientOnDataReceivedRaw;
_client.DdpReconnect += OnDdpReconnect;
SetJsonOptions(jsonSerializerSettings);
+
+ _restClient = new RestClient(url, useSsl, logger);
}
public RocketChatDriver(ILogger logger, IDdpClient client, IStreamCollectionDatabase collectionDatabaseDatabase, bool isBot = true,
@@ -118,13 +122,13 @@ private void HandleStreamingCollections(string type, JObject data)
private void HandleRocketMessage(string type, JObject data)
{
var o = data.ToObject>(JsonSerializer);
- var isMessage = type == "added" && o.Collection == MessageTopic && o.Fields["args"] != null;
+ var isMessage = type == "changed" && o.Collection == MessageTopic && o.Fields["args"] != null;
if (!isMessage)
{
return;
}
- var messageRaw = o.Fields["args"][1];
+ var messageRaw = o.Fields["args"][0];
var message = messageRaw.ToObject(JsonSerializer);
message.IsBotMentioned = message.Mentions.Any(x => x.Id == UserId);
message.IsFromMyself = message.CreatedBy.Id == UserId;
@@ -180,8 +184,30 @@ public async Task SubscribeToRoomListAsync()
public async Task SubscribeToRoomAsync(string roomId = null)
{
- _logger.Info($"Subscribing to Room: #{roomId ?? "ALLROOMS"}");
- await _client.SubscribeAsync(MessageTopic, TimeoutToken, roomId, MessageSubscriptionLimit.ToString()).ConfigureAwait(false);
+ List ids = new List();
+
+ // Subscribe to all rooms when roomId is null
+ if (roomId == null)
+ {
+ var methodResult = await GetAvailableRoomInfoCollection().ConfigureAwait(false);
+ ids.AddRange(methodResult.Result.Where(roomInfo => roomInfo.Type != RoomType.DirectMessage).Select(roomInfo => roomInfo.Id));
+ } else
+ // Subsribe to given roomId
+ {
+ ids.Add(roomId);
+ }
+
+ List tasks = new List();
+ foreach (string id in ids)
+ {
+ _logger.Info($"Subscribing to Room: #{id}");
+ Task task = new Task(() => _client.SubscribeAndWaitAsync(MessageTopic, TimeoutToken, id, false));
+ tasks.Add(task);
+ task.Start();
+ }
+
+ await Task.WhenAll(tasks).ConfigureAwait(false);
+ await _client.SubscribeAndWaitAsync("stream-notify-user", TimeoutToken, $"{UserId}/subscriptions -changed", false);
}
public async Task SubscribeToRoomInformationAsync(string roomName, RoomType type)
@@ -228,34 +254,42 @@ public async Task PingAsync()
await _client.PingAsync(TimeoutToken).ConfigureAwait(false);
}
+ // TODO: Reuse login option for REST?
public async Task> LoginAsync(ILoginOption loginOption)
{
+ if (loginOption is IRestLoginOption)
+ {
+ await LoginRestApi(loginOption);
+ }
var ldapLogin = loginOption as LdapLoginOption;
if (ldapLogin != null)
{
- return await LoginWithLdapAsync(ldapLogin.Username, ldapLogin.Password).ConfigureAwait(false);
+ return await LoginWithLdapAsync(ldapLogin).ConfigureAwait(false);
}
var emailLogin = loginOption as EmailLoginOption;
if (emailLogin != null)
{
- return await LoginWithEmailAsync(emailLogin.Email, emailLogin.Password).ConfigureAwait(false);
+ return await LoginWithEmailAsync(emailLogin).ConfigureAwait(false);
}
var usernameLogin = loginOption as UsernameLoginOption;
if (usernameLogin != null)
{
- return await LoginWithUsernameAsync(usernameLogin.Username, usernameLogin.Password).ConfigureAwait(false);
+ return await LoginWithUsernameAsync(usernameLogin).ConfigureAwait(false);
}
var resumeLogin = loginOption as ResumeLoginOption;
- if (resumeLogin != null)
+ if (resumeLogin != null)
{
- return await LoginResumeAsync(resumeLogin.Token).ConfigureAwait(false);
+ return await LoginResumeAsync(resumeLogin).ConfigureAwait(false);
}
throw new NotSupportedException($"The given login option `{loginOption.GetType()}` is not supported.");
}
- public async Task> LoginWithEmailAsync(string email, string password)
+ public async Task> LoginWithEmailAsync(EmailLoginOption login)
{
+ string email = login.Email;
+ string password = login.Password;
+
_logger.Info($"Logging in with user {email} using an email...");
var passwordHash = EncodingHelper.Sha256Hash(password);
var request = new
@@ -274,8 +308,11 @@ public async Task> LoginWithEmailAsync(string email, s
return await InternalLoginAsync(request).ConfigureAwait(false);
}
- public async Task> LoginWithUsernameAsync(string username, string password)
+ public async Task> LoginWithUsernameAsync(UsernameLoginOption login)
{
+ string username = login.Username;
+ string password = login.Password;
+
_logger.Info($"Logging in with user {username} using a username...");
var passwordHash = EncodingHelper.Sha256Hash(password);
var request = new
@@ -294,8 +331,11 @@ public async Task> LoginWithUsernameAsync(string usern
return await InternalLoginAsync(request).ConfigureAwait(false);
}
- public async Task> LoginWithLdapAsync(string username, string password)
+ public async Task> LoginWithLdapAsync(LdapLoginOption login)
{
+ string username = login.Username;
+ string password = login.Password;
+
_logger.Info($"Logging in with user {username} using LDAP...");
var request = new
{
@@ -308,8 +348,10 @@ public async Task> LoginWithLdapAsync(string username,
return await InternalLoginAsync(request).ConfigureAwait(false);
}
- public async Task> LoginResumeAsync(string sessionToken)
+ public async Task> LoginResumeAsync(ResumeLoginOption login)
{
+ string sessionToken = login.Token;
+
_logger.Info($"Resuming session {sessionToken}");
var request = new
{
@@ -348,12 +390,27 @@ private async Task> InternalLoginAsync(object request)
return result;
}
+ ///
+ /// This method will retry the request with a totp code additionally sent to the server.
+ /// https://developer.rocket.chat/reference/api/realtime-api/2fa
+ ///
+ ///
+ ///
+ ///
+ private async Task> InternalTotpAsync(MethodResult errorResponse, object originalRequest, string totpCode)
+ {
+ var data = await _client.CallAsync("callWithTwoFactorRequired ", TimeoutToken, originalRequest).ConfigureAwait(false);
+ var result = data.ToObject>(JsonSerializer);
+ return result;
+ }
+
private async Task SetDriverUserInfoAsync(string userId)
{
UserId = userId;
var collection = await _collectionDatabase.WaitForObjectInCollectionAsync("users", userId, TimeoutToken).ConfigureAwait(false);
var user = collection.GetById(userId);
Username = user?.Username;
+ _logger.Info($"Logged in to RocketChat with the following username: {Username}");
}
public async Task RegisterUserAsync(string name, string emailOrUsername, string password)
@@ -417,35 +474,83 @@ public async Task JoinRoomAsync(string roomId)
return result.ToObject(JsonSerializer);
}
- public async Task> SendMessageAsync(string text, string roomId)
+ public async Task> SendMessageAsync(string text, string roomId, Attachment[] attachments = null)
{
_logger.Info($"Sending message to #{roomId}: {text}");
var request = new
{
msg = text,
rid = roomId,
- bot = IsBot
+ bot = IsBot,
+ attachments
};
var result = await _client.CallAsync("sendMessage", TimeoutToken, request).ConfigureAwait(false);
return result.ToObject>(JsonSerializer);
}
- public async Task> SendCustomMessageAsync(Attachment attachment, string roomId)
+ public async Task> SendCustomMessageAsync(Attachment[] attachments, string roomId)
{
var request = new
{
msg = "",
rid = roomId,
bot = IsBot,
- attachments = new[]
- {
- attachment
- }
+ attachments
};
var result = await _client.CallAsync("sendMessage", TimeoutToken, request).ConfigureAwait(false);
return result.ToObject>(JsonSerializer);
}
+ public async Task> SendCustomMessageAsync(Attachment attachment, string roomId)
+ {
+ return await SendCustomMessageAsync(new Attachment[] { attachment }, roomId).ConfigureAwait(false);
+ }
+
+ public async Task UploadFileToRoomAsync(string roomId, params object[] args)
+ {
+ var data = await _restClient.UploadAsync(RestSharp.Method.Post, $"rooms.upload/{roomId}", TimeoutToken, args).ConfigureAwait(false);
+
+ return data.ToObject(JsonSerializer);
+
+ }
+
+ public async Task> GetAttachments(RocketMessage message)
+ {
+ // TODO: Media handling
+ List result = new List();
+ foreach (Attachment attachment in message.Attachments)
+ {
+ try
+ {
+ string attachmentPath = String.Empty;
+ if (attachment.TitleLinkDownloadable ?? false)
+ {
+ attachmentPath = await _restClient.DownloadAsync(attachment.TitleLink, TimeoutToken);
+ }
+ else if (attachment.ImageUrl != null)
+ {
+ attachmentPath = await _restClient.DownloadAsync(attachment.ImageUrl, TimeoutToken);
+ }
+ if (attachmentPath != null)
+ {
+ result.Add(attachmentPath);
+ }
+ else
+ {
+ _logger.Warn("Attachment could not be downloaded!");
+ }
+
+ }
+ catch (Exception ex)
+ {
+ _logger.Error(ex);
+ }
+
+
+ }
+ return result;
+ }
+
public async Task UpdateMessageAsync(string messageId, string roomId, string newMessage)
{
_logger.Info($"Updating message {messageId}");
@@ -507,13 +612,13 @@ public async Task> HideRoomAsync(string roomId)
return results.ToObject>(JsonSerializer);
}
- public async Task> EraseRoomAsync(string roomId)
+ public async Task> EraseRoomAsync(string roomId)
{
_logger.Info($"Deleting room {roomId}.");
var results =
await _client.CallAsync("eraseRoom", TimeoutToken, roomId).ConfigureAwait(false);
- return results.ToObject>(JsonSerializer);
+ return results.ToObject>(JsonSerializer);
}
public async Task ResetAvatarAsync()
@@ -617,6 +722,26 @@ public TypedStreamCollection GetRoomInfoCollection()
return typedCollection;
}
+ public async Task>> GetAvailableRoomInfoCollection()
+ {
+ JObject result = await _client.CallAsync("rooms/get", TimeoutToken, 0).ConfigureAwait(false);
+ return result.ToObject>>(JsonSerializer);
+ }
+
+ public async Task> GetAvailableRoomsCollection()
+ {
+ JObject result = await _client.CallAsync("rooms/get", TimeoutToken, new object[] { 0 }).ConfigureAwait(false);
+ MethodResult> roomMethodResult = result.ToObject>>(JsonSerializer);
+ throw new NotImplementedException();
+ }
+
+ public async Task SetUserPresence(string status)
+ {
+ // await _client.CallAsync("UserPresence:setDefaultStatus", TimeoutToken, status);
+ await _client.CallAsync($"UserPresence:{status}", TimeoutToken);
+
+ }
+
public void Dispose()
{
_client.Dispose();
@@ -635,5 +760,10 @@ private CancellationToken CreateTimeoutToken()
return source.Token;
}
+
+ public async Task LoginRestApi(object args)
+ {
+ await _restClient.LoginAsync(args).ConfigureAwait(false);
+ }
}
}
\ No newline at end of file
diff --git a/src/Rocket.Chat.Net/Driver/WebSocketWrapper.cs b/src/Rocket.Chat.Net/Driver/WebSocketWrapper.cs
index 7ca303e..7c88fc0 100644
--- a/src/Rocket.Chat.Net/Driver/WebSocketWrapper.cs
+++ b/src/Rocket.Chat.Net/Driver/WebSocketWrapper.cs
@@ -3,18 +3,19 @@
using System;
using Rocket.Chat.Net.Interfaces;
- using Rocket.Chat.Net.Portability.Websockets;
+ using WebSocket4Net;
+ using SuperSocket.ClientEngine;
public class WebSocketWrapper : IWebSocketWrapper
{
- private readonly PortableWebSocket _socket;
+ private readonly WebSocket _socket;
- public WebSocketWrapper(PortableWebSocket socket)
+ public WebSocketWrapper(WebSocket socket)
{
_socket = socket;
}
- public event EventHandler MessageReceived
+ public event EventHandler MessageReceived
{
add { _socket.MessageReceived += value; }
remove { _socket.MessageReceived -= value; }
@@ -26,7 +27,7 @@ public event EventHandler Closed
remove { _socket.Closed -= value; }
}
- public event EventHandler Error
+ public event EventHandler Error
{
add { _socket.Error += value; }
remove { _socket.Error -= value; }
diff --git a/src/Rocket.Chat.Net/Helpers/EncodingHelper.cs b/src/Rocket.Chat.Net/Helpers/EncodingHelper.cs
index 1ae950d..59e0725 100644
--- a/src/Rocket.Chat.Net/Helpers/EncodingHelper.cs
+++ b/src/Rocket.Chat.Net/Helpers/EncodingHelper.cs
@@ -2,8 +2,8 @@
{
using System;
using System.IO;
-
- using Rocket.Chat.Net.Portability.Crypto;
+ using System.Text;
+ using System.Security.Cryptography;
public static class EncodingHelper
{
@@ -11,8 +11,19 @@ public static class EncodingHelper
public static string Sha256Hash(string value)
{
- var portableCrypto = new ShaHelper();
- return portableCrypto.Sha256Hash(value);
+ var builder = new StringBuilder();
+ var encoding = Encoding.UTF8;
+
+ using (var hash = SHA256.Create())
+ {
+ var result = hash.ComputeHash(encoding.GetBytes(value));
+ foreach (var b in result)
+ {
+ builder.Append(b.ToString("x2"));
+ }
+ }
+
+ return builder.ToString();
}
public static string ConvertToBase64(Stream stream)
diff --git a/src/Rocket.Chat.Net/Interfaces/Driver/IRocketClientManagement.cs b/src/Rocket.Chat.Net/Interfaces/Driver/IRocketClientManagement.cs
index 25ccfac..38b5302 100644
--- a/src/Rocket.Chat.Net/Interfaces/Driver/IRocketClientManagement.cs
+++ b/src/Rocket.Chat.Net/Interfaces/Driver/IRocketClientManagement.cs
@@ -3,6 +3,7 @@
using System.Threading.Tasks;
using Rocket.Chat.Net.Models;
+ using Rocket.Chat.Net.Models.LoginOptions;
using Rocket.Chat.Net.Models.MethodResults;
public interface IRocketClientManagement
@@ -19,7 +20,7 @@ public interface IRocketClientManagement
/// Email to use
/// Plaintext password to use (will be SHA-256 before sending)
///
- Task> LoginWithEmailAsync(string email, string password);
+ Task> LoginWithEmailAsync(EmailLoginOption login);
///
/// Login with LDAP
@@ -27,7 +28,7 @@ public interface IRocketClientManagement
/// Email/Username to use
/// Plaintext password to use
///
- Task> LoginWithLdapAsync(string username, string password);
+ Task> LoginWithLdapAsync(LdapLoginOption login);
///
/// Login with username
@@ -35,14 +36,14 @@ public interface IRocketClientManagement
/// Username to use
/// Plaintext password to use (will be SHA-256 before sending)
///
- Task> LoginWithUsernameAsync(string username, string password);
+ Task> LoginWithUsernameAsync(UsernameLoginOption login);
///
/// Resume a login session
///
/// Active token given from a previous login
///
- Task> LoginResumeAsync(string sessionToken);
+ Task> LoginResumeAsync(ResumeLoginOption login);
///
/// Login with a ILogin object
@@ -77,5 +78,7 @@ public interface IRocketClientManagement
/// Parameters to include in the subscription
///
Task SubscribeToAsync(string streamName, params object[] o);
+
+ Task SetUserPresence(string status);
}
}
\ No newline at end of file
diff --git a/src/Rocket.Chat.Net/Interfaces/Driver/IRocketMessagingManagement.cs b/src/Rocket.Chat.Net/Interfaces/Driver/IRocketMessagingManagement.cs
index 58bbcd2..8933e98 100644
--- a/src/Rocket.Chat.Net/Interfaces/Driver/IRocketMessagingManagement.cs
+++ b/src/Rocket.Chat.Net/Interfaces/Driver/IRocketMessagingManagement.cs
@@ -16,7 +16,7 @@ public interface IRocketMessagingManagement
/// Text of the message
/// The room to send to
///
- Task> SendMessageAsync(string text, string roomId);
+ Task> SendMessageAsync(string text, string roomId, Attachment[] attachments = null);
///
/// Edit a message by messageId
@@ -91,5 +91,13 @@ Task> LoadMessagesAsync(string roomId, DateTime
/// Room to send to
///
Task> SendCustomMessageAsync(Attachment attachment, string roomId);
+
+ ///
+ /// Send a message with an attachment.
+ ///
+ /// Attachment to include
+ /// Room to send to
+ ///
+ Task> SendCustomMessageAsync(Attachment[] attachments, string roomId);
}
}
\ No newline at end of file
diff --git a/src/Rocket.Chat.Net/Interfaces/Driver/IRocketRestClientManagement.cs b/src/Rocket.Chat.Net/Interfaces/Driver/IRocketRestClientManagement.cs
new file mode 100644
index 0000000..a6620dc
--- /dev/null
+++ b/src/Rocket.Chat.Net/Interfaces/Driver/IRocketRestClientManagement.cs
@@ -0,0 +1,23 @@
+using Rocket.Chat.Net.Models;
+using Rocket.Chat.Net.Models.RestResults;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Rocket.Chat.Net.Interfaces.Driver
+{
+ public interface IRocketRestClientManagement
+ {
+ Task LoginRestApi(object loginArgs);
+
+ Task UploadFileToRoomAsync(string roomId, params object[] args);
+
+ ///
+ /// Retrieves the attachments to a temporary folder and returns the paths where they are stored at.
+ ///
+ /// Message containing the attachments
+ ///
+ Task> GetAttachments(RocketMessage message);
+ }
+}
diff --git a/src/Rocket.Chat.Net/Interfaces/Driver/IRocketRoomManagement.cs b/src/Rocket.Chat.Net/Interfaces/Driver/IRocketRoomManagement.cs
index 352bdba..7e5ba0a 100644
--- a/src/Rocket.Chat.Net/Interfaces/Driver/IRocketRoomManagement.cs
+++ b/src/Rocket.Chat.Net/Interfaces/Driver/IRocketRoomManagement.cs
@@ -58,7 +58,7 @@ public interface IRocketRoomManagement
///
/// Room to delete by id
/// Number impacted?
- Task> EraseRoomAsync(string roomId);
+ Task> EraseRoomAsync(string roomId);
///
/// Creates a new private group.
@@ -92,6 +92,12 @@ public interface IRocketRoomManagement
[Obsolete("Use the property Rooms instead. This will be removed in version 2.")]
TypedStreamCollection GetRoomInfoCollection();
+ ///
+ /// This is the method call used to get all the rooms a user belongs to.
+ ///
+ ///
+ Task>> GetAvailableRoomInfoCollection();
+
///
/// Subscribe to information about a single room.
///
diff --git a/src/Rocket.Chat.Net/Interfaces/ILogger.cs b/src/Rocket.Chat.Net/Interfaces/ILogger.cs
deleted file mode 100644
index eaf2aa8..0000000
--- a/src/Rocket.Chat.Net/Interfaces/ILogger.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-namespace Rocket.Chat.Net.Interfaces
-{
- public interface ILogger
- {
- void Debug(string message);
-
- void Info(string message);
-
- void Warn(string message);
-
- void Error(string message);
-
- void Fatal(string message);
- }
-}
\ No newline at end of file
diff --git a/src/Rocket.Chat.Net/Interfaces/ILoginOption.cs b/src/Rocket.Chat.Net/Interfaces/ILoginOption.cs
index 413ddd7..382f8b9 100644
--- a/src/Rocket.Chat.Net/Interfaces/ILoginOption.cs
+++ b/src/Rocket.Chat.Net/Interfaces/ILoginOption.cs
@@ -1,6 +1,21 @@
-namespace Rocket.Chat.Net.Interfaces
+using OtpNet;
+using System.Text.Json.Serialization;
+
+namespace Rocket.Chat.Net.Interfaces
{
public interface ILoginOption
{
+
+ Totp TOTPSeed
+ {
+ get;
+ set;
+ }
+
+ string TOTPToken
+ {
+ get;
+ set;
+ }
}
}
\ No newline at end of file
diff --git a/src/Rocket.Chat.Net/Interfaces/IRestClient.cs b/src/Rocket.Chat.Net/Interfaces/IRestClient.cs
new file mode 100644
index 0000000..47c2a7b
--- /dev/null
+++ b/src/Rocket.Chat.Net/Interfaces/IRestClient.cs
@@ -0,0 +1,23 @@
+using Newtonsoft.Json.Linq;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading.Tasks;
+using System.Threading;
+using Rocket.Chat.Net.Models.RestResults;
+
+namespace Rocket.Chat.Net.Interfaces
+{
+ public interface IRestClient : IDisposable
+ {
+ string Url { get; }
+ bool IsDisposed { get; }
+ Task CallAsync(RestSharp.Method method, string path, CancellationToken token, params object[] args);
+
+ Task DownloadAsync(string path, CancellationToken token);
+
+ Task UploadAsync(RestSharp.Method method, string path, CancellationToken token, params object[] args);
+ Task LoginAsync(object args);
+
+ }
+}
diff --git a/src/Rocket.Chat.Net/Interfaces/IRestLoginOption.cs b/src/Rocket.Chat.Net/Interfaces/IRestLoginOption.cs
new file mode 100644
index 0000000..4e1a1ae
--- /dev/null
+++ b/src/Rocket.Chat.Net/Interfaces/IRestLoginOption.cs
@@ -0,0 +1,11 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Rocket.Chat.Net.Interfaces
+{
+ public interface IRestLoginOption : ILoginOption
+ {
+
+ }
+}
diff --git a/src/Rocket.Chat.Net/Interfaces/IRocketChatDriver.cs b/src/Rocket.Chat.Net/Interfaces/IRocketChatDriver.cs
index 1ec9d42..cb68c9c 100644
--- a/src/Rocket.Chat.Net/Interfaces/IRocketChatDriver.cs
+++ b/src/Rocket.Chat.Net/Interfaces/IRocketChatDriver.cs
@@ -5,6 +5,7 @@
using Rocket.Chat.Net.Interfaces.Driver;
public interface IRocketChatDriver : IDisposable,
+ IRocketRestClientManagement,
IRocketClientManagement,
IRocketUserManagement,
IRocketMessagingManagement,
diff --git a/src/Rocket.Chat.Net/Interfaces/IWebSocketWrapper.cs b/src/Rocket.Chat.Net/Interfaces/IWebSocketWrapper.cs
index f213ce5..339aca6 100644
--- a/src/Rocket.Chat.Net/Interfaces/IWebSocketWrapper.cs
+++ b/src/Rocket.Chat.Net/Interfaces/IWebSocketWrapper.cs
@@ -2,13 +2,14 @@
{
using System;
- using Rocket.Chat.Net.Portability.Websockets;
+ using WebSocket4Net;
+ using SuperSocket.ClientEngine;
public interface IWebSocketWrapper
{
- event EventHandler MessageReceived;
+ event EventHandler MessageReceived;
event EventHandler Closed;
- event EventHandler Error;
+ event EventHandler Error;
event EventHandler Opened;
void Open();
void Close();
diff --git a/src/Rocket.Chat.Net/JsonConverters/RestApiConverter.cs b/src/Rocket.Chat.Net/JsonConverters/RestApiConverter.cs
new file mode 100644
index 0000000..a1c5628
--- /dev/null
+++ b/src/Rocket.Chat.Net/JsonConverters/RestApiConverter.cs
@@ -0,0 +1,36 @@
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Rocket.Chat.Net.JsonConverters
+{
+ public class RestApiStatusConverter : JsonConverter
+ {
+ public override bool CanConvert(Type objectType)
+ {
+ return objectType == typeof(string);
+ }
+
+ public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+ {
+ var value = reader.Value;
+ if (value == null || String.IsNullOrWhiteSpace(value.ToString()))
+ {
+ return false;
+ }
+
+ if ("success".Equals(value.ToString(), StringComparison.OrdinalIgnoreCase))
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/src/Rocket.Chat.Net/Loggers/DummyLogger.cs b/src/Rocket.Chat.Net/Loggers/DummyLogger.cs
deleted file mode 100644
index 6a6c56d..0000000
--- a/src/Rocket.Chat.Net/Loggers/DummyLogger.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-namespace Rocket.Chat.Net.Loggers
-{
- using Rocket.Chat.Net.Interfaces;
-
- public class DummyLogger : ILogger
- {
- public void Debug(string message)
- {
- }
-
- public void Info(string message)
- {
- }
-
- public void Warn(string message)
- {
- }
-
- public void Error(string message)
- {
- }
-
- public void Fatal(string message)
- {
- }
- }
-}
\ No newline at end of file
diff --git a/src/Rocket.Chat.Net/Models/Action.cs b/src/Rocket.Chat.Net/Models/Action.cs
new file mode 100644
index 0000000..083fd9e
--- /dev/null
+++ b/src/Rocket.Chat.Net/Models/Action.cs
@@ -0,0 +1,23 @@
+using JetBrains.Annotations;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Rocket.Chat.Net.Models
+{
+ public class Action
+ {
+ [JsonProperty("type")]
+ public string Type { get; set; }
+
+ [JsonProperty("msg_in_chat_window")]
+ public bool MsgInChatWindow { get; set; }
+
+ [JsonProperty("text")]
+ public string Text { get; set; }
+
+ [JsonProperty("msg")]
+ public string Message { get; set; }
+ }
+}
diff --git a/src/Rocket.Chat.Net/Models/Attachment.cs b/src/Rocket.Chat.Net/Models/Attachment.cs
index afe41ec..8e5deb0 100644
--- a/src/Rocket.Chat.Net/Models/Attachment.cs
+++ b/src/Rocket.Chat.Net/Models/Attachment.cs
@@ -1,11 +1,13 @@
namespace Rocket.Chat.Net.Models
{
using System;
-
+ using System.Collections;
+ using System.Collections.Generic;
using Newtonsoft.Json;
using Rocket.Chat.Net.JsonConverters;
+ [JsonObject(ItemNullValueHandling = NullValueHandling.Ignore)]
public class Attachment
{
[JsonProperty(PropertyName = "title")]
@@ -32,20 +34,24 @@ public class Attachment
[JsonProperty(PropertyName = "thumb_url")]
public string ThumbUrl { get; set; }
+ [JsonProperty(PropertyName = "actions")]
+ public IEnumerable Actions { get; set; }
+
///
/// e.g. #FF0000
///
[JsonProperty(PropertyName = "color")]
public string Color { get; set; }
- [JsonProperty(PropertyName = "ts"), JsonConverter(typeof(MeteorDateConverter))]
+ // [JsonProperty(PropertyName = "ts"), JsonConverter(typeof(MeteorDateConverter))]
+ [JsonProperty(PropertyName = "ts")]
public DateTime? Timestamp { get; set; }
protected bool Equals(Attachment other)
{
return string.Equals(Title, other.Title) && string.Equals(TitleLink, other.TitleLink) && TitleLinkDownloadable == other.TitleLinkDownloadable
&& string.Equals(Text, other.Text) && string.Equals(ImageUrl, other.ImageUrl) && string.Equals(AuthorName, other.AuthorName)
- && string.Equals(AuthorIcon, other.AuthorIcon) && string.Equals(ThumbUrl, other.ThumbUrl) && string.Equals(Color, other.Color)
+ && string.Equals(AuthorIcon, other.AuthorIcon) && string.Equals(ThumbUrl, other.ThumbUrl) && string.Equals(Color, other.Color) && string.Equals(Actions, other.Actions)
&& Timestamp.Equals(other.Timestamp);
}
diff --git a/src/Rocket.Chat.Net/Models/LoginOptions/EmailLoginOption.cs b/src/Rocket.Chat.Net/Models/LoginOptions/EmailLoginOption.cs
index a6ee176..2d71e92 100644
--- a/src/Rocket.Chat.Net/Models/LoginOptions/EmailLoginOption.cs
+++ b/src/Rocket.Chat.Net/Models/LoginOptions/EmailLoginOption.cs
@@ -1,17 +1,46 @@
namespace Rocket.Chat.Net.Models.LoginOptions
{
+ using Newtonsoft.Json;
+ using OtpNet;
using Rocket.Chat.Net.Interfaces;
-
- public class EmailLoginOption : ILoginOption
+ using System.Runtime.CompilerServices;
+
+ public class EmailLoginOption : IRestLoginOption
{
+
+ private Totp totpSeed;
+ private string totpToken;
+
///
/// Email of the user to login as. Should be in the format of user@example.com.
///
+ [JsonProperty(PropertyName = "user")]
public string Email { get; set; }
///
/// Plaintext password of the user.
///
+ [JsonProperty(PropertyName = "password")]
public string Password { get; set; }
+
+ [JsonIgnore]
+ public Totp TOTPSeed {
+ get => totpSeed ;
+ set => totpSeed = value;
+ }
+
+ [JsonIgnore]
+ public string TOTPToken {
+ get
+ {
+ if (this.totpSeed != null)
+ totpToken = totpSeed.ComputeTotp();
+ return totpToken;
+ }
+ set
+ {
+ totpToken = value;
+ }
+ }
}
}
\ No newline at end of file
diff --git a/src/Rocket.Chat.Net/Models/LoginOptions/LdapLoginOption.cs b/src/Rocket.Chat.Net/Models/LoginOptions/LdapLoginOption.cs
index c9d0e2b..bc57126 100644
--- a/src/Rocket.Chat.Net/Models/LoginOptions/LdapLoginOption.cs
+++ b/src/Rocket.Chat.Net/Models/LoginOptions/LdapLoginOption.cs
@@ -1,20 +1,50 @@
namespace Rocket.Chat.Net.Models.LoginOptions
{
+ using OtpNet;
using System.Diagnostics.CodeAnalysis;
using Rocket.Chat.Net.Interfaces;
+ using Newtonsoft.Json;
[SuppressMessage("ReSharper", "UnusedAutoPropertyAccessor.Global")]
- public class LdapLoginOption : ILoginOption
+ public class LdapLoginOption : IRestLoginOption
{
+ private Totp totpSeed;
+ private string totpToken;
+
///
/// Username of the user to login as. Do not include the domain in which this user resides.
///
+ [JsonProperty(PropertyName = "user")]
public string Username { get; set; }
///
/// Plaintext password of the user.
///
+ [JsonProperty(PropertyName = "password")]
public string Password { get; set; }
+
+ [JsonIgnore]
+ public Totp TOTPSeed
+ {
+ get => totpSeed;
+ set => totpSeed = value;
+ }
+
+ [JsonIgnore]
+
+ public string TOTPToken
+ {
+ get
+ {
+ if (this.totpSeed != null)
+ totpToken = totpSeed.ComputeTotp();
+ return totpToken;
+ }
+ set
+ {
+ totpToken = value;
+ }
+ }
}
}
\ No newline at end of file
diff --git a/src/Rocket.Chat.Net/Models/LoginOptions/ResumeLoginOption.cs b/src/Rocket.Chat.Net/Models/LoginOptions/ResumeLoginOption.cs
index 44e1a9a..d510990 100644
--- a/src/Rocket.Chat.Net/Models/LoginOptions/ResumeLoginOption.cs
+++ b/src/Rocket.Chat.Net/Models/LoginOptions/ResumeLoginOption.cs
@@ -1,15 +1,42 @@
namespace Rocket.Chat.Net.Models.LoginOptions
{
+ using OtpNet;
using System.Diagnostics.CodeAnalysis;
using Rocket.Chat.Net.Interfaces;
+ using System.Text.Json.Serialization;
[SuppressMessage("ReSharper", "UnusedAutoPropertyAccessor.Global")]
public class ResumeLoginOption : ILoginOption
{
+ private Totp totpSeed;
+ private string totpToken;
+
///
/// Active login token given from a successful, previous login.
///
public string Token { get; set; }
+
+ [JsonIgnore]
+ public Totp TOTPSeed
+ {
+ get => totpSeed;
+ set => totpSeed = value;
+ }
+
+ [JsonIgnore]
+ public string TOTPToken
+ {
+ get
+ {
+ if (this.totpSeed != null)
+ totpToken = totpSeed.ComputeTotp();
+ return totpToken;
+ }
+ set
+ {
+ totpToken = value;
+ }
+ }
}
}
\ No newline at end of file
diff --git a/src/Rocket.Chat.Net/Models/LoginOptions/UsernameLoginOption.cs b/src/Rocket.Chat.Net/Models/LoginOptions/UsernameLoginOption.cs
index 01cecd7..ecdc3cc 100644
--- a/src/Rocket.Chat.Net/Models/LoginOptions/UsernameLoginOption.cs
+++ b/src/Rocket.Chat.Net/Models/LoginOptions/UsernameLoginOption.cs
@@ -1,20 +1,48 @@
namespace Rocket.Chat.Net.Models.LoginOptions
{
using System.Diagnostics.CodeAnalysis;
-
+ using Newtonsoft.Json;
+ using OtpNet;
using Rocket.Chat.Net.Interfaces;
[SuppressMessage("ReSharper", "UnusedAutoPropertyAccessor.Global")]
- public class UsernameLoginOption : ILoginOption
+ public class UsernameLoginOption : IRestLoginOption
{
+ private Totp totpSeed;
+ private string totpToken;
+
///
/// Username of the user to login as. This should not be a email address.
///
+ [JsonProperty(PropertyName = "user")]
public string Username { get; set; }
///
/// Plaintext password of the user.
///
+ [JsonProperty(PropertyName = "password")]
public string Password { get; set; }
+
+ [JsonIgnore]
+ public Totp TOTPSeed
+ {
+ get => totpSeed;
+ set => totpSeed = value;
+ }
+
+ [JsonIgnore]
+ public string TOTPToken
+ {
+ get
+ {
+ if (this.totpSeed != null)
+ totpToken = totpSeed.ComputeTotp();
+ return totpToken;
+ }
+ set
+ {
+ totpToken = value;
+ }
+ }
}
}
\ No newline at end of file
diff --git a/src/Rocket.Chat.Net/Models/RestResults/RestLoginResult.cs b/src/Rocket.Chat.Net/Models/RestResults/RestLoginResult.cs
new file mode 100644
index 0000000..c5e873a
--- /dev/null
+++ b/src/Rocket.Chat.Net/Models/RestResults/RestLoginResult.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Rocket.Chat.Net.Models.RestResults
+{
+ public class RestLoginResult
+ {
+
+ public string UserId { get; set; }
+
+ public string AuthToken { get; set; }
+
+ public User Me { get; set; }
+
+ }
+}
diff --git a/src/Rocket.Chat.Net/Models/RestResults/RestResult.cs b/src/Rocket.Chat.Net/Models/RestResults/RestResult.cs
new file mode 100644
index 0000000..3b94a4d
--- /dev/null
+++ b/src/Rocket.Chat.Net/Models/RestResults/RestResult.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+using Newtonsoft.Json;
+using Newtonsoft.Json.Converters;
+using Rocket.Chat.Net.JsonConverters;
+
+namespace Rocket.Chat.Net.Models.RestResults
+{
+ public class RestResult
+ {
+ [JsonConstructor]
+ public RestResult(string status)
+ {
+ if (status == "success")
+ Success = true;
+ else
+ Success = false;
+ }
+
+ [JsonProperty(PropertyName = "_id")]
+ public string Id { get; set; }
+
+ public bool Success { get; set; }
+
+ public string Error { get; set; }
+ }
+
+ public class RestResult : RestResult
+ {
+ public RestResult(string status) : base(status)
+ {
+ }
+
+ public T Data { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Rocket.Chat.Net/Models/RocketMessage.cs b/src/Rocket.Chat.Net/Models/RocketMessage.cs
index b52908d..fb5d922 100644
--- a/src/Rocket.Chat.Net/Models/RocketMessage.cs
+++ b/src/Rocket.Chat.Net/Models/RocketMessage.cs
@@ -15,6 +15,7 @@
///
[SuppressMessage("ReSharper", "UnusedAutoPropertyAccessor.Global")]
[SuppressMessage("ReSharper", "CollectionNeverUpdated.Global")]
+ [JsonObject(ItemNullValueHandling = NullValueHandling.Ignore)]
public class RocketMessage
{
public RocketMessage()
diff --git a/src/Rocket.Chat.Net/Models/SubscriptionResults/SubscriptionResult.cs b/src/Rocket.Chat.Net/Models/SubscriptionResults/SubscriptionResult.cs
index 4587160..2a9b695 100644
--- a/src/Rocket.Chat.Net/Models/SubscriptionResults/SubscriptionResult.cs
+++ b/src/Rocket.Chat.Net/Models/SubscriptionResults/SubscriptionResult.cs
@@ -4,6 +4,7 @@ namespace Rocket.Chat.Net.Models.SubscriptionResults
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
+ using Rocket.Chat.Net.Models.MethodResults;
public class SubscriptionResult
{
@@ -14,6 +15,8 @@ public class SubscriptionResult
public string Id { get; set; }
+ public ErrorResult Error { get; set; }
+
public T Fields { get; set; }
public IList Cleared { get; set; }
diff --git a/src/Rocket.Chat.Net/Properties/AssemblyInfo.cs b/src/Rocket.Chat.Net/Properties/AssemblyInfo.cs
deleted file mode 100644
index 7b86be7..0000000
--- a/src/Rocket.Chat.Net/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-using System.Reflection;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-
-[assembly: AssemblyTitle("Rocket.Chat.Net")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("Rocket.Chat.Net")]
-[assembly: AssemblyCopyright("Copyright © 2016")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components. If you need to access a type in this assembly from
-// COM, set the ComVisible attribute to true on that type.
-
-[assembly: ComVisible(false)]
-
-// The following GUID is for the ID of the typelib if this project is exposed to COM
-
-[assembly: Guid("a078aeb9-5502-441c-b44a-ff4bbe007551")]
-
-// Version information for an assembly consists of the following four values:
-//
-// Major Version
-// Minor Version
-// Build Number
-// Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
-
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
-[assembly: AssemblyInformationalVersion("1.0.0.0")]
\ No newline at end of file
diff --git a/src/Rocket.Chat.Net/Rocket.Chat.Net.csproj b/src/Rocket.Chat.Net/Rocket.Chat.Net.csproj
index c03558a..7016b8c 100644
--- a/src/Rocket.Chat.Net/Rocket.Chat.Net.csproj
+++ b/src/Rocket.Chat.Net/Rocket.Chat.Net.csproj
@@ -1,141 +1,25 @@
-
-
-
-
+
+
- Debug
- AnyCPU
- {A078AEB9-5502-441C-B44A-FF4BBE007551}
- Library
- Properties
- Rocket.Chat.Net
- Rocket.Chat.Net
- v4.5
- 512
-
-
- Profile111
- {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ netstandard2.0
-
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
-
-
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
-
-
- bin\Mono-4.5\
- TRACE
- true
- pdbonly
- AnyCPU
- prompt
- MinimumRecommendedRules.ruleset
- v4.5
-
-
-
- ..\..\packages\Newtonsoft.Json.8.0.3\lib\portable-net40+sl5+wp80+win8+wpa81\Newtonsoft.Json.dll
- True
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
- Designer
-
+
+
+
+
+
+
-
- {662ce701-056d-420a-b03b-4f2613eea044}
- Rocket.Chat.Net.Portability
-
+
+
+
+
+
+
+
-
-
-
- This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
-
-
-
-
-
-
-
\ No newline at end of file
+
+
diff --git a/src/Rocket.Chat.Net/Rocket.Chat.Net.v2.ncrunchproject b/src/Rocket.Chat.Net/Rocket.Chat.Net.v2.ncrunchproject
deleted file mode 100644
index 30815b1..0000000
--- a/src/Rocket.Chat.Net/Rocket.Chat.Net.v2.ncrunchproject
+++ /dev/null
@@ -1,26 +0,0 @@
-
- true
- 1000
- false
- false
- false
- true
- false
- false
- false
- false
- false
- true
- true
- false
- true
- true
- true
- 60000
-
-
-
- AutoDetect
- STA
- x86
-
\ No newline at end of file
diff --git a/src/Rocket.Chat.Net/packages.config b/src/Rocket.Chat.Net/packages.config
deleted file mode 100644
index 263bd3b..0000000
--- a/src/Rocket.Chat.Net/packages.config
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/test/Rocket.Chat.Net.Bot.Tests/Rocket.Chat.Net.Bot.Tests.csproj b/test/Rocket.Chat.Net.Bot.Tests/Rocket.Chat.Net.Bot.Tests.csproj
index 5c61db7..ba88493 100644
--- a/test/Rocket.Chat.Net.Bot.Tests/Rocket.Chat.Net.Bot.Tests.csproj
+++ b/test/Rocket.Chat.Net.Bot.Tests/Rocket.Chat.Net.Bot.Tests.csproj
@@ -1,5 +1,6 @@
+
Debug
@@ -9,7 +10,7 @@
Properties
Rocket.Chat.Net.Bot.Tests
Rocket.Chat.Net.Bot.Tests
- v4.5
+ v4.8
512
{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
10.0
@@ -47,6 +48,12 @@
..\..\packages\FluentAssertions.4.9.1\lib\net45\FluentAssertions.Core.dll
True
+
+ ..\..\packages\Microsoft.Bcl.AsyncInterfaces.5.0.0\lib\net461\Microsoft.Bcl.AsyncInterfaces.dll
+
+
+ ..\..\packages\NLog.5.1.0\lib\net46\NLog.dll
+
..\..\packages\NSubstitute.1.10.0.0\lib\net45\NSubstitute.dll
True
@@ -55,7 +62,37 @@
..\..\packages\AutoFixture.3.47.8\lib\net40\Ploeh.AutoFixture.dll
True
+
+ ..\..\packages\RestSharp.108.0.3\lib\netstandard2.0\RestSharp.dll
+
+
+ ..\..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll
+
+
+
+
+ ..\..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll
+
+
+
+ ..\..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll
+
+
+ ..\..\packages\System.Runtime.CompilerServices.Unsafe.5.0.0\lib\net45\System.Runtime.CompilerServices.Unsafe.dll
+
+
+ ..\..\packages\System.Text.Encodings.Web.5.0.0\lib\net461\System.Text.Encodings.Web.dll
+
+
+ ..\..\packages\System.Text.Json.5.0.1\lib\net461\System.Text.Json.dll
+
+
+ ..\..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll
+
+
+ ..\..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll
+
@@ -90,7 +127,7 @@
- {a6ff1f57-0837-4f1a-9248-1cce8477295e}
+ {0c2862be-2cfb-4890-b154-4b4e7753e11f}
Rocket.Chat.Net.Bot
@@ -99,6 +136,7 @@
+
@@ -126,6 +164,7 @@
This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+