public static async Task <bool> ActOnButtonAsync(SocketMessageComponent component) { var interactiveMessage = FromMessageId(DataManager.AllGuildData[component.Channel.GetGuild().Id], component.Message.Id); if (interactiveMessage == null) { return(false); } foreach (var actionButton in interactiveMessage.GetActionButtons()) { string[] idParts = component.Data.CustomId.Split(":", 2); if (idParts[0] == interactiveMessage.GetHashCode().ToString() && idParts[1] == actionButton.Label) { try { await actionButton.Action?.Invoke(component); Logger.Log($"Handled button press '{actionButton.Label}' for {component.User} in {component.Channel.GetGuild()?.Name}/{component.Channel.Name}", LogSeverity.Verbose); } catch (Exception ex) when(ex is not CommandReturnException) { Logger.LogException(ex, $"Button press {component.Data.CustomId} by {component.User} threw an exception when invoked."); // TODO: make this message same as the command unhandled exception message. await new ErrorMessage($"```{ex.Message}```", "The interaction couldn't be completed") .SendAsync(component.Channel); } return(true); } } return(false); }
private async Task BumperButtonExecutedAsync(SocketMessageComponent component) { switch (component.Data.CustomId) { case "BumpNotificationsSubscribe": { await _bumper.SubscribeUserAsync(component.User.Id); var builder = new EmbedBuilder() .WithColor(new Color(0x48BA59)) .WithDescription($"{component.User.Mention} тепер отримуватиме сповіщення про **bump**"); await component.RespondAsync(embed : builder.Build(), ephemeral : true); } break; case "BumpNotificationsUnsubscribe": { await _bumper.UnSubscribeUserAsync(component.User.Id); var builder = new EmbedBuilder() .WithColor(new Color(0xEE1B24)) .WithDescription($"{component.User.Mention} більше не отримуватиме сповіщення про **bump**"); await component.RespondAsync(embed : builder.Build(), ephemeral : true); } break; default: break; } }
private async Task OnSelectMenuExecutedAsync(SocketMessageComponent component) { if (_activityChannelIDs.Any(x => x == component.Channel.Id)) { await ActivitySelectMenuExecutedAsync(component); } }
public ButtonHandler(SocketMessageComponent socketMessageComponent) { SocketMessageComponent = socketMessageComponent; SocketUserMessage = SocketMessageComponent.Message; DatabaseManager = DatabaseManager.Instance(); }
private static async Task OnButtonUsed(SocketMessageComponent smc) { if (smc.Data.CustomId == "EMOJI!") { await smc.RespondAsync($"you used the [{smc.Data.CustomId}] button!"); } }
public async Task <IResult> ExecuteAsync(SocketMessageComponent arg) { if (!messages.TryGetValue(arg.Message?.Id ?? 0, out var data)) { return(ExecuteResult.FromError(CommandError.Unsuccessful, "No state data found, unknown callback")); } var args = new CallbackEventArgs() { ComponentId = arg.Data.CustomId, Message = arg.Message, State = data.State, User = arg.User, Interaction = arg }; try { var result = await data.Method.Invoke(args).ConfigureAwait(false); return(result); } catch (Exception ex) { return(ExecuteResult.FromError(ex)); } return(ExecuteResult.FromSuccess()); }
private async Task MusicPlayerButtonExecutedAsync(SocketMessageComponent component) { var userVoiceChannel = (component.User as IGuildUser).VoiceChannel; if (userVoiceChannel is null) { return; } var botUser = await userVoiceChannel.GetUserAsync(_client.CurrentUser.Id); if (botUser is null) { return; } switch (component.Data.CustomId) { case "MusicPlayerShuffle": _musicPlayer.Shuffle(); await component.DeferAsync(); break; case "MusicPlayerPrevious": _musicPlayer.Previous(); await component.DeferAsync(); break; case "MusicPlayerContinue": _musicPlayer.Continue(); await component.DeferAsync(); break; case "MusicPlayerPause": _musicPlayer.Pause(); await component.DeferAsync(); break; case "MusicPlayerStop": _musicPlayer.Stop(); await component.DeferAsync(); break; case "MusicPlayerNext": _musicPlayer.Next(); await component.DeferAsync(); break; default: break; } }
protected virtual async Task RenderAsync(SocketMessageComponent interaction) { var embed = BuildEmbed(); var components = BuildComponents(interaction.Channel, interaction.User); await interaction.UpdateAsync(message => { message.Embed = embed; message.Components = components; }).ConfigureAwait(false); }
/// <summary> /// Handles the given socket component interaction /// </summary> /// <param name="component">The interaction that occurred</param> /// <returns>A task representing the completion of the interaction</returns> public async Task HandleComponentAsync(SocketMessageComponent component) { if (component.User.IsBot || component.User.Id == _client.CurrentUser.Id) { await component.DeferAsync(ephemeral : true); return; } var id = component.Data.CustomId; if (!_handlers.GetHandler(id, out var method, out var type)) { _logger.LogWarning($"Cannot find loaded button for `{id}`"); await component.DeferAsync(ephemeral : true); return; } if (method == null || type == null) { _logger.LogWarning($"Method or type is null for `{id}`"); await component.DeferAsync(ephemeral : true); return; } var service = _provider.GetService(type); if (service == null) { _logger.LogWarning($"Cannot find service for type `{type.Name}`"); await component.DeferAsync(ephemeral : true); return; } ((ComponentHandler)service).SetContext(component, _client); var res = method.Invoke(service, Array.Empty <object>()); if (res == null) { return; } if (method.ReturnType == typeof(Task) || method.ReturnType == typeof(Task <>)) { await(Task) res; } }
/// <summary> /// Handles the given socket component interaction /// </summary> /// <param name="component">The interaction that occurred</param> public void HandleComponent(SocketMessageComponent component) { _ = Task.Run(async() => { try { await HandleComponentAsync(component); } catch (Exception ex) { _logger.LogError(ex, $"Error occurred while resolving component message: {component.Message.Id}::{component.User.Id}"); } }); }
private async Task OnButtonExecutedAsync(SocketMessageComponent component) { if (_bumpChannelIDs.Any(x => x == component.Channel.Id)) { await BumperButtonExecutedAsync(component); } else if (_activityChannelIDs.Any(x => x == component.Channel.Id)) { await ActivityButtonExecutedAsync(component); } else if (_musicChannelIDs.Any(x => x == component.Channel.Id)) { await MusicPlayerButtonExecutedAsync(component); } }
public static async Task Handler(IDbService db, SocketMessageComponent component) { if (component.Data.CustomId != "cem-modmail") { return; } if (component.Message.Channel is not ITextChannel channel) { return; } var guildConfig = db.Guilds.FirstOrDefault(g => g.Id == channel.GuildId); if (guildConfig == null) { Log.Warning("Modmail: no guild configuration exists for guild {GuildName}", channel.Guild.Name); return; } // Create the user thread var member = await channel.Guild.GetUserAsync(component.User.Id); var threadName = string.IsNullOrEmpty(member.Nickname) ? member.ToString() : member.Nickname; var userThread = await channel.CreateThreadAsync(threadName, ThreadType.PrivateThread); var requestMessage = await userThread.SendMessageAsync("Please enter the contents of your modmail here."); await userThread.AddUserAsync(member); Log.Information("Created thread \"{ThreadName}\" for user \"{User}\".", threadName, member.ToString()); // Create the mod thread if (await channel.Guild.GetTextChannelAsync(guildConfig.ReportChannel) is not SocketTextChannel reportsChannel) { Log.Warning("Modmail: reports channel is not of type SocketTextChannel"); return; } var threadStart = await reportsChannel.SendMessageAsync($"{member.Mention} just sent a modmail!"); IThreadChannel modThread = reportsChannel.Threads.FirstOrDefault(t => t.Name == threadName) ?? await reportsChannel.CreateThreadAsync(threadName, message : threadStart); await modThread.SendMessageAsync($"<@&{guildConfig.Roles["Moderator"]}>: {requestMessage.GetJumpUrl()}"); }
private async Task OnButtonClickedAsync(SocketMessageComponent component) { if (component.Message.Author.Id != _client.CurrentUser.Id) { return; } if (component.User is not SocketGuildUser user) { return; } if (!component.Data.CustomId.StartsWith("RA-")) { return; } string[] tokens = component.Data.CustomId.Split('-'); var role = user.Guild.GetRole(Convert.ToUInt64(tokens[2])); if (role is null) { return; } var embed = new EmbedBuilder() .WithAuthor(user) .WithDescription(role.Mention) .WithColor(_config.Value.EmbedColor); if (user.Roles.Any(r => r.Id == role.Id)) { await user.RemoveRoleAsync(role); embed.WithTitle("Removed role"); _logger.LogTrace($"{role.Mention} is removed from {user.Mention}"); } else { await user.AddRoleAsync(role); embed.WithTitle("Granted role"); _logger.LogTrace($"{role.Mention} is granted to {user.Mention}"); } await component.RespondAsync(embed : embed.Build(), ephemeral : true); }
private async Task ActivityButtonExecutedAsync(SocketMessageComponent component) { var user = await _client.Rest.GetGuildUserAsync((component.Channel as IGuildChannel).GuildId, component.User.Id); if (!user.RoleIds.Any(id => _destinyRoleIDs.Any(x => x == id))) { return; } switch (component.Data.CustomId) { case "ActivitierSubscribe": { await component.DeferAsync(); await _activityManager.UserSubscribeOrUnsubscribeAsync(component.Message.Id, component.User.Id); } break; default: break; } }
// Print a movie to an interaction public static async Task PrintToInteraction(SocketMessageComponent interaction) { var movie = new Movie { Url = $"https://www.rottentomatoes.com/m/{interaction.Data.CustomId}" }; // Get the HTML & JSON from the RT page var rawHTML = await WebUtils.DownloadString(movie.Url); var html = new HtmlDocument(); html.LoadHtml(rawHTML); // Get the JSON from the HTML dynamic JSON = JsonConvert.DeserializeObject(rawHTML.CutBeforeAndAfter("<script id=\"score-details-json\" type=\"application/json\">", "</script>")); // Title movie.Name = HttpUtility.HtmlDecode(JSON.scoreboard.title.ToString()); // Tomatometer movie.CriticScore = JSON.scoreboard.tomatometerScore == null ? "N/A" : $"{JSON.scoreboard.tomatometerScore}%"; // Year movie.Year = JSON.scoreboard.info.ToString(); switch (JSON.scoreboard.tomatometerState.ToString()) { case "certified-fresh": movie.CriticScoreIcon = "<:certified_fresh:737761619375030422>"; break; case "fresh": movie.CriticScoreIcon = "<:fresh:737761619299270737>"; break; case "rotten": movie.CriticScoreIcon = "<:rotten:737761619299532874>"; break; default: movie.CriticScoreIcon = "<:notomatometer:891357892417028127>"; break; } // Audience Score movie.AudienceScore = JSON.modal.audienceScoreAll.score == null ? "N/A" : $"{JSON.modal.audienceScoreAll.score}%"; // Audience Score Icon switch (JSON.modal.audienceScoreAll.audienceClass.ToString()) { case "upright": movie.AudienceIcon = "<:audienceliked:737761619328761967>"; break; case "spilled": movie.AudienceIcon = "<:audiencedisliked:737761619416842321>"; break; default: movie.AudienceIcon = "<:noaudiencescore:891357892442198047>"; break; } // Critic Consensus movie.CriticsConsensus = html.Text.Contains("<span data-qa=\"critics-consensus\">") ? html.DocumentNode.SelectSingleNode("//p[contains(@class, 'what-to-know__section-body')]").InnerText.Trim().Replace("Read critic reviews", "") : "No consensus yet."; movie.Poster = rawHTML.CutBefore("class=\"posterImage js-lazy") .CutBefore("data-src=\"") .CutAfter("\""); // Create a pretty embed & send it await interaction.UpdateAsync(x => { x.Components = new ComponentBuilder().WithButton("View on RottenTomatoes.com", style: ButtonStyle.Link, url: movie.Url).Build(); x.Content = null; x.Embed = new EmbedBuilder() .WithTitle($"{movie.Name} - {movie.Year}") .WithColor(EmbedUtils.Red) .WithThumbnailUrl(movie.Poster) .AddField("Tomatometer", $"{movie.CriticScoreIcon} {movie.CriticScore}") .AddField("Audience Score", $"{movie.AudienceIcon} {movie.AudienceScore}") .AddField("Critics Consensus", movie.CriticsConsensus) .Build(); }); }
private async Task ActivitySelectMenuExecutedAsync(SocketMessageComponent component) { switch (component.Data.CustomId) { case "QuickActivitySelector": { var builder = new EmbedBuilder() .WithColor(new Color(0xFFFFFF)) .WithDescription("Оберіть зручний час"); var menuBuilder = new SelectMenuBuilder() .WithPlaceholder("Оберіть час") .WithCustomId(string.Join(',', component.Data.Values)) .WithMinValues(1).WithMaxValues(1); var startDate = DateTime.Now; var endDate = startDate.AddHours(12); var tmpDate = startDate.AddMinutes(30); while (tmpDate < endDate) { menuBuilder = menuBuilder.AddOption(tmpDate.ToString("dd.MM HH:mm"), tmpDate.ToString("dd.MM_HH:mm")); tmpDate = tmpDate.AddMinutes(30); } var componentBuilder = new ComponentBuilder() .WithSelectMenu(menuBuilder); await component.RespondAsync(embed : builder.Build(), components : componentBuilder.Build(), ephemeral : true); } break; case string c when c.StartsWith("QuickActivity_"): { var raid = new ActivityContainer() { ChannelID = component.Channel.Id, ActivityType = Enum.Parse <BungieSharper.Entities.Destiny.HistoricalStats.Definitions.DestinyActivityModeType>(c.Split('_')[1]), PlannedDate = DateTime.ParseExact(string.Join(',', component.Data.Values), "dd.MM_HH:mm", CultureInfo.CurrentCulture), ActivityName = null, Description = null, Users = new ulong[] { component.User.Id } }; await component.DeferAsync(); await InitActivityAsync(raid); } break; case string c when c.StartsWith("QuickRaid_"): { var raid = new ActivityContainer() { ChannelID = component.Channel.Id, ActivityType = BungieSharper.Entities.Destiny.HistoricalStats.Definitions.DestinyActivityModeType.Raid, PlannedDate = DateTime.ParseExact(string.Join(',', component.Data.Values), "dd.MM_HH:mm", CultureInfo.CurrentCulture), ActivityName = c.Split('_')[1], Description = null, Users = new ulong[] { component.User.Id } }; await component.DeferAsync(); await InitActivityAsync(raid); } break; default: break; } }
public ComponentCommandContext(SocketMessageComponent ctx) => _ctx = ctx;
/// <summary> /// Handler for button executions /// </summary> /// <param name="arg">The button handler</param> /// <returns>A task representing the completion of the reaction handling</returns> public Task Client_ButtonExecuted(SocketMessageComponent arg) { _buttons.HandleComponent(arg); return(Task.CompletedTask); }
private async Task HandleComponent(SocketMessageComponent component) { throw new NotImplementedException(); }