From 60f74d088aad3b6567d05c2f9ad2b4d525998997 Mon Sep 17 00:00:00 2001 From: Brandon Smith Date: Mon, 17 Aug 2015 18:57:44 -0300 Subject: [PATCH] Project restructure, Added .Net Core support, Fixed some bugs --- .gitignore | 1 + Discord.Net.sln | 54 ++++-- Discord.Net/BuildNuget.cmd | 2 - Discord.Net/Discord.Net.csproj | 89 ---------- Discord.Net/Discord.Net.nuspec | 17 -- global.json | 8 + .../Discord.Net.Commands.csproj | 67 ++++++++ .../Properties/AssemblyInfo.cs | 10 +- src/Discord.Net.Commands/CommandBuilder.cs | 32 ++++ src/Discord.Net.Commands/CommandParser.cs | 154 ++++++++++++++++++ .../Discord.Net.Commands.xproj | 21 +++ .../DiscordBotClient.Events.cs | 50 ++++++ src/Discord.Net.Commands/DiscordBotClient.cs | 151 +++++++++++++++++ src/Discord.Net.Commands/project.json | 26 +++ src/Discord.Net.Net45/Discord.Net.csproj | 121 ++++++++++++++ .../Properties/AssemblyInfo.cs | 17 ++ .../Discord.Net.Net45}/packages.config | 2 +- .../Discord.Net}/API/DiscordAPI.cs | 0 .../Discord.Net}/API/Endpoints.cs | 0 .../Discord.Net/API/Models/APIRequests.cs | 0 .../Discord.Net}/API/Models/APIResponses.cs | 0 .../Discord.Net}/API/Models/Common.cs | 0 .../API/Models/WebSocketCommands.cs | 0 .../API/Models/WebSocketEvents.cs | 0 {Discord.Net => src/Discord.Net}/Channel.cs | 2 +- .../Discord.Net}/ChannelTypes.cs | 0 src/Discord.Net/Discord.Net.xproj | 21 +++ .../Discord.Net}/DiscordClient.Events.cs | 0 .../Discord.Net}/DiscordClient.cs | 60 ++++--- .../Discord.Net}/DiscordWebSocket.Events.cs | 0 .../Discord.Net}/DiscordWebSocket.cs | 16 +- .../Discord.Net}/Helpers/AsyncCache.cs | 0 .../Discord.Net}/Helpers/Http.cs | 34 ++-- {Discord.Net => src/Discord.Net}/Invite.cs | 0 .../Discord.Net}/Membership.cs | 0 {Discord.Net => src/Discord.Net}/Message.cs | 0 {Discord.Net => src/Discord.Net}/Regions.cs | 0 {Discord.Net => src/Discord.Net}/Role.cs | 0 {Discord.Net => src/Discord.Net}/Server.cs | 0 {Discord.Net => src/Discord.Net}/User.cs | 0 src/Discord.Net/packages.config | 4 + src/Discord.Net/project.json | 28 ++++ .../Discord.Net.Tests.csproj | 7 +- .../Properties/AssemblyInfo.cs | 0 .../Discord.Net.Tests}/Tests.cs | 0 45 files changed, 830 insertions(+), 164 deletions(-) delete mode 100644 Discord.Net/BuildNuget.cmd delete mode 100644 Discord.Net/Discord.Net.csproj delete mode 100644 Discord.Net/Discord.Net.nuspec create mode 100644 global.json create mode 100644 src/Discord.Net.Commands.Net45/Discord.Net.Commands.csproj rename {Discord.Net => src/Discord.Net.Commands.Net45}/Properties/AssemblyInfo.cs (57%) create mode 100644 src/Discord.Net.Commands/CommandBuilder.cs create mode 100644 src/Discord.Net.Commands/CommandParser.cs create mode 100644 src/Discord.Net.Commands/Discord.Net.Commands.xproj create mode 100644 src/Discord.Net.Commands/DiscordBotClient.Events.cs create mode 100644 src/Discord.Net.Commands/DiscordBotClient.cs create mode 100644 src/Discord.Net.Commands/project.json create mode 100644 src/Discord.Net.Net45/Discord.Net.csproj create mode 100644 src/Discord.Net.Net45/Properties/AssemblyInfo.cs rename {Discord.Net => src/Discord.Net.Net45}/packages.config (83%) rename {Discord.Net => src/Discord.Net}/API/DiscordAPI.cs (100%) rename {Discord.Net => src/Discord.Net}/API/Endpoints.cs (100%) rename Discord.Net/API/Models/ApiRequests.cs => src/Discord.Net/API/Models/APIRequests.cs (100%) rename {Discord.Net => src/Discord.Net}/API/Models/APIResponses.cs (100%) rename {Discord.Net => src/Discord.Net}/API/Models/Common.cs (100%) rename {Discord.Net => src/Discord.Net}/API/Models/WebSocketCommands.cs (100%) rename {Discord.Net => src/Discord.Net}/API/Models/WebSocketEvents.cs (100%) rename {Discord.Net => src/Discord.Net}/Channel.cs (89%) rename {Discord.Net => src/Discord.Net}/ChannelTypes.cs (100%) create mode 100644 src/Discord.Net/Discord.Net.xproj rename {Discord.Net => src/Discord.Net}/DiscordClient.Events.cs (100%) rename {Discord.Net => src/Discord.Net}/DiscordClient.cs (93%) rename {Discord.Net => src/Discord.Net}/DiscordWebSocket.Events.cs (100%) rename {Discord.Net => src/Discord.Net}/DiscordWebSocket.cs (96%) rename {Discord.Net => src/Discord.Net}/Helpers/AsyncCache.cs (100%) rename {Discord.Net => src/Discord.Net}/Helpers/Http.cs (86%) rename {Discord.Net => src/Discord.Net}/Invite.cs (100%) rename {Discord.Net => src/Discord.Net}/Membership.cs (100%) rename {Discord.Net => src/Discord.Net}/Message.cs (100%) rename {Discord.Net => src/Discord.Net}/Regions.cs (100%) rename {Discord.Net => src/Discord.Net}/Role.cs (100%) rename {Discord.Net => src/Discord.Net}/Server.cs (100%) rename {Discord.Net => src/Discord.Net}/User.cs (100%) create mode 100644 src/Discord.Net/packages.config create mode 100644 src/Discord.Net/project.json rename {Discord.Net.Tests => test/Discord.Net.Tests}/Discord.Net.Tests.csproj (94%) rename {Discord.Net.Tests => test/Discord.Net.Tests}/Properties/AssemblyInfo.cs (100%) rename {Discord.Net.Tests => test/Discord.Net.Tests}/Tests.cs (100%) diff --git a/.gitignore b/.gitignore index a16fc009f..2fcef09e8 100644 --- a/.gitignore +++ b/.gitignore @@ -197,3 +197,4 @@ FakesAssemblies/ #Custom Credentials.cs +project.lock.json \ No newline at end of file diff --git a/Discord.Net.sln b/Discord.Net.sln index 0eac29c74..1d7cbfd25 100644 --- a/Discord.Net.sln +++ b/Discord.Net.sln @@ -3,17 +3,28 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 VisualStudioVersion = 14.0.23107.0 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Discord.Net", "Discord.Net\Discord.Net.csproj", "{8D23F61B-723C-4966-859D-1119B28BCF19}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{8D7989F0-66CE-4DBB-8230-D8C811E9B1D7}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{1DDC89B5-2A88-45E5-A743-7A43E6B5C4B3}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{6317A2E6-8E36-4C3E-949B-3F10EC888AB9}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{1BE8AF3F-3CFD-433F-A380-D294A4F617C1}" ProjectSection(SolutionItems) = preProject - .gitattributes = .gitattributes - .gitignore = .gitignore - LICENSE = LICENSE - README.md = README.md + global.json = global.json EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Discord.Net.Tests", "Discord.Net.Tests\Discord.Net.Tests.csproj", "{855D6B1D-847B-42DA-BE6A-23683EA89511}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Discord.Net.Tests", "test\Discord.Net.Tests\Discord.Net.Tests.csproj", "{855D6B1D-847B-42DA-BE6A-23683EA89511}" +EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Discord.Net", "src\Discord.Net\Discord.Net.xproj", "{ACFB060B-EC8A-4926-B293-04C01E17EE23}" +EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Discord.Net.Commands", "src\Discord.Net.Commands\Discord.Net.Commands.xproj", "{19793545-EF89-48F4-8100-3EBAAD0A9141}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "net45", "net45", "{B47C4063-C4EB-46AA-886D-B868DA1BF0A0}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Discord.Net", "src\Discord.Net.Net45\Discord.Net.csproj", "{8D71A857-879A-4A10-859E-5FF824ED6688}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Discord.Net.Commands", "src\Discord.Net.Commands.Net45\Discord.Net.Commands.csproj", "{1B5603B4-6F8F-4289-B945-7BAAE523D740}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "dotnet", "dotnet", "{EA68EBE2-51C8-4440-9EF7-D633C90A5D35}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -21,16 +32,37 @@ Global Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {8D23F61B-723C-4966-859D-1119B28BCF19}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8D23F61B-723C-4966-859D-1119B28BCF19}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8D23F61B-723C-4966-859D-1119B28BCF19}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8D23F61B-723C-4966-859D-1119B28BCF19}.Release|Any CPU.Build.0 = Release|Any CPU {855D6B1D-847B-42DA-BE6A-23683EA89511}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {855D6B1D-847B-42DA-BE6A-23683EA89511}.Debug|Any CPU.Build.0 = Debug|Any CPU {855D6B1D-847B-42DA-BE6A-23683EA89511}.Release|Any CPU.ActiveCfg = Release|Any CPU {855D6B1D-847B-42DA-BE6A-23683EA89511}.Release|Any CPU.Build.0 = Release|Any CPU + {ACFB060B-EC8A-4926-B293-04C01E17EE23}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ACFB060B-EC8A-4926-B293-04C01E17EE23}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ACFB060B-EC8A-4926-B293-04C01E17EE23}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ACFB060B-EC8A-4926-B293-04C01E17EE23}.Release|Any CPU.Build.0 = Release|Any CPU + {19793545-EF89-48F4-8100-3EBAAD0A9141}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {19793545-EF89-48F4-8100-3EBAAD0A9141}.Debug|Any CPU.Build.0 = Debug|Any CPU + {19793545-EF89-48F4-8100-3EBAAD0A9141}.Release|Any CPU.ActiveCfg = Release|Any CPU + {19793545-EF89-48F4-8100-3EBAAD0A9141}.Release|Any CPU.Build.0 = Release|Any CPU + {8D71A857-879A-4A10-859E-5FF824ED6688}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8D71A857-879A-4A10-859E-5FF824ED6688}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8D71A857-879A-4A10-859E-5FF824ED6688}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8D71A857-879A-4A10-859E-5FF824ED6688}.Release|Any CPU.Build.0 = Release|Any CPU + {1B5603B4-6F8F-4289-B945-7BAAE523D740}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1B5603B4-6F8F-4289-B945-7BAAE523D740}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1B5603B4-6F8F-4289-B945-7BAAE523D740}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1B5603B4-6F8F-4289-B945-7BAAE523D740}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {855D6B1D-847B-42DA-BE6A-23683EA89511} = {6317A2E6-8E36-4C3E-949B-3F10EC888AB9} + {ACFB060B-EC8A-4926-B293-04C01E17EE23} = {EA68EBE2-51C8-4440-9EF7-D633C90A5D35} + {19793545-EF89-48F4-8100-3EBAAD0A9141} = {EA68EBE2-51C8-4440-9EF7-D633C90A5D35} + {B47C4063-C4EB-46AA-886D-B868DA1BF0A0} = {8D7989F0-66CE-4DBB-8230-D8C811E9B1D7} + {8D71A857-879A-4A10-859E-5FF824ED6688} = {B47C4063-C4EB-46AA-886D-B868DA1BF0A0} + {1B5603B4-6F8F-4289-B945-7BAAE523D740} = {B47C4063-C4EB-46AA-886D-B868DA1BF0A0} + {EA68EBE2-51C8-4440-9EF7-D633C90A5D35} = {8D7989F0-66CE-4DBB-8230-D8C811E9B1D7} + EndGlobalSection EndGlobal diff --git a/Discord.Net/BuildNuget.cmd b/Discord.Net/BuildNuget.cmd deleted file mode 100644 index d72e6c121..000000000 --- a/Discord.Net/BuildNuget.cmd +++ /dev/null @@ -1,2 +0,0 @@ -nuget pack Discord.Net.csproj -Prop Configuration=Release -pause \ No newline at end of file diff --git a/Discord.Net/Discord.Net.csproj b/Discord.Net/Discord.Net.csproj deleted file mode 100644 index 9325d90be..000000000 --- a/Discord.Net/Discord.Net.csproj +++ /dev/null @@ -1,89 +0,0 @@ - - - - - Release - AnyCPU - {8D23F61B-723C-4966-859D-1119B28BCF19} - Library - Properties - Discord - Discord.Net - v4.5 - 512 - - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - false - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - false - - - - ..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll - True - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Designer - - - - - - \ No newline at end of file diff --git a/Discord.Net/Discord.Net.nuspec b/Discord.Net/Discord.Net.nuspec deleted file mode 100644 index 3ff7640dd..000000000 --- a/Discord.Net/Discord.Net.nuspec +++ /dev/null @@ -1,17 +0,0 @@ - - - - $id$ - $version$ - $title$ - $author$ - $author$ - http://opensource.org/licenses/MIT - https://github.com/RogueException/Discord.Net - false - $description$ - - Copyright 2015 - Discord DiscordApp - - \ No newline at end of file diff --git a/global.json b/global.json new file mode 100644 index 000000000..4a056d884 --- /dev/null +++ b/global.json @@ -0,0 +1,8 @@ +{ + "projects": [ "src" ], + "sdk": { + "version": "1.0.0-beta6", + "architecture": "x64", + "runtime": "coreclr" + } +} \ No newline at end of file diff --git a/src/Discord.Net.Commands.Net45/Discord.Net.Commands.csproj b/src/Discord.Net.Commands.Net45/Discord.Net.Commands.csproj new file mode 100644 index 000000000..bf7a0d06d --- /dev/null +++ b/src/Discord.Net.Commands.Net45/Discord.Net.Commands.csproj @@ -0,0 +1,67 @@ + + + + + Debug + AnyCPU + {1B5603B4-6F8F-4289-B945-7BAAE523D740} + Library + Properties + Discord.Net + Discord.Net.Commands + 512 + v4.5 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + true + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + true + + + + + + + + {8d71a857-879a-4a10-859e-5ff824ed6688} + Discord.Net + + + + + CommandBuilder.cs + + + CommandParser.cs + + + DiscordBotClient.cs + + + DiscordBotClient.Events.cs + + + + + + \ No newline at end of file diff --git a/Discord.Net/Properties/AssemblyInfo.cs b/src/Discord.Net.Commands.Net45/Properties/AssemblyInfo.cs similarity index 57% rename from Discord.Net/Properties/AssemblyInfo.cs rename to src/Discord.Net.Commands.Net45/Properties/AssemblyInfo.cs index 8c94c0232..e8e45ec9a 100644 --- a/Discord.Net/Properties/AssemblyInfo.cs +++ b/src/Discord.Net.Commands.Net45/Properties/AssemblyInfo.cs @@ -1,13 +1,17 @@ using System.Reflection; +using System.Runtime.InteropServices; [assembly: AssemblyTitle("Discord.Net")] [assembly: AssemblyDescription("An unofficial .Net API wrapper for the Discord client.")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("RogueException")] [assembly: AssemblyProduct("Discord.Net")] -[assembly: AssemblyCopyright("Copyright © RogueException 2015")] +[assembly: AssemblyCopyright("Copyright © 2015")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] -[assembly: AssemblyVersion("0.3.2.0")] -[assembly: AssemblyFileVersion("0.3.2.0")] +[assembly: ComVisible(false)] +[assembly: Guid("76ea00e6-ea24-41e1-acb2-639c0313fa80")] + +[assembly: AssemblyVersion("0.2.0.0")] +[assembly: AssemblyFileVersion("0.2.0.0")] diff --git a/src/Discord.Net.Commands/CommandBuilder.cs b/src/Discord.Net.Commands/CommandBuilder.cs new file mode 100644 index 000000000..78a505ea9 --- /dev/null +++ b/src/Discord.Net.Commands/CommandBuilder.cs @@ -0,0 +1,32 @@ +using System; +using System.Threading.Tasks; + +namespace Discord +{ + public sealed class CommandBuilder + { + private readonly DiscordBotClient _client; + private readonly string _prefix; + private readonly bool _useWhitelist; + + public CommandBuilder(DiscordBotClient client, string prefix, bool useWhitelist = false) + { + _client = client; + _prefix = prefix; + _useWhitelist = useWhitelist; + } + + public void AddCommandGroup(string cmd, Action config, bool useWhitelist = false) + { + config(new CommandBuilder(_client, _prefix + ' ' + cmd, useWhitelist)); + } + public void AddCommand(string cmd, int minArgs, int maxArgs, Action handler, bool? useWhitelist = null) + { + AddCommand(cmd, minArgs, maxArgs, e => { handler(e); return null; }, useWhitelist); + } + public void AddCommand(string cmd, int minArgs, int maxArgs, Func handler, bool? useWhitelist = null) + { + _client.AddCommand(cmd != "" ? _prefix + ' ' + cmd : _prefix, minArgs, maxArgs, handler, useWhitelist ?? _useWhitelist); + } + } +} diff --git a/src/Discord.Net.Commands/CommandParser.cs b/src/Discord.Net.Commands/CommandParser.cs new file mode 100644 index 000000000..ef854fea2 --- /dev/null +++ b/src/Discord.Net.Commands/CommandParser.cs @@ -0,0 +1,154 @@ +using System.Collections.Generic; + +namespace Discord +{ + public static class CommandParser + { + private enum CommandParserPart + { + None, + CommandName, + Parameter, + QuotedParameter, + DoubleQuotedParameter + } + + public static bool Parse(string input, out string command, out string[] args) + { + return Parse(input, out command, out args, true); + } + public static bool ParseArgs(string input, out string[] args) + { + string ignored; + return Parse(input, out ignored, out args, false); + } + + private static bool Parse(string input, out string command, out string[] args, bool parseCommand) + { + CommandParserPart currentPart = parseCommand ? CommandParserPart.CommandName : CommandParserPart.None; + int startPosition = 0; + int endPosition = 0; + int inputLength = input.Length; + bool isEscaped = false; + List argList = new List(); + + command = null; + args = null; + + if (input == "") + return false; + + while (endPosition < inputLength) + { + char currentChar = input[endPosition++]; + if (isEscaped) + isEscaped = false; + else if (currentChar == '\\') + isEscaped = true; + + switch (currentPart) + { + case CommandParserPart.CommandName: + if ((!isEscaped && currentChar == ' ') || endPosition >= inputLength) + { + int length = (currentChar == ' ' ? endPosition - 1 : endPosition) - startPosition; + string temp = input.Substring(startPosition, length); + if (temp == "") + startPosition = endPosition; + else + { + currentPart = CommandParserPart.None; + command = temp; + startPosition = endPosition; + } + } + break; + case CommandParserPart.None: + if ((!isEscaped && currentChar == '\"')) + { + currentPart = CommandParserPart.DoubleQuotedParameter; + startPosition = endPosition; + } + else if ((!isEscaped && currentChar == '\'')) + { + currentPart = CommandParserPart.QuotedParameter; + startPosition = endPosition; + } + else if ((!isEscaped && currentChar == ' ') || endPosition >= inputLength) + { + int length = (currentChar == ' ' ? endPosition - 1 : endPosition) - startPosition; + string temp = input.Substring(startPosition, length); + if (temp == "") + startPosition = endPosition; + else + { + currentPart = CommandParserPart.None; + argList.Add(temp); + startPosition = endPosition; + } + } + break; + case CommandParserPart.QuotedParameter: + if ((!isEscaped && currentChar == '\'')) + { + string temp = input.Substring(startPosition, endPosition - startPosition - 1); + currentPart = CommandParserPart.None; + argList.Add(temp); + startPosition = endPosition; + } + else if (endPosition >= inputLength) + return false; + break; + case CommandParserPart.DoubleQuotedParameter: + if ((!isEscaped && currentChar == '\"')) + { + string temp = input.Substring(startPosition, endPosition - startPosition - 1); + currentPart = CommandParserPart.None; + argList.Add(temp); + startPosition = endPosition; + } + else if (endPosition >= inputLength) + return false; + break; + } + } + + if (parseCommand && (command == null || command == "")) + return false; + + args = argList.ToArray(); + return true; + } + + public static bool ArgsEqual(string[] args, int expected) + { + return args.Length == expected; + } + public static bool ArgsAtLeast(string[] args, int expected) + { + return args.Length >= expected; + } + public static bool ArgsAtMost(string[] args, int expected) + { + return args.Length <= expected; + } + public static bool ArgsIn(string[] args, params int[] expected) + { + int count = args.Length; + for (int i = 0; i < expected.Length; i++) + { + if (count == expected[i]) + return true; + } + return false; + } + public static bool ArgsBetween(string[] args, int min, int max) + { + return args.Length >= min && args.Length <= max; + } + public static bool NoArgs(string[] args, params int[] expected) + { + return args.Length == 0; + } + } +} diff --git a/src/Discord.Net.Commands/Discord.Net.Commands.xproj b/src/Discord.Net.Commands/Discord.Net.Commands.xproj new file mode 100644 index 000000000..e6d1163ef --- /dev/null +++ b/src/Discord.Net.Commands/Discord.Net.Commands.xproj @@ -0,0 +1,21 @@ + + + + 14.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + 19793545-ef89-48f4-8100-3ebaad0a9141 + Discord.Net.Commands + ..\..\artifacts\obj\$(MSBuildProjectName) + ..\..\artifacts\bin\$(MSBuildProjectName)\ + + + 2.0 + + + True + + + \ No newline at end of file diff --git a/src/Discord.Net.Commands/DiscordBotClient.Events.cs b/src/Discord.Net.Commands/DiscordBotClient.Events.cs new file mode 100644 index 000000000..edddc4953 --- /dev/null +++ b/src/Discord.Net.Commands/DiscordBotClient.Events.cs @@ -0,0 +1,50 @@ +using System; + +namespace Discord +{ + public partial class DiscordBotClient : DiscordClient + { + public class CommandEventArgs + { + public readonly Message Message; + public readonly Command Command; + public readonly string[] Args; + + public User User => Message.User; + public string UserId => Message.UserId; + public Channel Channel => Message.Channel; + public string ChannelId => Message.ChannelId; + public Server Server => Message.Channel.Server; + public string ServerId => Message.Channel.ServerId; + + public CommandEventArgs(Message message, Command command, string[] args) + { + Message = message; + Command = command; + Args = args; + } + } + public class CommandErrorEventArgs : CommandEventArgs + { + public readonly Exception Exception; + public CommandErrorEventArgs(Message message, Command command, string[] args, Exception ex) + : base(message, command, args) + { + Exception = ex; + } + } + + public event EventHandler RanCommand; + private void RaiseRanCommand(CommandEventArgs args) + { + if (RanCommand != null) + RanCommand(this, args); + } + public event EventHandler CommandError; + private void RaiseCommandError(Message msg, Command command, string[] args, Exception ex) + { + if (CommandError != null) + CommandError(this, new CommandErrorEventArgs(msg, command, args, ex)); + } + } +} diff --git a/src/Discord.Net.Commands/DiscordBotClient.cs b/src/Discord.Net.Commands/DiscordBotClient.cs new file mode 100644 index 000000000..35d0f4c4b --- /dev/null +++ b/src/Discord.Net.Commands/DiscordBotClient.cs @@ -0,0 +1,151 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace Discord +{ + public sealed class Command + { + public readonly string[] Text; + public readonly int MinArgs, MaxArgs; + public readonly bool UseWhitelist; + internal readonly Func Handler; + + public Command(string[] text, int minArgs, int maxArgs, bool useWhitelist, Func handler) + { + Text = text; + MinArgs = minArgs; + MaxArgs = maxArgs; + UseWhitelist = useWhitelist; + Handler = handler; + } + } + + /// + /// A Discord.Net client with extensions for handling common bot operations like text commands. + /// + public partial class DiscordBotClient : DiscordClient + { + private List _commands; + private List _whitelist; + + public IEnumerable Commands => _commands; + + public char CommandChar { get; set; } + public bool UseCommandChar { get; set; } + public bool RequireCommandCharInPublic { get; set; } + public bool RequireCommandCharInPrivate { get; set; } + public bool AlwaysUseWhitelist { get; set; } + + public DiscordBotClient() + { + _commands = new List(); + _whitelist = new List(); + + CommandChar = '~'; + RequireCommandCharInPublic = true; + RequireCommandCharInPrivate = true; + AlwaysUseWhitelist = false; + + MessageCreated += async (s, e) => + { + //Ignore messages from ourselves + if (e.Message.UserId == UserId) + return; + + //Check the global whitelist + if (AlwaysUseWhitelist && !_whitelist.Contains(e.Message.UserId)) + return; + + //Check for the command character + string msg = e.Message.Text; + if (UseCommandChar) + { + if (msg.Length == 0) + return; + bool isPrivate = e.Message.Channel.IsPrivate; + bool hasCommandChar = msg[0] == CommandChar; + if (hasCommandChar) + msg = msg.Substring(1); + if (!isPrivate && RequireCommandCharInPublic && !hasCommandChar) + return; + if (isPrivate && RequireCommandCharInPrivate && !hasCommandChar) + return; + } + + string[] args; + if (!CommandParser.ParseArgs(msg, out args)) + return; + + for (int i = 0; i < _commands.Count; i++) + { + Command cmd = _commands[i]; + + //Check Command Parts + if (args.Length < cmd.Text.Length) + continue; + + bool isValid = true; + for (int j = 0; j < cmd.Text.Length; j++) + { + if (!string.Equals(args[j], cmd.Text[j], StringComparison.OrdinalIgnoreCase)) + { + isValid = false; + break; + } + } + if (!isValid) + continue; + + //Check Whitelist + if (cmd.UseWhitelist && !_whitelist.Contains(e.Message.UserId)) + continue; + + //Check Arg Count + int argCount = args.Length - cmd.Text.Length; + if (argCount < cmd.MinArgs || argCount > cmd.MaxArgs) + continue; + + //Run Command + string[] newArgs = new string[argCount]; + for (int j = 0; j < newArgs.Length; j++) + newArgs[j] = args[j + cmd.Text.Length]; + + var eventArgs = new CommandEventArgs(e.Message, cmd, newArgs); + RaiseRanCommand(eventArgs); + try + { + var task = cmd.Handler(eventArgs); + if (task != null) + await task; + } + catch (Exception ex) + { + RaiseCommandError(e.Message, cmd, newArgs, ex); + } + break; + } + }; + } + + public void AddCommandGroup(string cmd, Action config, bool useWhitelist = false) + { + config(new CommandBuilder(this, cmd, useWhitelist)); + } + public void AddCommand(string cmd, int minArgs, int maxArgs, Action handler, bool useWhitelist = false) + { + AddCommand(cmd, minArgs, maxArgs, e => { handler(e); return null; }, useWhitelist); + } + public void AddCommand(string cmd, int minArgs, int maxArgs, Func handler, bool useWhitelist = false) + { + _commands.Add(new Command(cmd.Split(' '), minArgs, maxArgs, useWhitelist, handler)); + } + + public void AddWhitelist(User user) + => AddWhitelist(user.Id); + public void AddWhitelist(string userId) + { + _whitelist.Add(userId); + } + } +} diff --git a/src/Discord.Net.Commands/project.json b/src/Discord.Net.Commands/project.json new file mode 100644 index 000000000..b2521d6af --- /dev/null +++ b/src/Discord.Net.Commands/project.json @@ -0,0 +1,26 @@ +{ + "version": "0.2.0-*", + "description": "A small Discord.Net extension to make bot creation easier.", + "authors": [ "RogueException" ], + "tags": [ "discord", "discordapp" ], + "projectUrl": "https://github.com/RogueException/Discord.Net", + "licenseUrl": "http://opensource.org/licenses/MIT", + "repository": { + "type": "git", + "url": "git://github.com/RogueException/Discord.Net" + }, + "compilationOptions": { + "warningsAsErrors": true + }, + "dependencies": { + "Discord.Net": "" + }, + "frameworks": { + "dotnet": { + "dependencies": { + "System.Runtime": "4.0.20", + "Microsoft.CSharp": "4.0.0" + } + } + } +} diff --git a/src/Discord.Net.Net45/Discord.Net.csproj b/src/Discord.Net.Net45/Discord.Net.csproj new file mode 100644 index 000000000..157eae0e7 --- /dev/null +++ b/src/Discord.Net.Net45/Discord.Net.csproj @@ -0,0 +1,121 @@ + + + + + Debug + AnyCPU + {8D71A857-879A-4A10-859E-5FF824ED6688} + Library + Properties + Discord.Net + Discord.Net + 512 + v4.5 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + true + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + true + + + + ..\..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll + True + + + + + + + + + API\DiscordAPI.cs + + + API\Endpoints.cs + + + API\Models\APIRequests.cs + + + API\Models\APIResponses.cs + + + API\Models\Common.cs + + + API\Models\WebSocketCommands.cs + + + API\Models\WebSocketEvents.cs + + + Channel.cs + + + ChannelTypes.cs + + + DiscordClient.cs + + + DiscordClient.Events.cs + + + DiscordWebSocket.cs + + + DiscordWebSocket.Events.cs + + + Helpers\AsyncCache.cs + + + Helpers\Http.cs + + + Invite.cs + + + Membership.cs + + + Message.cs + + + Regions.cs + + + Role.cs + + + Server.cs + + + User.cs + + + + + + \ No newline at end of file diff --git a/src/Discord.Net.Net45/Properties/AssemblyInfo.cs b/src/Discord.Net.Net45/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..3d45d6d43 --- /dev/null +++ b/src/Discord.Net.Net45/Properties/AssemblyInfo.cs @@ -0,0 +1,17 @@ +using System.Reflection; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("Discord.Net")] +[assembly: AssemblyDescription("An unofficial .Net API wrapper for the Discord client.")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("RogueException")] +[assembly: AssemblyProduct("Discord.Net")] +[assembly: AssemblyCopyright("Copyright © 2015")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] +[assembly: Guid("76ea00e6-ea24-41e1-acb2-639c0313fa80")] + +[assembly: AssemblyVersion("0.3.3.0")] +[assembly: AssemblyFileVersion("0.3.3.0")] diff --git a/Discord.Net/packages.config b/src/Discord.Net.Net45/packages.config similarity index 83% rename from Discord.Net/packages.config rename to src/Discord.Net.Net45/packages.config index 64b5d8efe..505e58836 100644 --- a/Discord.Net/packages.config +++ b/src/Discord.Net.Net45/packages.config @@ -1,4 +1,4 @@  - + \ No newline at end of file diff --git a/Discord.Net/API/DiscordAPI.cs b/src/Discord.Net/API/DiscordAPI.cs similarity index 100% rename from Discord.Net/API/DiscordAPI.cs rename to src/Discord.Net/API/DiscordAPI.cs diff --git a/Discord.Net/API/Endpoints.cs b/src/Discord.Net/API/Endpoints.cs similarity index 100% rename from Discord.Net/API/Endpoints.cs rename to src/Discord.Net/API/Endpoints.cs diff --git a/Discord.Net/API/Models/ApiRequests.cs b/src/Discord.Net/API/Models/APIRequests.cs similarity index 100% rename from Discord.Net/API/Models/ApiRequests.cs rename to src/Discord.Net/API/Models/APIRequests.cs diff --git a/Discord.Net/API/Models/APIResponses.cs b/src/Discord.Net/API/Models/APIResponses.cs similarity index 100% rename from Discord.Net/API/Models/APIResponses.cs rename to src/Discord.Net/API/Models/APIResponses.cs diff --git a/Discord.Net/API/Models/Common.cs b/src/Discord.Net/API/Models/Common.cs similarity index 100% rename from Discord.Net/API/Models/Common.cs rename to src/Discord.Net/API/Models/Common.cs diff --git a/Discord.Net/API/Models/WebSocketCommands.cs b/src/Discord.Net/API/Models/WebSocketCommands.cs similarity index 100% rename from Discord.Net/API/Models/WebSocketCommands.cs rename to src/Discord.Net/API/Models/WebSocketCommands.cs diff --git a/Discord.Net/API/Models/WebSocketEvents.cs b/src/Discord.Net/API/Models/WebSocketEvents.cs similarity index 100% rename from Discord.Net/API/Models/WebSocketEvents.cs rename to src/Discord.Net/API/Models/WebSocketEvents.cs diff --git a/Discord.Net/Channel.cs b/src/Discord.Net/Channel.cs similarity index 89% rename from Discord.Net/Channel.cs rename to src/Discord.Net/Channel.cs index 44fe5e231..8ab723969 100644 --- a/Discord.Net/Channel.cs +++ b/src/Discord.Net/Channel.cs @@ -11,7 +11,7 @@ namespace Discord public string Id { get; } private string _name; - public string Name { get { return !IsPrivate ? _name : '@' + Recipient.Name; } internal set { _name = value; } } + public string Name { get { return !IsPrivate ? $"#{_name}" : $"@{Recipient.Name}"; } internal set { _name = value; } } public bool IsPrivate { get; } public string Type { get; internal set; } diff --git a/Discord.Net/ChannelTypes.cs b/src/Discord.Net/ChannelTypes.cs similarity index 100% rename from Discord.Net/ChannelTypes.cs rename to src/Discord.Net/ChannelTypes.cs diff --git a/src/Discord.Net/Discord.Net.xproj b/src/Discord.Net/Discord.Net.xproj new file mode 100644 index 000000000..5518fc017 --- /dev/null +++ b/src/Discord.Net/Discord.Net.xproj @@ -0,0 +1,21 @@ + + + + 14.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + acfb060b-ec8a-4926-b293-04c01e17ee23 + Discord.Net + ..\..\artifacts\obj\$(MSBuildProjectName) + ..\..\artifacts\bin\$(MSBuildProjectName)\ + + + 2.0 + + + True + + + \ No newline at end of file diff --git a/Discord.Net/DiscordClient.Events.cs b/src/Discord.Net/DiscordClient.Events.cs similarity index 100% rename from Discord.Net/DiscordClient.Events.cs rename to src/Discord.Net/DiscordClient.Events.cs diff --git a/Discord.Net/DiscordClient.cs b/src/Discord.Net/DiscordClient.cs similarity index 93% rename from Discord.Net/DiscordClient.cs rename to src/Discord.Net/DiscordClient.cs index 7c306390e..052fe47f7 100644 --- a/Discord.Net/DiscordClient.cs +++ b/src/Discord.Net/DiscordClient.cs @@ -18,7 +18,7 @@ namespace Discord private DiscordWebSocket _webSocket; private HttpOptions _httpOptions; - private bool _isClosing, _isReady; + private bool _isReady; public string UserId { get; private set; } public User User => _users[UserId]; @@ -38,11 +38,14 @@ namespace Discord public IEnumerable Roles => _roles; private AsyncCache _roles; + private ManualResetEventSlim _isStopping; + public bool IsConnected => _isReady; public DiscordClient() { - string version = typeof(DiscordClient).GetTypeInfo().Assembly.GetName().Version.ToString(2); + _isStopping = new ManualResetEventSlim(false); + string version = typeof(DiscordClient).GetTypeInfo().Assembly.GetName().Version.ToString(2); _httpOptions = new HttpOptions($"Discord.Net/{version} (https://github.com/RogueException/Discord.Net)"); _servers = new AsyncCache( @@ -152,12 +155,12 @@ namespace Discord { //Reconnect if we didn't cause the disconnect RaiseDisconnected(); - while (!_isClosing) + while (!_isStopping.IsSet) { try { await Task.Delay(ReconnectDelay); - await _webSocket.ConnectAsync(Endpoints.WebSocket_Hub, _httpOptions); + await _webSocket.ConnectAsync(Endpoints.WebSocket_Hub, true, _httpOptions); break; } catch (Exception) @@ -395,7 +398,7 @@ namespace Discord public User FindUser(string name) { return _users - .Where(x => string.Equals(x.Name, name, StringComparison.InvariantCultureIgnoreCase)) + .Where(x => string.Equals(x.Name, name, StringComparison.OrdinalIgnoreCase)) .FirstOrDefault(); } public User FindUser(string name, string discriminator) @@ -405,7 +408,7 @@ namespace Discord return _users .Where(x => - string.Equals(x.Name, name, StringComparison.InvariantCultureIgnoreCase) && + string.Equals(x.Name, name, StringComparison.OrdinalIgnoreCase) && x.Discriminator == discriminator ) .FirstOrDefault(); @@ -418,7 +421,7 @@ namespace Discord name = name.Substring(1); return _users - .Where(x => string.Equals(x.Name, name, StringComparison.InvariantCultureIgnoreCase)) + .Where(x => string.Equals(x.Name, name, StringComparison.OrdinalIgnoreCase)) .FirstOrDefault(); } @@ -426,7 +429,7 @@ namespace Discord public Server FindServer(string name) { return _servers - .Where(x => string.Equals(x.Name, name, StringComparison.InvariantCultureIgnoreCase)) + .Where(x => string.Equals(x.Name, name, StringComparison.OrdinalIgnoreCase)) .FirstOrDefault(); } @@ -437,7 +440,7 @@ namespace Discord name = name.Substring(1); return _channels - .Where(x => string.Equals(x.Name, name, StringComparison.InvariantCultureIgnoreCase)) + .Where(x => string.Equals(x.Name, name, StringComparison.OrdinalIgnoreCase)) .FirstOrDefault(); } public Channel FindChannel(Server server, string name) @@ -449,7 +452,7 @@ namespace Discord return _channels .Where(x => - string.Equals(x.Name, name, StringComparison.InvariantCultureIgnoreCase) && + string.Equals(x.Name, name, StringComparison.OrdinalIgnoreCase) && x.ServerId == serverId ) .FirstOrDefault(); @@ -461,7 +464,7 @@ namespace Discord public Role FindRole(string serverId, string name) { return _roles - .Where(x => string.Equals(x.Name, name, StringComparison.InvariantCultureIgnoreCase)) + .Where(x => string.Equals(x.Name, name, StringComparison.OrdinalIgnoreCase)) .FirstOrDefault(); } @@ -495,26 +498,39 @@ namespace Discord //Auth public async Task Connect(string email, string password) { - _isClosing = false; + _isStopping.Reset(); + + //Open websocket while we wait for login response + Task socketTask = _webSocket.ConnectAsync(Endpoints.WebSocket_Hub, false, _httpOptions); var response = await DiscordAPI.Login(email, password, _httpOptions); _httpOptions.Token = response.Token; - await _webSocket.ConnectAsync(Endpoints.WebSocket_Hub, _httpOptions); + + //Wait for websocket to finish connecting, then send token + await socketTask; + _webSocket.Login(_httpOptions); + _isReady = true; } public async Task ConnectAnonymous(string username) { - _isClosing = false; + _isStopping.Reset(); + + //Open websocket while we wait for login response + Task socketTask = _webSocket.ConnectAsync(Endpoints.WebSocket_Hub, false, _httpOptions); var response = await DiscordAPI.LoginAnonymous(username, _httpOptions); _httpOptions.Token = response.Token; - await _webSocket.ConnectAsync(Endpoints.WebSocket_Hub, _httpOptions); + + //Wait for websocket to finish connecting, then send token + await socketTask; + _webSocket.Login(_httpOptions); + _isReady = true; } public async Task Disconnect() { _isReady = false; - _isClosing = true; + _isStopping.Set(); await _webSocket.DisconnectAsync(); - _isClosing = false; _channels.Clear(); _messages.Clear(); @@ -783,12 +799,14 @@ namespace Discord if (!_isReady) throw new InvalidOperationException("The client is not currently connected to Discord"); } + + /// + /// Blocking call that will not return until client has been stopped. This is mainly intended for use in console applications. + /// + /// public void Block() { - //Blocking call for console apps - //TODO: Improve this - while (!_isClosing) - Thread.Sleep(1000); + _isStopping.Wait(); } } } diff --git a/Discord.Net/DiscordWebSocket.Events.cs b/src/Discord.Net/DiscordWebSocket.Events.cs similarity index 100% rename from Discord.Net/DiscordWebSocket.Events.cs rename to src/Discord.Net/DiscordWebSocket.Events.cs diff --git a/Discord.Net/DiscordWebSocket.cs b/src/Discord.Net/DiscordWebSocket.cs similarity index 96% rename from Discord.Net/DiscordWebSocket.cs rename to src/Discord.Net/DiscordWebSocket.cs index 27caee53d..ff0f8f555 100644 --- a/Discord.Net/DiscordWebSocket.cs +++ b/src/Discord.Net/DiscordWebSocket.cs @@ -25,7 +25,7 @@ namespace Discord private DateTime _lastHeartbeat; private AutoResetEvent _connectWaitOnLogin, _connectWaitOnLogin2; - public async Task ConnectAsync(string url, HttpOptions options) + public async Task ConnectAsync(string url, bool autoLogin, HttpOptions options) { await DisconnectAsync(); @@ -34,7 +34,6 @@ namespace Discord _sendQueue = new ConcurrentQueue(); _webSocket = new ClientWebSocket(); - _webSocket.Options.Cookies = options.Cookies; _webSocket.Options.KeepAliveInterval = TimeSpan.Zero; _cancelToken = new CancellationTokenSource(); @@ -58,6 +57,11 @@ namespace Discord RaiseDisconnected(); }); + if (autoLogin) + Login(options); + } + public void Login(HttpOptions options) + { WebSocketCommands.Login msg = new WebSocketCommands.Login(); msg.Payload.Token = options.Token; msg.Payload.Properties["$os"] = ""; @@ -65,12 +69,14 @@ namespace Discord msg.Payload.Properties["$device"] = "Discord.Net"; msg.Payload.Properties["$referrer"] = ""; msg.Payload.Properties["$referring_domain"] = ""; - SendMessage(msg, cancelToken); + SendMessage(msg, _cancelToken.Token); if (!_connectWaitOnLogin.WaitOne(ReadyTimeout)) //Pre-Event throw new Exception("No reply from Discord server"); _connectWaitOnLogin2.WaitOne(); //Post-Event - } + + RaiseConnected(); + } public async Task DisconnectAsync() { if (_tasks != null) @@ -82,8 +88,6 @@ namespace Discord private async Task ReceiveAsync() { - RaiseConnected(); - var cancelToken = _cancelToken.Token; var buffer = new byte[ReceiveChunkSize]; var builder = new StringBuilder(); diff --git a/Discord.Net/Helpers/AsyncCache.cs b/src/Discord.Net/Helpers/AsyncCache.cs similarity index 100% rename from Discord.Net/Helpers/AsyncCache.cs rename to src/Discord.Net/Helpers/AsyncCache.cs diff --git a/Discord.Net/Helpers/Http.cs b/src/Discord.Net/Helpers/Http.cs similarity index 86% rename from Discord.Net/Helpers/Http.cs rename to src/Discord.Net/Helpers/Http.cs index b08e01777..efa240e97 100644 --- a/Discord.Net/Helpers/Http.cs +++ b/src/Discord.Net/Helpers/Http.cs @@ -3,7 +3,6 @@ using System; using System.IO; using System.IO.Compression; using System.Net; -using System.Net.Cache; using System.Text; using System.Threading.Tasks; @@ -13,18 +12,15 @@ namespace Discord.Helpers { public readonly string UserAgent; public string Token; - public CookieContainer Cookies; public HttpOptions(string userAgent) { UserAgent = userAgent; - Cookies = new CookieContainer(1); } } internal static class Http { - private static readonly RequestCachePolicy _cachePolicy = new RequestCachePolicy(RequestCacheLevel.NoCacheNoStore); #if DEBUG private const bool _isDebug = true; #else @@ -107,12 +103,13 @@ namespace Discord.Helpers //Create Request HttpWebRequest request = WebRequest.CreateHttp(path); request.Accept = "*/*"; + request.Method = method; + request.Proxy = null; request.Headers[HttpRequestHeader.AcceptLanguage] = "en-US;q=0.8"; request.Headers[HttpRequestHeader.AcceptEncoding] = "gzip, deflate"; - request.CachePolicy = _cachePolicy; - request.CookieContainer = options.Cookies; - request.Method = method; - request.UserAgent = options.UserAgent; + request.Headers[HttpRequestHeader.UserAgent] = options.UserAgent; + request.Headers[HttpRequestHeader.Authorization] = options.Token; + //request.UserAgent = options.UserAgent; //Add Payload if (data != null) @@ -140,18 +137,35 @@ namespace Discord.Helpers largeBuffer.Write(smallBuffer, 0, bytesRead); //Do we need to decompress? - if (!string.IsNullOrEmpty(response.ContentEncoding)) + string encoding = response.Headers[HttpResponseHeader.ContentEncoding]; + if (!string.IsNullOrEmpty(encoding)) { largeBuffer.Position = 0; - using (var decoder = GetDecoder(response.ContentEncoding, largeBuffer)) + using (var decoder = GetDecoder(encoding, largeBuffer)) using (var decodedStream = new MemoryStream()) { decoder.CopyTo(decodedStream); +#if !DOTNET return Encoding.UTF8.GetString(decodedStream.GetBuffer(), 0, (int)decodedStream.Length); +#else + ArraySegment buffer; + if (!decodedStream.TryGetBuffer(out buffer)) + throw new InvalidOperationException("Failed to get response buffer."); + return Encoding.UTF8.GetString(buffer.Array, buffer.Offset, (int)decodedStream.Length); +#endif } } else + { +#if !DOTNET return Encoding.UTF8.GetString(largeBuffer.GetBuffer(), 0, (int)largeBuffer.Length); +#else + ArraySegment buffer; + if (!largeBuffer.TryGetBuffer(out buffer)) + throw new InvalidOperationException("Failed to get response buffer."); + return Encoding.UTF8.GetString(buffer.Array, buffer.Offset, (int)largeBuffer.Length); +#endif + } } } else diff --git a/Discord.Net/Invite.cs b/src/Discord.Net/Invite.cs similarity index 100% rename from Discord.Net/Invite.cs rename to src/Discord.Net/Invite.cs diff --git a/Discord.Net/Membership.cs b/src/Discord.Net/Membership.cs similarity index 100% rename from Discord.Net/Membership.cs rename to src/Discord.Net/Membership.cs diff --git a/Discord.Net/Message.cs b/src/Discord.Net/Message.cs similarity index 100% rename from Discord.Net/Message.cs rename to src/Discord.Net/Message.cs diff --git a/Discord.Net/Regions.cs b/src/Discord.Net/Regions.cs similarity index 100% rename from Discord.Net/Regions.cs rename to src/Discord.Net/Regions.cs diff --git a/Discord.Net/Role.cs b/src/Discord.Net/Role.cs similarity index 100% rename from Discord.Net/Role.cs rename to src/Discord.Net/Role.cs diff --git a/Discord.Net/Server.cs b/src/Discord.Net/Server.cs similarity index 100% rename from Discord.Net/Server.cs rename to src/Discord.Net/Server.cs diff --git a/Discord.Net/User.cs b/src/Discord.Net/User.cs similarity index 100% rename from Discord.Net/User.cs rename to src/Discord.Net/User.cs diff --git a/src/Discord.Net/packages.config b/src/Discord.Net/packages.config new file mode 100644 index 000000000..505e58836 --- /dev/null +++ b/src/Discord.Net/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/Discord.Net/project.json b/src/Discord.Net/project.json new file mode 100644 index 000000000..af79b0793 --- /dev/null +++ b/src/Discord.Net/project.json @@ -0,0 +1,28 @@ +{ + "version": "0.3.3-*", + "description": "An unofficial .Net API wrapper for the Discord client.", + "authors": [ "RogueException" ], + "tags": [ "discord", "discordapp" ], + "projectUrl": "https://github.com/RogueException/Discord.Net", + "licenseUrl": "http://opensource.org/licenses/MIT", + "repository": { + "type": "git", + "url": "git://github.com/RogueException/Discord.Net" + }, + "compilationOptions": { + "warningsAsErrors": true + }, + "frameworks": { + "dotnet": { + "dependencies": { + "System.Collections.Concurrent": "4.0.10", + "System.IO.Compression": "4.0.0-beta-23109", + "System.Net.Requests": "4.0.10-beta-23109", + "System.Net.WebSockets.Client": "4.0.0-beta-23109", + "System.Runtime": "4.0.20", + "Microsoft.CSharp": "4.0.0", + "Newtonsoft.Json": "7.0.1" + } + } + } +} diff --git a/Discord.Net.Tests/Discord.Net.Tests.csproj b/test/Discord.Net.Tests/Discord.Net.Tests.csproj similarity index 94% rename from Discord.Net.Tests/Discord.Net.Tests.csproj rename to test/Discord.Net.Tests/Discord.Net.Tests.csproj index af0d9e395..27d5930b7 100644 --- a/Discord.Net.Tests/Discord.Net.Tests.csproj +++ b/test/Discord.Net.Tests/Discord.Net.Tests.csproj @@ -8,7 +8,7 @@ Properties Discord.Net.Tests Discord.Net.Tests - v4.5.2 + v4.6 512 {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 10.0 @@ -16,6 +16,7 @@ $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages False UnitTest + true @@ -55,8 +56,8 @@ - - {8d23f61b-723c-4966-859d-1119b28bcf19} + + {8d71a857-879a-4a10-859e-5ff824ed6688} Discord.Net diff --git a/Discord.Net.Tests/Properties/AssemblyInfo.cs b/test/Discord.Net.Tests/Properties/AssemblyInfo.cs similarity index 100% rename from Discord.Net.Tests/Properties/AssemblyInfo.cs rename to test/Discord.Net.Tests/Properties/AssemblyInfo.cs diff --git a/Discord.Net.Tests/Tests.cs b/test/Discord.Net.Tests/Tests.cs similarity index 100% rename from Discord.Net.Tests/Tests.cs rename to test/Discord.Net.Tests/Tests.cs