-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathCustomButtonModule.cs
87 lines (73 loc) · 3.37 KB
/
CustomButtonModule.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
using System;
using System.Threading.Tasks;
using Discord;
using Discord.Commands;
using ExampleBot.Extensions;
using Fergun.Interactive;
using Fergun.Interactive.Selection;
namespace ExampleBot.Modules;
[Group("custom")]
public partial class CustomModule : ModuleBase
{
// Sends a selection of buttons, where each option has its own button style/color.
[Command("button", RunMode = RunMode.Async)]
public async Task CustomButtonSelectionAsync()
{
// To be able to create buttons with custom colors, we need to create a custom selection and a builder for that new selection.
// See ButtonSelectionBuilder<T> and ButtonSelection<T> (below) for more information.
// A ButtonSelection uses ButtonOption<T>s, specifically created for this custom selection.
var options = new ButtonOption<string>[]
{
new("Primary", ButtonStyle.Primary),
new("Secondary", ButtonStyle.Secondary),
new("Success", ButtonStyle.Success),
new("Danger", ButtonStyle.Danger)
};
var pageBuilder = new PageBuilder()
.WithDescription("Button selection")
.WithRandomColor();
var buttonSelection = new ButtonSelectionBuilder<string>()
.WithOptions(options)
.WithStringConverter(x => x.Option)
.WithSelectionPage(pageBuilder)
.AddUser(Context.User)
.Build();
await _interactive.SendSelectionAsync(buttonSelection, Context.Channel);
}
// Custom selection builder for ButtonSelections
public class ButtonSelectionBuilder<T> : BaseSelectionBuilder<ButtonSelection<T>, ButtonOption<T>, ButtonSelectionBuilder<T>>
{
// Since this selection specifically created for buttons, it makes sense to make this option the default.
public override InputType InputType => InputType.Buttons;
// We must override the Build method
public override ButtonSelection<T> Build() => new(this);
}
// Custom selection where you can override the default button style/color
public class ButtonSelection<T>(ButtonSelectionBuilder<T> builder) : BaseSelection<ButtonOption<T>>(builder)
{
// 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 = label;
builder.WithButton(button);
}
return builder;
}
}
public record ButtonOption<T>(T Option, ButtonStyle Style); // An option with a style
}