Browse Source

Merge branch 'concrete2' into dev

tags/1.0-rc
RogueException 8 years ago
parent
commit
ab5279dd14
100 changed files with 1831 additions and 266 deletions
  1. +38
    -1
      Discord.Net.sln
  2. +3
    -0
      src/Discord.Net.Commands/AssemblyInfo.cs
  3. +1
    -0
      src/Discord.Net.Commands/Attributes/CommandAttribute.cs
  4. +9
    -0
      src/Discord.Net.Commands/Attributes/DontAutoLoadAttribute.cs
  5. +0
    -22
      src/Discord.Net.Commands/Attributes/ModuleAttribute.cs
  6. +1
    -1
      src/Discord.Net.Commands/Attributes/PreconditionAttribute.cs
  7. +1
    -1
      src/Discord.Net.Commands/Attributes/Preconditions/RequireContextAttribute.cs
  8. +2
    -2
      src/Discord.Net.Commands/Attributes/Preconditions/RequirePermissionAttribute.cs
  9. +18
    -0
      src/Discord.Net.Commands/CommandContext.cs
  10. +41
    -27
      src/Discord.Net.Commands/CommandInfo.cs
  11. +1
    -1
      src/Discord.Net.Commands/CommandParameter.cs
  12. +1
    -1
      src/Discord.Net.Commands/CommandParser.cs
  13. +74
    -74
      src/Discord.Net.Commands/CommandService.cs
  14. +1
    -1
      src/Discord.Net.Commands/Extensions/MessageExtensions.cs
  15. +4
    -4
      src/Discord.Net.Commands/Map/CommandMap.cs
  16. +5
    -5
      src/Discord.Net.Commands/Map/CommandMapNode.cs
  17. +15
    -0
      src/Discord.Net.Commands/ModuleBase.cs
  18. +22
    -19
      src/Discord.Net.Commands/ModuleInfo.cs
  19. +7
    -1
      src/Discord.Net.Commands/PrimitiveParsers.cs
  20. +5
    -7
      src/Discord.Net.Commands/Readers/ChannelTypeReader.cs
  21. +1
    -1
      src/Discord.Net.Commands/Readers/EnumTypeReader.cs
  22. +4
    -4
      src/Discord.Net.Commands/Readers/MessageTypeReader.cs
  23. +5
    -6
      src/Discord.Net.Commands/Readers/RoleTypeReader.cs
  24. +1
    -1
      src/Discord.Net.Commands/Readers/SimpleTypeReader.cs
  25. +1
    -1
      src/Discord.Net.Commands/Readers/TypeReader.cs
  26. +12
    -12
      src/Discord.Net.Commands/Readers/UserTypeReader.cs
  27. +15
    -9
      src/Discord.Net.Commands/ReflectionUtils.cs
  28. +3
    -3
      src/Discord.Net.Commands/Results/SearchResult.cs
  29. +0
    -1
      src/Discord.Net.Commands/Results/TypeReaderResult.cs
  30. +9
    -0
      src/Discord.Net.Commands/RunMode.cs
  31. +6
    -8
      src/Discord.Net.Commands/project.json
  32. +3
    -1
      src/Discord.Net.Core/API/CDN.cs
  33. +5
    -4
      src/Discord.Net.Core/API/Common/Application.cs
  34. +0
    -0
      src/Discord.Net.Core/API/Common/Attachment.cs
  35. +0
    -0
      src/Discord.Net.Core/API/Common/Ban.cs
  36. +0
    -0
      src/Discord.Net.Core/API/Common/Channel.cs
  37. +0
    -0
      src/Discord.Net.Core/API/Common/Connection.cs
  38. +0
    -0
      src/Discord.Net.Core/API/Common/Embed.cs
  39. +0
    -0
      src/Discord.Net.Core/API/Common/EmbedProvider.cs
  40. +0
    -0
      src/Discord.Net.Core/API/Common/EmbedThumbnail.cs
  41. +0
    -0
      src/Discord.Net.Core/API/Common/Emoji.cs
  42. +0
    -0
      src/Discord.Net.Core/API/Common/Game.cs
  43. +0
    -0
      src/Discord.Net.Core/API/Common/Guild.cs
  44. +0
    -0
      src/Discord.Net.Core/API/Common/GuildEmbed.cs
  45. +0
    -0
      src/Discord.Net.Core/API/Common/GuildMember.cs
  46. +0
    -0
      src/Discord.Net.Core/API/Common/Integration.cs
  47. +0
    -0
      src/Discord.Net.Core/API/Common/IntegrationAccount.cs
  48. +0
    -0
      src/Discord.Net.Core/API/Common/Invite.cs
  49. +0
    -0
      src/Discord.Net.Core/API/Common/InviteChannel.cs
  50. +0
    -0
      src/Discord.Net.Core/API/Common/InviteGuild.cs
  51. +0
    -0
      src/Discord.Net.Core/API/Common/InviteMetadata.cs
  52. +5
    -1
      src/Discord.Net.Core/API/Common/Message.cs
  53. +0
    -0
      src/Discord.Net.Core/API/Common/Overwrite.cs
  54. +0
    -0
      src/Discord.Net.Core/API/Common/Presence.cs
  55. +0
    -0
      src/Discord.Net.Core/API/Common/ReadState.cs
  56. +0
    -0
      src/Discord.Net.Core/API/Common/Relationship.cs
  57. +2
    -1
      src/Discord.Net.Core/API/Common/RelationshipType.cs
  58. +2
    -0
      src/Discord.Net.Core/API/Common/Role.cs
  59. +0
    -0
      src/Discord.Net.Core/API/Common/User.cs
  60. +0
    -0
      src/Discord.Net.Core/API/Common/UserGuild.cs
  61. +0
    -0
      src/Discord.Net.Core/API/Common/VoiceRegion.cs
  62. +0
    -0
      src/Discord.Net.Core/API/Common/VoiceState.cs
  63. +1140
    -0
      src/Discord.Net.Core/API/DiscordRestApiClient.cs
  64. +1
    -1
      src/Discord.Net.Core/API/Image.cs
  65. +0
    -0
      src/Discord.Net.Core/API/Int53Attribute.cs
  66. +19
    -0
      src/Discord.Net.Core/API/ObjectOrId.cs
  67. +16
    -0
      src/Discord.Net.Core/API/Rest/CreateChannelInviteParams.cs
  68. +6
    -3
      src/Discord.Net.Core/API/Rest/CreateDMChannelParams.cs
  69. +8
    -0
      src/Discord.Net.Core/API/Rest/CreateGuildBanParams.cs
  70. +23
    -0
      src/Discord.Net.Core/API/Rest/CreateGuildChannelParams.cs
  71. +8
    -3
      src/Discord.Net.Core/API/Rest/CreateGuildIntegrationParams.cs
  72. +9
    -6
      src/Discord.Net.Core/API/Rest/CreateGuildParams.cs
  73. +22
    -0
      src/Discord.Net.Core/API/Rest/CreateMessageParams.cs
  74. +17
    -0
      src/Discord.Net.Core/API/Rest/DeleteMessagesParams.cs
  75. +10
    -0
      src/Discord.Net.Core/API/Rest/GetChannelMessagesParams.cs
  76. +0
    -0
      src/Discord.Net.Core/API/Rest/GetGatewayResponse.cs
  77. +9
    -0
      src/Discord.Net.Core/API/Rest/GetGuildMembersParams.cs
  78. +0
    -0
      src/Discord.Net.Core/API/Rest/GetGuildPruneCountResponse.cs
  79. +6
    -1
      src/Discord.Net.Core/API/Rest/GuildPruneParams.cs
  80. +10
    -3
      src/Discord.Net.Core/API/Rest/ModifyChannelPermissionsParams.cs
  81. +6
    -1
      src/Discord.Net.Core/API/Rest/ModifyCurrentUserNickParams.cs
  82. +2
    -6
      src/Discord.Net.Core/API/Rest/ModifyCurrentUserParams.cs
  83. +2
    -5
      src/Discord.Net.Core/API/Rest/ModifyGuildChannelParams.cs
  84. +8
    -3
      src/Discord.Net.Core/API/Rest/ModifyGuildChannelsParams.cs
  85. +14
    -0
      src/Discord.Net.Core/API/Rest/ModifyGuildEmbedParams.cs
  86. +16
    -0
      src/Discord.Net.Core/API/Rest/ModifyGuildIntegrationParams.cs
  87. +20
    -0
      src/Discord.Net.Core/API/Rest/ModifyGuildMemberParams.cs
  88. +30
    -0
      src/Discord.Net.Core/API/Rest/ModifyGuildParams.cs
  89. +20
    -0
      src/Discord.Net.Core/API/Rest/ModifyGuildRoleParams.cs
  90. +6
    -1
      src/Discord.Net.Core/API/Rest/ModifyGuildRolesParams.cs
  91. +1
    -2
      src/Discord.Net.Core/API/Rest/ModifyMessageParams.cs
  92. +11
    -0
      src/Discord.Net.Core/API/Rest/ModifyPresenceParams.cs
  93. +1
    -2
      src/Discord.Net.Core/API/Rest/ModifyTextChannelParams.cs
  94. +2
    -5
      src/Discord.Net.Core/API/Rest/ModifyVoiceChannelParams.cs
  95. +35
    -0
      src/Discord.Net.Core/API/Rest/UploadFileParams.cs
  96. +7
    -0
      src/Discord.Net.Core/AssemblyInfo.cs
  97. +4
    -4
      src/Discord.Net.Core/Audio/IAudioClient.cs
  98. +0
    -0
      src/Discord.Net.Core/Audio/Opus/OpusApplication.cs
  99. +0
    -0
      src/Discord.Net.Core/ConnectionState.cs
  100. +19
    -0
      src/Discord.Net.Core/Discord.Net.Core.xproj

+ 38
- 1
Discord.Net.sln View File

@@ -3,7 +3,23 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Discord.Net", "src\Discord.Net\Discord.Net.xproj", "{91E9E7BD-75C9-4E98-84AA-2C271922E5C2}"
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{F7F3E124-93C7-4846-AE87-9CE12BD82859}"
ProjectSection(SolutionItems) = preProject
global.json = global.json
README.md = README.md
EndProjectSection
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Discord.Net", "src\Discord.Net\Discord.Net.xproj", "{496DB20A-A455-4D01-B6BC-90FE6D7C6B81}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Discord.Net.Core", "src\Discord.Net.Core\Discord.Net.Core.xproj", "{91E9E7BD-75C9-4E98-84AA-2C271922E5C2}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Impls", "Impls", "{288C363D-A636-4EAE-9AC1-4698B641B26E}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Discord.Net.Rest", "src\Discord.Net.Rest\Discord.Net.Rest.xproj", "{BFC6DC28-0351-4573-926A-D4124244C04F}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Discord.Net.WebSocket", "src\Discord.Net.WebSocket\Discord.Net.WebSocket.xproj", "{22AB6C66-536C-4AC2-BBDB-A8BC4EB6B14D}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Discord.Net.Rpc", "src\Discord.Net.Rpc\Discord.Net.Rpc.xproj", "{5688A353-121E-40A1-8BFA-B17B91FB48FB}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Discord.Net.Commands", "src\Discord.Net.Commands\Discord.Net.Commands.xproj", "{078DD7E6-943D-4D09-AFC2-D2BA58B76C9C}"
EndProject
@@ -13,10 +29,26 @@ Global
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{496DB20A-A455-4D01-B6BC-90FE6D7C6B81}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{496DB20A-A455-4D01-B6BC-90FE6D7C6B81}.Debug|Any CPU.Build.0 = Debug|Any CPU
{496DB20A-A455-4D01-B6BC-90FE6D7C6B81}.Release|Any CPU.ActiveCfg = Release|Any CPU
{496DB20A-A455-4D01-B6BC-90FE6D7C6B81}.Release|Any CPU.Build.0 = Release|Any CPU
{91E9E7BD-75C9-4E98-84AA-2C271922E5C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{91E9E7BD-75C9-4E98-84AA-2C271922E5C2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{91E9E7BD-75C9-4E98-84AA-2C271922E5C2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{91E9E7BD-75C9-4E98-84AA-2C271922E5C2}.Release|Any CPU.Build.0 = Release|Any CPU
{BFC6DC28-0351-4573-926A-D4124244C04F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BFC6DC28-0351-4573-926A-D4124244C04F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BFC6DC28-0351-4573-926A-D4124244C04F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BFC6DC28-0351-4573-926A-D4124244C04F}.Release|Any CPU.Build.0 = Release|Any CPU
{22AB6C66-536C-4AC2-BBDB-A8BC4EB6B14D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{22AB6C66-536C-4AC2-BBDB-A8BC4EB6B14D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{22AB6C66-536C-4AC2-BBDB-A8BC4EB6B14D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{22AB6C66-536C-4AC2-BBDB-A8BC4EB6B14D}.Release|Any CPU.Build.0 = Release|Any CPU
{5688A353-121E-40A1-8BFA-B17B91FB48FB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5688A353-121E-40A1-8BFA-B17B91FB48FB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5688A353-121E-40A1-8BFA-B17B91FB48FB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5688A353-121E-40A1-8BFA-B17B91FB48FB}.Release|Any CPU.Build.0 = Release|Any CPU
{078DD7E6-943D-4D09-AFC2-D2BA58B76C9C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{078DD7E6-943D-4D09-AFC2-D2BA58B76C9C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{078DD7E6-943D-4D09-AFC2-D2BA58B76C9C}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -25,4 +57,9 @@ Global
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{BFC6DC28-0351-4573-926A-D4124244C04F} = {288C363D-A636-4EAE-9AC1-4698B641B26E}
{22AB6C66-536C-4AC2-BBDB-A8BC4EB6B14D} = {288C363D-A636-4EAE-9AC1-4698B641B26E}
{5688A353-121E-40A1-8BFA-B17B91FB48FB} = {288C363D-A636-4EAE-9AC1-4698B641B26E}
EndGlobalSection
EndGlobal

+ 3
- 0
src/Discord.Net.Commands/AssemblyInfo.cs View File

@@ -0,0 +1,3 @@
using System.Runtime.CompilerServices;

[assembly: InternalsVisibleTo("Discord.Net.Tests")]

+ 1
- 0
src/Discord.Net.Commands/Attributes/CommandAttribute.cs View File

@@ -6,6 +6,7 @@ namespace Discord.Commands
public class CommandAttribute : Attribute
{
public string Text { get; }
public RunMode RunMode { get; set; } = RunMode.Sync;

public CommandAttribute()
{


+ 9
- 0
src/Discord.Net.Commands/Attributes/DontAutoLoadAttribute.cs View File

@@ -0,0 +1,9 @@
using System;

namespace Discord.Commands
{
[AttributeUsage(AttributeTargets.Class)]
public class DontAutoLoadAttribute : Attribute
{
}
}

+ 0
- 22
src/Discord.Net.Commands/Attributes/ModuleAttribute.cs View File

@@ -1,22 +0,0 @@
using System;

namespace Discord.Commands
{
[AttributeUsage(AttributeTargets.Class)]
public class ModuleAttribute : Attribute
{
public string Prefix { get; }
public bool AutoLoad { get; set; }

public ModuleAttribute()
{
Prefix = null;
AutoLoad = true;
}
public ModuleAttribute(string prefix)
{
Prefix = prefix;
AutoLoad = true;
}
}
}

+ 1
- 1
src/Discord.Net.Commands/Attributes/PreconditionAttribute.cs View File

@@ -6,6 +6,6 @@ namespace Discord.Commands
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
public abstract class PreconditionAttribute : Attribute
{
public abstract Task<PreconditionResult> CheckPermissions(IUserMessage context, Command executingCommand, object moduleInstance);
public abstract Task<PreconditionResult> CheckPermissions(CommandContext context, CommandInfo command, IDependencyMap map);
}
}

+ 1
- 1
src/Discord.Net.Commands/Attributes/Preconditions/RequireContextAttribute.cs View File

@@ -21,7 +21,7 @@ namespace Discord.Commands
Contexts = contexts;
}

public override Task<PreconditionResult> CheckPermissions(IUserMessage context, Command executingCommand, object moduleInstance)
public override Task<PreconditionResult> CheckPermissions(CommandContext context, CommandInfo command, IDependencyMap map)
{
bool isValid = false;



+ 2
- 2
src/Discord.Net.Commands/Attributes/Preconditions/RequirePermissionAttribute.cs View File

@@ -20,9 +20,9 @@ namespace Discord.Commands
GuildPermission = null;
}
public override Task<PreconditionResult> CheckPermissions(IUserMessage context, Command executingCommand, object moduleInstance)
public override Task<PreconditionResult> CheckPermissions(CommandContext context, CommandInfo command, IDependencyMap map)
{
var guildUser = context.Author as IGuildUser;
var guildUser = context.User as IGuildUser;

if (GuildPermission.HasValue)
{


+ 18
- 0
src/Discord.Net.Commands/CommandContext.cs View File

@@ -0,0 +1,18 @@
namespace Discord.Commands
{
public struct CommandContext
{
public IGuild Guild { get; }
public IMessageChannel Channel { get; }
public IUser User { get; }
public IUserMessage Message { get; }

public CommandContext(IGuild guild, IMessageChannel channel, IUser user, IUserMessage msg)
{
Guild = guild;
Channel = channel;
User = user;
Message = msg;
}
}
}

src/Discord.Net.Commands/Command.cs → src/Discord.Net.Commands/CommandInfo.cs View File

@@ -10,38 +10,38 @@ using System.Threading.Tasks;
namespace Discord.Commands
{
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
public class Command
public class CommandInfo
{
private static readonly MethodInfo _convertParamsMethod = typeof(Command).GetTypeInfo().GetDeclaredMethod(nameof(ConvertParamsList));
private static readonly MethodInfo _convertParamsMethod = typeof(CommandInfo).GetTypeInfo().GetDeclaredMethod(nameof(ConvertParamsList));
private static readonly ConcurrentDictionary<Type, Func<IEnumerable<object>, object>> _arrayConverters = new ConcurrentDictionary<Type, Func<IEnumerable<object>, object>>();

private readonly object _instance;
private readonly Func<IUserMessage, IReadOnlyList<object>, Task> _action;
private readonly Func<CommandContext, object[], Task> _action;

public MethodInfo Source { get; }
public Module Module { get; }
public ModuleInfo Module { get; }
public string Name { get; }
public string Summary { get; }
public string Remarks { get; }
public string Text { get; }
public int Priority { get; }
public bool HasVarArgs { get; }
public RunMode RunMode { get; }
public IReadOnlyList<string> Aliases { get; }
public IReadOnlyList<CommandParameter> Parameters { get; }
public IReadOnlyList<PreconditionAttribute> Preconditions { get; }

internal Command(MethodInfo source, Module module, object instance, CommandAttribute attribute, string groupPrefix)
internal CommandInfo(MethodInfo source, ModuleInfo module, CommandAttribute attribute, string groupPrefix)
{
try
{
Source = source;
Module = module;
_instance = instance;

Name = source.Name;

if (attribute.Text == null)
Text = groupPrefix;
RunMode = attribute.RunMode;

if (groupPrefix != "")
groupPrefix += " ";
@@ -85,18 +85,18 @@ namespace Discord.Commands
}
}

public async Task<PreconditionResult> CheckPreconditions(IUserMessage context)
public async Task<PreconditionResult> CheckPreconditions(CommandContext context, IDependencyMap map = null)
{
foreach (PreconditionAttribute precondition in Module.Preconditions)
{
var result = await precondition.CheckPermissions(context, this, Module.Instance).ConfigureAwait(false);
var result = await precondition.CheckPermissions(context, this, map).ConfigureAwait(false);
if (!result.IsSuccess)
return result;
}

foreach (PreconditionAttribute precondition in Preconditions)
{
var result = await precondition.CheckPermissions(context, this, Module.Instance).ConfigureAwait(false);
var result = await precondition.CheckPermissions(context, this, map).ConfigureAwait(false);
if (!result.IsSuccess)
return result;
}
@@ -104,7 +104,7 @@ namespace Discord.Commands
return PreconditionResult.FromSuccess();
}

public async Task<ParseResult> Parse(IUserMessage context, SearchResult searchResult, PreconditionResult? preconditionResult = null)
public async Task<ParseResult> Parse(CommandContext context, SearchResult searchResult, PreconditionResult? preconditionResult = null)
{
if (!searchResult.IsSuccess)
return ParseResult.FromError(searchResult);
@@ -125,7 +125,7 @@ namespace Discord.Commands

return await CommandParser.ParseArgs(this, context, input, 0).ConfigureAwait(false);
}
public Task<ExecuteResult> Execute(IUserMessage context, ParseResult parseResult)
public Task<ExecuteResult> Execute(CommandContext context, ParseResult parseResult)
{
if (!parseResult.IsSuccess)
return Task.FromResult(ExecuteResult.FromError(parseResult));
@@ -148,11 +148,23 @@ namespace Discord.Commands

return Execute(context, argList, paramList);
}
public async Task<ExecuteResult> Execute(IUserMessage context, IEnumerable<object> argList, IEnumerable<object> paramList)
public async Task<ExecuteResult> Execute(CommandContext context, IEnumerable<object> argList, IEnumerable<object> paramList)
{
try
{
await _action.Invoke(context, GenerateArgs(argList, paramList)).ConfigureAwait(false);//Note: This code may need context
var args = GenerateArgs(argList, paramList);
switch (RunMode)
{
case RunMode.Sync: //Always sync
await _action(context, args).ConfigureAwait(false);
break;
case RunMode.Mixed: //Sync until first await statement
var t1 = _action(context, args);
break;
case RunMode.Async: //Always async
var t2 = Task.Run(() => _action(context, args));
break;
}
return ExecuteResult.FromSuccess();
}
catch (Exception ex)
@@ -169,11 +181,9 @@ namespace Discord.Commands
private IReadOnlyList<CommandParameter> BuildParameters(MethodInfo methodInfo)
{
var parameters = methodInfo.GetParameters();
if (parameters.Length == 0 || parameters[0].ParameterType != typeof(IUserMessage))
throw new InvalidOperationException($"The first parameter of a command must be {nameof(IUserMessage)}.");

var paramBuilder = ImmutableArray.CreateBuilder<CommandParameter>(parameters.Length - 1);
for (int i = 1; i < parameters.Length; i++)
var paramBuilder = ImmutableArray.CreateBuilder<CommandParameter>(parameters.Length);
for (int i = 0; i < parameters.Length; i++)
{
var parameter = parameters[i];
var type = parameter.ParameterType;
@@ -209,19 +219,23 @@ namespace Discord.Commands
}
return paramBuilder.ToImmutable();
}
private Func<IUserMessage, IReadOnlyList<object>, Task> BuildAction(MethodInfo methodInfo)
private Func<CommandContext, object[], Task> BuildAction(MethodInfo methodInfo)
{
if (methodInfo.ReturnType != typeof(Task))
throw new InvalidOperationException("Commands must return a non-generic Task.");

return (msg, args) =>
return (context, args) =>
{
object[] newArgs = new object[args.Count + 1];
newArgs[0] = msg;
for (int i = 0; i < args.Count; i++)
newArgs[i + 1] = args[i];
var result = methodInfo.Invoke(_instance, newArgs);
return result as Task ?? Task.CompletedTask;
var instance = Module.CreateInstance();
instance.Context = context;
try
{
return methodInfo.Invoke(instance, args) as Task ?? Task.CompletedTask;
}
finally
{
(instance as IDisposable)?.Dispose();
}
};
}


+ 1
- 1
src/Discord.Net.Commands/CommandParameter.cs View File

@@ -32,7 +32,7 @@ namespace Discord.Commands
DefaultValue = defaultValue;
}

public async Task<TypeReaderResult> Parse(IUserMessage context, string input)
public async Task<TypeReaderResult> Parse(CommandContext context, string input)
{
return await _reader.Read(context, input).ConfigureAwait(false);
}


+ 1
- 1
src/Discord.Net.Commands/CommandParser.cs View File

@@ -13,7 +13,7 @@ namespace Discord.Commands
QuotedParameter
}
public static async Task<ParseResult> ParseArgs(Command command, IUserMessage context, string input, int startPos)
public static async Task<ParseResult> ParseArgs(CommandInfo command, CommandContext context, string input, int startPos)
{
CommandParameter curParam = null;
StringBuilder argBuilder = new StringBuilder(input.Length);


+ 74
- 74
src/Discord.Net.Commands/CommandService.cs View File

@@ -11,21 +11,25 @@ namespace Discord.Commands
{
public class CommandService
{
private static readonly TypeInfo _moduleTypeInfo = typeof(ModuleBase).GetTypeInfo();

private readonly SemaphoreSlim _moduleLock;
private readonly ConcurrentDictionary<Type, Module> _modules;
private readonly ConcurrentDictionary<Type, ModuleInfo> _moduleDefs;
private readonly ConcurrentDictionary<Type, TypeReader> _typeReaders;
private readonly CommandMap _map;

public IEnumerable<Module> Modules => _modules.Select(x => x.Value);
public IEnumerable<Command> Commands => _modules.SelectMany(x => x.Value.Commands);
public IEnumerable<ModuleInfo> Modules => _moduleDefs.Select(x => x.Value);
public IEnumerable<CommandInfo> Commands => _moduleDefs.SelectMany(x => x.Value.Commands);

public CommandService()
{
_moduleLock = new SemaphoreSlim(1, 1);
_modules = new ConcurrentDictionary<Type, Module>();
_moduleDefs = new ConcurrentDictionary<Type, ModuleInfo>();
_map = new CommandMap();
_typeReaders = new ConcurrentDictionary<Type, TypeReader>
{
[typeof(bool)] = new SimpleTypeReader<bool>(),
[typeof(char)] = new SimpleTypeReader<char>(),
[typeof(string)] = new SimpleTypeReader<string>(),
[typeof(byte)] = new SimpleTypeReader<byte>(),
[typeof(sbyte)] = new SimpleTypeReader<sbyte>(),
@@ -43,7 +47,6 @@ namespace Discord.Commands
[typeof(IMessage)] = new MessageTypeReader<IMessage>(),
[typeof(IUserMessage)] = new MessageTypeReader<IUserMessage>(),
//[typeof(ISystemMessage)] = new MessageTypeReader<ISystemMessage>(),
[typeof(IChannel)] = new ChannelTypeReader<IChannel>(),
[typeof(IDMChannel)] = new ChannelTypeReader<IDMChannel>(),
[typeof(IGroupChannel)] = new ChannelTypeReader<IGroupChannel>(),
@@ -53,120 +56,99 @@ namespace Discord.Commands
[typeof(ITextChannel)] = new ChannelTypeReader<ITextChannel>(),
[typeof(IVoiceChannel)] = new ChannelTypeReader<IVoiceChannel>(),

//[typeof(IGuild)] = new GuildTypeReader<IGuild>(),

[typeof(IRole)] = new RoleTypeReader<IRole>(),

//[typeof(IInvite)] = new InviteTypeReader<IInvite>(),
//[typeof(IInviteMetadata)] = new InviteTypeReader<IInviteMetadata>(),

[typeof(IUser)] = new UserTypeReader<IUser>(),
[typeof(IGroupUser)] = new UserTypeReader<IGroupUser>(),
[typeof(IGuildUser)] = new UserTypeReader<IGuildUser>(),
};
}

public void AddTypeReader<T>(TypeReader reader)
{
_typeReaders[typeof(T)] = reader;
}
public void AddTypeReader(Type type, TypeReader reader)
{
_typeReaders[type] = reader;
}
internal TypeReader GetTypeReader(Type type)
{
TypeReader reader;
if (_typeReaders.TryGetValue(type, out reader))
return reader;
return null;
}

public async Task<Module> Load(object moduleInstance)
//Modules
public async Task<ModuleInfo> AddModule<T>(IDependencyMap dependencyMap = null)
{
await _moduleLock.WaitAsync().ConfigureAwait(false);
try
{
if (_modules.ContainsKey(moduleInstance.GetType()))
throw new ArgumentException($"This module has already been loaded.");
if (_moduleDefs.ContainsKey(typeof(T)))
throw new ArgumentException($"This module has already been added.");

var typeInfo = moduleInstance.GetType().GetTypeInfo();
var moduleAttr = typeInfo.GetCustomAttribute<ModuleAttribute>();
if (moduleAttr == null)
throw new ArgumentException($"Modules must be marked with ModuleAttribute.");
var typeInfo = typeof(T).GetTypeInfo();
if (!_moduleTypeInfo.IsAssignableFrom(typeInfo))
throw new ArgumentException($"Modules must inherit ModuleBase.");

return LoadInternal(moduleInstance, moduleAttr, typeInfo, null);
return AddModuleInternal(typeInfo, dependencyMap);
}
finally
{
_moduleLock.Release();
}
}
private Module LoadInternal(object moduleInstance, ModuleAttribute moduleAttr, TypeInfo typeInfo, IDependencyMap dependencyMap)
{
if (_modules.ContainsKey(moduleInstance.GetType()))
return _modules[moduleInstance.GetType()];

var loadedModule = new Module(typeInfo, this, moduleInstance, moduleAttr, dependencyMap);
_modules[moduleInstance.GetType()] = loadedModule;

foreach (var cmd in loadedModule.Commands)
_map.AddCommand(cmd);

return loadedModule;
}
public async Task<IEnumerable<Module>> LoadAssembly(Assembly assembly, IDependencyMap dependencyMap = null)
public async Task<IEnumerable<ModuleInfo>> AddModules(Assembly assembly, IDependencyMap dependencyMap = null)
{
var modules = ImmutableArray.CreateBuilder<Module>();
var moduleDefs = ImmutableArray.CreateBuilder<ModuleInfo>();
await _moduleLock.WaitAsync().ConfigureAwait(false);
try
{
foreach (var type in assembly.ExportedTypes)
{
var typeInfo = type.GetTypeInfo();
var moduleAttr = typeInfo.GetCustomAttribute<ModuleAttribute>();
if (moduleAttr != null && moduleAttr.AutoLoad)
if (!_moduleDefs.ContainsKey(type))
{
var moduleInstance = ReflectionUtils.CreateObject(typeInfo, this, dependencyMap);
modules.Add(LoadInternal(moduleInstance, moduleAttr, typeInfo, dependencyMap));
var typeInfo = type.GetTypeInfo();
if (_moduleTypeInfo.IsAssignableFrom(typeInfo))
{
var dontAutoLoad = typeInfo.GetCustomAttribute<DontAutoLoadAttribute>();
if (dontAutoLoad == null)
moduleDefs.Add(AddModuleInternal(typeInfo, dependencyMap));
}
}
}
return modules.ToImmutable();
return moduleDefs.ToImmutable();
}
finally
{
_moduleLock.Release();
}
}
private ModuleInfo AddModuleInternal(TypeInfo typeInfo, IDependencyMap dependencyMap)
{
var moduleDef = new ModuleInfo(typeInfo, this, dependencyMap);
_moduleDefs[typeInfo.BaseType] = moduleDef;

foreach (var cmd in moduleDef.Commands)
_map.AddCommand(cmd);

return moduleDef;
}

public async Task<bool> Unload(Module module)
public async Task<bool> RemoveModule(ModuleInfo module)
{
await _moduleLock.WaitAsync().ConfigureAwait(false);
try
{
return UnloadInternal(module.Instance);
return RemoveModuleInternal(module.Source.BaseType);
}
finally
{
_moduleLock.Release();
}
}
public async Task<bool> Unload(object moduleInstance)
public async Task<bool> RemoveModule<T>()
{
await _moduleLock.WaitAsync().ConfigureAwait(false);
try
{
return UnloadInternal(moduleInstance);
return RemoveModuleInternal(typeof(T));
}
finally
{
_moduleLock.Release();
}
}
private bool UnloadInternal(object module)
private bool RemoveModuleInternal(Type type)
{
Module unloadedModule;
if (_modules.TryRemove(module.GetType(), out unloadedModule))
ModuleInfo unloadedModule;
if (_moduleDefs.TryRemove(type, out unloadedModule))
{
foreach (var cmd in unloadedModule.Commands)
_map.RemoveCommand(cmd);
@@ -176,8 +158,26 @@ namespace Discord.Commands
return false;
}

public SearchResult Search(IUserMessage message, int argPos) => Search(message, message.Content.Substring(argPos));
public SearchResult Search(IUserMessage message, string input)
//Type Readers
public void AddTypeReader<T>(TypeReader reader)
{
_typeReaders[typeof(T)] = reader;
}
public void AddTypeReader(Type type, TypeReader reader)
{
_typeReaders[type] = reader;
}
internal TypeReader GetTypeReader(Type type)
{
TypeReader reader;
if (_typeReaders.TryGetValue(type, out reader))
return reader;
return null;
}

//Execution
public SearchResult Search(CommandContext context, int argPos) => Search(context, context.Message.Content.Substring(argPos));
public SearchResult Search(CommandContext context, string input)
{
string lowerInput = input.ToLowerInvariant();
var matches = _map.GetCommands(input).OrderByDescending(x => x.Priority).ToImmutableArray();
@@ -188,18 +188,18 @@ namespace Discord.Commands
return SearchResult.FromError(CommandError.UnknownCommand, "Unknown command.");
}

public Task<IResult> Execute(IUserMessage message, int argPos, MultiMatchHandling multiMatchHandling = MultiMatchHandling.Exception)
=> Execute(message, message.Content.Substring(argPos), multiMatchHandling);
public async Task<IResult> Execute(IUserMessage message, string input, MultiMatchHandling multiMatchHandling = MultiMatchHandling.Exception)
public Task<IResult> Execute(CommandContext context, int argPos, MultiMatchHandling multiMatchHandling = MultiMatchHandling.Exception)
=> Execute(context, context.Message.Content.Substring(argPos), multiMatchHandling);
public async Task<IResult> Execute(CommandContext context, string input, MultiMatchHandling multiMatchHandling = MultiMatchHandling.Exception)
{
var searchResult = Search(message, input);
var searchResult = Search(context, input);
if (!searchResult.IsSuccess)
return searchResult;

var commands = searchResult.Commands;
for (int i = commands.Count - 1; i >= 0; i--)
{
var preconditionResult = await commands[i].CheckPreconditions(message);
var preconditionResult = await commands[i].CheckPreconditions(context).ConfigureAwait(false);
if (!preconditionResult.IsSuccess)
{
if (commands.Count == 1)
@@ -208,17 +208,17 @@ namespace Discord.Commands
continue;
}

var parseResult = await commands[i].Parse(message, searchResult, preconditionResult);
var parseResult = await commands[i].Parse(context, searchResult, preconditionResult).ConfigureAwait(false);
if (!parseResult.IsSuccess)
{
if (parseResult.Error == CommandError.MultipleMatches)
{
TypeReaderValue[] argList, paramList;
IReadOnlyList<TypeReaderValue> argList, paramList;
switch (multiMatchHandling)
{
case MultiMatchHandling.Best:
argList = parseResult.ArgValues.Select(x => x.Values.OrderByDescending(y => y.Score).First()).ToArray();
paramList = parseResult.ParamValues.Select(x => x.Values.OrderByDescending(y => y.Score).First()).ToArray();
argList = parseResult.ArgValues.Select(x => x.Values.OrderByDescending(y => y.Score).First()).ToImmutableArray();
paramList = parseResult.ParamValues.Select(x => x.Values.OrderByDescending(y => y.Score).First()).ToImmutableArray();
parseResult = ParseResult.FromSuccess(argList, paramList);
break;
}
@@ -233,7 +233,7 @@ namespace Discord.Commands
}
}

return await commands[i].Execute(message, parseResult);
return await commands[i].Execute(context, parseResult).ConfigureAwait(false);
}
return SearchResult.FromError(CommandError.UnknownCommand, "This input does not match any overload.");


+ 1
- 1
src/Discord.Net.Commands/Extensions/MessageExtensions.cs View File

@@ -32,7 +32,7 @@
if (text.Length < endPos + 2 || text[endPos + 1] != ' ') return false; //Must end in "> "

ulong userId;
if (!MentionUtils.TryParseUser(text.Substring(0, endPos + 2), out userId)) return false;
if (!MentionUtils.TryParseUser(text.Substring(0, endPos + 1), out userId)) return false;
if (userId == user.Id)
{
argPos = endPos + 2;


+ 4
- 4
src/Discord.Net.Commands/Map/CommandMap.cs View File

@@ -16,7 +16,7 @@ namespace Discord.Commands
_nodes = new ConcurrentDictionary<string, CommandMapNode>();
}

public void AddCommand(Command command)
public void AddCommand(CommandInfo command)
{
foreach (string text in command.Aliases)
{
@@ -35,7 +35,7 @@ namespace Discord.Commands
}
}
}
public void RemoveCommand(Command command)
public void RemoveCommand(CommandInfo command)
{
foreach (string text in command.Aliases)
{
@@ -60,7 +60,7 @@ namespace Discord.Commands
}
}

public IEnumerable<Command> GetCommands(string text)
public IEnumerable<CommandInfo> GetCommands(string text)
{
int nextSpace = NextWhitespace(text);
string name;
@@ -76,7 +76,7 @@ namespace Discord.Commands
if (_nodes.TryGetValue(name, out nextNode))
return nextNode.GetCommands(text, nextSpace + 1);
else
return Enumerable.Empty<Command>();
return Enumerable.Empty<CommandInfo>();
}
}



+ 5
- 5
src/Discord.Net.Commands/Map/CommandMapNode.cs View File

@@ -9,7 +9,7 @@ namespace Discord.Commands
private readonly ConcurrentDictionary<string, CommandMapNode> _nodes;
private readonly string _name;
private readonly object _lockObj = new object();
private ImmutableArray<Command> _commands;
private ImmutableArray<CommandInfo> _commands;

public bool IsEmpty => _commands.Length == 0 && _nodes.Count == 0;

@@ -17,10 +17,10 @@ namespace Discord.Commands
{
_name = name;
_nodes = new ConcurrentDictionary<string, CommandMapNode>();
_commands = ImmutableArray.Create<Command>();
_commands = ImmutableArray.Create<CommandInfo>();
}

public void AddCommand(string text, int index, Command command)
public void AddCommand(string text, int index, CommandInfo command)
{
int nextSpace = text.IndexOf(' ', index);
string name;
@@ -41,7 +41,7 @@ namespace Discord.Commands
}
}
}
public void RemoveCommand(string text, int index, Command command)
public void RemoveCommand(string text, int index, CommandInfo command)
{
int nextSpace = text.IndexOf(' ', index);
string name;
@@ -68,7 +68,7 @@ namespace Discord.Commands
}
}

public IEnumerable<Command> GetCommands(string text, int index)
public IEnumerable<CommandInfo> GetCommands(string text, int index)
{
int nextSpace = text.IndexOf(' ', index);
string name;


+ 15
- 0
src/Discord.Net.Commands/ModuleBase.cs View File

@@ -0,0 +1,15 @@
using System.Threading.Tasks;

namespace Discord.Commands
{
public abstract class ModuleBase
{
public IDiscordClient Client { get; internal set; }
public CommandContext Context { get; internal set; }

protected virtual async Task ReplyAsync(string message, bool isTTS = false, RequestOptions options = null)
{
await Context.Channel.SendMessageAsync(message, isTTS, options).ConfigureAwait(false);
}
}
}

src/Discord.Net.Commands/Module.cs → src/Discord.Net.Commands/ModuleInfo.cs View File

@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Reflection;
@@ -6,26 +7,31 @@ using System.Reflection;
namespace Discord.Commands
{
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
public class Module
public class ModuleInfo
{
internal readonly Func<ModuleBase> _builder;

public TypeInfo Source { get; }
public CommandService Service { get; }
public string Name { get; }
public string Prefix { get; }
public string Summary { get; }
public string Remarks { get; }
public IEnumerable<Command> Commands { get; }
internal object Instance { get; }

public IEnumerable<CommandInfo> Commands { get; }
public IReadOnlyList<PreconditionAttribute> Preconditions { get; }

internal Module(TypeInfo source, CommandService service, object instance, ModuleAttribute moduleAttr, IDependencyMap dependencyMap)
internal ModuleInfo(TypeInfo source, CommandService service, IDependencyMap dependencyMap)
{
Source = source;
Service = service;
Name = source.Name;
Prefix = moduleAttr.Prefix ?? "";
Instance = instance;
_builder = ReflectionUtils.CreateBuilder<ModuleBase>(source, Service, dependencyMap);

var groupAttr = source.GetCustomAttribute<GroupAttribute>();
if (groupAttr != null)
Prefix = groupAttr.Prefix;
else
Prefix = "";

var nameAttr = source.GetCustomAttribute<NameAttribute>();
if (nameAttr != null)
@@ -39,20 +45,19 @@ namespace Discord.Commands
if (remarksAttr != null)
Remarks = remarksAttr.Text;

List<Command> commands = new List<Command>();
SearchClass(source, instance, commands, Prefix, dependencyMap);
List<CommandInfo> commands = new List<CommandInfo>();
SearchClass(source, commands, Prefix, dependencyMap);
Commands = commands;

Preconditions = BuildPreconditions();
Preconditions = Source.GetCustomAttributes<PreconditionAttribute>().ToImmutableArray();
}

private void SearchClass(TypeInfo parentType, object instance, List<Command> commands, string groupPrefix, IDependencyMap dependencyMap)
private void SearchClass(TypeInfo parentType, List<CommandInfo> commands, string groupPrefix, IDependencyMap dependencyMap)
{
foreach (var method in parentType.DeclaredMethods)
{
var cmdAttr = method.GetCustomAttribute<CommandAttribute>();
if (cmdAttr != null)
commands.Add(new Command(method, this, instance, cmdAttr, groupPrefix));
commands.Add(new CommandInfo(method, this, cmdAttr, groupPrefix));
}
foreach (var type in parentType.DeclaredNestedTypes)
{
@@ -66,15 +71,13 @@ namespace Discord.Commands
else
nextGroupPrefix = groupAttrib.Prefix ?? type.Name.ToLowerInvariant();

SearchClass(type, ReflectionUtils.CreateObject(type, Service, dependencyMap), commands, nextGroupPrefix, dependencyMap);
SearchClass(type, commands, nextGroupPrefix, dependencyMap);
}
}
}

private IReadOnlyList<PreconditionAttribute> BuildPreconditions()
{
return Source.GetCustomAttributes<PreconditionAttribute>().ToImmutableArray();
}
internal ModuleBase CreateInstance()
=> _builder();

public override string ToString() => Name;
private string DebuggerDisplay => Name;

+ 7
- 1
src/Discord.Net.Commands/PrimitiveParsers.cs View File

@@ -13,7 +13,7 @@ namespace Discord.Commands
static PrimitiveParsers()
{
var parserBuilder = ImmutableDictionary.CreateBuilder<Type, Delegate>();
parserBuilder[typeof(string)] = (TryParseDelegate<string>)delegate(string str, out string value) { value = str; return true; };
parserBuilder[typeof(bool)] = (TryParseDelegate<bool>)bool.TryParse;
parserBuilder[typeof(sbyte)] = (TryParseDelegate<sbyte>)sbyte.TryParse;
parserBuilder[typeof(byte)] = (TryParseDelegate<byte>)byte.TryParse;
parserBuilder[typeof(short)] = (TryParseDelegate<short>)short.TryParse;
@@ -27,6 +27,12 @@ namespace Discord.Commands
parserBuilder[typeof(decimal)] = (TryParseDelegate<decimal>)decimal.TryParse;
parserBuilder[typeof(DateTime)] = (TryParseDelegate<DateTime>)DateTime.TryParse;
parserBuilder[typeof(DateTimeOffset)] = (TryParseDelegate<DateTimeOffset>)DateTimeOffset.TryParse;
parserBuilder[typeof(char)] = (TryParseDelegate<char>)char.TryParse;
parserBuilder[typeof(string)] = (TryParseDelegate<string>)delegate (string str, out string value)
{
value = str;
return true;
};
_parsers = parserBuilder.ToImmutable();
}



+ 5
- 7
src/Discord.Net.Commands/Readers/ChannelTypeReader.cs View File

@@ -9,23 +9,21 @@ namespace Discord.Commands
internal class ChannelTypeReader<T> : TypeReader
where T : class, IChannel
{
public override async Task<TypeReaderResult> Read(IUserMessage context, string input)
public override async Task<TypeReaderResult> Read(CommandContext context, string input)
{
var guild = (context.Channel as IGuildChannel)?.Guild;

if (guild != null)
if (context.Guild != null)
{
var results = new Dictionary<ulong, TypeReaderValue>();
var channels = await guild.GetChannelsAsync().ConfigureAwait(false);
var channels = await context.Guild.GetChannelsAsync(CacheMode.CacheOnly).ConfigureAwait(false);
ulong id;

//By Mention (1.0)
if (MentionUtils.TryParseChannel(input, out id))
AddResult(results, await guild.GetChannelAsync(id).ConfigureAwait(false) as T, 1.00f);
AddResult(results, await context.Guild.GetChannelAsync(id, CacheMode.CacheOnly).ConfigureAwait(false) as T, 1.00f);

//By Id (0.9)
if (ulong.TryParse(input, NumberStyles.None, CultureInfo.InvariantCulture, out id))
AddResult(results, await guild.GetChannelAsync(id).ConfigureAwait(false) as T, 0.90f);
AddResult(results, await context.Guild.GetChannelAsync(id, CacheMode.CacheOnly).ConfigureAwait(false) as T, 0.90f);

//By Name (0.7-0.8)
foreach (var channel in channels.Where(x => string.Equals(input, x.Name, StringComparison.OrdinalIgnoreCase)))


+ 1
- 1
src/Discord.Net.Commands/Readers/EnumTypeReader.cs View File

@@ -42,7 +42,7 @@ namespace Discord.Commands
_enumsByValue = byValueBuilder.ToImmutable();
}

public override Task<TypeReaderResult> Read(IUserMessage context, string input)
public override Task<TypeReaderResult> Read(CommandContext context, string input)
{
T baseValue;
object enumValue;


+ 4
- 4
src/Discord.Net.Commands/Readers/MessageTypeReader.cs View File

@@ -6,19 +6,19 @@ namespace Discord.Commands
internal class MessageTypeReader<T> : TypeReader
where T : class, IMessage
{
public override Task<TypeReaderResult> Read(IUserMessage context, string input)
public override async Task<TypeReaderResult> Read(CommandContext context, string input)
{
ulong id;

//By Id (1.0)
if (ulong.TryParse(input, NumberStyles.None, CultureInfo.InvariantCulture, out id))
{
var msg = context.Channel.GetCachedMessage(id) as T;
var msg = await context.Channel.GetMessageAsync(id, CacheMode.CacheOnly).ConfigureAwait(false) as T;
if (msg != null)
return Task.FromResult(TypeReaderResult.FromSuccess(msg));
return TypeReaderResult.FromSuccess(msg);
}

return Task.FromResult(TypeReaderResult.FromError(CommandError.ObjectNotFound, "Message not found."));
return TypeReaderResult.FromError(CommandError.ObjectNotFound, "Message not found.");
}
}
}

+ 5
- 6
src/Discord.Net.Commands/Readers/RoleTypeReader.cs View File

@@ -9,23 +9,22 @@ namespace Discord.Commands
internal class RoleTypeReader<T> : TypeReader
where T : class, IRole
{
public override Task<TypeReaderResult> Read(IUserMessage context, string input)
public override Task<TypeReaderResult> Read(CommandContext context, string input)
{
var guild = (context.Channel as IGuildChannel)?.Guild;
ulong id;

if (guild != null)
if (context.Guild != null)
{
var results = new Dictionary<ulong, TypeReaderValue>();
var roles = guild.Roles;
var roles = context.Guild.Roles;

//By Mention (1.0)
if (MentionUtils.TryParseRole(input, out id))
AddResult(results, guild.GetRole(id) as T, 1.00f);
AddResult(results, context.Guild.GetRole(id) as T, 1.00f);

//By Id (0.9)
if (ulong.TryParse(input, NumberStyles.None, CultureInfo.InvariantCulture, out id))
AddResult(results, guild.GetRole(id) as T, 0.90f);
AddResult(results, context.Guild.GetRole(id) as T, 0.90f);

//By Name (0.7-0.8)
foreach (var role in roles.Where(x => string.Equals(input, x.Name, StringComparison.OrdinalIgnoreCase)))


+ 1
- 1
src/Discord.Net.Commands/Readers/SimpleTypeReader.cs View File

@@ -11,7 +11,7 @@ namespace Discord.Commands
_tryParse = PrimitiveParsers.Get<T>();
}

public override Task<TypeReaderResult> Read(IUserMessage context, string input)
public override Task<TypeReaderResult> Read(CommandContext context, string input)
{
T value;
if (_tryParse(input, out value))


+ 1
- 1
src/Discord.Net.Commands/Readers/TypeReader.cs View File

@@ -4,6 +4,6 @@ namespace Discord.Commands
{
public abstract class TypeReader
{
public abstract Task<TypeReaderResult> Read(IUserMessage context, string input);
public abstract Task<TypeReaderResult> Read(CommandContext context, string input);
}
}

+ 12
- 12
src/Discord.Net.Commands/Readers/UserTypeReader.cs View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
@@ -9,33 +10,32 @@ namespace Discord.Commands
internal class UserTypeReader<T> : TypeReader
where T : class, IUser
{
public override async Task<TypeReaderResult> Read(IUserMessage context, string input)
public override async Task<TypeReaderResult> Read(CommandContext context, string input)
{
var results = new Dictionary<ulong, TypeReaderValue>();
var guild = (context.Channel as IGuildChannel)?.Guild;
IReadOnlyCollection<IUser> channelUsers = await context.Channel.GetUsersAsync().ConfigureAwait(false);
IReadOnlyCollection<IUser> channelUsers = (await context.Channel.GetUsersAsync(CacheMode.CacheOnly).Flatten().ConfigureAwait(false)).ToArray(); //TODO: must be a better way?
IReadOnlyCollection<IGuildUser> guildUsers = null;
ulong id;

if (guild != null)
guildUsers = await guild.GetUsersAsync().ConfigureAwait(false);
if (context.Guild != null)
guildUsers = await context.Guild.GetUsersAsync(CacheMode.CacheOnly).ConfigureAwait(false);

//By Mention (1.0)
if (MentionUtils.TryParseUser(input, out id))
{
if (guild != null)
AddResult(results, await guild.GetUserAsync(id).ConfigureAwait(false) as T, 1.00f);
if (context.Guild != null)
AddResult(results, await context.Guild.GetUserAsync(id, CacheMode.CacheOnly).ConfigureAwait(false) as T, 1.00f);
else
AddResult(results, await context.Channel.GetUserAsync(id).ConfigureAwait(false) as T, 1.00f);
AddResult(results, await context.Channel.GetUserAsync(id, CacheMode.CacheOnly).ConfigureAwait(false) as T, 1.00f);
}

//By Id (0.9)
if (ulong.TryParse(input, NumberStyles.None, CultureInfo.InvariantCulture, out id))
{
if (guild != null)
AddResult(results, await guild.GetUserAsync(id).ConfigureAwait(false) as T, 0.90f);
if (context.Guild != null)
AddResult(results, await context.Guild.GetUserAsync(id, CacheMode.CacheOnly).ConfigureAwait(false) as T, 0.90f);
else
AddResult(results, await context.Channel.GetUserAsync(id).ConfigureAwait(false) as T, 0.90f);
AddResult(results, await context.Channel.GetUserAsync(id, CacheMode.CacheOnly).ConfigureAwait(false) as T, 0.90f);
}

//By Username + Discriminator (0.7-0.85)
@@ -75,7 +75,7 @@ namespace Discord.Commands
}

if (results.Count > 0)
return TypeReaderResult.FromSuccess(results.Values.ToArray());
return TypeReaderResult.FromSuccess(results.Values.ToImmutableArray());
return TypeReaderResult.FromError(CommandError.ObjectNotFound, "User not found.");
}



+ 15
- 9
src/Discord.Net.Commands/ReflectionUtils.cs View File

@@ -6,7 +6,10 @@ namespace Discord.Commands
{
internal class ReflectionUtils
{
internal static object CreateObject(TypeInfo typeInfo, CommandService service, IDependencyMap map = null)
internal static T CreateObject<T>(TypeInfo typeInfo, CommandService service, IDependencyMap map = null)
=> CreateBuilder<T>(typeInfo, service, map)();

internal static Func<T> CreateBuilder<T>(TypeInfo typeInfo, CommandService service, IDependencyMap map = null)
{
var constructors = typeInfo.DeclaredConstructors.Where(x => !x.IsStatic).ToArray();
if (constructors.Length == 0)
@@ -14,7 +17,7 @@ namespace Discord.Commands
else if (constructors.Length > 1)
throw new InvalidOperationException($"Multiple constructors found for \"{typeInfo.FullName}\"");

var constructor = constructors[0];
var constructor = constructors[0];
ParameterInfo[] parameters = constructor.GetParameters();
object[] args = new object[parameters.Length];

@@ -34,14 +37,17 @@ namespace Discord.Commands
args[i] = arg;
}

try
{
return constructor.Invoke(args);
}
catch (Exception ex)
return () =>
{
throw new Exception($"Failed to create \"{typeInfo.FullName}\"", ex);
}
try
{
return (T)constructor.Invoke(args);
}
catch (Exception ex)
{
throw new Exception($"Failed to create \"{typeInfo.FullName}\"", ex);
}
};
}
}
}

+ 3
- 3
src/Discord.Net.Commands/Results/SearchResult.cs View File

@@ -7,14 +7,14 @@ namespace Discord.Commands
public struct SearchResult : IResult
{
public string Text { get; }
public IReadOnlyList<Command> Commands { get; }
public IReadOnlyList<CommandInfo> Commands { get; }

public CommandError? Error { get; }
public string ErrorReason { get; }

public bool IsSuccess => !Error.HasValue;

private SearchResult(string text, IReadOnlyList<Command> commands, CommandError? error, string errorReason)
private SearchResult(string text, IReadOnlyList<CommandInfo> commands, CommandError? error, string errorReason)
{
Text = text;
Commands = commands;
@@ -22,7 +22,7 @@ namespace Discord.Commands
ErrorReason = errorReason;
}

public static SearchResult FromSuccess(string text, IReadOnlyList<Command> commands)
public static SearchResult FromSuccess(string text, IReadOnlyList<CommandInfo> commands)
=> new SearchResult(text, commands, null, null);
public static SearchResult FromError(CommandError error, string reason)
=> new SearchResult(null, null, error, reason);


+ 0
- 1
src/Discord.Net.Commands/Results/TypeReaderResult.cs View File

@@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;

namespace Discord.Commands
{


+ 9
- 0
src/Discord.Net.Commands/RunMode.cs View File

@@ -0,0 +1,9 @@
namespace Discord.Commands
{
public enum RunMode
{
Sync,
Mixed,
Async
}
}

+ 6
- 8
src/Discord.Net.Commands/project.json View File

@@ -13,24 +13,22 @@
}
},

"buildOptions": {
"allowUnsafe": true,
"warningsAsErrors": false,
"xmlDoc": true
},

"configurations": {
"Release": {
"buildOptions": {
"define": [ "RELEASE" ],
"nowarn": [ "CS1573", "CS1591" ],
"optimize": true
"optimize": true,
"warningsAsErrors": true,
"xmlDoc": true
}
}
},

"dependencies": {
"Discord.Net": "1.0.0-*"
"Discord.Net.Core": {
"target": "project"
}
},

"frameworks": {


src/Discord.Net/API/CDN.cs → src/Discord.Net.Core/API/CDN.cs View File

@@ -1,6 +1,6 @@
namespace Discord.API
{
internal static class CDN
public static class CDN
{
public static string GetApplicationIconUrl(ulong appId, string iconId)
=> iconId != null ? $"{DiscordConfig.CDNUrl}app-icons/{appId}/{iconId}.jpg" : null;
@@ -12,5 +12,7 @@
=> splashId != null ? $"{DiscordConfig.CDNUrl}splashes/{guildId}/{splashId}.jpg" : null;
public static string GetChannelIconUrl(ulong channelId, string iconId)
=> iconId != null ? $"{DiscordConfig.CDNUrl}channel-icons/{channelId}/{iconId}.jpg" : null;
public static string GetEmojiUrl(ulong emojiId)
=> $"{DiscordConfig.CDNUrl}emojis/{emojiId}.png";
}
}

src/Discord.Net/API/Common/Application.cs → src/Discord.Net.Core/API/Common/Application.cs View File

@@ -11,13 +11,14 @@ namespace Discord.API
public string[] RPCOrigins { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("flags"), Int53]
public ulong Flags { get; set; }
[JsonProperty("owner")]
public User Owner { get; set; }
[JsonProperty("id")]
public ulong Id { get; set; }
[JsonProperty("icon")]
public string Icon { get; set; }

[JsonProperty("flags"), Int53]
public Optional<ulong> Flags { get; set; }
[JsonProperty("owner")]
public Optional<User> Owner { get; set; }
}
}

src/Discord.Net/API/Common/Attachment.cs → src/Discord.Net.Core/API/Common/Attachment.cs View File


src/Discord.Net/API/Common/Ban.cs → src/Discord.Net.Core/API/Common/Ban.cs View File


src/Discord.Net/API/Common/Channel.cs → src/Discord.Net.Core/API/Common/Channel.cs View File


src/Discord.Net/API/Common/Connection.cs → src/Discord.Net.Core/API/Common/Connection.cs View File


src/Discord.Net/API/Common/Embed.cs → src/Discord.Net.Core/API/Common/Embed.cs View File


src/Discord.Net/API/Common/EmbedProvider.cs → src/Discord.Net.Core/API/Common/EmbedProvider.cs View File


src/Discord.Net/API/Common/EmbedThumbnail.cs → src/Discord.Net.Core/API/Common/EmbedThumbnail.cs View File


src/Discord.Net/API/Common/Emoji.cs → src/Discord.Net.Core/API/Common/Emoji.cs View File


src/Discord.Net/API/Common/Game.cs → src/Discord.Net.Core/API/Common/Game.cs View File


src/Discord.Net/API/Common/Guild.cs → src/Discord.Net.Core/API/Common/Guild.cs View File


src/Discord.Net/API/Common/GuildEmbed.cs → src/Discord.Net.Core/API/Common/GuildEmbed.cs View File


src/Discord.Net/API/Common/GuildMember.cs → src/Discord.Net.Core/API/Common/GuildMember.cs View File


src/Discord.Net/API/Common/Integration.cs → src/Discord.Net.Core/API/Common/Integration.cs View File


src/Discord.Net/API/Common/IntegrationAccount.cs → src/Discord.Net.Core/API/Common/IntegrationAccount.cs View File


src/Discord.Net/API/Common/Invite.cs → src/Discord.Net.Core/API/Common/Invite.cs View File


src/Discord.Net/API/Common/InviteChannel.cs → src/Discord.Net.Core/API/Common/InviteChannel.cs View File


src/Discord.Net/API/Common/InviteGuild.cs → src/Discord.Net.Core/API/Common/InviteGuild.cs View File


src/Discord.Net/API/Common/InviteMetadata.cs → src/Discord.Net.Core/API/Common/InviteMetadata.cs View File


src/Discord.Net/API/Common/Message.cs → src/Discord.Net.Core/API/Common/Message.cs View File

@@ -12,6 +12,8 @@ namespace Discord.API
public MessageType Type { get; set; }
[JsonProperty("channel_id")]
public ulong ChannelId { get; set; }
[JsonProperty("webhook_id")]
public Optional<ulong> WebhookId { get; set; }
[JsonProperty("author")]
public Optional<User> Author { get; set; }
[JsonProperty("content")]
@@ -25,7 +27,9 @@ namespace Discord.API
[JsonProperty("mention_everyone")]
public Optional<bool> MentionEveryone { get; set; }
[JsonProperty("mentions")]
public Optional<User[]> Mentions { get; set; }
public Optional<ObjectOrId<User>[]> UserMentions { get; set; }
[JsonProperty("mention_roles")]
public Optional<ulong[]> RoleMentions { get; set; }
[JsonProperty("attachments")]
public Optional<Attachment[]> Attachments { get; set; }
[JsonProperty("embeds")]

src/Discord.Net/API/Common/Overwrite.cs → src/Discord.Net.Core/API/Common/Overwrite.cs View File


src/Discord.Net/API/Common/Presence.cs → src/Discord.Net.Core/API/Common/Presence.cs View File


src/Discord.Net/API/Common/ReadState.cs → src/Discord.Net.Core/API/Common/ReadState.cs View File


src/Discord.Net/API/Common/Relationship.cs → src/Discord.Net.Core/API/Common/Relationship.cs View File


src/Discord.Net/API/Common/RelationshipType.cs → src/Discord.Net.Core/API/Common/RelationshipType.cs View File

@@ -5,6 +5,7 @@ namespace Discord.API
{
Friend = 1,
Blocked = 2,
Pending = 4
IncomingPending = 3,
OutgoingPending = 4
}
}

src/Discord.Net/API/Common/Role.cs → src/Discord.Net.Core/API/Common/Role.cs View File

@@ -13,6 +13,8 @@ namespace Discord.API
public uint Color { get; set; }
[JsonProperty("hoist")]
public bool Hoist { get; set; }
[JsonProperty("mentionable")]
public bool Mentionable { get; set; }
[JsonProperty("position")]
public int Position { get; set; }
[JsonProperty("permissions"), Int53]

src/Discord.Net/API/Common/User.cs → src/Discord.Net.Core/API/Common/User.cs View File


src/Discord.Net/API/Common/UserGuild.cs → src/Discord.Net.Core/API/Common/UserGuild.cs View File


src/Discord.Net/API/Common/VoiceRegion.cs → src/Discord.Net.Core/API/Common/VoiceRegion.cs View File


src/Discord.Net/API/Common/VoiceState.cs → src/Discord.Net.Core/API/Common/VoiceState.cs View File


+ 1140
- 0
src/Discord.Net.Core/API/DiscordRestApiClient.cs
File diff suppressed because it is too large
View File


src/Discord.Net/API/Image.cs → src/Discord.Net.Core/API/Image.cs View File

@@ -2,7 +2,7 @@

namespace Discord.API
{
internal struct Image
public struct Image
{
public Stream Stream { get; }
public string Hash { get; }

src/Discord.Net/API/Int53Attribute.cs → src/Discord.Net.Core/API/Int53Attribute.cs View File


+ 19
- 0
src/Discord.Net.Core/API/ObjectOrId.cs View File

@@ -0,0 +1,19 @@
namespace Discord.API
{
public struct ObjectOrId<T>
{
public ulong Id { get; }
public T Object { get; }

public ObjectOrId(ulong id)
{
Id = id;
Object = default(T);
}
public ObjectOrId(T obj)
{
Id = 0;
Object = obj;
}
}
}

+ 16
- 0
src/Discord.Net.Core/API/Rest/CreateChannelInviteParams.cs View File

@@ -0,0 +1,16 @@
#pragma warning disable CS1591
using Newtonsoft.Json;

namespace Discord.API.Rest
{
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
public class CreateChannelInviteParams
{
[JsonProperty("max_age")]
public Optional<int> MaxAge { get; set; }
[JsonProperty("max_uses")]
public Optional<int> MaxUses { get; set; }
[JsonProperty("temporary")]
public Optional<bool> IsTemporary { get; set; }
}
}

src/Discord.Net/API/Rest/CreateDMChannelParams.cs → src/Discord.Net.Core/API/Rest/CreateDMChannelParams.cs View File

@@ -7,8 +7,11 @@ namespace Discord.API.Rest
public class CreateDMChannelParams
{
[JsonProperty("recipient_id")]
internal ulong _recipientId { get; set; }
public ulong RecipientId { set { _recipientId = value; } }
public IUser Recipient { set { _recipientId = value.Id; } }
public ulong RecipientId { get; }

public CreateDMChannelParams(ulong recipientId)
{
RecipientId = recipientId;
}
}
}

+ 8
- 0
src/Discord.Net.Core/API/Rest/CreateGuildBanParams.cs View File

@@ -0,0 +1,8 @@
#pragma warning disable CS1591
namespace Discord.API.Rest
{
public class CreateGuildBanParams
{
public Optional<int> DeleteMessageDays { get; set; }
}
}

+ 23
- 0
src/Discord.Net.Core/API/Rest/CreateGuildChannelParams.cs View File

@@ -0,0 +1,23 @@
#pragma warning disable CS1591
using Newtonsoft.Json;

namespace Discord.API.Rest
{
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
public class CreateGuildChannelParams
{
[JsonProperty("name")]
public string Name { get; }
[JsonProperty("type")]
public ChannelType Type { get; }

[JsonProperty("bitrate")]
public Optional<int> Bitrate { get; set; }

public CreateGuildChannelParams(string name, ChannelType type)
{
Name = name;
Type = type;
}
}
}

src/Discord.Net/API/Rest/CreateGuildIntegrationParams.cs → src/Discord.Net.Core/API/Rest/CreateGuildIntegrationParams.cs View File

@@ -7,9 +7,14 @@ namespace Discord.API.Rest
public class CreateGuildIntegrationParams
{
[JsonProperty("id")]
public ulong Id { internal get; set; }

public ulong Id { get; }
[JsonProperty("type")]
public string Type { internal get; set; }
public string Type { get; }

public CreateGuildIntegrationParams(ulong id, string type)
{
Id = id;
Type = type;
}
}
}

src/Discord.Net/API/Rest/CreateGuildParams.cs → src/Discord.Net.Core/API/Rest/CreateGuildParams.cs View File

@@ -1,6 +1,5 @@
#pragma warning disable CS1591
using Newtonsoft.Json;
using System.IO;

namespace Discord.API.Rest
{
@@ -8,13 +7,17 @@ namespace Discord.API.Rest
public class CreateGuildParams
{
[JsonProperty("name")]
public string Name { internal get; set; }

public string Name { get; }
[JsonProperty("region")]
public string Region { internal get; set; }
public string RegionId { get; }

[JsonProperty("icon")]
internal Optional<Image?> _icon { get; set; }
public Stream Icon { set { _icon = value != null ? new Image(value) : (Image?)null; } }
public Optional<Image?> Icon { get; set; }

public CreateGuildParams(string name, string regionId)
{
Name = name;
RegionId = regionId;
}
}
}

+ 22
- 0
src/Discord.Net.Core/API/Rest/CreateMessageParams.cs View File

@@ -0,0 +1,22 @@
#pragma warning disable CS1591
using Newtonsoft.Json;

namespace Discord.API.Rest
{
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
public class CreateMessageParams
{
[JsonProperty("content")]
public string Content { get; }

[JsonProperty("nonce")]
public Optional<string> Nonce { get; set; }
[JsonProperty("tts")]
public Optional<bool> IsTTS { get; set; }

public CreateMessageParams(string content)
{
Content = content;
}
}
}

+ 17
- 0
src/Discord.Net.Core/API/Rest/DeleteMessagesParams.cs View File

@@ -0,0 +1,17 @@
#pragma warning disable CS1591
using Newtonsoft.Json;

namespace Discord.API.Rest
{
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
public class DeleteMessagesParams
{
[JsonProperty("messages")]
public ulong[] MessageIds { get; }

public DeleteMessagesParams(ulong[] messageIds)
{
MessageIds = messageIds;
}
}
}

+ 10
- 0
src/Discord.Net.Core/API/Rest/GetChannelMessagesParams.cs View File

@@ -0,0 +1,10 @@
#pragma warning disable CS1591
namespace Discord.API.Rest
{
public class GetChannelMessagesParams
{
public Optional<int> Limit { get; set; }
public Optional<Direction> RelativeDirection { get; set; }
public Optional<ulong> RelativeMessageId { get; set; }
}
}

src/Discord.Net/API/Rest/GetGatewayResponse.cs → src/Discord.Net.Core/API/Rest/GetGatewayResponse.cs View File


+ 9
- 0
src/Discord.Net.Core/API/Rest/GetGuildMembersParams.cs View File

@@ -0,0 +1,9 @@
#pragma warning disable CS1591
namespace Discord.API.Rest
{
public class GetGuildMembersParams
{
public Optional<int> Limit { get; set; }
public Optional<ulong> AfterUserId { get; set; }
}
}

src/Discord.Net/API/Rest/GetGuildPruneCountResponse.cs → src/Discord.Net.Core/API/Rest/GetGuildPruneCountResponse.cs View File


src/Discord.Net/API/Rest/GuildPruneParams.cs → src/Discord.Net.Core/API/Rest/GuildPruneParams.cs View File

@@ -7,6 +7,11 @@ namespace Discord.API.Rest
public class GuildPruneParams
{
[JsonProperty("days")]
public int Days { internal get; set; }
public int Days { get; }

public GuildPruneParams(int days)
{
Days = days;
}
}
}

src/Discord.Net/API/Rest/ModifyChannelPermissionsParams.cs → src/Discord.Net.Core/API/Rest/ModifyChannelPermissionsParams.cs View File

@@ -7,10 +7,17 @@ namespace Discord.API.Rest
public class ModifyChannelPermissionsParams
{
[JsonProperty("type")]
public string Type { internal get; set; }
public string Type { get; }
[JsonProperty("allow")]
public ulong Allow { internal get; set; }
public ulong Allow { get; }
[JsonProperty("deny")]
public ulong Deny { internal get; set; }
public ulong Deny { get; }

public ModifyChannelPermissionsParams(string type, ulong allow, ulong deny)
{
Type = type;
Allow = allow;
Deny = deny;
}
}
}

src/Discord.Net/API/Rest/ModifyCurrentUserNickParams.cs → src/Discord.Net.Core/API/Rest/ModifyCurrentUserNickParams.cs View File

@@ -7,6 +7,11 @@ namespace Discord.API.Rest
public class ModifyCurrentUserNickParams
{
[JsonProperty("nick")]
public string Nickname { internal get; set; }
public string Nickname { get; }

public ModifyCurrentUserNickParams(string nickname)
{
Nickname = nickname;
}
}
}

src/Discord.Net/API/Rest/ModifyCurrentUserParams.cs → src/Discord.Net.Core/API/Rest/ModifyCurrentUserParams.cs View File

@@ -1,6 +1,5 @@
#pragma warning disable CS1591
using Newtonsoft.Json;
using System.IO;

namespace Discord.API.Rest
{
@@ -8,11 +7,8 @@ namespace Discord.API.Rest
public class ModifyCurrentUserParams
{
[JsonProperty("username")]
internal Optional<string> _username { get; set; }
public string Username { set { _username = value; } }

public Optional<string> Username { get; set; }
[JsonProperty("avatar")]
internal Optional<Image> _avatar { get; set; }
public Stream Avatar { set { _avatar = new Image(value); } }
public Optional<Image> Avatar { get; set; }
}
}

src/Discord.Net/API/Rest/ModifyGuildChannelParams.cs → src/Discord.Net.Core/API/Rest/ModifyGuildChannelParams.cs View File

@@ -7,11 +7,8 @@ namespace Discord.API.Rest
public class ModifyGuildChannelParams
{
[JsonProperty("name")]
internal Optional<string> _name { get; set; }
public string Name { set { _name = value; } }

public Optional<string> Name { get; set; }
[JsonProperty("position")]
internal Optional<int> _position { get; set; }
public int Position { set { _position = value; } }
public Optional<int> Position { get; set; }
}
}

src/Discord.Net/API/Rest/ModifyGuildChannelsParams.cs → src/Discord.Net.Core/API/Rest/ModifyGuildChannelsParams.cs View File

@@ -7,9 +7,14 @@ namespace Discord.API.Rest
public class ModifyGuildChannelsParams
{
[JsonProperty("id")]
public ulong Id { internal get; set; }

public ulong Id { get; set; }
[JsonProperty("position")]
public int Position { internal get; set; }
public int Position { get; set; }

public ModifyGuildChannelsParams(ulong id, int position)
{
Id = id;
Position = position;
}
}
}

+ 14
- 0
src/Discord.Net.Core/API/Rest/ModifyGuildEmbedParams.cs View File

@@ -0,0 +1,14 @@
#pragma warning disable CS1591
using Newtonsoft.Json;

namespace Discord.API.Rest
{
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
public class ModifyGuildEmbedParams
{
[JsonProperty("enabled")]
public Optional<bool> Enabled { get; set; }
[JsonProperty("channel")]
public Optional<ulong?> ChannelId { get; set; }
}
}

+ 16
- 0
src/Discord.Net.Core/API/Rest/ModifyGuildIntegrationParams.cs View File

@@ -0,0 +1,16 @@
#pragma warning disable CS1591
using Newtonsoft.Json;

namespace Discord.API.Rest
{
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
public class ModifyGuildIntegrationParams
{
[JsonProperty("expire_behavior")]
public Optional<int> ExpireBehavior { get; set; }
[JsonProperty("expire_grace_period")]
public Optional<int> ExpireGracePeriod { get; set; }
[JsonProperty("enable_emoticons")]
public Optional<bool> EnableEmoticons { get; set; }
}
}

+ 20
- 0
src/Discord.Net.Core/API/Rest/ModifyGuildMemberParams.cs View File

@@ -0,0 +1,20 @@
#pragma warning disable CS1591
using Newtonsoft.Json;

namespace Discord.API.Rest
{
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
public class ModifyGuildMemberParams
{
[JsonProperty("mute")]
public Optional<bool> Mute { get; set; }
[JsonProperty("deaf")]
public Optional<bool> Deaf { get; set; }
[JsonProperty("nick")]
public Optional<string> Nickname { get; set; }
[JsonProperty("roles")]
public Optional<ulong[]> RoleIds { get; set; }
[JsonProperty("channel_id")]
public Optional<ulong> ChannelId { get; set; }
}
}

+ 30
- 0
src/Discord.Net.Core/API/Rest/ModifyGuildParams.cs View File

@@ -0,0 +1,30 @@
#pragma warning disable CS1591
using Newtonsoft.Json;

namespace Discord.API.Rest
{
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
public class ModifyGuildParams
{
[JsonProperty("username")]
public Optional<string> Username { get; set; }
[JsonProperty("name")]
public Optional<string> Name { get; set; }
[JsonProperty("region")]
public Optional<string> RegionId { get; set; }
[JsonProperty("verification_level")]
public Optional<VerificationLevel> VerificationLevel { get; set; }
[JsonProperty("default_message_notifications")]
public Optional<DefaultMessageNotifications> DefaultMessageNotifications { get; set; }
[JsonProperty("afk_timeout")]
public Optional<int> AfkTimeout { get; set; }
[JsonProperty("icon")]
public Optional<Image?> Icon { get; set; }
[JsonProperty("splash")]
public Optional<Image?> Splash { get; set; }
[JsonProperty("afk_channel_id")]
public Optional<ulong?> AfkChannelId { get; set; }
[JsonProperty("owner_id")]
public Optional<ulong> OwnerId { get; set; }
}
}

+ 20
- 0
src/Discord.Net.Core/API/Rest/ModifyGuildRoleParams.cs View File

@@ -0,0 +1,20 @@
#pragma warning disable CS1591
using Newtonsoft.Json;

namespace Discord.API.Rest
{
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
public class ModifyGuildRoleParams
{
[JsonProperty("name")]
public Optional<string> Name { get; set; }
[JsonProperty("permissions")]
public Optional<ulong> Permissions { get; set; }
[JsonProperty("position")]
public Optional<int> Position { get; set; }
[JsonProperty("color")]
public Optional<uint> Color { get; set; }
[JsonProperty("hoist")]
public Optional<bool> Hoist { get; set; }
}
}

src/Discord.Net/API/Rest/ModifyGuildRolesParams.cs → src/Discord.Net.Core/API/Rest/ModifyGuildRolesParams.cs View File

@@ -7,6 +7,11 @@ namespace Discord.API.Rest
public class ModifyGuildRolesParams : ModifyGuildRoleParams
{
[JsonProperty("id")]
public ulong Id { internal get; set; }
public ulong Id { get; }

public ModifyGuildRolesParams(ulong id)
{
Id = id;
}
}
}

src/Discord.Net/API/Rest/ModifyMessageParams.cs → src/Discord.Net.Core/API/Rest/ModifyMessageParams.cs View File

@@ -7,7 +7,6 @@ namespace Discord.API.Rest
public class ModifyMessageParams
{
[JsonProperty("content")]
internal Optional<string> _content { get; set; }
public string Content { set { _content = value; } }
public Optional<string> Content { get; set; }
}
}

+ 11
- 0
src/Discord.Net.Core/API/Rest/ModifyPresenceParams.cs View File

@@ -0,0 +1,11 @@
#pragma warning disable CS1591
using System;

namespace Discord.API.Rest
{
public class ModifyPresenceParams
{
public Optional<UserStatus> Status { get; set; }
public Optional<Game> Game { get; set; }
}
}

src/Discord.Net/API/Rest/ModifyTextChannelParams.cs → src/Discord.Net.Core/API/Rest/ModifyTextChannelParams.cs View File

@@ -7,7 +7,6 @@ namespace Discord.API.Rest
public class ModifyTextChannelParams : ModifyGuildChannelParams
{
[JsonProperty("topic")]
internal Optional<string> _topic { get; set; }
public string Topic { set { _topic = value; } }
public Optional<string> Topic { get; set; }
}
}

src/Discord.Net/API/Rest/ModifyVoiceChannelParams.cs → src/Discord.Net.Core/API/Rest/ModifyVoiceChannelParams.cs View File

@@ -7,11 +7,8 @@ namespace Discord.API.Rest
public class ModifyVoiceChannelParams : ModifyGuildChannelParams
{
[JsonProperty("bitrate")]
internal Optional<int> _bitrate { get; set; }
public int Bitrate { set { _bitrate = value; } }

public Optional<int> Bitrate { get; set; }
[JsonProperty("user_limit")]
internal Optional<int> _userLimit { get; set; }
public int UserLimit { set { _userLimit = value; } }
public Optional<int> UserLimit { get; set; }
}
}

+ 35
- 0
src/Discord.Net.Core/API/Rest/UploadFileParams.cs View File

@@ -0,0 +1,35 @@
#pragma warning disable CS1591
using Discord.Net.Rest;
using System.Collections.Generic;
using System.IO;

namespace Discord.API.Rest
{
public class UploadFileParams
{
public Stream File { get; }

public Optional<string> Filename { get; set; }
public Optional<string> Content { get; set; }
public Optional<string> Nonce { get; set; }
public Optional<bool> IsTTS { get; set; }

public UploadFileParams(Stream file)
{
File = file;
}

public IReadOnlyDictionary<string, object> ToDictionary()
{
var d = new Dictionary<string, object>();
d["file"] = new MultipartFile(File, Filename.GetValueOrDefault("unknown.dat"));
if (Content.IsSpecified)
d["content"] = Content.Value;
if (IsTTS.IsSpecified)
d["tts"] = IsTTS.Value.ToString();
if (Nonce.IsSpecified)
d["nonce"] = Nonce.Value;
return d;
}
}
}

+ 7
- 0
src/Discord.Net.Core/AssemblyInfo.cs View File

@@ -0,0 +1,7 @@
using System.Runtime.CompilerServices;

[assembly: InternalsVisibleTo("Discord.Net.Rest")]
[assembly: InternalsVisibleTo("Discord.Net.Rpc")]
[assembly: InternalsVisibleTo("Discord.Net.WebSocket")]
[assembly: InternalsVisibleTo("Discord.Net.Commands")]
[assembly: InternalsVisibleTo("Discord.Net.Tests")]

src/Discord.Net/Audio/IAudioClient.cs → src/Discord.Net.Core/Audio/IAudioClient.cs View File

@@ -1,4 +1,5 @@
using System;
using System.IO;
using System.Threading.Tasks;

namespace Discord.Audio
@@ -8,8 +9,7 @@ namespace Discord.Audio
event Func<Task> Connected;
event Func<Exception, Task> Disconnected;
event Func<int, int, Task> LatencyUpdated;

DiscordVoiceAPIClient ApiClient { get; }
/// <summary> Gets the current connection state of this client. </summary>
ConnectionState ConnectionState { get; }
/// <summary> Gets the estimated round-trip latency, in milliseconds, to the gateway server. </summary>
@@ -17,7 +17,7 @@ namespace Discord.Audio

Task DisconnectAsync();

RTPWriteStream CreateOpusStream(int samplesPerFrame, int bufferSize = 4000);
OpusEncodeStream CreatePCMStream(int samplesPerFrame, int? bitrate = null, OpusApplication application = OpusApplication.MusicOrMixed, int bufferSize = 4000);
Stream CreateOpusStream(int samplesPerFrame, int bufferSize = 4000);
Stream CreatePCMStream(int samplesPerFrame, int? bitrate = null, OpusApplication application = OpusApplication.MusicOrMixed, int bufferSize = 4000);
}
}

src/Discord.Net/Audio/Opus/OpusApplication.cs → src/Discord.Net.Core/Audio/Opus/OpusApplication.cs View File


src/Discord.Net/ConnectionState.cs → src/Discord.Net.Core/ConnectionState.cs View File


+ 19
- 0
src/Discord.Net.Core/Discord.Net.Core.xproj View File

@@ -0,0 +1,19 @@
<?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)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>91e9e7bd-75c9-4e98-84aa-2c271922e5c2</ProjectGuid>
<RootNamespace>Discord</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save