private async Task ExecuteStressTestMessage(DiscordRestClient rest) { DiscordWebhookBuilder?hook = new DiscordWebhookBuilder() .WithContent($"This Channel: <#{this.GuildId}>" + "\n```\n" + "STRESS TEST\n\n" + $"This Partner ({this.GuildName}):\n" + $"ID: {this.GuildId}\n" + $"Tags: {string.Join(", ", this.Tags)}\n" + $"Size: {this.UserCount}\n" + $"Donor Rank: {this.DonorRank}\n\n" + $"Other Partner ({this.Match.GuildName}):\n" + $"ID: {this.Match.GuildId}\n" + $"Tags: {string.Join(", ", this.Match.Tags)}\n" + $"Size: {this.Match.UserCount}\n" + $"Donor Rank: {this.Match.DonorRank}\n" + $"Extra: {this.ExtraMessage}" + $"\n```\n" + $"Other Channel: <#{this.Match.GuildId}>") .AddEmbed(new DiscordEmbedBuilder() .WithColor(DiscordColor.Gray) .WithTitle("Partner Bot Advertisment") .WithDescription($"**ID:** {this.Match.GuildId}") .WithImageUrl(this.Match.Banner) ); await rest.ExecuteWebhookAsync(this.WebhookId, this.WebhookToken, hook); }
// , // /| __ // / | ,-~ / // Y :| // / // | jj /( .^ // >-"~"-v" // / Y // jo o | // ( ~T~j // >._-' _./ // / "~" | // Y _, | // /| ;-"~ _ l /// l/ ,-"~ \ //\//\/ .- \ // Y / Y -Row // l I ! // ]\ _\ /"\ //(" ~----( ~ Y. ) #endregion bunny public async Task <DiscordMessage> SendWebhookMessage(string content = null, DiscordEmbed[] embeds = null, FileStream fileStream = null, string fileName = null) { var dwb = new DiscordWebhookBuilder(); if (!(embeds is null)) { if (embeds.Length > 10) { throw new ArgumentException("More than 10 embeds provided."); } dwb.AddEmbeds(embeds); } if (!(content is null)) { dwb.WithContent(content); } if (!(fileStream is null) && !(fileName is null)) { dwb.AddFile(Path.GetFileName(fileName), fileStream); } if (embeds is null && content is null && fileStream is null) { throw new ArgumentException("Cannot send an empty message."); } return(await webhook.ExecuteAsync(dwb)); }
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); }
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); } }
private async Task AddAttachmentsToBuilder(DiscordWebhookBuilder dwb, IReadOnlyCollection <DiscordAttachment> attachments) { async Task <(DiscordAttachment, Stream)> GetStream(DiscordAttachment attachment) { var attachmentResponse = await _client.GetAsync(attachment.Url, HttpCompletionOption.ResponseHeadersRead); return(attachment, await attachmentResponse.Content.ReadAsStreamAsync()); } foreach (var(attachment, attachmentStream) in await Task.WhenAll(attachments.Select(GetStream))) { dwb.AddFile(attachment.FileName, attachmentStream); } }
public override async Task <ulong?> CreateResponse() { var builder = new DiscordWebhookBuilder().WithContent(await GetContent()); if (MissCount > 1) { foreach (var row in GetMissComponents()) { builder.AddComponents(row); } } await ctx.EditResponseAsync(builder); return(ctx.InteractionId); }
private async Task <DiscordWebhookBuilder> GetInteractionEditAsync(Partner partner, bool isChanged = false, DiscordChannel?channel = null, string?errorMessage = null) { var builder = new DiscordWebhookBuilder() .AddEmbed(await GetRequiermentsEmbed(partner, channel)); foreach (var item in await GetComponents(partner, isChanged)) { builder.AddComponents(item); } if (errorMessage is not null) { builder.AddEmbed(ErrorBase().WithDescription(errorMessage)); } return(builder); }
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); }
#pragma warning disable 4014 new public static void OnStart(DiscordClient discord, IConfiguration configuration) { var context = new dataContext(); discord.MessageCreated += async(client, args) => { Task.Run(async() => { if (!args.Message.Content.StartsWith("\\") && // Not escaped context.Anonchannels.Any(c => c.Id == args.Channel.Id.ToString()) && // In an anon channel !args.Author.IsBot && // Not a bot !context.AnonBans.AsNoTracking().AsEnumerable().Any(u => u.User == args.Author.Id.ToString() && // AsNoTracking used to avoid cache u.Server == args.Guild.Id.ToString() && (u.ExpiresAt == (ulong)0 || u.ExpiresAt > (ulong)DateTimeOffset.Now.ToUnixTimeSeconds()))) // Not anonbanned { if (args.Message.Attachments.Count == 0) { try { await args.Message.DeleteAsync(); } catch { } } // TODO: Work around rate limit here var webhook = await args.Channel.CreateWebhookAsync("Anon"); var msg = new DiscordWebhookBuilder().WithContent(args.Message.Content.CleanPings(args.Guild)); foreach (var attachment in args.Message.Attachments) { var fileStream = WebRequest.Create(attachment.ProxyUrl).GetResponse().GetResponseStream(); msg.AddFile(attachment.FileName, fileStream); } var anonMessage = await webhook.ExecuteAsync(msg); await webhook.DeleteAsync(); try { await args.Message.DeleteAsync(); } catch { } await context.Anonmessages.AddAsync(new Anonmessage { Id = anonMessage.Id.ToString(), Server = anonMessage.Channel.GuildId.ToString(), User = args.Author.Id.ToString() }); await context.SaveChangesAsync(); } } ); }; }
public async Task SayAsAuthorAsync(CommandContext context, [RemainingText][Description("The message to say as you as well as the options you want used in the message")] string message = "") { message = await CheckAndDeleteOnHide(context, message); DiscordWebhook?webhook = (await context.Channel.GetWebhooksAsync()).FirstOrDefault(wbhk => wbhk.Name.Equals("Norm")); if (webhook == null) { webhook = await context.Channel.CreateWebhookAsync("Norm"); } DiscordWebhookBuilder wBuilder = new DiscordWebhookBuilder() .WithContent(ParseOptionsAndEdit(message)) .WithAvatarUrl(context.Member.AvatarUrl) .WithUsername(context.Member.DisplayName) .AddMentions(Mentions.None.Union(new List <IMention> { new UserMention(), })); await webhook.ExecuteAsync(wBuilder); }
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); } }
public async Task Faq(InteractionContext ctx, [Choice("discordinstall", "discordinstall")] [Option("option", "option")] string option, [Option("atuser", "user to mention")] DiscordUser user = null !) { await ctx.CreateResponseAsync(InteractionResponseType.DeferredChannelMessageWithSource); switch (option) { case "discordinstall": var embed = new DiscordEmbedBuilder() { Title = Formatter.Underline(Formatter.Bold("Please do not run these commands as root")), Description = "How to install discord using xbps-src \n" + Formatter.BlockCode(@"git clone https://github.com/void-linux/void-packages cd void-packages ./xbps-src binary-bootstrap echo XBPS_ALLOW_RESTRICTED=yes > etc/conf ./xbps-src pkg discord sudo xbps-install --repository=hostdir/binpkgs/nonfree discord", "bash") }; var build = new DiscordWebhookBuilder(); if (user != null) { embed.Description += $"\n{user.Mention}"; } build.AddEmbed(embed); await ctx.EditResponseAsync(build); return; break; case "": break; } await ctx.DeleteResponseAsync(); }
public async Task <DiscordInteraction> RequestPointsEphemeral(ContextMenuContext ctx, ulong messageID) { DiscordWebhookBuilder webhook = new DiscordWebhookBuilder { Content = $"For this rule you can reduce the users chances by {Rule.MinPoints} - {Rule.MaxPoints}" }; for (int i = 0; i < 3; i++) { List <DiscordButtonComponent> buttons = new List <DiscordButtonComponent>(); for (int index = i * 5; index < (i * 5) + 5; index++) { buttons.Add(new DiscordButtonComponent ( ButtonStyle.Primary, (index + 1).ToString(), (index + 1).ToString(), (index + 1) < Rule.MinPoints || (index + 1) > Rule.MaxPoints) ); } webhook.AddComponents(buttons); } DiscordMessage pointsMessage = await ctx.EditFollowupAsync(messageID, webhook); var interactpointsMessage = await Interactivity.WaitForButtonAsync(pointsMessage, Mod, TimeSpan.FromMinutes(2)); PointsDeducted = int.Parse(interactpointsMessage.Result.Id); foreach (var item in webhook.Components) { foreach (DiscordButtonComponent button in item.Components) { button.Disable(); } } await ctx.EditFollowupAsync(messageID, webhook); return(interactpointsMessage.Result.Interaction); }
public async Task CreateUserWebhook(string title, string description, string hookName, string avatarUrl, ulong guildId, ulong channelId) { try { var guild = await _guildService.GetGuild(guildId); var context = guild.Channels[channelId]; var webhook = await context.CreateWebhookAsync(hookName); var data = new DiscordWebhookBuilder() .WithAvatarUrl(avatarUrl) .AddEmbed( new DiscordEmbedBuilder() .WithColor(new DiscordColor(204, 255, 94)) .WithTitle(title) .WithDescription(description) ); await webhook.ExecuteAsync(data); await webhook.DeleteAsync(); } catch (Exception ex) { if (ex is BadRequestException bad) { _logger.LogError(ex, "Failed to create webhook. Errors: {Errors}", bad.Errors); } else { _logger.LogError(ex, "Failed to create webhook"); } } }
public async Task GetTLDR(InteractionContext ctx, [Option("page", "page to find")] string page, [Choice("linux", "linux")] [Choice("osx", "osx")] [Choice("windows", "windows")] [Choice("android", "android")] [Choice("sunos", "sunos")] [Choice("common", "common")] [Option("platform", "Specifies the platform to be used")] string platform = "linux", // [Option("language", "Specifies the preferred language for the page returned")] // string? language = null, [Option("update", "Updates the offline cache of pages")] bool update = false ) { await ctx.CreateResponseAsync(InteractionResponseType.DeferredChannelMessageWithSource); if (update || !Directory.Exists("tldr-cache")) { await ctx.EditResponseAsync(new DiscordWebhookBuilder().WithContent("Updating cache...")); try { await UpdateCache(); await ctx.EditResponseAsync(new DiscordWebhookBuilder().WithContent("Cache updated")); } catch (Exception e) { await ctx.EditResponseAsync(new DiscordWebhookBuilder().WithContent("Cache update failed")); return; } } //language ??= ctx.Guild.PreferredLocale; page = page.ToLower(); page = page.Replace(' ', '-'); var path = FindPage(page, platform); if (path == null) { await ctx.EditResponseAsync(new DiscordWebhookBuilder().WithContent("page not found")); return; } var lines = await File.ReadAllLinesAsync(path); var builder = new DiscordWebhookBuilder(); var resultPlatform = path.Split('/')[2]; var embed = new DiscordEmbedBuilder() .WithTitle($"tldr page: {lines.FirstOrDefault()?.Remove(0, 2)} ({resultPlatform})") .WithAuthor("tldr pages", "https://tldr.sh/", "https://tldr.sh/assets/img/icon.png") .WithColor(new DiscordColor("#54B59A")) .WithDescription(string.Join("\n", lines.Skip(1)).Replace("\n\n", "\n")) .WithFooter("tldr - collaborative cheatsheets for console commands ", "https://github.githubassets.com/images/icons/emoji/unicode/1f4da.png") .Build(); builder.AddEmbed(embed); if (resultPlatform != "common" && resultPlatform != platform) { var warningEmbed = new DiscordEmbedBuilder() .WithTitle("Platform: " + resultPlatform) .WithColor(DiscordColor.Red) .Build(); builder.AddEmbed(warningEmbed); } await ctx.EditResponseAsync(builder); }
private async Task <DiscordWebhookBuilder> AddPreviousDropdownsAsync(TvShow tvShow, DiscordWebhookBuilder builder) { var selectors = (await _interactionContext.GetOriginalResponseAsync()).Components.SelectMany(x => x.Components).OfType <DiscordSelectComponent>(); DiscordSelectComponent previousTvSelector = selectors.FirstOrDefault(x => x.CustomId.StartsWith("TRS", true, null)); if (previousTvSelector != null) { var tvSelector = new DiscordSelectComponent(previousTvSelector.CustomId, GetFormatedTvShowTitle(tvShow), previousTvSelector.Options); builder.AddComponents(tvSelector); } DiscordSelectComponent previousSeasonSelector = selectors.FirstOrDefault(x => x.CustomId.StartsWith("TSS", true, null)); if (previousSeasonSelector != null) { if (!tvShow.AllSeasonsAvailable() && previousSeasonSelector != null && previousSeasonSelector.Options.Any(x => x.Value.Contains(tvShow.TheTvDbId.ToString(), StringComparison.OrdinalIgnoreCase))) { if (!_interactionContext.Data.CustomId.StartsWith("TRS", true, null)) { var newOptions = tvShow.Seasons.Select(x => new DiscordSelectComponentOption(GetFormattedSeasonName(tvShow, x), $"{tvShow.TheTvDbId.ToString()}/{x.SeasonNumber.ToString()}")).ToDictionary(x => x.Value, x => x); var oldOptions = previousSeasonSelector.Options; var currentOptions = oldOptions.Select(x => new DiscordSelectComponentOption(newOptions.ContainsKey(x.Value) ? newOptions[x.Value].Label : x.Label, x.Value)).ToList(); string defaultSelectedValue = currentOptions.First().Label; try { defaultSelectedValue = _interactionContext.Data.Values.Any() ? currentOptions.Single(x => x.Value == _interactionContext.Data.Values.Single()).Label : currentOptions.Single(x => x.Value == string.Join("/", _interactionContext.Data.CustomId.Split("/").Skip(2))).Label; } catch { } var seasonSelector = new DiscordSelectComponent(previousSeasonSelector.CustomId, defaultSelectedValue, currentOptions); builder.AddComponents(seasonSelector); } } } return(builder); }
/// <summary> /// Creates a follow up message to the interaction /// </summary> /// <param name="webhook">The message to be sent, in the form of a webhook</param> /// <returns>The created message</returns> public async Task <DiscordMessage> FollowUpAsync(DiscordWebhookBuilder webhook) { return(await SlashCommandsExtension.CreateFollowupMessageAsync(Token, webhook)); }
public async Task SendWebhookFilesAsync(CommandContext ctx) { var webhook = await ctx.Channel.CreateWebhookAsync("webhook-test"); using (var fs = new FileStream("ADumbFile.txt", FileMode.Open, FileAccess.Read)) { // Verify that the lib resets the position when asked var builder = new DiscordWebhookBuilder() .WithContent("Testing the `AddFile(Dictionary<string, stream>)` Overload with resetting the postion turned on.") .AddFiles(new Dictionary <string, Stream>() { { "ADumbFile1.txt", fs } }, true); await builder.SendAsync(webhook); await builder.SendAsync(webhook); builder.Clear(); //Verify the lib doesnt reset the position. THe file sent should have 0 bytes. builder.WithContent("Testing the `AddFile(Dictionary<string, stream> files)` Overload with resetting the postion turned off The 2nd file sent should have 0 bytes.") .AddFiles(new Dictionary <string, Stream>() { { "ADumbFile1.txt", fs } }, false); await builder.SendAsync(webhook); await builder.SendAsync(webhook); builder.Clear(); fs.Position = 0; // Verify that the lib resets the position when asked builder.WithContent("Testing the `AddFile(Stream stream)` Overload with resetting the postion turned on.") .AddFile(fs, true); await builder.SendAsync(webhook); await builder.SendAsync(webhook); builder.Clear(); //Verify the lib doesnt reset the position. THe file sent should have 0 bytes. builder.WithContent("Testing the `AddFile(Stream stream)` Overload with resetting the postion turned off. The 2nd file sent should have 0 bytes.") .AddFile(fs, false); await builder.SendAsync(webhook); await builder.SendAsync(webhook); builder.Clear(); fs.Position = 0; // Verify that the lib resets the position when asked builder.WithContent("Testing the `AddFile(string fileName, Stream stream)` Overload with resetting the postion turned on.") .AddFile("ADumbFile2.txt", fs, true); await builder.SendAsync(webhook); await builder.SendAsync(webhook); builder.Clear(); //Verify the lib doesnt reset the position. THe file sent should have 0 bytes. builder.WithContent("Testing the `AddFile(string fileName, Stream stream)` Overload with resetting the postion turned off. The 2nd file sent should have 0 bytes.") .AddFile("ADumbFile2.txt", fs, false); await builder.SendAsync(webhook); await builder.SendAsync(webhook); } await webhook.DeleteAsync(); }
public async Task GetTLDR(InteractionContext ctx, [Option("page", "page to find")] string name, [Option("platform", "Specifies the platform to be used")] Platform platform = Platform.Linux, [Option("language", "Specifies the preferred language for the page returned")] string?language = null ) { await ctx.CreateResponseAsync(InteractionResponseType.DeferredChannelMessageWithSource); if (!await CheckCache(ctx)) { await ctx.EditResponseAsync(new DiscordWebhookBuilder().WithContent("Cache update failed")); } name = name.ToLower(); name = name.Replace(' ', '-'); var index = await GetIndex(); var page = index.Commands.FirstOrDefault(x => x.Name == name); //if page not found, redownload cache and try again if (page == null) { await CheckCache(ctx); index = await GetIndex(); page = index.Commands.FirstOrDefault(x => x.Name == name); if (page == null) { await ctx.EditResponseAsync(new DiscordWebhookBuilder().WithContent("page not found")); return; } } var targets = page.Targets.Where(x => x.Os == platform).ToList(); if (!targets.Any()) { //fallback to common targets = page.Targets.Where(x => x.Os == Platform.Common).ToList(); //fallback to random platform if (!targets.Any()) { targets = page.Targets.ToList(); } } if (language != null) { var langTargets = targets.Where(x => x.Language == language) .ToList(); if (!langTargets.Any()) { await ctx.EditResponseAsync(new DiscordWebhookBuilder().WithContent("page not found in chosen language")); return; } targets = langTargets; } else { //default to english var langTargets = targets.Where(x => x.Language == "en") .ToList(); if (langTargets.Any()) { targets = langTargets; } } var finalTarget = targets.FirstOrDefault(); if (finalTarget == null) { await ctx.EditResponseAsync(new DiscordWebhookBuilder().WithContent("page not found")); return; } var lines = await GetPageFromTarget(name, finalTarget); var builder = new DiscordWebhookBuilder(); var embed = new DiscordEmbedBuilder() .WithTitle($"tldr page: {lines.FirstOrDefault()?.Remove(0, 2)} ({finalTarget.Os})") .WithAuthor("tldr pages", "https://tldr.sh/", "https://tldr.sh/assets/img/icon.png") .WithColor(new DiscordColor("#54B59A")) .WithDescription(string.Join("\n", lines.Skip(1)).Replace("\n\n", "\n")) .WithFooter("tldr - collaborative cheatsheets for console commands ", "https://github.githubassets.com/images/icons/emoji/unicode/1f4da.png") .Build(); builder.AddEmbed(embed); if (finalTarget.Os != Platform.Common && finalTarget.Os != platform) { var warningEmbed = new DiscordEmbedBuilder() .WithTitle($"Platform: {finalTarget.Os}") .WithColor(DiscordColor.Red) .Build(); builder.AddEmbed(warningEmbed); } await ctx.EditResponseAsync(builder); }
private async Task <DiscordWebhookBuilder> AddPreviousDropdownsAsync(Movie movie, DiscordWebhookBuilder builder) { var previousMovieSelector = (DiscordSelectComponent)(await _interactionContext.GetOriginalResponseAsync()).Components.FirstOrDefault(x => x.Components.OfType <DiscordSelectComponent>().Any())?.Components?.Single(); if (previousMovieSelector != null) { var movieSelector = new DiscordSelectComponent(previousMovieSelector.CustomId, GetFormatedMovieTitle(movie), previousMovieSelector.Options); builder.AddComponents(movieSelector); } return(builder); }
/// <summary> /// Broadcasts a message to all registered webhooks. /// </summary> /// <param name="builder">Webhook builder filled with data to send.</param> /// <returns></returns> public async Task <Dictionary <DiscordWebhook, DiscordMessage> > BroadcastMessageAsync(DiscordWebhookBuilder builder) { var deadhooks = new List <DiscordWebhook>(); var messages = new Dictionary <DiscordWebhook, DiscordMessage>(); foreach (var hook in _hooks) { try { messages.Add(hook, await hook.ExecuteAsync(builder).ConfigureAwait(false)); } catch (NotFoundException) { deadhooks.Add(hook); } } // Removing dead webhooks from collection foreach (var xwh in deadhooks) { _hooks.Remove(xwh); } return(messages); }
/// <summary> /// Created a follow up message to the interaction /// </summary> /// <param name="token">The token of the interaction</param> /// <param name="webhook">The data to send</param> /// <returns>The returned <see cref="DiscordMessage"/></returns> public Task <DiscordMessage> CreateFollowupMessageAsync(string token, DiscordWebhookBuilder webhook) => Client.ApiClient.ExecuteWebhookAsync(Client.CurrentApplication.Id, token, webhook);