Use a dropdown and a Create ticket button on the ticket panel, in orange

The panel is now one category dropdown and a Create ticket button
instead of a button per category. Discord doesn't send the dropdown's
value with a button click, so each member's pick is remembered in
memory for 15 minutes (per guild and member, capped). Panels posted
before keep working until they're reposted. Every ticket embed is
orange, closed tickets included.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
FernandoJVideiraandClaude Opus 5.5 committed 2026-10-21 11:58:19 +01:00
1 parent e453a9ba94
commit e10e1f7a86
8 files changed
+178 -50

No files matched your search

+17 -28
View File
@@ -15,8 +15,9 @@ import (
// Custom IDs. Everything starts with "tickets:" so the interaction router can
// hand it to this package.
const (
idOpenPrefix = "tickets:open:" // panel button, + category ID
idSelect = "tickets:select" // panel dropdown (many categories)
idOpenPrefix = "tickets:open:" // older panels: one button per category, + category ID
idSelect = "tickets:select" // panel dropdown
idCreate = "tickets:create" // panel "Create ticket" button
idOpenFormPrefix = "tickets:openform:" // opening form, + category ID
idClaim = "tickets:claim"
idClose = "tickets:close"
@@ -42,8 +43,8 @@ func parseEmoji(s string) *discordgo.ComponentEmoji {
}
// BuildPanel is the message members open tickets from: an embed with the
// guild's text and one button per category, or a dropdown once there are
// more categories than fit comfortably in a row.
// guild's text and each category's description, a dropdown to pick the
// category, and a Create ticket button that opens the form for that pick.
func BuildPanel(s *ticketrepo.Settings, cats []ticketrepo.Category) (*discordgo.MessageEmbed, []discordgo.MessageComponent) {
embed := &discordgo.MessageEmbed{
Title: clip(s.PanelTitle, 256),
@@ -54,27 +55,7 @@ func BuildPanel(s *ticketrepo.Settings, cats []ticketrepo.Category) (*discordgo.
cats = cats[:maxCategories]
}
if len(cats) <= maxPanelButtons {
var buttons []discordgo.MessageComponent
for _, c := range cats {
buttons = append(buttons, discordgo.Button{
Label: clip(c.Name, 80),
Style: discordgo.PrimaryButton,
CustomID: idOpenPrefix + id(c.ID),
Emoji: parseEmoji(c.Emoji),
})
}
// With few categories their descriptions go in the embed, since a
// button has no room for one.
for _, c := range cats {
if c.Description != "" {
embed.Fields = append(embed.Fields, &discordgo.MessageEmbedField{Name: clip(c.Name, 256), Value: clip(c.Description, 1024)})
}
}
return embed, []discordgo.MessageComponent{discordgo.ActionsRow{Components: buttons}}
}
var opts []discordgo.SelectMenuOption
opts := make([]discordgo.SelectMenuOption, 0, len(cats))
for _, c := range cats {
opts = append(opts, discordgo.SelectMenuOption{
Label: clip(c.Name, 100),
@@ -82,10 +63,18 @@ func BuildPanel(s *ticketrepo.Settings, cats []ticketrepo.Category) (*discordgo.
Description: clip(c.Description, 100),
Emoji: parseEmoji(c.Emoji),
})
if c.Description != "" {
embed.Fields = append(embed.Fields, &discordgo.MessageEmbedField{Name: clip(c.Name, 256), Value: clip(c.Description, 1024)})
}
}
return embed, []discordgo.MessageComponent{
discordgo.ActionsRow{Components: []discordgo.MessageComponent{
discordgo.SelectMenu{CustomID: idSelect, Placeholder: "Choose what you need help with", Options: opts},
}},
discordgo.ActionsRow{Components: []discordgo.MessageComponent{
discordgo.Button{Label: "Create ticket", Style: discordgo.PrimaryButton, CustomID: idCreate, Emoji: &discordgo.ComponentEmoji{Name: "🎫"}},
}},
}
return embed, []discordgo.MessageComponent{discordgo.ActionsRow{Components: []discordgo.MessageComponent{
discordgo.SelectMenu{CustomID: idSelect, Placeholder: "Choose what you need help with", Options: opts},
}}}
}
// PostPanel posts the panel in the ticket channel, or updates the one it