protected override async Task UpdateMessageAsync(IDiscordContext context, Optional <string> message, Optional <Embed> embed, CancellationToken cancellationToken = default) { var currentTime = DateTime.Now; var timeToWait = _lastUpdateTime + TimeSpan.FromSeconds(1) - currentTime; // if updating too quickly if (timeToWait.Ticks > 0) { lock (_pendingStates) { // queue current state to update in the background _pendingStates.Enqueue(new InteractiveViewState(context, message, embed)); // ReSharper disable once RedundantArgumentDefaultValue // we are the first in queue, so start the background updater if (_pendingStates.Count == 1) { _ = Task.Run(() => UpdateStateAsync(timeToWait, default), cancellationToken); } } } // otherwise update immediately else { await base.UpdateMessageAsync(context, message, embed, cancellationToken); } _lastUpdateTime = currentTime; }
public InteractiveViewState(IDiscordContext context, Optional <string> message, Optional <Embed> embed) { Context = context; Message = message; Embed = embed; }
public FeedModule(IOptions <AppSettings> options, IDiscordContext context, IDatabase db) { _settings = options.Value; _context = context; _db = db; }
public OptionModule(IDiscordContext context, IDatabase db, GuildSettingsCache settingsCache, InteractiveManager interactive) { _context = context; _db = db; _settingsCache = settingsCache; _interactive = interactive; }
public async Task ReportAsync(Exception e, IDiscordContext context, bool friendlyReply = true, CancellationToken cancellationToken = default) { try { // handle permission exceptions differently if (e is HttpException httpException && httpException.DiscordCode == 50013) // 500013 missing perms { await ReportMissingPermissionAsync(context, cancellationToken); return; } // send error message to the current channel if (friendlyReply) { await _interactiveManager.SendInteractiveAsync( new ErrorMessage(e), context, cancellationToken); } // send detailed error message to the guild error channel var errorChannel = _discord.GetGuild(_settings.Discord.Guild.GuildId) ?.GetTextChannel(_settings.Discord.Guild.ErrorChannelId); if (errorChannel != null && !_environment.IsDevelopment()) { await _interactiveManager.SendInteractiveAsync( new ErrorMessage(e, true), new DiscordContextWrapper(context) { Channel = errorChannel }, cancellationToken); } // send to logger if no error channel or we are debugging else { _logger.LogWarning(e, "Exception while handling message {0}.", context.Message?.Id); } } catch (Exception reportingException) { // ignore reporting errors _logger.LogWarning(reportingException, "Failed to report exception: {0}", e); } }
static async Task ReportMissingPermissionAsync(IDiscordContext context, CancellationToken cancellationToken = default) { try { // tell the user in DM that we don't have perms await context.ReplyDmAsync("errorMessage.missingPerms"); } catch { // the user has DM disabled // we can only hope they figure out the permissions by themselves } }
public async Task SendInteractiveAsync(IEmbedMessage message, IDiscordContext context, CancellationToken cancellationToken = default, bool forceStateful = true) { // create dependency scope to initialize the interactive within using (var scope = _services.CreateScope()) { var services = new ServiceDictionary(scope.ServiceProvider) { { typeof(IDiscordContext), context } }; // initialize interactive if (!await message.UpdateViewAsync(services, cancellationToken)) { return; } } var id = message.Message.Id; if (message is IInteractiveMessage interactiveMessage) { if (forceStateful || interactiveMessage.Triggers.Values.Any(t => !t.CanRunStateless)) { InteractiveMessages[id] = interactiveMessage; } } // forget interactives in an hour _ = Task.Run(async() => { try { await Task.Delay(TimeSpan.FromHours(1), cancellationToken); } catch (TaskCanceledException) { } finally { InteractiveMessages.TryRemove(id, out _); } }, cancellationToken); }
public static async Task <bool> EnsureGuildAdminAsync(IDiscordContext context, CancellationToken cancellationToken = default) { if (!(context.User is IGuildUser user)) { await context.ReplyAsync("commandInvokeNotInGuild"); return(false); } if (!user.GuildPermissions.ManageGuild) { await context.ReplyAsync("notGuildAdmin"); return(false); } return(true); }
protected virtual async Task UpdateMessageAsync(IDiscordContext context, Optional <string> content, Optional <Embed> embed, CancellationToken cancellationToken = default) { if (Message == null) { Message = await context.Channel.SendMessageAsync(content.GetValueOrDefault(), false, embed.GetValueOrDefault()); } else { await Message.ModifyAsync(m => { m.Content = content; m.Embed = embed; }); } }
public DiscordContextWrapper(IDiscordContext context) { _context = context; }