@@ -197,3 +197,4 @@ FakesAssemblies/ | |||
#Custom | |||
Credentials.cs | |||
project.lock.json |
@@ -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 |
@@ -1,2 +0,0 @@ | |||
nuget pack Discord.Net.csproj -Prop Configuration=Release | |||
pause |
@@ -1,89 +0,0 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | |||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> | |||
<PropertyGroup> | |||
<Configuration Condition=" '$(Configuration)' == '' ">Release</Configuration> | |||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> | |||
<ProjectGuid>{8D23F61B-723C-4966-859D-1119B28BCF19}</ProjectGuid> | |||
<OutputType>Library</OutputType> | |||
<AppDesignerFolder>Properties</AppDesignerFolder> | |||
<RootNamespace>Discord</RootNamespace> | |||
<AssemblyName>Discord.Net</AssemblyName> | |||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion> | |||
<FileAlignment>512</FileAlignment> | |||
<TargetFrameworkProfile /> | |||
</PropertyGroup> | |||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> | |||
<DebugSymbols>true</DebugSymbols> | |||
<DebugType>full</DebugType> | |||
<Optimize>false</Optimize> | |||
<OutputPath>bin\Debug\</OutputPath> | |||
<DefineConstants>DEBUG;TRACE</DefineConstants> | |||
<ErrorReport>prompt</ErrorReport> | |||
<WarningLevel>4</WarningLevel> | |||
<Prefer32Bit>false</Prefer32Bit> | |||
</PropertyGroup> | |||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> | |||
<DebugType>pdbonly</DebugType> | |||
<Optimize>true</Optimize> | |||
<OutputPath>bin\Release\</OutputPath> | |||
<DefineConstants>TRACE</DefineConstants> | |||
<ErrorReport>prompt</ErrorReport> | |||
<WarningLevel>4</WarningLevel> | |||
<Prefer32Bit>false</Prefer32Bit> | |||
</PropertyGroup> | |||
<ItemGroup> | |||
<Reference Include="Newtonsoft.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> | |||
<HintPath>..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll</HintPath> | |||
<Private>True</Private> | |||
</Reference> | |||
<Reference Include="System" /> | |||
<Reference Include="System.Core" /> | |||
<Reference Include="System.Xml.Linq" /> | |||
<Reference Include="System.Data.DataSetExtensions" /> | |||
<Reference Include="Microsoft.CSharp" /> | |||
<Reference Include="System.Data" /> | |||
<Reference Include="System.Net.Http" /> | |||
<Reference Include="System.Xml" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<Compile Include="API\Models\Common.cs" /> | |||
<Compile Include="API\Models\APIRequests.cs" /> | |||
<Compile Include="API\Endpoints.cs" /> | |||
<Compile Include="API\Models\APIResponses.cs" /> | |||
<Compile Include="API\Models\WebSocketCommands.cs" /> | |||
<Compile Include="ChannelTypes.cs" /> | |||
<Compile Include="Helpers\AsyncCache.cs" /> | |||
<Compile Include="Invite.cs" /> | |||
<Compile Include="Membership.cs" /> | |||
<Compile Include="Role.cs" /> | |||
<Compile Include="Message.cs" /> | |||
<Compile Include="Channel.cs" /> | |||
<Compile Include="DiscordWebSocket.Events.cs" /> | |||
<Compile Include="Helpers\Http.cs" /> | |||
<Compile Include="API\DiscordAPI.cs" /> | |||
<Compile Include="API\Models\WebSocketEvents.cs" /> | |||
<Compile Include="DiscordClient.cs" /> | |||
<Compile Include="Regions.cs" /> | |||
<Compile Include="DiscordClient.Events.cs" /> | |||
<Compile Include="Properties\AssemblyInfo.cs" /> | |||
<Compile Include="DiscordWebSocket.cs" /> | |||
<Compile Include="Server.cs" /> | |||
<Compile Include="User.cs" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<None Include="BuildNuget.cmd" /> | |||
<None Include="Discord.Net.nuspec"> | |||
<SubType>Designer</SubType> | |||
</None> | |||
<None Include="packages.config" /> | |||
</ItemGroup> | |||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> | |||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. | |||
Other similar extension points exist, see Microsoft.Common.targets. | |||
<Target Name="BeforeBuild"> | |||
</Target> | |||
<Target Name="AfterBuild"> | |||
</Target> | |||
--> | |||
</Project> |
@@ -1,17 +0,0 @@ | |||
<?xml version="1.0"?> | |||
<package > | |||
<metadata> | |||
<id>$id$</id> | |||
<version>$version$</version> | |||
<title>$title$</title> | |||
<authors>$author$</authors> | |||
<owners>$author$</owners> | |||
<licenseUrl>http://opensource.org/licenses/MIT</licenseUrl> | |||
<projectUrl>https://github.com/RogueException/Discord.Net</projectUrl> | |||
<requireLicenseAcceptance>false</requireLicenseAcceptance> | |||
<description>$description$</description> | |||
<releaseNotes></releaseNotes> | |||
<copyright>Copyright 2015</copyright> | |||
<tags>Discord DiscordApp</tags> | |||
</metadata> | |||
</package> |
@@ -0,0 +1,8 @@ | |||
{ | |||
"projects": [ "src" ], | |||
"sdk": { | |||
"version": "1.0.0-beta6", | |||
"architecture": "x64", | |||
"runtime": "coreclr" | |||
} | |||
} |
@@ -0,0 +1,67 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | |||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> | |||
<PropertyGroup> | |||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> | |||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> | |||
<ProjectGuid>{1B5603B4-6F8F-4289-B945-7BAAE523D740}</ProjectGuid> | |||
<OutputType>Library</OutputType> | |||
<AppDesignerFolder>Properties</AppDesignerFolder> | |||
<RootNamespace>Discord.Net</RootNamespace> | |||
<AssemblyName>Discord.Net.Commands</AssemblyName> | |||
<FileAlignment>512</FileAlignment> | |||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion> | |||
</PropertyGroup> | |||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> | |||
<DebugSymbols>true</DebugSymbols> | |||
<DebugType>full</DebugType> | |||
<Optimize>false</Optimize> | |||
<OutputPath>bin\Debug\</OutputPath> | |||
<DefineConstants>DEBUG;TRACE</DefineConstants> | |||
<ErrorReport>prompt</ErrorReport> | |||
<WarningLevel>4</WarningLevel> | |||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors> | |||
</PropertyGroup> | |||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> | |||
<DebugType>pdbonly</DebugType> | |||
<Optimize>true</Optimize> | |||
<OutputPath>bin\Release\</OutputPath> | |||
<DefineConstants>TRACE</DefineConstants> | |||
<ErrorReport>prompt</ErrorReport> | |||
<WarningLevel>4</WarningLevel> | |||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors> | |||
</PropertyGroup> | |||
<ItemGroup /> | |||
<ItemGroup> | |||
<Reference Include="System" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<ProjectReference Include="..\Discord.Net.Net45\Discord.Net.csproj"> | |||
<Project>{8d71a857-879a-4a10-859e-5ff824ed6688}</Project> | |||
<Name>Discord.Net</Name> | |||
</ProjectReference> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<Compile Include="..\Discord.Net.Commands\CommandBuilder.cs"> | |||
<Link>CommandBuilder.cs</Link> | |||
</Compile> | |||
<Compile Include="..\Discord.Net.Commands\CommandParser.cs"> | |||
<Link>CommandParser.cs</Link> | |||
</Compile> | |||
<Compile Include="..\Discord.Net.Commands\DiscordBotClient.cs"> | |||
<Link>DiscordBotClient.cs</Link> | |||
</Compile> | |||
<Compile Include="..\Discord.Net.Commands\DiscordBotClient.Events.cs"> | |||
<Link>DiscordBotClient.Events.cs</Link> | |||
</Compile> | |||
<Compile Include="Properties\AssemblyInfo.cs" /> | |||
</ItemGroup> | |||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> | |||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. | |||
Other similar extension points exist, see Microsoft.Common.targets. | |||
<Target Name="BeforeBuild"> | |||
</Target> | |||
<Target Name="AfterBuild"> | |||
</Target> | |||
--> | |||
</Project> |
@@ -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")] |
@@ -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<CommandBuilder> config, bool useWhitelist = false) | |||
{ | |||
config(new CommandBuilder(_client, _prefix + ' ' + cmd, useWhitelist)); | |||
} | |||
public void AddCommand(string cmd, int minArgs, int maxArgs, Action<DiscordBotClient.CommandEventArgs> handler, bool? useWhitelist = null) | |||
{ | |||
AddCommand(cmd, minArgs, maxArgs, e => { handler(e); return null; }, useWhitelist); | |||
} | |||
public void AddCommand(string cmd, int minArgs, int maxArgs, Func<DiscordBotClient.CommandEventArgs, Task> handler, bool? useWhitelist = null) | |||
{ | |||
_client.AddCommand(cmd != "" ? _prefix + ' ' + cmd : _prefix, minArgs, maxArgs, handler, useWhitelist ?? _useWhitelist); | |||
} | |||
} | |||
} |
@@ -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<string> argList = new List<string>(); | |||
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; | |||
} | |||
} | |||
} |
@@ -0,0 +1,21 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | |||
<PropertyGroup> | |||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion> | |||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath> | |||
</PropertyGroup> | |||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" /> | |||
<PropertyGroup Label="Globals"> | |||
<ProjectGuid>19793545-ef89-48f4-8100-3ebaad0a9141</ProjectGuid> | |||
<RootNamespace>Discord.Net.Commands</RootNamespace> | |||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath> | |||
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath> | |||
</PropertyGroup> | |||
<PropertyGroup> | |||
<SchemaVersion>2.0</SchemaVersion> | |||
</PropertyGroup> | |||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'"> | |||
<ProduceOutputsOnBuild>True</ProduceOutputsOnBuild> | |||
</PropertyGroup> | |||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" /> | |||
</Project> |
@@ -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<CommandEventArgs> RanCommand; | |||
private void RaiseRanCommand(CommandEventArgs args) | |||
{ | |||
if (RanCommand != null) | |||
RanCommand(this, args); | |||
} | |||
public event EventHandler<CommandErrorEventArgs> CommandError; | |||
private void RaiseCommandError(Message msg, Command command, string[] args, Exception ex) | |||
{ | |||
if (CommandError != null) | |||
CommandError(this, new CommandErrorEventArgs(msg, command, args, ex)); | |||
} | |||
} | |||
} |
@@ -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<DiscordBotClient.CommandEventArgs, Task> Handler; | |||
public Command(string[] text, int minArgs, int maxArgs, bool useWhitelist, Func<DiscordBotClient.CommandEventArgs, Task> handler) | |||
{ | |||
Text = text; | |||
MinArgs = minArgs; | |||
MaxArgs = maxArgs; | |||
UseWhitelist = useWhitelist; | |||
Handler = handler; | |||
} | |||
} | |||
/// <summary> | |||
/// A Discord.Net client with extensions for handling common bot operations like text commands. | |||
/// </summary> | |||
public partial class DiscordBotClient : DiscordClient | |||
{ | |||
private List<Command> _commands; | |||
private List<string> _whitelist; | |||
public IEnumerable<Command> 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<Command>(); | |||
_whitelist = new List<string>(); | |||
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<CommandBuilder> config, bool useWhitelist = false) | |||
{ | |||
config(new CommandBuilder(this, cmd, useWhitelist)); | |||
} | |||
public void AddCommand(string cmd, int minArgs, int maxArgs, Action<CommandEventArgs> handler, bool useWhitelist = false) | |||
{ | |||
AddCommand(cmd, minArgs, maxArgs, e => { handler(e); return null; }, useWhitelist); | |||
} | |||
public void AddCommand(string cmd, int minArgs, int maxArgs, Func<CommandEventArgs, Task> 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); | |||
} | |||
} | |||
} |
@@ -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" | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,121 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | |||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> | |||
<PropertyGroup> | |||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> | |||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> | |||
<ProjectGuid>{8D71A857-879A-4A10-859E-5FF824ED6688}</ProjectGuid> | |||
<OutputType>Library</OutputType> | |||
<AppDesignerFolder>Properties</AppDesignerFolder> | |||
<RootNamespace>Discord.Net</RootNamespace> | |||
<AssemblyName>Discord.Net</AssemblyName> | |||
<FileAlignment>512</FileAlignment> | |||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion> | |||
</PropertyGroup> | |||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> | |||
<DebugSymbols>true</DebugSymbols> | |||
<DebugType>full</DebugType> | |||
<Optimize>false</Optimize> | |||
<OutputPath>bin\Debug\</OutputPath> | |||
<DefineConstants>DEBUG;TRACE</DefineConstants> | |||
<ErrorReport>prompt</ErrorReport> | |||
<WarningLevel>4</WarningLevel> | |||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors> | |||
</PropertyGroup> | |||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> | |||
<DebugType>pdbonly</DebugType> | |||
<Optimize>true</Optimize> | |||
<OutputPath>bin\Release\</OutputPath> | |||
<DefineConstants>TRACE</DefineConstants> | |||
<ErrorReport>prompt</ErrorReport> | |||
<WarningLevel>4</WarningLevel> | |||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors> | |||
</PropertyGroup> | |||
<ItemGroup> | |||
<Reference Include="Newtonsoft.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> | |||
<HintPath>..\..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll</HintPath> | |||
<Private>True</Private> | |||
</Reference> | |||
<Reference Include="System" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<None Include="packages.config" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<Compile Include="..\Discord.Net\API\DiscordAPI.cs"> | |||
<Link>API\DiscordAPI.cs</Link> | |||
</Compile> | |||
<Compile Include="..\Discord.Net\API\Endpoints.cs"> | |||
<Link>API\Endpoints.cs</Link> | |||
</Compile> | |||
<Compile Include="..\Discord.Net\API\Models\APIRequests.cs"> | |||
<Link>API\Models\APIRequests.cs</Link> | |||
</Compile> | |||
<Compile Include="..\Discord.Net\API\Models\APIResponses.cs"> | |||
<Link>API\Models\APIResponses.cs</Link> | |||
</Compile> | |||
<Compile Include="..\Discord.Net\API\Models\Common.cs"> | |||
<Link>API\Models\Common.cs</Link> | |||
</Compile> | |||
<Compile Include="..\Discord.Net\API\Models\WebSocketCommands.cs"> | |||
<Link>API\Models\WebSocketCommands.cs</Link> | |||
</Compile> | |||
<Compile Include="..\Discord.Net\API\Models\WebSocketEvents.cs"> | |||
<Link>API\Models\WebSocketEvents.cs</Link> | |||
</Compile> | |||
<Compile Include="..\Discord.Net\Channel.cs"> | |||
<Link>Channel.cs</Link> | |||
</Compile> | |||
<Compile Include="..\Discord.Net\ChannelTypes.cs"> | |||
<Link>ChannelTypes.cs</Link> | |||
</Compile> | |||
<Compile Include="..\Discord.Net\DiscordClient.cs"> | |||
<Link>DiscordClient.cs</Link> | |||
</Compile> | |||
<Compile Include="..\Discord.Net\DiscordClient.Events.cs"> | |||
<Link>DiscordClient.Events.cs</Link> | |||
</Compile> | |||
<Compile Include="..\Discord.Net\DiscordWebSocket.cs"> | |||
<Link>DiscordWebSocket.cs</Link> | |||
</Compile> | |||
<Compile Include="..\Discord.Net\DiscordWebSocket.Events.cs"> | |||
<Link>DiscordWebSocket.Events.cs</Link> | |||
</Compile> | |||
<Compile Include="..\Discord.Net\Helpers\AsyncCache.cs"> | |||
<Link>Helpers\AsyncCache.cs</Link> | |||
</Compile> | |||
<Compile Include="..\Discord.Net\Helpers\Http.cs"> | |||
<Link>Helpers\Http.cs</Link> | |||
</Compile> | |||
<Compile Include="..\Discord.Net\Invite.cs"> | |||
<Link>Invite.cs</Link> | |||
</Compile> | |||
<Compile Include="..\Discord.Net\Membership.cs"> | |||
<Link>Membership.cs</Link> | |||
</Compile> | |||
<Compile Include="..\Discord.Net\Message.cs"> | |||
<Link>Message.cs</Link> | |||
</Compile> | |||
<Compile Include="..\Discord.Net\Regions.cs"> | |||
<Link>Regions.cs</Link> | |||
</Compile> | |||
<Compile Include="..\Discord.Net\Role.cs"> | |||
<Link>Role.cs</Link> | |||
</Compile> | |||
<Compile Include="..\Discord.Net\Server.cs"> | |||
<Link>Server.cs</Link> | |||
</Compile> | |||
<Compile Include="..\Discord.Net\User.cs"> | |||
<Link>User.cs</Link> | |||
</Compile> | |||
<Compile Include="Properties\AssemblyInfo.cs" /> | |||
</ItemGroup> | |||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> | |||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. | |||
Other similar extension points exist, see Microsoft.Common.targets. | |||
<Target Name="BeforeBuild"> | |||
</Target> | |||
<Target Name="AfterBuild"> | |||
</Target> | |||
--> | |||
</Project> |
@@ -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")] |
@@ -1,4 +1,4 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<packages> | |||
<package id="Newtonsoft.Json" version="7.0.1" targetFramework="net452" /> | |||
<package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45" /> | |||
</packages> |
@@ -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; } |
@@ -0,0 +1,21 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | |||
<PropertyGroup> | |||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion> | |||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath> | |||
</PropertyGroup> | |||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" /> | |||
<PropertyGroup Label="Globals"> | |||
<ProjectGuid>acfb060b-ec8a-4926-b293-04c01e17ee23</ProjectGuid> | |||
<RootNamespace>Discord.Net</RootNamespace> | |||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath> | |||
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath> | |||
</PropertyGroup> | |||
<PropertyGroup> | |||
<SchemaVersion>2.0</SchemaVersion> | |||
</PropertyGroup> | |||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'"> | |||
<ProduceOutputsOnBuild>True</ProduceOutputsOnBuild> | |||
</PropertyGroup> | |||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" /> | |||
</Project> |
@@ -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<Role> Roles => _roles; | |||
private AsyncCache<Role, API.Models.Role> _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<Server, API.Models.ServerReference>( | |||
@@ -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"); | |||
} | |||
/// <summary> | |||
/// Blocking call that will not return until client has been stopped. This is mainly intended for use in console applications. | |||
/// </summary> | |||
/// <returns></returns> | |||
public void Block() | |||
{ | |||
//Blocking call for console apps | |||
//TODO: Improve this | |||
while (!_isClosing) | |||
Thread.Sleep(1000); | |||
_isStopping.Wait(); | |||
} | |||
} | |||
} |
@@ -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<byte[]>(); | |||
_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(); |
@@ -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<byte> 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<byte> 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 |
@@ -0,0 +1,4 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<packages> | |||
<package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45" /> | |||
</packages> |
@@ -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" | |||
} | |||
} | |||
} | |||
} |
@@ -8,7 +8,7 @@ | |||
<AppDesignerFolder>Properties</AppDesignerFolder> | |||
<RootNamespace>Discord.Net.Tests</RootNamespace> | |||
<AssemblyName>Discord.Net.Tests</AssemblyName> | |||
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion> | |||
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion> | |||
<FileAlignment>512</FileAlignment> | |||
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> | |||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion> | |||
@@ -16,6 +16,7 @@ | |||
<ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages</ReferencePath> | |||
<IsCodedUITest>False</IsCodedUITest> | |||
<TestProjectType>UnitTest</TestProjectType> | |||
<TargetFrameworkProfile /> | |||
</PropertyGroup> | |||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> | |||
<DebugSymbols>true</DebugSymbols> | |||
@@ -55,8 +56,8 @@ | |||
<Compile Include="Properties\AssemblyInfo.cs" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<ProjectReference Include="..\Discord.Net\Discord.Net.csproj"> | |||
<Project>{8d23f61b-723c-4966-859d-1119b28bcf19}</Project> | |||
<ProjectReference Include="..\..\src\Discord.Net.Net45\Discord.Net.csproj"> | |||
<Project>{8d71a857-879a-4a10-859e-5ff824ed6688}</Project> | |||
<Name>Discord.Net</Name> | |||
</ProjectReference> | |||
</ItemGroup> |