Beispiel #1
0
        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;
        }
Beispiel #2
0
 public InteractiveViewState(IDiscordContext context,
                             Optional <string> message,
                             Optional <Embed> embed)
 {
     Context = context;
     Message = message;
     Embed   = embed;
 }
Beispiel #3
0
 public FeedModule(IOptions <AppSettings> options,
                   IDiscordContext context,
                   IDatabase db)
 {
     _settings = options.Value;
     _context  = context;
     _db       = db;
 }
Beispiel #4
0
 public OptionModule(IDiscordContext context,
                     IDatabase db,
                     GuildSettingsCache settingsCache,
                     InteractiveManager interactive)
 {
     _context       = context;
     _db            = db;
     _settingsCache = settingsCache;
     _interactive   = interactive;
 }
Beispiel #5
0
        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);
            }
        }
Beispiel #6
0
 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
     }
 }
Beispiel #7
0
        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);
        }
Beispiel #8
0
        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);
        }
Beispiel #9
0
 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;
         });
     }
 }
Beispiel #10
0
 public DiscordContextWrapper(IDiscordContext context)
 {
     _context = context;
 }