| @@ -7,7 +7,7 @@ | |||||
| <ProjectGuid>{1B5603B4-6F8F-4289-B945-7BAAE523D740}</ProjectGuid> | <ProjectGuid>{1B5603B4-6F8F-4289-B945-7BAAE523D740}</ProjectGuid> | ||||
| <OutputType>Library</OutputType> | <OutputType>Library</OutputType> | ||||
| <AppDesignerFolder>Properties</AppDesignerFolder> | <AppDesignerFolder>Properties</AppDesignerFolder> | ||||
| <RootNamespace>Discord</RootNamespace> | |||||
| <RootNamespace>Discord.Commands</RootNamespace> | |||||
| <AssemblyName>Discord.Net.Commands</AssemblyName> | <AssemblyName>Discord.Net.Commands</AssemblyName> | ||||
| <FileAlignment>512</FileAlignment> | <FileAlignment>512</FileAlignment> | ||||
| <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> | <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> | ||||
| @@ -43,17 +43,23 @@ | |||||
| <Compile Include="..\Discord.Net.Commands\CommandBuilder.cs"> | <Compile Include="..\Discord.Net.Commands\CommandBuilder.cs"> | ||||
| <Link>CommandBuilder.cs</Link> | <Link>CommandBuilder.cs</Link> | ||||
| </Compile> | </Compile> | ||||
| <Compile Include="..\Discord.Net.Commands\CommandExtensions.cs"> | |||||
| <Link>CommandExtensions.cs</Link> | |||||
| </Compile> | |||||
| <Compile Include="..\Discord.Net.Commands\CommandMap.cs"> | <Compile Include="..\Discord.Net.Commands\CommandMap.cs"> | ||||
| <Link>CommandMap.cs</Link> | <Link>CommandMap.cs</Link> | ||||
| </Compile> | </Compile> | ||||
| <Compile Include="..\Discord.Net.Commands\CommandParser.cs"> | <Compile Include="..\Discord.Net.Commands\CommandParser.cs"> | ||||
| <Link>CommandParser.cs</Link> | <Link>CommandParser.cs</Link> | ||||
| </Compile> | </Compile> | ||||
| <Compile Include="..\Discord.Net.Commands\CommandsPlugin.cs"> | |||||
| <Link>CommandsPlugin.cs</Link> | |||||
| <Compile Include="..\Discord.Net.Commands\CommandService.cs"> | |||||
| <Link>CommandService.cs</Link> | |||||
| </Compile> | |||||
| <Compile Include="..\Discord.Net.Commands\CommandService.Events.cs"> | |||||
| <Link>CommandService.Events.cs</Link> | |||||
| </Compile> | </Compile> | ||||
| <Compile Include="..\Discord.Net.Commands\CommandsPlugin.Events.cs"> | |||||
| <Link>CommandsPlugin.Events.cs</Link> | |||||
| <Compile Include="..\Discord.Net.Commands\CommandServiceConfig.cs"> | |||||
| <Link>CommandServiceConfig.cs</Link> | |||||
| </Compile> | </Compile> | ||||
| <Compile Include="Properties\AssemblyInfo.cs" /> | <Compile Include="Properties\AssemblyInfo.cs" /> | ||||
| </ItemGroup> | </ItemGroup> | ||||
| @@ -7,15 +7,15 @@ namespace Discord.Commands | |||||
| { | { | ||||
| public sealed class CommandBuilder | public sealed class CommandBuilder | ||||
| { | { | ||||
| private readonly CommandsPlugin _plugin; | |||||
| private readonly CommandService _service; | |||||
| private readonly Command _command; | private readonly Command _command; | ||||
| private List<CommandParameter> _params; | private List<CommandParameter> _params; | ||||
| private bool _allowRequired, _isClosed; | private bool _allowRequired, _isClosed; | ||||
| private string _prefix; | private string _prefix; | ||||
| public CommandBuilder(CommandsPlugin plugin, Command command, string prefix) | |||||
| public CommandBuilder(CommandService service, Command command, string prefix) | |||||
| { | { | ||||
| _plugin = plugin; | |||||
| _service = service; | |||||
| _command = command; | _command = command; | ||||
| _params = new List<CommandParameter>(); | _params = new List<CommandParameter>(); | ||||
| _prefix = prefix; | _prefix = prefix; | ||||
| @@ -75,8 +75,8 @@ namespace Discord.Commands | |||||
| { | { | ||||
| _command.SetParameters(_params.ToArray()); | _command.SetParameters(_params.ToArray()); | ||||
| foreach (var alias in _command.Aliases) | foreach (var alias in _command.Aliases) | ||||
| _plugin.Map.AddCommand(alias, _command); | |||||
| _plugin.AddCommand(_command); | |||||
| _service.Map.AddCommand(alias, _command); | |||||
| _service.AddCommand(_command); | |||||
| } | } | ||||
| internal static string AppendPrefix(string prefix, string cmd) | internal static string AppendPrefix(string prefix, string cmd) | ||||
| @@ -99,13 +99,13 @@ namespace Discord.Commands | |||||
| } | } | ||||
| public sealed class CommandGroupBuilder | public sealed class CommandGroupBuilder | ||||
| { | { | ||||
| internal readonly CommandsPlugin _plugin; | |||||
| internal readonly CommandService _service; | |||||
| private readonly string _prefix; | private readonly string _prefix; | ||||
| private int _defaultMinPermissions; | private int _defaultMinPermissions; | ||||
| internal CommandGroupBuilder(CommandsPlugin plugin, string prefix, int defaultMinPermissions) | |||||
| internal CommandGroupBuilder(CommandService service, string prefix, int defaultMinPermissions) | |||||
| { | { | ||||
| _plugin = plugin; | |||||
| _service = service; | |||||
| _prefix = prefix; | _prefix = prefix; | ||||
| _defaultMinPermissions = defaultMinPermissions; | _defaultMinPermissions = defaultMinPermissions; | ||||
| } | } | ||||
| @@ -117,7 +117,7 @@ namespace Discord.Commands | |||||
| public CommandGroupBuilder CreateCommandGroup(string cmd, Action<CommandGroupBuilder> config = null) | public CommandGroupBuilder CreateCommandGroup(string cmd, Action<CommandGroupBuilder> config = null) | ||||
| { | { | ||||
| config(new CommandGroupBuilder(_plugin, _prefix + ' ' + cmd, _defaultMinPermissions)); | |||||
| config(new CommandGroupBuilder(_service, _prefix + ' ' + cmd, _defaultMinPermissions)); | |||||
| return this; | return this; | ||||
| } | } | ||||
| public CommandBuilder CreateCommand() | public CommandBuilder CreateCommand() | ||||
| @@ -126,7 +126,7 @@ namespace Discord.Commands | |||||
| { | { | ||||
| var command = new Command(CommandBuilder.AppendPrefix(_prefix, cmd)); | var command = new Command(CommandBuilder.AppendPrefix(_prefix, cmd)); | ||||
| command.MinPermissions = _defaultMinPermissions; | command.MinPermissions = _defaultMinPermissions; | ||||
| return new CommandBuilder(_plugin, command, _prefix); | |||||
| return new CommandBuilder(_service, command, _prefix); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -0,0 +1,8 @@ | |||||
| namespace Discord.Commands | |||||
| { | |||||
| public static class CommandExtensions | |||||
| { | |||||
| public static CommandService Commands(this DiscordClient client) | |||||
| => client.GetService<CommandService>(); | |||||
| } | |||||
| } | |||||
| @@ -36,7 +36,7 @@ namespace Discord.Commands | |||||
| } | } | ||||
| } | } | ||||
| public partial class CommandsPlugin | |||||
| public partial class CommandService | |||||
| { | { | ||||
| public event EventHandler<CommandEventArgs> RanCommand; | public event EventHandler<CommandEventArgs> RanCommand; | ||||
| private void RaiseRanCommand(CommandEventArgs args) | private void RaiseRanCommand(CommandEventArgs args) | ||||
| @@ -0,0 +1,184 @@ | |||||
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.Linq; | |||||
| using System.Text; | |||||
| using System.Threading.Tasks; | |||||
| namespace Discord.Commands | |||||
| { | |||||
| /// <summary> A Discord.Net client with extensions for handling common bot operations like text commands. </summary> | |||||
| public partial class CommandService : IService | |||||
| { | |||||
| private DiscordClient _client; | |||||
| CommandServiceConfig Config { get; } | |||||
| public IEnumerable<Command> Commands => _commands; | |||||
| private readonly List<Command> _commands; | |||||
| internal CommandMap Map => _map; | |||||
| private readonly CommandMap _map; | |||||
| public CommandService(CommandServiceConfig config) | |||||
| { | |||||
| Config = config; | |||||
| _commands = new List<Command>(); | |||||
| _map = new CommandMap(null); | |||||
| } | |||||
| void IService.Install(DiscordClient client) | |||||
| { | |||||
| _client = client; | |||||
| Config.Lock(); | |||||
| if (Config.HelpMode != HelpMode.Disable) | |||||
| { | |||||
| CreateCommand("help") | |||||
| .Parameter("command", ParameterType.Multiple) | |||||
| .Hide() | |||||
| .Info("Returns information about commands.") | |||||
| .Do(async e => | |||||
| { | |||||
| Channel channel = Config.HelpMode == HelpMode.Public ? e.Channel : await client.CreatePMChannel(e.User); | |||||
| if (e.Args.Length > 0) //Show command help | |||||
| { | |||||
| var cmd = _map.GetCommand(string.Join(" ", e.Args)); | |||||
| if (cmd != null) | |||||
| await ShowHelp(cmd, e.User, channel); | |||||
| else | |||||
| await client.SendMessage(channel, "Unable to display help: unknown command."); | |||||
| } | |||||
| else //Show general help | |||||
| await ShowHelp(e.User, channel); | |||||
| }); | |||||
| } | |||||
| client.MessageReceived += async (s, e) => | |||||
| { | |||||
| if (_commands.Count == 0) return; | |||||
| if (e.Message.IsAuthor) return; | |||||
| string msg = e.Message.Text; | |||||
| if (msg.Length == 0) return; | |||||
| //Check for command char if one is provided | |||||
| var chars = Config.CommandChars; | |||||
| if (chars.Length > 0) | |||||
| { | |||||
| if (!chars.Contains(msg[0])) | |||||
| return; | |||||
| msg = msg.Substring(1); | |||||
| } | |||||
| //Parse command | |||||
| Command command; | |||||
| int argPos; | |||||
| CommandParser.ParseCommand(msg, _map, out command, out argPos); | |||||
| if (command == null) | |||||
| { | |||||
| CommandEventArgs errorArgs = new CommandEventArgs(e.Message, null, null, null); | |||||
| RaiseCommandError(CommandErrorType.UnknownCommand, errorArgs); | |||||
| return; | |||||
| } | |||||
| else | |||||
| { | |||||
| int userPermissions = Config.PermissionResolver?.Invoke(e.Message.User) ?? 0; | |||||
| //Parse arguments | |||||
| string[] args; | |||||
| var error = CommandParser.ParseArgs(msg, argPos, command, out args); | |||||
| if (error != null) | |||||
| { | |||||
| var errorArgs = new CommandEventArgs(e.Message, command, userPermissions, null); | |||||
| RaiseCommandError(error.Value, errorArgs); | |||||
| return; | |||||
| } | |||||
| var eventArgs = new CommandEventArgs(e.Message, command, userPermissions, args); | |||||
| // Check permissions | |||||
| if (userPermissions < command.MinPermissions) | |||||
| { | |||||
| RaiseCommandError(CommandErrorType.BadPermissions, eventArgs); | |||||
| return; | |||||
| } | |||||
| // Run the command | |||||
| try | |||||
| { | |||||
| RaiseRanCommand(eventArgs); | |||||
| await command.Run(eventArgs).ConfigureAwait(false); | |||||
| } | |||||
| catch (Exception ex) | |||||
| { | |||||
| RaiseCommandError(CommandErrorType.Exception, eventArgs, ex); | |||||
| } | |||||
| } | |||||
| }; | |||||
| } | |||||
| public Task ShowHelp(User user, Channel channel) | |||||
| { | |||||
| int permissions = Config.PermissionResolver(user); | |||||
| StringBuilder output = new StringBuilder(); | |||||
| output.AppendLine("These are the commands you can use:"); | |||||
| output.Append(string.Join(", ", _commands | |||||
| .Where(x => permissions >= x.MinPermissions && !x.IsHidden) | |||||
| .Select(x => '`' + x.Text + '`'))); | |||||
| var chars = Config.CommandChars; | |||||
| if (chars.Length > 0) | |||||
| { | |||||
| if (chars.Length == 1) | |||||
| output.AppendLine($"\nYou can use `{chars[0]}` to call a command."); | |||||
| else | |||||
| output.AppendLine($"\nYou can use `{string.Join(" ", chars.Take(chars.Length - 1))}` or `{chars.Last()}` to call a command."); | |||||
| } | |||||
| output.AppendLine("`help <command>` can tell you more about how to use a command."); | |||||
| return _client.SendMessage(channel, output.ToString()); | |||||
| } | |||||
| public Task ShowHelp(Command command, User user, Channel channel) | |||||
| { | |||||
| StringBuilder output = new StringBuilder(); | |||||
| output.Append($"`{command.Text}`"); | |||||
| if (command.MinArgs != null && command.MaxArgs != null) | |||||
| { | |||||
| if (command.MinArgs == command.MaxArgs) | |||||
| { | |||||
| if (command.MaxArgs != 0) | |||||
| output.Append($" {command.MinArgs.ToString()} Args"); | |||||
| } | |||||
| else | |||||
| output.Append($" {command.MinArgs.ToString()} - {command.MaxArgs.ToString()} Args"); | |||||
| } | |||||
| else if (command.MinArgs != null && command.MaxArgs == null) | |||||
| output.Append($" ≥{command.MinArgs.ToString()} Args"); | |||||
| else if (command.MinArgs == null && command.MaxArgs != null) | |||||
| output.Append($" ≤{command.MaxArgs.ToString()} Args"); | |||||
| output.Append($": {command.Description ?? "No description set for this command."}"); | |||||
| return _client.SendMessage(channel, output.ToString()); | |||||
| } | |||||
| public void CreateCommandGroup(string cmd, Action<CommandGroupBuilder> config = null) | |||||
| => config(new CommandGroupBuilder(this, cmd, 0)); | |||||
| public CommandBuilder CreateCommand(string cmd) | |||||
| { | |||||
| var command = new Command(cmd); | |||||
| _commands.Add(command); | |||||
| return new CommandBuilder(this, command, ""); | |||||
| } | |||||
| internal void AddCommand(Command command) | |||||
| { | |||||
| _commands.Add(command); | |||||
| _map.AddCommand(command.Text, command); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,49 @@ | |||||
| using System; | |||||
| namespace Discord.Commands | |||||
| { | |||||
| public enum HelpMode | |||||
| { | |||||
| /// <summary> Disable the automatic help command. </summary> | |||||
| Disable, | |||||
| /// <summary> Use the automatic help command and respond in the channel the command is used. </summary> | |||||
| Public, | |||||
| /// <summary> Use the automatic help command and respond in a private message. </summary> | |||||
| Private | |||||
| } | |||||
| public class CommandServiceConfig | |||||
| { | |||||
| public Func<User, int> PermissionResolver { get { return _permissionsResolver; } set { SetValue(ref _permissionsResolver, value); } } | |||||
| private Func<User, int> _permissionsResolver; | |||||
| public char? CommandChar | |||||
| { | |||||
| get | |||||
| { | |||||
| return _commandChars.Length > 0 ? _commandChars[0] : (char?)null; | |||||
| } | |||||
| set | |||||
| { | |||||
| if (value != null) | |||||
| CommandChars = new char[] { value.Value }; | |||||
| else | |||||
| CommandChars = new char[0]; | |||||
| } | |||||
| } | |||||
| public char[] CommandChars { get { return _commandChars; } set { SetValue(ref _commandChars, value); } } | |||||
| private char[] _commandChars = new char[] { '!' }; | |||||
| public HelpMode HelpMode { get { return _helpMode; } set { SetValue(ref _helpMode, value); } } | |||||
| private HelpMode _helpMode = HelpMode.Disable; | |||||
| //Lock | |||||
| protected bool _isLocked; | |||||
| internal void Lock() { _isLocked = true; } | |||||
| protected void SetValue<T>(ref T storage, T value) | |||||
| { | |||||
| if (_isLocked) | |||||
| throw new InvalidOperationException("Unable to modify a discord client's configuration after it has been created."); | |||||
| storage = value; | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,211 +0,0 @@ | |||||
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.Linq; | |||||
| using System.Text; | |||||
| using System.Threading.Tasks; | |||||
| namespace Discord.Commands | |||||
| { | |||||
| /// <summary> A Discord.Net client with extensions for handling common bot operations like text commands. </summary> | |||||
| public partial class CommandsPlugin | |||||
| { | |||||
| private readonly DiscordClient _client; | |||||
| private readonly Func<User, int> _getPermissions; | |||||
| public IEnumerable<Command> Commands => _commands; | |||||
| private readonly List<Command> _commands; | |||||
| internal CommandMap Map => _map; | |||||
| private readonly CommandMap _map; | |||||
| public char? ComamndChar | |||||
| { | |||||
| get { return _commandChars.Length > 0 ? _commandChars[0] : (char?)null; } | |||||
| set { _commandChars = value != null ? new char[] { value.Value } : new char[0]; } | |||||
| } | |||||
| public IEnumerable<char> CommandChars { get { return _commandChars; } set { _commandChars = value.ToArray(); } } | |||||
| private char[] _commandChars; | |||||
| public bool RequireCommandCharInPublic { get; set; } | |||||
| public bool RequireCommandCharInPrivate { get; set; } | |||||
| public bool HelpInPublic { get; set; } | |||||
| public CommandsPlugin(DiscordClient client, Func<User, int> getPermissions = null, bool builtInHelp = false) | |||||
| { | |||||
| _client = client; | |||||
| _getPermissions = getPermissions; | |||||
| _commands = new List<Command>(); | |||||
| _map = new CommandMap(null); | |||||
| _commandChars = new char[] { '!' }; | |||||
| RequireCommandCharInPublic = true; | |||||
| RequireCommandCharInPrivate = true; | |||||
| HelpInPublic = true; | |||||
| if (builtInHelp) | |||||
| { | |||||
| CreateCommand("help") | |||||
| .Parameter("command", ParameterType.Optional) | |||||
| .Hide() | |||||
| .Info("Returns information about commands.") | |||||
| .Do(async e => | |||||
| { | |||||
| if (e.Command.Text != "help") | |||||
| await Reply(e, CommandDetails(e.Command)); | |||||
| else | |||||
| { | |||||
| if (e.Args == null) | |||||
| { | |||||
| int permissions = getPermissions(e.User); | |||||
| StringBuilder output = new StringBuilder(); | |||||
| output.AppendLine("These are the commands you can use:"); | |||||
| output.Append("`"); | |||||
| output.Append(string.Join(", ", _commands.Select(x => permissions >= x.MinPermissions && !x.IsHidden))); | |||||
| output.Append("`"); | |||||
| if (_commandChars.Length > 0) | |||||
| { | |||||
| if (_commandChars.Length == 1) | |||||
| output.AppendLine($"\nYou can use `{_commandChars[0]}` to call a command."); | |||||
| else | |||||
| output.AppendLine($"\nYou can use `{string.Join(" ", CommandChars.Take(_commandChars.Length - 1))}` and `{_commandChars.Last()}` to call a command."); | |||||
| } | |||||
| output.AppendLine("`help <command>` can tell you more about how to use a command."); | |||||
| await Reply(e, output.ToString()); | |||||
| } | |||||
| else | |||||
| { | |||||
| var cmd = _map.GetCommand(e.Args[0]); | |||||
| if (cmd != null) | |||||
| await Reply(e, CommandDetails(cmd)); | |||||
| else | |||||
| await Reply(e, $"`{e.Args[0]}` is not a valid command."); | |||||
| } | |||||
| } | |||||
| }); | |||||
| } | |||||
| client.MessageReceived += async (s, e) => | |||||
| { | |||||
| if (_commands.Count == 0) return; | |||||
| if (e.Message.IsAuthor) return; | |||||
| string msg = e.Message.Text; | |||||
| if (msg.Length == 0) return; | |||||
| //Check for command char if one is provided | |||||
| if (_commandChars.Length > 0) | |||||
| { | |||||
| bool isPrivate = e.Message.Channel.IsPrivate; | |||||
| bool hasCommandChar = _commandChars.Contains(msg[0]); | |||||
| if (hasCommandChar) | |||||
| msg = msg.Substring(1); | |||||
| if (isPrivate && RequireCommandCharInPrivate && !hasCommandChar) | |||||
| return; // If private, and command char is required, and it doesn't have it, ignore it. | |||||
| if (!isPrivate && RequireCommandCharInPublic && !hasCommandChar) | |||||
| return; // Same, but public. | |||||
| } | |||||
| //Parse command | |||||
| Command command; | |||||
| int argPos; | |||||
| CommandParser.ParseCommand(msg, _map, out command, out argPos); | |||||
| if (command == null) | |||||
| { | |||||
| CommandEventArgs errorArgs = new CommandEventArgs(e.Message, null, null, null); | |||||
| RaiseCommandError(CommandErrorType.UnknownCommand, errorArgs); | |||||
| return; | |||||
| } | |||||
| else | |||||
| { | |||||
| int userPermissions = _getPermissions != null ? _getPermissions(e.Message.User) : 0; | |||||
| //Parse arguments | |||||
| string[] args; | |||||
| var error = CommandParser.ParseArgs(msg, argPos, command, out args); | |||||
| if (error != null) | |||||
| { | |||||
| var errorArgs = new CommandEventArgs(e.Message, command, userPermissions, null); | |||||
| RaiseCommandError(error.Value, errorArgs); | |||||
| return; | |||||
| } | |||||
| var eventArgs = new CommandEventArgs(e.Message, command, userPermissions, args); | |||||
| // Check permissions | |||||
| if (userPermissions < command.MinPermissions) | |||||
| { | |||||
| RaiseCommandError(CommandErrorType.BadPermissions, eventArgs); | |||||
| return; | |||||
| } | |||||
| // Run the command | |||||
| try | |||||
| { | |||||
| RaiseRanCommand(eventArgs); | |||||
| await command.Run(eventArgs).ConfigureAwait(false); | |||||
| } | |||||
| catch (Exception ex) | |||||
| { | |||||
| RaiseCommandError(CommandErrorType.Exception, eventArgs, ex); | |||||
| } | |||||
| } | |||||
| }; | |||||
| } | |||||
| private string CommandDetails(Command command) | |||||
| { | |||||
| StringBuilder output = new StringBuilder(); | |||||
| output.Append($"`{command.Text}`"); | |||||
| if (command.MinArgs != null && command.MaxArgs != null) | |||||
| { | |||||
| if (command.MinArgs == command.MaxArgs) | |||||
| { | |||||
| if (command.MaxArgs != 0) | |||||
| output.Append($" {command.MinArgs.ToString()} Args"); | |||||
| } | |||||
| else | |||||
| output.Append($" {command.MinArgs.ToString()} - {command.MaxArgs.ToString()} Args"); | |||||
| } | |||||
| else if (command.MinArgs != null && command.MaxArgs == null) | |||||
| output.Append($" ≥{command.MinArgs.ToString()} Args"); | |||||
| else if (command.MinArgs == null && command.MaxArgs != null) | |||||
| output.Append($" ≤{command.MaxArgs.ToString()} Args"); | |||||
| output.Append($": {command.Description ?? "No description set for this command."}"); | |||||
| return output.ToString(); | |||||
| } | |||||
| internal async Task Reply(CommandEventArgs e, string message) | |||||
| { | |||||
| if (HelpInPublic) | |||||
| await _client.SendMessage(e.Channel, message); | |||||
| else | |||||
| await _client.SendPrivateMessage(e.User, message); | |||||
| } | |||||
| public void CreateCommandGroup(string cmd, Action<CommandGroupBuilder> config = null) | |||||
| => config(new CommandGroupBuilder(this, cmd, 0)); | |||||
| public CommandBuilder CreateCommand(string cmd) | |||||
| { | |||||
| var command = new Command(cmd); | |||||
| _commands.Add(command); | |||||
| return new CommandBuilder(null, command, ""); | |||||
| } | |||||
| internal void AddCommand(Command command) | |||||
| { | |||||
| _commands.Add(command); | |||||
| _map.AddCommand(command.Text, command); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -232,6 +232,9 @@ | |||||
| <Compile Include="..\Discord.Net\HttpException.cs"> | <Compile Include="..\Discord.Net\HttpException.cs"> | ||||
| <Link>HttpException.cs</Link> | <Link>HttpException.cs</Link> | ||||
| </Compile> | </Compile> | ||||
| <Compile Include="..\Discord.Net\IService.cs"> | |||||
| <Link>IService.cs</Link> | |||||
| </Compile> | |||||
| <Compile Include="..\Discord.Net\Models\Channel.cs"> | <Compile Include="..\Discord.Net\Models\Channel.cs"> | ||||
| <Link>Models\Channel.cs</Link> | <Link>Models\Channel.cs</Link> | ||||
| </Compile> | </Compile> | ||||
| @@ -17,6 +17,7 @@ namespace Discord | |||||
| private readonly JsonSerializer _serializer; | private readonly JsonSerializer _serializer; | ||||
| private readonly ConcurrentQueue<Message> _pendingMessages; | private readonly ConcurrentQueue<Message> _pendingMessages; | ||||
| private readonly ConcurrentDictionary<string, DiscordWSClient> _voiceClients; | private readonly ConcurrentDictionary<string, DiscordWSClient> _voiceClients; | ||||
| private readonly Dictionary<Type, IService> _services; | |||||
| private bool _sentInitialLog; | private bool _sentInitialLog; | ||||
| private uint _nextVoiceClientId; | private uint _nextVoiceClientId; | ||||
| private UserStatus _status; | private UserStatus _status; | ||||
| @@ -46,6 +47,7 @@ namespace Discord | |||||
| _roles = new Roles(this, cacheLock); | _roles = new Roles(this, cacheLock); | ||||
| _servers = new Servers(this, cacheLock); | _servers = new Servers(this, cacheLock); | ||||
| _globalUsers = new GlobalUsers(this, cacheLock); | _globalUsers = new GlobalUsers(this, cacheLock); | ||||
| _services = new Dictionary<Type, IService>(); | |||||
| _status = UserStatus.Online; | _status = UserStatus.Online; | ||||
| @@ -168,7 +170,6 @@ namespace Discord | |||||
| _serializer.MissingMemberHandling = MissingMemberHandling.Error; | _serializer.MissingMemberHandling = MissingMemberHandling.Error; | ||||
| #endif | #endif | ||||
| } | } | ||||
| internal override VoiceWebSocket CreateVoiceSocket() | internal override VoiceWebSocket CreateVoiceSocket() | ||||
| { | { | ||||
| var socket = base.CreateVoiceSocket(); | var socket = base.CreateVoiceSocket(); | ||||
| @@ -216,7 +217,6 @@ namespace Discord | |||||
| await Connect(token).ConfigureAwait(false); | await Connect(token).ConfigureAwait(false); | ||||
| return token; | return token; | ||||
| } | } | ||||
| /// <summary> Connects to the Discord server with the provided token. </summary> | /// <summary> Connects to the Discord server with the provided token. </summary> | ||||
| public async Task Connect(string token) | public async Task Connect(string token) | ||||
| { | { | ||||
| @@ -273,6 +273,22 @@ namespace Discord | |||||
| _currentUser = null; | _currentUser = null; | ||||
| } | } | ||||
| public void AddService<T>(T obj) | |||||
| where T : class, IService | |||||
| { | |||||
| _services.Add(typeof(T), obj); | |||||
| obj.Install(this); | |||||
| } | |||||
| public T GetService<T>() | |||||
| where T : class, IService | |||||
| { | |||||
| IService service; | |||||
| if (_services.TryGetValue(typeof(T), out service)) | |||||
| return service as T; | |||||
| else | |||||
| return null; | |||||
| } | |||||
| protected override IEnumerable<Task> GetTasks() | protected override IEnumerable<Task> GetTasks() | ||||
| { | { | ||||
| if (Config.UseMessageQueue) | if (Config.UseMessageQueue) | ||||
| @@ -0,0 +1,7 @@ | |||||
| namespace Discord | |||||
| { | |||||
| public interface IService | |||||
| { | |||||
| void Install(DiscordClient client); | |||||
| } | |||||
| } | |||||