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}. +