Exemple #1
0
        protected virtual MessageComponent BuildComponents(IChannel channel, IUser user)
        {
            const ButtonStyle buttonStyle = ButtonStyle.Secondary;

            var builder = new ComponentBuilder()
                          .WithButton(style: buttonStyle, emote: Options.First, customId: FirstId, disabled: _page <= 1)
                          .WithButton(style: buttonStyle, emote: Options.Back, customId: PreviousId, disabled: _page <= 1)
                          .WithButton(style: buttonStyle, emote: Options.Next, customId: NextId, disabled: _page >= _pages)
                          .WithButton(style: buttonStyle, emote: Options.Last, customId: LastId, disabled: _page >= _pages);

            var manageMessages = (channel is IGuildChannel guildChannel) &&
                                 (user as IGuildUser).GetPermissions(guildChannel).ManageMessages;

            if (Options.JumpDisplayOptions == JumpDisplayOptions.Always ||
                (Options.JumpDisplayOptions == JumpDisplayOptions.WithManageMessages && manageMessages))
            {
                builder.WithButton(style: buttonStyle, emote: Options.Jump, customId: JumpId);
            }

            builder.WithButton(style: buttonStyle, emote: new Emoji("🛑"), customId: StopId);

            if (Options.DisplayInformationIcon)
            {
                builder.WithButton(style: buttonStyle, emote: Options.Info, customId: InfoId);
            }

            return(builder.Build());
        }
Exemple #2
0
        public async Task PutRoles([Remainder] ITextChannel channel)
        {
            var builder = new ComponentBuilder();

            builder.WithButton("Venus", $"^{nameof(ChangeAdeptAction)}.Venus", ButtonStyle.Primary, emote: Emotes.GetEmote(Element.Venus));
            builder.WithButton("Mars", $"^{nameof(ChangeAdeptAction)}.Mars", ButtonStyle.Primary, emote: Emotes.GetEmote(Element.Mars));
            builder.WithButton("Jupiter", $"^{nameof(ChangeAdeptAction)}.Jupiter", ButtonStyle.Primary, emote: Emotes.GetEmote(Element.Jupiter));
            builder.WithButton("Mercury", $"^{nameof(ChangeAdeptAction)}.Mercury", ButtonStyle.Primary, emote: Emotes.GetEmote(Element.Mercury));
            await channel.SendMessageAsync($"Choose from {Emotes.GetIcon(Element.Venus)}Venus, {Emotes.GetIcon(Element.Mars)}Mars, " +
                                           $"{Emotes.GetIcon(Element.Jupiter)}Jupiter, or {Emotes.GetIcon(Element.Mercury)}Mercury. You can change your role/element at any time.", components : builder.Build());
        }
Exemple #3
0
        public async Task Buttons()
        {
            ComponentBuilder builder = new ComponentBuilder();

            builder.WithButton("Test button 1", "btn1", ButtonStyle.Danger);
            builder.WithButton("Test button 2", "btn2", ButtonStyle.Danger);
            var msg = await ReplyAsync("Click button below", component : builder.Build());

            var srv = Program.Services.GetRequiredService <MessageComponentService>();

            srv.Register(msg, handleButton);
        }
Exemple #4
0
        //[Command("unpause")]
        //[Summary("Pauses the joining of the list.")]
        //[ModPermission]
        //public async Task Unpause()
        //{
        //    storage.IsPaused = false;
        //    storage.Save();

        //    await UpdateReactionMessageAsync(waitingList, Context.Guild, storage);

        //    await Context.Message.ReplyAsync("Waiting list has been unpaused");
        //}

        public static async Task UpdatePublicMessageAsync(IWaitingList waitingList, IGuild guild, GuildData guildData)
        {
            var message = await GetMessageAsync(guild, guildData);

            if (message is not IUserMessage)
            {
                return;
            }

            var embedBuilder = new EmbedBuilder
            {
                Color = Color.Green,
                Title = $"Waiting list"
            };

            var sortedList = await waitingList.GetPlayerListAsync();

            var description = "";
            int counter     = 0;

            foreach (var player in sortedList)
            {
                description += $"**{++counter}.** {player.Name} ({GetMentionWithId(player.UserId)}) {(player.IsSub ? "(Sub) " : "")}";
                if (player.PlayCount > 0)
                {
                    description += $"(Played { player.PlayCount} time{ (player.PlayCount > 1 ? "s" : "")})";
                }
                description += "\r\n";
            }
            string url = "https://wl.pdelvo.com/WaitingList/" + guild.Id;

            embedBuilder.Description = description;
            embedBuilder.AddField("\u200B", "[View this list in real time](" + url + ")");

            ComponentBuilder componentBuilder = new ComponentBuilder();

            componentBuilder.WithButton("Join", customId: "join", disabled: guildData.IsPaused);
            componentBuilder.WithButton("Leave", customId: "leave");

            // Waiting for an updated Discord.Net package for this to work
            componentBuilder.WithButton("Website", null, style: ButtonStyle.Link, url: url);

            Embed embed = embedBuilder.Build();

            await message.ModifyAsync(p =>
            {
                p.Content    = $"Join the waiting list now!:";
                p.Embed      = embed;
                p.Components = componentBuilder.Build();
            });
        }
        // This method needs to be overriden to build our own component the way we want.
        public override ComponentBuilder GetOrAddComponents(bool disableAll, ComponentBuilder builder = null)
        {
            builder ??= new ComponentBuilder();
            foreach (var option in Options)
            {
                var    emote = EmoteConverter?.Invoke(option);
                string label = StringConverter?.Invoke(option);
                if (emote is null && label is null)
                {
                    throw new InvalidOperationException($"Neither {nameof(EmoteConverter)} nor {nameof(StringConverter)} returned a valid emote or string.");
                }

                var button = new ButtonBuilder()
                             .WithCustomId(emote?.ToString() ?? label)
                             .WithStyle(option.Style) // Use the style of the option
                             .WithEmote(emote)
                             .WithDisabled(disableAll);

                if (label is not null)
                {
                    button.Label = option.Option.ToString();
                }

                builder.WithButton(button);
            }

            return(builder);
        }
        ComponentBuilder GetButtons(RolesService.RolesSetup setup)
        {
            var builder = new ComponentBuilder();
            int buttons = 0;

            foreach (var emoji in setup.Roles)
            {
                IEmote em;
                if (Emote.TryParse(emoji.Key, out var emote))
                {
                    em = emote;
                }
                else
                {
                    em = new Emoji(emoji.Key);
                }
                var role = Context.Guild.GetRole(emoji.Value);
                var name = role?.Name ?? emoji.Value.ToString();
                builder.WithButton(name,
                                   emoji.Value.ToString(),
                                   ButtonStyle.Primary,
                                   em,
                                   row: (buttons++) / 5
                                   );
            }
            return(builder);
        }
Exemple #7
0
        public async Task Buttons()
        {
            try
            {
                ComponentBuilder builder = new ComponentBuilder();
                builder.WithButton("Test button 1", "btn1", ButtonStyle.Danger);
                builder.WithButton("Test button 2", "btn2", ButtonStyle.Danger);
                var msg = await Interaction.RespondAsync("Click below", component : builder.Build());

                var srv = Program.Services.GetRequiredService <MessageComponentService>();
                srv.Register(msg, handleButton);
            }
            catch (Exception ex)
            {
                Program.LogError(ex, "EchoButtons");
            }
        }
Exemple #8
0
        public async Task BotInfoAsync(ICommandContext ctx)
        {
            var embed = new EmbedBuilder
            {
                Title = "Status",
                Color = Color.Purple
            };

            embed.AddField("Latest version", Utils.ToDiscordTimestamp(new FileInfo(Assembly.GetEntryAssembly().Location).LastWriteTimeUtc, Utils.TimestampInfo.None), true);
            embed.AddField("Last command received", Utils.ToDiscordTimestamp(StaticObjects.LastMessage, Utils.TimestampInfo.TimeAgo), true);
            embed.AddField("Uptime", Utils.ToDiscordTimestamp(StaticObjects.Started, Utils.TimestampInfo.TimeAgo), true);
            embed.AddField("Guild count", StaticObjects.Client.Guilds.Count, true);

            var options = new ComponentBuilder();

            if (StaticObjects.IsBotOwner(ctx.User))
            {
                options.WithSelectMenu("delCache", StaticObjects.AllGameNames.Select(x => new SelectMenuOptionBuilder(x, StaticObjects.Db.GetCacheName(x))).ToList(), placeholder: "Select a game cache to delete (require bot restart)");
            }
            options.WithButton("Show Global Stats", "globalStats");

            await ctx.ReplyAsync(embed : embed.Build(), components : options.Build(), ephemeral : true);

            embed.AddField("Useful links",
#if NSFW_BUILD
                           " - [Source Code](https://github.com/Xwilarg/Sanara)\n" +
                           " - [Website](https://sanara.zirk.eu/)\n" +
#endif
                           " - [Invitation Link](https://discord.com/api/oauth2/authorize?client_id=" + StaticObjects.ClientId + "&scope=bot%20applications.commands)\n"
#if NSFW_BUILD
                           +
                           " - [Support Server](https://discordapp.com/invite/H6wMRYV)\n" +
                           " - [Top.gg](https://discordbots.org/bot/329664361016721408)"
#endif
                           );
            embed.AddField("Credits",
                           "Programming: [Zirk#0001](https://zirk.eu/)\n" +
                           "With the help of [TheIndra](https://theindra.eu/)\n"
#if NSFW_BUILD
                           +
                           "Profile Picture: [Uikoui](https://www.pixiv.net/en/users/11608780)"
#endif // TODO: Can prob use current pfp for SFW version
                           );

#if NSFW_BUILD
            // Get latests commits
            StringBuilder str  = new();
            var           json = JsonConvert.DeserializeObject <JArray>(await StaticObjects.HttpClient.GetStringAsync("https://api.github.com/repos/Xwilarg/Sanara/commits?per_page=5"));
            foreach (var elem in json)
            {
                var time = Utils.ToDiscordTimestamp(DateTime.ParseExact(elem["commit"]["author"]["date"].Value <string>(), "MM/dd/yyyy HH:mm:ss", CultureInfo.InvariantCulture), Utils.TimestampInfo.None);
                str.AppendLine($"{time}: [{elem["commit"]["message"].Value<string>()}](https://github.com/Xwilarg/Sanara/commit/{elem["sha"].Value<string>()})");
            }
            embed.AddField("Latest changes", str.ToString());

            await ctx.ReplyAsync(embed : embed.Build(), components : options.Build());
#endif
        }
Exemple #9
0
 public async Task PingAsync(IIodemCommandContext context)
 {
     var cb = new ComponentBuilder();
     cb.WithButton("Ping", "my_id");
     await context.ReplyAsync(embed: new EmbedBuilder()
         .WithColor(Colors.Get("Iodem"))
         .WithDescription($"Pong! {Global.Client.Latency} ms")
         .Build(), component: cb.Build());
 }
Exemple #10
0
        private async Task User_RolesAdded(SocketGuildUser user, SocketRole[] added)
        {
            var muted = await GetMutedRole(user.Guild);

            if (added.Any(x => x.Id == muted.Id) == false)
            {
                return;
            }

            var penalty = FindPenalty(x =>
            {
                if (!(x is MutePenalty mute))
                {
                    return(false);
                }
                if (mute.Guild.Id != user.Guild.Id)
                {
                    return(false);
                }
                return(x.Target?.Id == user.Id);
            }) as MutePenalty;

            if (penalty == null)
            {
                DefaultDurations.TryGetValue(user.Guild.Id, out var defStr);
                TimeSpan?duration = defStr == null ? null : GetDurationForDefault(defStr);
                penalty = await AddMute(user.Guild.CurrentUser, user, "Detected via role change", duration);

                var embed    = getRoleMuteBuilder(user, penalty);
                var cBuilder = new ComponentBuilder();
                cBuilder.WithButton("Set duration to 1h", $"{penalty.Id}-0", ButtonStyle.Secondary);
                cBuilder.WithButton("+1 hour", $"{penalty.Id}-1", ButtonStyle.Success);
                cBuilder.WithButton("-1 hour", $"{penalty.Id}-2", ButtonStyle.Primary);

                cBuilder.WithButton("Remove Mute", $"{penalty.Id}-3", ButtonStyle.Danger, row: 1);

                // addmute already saves the service
                var msg = await user.Guild.PublicUpdatesChannel.SendMessageAsync(embed : embed.Build(),
                                                                                 component : cBuilder.Build());

                MessageComponentService.Register(msg, handleMuteChange, penalty.Id.ToString());
            }
        }
        public async Task Help()
        {
            // Check whitelist:
            if (!Whitelist.IsServerOnList(((Context.Guild == null) ? (0) : (Context.Guild.Id))))
            {
                // Self-hosted whitelist notification for official bot:
                if (Context.Client.CurrentUser.Id == 815695225678463017)
                {
                    await RespondAsync("This bot is now self-host only. Learn more about this change in the updates channel on the support server: https://discord.gg/8dkjmGSbYE", ephemeral : true);
                }
                else
                {
                    await RespondAsync("This guild is not on the whitelist. The command was blocked.", ephemeral : true);
                }
                return;
            }
            //response embed:
            var embed = new EmbedBuilder();

            embed.Title       = "Help With Instagram Embed";
            embed.Url         = "https://discord.gg/6K3tdsYd6J";
            embed.Description = "This bot uploads videos and images from an Instagram post provided via a link. The bot also allows for subscribing to new posts from accounts using the `/subscribe` command.";
            embed.AddField("Embedding Individual Posts", "To embed the contents of an Instagram url, simply paste the link into the chat and the bot will do the rest (as long as it has permission to).\nYou can also use the `/link` along with a URL.\nFor posts with multiple slides, use the `/link` command along with the optional `Index:` parameter to select the specific slide.\nTo get information about an Instagram account, use `/profile [username]` or `/link` with a link to the profile. These commands will NOT subscribe you to an account or get reoccuring updates from that account. Use `/subscribe` for that.");
            embed.AddField("Subscriptions", "Note: The subscriptions module is currently under beta testing to limited guilds.\nTo subscribe to an account, use `/subscribe` and the users Instagram account to get new posts from that account delivered to the channel where the command is executed.\nTo unsubscribe from an account, use `/unsubscribe` and the username of the Instagram account in the channel that is subscribed to the account. You can also use `/unsubscribeall` to unsubscribe from all Instagram accounts.\nUse `/subscribed` to list all of the Instagram accounts that the guild is subscribed to.");
            embed.AddField("Roles", "Only users with the role `InstagramBotSubscribe` (case sensitive) or guild administrator permission are allowed to unsubscribe and subscribe to accounts.");
            embed.AddField("Permissions", "The following channel permissions are required for the bot's operation:\n" +
                           "- `Send Messages`\n" +
                           "- `View Channel`\n" +
                           "- `Attach Files`\n" +
                           "- `Manage Messages` (optional-used to remove duplicate embeds)");
            // Only display on official bot.
            if (Context.Client.CurrentUser.Id == 815695225678463017)
            {
                embed.AddField("Legal", "[Terms of Use](https://github.com/bman46/InstagramEmbedDiscordBot/blob/master/legal/TermsAndConditions.md)\n[Privacy Policy](https://github.com/bman46/InstagramEmbedDiscordBot/blob/master/legal/Privacy.md)");
            }
            else
            {
                embed.AddField("Support", "Please note that this bot is self-hosted. For any support, ask the server owner/mods.");
            }
            embed.WithColor(new Color(131, 58, 180));

            ComponentBuilder component = new ComponentBuilder();

            // Only on official bot:
            if (Context.Client.CurrentUser.Id == 815695225678463017)
            {
                ButtonBuilder button = new ButtonBuilder();
                button.Label = "Support Server";
                button.Style = ButtonStyle.Link;
                button.Url   = "https://discord.gg/6K3tdsYd6J";
                component.WithButton(button);
            }

            await RespondAsync(embed : embed.Build(), ephemeral : false, components : component.Build());
        }
Exemple #12
0
        public async Task <string> SelectButtonAsync(IEnumerable <string> options, string text = null, Embed embed = null, bool deleteWhenDone = false, TimeSpan?timeout = null)
        {
            var builder = new ComponentBuilder();

            for (int i = 0; i < options.Count(); i++)
            {
                builder.WithButton(ButtonBuilder.CreatePrimaryButton(options.ElementAt(i), i.ToString()));
            }
            var btn = await SelectButtonAsync(builder, text, embed, deleteWhenDone, timeout).ConfigureAwait(false);

            return(options.ElementAt(int.Parse(btn.CustomId)));
        }
Exemple #13
0
        public static async Task <(Embed Embed, MessageComponent Components)> GetSettingsDisplayAsync(IGuild guild)
        {
            var subs = await StaticObjects.GetSubscriptionsAsync(guild.Id);

            var mySubs = subs?.Select(x => $"**{Utils.ToWordCase(x.Key)}**: {(x.Value == null ? "None" : x.Value.Mention)}");
            var button = new ComponentBuilder();

            if (subs != null)
            {
                foreach (var sub in subs)
                {
                    if (sub.Value != null)
                    {
                        button.WithButton($"Remove {sub.Key} subscription", $"delSub-{sub.Key}", style: ButtonStyle.Danger);
                    }
                }
            }
            button.WithButton("Database dump", "dump", style: ButtonStyle.Secondary);
            button.WithButton("Toggle translation from flags", "flag", style: ButtonStyle.Secondary);
            return(new EmbedBuilder
            {
                Title = guild.ToString(),
                Color = Color.Purple,
                Fields = new List <EmbedFieldBuilder>
                {
                    new EmbedFieldBuilder
                    {
                        Name = "Translation from flags",
                        Value = StaticObjects.Db.GetGuild(guild.Id).TranslateUsingFlags ? "Enabled" : "Disabled"
                    },
                    new EmbedFieldBuilder
                    {
                        Name = "Subscriptions",
                        Value = subs == null ? "Not yet initialized" : (mySubs.Any() ?  string.Join("\n", mySubs) : "None")
                    }
                }
            }.Build(), button.Build());
        }
        /// <summary>
        /// Precondition to disable the source of an interaction.
        /// </summary>
        /// <param name="context"></param>
        /// <param name="commandInfo"></param>
        /// <param name="services"></param>
        /// <returns></returns>
        public override async Task <PreconditionResult> CheckRequirementsAsync(IInteractionContext context, ICommandInfo commandInfo, IServiceProvider services)
        {
            if (context.Interaction is not IComponentInteraction messageComponent)
            {
                return(PreconditionResult.FromError("This attribute does not work for application commands!"));
            }

            var builder = new ComponentBuilder();

            var rows = ComponentBuilder.FromMessage(messageComponent.Message).ActionRows;

            for (int i = 0; i < rows.Count; i++)
            {
                foreach (var component in rows[i].Components)
                {
                    switch (component)
                    {
                    case ButtonComponent button:
                        builder.WithButton(button.ToBuilder()
                                           .WithDisabled(!button.CustomId.StartsWith("delete-message-")), i);
                        break;

                    case SelectMenuComponent menu:
                        builder.WithSelectMenu(menu.ToBuilder()
                                               .WithDisabled(true), i);
                        break;
                    }
                }
            }

            try
            {
                await messageComponent.Message.ModifyAsync(x => x.Components = builder.Build());

                return(PreconditionResult.FromSuccess());
            }
            catch (Exception ex)
            {
                return(PreconditionResult.FromError(ex));
            }
        }
Exemple #15
0
        public async Task Pause()
        {
            if (!guildData.IsEnabled)
            {
                await Context.Message.ReplyAsync("Waiting list has not open");

                return;
            }
            guildData.IsPaused = true;
            dataContext.Update(guildData);
            dataContext.SaveChanges();

            await UpdatePublicMessageAsync(waitingList, Context.Guild, guildData);

            ComponentBuilder componentBuilder = new ComponentBuilder();

            componentBuilder.WithButton("Unpause", customId: "unpause");

            await Context.Message.DeleteAsync();

            await Context.Channel.SendMessageAsync("Waiting list has been paused", component : componentBuilder.Build());
        }
Exemple #16
0
        public async Task Start()
        {
            var message = await GetMessageAsync(Context.Guild, guildData);

            if (message != null)
            {
                await Context.Message.ReplyAsync("Waiting list is already open");

                return;
            }

            waitingList.ClearUsers();

            var waitingListChannel = Context.Guild.GetTextChannel(guildData.WaitingListChannelId);

            message = await waitingListChannel.SendMessageAsync("Join the waiting list now!");

            guildData.PublicMessageId = message.Id;
            guildData.IsEnabled       = true;
            guildData.IsPaused        = false;
            dataContext.Update(guildData);
            dataContext.SaveChanges();
            // await message.AddReactionAsync(storage.ReactionEmote);

            await UpdatePublicMessageAsync(waitingList, Context.Guild, guildData);

            var modMessage = await Context.Message.ReplyAsync("Waiting list has been started");

            ComponentBuilder componentBuilder = new ComponentBuilder();

            componentBuilder.WithButton("Clear counters", customId: "clearcounters");

            await modMessage.ModifyAsync(p =>
            {
                p.Components = componentBuilder.Build();
            });
        }
        private async Task <bool> FavEmoteGetPage(int dir, string searchTerm, int page, int rows = 4, int columns = 5, bool secondTry = false)
        {
            var message = Context.Interaction as SocketMessageComponent;
            var user    = Context.Interaction.User;

            if (message.Message.Embeds.First().Author.Value.Name != $"{user.Username}#{user.Discriminator}")
            {
                Context.Interaction.RespondAsync("You did not invoke this message.", null, false, true);
                //Context.Interaction.DeferAsync();
                return(false);
            }

            page += dir;

            if (page < 0)
            {
                return(false);                                                                                        // disable prev button on page 0
            }
            var    emoteResult = DiscordHelper.SearchEmote(searchTerm, Context.Guild.Id, page, false, rows, columns); // TODO pass debug info aswell
            string desc        = $"Available({page * emoteResult.PageSize}-{Math.Min((page + 1) * emoteResult.PageSize, emoteResult.TotalEmotesFound)}/{emoteResult.TotalEmotesFound}) '{searchTerm}' {Environment.NewLine}**To use the emotes (Usage .<name>)**";

            EmbedBuilder builder = new EmbedBuilder()
            {
                ImageUrl    = emoteResult.Url,
                Description = desc,
                Color       = Color.DarkRed,
                Title       = "Image full size",
                Footer      = new EmbedFooterBuilder()
                {
                    Text = searchTerm + " Page: " + page
                },
                ThumbnailUrl = "https://cdn.battlerush.dev/bot_xmas.png",
                Timestamp    = DateTimeOffset.Now,
                Url          = emoteResult.Url,
            };

            builder.WithAuthor(Context.Interaction.User);

            var builderComponent = new ComponentBuilder();

            try
            {
                int row = 0;
                int col = 0;
                foreach (var emote in emoteResult.EmoteList)
                {
                    if (emoteResult.valid.Skip(row * columns + col).First())
                    {
                        builderComponent.WithButton(emote.Value, $"emote-fav-{emote.Key}", ButtonStyle.Primary, Emote.Parse($"<:{emote.Value}:{emote.Key}>"), null, false, row);
                    }
                    else
                    {
                        builderComponent.WithButton(emote.Value, $"emote-fav-{emote.Key}", ButtonStyle.Primary, null, null, false, row);
                    }

                    col++;

                    if (col == columns)
                    {
                        row++;
                        col = 0;
                    }
                }

                // Start fresh row for paging
                if (col > 0)
                {
                    row++;
                }

                builderComponent.WithButton("Prev <", $"emote-fav-get-prev-page-{searchTerm}-{page}", ButtonStyle.Danger, null, null, page == 0, row);
                builderComponent.WithButton("> Next", $"emote-fav-get-next-page-{searchTerm}-{page}", ButtonStyle.Success, null, null, (page + 1) * emoteResult.PageSize > emoteResult.TotalEmotesFound, row);

                await message.Message.ModifyAsync(i => { i.Embed = builder.Build(); i.Components = builderComponent.Build(); });
            }
            catch (HttpException ex)
            {
                foreach (var error in ex.Errors)
                {
                    if (error.Errors.Any(i => i.Code == "BUTTON_COMPONENT_INVALID_EMOJI"))
                    {
                        var parts = error.Path.Split('.');

                        int error_row    = Convert.ToInt32(Regex.Replace(parts[0], "[^0-9]", ""));
                        int error_column = Convert.ToInt32(Regex.Replace(parts[1], "[^0-9]", ""));


                        var brokenEmote = emoteResult.EmoteList.Skip(error_row * columns + error_column).First();
                        EmoteDBManager.Instance().ChangeValidStatus(brokenEmote.Key, false);
                    }
                }

                // call yourself again to retry ->
                if (secondTry == false)
                {
                    await FavEmoteGetPage(dir, searchTerm, (page -= dir), rows = 4, columns = 5, true);
                }

                // Some emotes may no lonver be valid -> db entry to invalidate the emote
            }
            //Context.Interaction.DeferAsync();
            return(true);
        }
Exemple #18
0
        /// <summary>
        /// Handles adding a button to the component builder
        /// </summary>
        /// <param name="btn">The attribute that represents the buttons config</param>
        /// <param name="method">The method the attribute handles</param>
        /// <param name="builder">The component builder</param>
        public void HandleButton(ButtonAttribute btn, MethodInfo method, ComponentBuilder builder)
        {
            var id = _handlers.IdFromMethod(method);

            builder.WithButton(btn.Label, id, btn.Style, btn.Emote?.GetEmote(), btn.Url, btn.Disabled, btn.Row);
        }
Exemple #19
0
        public async Task <ButtonComponent> SelectButtonAsync(ComponentBuilder builder, string text = null, Embed embed = null, bool deleteWhenDone = false, TimeSpan?timeout = null,
                                                              AllowedMentions allowedMentions       = null)
        {
            if (string.IsNullOrWhiteSpace(text) && embed == null)
            {
                throw new ArgumentNullException($"One of {nameof(text)} or {nameof(embed)} must be non-null");
            }

            var selectionSource = new TaskCompletionSource <ButtonComponent>();

            var selectionTask = selectionSource.Task;
            var timeoutTask   = Task.Delay(timeout ?? InteractivityService.DefaultTimeout);

            var components = builder.Build();

            var message = await ReplyAsync(message : text, embed : embed, component : components, allowedMentions : allowedMentions).ConfigureAwait(false);

            async Task CheckButtonAsync(CallbackEventArgs e)
            {
                if (e.User.Id != Context.User.Id)
                {
                    return;
                }

                var btn = getButton(components, e.ComponentId);

                selectionSource.SetResult(btn);
            }

            try
            {
                ComponentService.Register(message, CheckButtonAsync, doSave: false);
                var task_result = await Task.WhenAny(timeoutTask, selectionTask).ConfigureAwait(false);

                var result = task_result == selectionTask
                    ? await selectionTask.ConfigureAwait(false)
                    : null;

                if (deleteWhenDone)
                {
                    await message.DeleteAsync().ConfigureAwait(false);
                }
                else
                { // disable the buttons instead
                    var disabledBuilder = new ComponentBuilder();
                    int i = 0;
                    foreach (var row in builder.ActionRows)
                    {
                        foreach (var btn in row.Components)
                        {
                            disabledBuilder.WithButton(btn.Label,
                                                       btn.CustomId, btn.Style, btn.Emote, btn.Url, true, i);
                        }
                        i++;
                    }
                    await message.ModifyAsync(x =>
                    {
                        x.Components = disabledBuilder.Build();
                    });
                }

                return(result);
            } finally
            {
                ComponentService.Unregister(message);
            }
        }
        public async Task EmoteFavourite(string search, bool secondTry = false)
        {
            int rows    = 4;
            int columns = 5;

            if (!CommonHelper.AllowedToRun(BotPermissionType.EnableType2Commands, Context.Message.Channel.Id, Context.Message.Author.Id))
            {
                return;
            }

            Stopwatch watch = new Stopwatch();

            watch.Start();

            var author = Context.Message.Author;

            if (search.Length < 2 && author.Id != Program.ApplicationSetting.Owner)
            {
                await Context.Channel.SendMessageAsync($"Search term needs to be atleast 2 characters long", false); // to prevent from db overload

                return;
            }

            var emoteResult = DiscordHelper.SearchEmote(search, Context.Guild.Id, 0, false, rows, columns);


            watch.Stop();

            int page = 0;

            string desc = $"**Available({page * emoteResult.PageSize}-{Math.Min((page + 1) * emoteResult.PageSize, emoteResult.TotalEmotesFound)}/{emoteResult.TotalEmotesFound}) '{search}' emojis to use (Usage .<name>)**" + Environment.NewLine;

            try
            {
                EmbedBuilder builder = new EmbedBuilder()
                {
                    ImageUrl    = emoteResult.Url,
                    Description = desc,
                    Color       = Color.DarkRed,
                    Title       = "Image full size",
                    Footer      = new EmbedFooterBuilder()
                    {
                        Text = search + " Page: " + page
                    },
                    ThumbnailUrl = "https://cdn.battlerush.dev/bot_xmas.png",
                    Timestamp    = DateTimeOffset.Now,
                    Url          = emoteResult.Url,
                };
                builder.WithAuthor(Context.User);

                //foreach (var item in emoteResult.Fields)
                //    builder.AddField(item.Key, item.Value);


                // TODO create common place for button ids
                var builderComponent = new ComponentBuilder();

                int row = 0;
                int col = 0;
                foreach (var emote in emoteResult.EmoteList)
                {
                    if (emoteResult.valid.Skip(row * columns + col).First())
                    {
                        builderComponent.WithButton(emote.Value, $"emote-fav-{emote.Key}", ButtonStyle.Primary, Emote.Parse($"<:{emote.Value}:{emote.Key}>"), null, false, row);
                    }
                    else
                    {
                        builderComponent.WithButton(emote.Value, $"emote-fav-{emote.Key}", ButtonStyle.Primary, null, null, false, row);
                    }

                    col++;

                    if (col == columns)
                    {
                        row++;
                        col = 0;
                    }
                }

                // Start fresh row for paging
                if (col > 0)
                {
                    row++;
                }

                builderComponent.WithButton("Prev <", $"emote-fav-get-prev-page-{search}-{page}", ButtonStyle.Danger, null, null, page == 0, row);
                builderComponent.WithButton("> Next", $"emote-fav-get-next-page-{search}-{page}", ButtonStyle.Success, null, null, (page + 1) * emoteResult.PageSize > emoteResult.TotalEmotesFound, row);

                var msg2 = await Context.Channel.SendMessageAsync("", false, builder.Build(), null, null, null, builderComponent.Build());
            }
            catch (HttpException ex)
            {
                foreach (var error in ex.Errors)
                {
                    if (error.Errors.Any(i => i.Code == "BUTTON_COMPONENT_INVALID_EMOJI"))
                    {
                        var parts = error.Path.Split('.');

                        int error_row    = Convert.ToInt32(Regex.Replace(parts[0], "[^0-9]", ""));
                        int error_column = Convert.ToInt32(Regex.Replace(parts[1], "[^0-9]", ""));


                        var brokenEmote = emoteResult.EmoteList.Skip(error_row * columns + error_column).First();
                        EmoteDBManager.Instance().ChangeValidStatus(brokenEmote.Key, false);
                    }
                }

                // call yourself again to retry ->
                if (secondTry == false)
                {
                    await EmoteFavourite(search, true);
                }

                // Some emotes may no lonver be valid -> db entry to invalidate the emote
            }
            catch (Exception ex)
            {
                await Context.Channel.SendMessageAsync(ex.ToString(), false);
            }
        }
        public async Task ViewFavouriteEmotes()
        {
            var userFavEmotes = DatabaseManager.EmoteDatabaseManager.GetFavouriteEmotes(Context.User.Id);
            var emotes        = DatabaseManager.EmoteDatabaseManager.GetDiscordEmotes(userFavEmotes.Select(i => i.DiscordEmoteId).ToList());

            string fileName = $"emote_fav_{new Random().Next(int.MaxValue)}.png";

            // Show the user specified emote name
            foreach (var emote in emotes)
            {
                emote.EmoteName = userFavEmotes.SingleOrDefault(i => i.DiscordEmoteId == emote.DiscordEmoteId)?.Name ?? "N/A";
            }

            // TODO List guild emotes

            var emoteDrawing = DiscordHelper.DrawPreviewImage(emotes, new List <GuildEmote>(), 10, 10);

            DrawingHelper.SaveToDisk(Path.Combine(Program.ApplicationSetting.CDNPath, fileName), emoteDrawing.Bitmap);

            EmbedBuilder builder = new EmbedBuilder()
            {
                ImageUrl    = $"https://cdn.battlerush.dev/{fileName}",
                Description = "Your Favourited emotes",
                Color       = Color.DarkRed,
                Title       = "Image full size",
                Footer      = new EmbedFooterBuilder()
                {
                    Text = "" + " Page: " + -1
                },
                ThumbnailUrl = "https://cdn.battlerush.dev/bot_xmas.png",
                Timestamp    = DateTimeOffset.Now,
                Url          = $"https://cdn.battlerush.dev/{fileName}",
            };

            builder.WithAuthor(Context.User);

            // COPY OF OTHER FAV FUNCTION
            var builderComponent = new ComponentBuilder();

            int rows    = 4;
            int columns = 5;

            int row = 0;
            int col = 0;

            foreach (var emote in emotes)
            {
                if (emote.IsValid && false)
                {
                    builderComponent.WithButton(emote.EmoteName, $"emote-del-{emote.DiscordEmoteId}", ButtonStyle.Primary, Emote.Parse($"<:{emote.EmoteName}:{emote.DiscordEmoteId}>"), null, false, row);
                }
                else
                {
                    builderComponent.WithButton(emote.EmoteName, $"emote-del-{emote.DiscordEmoteId}", ButtonStyle.Danger, null, null, false, row);
                }

                col++;

                if (col == columns)
                {
                    row++;
                    col = 0;
                }
            }

            // Start fresh row for paging
            if (col > 0)
            {
                row++;
            }

            //builderComponent.WithButton("Prev <", $"emote-fav-get-prev-page-{search}-{page}", ButtonStyle.Danger, null, null, page == 0, row);
            //builderComponent.WithButton("> Next", $"emote-fav-get-next-page-{search}-{page}", ButtonStyle.Success, null, null, (page + 1) * emoteResult.PageSize > emoteResult.TotalEmotesFound, row);

            var msg2 = await Context.Channel.SendMessageAsync("", false, builder.Build(), null, null, null, builderComponent.Build());
        }
Exemple #22
0
        public async Task <CommandResult> InviteNextPlayerAsync(Invite invite)
        {
            IAsyncEnumerable <UserInGuild> list = guildData.GetSortedList().ToAsyncEnumerable();

            if (invite.InviteRole is ulong roleId)
            {
                list = list.WhereAwait(async x =>
                {
                    var restGuildUser = await restClient.GetGuildUserAsync(guildId, x.UserId);

                    var hasRole = restGuildUser.RoleIds.Contains(roleId);

                    return(hasRole == invite.IsInviteRolePositive);
                });
            }

            if (!await list.AnyAsync())
            {
                return(CommandResult.FromError($"Could not invite additional player. List is empty."));
            }

            string message;

            try
            {
                message = string.Format(guildData.DMMessageFormat, invite.FormatData);
            }
            catch (Exception)
            {
                return(CommandResult.FromError("The arguments had the wrong format"));
            }

            StringBuilder warnings = new StringBuilder();

            // Send invites
            var player = await list.FirstAsync();

            player.IsInWaitingList = false;
            player.PlayCount++;

            dataContext.Update(player);
            dataContext.SaveChanges();

            var restGuildUser = await restClient.GetGuildUserAsync(guildId, player.UserId);

            try
            {
                ComponentBuilder componentBuilder = new ComponentBuilder();
                componentBuilder.WithButton("Yes", customId: $"joinYes;{invite.Id}");
                componentBuilder.WithButton("No", customId: $"joinNo;{invite.Id}");


                var userMessage = await restGuildUser.SendMessageAsync($"Are you ready to join? You have 1 minute to respond.", component : componentBuilder.Build());


                invite.InvitedUsers.Add(new InvitedUser
                {
                    Invite              = invite,
                    InviteTime          = DateTime.Now,
                    DmQuestionMessageId = userMessage.Id,
                    User = player
                });

                dataContext.Update(invite);
                dataContext.SaveChanges();
            }
            catch (Exception ex)
            {
                warnings.AppendLine($"Could not invite {restGuildUser.Mention}. Exception: {ex.Message}");
            }

            await this.dataContext.SaveChangesAsync();

            return(CommandResult.FromSuccess("Players have been invited." + (warnings.Length > 0 ? "\r\n" + warnings.ToString() : "")));
        }
Exemple #23
0
        public async Task <(CommandResult commandResult, Invite?invite)> GetInvite(string[] arguments, int numberOfPlayers, ulong?inviteRole = null, bool?isInviteRolePositive = null, bool removeFromList = true)
        {
            IAsyncEnumerable <UserInGuild> asyncList = guildData.GetSortedList().ToAsyncEnumerable();

            if (inviteRole is ulong roleId)
            {
                asyncList = asyncList.WhereAwait(async x =>
                {
                    var restGuildUser = await restClient.GetGuildUserAsync(guildId, x.UserId);

                    var hasRole = restGuildUser.RoleIds.Contains(roleId);

                    return(hasRole == isInviteRolePositive);
                });
            }

            var list = await asyncList.ToListAsync();

            if (list.Count < numberOfPlayers)
            {
                return(CommandResult.FromError($"Did not send invites. There are only {list.Count} players in the list."), null);
            }

            string message;

            try
            {
                message = string.Format(guildData.DMMessageFormat, arguments);
            }
            catch (Exception)
            {
                return(CommandResult.FromError("The arguments had the wrong format"), null);
            }

            var invite = new Invite
            {
                FormatData           = arguments,
                Guild                = guildData,
                InvitedUsers         = new List <InvitedUser>(),
                InviteTime           = DateTime.Now,
                NumberOfInvitedUsers = numberOfPlayers,
                InviteRole           = inviteRole,
                IsInviteRolePositive = isInviteRolePositive
            };

            dataContext.Invites.Add(invite);
            dataContext.SaveChanges();

            StringBuilder warnings = new StringBuilder();

            // Send invites
            for (int i = 0; i < numberOfPlayers; i++)
            {
                var player = list[i];

                player.IsInWaitingList = false;
                player.PlayCount++;

                dataContext.Update(player);
                dataContext.SaveChanges();

                var restGuildUser = await restClient.GetGuildUserAsync(guildId, player.UserId);

                try
                {
                    ComponentBuilder componentBuilder = new ComponentBuilder();
                    componentBuilder.WithButton("Yes", customId: $"joinYes;{invite.Id}");
                    componentBuilder.WithButton("No", customId: $"joinNo;{invite.Id}");


                    var userMessage = await restGuildUser.SendMessageAsync($"Are you ready to join? You have 1 minute to respond.", component : componentBuilder.Build());


                    InvitedUser invitedUser = new InvitedUser
                    {
                        Invite              = invite,
                        InviteTime          = DateTime.Now,
                        DmQuestionMessageId = userMessage.Id,
                        User = player
                    };

                    dataContext.InvitedUsers.Add(invitedUser);
                }
                catch (Exception ex)
                {
                    warnings.AppendLine($"Could not invite {restGuildUser?.Mention ?? player.Name}. Exception: {ex.Message}");
                }
            }

            this.dataContext.Update(invite);

            await this.dataContext.SaveChangesAsync();

            return(CommandResult.FromSuccess("Players have been invited." + (warnings.Length > 0 ? "\r\n" + warnings.ToString() : "")), invite);
        }
        // Search Rotten Tomatoes for movies and create a selection
        public static async Task SearchRottenTomatoes(SocketSlashCommand command)
        {
            // Get our input from the interaction
            var search = command.Data.Options.ElementAt(0).Value.ToString();

            // Make a list of results
            var resultItems = new List <SearchResultItem>();

            // Get the website html
            var data = await WebUtils.DownloadString($"https://www.rottentomatoes.com/search?search={search}");

            //If there's no result, tell the user and then stop.
            if (data.Contains("Sorry, no results found for"))
            {
                await command.FollowupAsync(embed : new EmbedBuilder()
                                            .WithTitle("Rotten Tomatoes Search")
                                            .WithDescription($"Sorry, no results were found for \"{search}\"\n\nTry reformatting your search if the title contains colons, hyphens, etc.")
                                            .WithColor(EmbedUtils.Red)
                                            .Build());

                return;
            }

            // Slim down the data
            data = data
                   .CutBefore(
                "<search-page-result slot=\"movie\" skeleton=\"panel\" type=\"movie\" data-qa=\"search-result\">")
                   .CutBeforeAndAfter("<ul slot=\"list\">", "</ul>");

            do
            {
                var temp = data.CutAfter("</search-page-media-row>");
                resultItems.Add(new SearchResultItem(new Movie(temp)));

                data = data.CutBefore("</search-page-media-row>");
            } while (data.Contains("search-page-media-row"));

            var buttons = new ComponentBuilder();

            for (int i = 0; i < (resultItems.Count <= 5 ? resultItems.Count : 5); i++)
            {
                var text = $"{resultItems[i].Movie.CriticScore} {resultItems[i].Movie.Name} ({resultItems[i].Movie.Year})";

                // Decode the HTML
                text = HttpUtility.HtmlDecode(text);

                // Button Labels can only be 80 characters
                if (text.Length > 80)
                {
                    text = $"{text.Substring(0, 77)}...";
                }

                var customId = resultItems[i].Movie.Url.CutBefore("/m/");

                // Custom IDs can only be 100 characters (skip it otherwise)
                if (customId.Length > 100)
                {
                    continue;
                }

                buttons.WithButton(text, customId: customId, ButtonStyle.Danger, row: i, emote: Emote.Parse(resultItems[i].Movie.CriticScoreIcon));
            }

            await command.FollowupAsync("Please select a result or search again.", component : buttons.Build());
        }