| @@ -50,7 +50,7 @@ public class Program | |||||
| // rather an object stating if the command executed succesfully) | // rather an object stating if the command executed succesfully) | ||||
| var result = await commands.ExecuteAsync(context, argPos, map); | var result = await commands.ExecuteAsync(context, argPos, map); | ||||
| if (!result.IsSuccess) | if (!result.IsSuccess) | ||||
| await msg.Channel.SendMessageAsync(result.ErrorReason); | |||||
| await context.Channel.SendMessageAsync(result.ErrorReason); | |||||
| } | } | ||||
| } | |||||
| } | |||||
| @@ -11,7 +11,7 @@ public class Commands | |||||
| var map = new DependencyMap(); | var map = new DependencyMap(); | ||||
| map.Add(client); | map.Add(client); | ||||
| map.Add(commands); | map.Add(commands); | ||||
| await commands.LoadAssembly(Assembly.GetCurrentAssembly(), map); | |||||
| await commands.AddModulesAsync(Assembly.GetEntryAssembly()); | |||||
| } | } | ||||
| // In ConfigureServices, we will inject the Dependency Map with | // In ConfigureServices, we will inject the Dependency Map with | ||||
| // all of the services our client will use. | // all of the services our client will use. | ||||
| @@ -21,4 +21,4 @@ public class Commands | |||||
| map.Add(new DatabaseService(map)); | map.Add(new DatabaseService(map)); | ||||
| } | } | ||||
| // ... | // ... | ||||
| } | |||||
| } | |||||
| @@ -4,7 +4,7 @@ | |||||
| public class RequireOwnerAttribute : PreconditionAttribute | public class RequireOwnerAttribute : PreconditionAttribute | ||||
| { | { | ||||
| // Override the CheckPermissions method | // Override the CheckPermissions method | ||||
| public override Task<PreconditionResult> CheckPermissions(CommandContext context, CommandInfo command, IDependencyMap map) | |||||
| public async override Task<PreconditionResult> CheckPermissions(CommandContext context, CommandInfo command, IDependencyMap map) | |||||
| { | { | ||||
| // Get the ID of the bot's owner | // Get the ID of the bot's owner | ||||
| var ownerId = (await map.Get<DiscordSocketClient>().GetApplicationInfoAsync()).Owner.Id; | var ownerId = (await map.Get<DiscordSocketClient>().GetApplicationInfoAsync()).Owner.Id; | ||||
| @@ -15,4 +15,4 @@ public class RequireOwnerAttribute : PreconditionAttribute | |||||
| else | else | ||||
| return PreconditionResult.FromError("You must be the owner of the bot to run this command."); | return PreconditionResult.FromError("You must be the owner of the bot to run this command."); | ||||
| } | } | ||||
| } | |||||
| } | |||||
| @@ -214,9 +214,9 @@ namespace Discord.Commands | |||||
| public SearchResult Search(CommandContext context, int argPos) => Search(context, context.Message.Content.Substring(argPos)); | public SearchResult Search(CommandContext context, int argPos) => Search(context, context.Message.Content.Substring(argPos)); | ||||
| public SearchResult Search(CommandContext context, string input) | public SearchResult Search(CommandContext context, string input) | ||||
| { | { | ||||
| input = _caseSensitive ? input : input.ToLowerInvariant(); | |||||
| var matches = _map.GetCommands(input).OrderByDescending(x => x.Priority).ToImmutableArray(); | |||||
| string searchInput = _caseSensitive ? input : input.ToLowerInvariant(); | |||||
| var matches = _map.GetCommands(searchInput).OrderByDescending(x => x.Priority).ToImmutableArray(); | |||||
| if (matches.Length > 0) | if (matches.Length > 0) | ||||
| return SearchResult.FromSuccess(input, matches); | return SearchResult.FromSuccess(input, matches); | ||||
| else | else | ||||
| @@ -70,21 +70,17 @@ namespace Discord.Rpc | |||||
| => new API.DiscordRpcApiClient(clientId, DiscordRestConfig.UserAgent, origin, config.RestClientProvider, config.WebSocketProvider, requestQueue: new RequestQueue()); | => new API.DiscordRpcApiClient(clientId, DiscordRestConfig.UserAgent, origin, config.RestClientProvider, config.WebSocketProvider, requestQueue: new RequestQueue()); | ||||
| /// <inheritdoc /> | /// <inheritdoc /> | ||||
| public Task ConnectAsync() => ConnectAsync(false); | |||||
| internal async Task ConnectAsync(bool ignoreLoginCheck) | |||||
| public async Task ConnectAsync() | |||||
| { | { | ||||
| await _connectionLock.WaitAsync().ConfigureAwait(false); | await _connectionLock.WaitAsync().ConfigureAwait(false); | ||||
| try | try | ||||
| { | { | ||||
| await ConnectInternalAsync(ignoreLoginCheck, false).ConfigureAwait(false); | |||||
| await ConnectInternalAsync(false).ConfigureAwait(false); | |||||
| } | } | ||||
| finally { _connectionLock.Release(); } | finally { _connectionLock.Release(); } | ||||
| } | } | ||||
| private async Task ConnectInternalAsync(bool ignoreLoginCheck, bool isReconnecting) | |||||
| { | |||||
| if (!ignoreLoginCheck && LoginState != LoginState.LoggedIn) | |||||
| throw new InvalidOperationException("You must log in before connecting."); | |||||
| private async Task ConnectInternalAsync(bool isReconnecting) | |||||
| { | |||||
| if (!isReconnecting && _reconnectCancelToken != null && !_reconnectCancelToken.IsCancellationRequested) | if (!isReconnecting && _reconnectCancelToken != null && !_reconnectCancelToken.IsCancellationRequested) | ||||
| _reconnectCancelToken.Cancel(); | _reconnectCancelToken.Cancel(); | ||||
| @@ -198,7 +194,7 @@ namespace Discord.Rpc | |||||
| try | try | ||||
| { | { | ||||
| if (cancelToken.IsCancellationRequested) return; | if (cancelToken.IsCancellationRequested) return; | ||||
| await ConnectInternalAsync(false, true).ConfigureAwait(false); | |||||
| await ConnectInternalAsync(true).ConfigureAwait(false); | |||||
| _reconnectTask = null; | _reconnectTask = null; | ||||
| return; | return; | ||||
| } | } | ||||
| @@ -223,7 +219,7 @@ namespace Discord.Rpc | |||||
| public async Task<string> AuthorizeAsync(string[] scopes, string rpcToken = null, RequestOptions options = null) | public async Task<string> AuthorizeAsync(string[] scopes, string rpcToken = null, RequestOptions options = null) | ||||
| { | { | ||||
| await ConnectAsync(true).ConfigureAwait(false); | |||||
| await ConnectAsync().ConfigureAwait(false); | |||||
| var result = await ApiClient.SendAuthorizeAsync(scopes, rpcToken, options).ConfigureAwait(false); | var result = await ApiClient.SendAuthorizeAsync(scopes, rpcToken, options).ConfigureAwait(false); | ||||
| await DisconnectAsync().ConfigureAwait(false); | await DisconnectAsync().ConfigureAwait(false); | ||||
| return result.Code; | return result.Code; | ||||
| @@ -57,6 +57,7 @@ namespace Discord.WebSocket | |||||
| internal ClientState State { get; private set; } | internal ClientState State { get; private set; } | ||||
| internal int ConnectionTimeout { get; private set; } | internal int ConnectionTimeout { get; private set; } | ||||
| internal WebSocketProvider WebSocketProvider { get; private set; } | internal WebSocketProvider WebSocketProvider { get; private set; } | ||||
| internal bool DownloadUsersOnGuildAvailable { get; private set; } | |||||
| public new DiscordSocketApiClient ApiClient => base.ApiClient as DiscordSocketApiClient; | public new DiscordSocketApiClient ApiClient => base.ApiClient as DiscordSocketApiClient; | ||||
| public new SocketSelfUser CurrentUser { get { return base.CurrentUser as SocketSelfUser; } private set { base.CurrentUser = value; } } | public new SocketSelfUser CurrentUser { get { return base.CurrentUser as SocketSelfUser; } private set { base.CurrentUser = value; } } | ||||
| @@ -76,6 +77,7 @@ namespace Discord.WebSocket | |||||
| LargeThreshold = config.LargeThreshold; | LargeThreshold = config.LargeThreshold; | ||||
| AudioMode = config.AudioMode; | AudioMode = config.AudioMode; | ||||
| WebSocketProvider = config.WebSocketProvider; | WebSocketProvider = config.WebSocketProvider; | ||||
| DownloadUsersOnGuildAvailable = config.DownloadUsersOnGuildAvailable; | |||||
| ConnectionTimeout = config.ConnectionTimeout; | ConnectionTimeout = config.ConnectionTimeout; | ||||
| State = new ClientState(0, 0); | State = new ClientState(0, 0); | ||||
| @@ -108,6 +110,15 @@ namespace Discord.WebSocket | |||||
| GuildUnavailable += async g => await _gatewayLogger.VerboseAsync($"Disconnected from {g.Name}").ConfigureAwait(false); | GuildUnavailable += async g => await _gatewayLogger.VerboseAsync($"Disconnected from {g.Name}").ConfigureAwait(false); | ||||
| LatencyUpdated += async (old, val) => await _gatewayLogger.VerboseAsync($"Latency = {val} ms").ConfigureAwait(false); | LatencyUpdated += async (old, val) => await _gatewayLogger.VerboseAsync($"Latency = {val} ms").ConfigureAwait(false); | ||||
| if (DownloadUsersOnGuildAvailable) | |||||
| { | |||||
| GuildAvailable += g => | |||||
| { | |||||
| var _ = g.DownloadUsersAsync(); | |||||
| return Task.CompletedTask; | |||||
| }; | |||||
| } | |||||
| _voiceRegions = ImmutableDictionary.Create<string, RestVoiceRegion>(); | _voiceRegions = ImmutableDictionary.Create<string, RestVoiceRegion>(); | ||||
| _largeGuilds = new ConcurrentQueue<ulong>(); | _largeGuilds = new ConcurrentQueue<ulong>(); | ||||
| } | } | ||||
| @@ -1663,7 +1674,7 @@ namespace Discord.WebSocket | |||||
| { | { | ||||
| if (_heartbeatTime != 0) //Server never responded to our last heartbeat | if (_heartbeatTime != 0) //Server never responded to our last heartbeat | ||||
| { | { | ||||
| if (ConnectionState == ConnectionState.Connected && (_guildDownloadTask?.IsCompleted ?? false)) | |||||
| if (ConnectionState == ConnectionState.Connected && (_guildDownloadTask?.IsCompleted ?? true)) | |||||
| { | { | ||||
| await _gatewayLogger.WarningAsync("Server missed last heartbeat").ConfigureAwait(false); | await _gatewayLogger.WarningAsync("Server missed last heartbeat").ConfigureAwait(false); | ||||
| await StartReconnectAsync(new Exception("Server missed last heartbeat")).ConfigureAwait(false); | await StartReconnectAsync(new Exception("Server missed last heartbeat")).ConfigureAwait(false); | ||||
| @@ -28,5 +28,8 @@ namespace Discord.WebSocket | |||||
| /// <summary> Gets or sets the provider used to generate new websocket connections. </summary> | /// <summary> Gets or sets the provider used to generate new websocket connections. </summary> | ||||
| public WebSocketProvider WebSocketProvider { get; set; } = () => new DefaultWebSocketClient(); | public WebSocketProvider WebSocketProvider { get; set; } = () => new DefaultWebSocketClient(); | ||||
| /// <summary> Gets or sets whether or not all users should be downloaded as guilds come available. </summary> | |||||
| public bool DownloadUsersOnGuildAvailable { get; set; } = false; | |||||
| } | } | ||||
| } | } | ||||