private async Task <ulong> ExecuteWebhookInner(DiscordChannel channel, DiscordWebhook webhook, string name, string avatarUrl, string content,
                                                       IReadOnlyList <DiscordAttachment> attachments, bool allowEveryone, bool hasRetried = false)
        {
            content = content.Truncate(2000);

            var dwb = new DiscordWebhookBuilder();

            dwb.WithUsername(FixClyde(name).Truncate(80));
            dwb.WithContent(content);
            dwb.AddMentions(content.ParseAllMentions(allowEveryone, channel.Guild));
            if (!string.IsNullOrWhiteSpace(avatarUrl))
            {
                dwb.WithAvatarUrl(avatarUrl);
            }

            var attachmentChunks = ChunkAttachmentsOrThrow(attachments, 8 * 1024 * 1024);

            if (attachmentChunks.Count > 0)
            {
                _logger.Information("Invoking webhook with {AttachmentCount} attachments totalling {AttachmentSize} MiB in {AttachmentChunks} chunks", attachments.Count, attachments.Select(a => a.FileSize).Sum() / 1024 / 1024, attachmentChunks.Count);
                await AddAttachmentsToBuilder(dwb, attachmentChunks[0]);
            }

            DiscordMessage response;

            using (_metrics.Measure.Timer.Time(BotMetrics.WebhookResponseTime)) {
                try
                {
                    response = await webhook.ExecuteAsync(dwb);
                }
                catch (JsonReaderException)
                {
                    // This happens sometimes when we hit a CloudFlare error (or similar) on Discord's end
                    // Nothing we can do about this - happens sometimes under server load, so just drop the message and give up
                    throw new WebhookExecutionErrorOnDiscordsEnd();
                }
                catch (NotFoundException e)
                {
                    var errorText = e.WebResponse?.Response;
                    if (errorText != null && errorText.Contains("10015") && !hasRetried)
                    {
                        // Error 10015 = "Unknown Webhook" - this likely means the webhook was deleted
                        // but is still in our cache. Invalidate, refresh, try again
                        _logger.Warning("Error invoking webhook {Webhook} in channel {Channel}", webhook.Id, webhook.ChannelId);

                        var newWebhook = await _webhookCache.InvalidateAndRefreshWebhook(channel, webhook);

                        return(await ExecuteWebhookInner(channel, newWebhook, name, avatarUrl, content, attachments, allowEveryone, hasRetried : true));
                    }

                    throw;
                }
            }

            // We don't care about whether the sending succeeds, and we don't want to *wait* for it, so we just fork it off
            var _ = TrySendRemainingAttachments(webhook, name, avatarUrl, attachmentChunks);

            return(response.Id);
        }
示例#2
0
        public async Task ExecuteAsync(DiscordRestClient rest, PartnerSenderArguments senderArguments)
        {
            if (senderArguments.DevelopmentStressTest)
            {
                await ExecuteStressTestMessage(rest);

                return;
            }

            bool vanity       = this.Match.VanityInvite is not null && this.Match.DonorRank >= DonorService.VANITY_LIMIT;
            bool attachEmbeds = this.Match.DonorRank >= DonorService.EMBED_LIMIT;

            DiscordWebhookBuilder?hook = new DiscordWebhookBuilder()
                                         .WithContent($"{this.Match.Message}\n\n" +
                                                      $"https://discord.gg/" +
                                                      $"{(vanity ? this.Match.VanityInvite : this.Match.Invite)}")
                                         .WithUsername($"{this.Match.GuildName} | Partner Bot");

            if (attachEmbeds)
            {
                if (this.Match.DonorRank >= DonorService.HIGHEST_RANK)
                {
                    hook.AddEmbeds(this.Match.MessageEmbeds);
                }
                else if (this.Match.MessageEmbeds.Count > 0)
                {
                    hook.AddEmbed(this.Match.MessageEmbeds[0]);
                }
            }

            hook.AddEmbed(new DiscordEmbedBuilder()
                          .WithColor(DiscordColor.Gray)
                          .WithTitle("Partner Bot Advertisment")
                          .WithDescription($"**ID:** {this.Match.GuildId}")
                          .WithFooter($"pb-advert{(this.Match.NSFW ? " | NSFW" : "")}",
                                      rest.CurrentApplication.GetAvatarUrl(ImageFormat.Png))
                          .WithImageUrl(this.Match.Banner));

            if (!string.IsNullOrWhiteSpace(this.Match.GuildIcon))
            {
                hook.WithAvatarUrl(this.Match.GuildIcon);
            }

            await rest.ExecuteWebhookAsync(this.WebhookId, this.WebhookToken, hook);

            if (this.ExtraMessage is not null)
            {
                var eDat = new PartnerData(this, this.ExtraMessage);

                await eDat.ExecuteAsync(rest, senderArguments);
            }
        }
示例#3
0
        public async Task SpoilCommand(CommandContext ctx, [Description("The message text"), RemainingText] string content)
        {
            var message = new DiscordWebhookBuilder();

            foreach (var attachment in ctx.Message.Attachments)
            {
                message.AddFile("SPOILER_" + attachment.FileName, GetStreamFromUrl(attachment.Url));
            }
            message.WithContent(content);
            message.WithAvatarUrl(ctx.Member.GetAvatarUrl(ImageFormat.Auto));
            message.WithUsername(ctx.Member.DisplayName);
            var webhook = (await ctx.Channel.GetWebhooksAsync()).FirstOrDefault();

            if (webhook == null)
            {
                webhook = await ctx.Channel.CreateWebhookAsync("SpoilHook");
            }
            await webhook.ExecuteAsync(message);
        }
        private async Task TrySendRemainingAttachments(DiscordWebhook webhook, string name, string avatarUrl, IReadOnlyList <IReadOnlyCollection <DiscordAttachment> > attachmentChunks)
        {
            if (attachmentChunks.Count <= 1)
            {
                return;
            }

            for (var i = 1; i < attachmentChunks.Count; i++)
            {
                var dwb = new DiscordWebhookBuilder();
                if (avatarUrl != null)
                {
                    dwb.WithAvatarUrl(avatarUrl);
                }
                dwb.WithUsername(name);
                await AddAttachmentsToBuilder(dwb, attachmentChunks[i]);

                await webhook.ExecuteAsync(dwb);
            }
        }