Skip to content

Commit

Permalink
Merge branch 'dev' into docs/faq-n-patches-offline
Browse files Browse the repository at this point in the history
  • Loading branch information
Still Hsu committed May 26, 2018
2 parents 3f572cc + fa759a2 commit 596b47e
Show file tree
Hide file tree
Showing 65 changed files with 484 additions and 328 deletions.
8 changes: 1 addition & 7 deletions Discord.Net.targets
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,7 @@
<PropertyGroup Condition=" '$(BuildNumber)' != '' And $(IsTagBuild) != 'true' ">
<VersionSuffix Condition=" '$(VersionSuffix)' != '' ">$(VersionSuffix)-$(BuildNumber)</VersionSuffix>
<VersionSuffix Condition=" '$(VersionSuffix)' == '' ">build-$(BuildNumber)</VersionSuffix>
</PropertyGroup>
<PropertyGroup Condition=" '$(TargetFramework)' == 'netstandard1.3' Or '$(TargetFramework)' == 'net45' ">
<DefineConstants>$(DefineConstants);FILESYSTEM;DEFAULTUDPCLIENT;DEFAULTWEBSOCKET</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(TargetFramework)' == 'netstandard1.3' ">
<DefineConstants>$(DefineConstants);FORMATSTR;UNIXTIME;MSTRYBUFFER;UDPDISPOSE</DefineConstants>
</PropertyGroup>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<NoWarn>$(NoWarn);CS1573;CS1591</NoWarn>
<WarningsAsErrors>true</WarningsAsErrors>
Expand Down
2 changes: 1 addition & 1 deletion samples/02_commands_framework/02_commands_framework.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.1.0-preview1-final" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.0.0" />
</ItemGroup>

<ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion src/Discord.Net.Analyzers/Discord.Net.Analyzers.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<TargetFramework>netstandard1.3</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis" Version="2.6.0" />
<PackageReference Include="Microsoft.CodeAnalysis" Version="2.8.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Discord.Net.Commands\Discord.Net.Commands.csproj" />
Expand Down
34 changes: 28 additions & 6 deletions src/Discord.Net.Commands/CommandParser.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Text;
using System.Threading.Tasks;
Expand All @@ -13,8 +14,7 @@ private enum ParserPart
Parameter,
QuotedParameter
}

public static async Task<ParseResult> ParseArgsAsync(CommandInfo command, ICommandContext context, IServiceProvider services, string input, int startPos)
public static async Task<ParseResult> ParseArgsAsync(CommandInfo command, ICommandContext context, bool ignoreExtraArgs, IServiceProvider services, string input, int startPos, IReadOnlyDictionary<char, char> aliasMap)
{
ParameterInfo curParam = null;
StringBuilder argBuilder = new StringBuilder(input.Length);
Expand All @@ -24,7 +24,27 @@ public static async Task<ParseResult> ParseArgsAsync(CommandInfo command, IComma
var argList = ImmutableArray.CreateBuilder<TypeReaderResult>();
var paramList = ImmutableArray.CreateBuilder<TypeReaderResult>();
bool isEscaping = false;
char c;
char c, matchQuote = '\0';

// local helper functions
bool IsOpenQuote(IReadOnlyDictionary<char, char> dict, char ch)
{
// return if the key is contained in the dictionary if it is populated
if (dict.Count != 0)
return dict.ContainsKey(ch);
// or otherwise if it is the default double quote
return c == '\"';
}

char GetMatch(IReadOnlyDictionary<char, char> dict, char ch)
{
// get the corresponding value for the key, if it exists
// and if the dictionary is populated
if (dict.Count != 0 && dict.TryGetValue(c, out var value))
return value;
// or get the default pair of the default double quote
return '\"';
}

for (int curPos = startPos; curPos <= endPos; curPos++)
{
Expand Down Expand Up @@ -74,9 +94,11 @@ public static async Task<ParseResult> ParseArgsAsync(CommandInfo command, IComma
argBuilder.Append(c);
continue;
}
if (c == '\"')

if (IsOpenQuote(aliasMap, c))
{
curPart = ParserPart.QuotedParameter;
matchQuote = GetMatch(aliasMap, c);
continue;
}
curPart = ParserPart.Parameter;
Expand All @@ -97,7 +119,7 @@ public static async Task<ParseResult> ParseArgsAsync(CommandInfo command, IComma
}
else if (curPart == ParserPart.QuotedParameter)
{
if (c == '\"')
if (c == matchQuote)
{
argString = argBuilder.ToString(); //Remove quotes
lastArgEndPos = curPos + 1;
Expand Down
9 changes: 7 additions & 2 deletions src/Discord.Net.Commands/CommandService.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Immutable;
Expand Down Expand Up @@ -38,6 +38,7 @@ public class CommandService
internal readonly RunMode _defaultRunMode;
internal readonly Logger _cmdLogger;
internal readonly LogManager _logManager;
internal readonly IReadOnlyDictionary<char, char> _quotationMarkAliasMap;

/// <summary>
/// Represents all modules loaded within <see cref="CommandService" />.
Expand Down Expand Up @@ -73,6 +74,7 @@ public CommandService(CommandServiceConfig config)
_ignoreExtraArgs = config.IgnoreExtraArgs;
_separatorChar = config.SeparatorChar;
_defaultRunMode = config.DefaultRunMode;
_quotationMarkAliasMap = (config.QuotationMarkAliasMap ?? new Dictionary<char, char>()).ToImmutableDictionary();
if (_defaultRunMode == RunMode.Default)
throw new InvalidOperationException("The default run mode cannot be set to Default.");

Expand All @@ -93,6 +95,10 @@ public CommandService(CommandServiceConfig config)
_defaultTypeReaders[typeof(Nullable<>).MakeGenericType(type)] = NullableTypeReader.Create(type, _defaultTypeReaders[type]);
}

var tsreader = new TimeSpanTypeReader();
_defaultTypeReaders[typeof(TimeSpan)] = tsreader;
_defaultTypeReaders[typeof(TimeSpan?)] = NullableTypeReader.Create(typeof(TimeSpan), tsreader);

_defaultTypeReaders[typeof(string)] =
new PrimitiveTypeReader<string>((string x, out string y) => { y = x; return true; }, 0);

Expand Down Expand Up @@ -447,7 +453,6 @@ public Task<IResult> ExecuteAsync(ICommandContext context, int argPos, IServiceP
public async Task<IResult> ExecuteAsync(ICommandContext context, string input, IServiceProvider services, MultiMatchHandling multiMatchHandling = MultiMatchHandling.Exception)
{
services = services ?? EmptyServiceProvider.Instance;

var searchResult = Search(context, input);
if (!searchResult.IsSuccess)
return searchResult;
Expand Down
9 changes: 6 additions & 3 deletions src/Discord.Net.Commands/CommandServiceConfig.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;

namespace Discord.Commands
{
Expand Down Expand Up @@ -33,9 +34,11 @@ public class CommandServiceConfig
/// </summary>
public bool ThrowOnError { get; set; } = true;

/// <summary>
/// Gets or sets whether extra parameters should be ignored.
/// </summary>
/// <summary> Collection of aliases that can wrap strings for command parsing.
/// represents the opening quotation mark and the value is the corresponding closing mark.</summary>
public Dictionary<char, char> QuotationMarkAliasMap { get; set; } = QuotationAliasUtils.GetDefaultAliasMap;

/// <summary> Determines whether extra parameters should be ignored. </summary>
public bool IgnoreExtraArgs { get; set; } = false;
}
}
10 changes: 7 additions & 3 deletions src/Discord.Net.Commands/Discord.Net.Commands.csproj
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="../../Discord.Net.targets" />
<PropertyGroup>
<AssemblyName>Discord.Net.Commands</AssemblyName>
<RootNamespace>Discord.Commands</RootNamespace>
<Description>A Discord.Net extension adding support for bot commands.</Description>
<TargetFrameworks>netstandard1.1;netstandard1.3</TargetFrameworks>
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">net46;netstandard1.3;netstandard2.0</TargetFrameworks>
<TargetFrameworks Condition=" '$(OS)' != 'Windows_NT' ">netstandard1.3;netstandard2.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Discord.Net.Core\Discord.Net.Core.csproj" />
</ItemGroup>
<ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.0.0" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' != 'netstandard2.0' ">
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="1.1.1" />
</ItemGroup>
</Project>
5 changes: 3 additions & 2 deletions src/Discord.Net.Commands/Info/CommandInfo.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Discord.Commands.Builders;
using Discord.Commands.Builders;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
Expand Down Expand Up @@ -172,7 +172,8 @@ public async Task<ParseResult> ParseAsync(ICommandContext context, int startInde
return ParseResult.FromError(preconditionResult);

string input = searchResult.Text.Substring(startIndex);
return await CommandParser.ParseArgsAsync(this, context, services, input, 0).ConfigureAwait(false);

return await CommandParser.ParseArgsAsync(this, context, _commandService._ignoreExtraArgs, services, input, 0, _commandService._quotationMarkAliasMap).ConfigureAwait(false);
}

public Task<IResult> ExecuteAsync(ICommandContext context, ParseResult parseResult, IServiceProvider services)
Expand Down
4 changes: 2 additions & 2 deletions src/Discord.Net.Commands/PrimitiveParsers.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;

Expand Down Expand Up @@ -29,7 +29,7 @@ static IReadOnlyDictionary<Type, Delegate> CreateParsers()
parserBuilder[typeof(decimal)] = (TryParseDelegate<decimal>)decimal.TryParse;
parserBuilder[typeof(DateTime)] = (TryParseDelegate<DateTime>)DateTime.TryParse;
parserBuilder[typeof(DateTimeOffset)] = (TryParseDelegate<DateTimeOffset>)DateTimeOffset.TryParse;
parserBuilder[typeof(TimeSpan)] = (TryParseDelegate<TimeSpan>)TimeSpan.TryParse;
//parserBuilder[typeof(TimeSpan)] = (TryParseDelegate<TimeSpan>)TimeSpan.TryParse;
parserBuilder[typeof(char)] = (TryParseDelegate<char>)char.TryParse;
return parserBuilder.ToImmutable();
}
Expand Down
35 changes: 35 additions & 0 deletions src/Discord.Net.Commands/Readers/TimeSpanTypeReader.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using System;
using System.Globalization;
using System.Threading.Tasks;

namespace Discord.Commands
{
internal class TimeSpanTypeReader : TypeReader
{
private static readonly string[] _formats = new[]
{
"%d'd'%h'h'%m'm'%s's'", //4d3h2m1s
"%d'd'%h'h'%m'm'", //4d3h2m
"%d'd'%h'h'%s's'", //4d3h 1s
"%d'd'%h'h'", //4d3h
"%d'd'%m'm'%s's'", //4d 2m1s
"%d'd'%m'm'", //4d 2m
"%d'd'%s's'", //4d 1s
"%d'd'", //4d
"%h'h'%m'm'%s's'", // 3h2m1s
"%h'h'%m'm'", // 3h2m
"%h'h'%s's'", // 3h 1s
"%h'h'", // 3h
"%m'm'%s's'", // 2m1s
"%m'm'", // 2m
"%s's'", // 1s
};

public override Task<TypeReaderResult> ReadAsync(ICommandContext context, string input, IServiceProvider services)
{
return (TimeSpan.TryParseExact(input.ToLowerInvariant(), _formats, CultureInfo.InvariantCulture, out var timeSpan))
? Task.FromResult(TypeReaderResult.FromSuccess(timeSpan))
: Task.FromResult(TypeReaderResult.FromError(CommandError.ParseFailed, "Failed to parse TimeSpan"));
}
}
}
95 changes: 95 additions & 0 deletions src/Discord.Net.Commands/Utilities/QuotationAliasUtils.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Globalization;

namespace Discord.Commands
{
/// <summary>
/// Utility methods for generating matching pairs of unicode quotation marks for CommandServiceConfig
/// </summary>
internal static class QuotationAliasUtils
{
/// <summary>
/// Generates an IEnumerable of characters representing open-close pairs of
/// quotation punctuation.
/// </summary>
internal static Dictionary<char, char> GetDefaultAliasMap
{
get
{
// Output of a gist provided by https://gist.github.com/ufcpp
// https://gist.github.com/ufcpp/5b2cf9a9bf7d0b8743714a0b88f7edc5
// This was not used for the implementation because of incompatibility with netstandard1.1
return new Dictionary<char, char> {
{'\"', '\"' },
{'«', '»' },
{'‘', '’' },
{'“', '”' },
{'„', '‟' },
{'‹', '›' },
{'‚', '‛' },
{'《', '》' },
{'〈', '〉' },
{'「', '」' },
{'『', '』' },
{'〝', '〞' },
{'﹁', '﹂' },
{'﹃', '﹄' },
{'"', '"' },
{''', ''' },
{'「', '」' },
{'(', ')' },
{'༺', '༻' },
{'༼', '༽' },
{'᚛', '᚜' },
{'⁅', '⁆' },
{'⌈', '⌉' },
{'⌊', '⌋' },
{'❨', '❩' },
{'❪', '❫' },
{'❬', '❭' },
{'❮', '❯' },
{'❰', '❱' },
{'❲', '❳' },
{'❴', '❵' },
{'⟅', '⟆' },
{'⟦', '⟧' },
{'⟨', '⟩' },
{'⟪', '⟫' },
{'⟬', '⟭' },
{'⟮', '⟯' },
{'⦃', '⦄' },
{'⦅', '⦆' },
{'⦇', '⦈' },
{'⦉', '⦊' },
{'⦋', '⦌' },
{'⦍', '⦎' },
{'⦏', '⦐' },
{'⦑', '⦒' },
{'⦓', '⦔' },
{'⦕', '⦖' },
{'⦗', '⦘' },
{'⧘', '⧙' },
{'⧚', '⧛' },
{'⧼', '⧽' },
{'⸂', '⸃' },
{'⸄', '⸅' },
{'⸉', '⸊' },
{'⸌', '⸍' },
{'⸜', '⸝' },
{'⸠', '⸡' },
{'⸢', '⸣' },
{'⸤', '⸥' },
{'⸦', '⸧' },
{'⸨', '⸩' },
{'【', '】'},
{'〔', '〕' },
{'〖', '〗' },
{'〘', '〙' },
{'〚', '〛' }
};
}
}
}
}
10 changes: 5 additions & 5 deletions src/Discord.Net.Core/Discord.Net.Core.csproj
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="../../Discord.Net.targets" />
<PropertyGroup>
<AssemblyName>Discord.Net.Core</AssemblyName>
<RootNamespace>Discord</RootNamespace>
<Description>The core components for the Discord.Net library.</Description>
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">net45;netstandard1.1;netstandard1.3</TargetFrameworks>
<TargetFrameworks Condition=" '$(OS)' != 'Windows_NT' ">netstandard1.1;netstandard1.3</TargetFrameworks>
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">net46;netstandard1.3;netstandard2.0</TargetFrameworks>
<TargetFrameworks Condition=" '$(OS)' != 'Windows_NT' ">netstandard1.3;netstandard2.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="10.0.2" />
<PackageReference Include="System.Collections.Immutable" Version="1.3.1" />
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
<PackageReference Include="System.Collections.Immutable" Version="1.4.0" />
<PackageReference Include="System.Interactive.Async" Version="3.1.1" />
</ItemGroup>
</Project>
1 change: 1 addition & 0 deletions src/Discord.Net.Core/DiscordConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ public class DiscordConfig
/// The maximum number of guilds that can be gotten per-batch.
/// </returns>
public const int MaxGuildsPerBatch = 100;
public const int MaxUserReactionsPerBatch = 100;
public const int MaxAuditLogEntriesPerBatch = 100;

/// <summary>
Expand Down
Loading

0 comments on commit 596b47e

Please sign in to comment.