Merged changed from dev branch
This commit is contained in:
18
src/Discord.Net.Commands/Attributes/PriorityAttribute.cs
Normal file
18
src/Discord.Net.Commands/Attributes/PriorityAttribute.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
|
||||
namespace Discord.Commands
|
||||
{
|
||||
/// <summary> Sets priority of commands </summary>
|
||||
[AttributeUsage(AttributeTargets.Method)]
|
||||
public class PriorityAttribute : Attribute
|
||||
{
|
||||
/// <summary> The priority which has been set for the command </summary>
|
||||
public int Priority { get; }
|
||||
|
||||
/// <summary> Creates a new <see cref="PriorityAttribute"/> with the given priority. </summary>
|
||||
public PriorityAttribute(int priority)
|
||||
{
|
||||
Priority = priority;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,13 +2,13 @@
|
||||
|
||||
namespace Discord.Commands
|
||||
{
|
||||
// Full summary of method
|
||||
// Extension of the Cosmetic Summary, for Groups, Commands, and Parameters
|
||||
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
|
||||
public class DescriptionAttribute : Attribute
|
||||
public class RemarksAttribute : Attribute
|
||||
{
|
||||
public string Text { get; }
|
||||
|
||||
public DescriptionAttribute(string text)
|
||||
public RemarksAttribute(string text)
|
||||
{
|
||||
Text = text;
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace Discord.Commands
|
||||
{
|
||||
// Brief summary of method/module/parameter
|
||||
// Cosmetic Summary, for Groups and Commands
|
||||
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Parameter)]
|
||||
public class SummaryAttribute : Attribute
|
||||
{
|
||||
|
||||
@@ -21,9 +21,10 @@ namespace Discord.Commands
|
||||
public MethodInfo Source { get; }
|
||||
public Module Module { get; }
|
||||
public string Name { get; }
|
||||
public string Description { get; }
|
||||
public string Summary { get; }
|
||||
public string Remarks { get; }
|
||||
public string Text { get; }
|
||||
public int Priority { get; }
|
||||
public bool HasVarArgs { get; }
|
||||
public IReadOnlyList<string> Aliases { get; }
|
||||
public IReadOnlyList<CommandParameter> Parameters { get; }
|
||||
@@ -38,7 +39,15 @@ namespace Discord.Commands
|
||||
_instance = instance;
|
||||
|
||||
Name = source.Name;
|
||||
Text = groupPrefix + attribute.Text;
|
||||
|
||||
if (attribute.Text == null)
|
||||
Text = groupPrefix;
|
||||
|
||||
if (groupPrefix != "")
|
||||
groupPrefix += " ";
|
||||
|
||||
if (attribute.Text != null)
|
||||
Text = groupPrefix + attribute.Text;
|
||||
|
||||
var aliasesBuilder = ImmutableArray.CreateBuilder<string>();
|
||||
|
||||
@@ -54,14 +63,17 @@ namespace Discord.Commands
|
||||
if (nameAttr != null)
|
||||
Name = nameAttr.Text;
|
||||
|
||||
var description = source.GetCustomAttribute<DescriptionAttribute>();
|
||||
if (description != null)
|
||||
Description = description.Text;
|
||||
|
||||
var summary = source.GetCustomAttribute<SummaryAttribute>();
|
||||
if (summary != null)
|
||||
Summary = summary.Text;
|
||||
|
||||
var remarksAttr = source.GetCustomAttribute<RemarksAttribute>();
|
||||
if (remarksAttr != null)
|
||||
Remarks = remarksAttr.Text;
|
||||
|
||||
var priorityAttr = source.GetCustomAttribute<PriorityAttribute>();
|
||||
Priority = priorityAttr?.Priority ?? 0;
|
||||
|
||||
Parameters = BuildParameters(source);
|
||||
HasVarArgs = Parameters.Count > 0 ? Parameters[Parameters.Count - 1].IsMultiple : false;
|
||||
Preconditions = BuildPreconditions(source);
|
||||
|
||||
@@ -150,6 +150,8 @@ namespace Discord.Commands
|
||||
for (int i = argList.Count; i < command.Parameters.Count; i++)
|
||||
{
|
||||
var param = command.Parameters[i];
|
||||
if (param.IsMultiple)
|
||||
continue;
|
||||
if (!param.IsOptional)
|
||||
return ParseResult.FromError(CommandError.BadArgCount, "The input text has too few parameters.");
|
||||
argList.Add(TypeReaderResult.FromSuccess(param.DefaultValue));
|
||||
|
||||
@@ -180,7 +180,7 @@ namespace Discord.Commands
|
||||
public SearchResult Search(IUserMessage message, string input)
|
||||
{
|
||||
string lowerInput = input.ToLowerInvariant();
|
||||
var matches = _map.GetCommands(input).ToImmutableArray();
|
||||
var matches = _map.GetCommands(input).OrderByDescending(x => x.Priority).ToImmutableArray();
|
||||
|
||||
if (matches.Length > 0)
|
||||
return SearchResult.FromSuccess(input, matches);
|
||||
|
||||
@@ -7,6 +7,7 @@ namespace Discord.Commands
|
||||
internal class CommandMap
|
||||
{
|
||||
static readonly char[] _whitespaceChars = new char[] { ' ', '\r', '\n' };
|
||||
private readonly object _lockObj = new object();
|
||||
|
||||
private readonly ConcurrentDictionary<string, CommandMapNode> _nodes;
|
||||
|
||||
@@ -23,11 +24,11 @@ namespace Discord.Commands
|
||||
string name;
|
||||
|
||||
if (nextSpace == -1)
|
||||
name = command.Text;
|
||||
name = text;
|
||||
else
|
||||
name = command.Text.Substring(0, nextSpace);
|
||||
name = text.Substring(0, nextSpace);
|
||||
|
||||
lock (this)
|
||||
lock (_lockObj)
|
||||
{
|
||||
var nextNode = _nodes.GetOrAdd(name, x => new CommandMapNode(x));
|
||||
nextNode.AddCommand(nextSpace == -1 ? "" : text, nextSpace + 1, command);
|
||||
@@ -42,11 +43,11 @@ namespace Discord.Commands
|
||||
string name;
|
||||
|
||||
if (nextSpace == -1)
|
||||
name = command.Text;
|
||||
name = text;
|
||||
else
|
||||
name = command.Text.Substring(0, nextSpace);
|
||||
name = text.Substring(0, nextSpace);
|
||||
|
||||
lock (this)
|
||||
lock (_lockObj)
|
||||
{
|
||||
CommandMapNode nextNode;
|
||||
if (_nodes.TryGetValue(name, out nextNode))
|
||||
@@ -69,7 +70,7 @@ namespace Discord.Commands
|
||||
else
|
||||
name = text.Substring(0, nextSpace);
|
||||
|
||||
lock (this)
|
||||
lock (_lockObj)
|
||||
{
|
||||
CommandMapNode nextNode;
|
||||
if (_nodes.TryGetValue(name, out nextNode))
|
||||
|
||||
@@ -8,6 +8,7 @@ namespace Discord.Commands
|
||||
{
|
||||
private readonly ConcurrentDictionary<string, CommandMapNode> _nodes;
|
||||
private readonly string _name;
|
||||
private readonly object _lockObj = new object();
|
||||
private ImmutableArray<Command> _commands;
|
||||
|
||||
public bool IsEmpty => _commands.Length == 0 && _nodes.Count == 0;
|
||||
@@ -24,7 +25,7 @@ namespace Discord.Commands
|
||||
int nextSpace = text.IndexOf(' ', index);
|
||||
string name;
|
||||
|
||||
lock (this)
|
||||
lock (_lockObj)
|
||||
{
|
||||
if (text == "")
|
||||
_commands = _commands.Add(command);
|
||||
@@ -45,7 +46,7 @@ namespace Discord.Commands
|
||||
int nextSpace = text.IndexOf(' ', index);
|
||||
string name;
|
||||
|
||||
lock (this)
|
||||
lock (_lockObj)
|
||||
{
|
||||
if (text == "")
|
||||
_commands = _commands.Remove(command);
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace Discord.Commands
|
||||
public string Name { get; }
|
||||
public string Prefix { get; }
|
||||
public string Summary { get; }
|
||||
public string Description { get; }
|
||||
public string Remarks { get; }
|
||||
public IEnumerable<Command> Commands { get; }
|
||||
internal object Instance { get; }
|
||||
|
||||
@@ -35,9 +35,9 @@ namespace Discord.Commands
|
||||
if (summaryAttr != null)
|
||||
Summary = summaryAttr.Text;
|
||||
|
||||
var descriptionAttr = source.GetCustomAttribute<DescriptionAttribute>();
|
||||
if (descriptionAttr != null)
|
||||
Description = descriptionAttr.Text;
|
||||
var remarksAttr = source.GetCustomAttribute<RemarksAttribute>();
|
||||
if (remarksAttr != null)
|
||||
Remarks = remarksAttr.Text;
|
||||
|
||||
List<Command> commands = new List<Command>();
|
||||
SearchClass(source, instance, commands, Prefix, dependencyMap);
|
||||
@@ -48,8 +48,6 @@ namespace Discord.Commands
|
||||
|
||||
private void SearchClass(TypeInfo parentType, object instance, List<Command> commands, string groupPrefix, IDependencyMap dependencyMap)
|
||||
{
|
||||
if (groupPrefix != "")
|
||||
groupPrefix += " ";
|
||||
foreach (var method in parentType.DeclaredMethods)
|
||||
{
|
||||
var cmdAttr = method.GetCustomAttribute<CommandAttribute>();
|
||||
@@ -62,10 +60,12 @@ namespace Discord.Commands
|
||||
if (groupAttrib != null)
|
||||
{
|
||||
string nextGroupPrefix;
|
||||
if (groupAttrib.Prefix != null)
|
||||
nextGroupPrefix = groupPrefix + groupAttrib.Prefix ?? type.Name;
|
||||
|
||||
if (groupPrefix != "")
|
||||
nextGroupPrefix = groupPrefix + " " + (groupAttrib.Prefix ?? type.Name.ToLowerInvariant());
|
||||
else
|
||||
nextGroupPrefix = groupPrefix;
|
||||
nextGroupPrefix = groupAttrib.Prefix ?? type.Name.ToLowerInvariant();
|
||||
|
||||
SearchClass(type, ReflectionUtils.CreateObject(type, Service, dependencyMap), commands, nextGroupPrefix, dependencyMap);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
{
|
||||
public static class Format
|
||||
{
|
||||
// Characters which need escaping
|
||||
private static string[] SensitiveCharacters = { "*", "_", "~", "`", "\\" };
|
||||
|
||||
/// <summary> Returns a markdown-formatted string with bold formatting. </summary>
|
||||
public static string Bold(string text) => $"**{text}**";
|
||||
/// <summary> Returns a markdown-formatted string with italics formatting. </summary>
|
||||
@@ -19,5 +22,15 @@
|
||||
else
|
||||
return $"`{text}`";
|
||||
}
|
||||
|
||||
/// <summary> Sanitizes the string, safely escaping any Markdown sequences. </summary>
|
||||
public static string Sanitize(string text)
|
||||
{
|
||||
foreach (string unsafeChar in SensitiveCharacters)
|
||||
{
|
||||
text = text.Replace(unsafeChar, $"\\{unsafeChar}");
|
||||
}
|
||||
return text;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace Discord.WebSocket
|
||||
private int _nextAudioId;
|
||||
private bool _canReconnect;
|
||||
|
||||
/// <summary> Gets the shard if of this client. </summary>
|
||||
/// <summary> Gets the shard of of this client. </summary>
|
||||
public int ShardId { get; }
|
||||
/// <summary> Gets the current connection state of this client. </summary>
|
||||
public ConnectionState ConnectionState { get; private set; }
|
||||
@@ -793,6 +793,7 @@ namespace Discord.WebSocket
|
||||
if (guild != null)
|
||||
{
|
||||
guild.AddChannel(data, DataStore);
|
||||
channel = guild.AddChannel(data, DataStore);
|
||||
|
||||
if (!guild.IsSynced)
|
||||
{
|
||||
@@ -1263,6 +1264,12 @@ namespace Discord.WebSocket
|
||||
}
|
||||
if (after != null)
|
||||
await _messageUpdatedEvent.InvokeAsync(Optional.Create(before), after).ConfigureAwait(false);
|
||||
{
|
||||
if (before != null)
|
||||
await _messageUpdatedEvent.InvokeAsync(Optional.Create<IMessage>(before), after).ConfigureAwait(false);
|
||||
else
|
||||
await _messageUpdatedEvent.InvokeAsync(Optional.Create<IMessage>(), after).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -148,11 +148,12 @@ namespace Discord.WebSocket
|
||||
|
||||
public override Task<IGuildChannel> GetChannelAsync(ulong id) => Task.FromResult<IGuildChannel>(GetChannel(id));
|
||||
public override Task<IReadOnlyCollection<IGuildChannel>> GetChannelsAsync() => Task.FromResult<IReadOnlyCollection<IGuildChannel>>(Channels);
|
||||
public void AddChannel(ChannelModel model, DataStore dataStore, ConcurrentHashSet<ulong> channels = null)
|
||||
public ISocketGuildChannel AddChannel(ChannelModel model, DataStore dataStore, ConcurrentHashSet<ulong> channels = null)
|
||||
{
|
||||
var channel = ToChannel(model);
|
||||
(channels ?? _channels).TryAdd(model.Id);
|
||||
dataStore.AddChannel(channel);
|
||||
return channel;
|
||||
}
|
||||
public ISocketGuildChannel GetChannel(ulong id)
|
||||
{
|
||||
|
||||
@@ -8,6 +8,7 @@ namespace Discord.WebSocket
|
||||
internal class SocketGlobalUser : User, ISocketUser
|
||||
{
|
||||
internal override bool IsAttached => true;
|
||||
private readonly object _lockObj = new object();
|
||||
|
||||
private ushort _references;
|
||||
|
||||
@@ -25,13 +26,13 @@ namespace Discord.WebSocket
|
||||
{
|
||||
checked
|
||||
{
|
||||
lock (this)
|
||||
lock (_lockObj)
|
||||
_references++;
|
||||
}
|
||||
}
|
||||
public void RemoveRef(DiscordSocketClient discord)
|
||||
{
|
||||
lock (this)
|
||||
lock (_lockObj)
|
||||
{
|
||||
if (--_references == 0)
|
||||
discord.RemoveUser(Id);
|
||||
@@ -40,16 +41,16 @@ namespace Discord.WebSocket
|
||||
|
||||
public override void Update(Model model)
|
||||
{
|
||||
lock (this)
|
||||
lock (_lockObj)
|
||||
base.Update(model, source);
|
||||
}
|
||||
public void Update(PresenceModel model)
|
||||
{
|
||||
//Race conditions are okay here. Multiple shards racing already cant guarantee presence in order.
|
||||
|
||||
//lock (this)
|
||||
|
||||
//lock (_lockObj)
|
||||
//{
|
||||
var game = model.Game != null ? new Game(model.Game) : null;
|
||||
var game = model.Game != null ? new Game(model.Game) : null;
|
||||
Presence = new Presence(game, model.Status);
|
||||
//}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
{
|
||||
"version": "1.0.0-*",
|
||||
"version": "1.0.0-beta2-*",
|
||||
|
||||
"buildOptions": {
|
||||
"compile": {
|
||||
"include": [ "../Discord.Net.Entities/**.cs", "../Discord.Net.Utils/**.cs" ]
|
||||
},
|
||||
"define": [ "WEBSOCKET" ]
|
||||
"include": [ "../Discord.Net.Utils/**.cs" ]
|
||||
}
|
||||
},
|
||||
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"version": "1.0.0-beta2-*",
|
||||
"description": "An aynchronous API wrapper for Discord using .NET. This package includes all of the optional Discord.Net components",
|
||||
{
|
||||
"version": "1.0.0-beta-*",
|
||||
"description": "An unofficial .Net API wrapper for the Discord service.",
|
||||
"authors": [ "RogueException" ],
|
||||
|
||||
"packOptions": {
|
||||
@@ -13,19 +13,38 @@
|
||||
}
|
||||
},
|
||||
|
||||
"dependencies": {
|
||||
"Discord.Net.Rest": {
|
||||
"target": "project"
|
||||
"buildOptions": {
|
||||
"allowUnsafe": true,
|
||||
"warningsAsErrors": false,
|
||||
"xmlDoc": true
|
||||
},
|
||||
|
||||
"configurations": {
|
||||
"Release": {
|
||||
"buildOptions": {
|
||||
"define": [ "RELEASE" ],
|
||||
"nowarn": [ "CS1573", "CS1591" ],
|
||||
"optimize": true
|
||||
}
|
||||
}
|
||||
//"Discord.Net.WebSocket": {
|
||||
// "target": "project"
|
||||
//},
|
||||
//"Discord.Net.Rpc": {
|
||||
// "target": "project"
|
||||
//},
|
||||
//"Discord.Net.Commands": {
|
||||
// "target": "project"
|
||||
//}
|
||||
},
|
||||
|
||||
"dependencies": {
|
||||
"Microsoft.Win32.Primitives": "4.0.1",
|
||||
"Newtonsoft.Json": "8.0.3",
|
||||
"System.Collections.Concurrent": "4.0.12",
|
||||
"System.Collections.Immutable": "1.2.0",
|
||||
"System.IO.Compression": "4.1.0",
|
||||
"System.IO.FileSystem": "4.0.1",
|
||||
"System.Net.Http": "4.1.0",
|
||||
"System.Net.NameResolution": "4.0.0",
|
||||
"System.Net.Sockets": "4.1.0",
|
||||
"System.Net.WebSockets.Client": "4.0.0",
|
||||
"System.Reflection.Extensions": "4.0.1",
|
||||
"System.Runtime.InteropServices": "4.1.0",
|
||||
"System.Runtime.InteropServices.RuntimeInformation": "4.0.0",
|
||||
"System.Runtime.Serialization.Primitives": "4.1.1",
|
||||
"System.Text.RegularExpressions": "4.1.0"
|
||||
},
|
||||
|
||||
"frameworks": {
|
||||
|
||||
Reference in New Issue
Block a user