|
| 1 | +package main |
| 2 | + |
| 3 | +import ( |
| 4 | + _ "embed" |
| 5 | + "errors" |
| 6 | + "fmt" |
| 7 | + "github.com/disgoorg/disgo/discord" |
| 8 | + "github.com/disgoorg/disgo/handler" |
| 9 | + "github.com/disgoorg/disgo/rest" |
| 10 | + "github.com/disgoorg/json" |
| 11 | + "log/slog" |
| 12 | +) |
| 13 | + |
| 14 | +var pingCommand = discord.SlashCommandCreate{ |
| 15 | + Name: "ping", |
| 16 | + Description: "Ping...... pong!", |
| 17 | + DefaultMemberPermissions: json.NewNullablePtr(discord.PermissionManageGuild), |
| 18 | +} |
| 19 | + |
| 20 | +func pingHandler(ev *handler.CommandEvent) error { |
| 21 | + return ev.CreateMessage(discord.MessageCreate{ |
| 22 | + Content: "Pong!", |
| 23 | + Flags: discord.MessageFlagEphemeral, |
| 24 | + }) |
| 25 | +} |
| 26 | + |
| 27 | +var createReportButtonCommand = discord.SlashCommandCreate{ |
| 28 | + Name: "create-report-button", |
| 29 | + Description: "Create a button", |
| 30 | + DefaultMemberPermissions: json.NewNullablePtr(discord.PermissionManageGuild), |
| 31 | + DMPermission: ref(false), |
| 32 | + Options: []discord.ApplicationCommandOption{ |
| 33 | + discord.ApplicationCommandOptionString{ |
| 34 | + Name: "label", |
| 35 | + Description: "The label on the button to create", |
| 36 | + Required: true, |
| 37 | + }, |
| 38 | + discord.ApplicationCommandOptionString{ |
| 39 | + Name: "button-color", |
| 40 | + Description: "The color of the button", |
| 41 | + Required: false, |
| 42 | + Choices: []discord.ApplicationCommandOptionChoiceString{ |
| 43 | + { |
| 44 | + Name: "red", |
| 45 | + Value: "red", |
| 46 | + }, |
| 47 | + { |
| 48 | + Name: "green", |
| 49 | + Value: "green", |
| 50 | + }, |
| 51 | + { |
| 52 | + Name: "blue", |
| 53 | + Value: "blue", |
| 54 | + }, |
| 55 | + { |
| 56 | + Name: "grey", |
| 57 | + Value: "grey", |
| 58 | + }, |
| 59 | + }, |
| 60 | + }, |
| 61 | + discord.ApplicationCommandOptionRole{ |
| 62 | + Name: "role", |
| 63 | + Description: "The role that should be tagged when submitting a report", |
| 64 | + Required: false, |
| 65 | + }, |
| 66 | + }, |
| 67 | +} |
| 68 | + |
| 69 | +var stringToButtonStyle = map[string]discord.ButtonStyle{ |
| 70 | + "red": discord.ButtonStyleDanger, |
| 71 | + "green": discord.ButtonStyleSuccess, |
| 72 | + "blue": discord.ButtonStylePrimary, |
| 73 | + "grey": discord.ButtonStyleSecondary, |
| 74 | +} |
| 75 | + |
| 76 | +func createReportButtonHandler(ev *handler.CommandEvent) error { |
| 77 | + data := ev.SlashCommandInteractionData() |
| 78 | + label := data.String("label") |
| 79 | + color := data.String("button-color") |
| 80 | + role := data.Role("role") |
| 81 | + if color == "" { |
| 82 | + color = "blue" |
| 83 | + } |
| 84 | + |
| 85 | + return ev.CreateMessage(discord.MessageCreate{ |
| 86 | + Components: []discord.ContainerComponent{ |
| 87 | + discord.ActionRowComponent{ |
| 88 | + discord.NewButton( |
| 89 | + stringToButtonStyle[color], |
| 90 | + label, |
| 91 | + fmt.Sprintf("/report-button/%d", uint64(role.ID)), |
| 92 | + "", |
| 93 | + ), |
| 94 | + }, |
| 95 | + }, |
| 96 | + }) |
| 97 | +} |
| 98 | + |
| 99 | +func reportButtonHandler(ev *handler.ComponentEvent) error { |
| 100 | + slog.Info("Received report button interaction", |
| 101 | + "user_id", ev.User().ID, |
| 102 | + "user_name", ev.User().Username, |
| 103 | + "guild_id", *ev.GuildID(), |
| 104 | + "channel_id", ev.Channel().ID(), |
| 105 | + ) |
| 106 | + role := ev.Variables["role"] |
| 107 | + customID := fmt.Sprintf("/report-modal/%s", role) |
| 108 | + slog.Info("Sending modal", "custom_id", customID) |
| 109 | + modal := discord.NewModalCreateBuilder(). |
| 110 | + SetCustomID(customID). |
| 111 | + SetTitle("Report"). |
| 112 | + AddActionRow( |
| 113 | + discord.NewShortTextInput("title", "Subject"). |
| 114 | + WithPlaceholder("Subject or topic of the report"). |
| 115 | + WithRequired(true). |
| 116 | + WithMinLength(5). |
| 117 | + WithMaxLength(72)). |
| 118 | + AddActionRow( |
| 119 | + discord.NewParagraphTextInput("description", "Description"). |
| 120 | + WithPlaceholder( |
| 121 | + "Report information\n\n" + |
| 122 | + "Markdown is supported.\n" + |
| 123 | + "More details, images, etc. can be submitted afterwards."). |
| 124 | + WithRequired(true). |
| 125 | + WithMinLength(24), |
| 126 | + ). |
| 127 | + Build() |
| 128 | + |
| 129 | + err := ev.Modal(modal) |
| 130 | + if err != nil { |
| 131 | + slog.Error("Failed to send modal", "err", err) |
| 132 | + |
| 133 | + var restErr rest.Error |
| 134 | + if errors.As(err, &restErr) { |
| 135 | + println(string(restErr.RsBody)) |
| 136 | + } |
| 137 | + } else { |
| 138 | + slog.Info("Sent modal") |
| 139 | + } |
| 140 | + return err |
| 141 | +} |
| 142 | + |
| 143 | +func reportModalHandler(ev *handler.ModalEvent) error { |
| 144 | + _ = ev.DeferCreateMessage(true) |
| 145 | + role := ev.Variables["role"] |
| 146 | + title := ev.Data.Text("title") |
| 147 | + description := ev.Data.Text("description") |
| 148 | + |
| 149 | + thread, err := ev.Client().Rest().CreateThread( |
| 150 | + ev.Channel().ID(), |
| 151 | + discord.GuildPrivateThreadCreate{ |
| 152 | + Name: title, |
| 153 | + AutoArchiveDuration: 10080, |
| 154 | + Invitable: false, |
| 155 | + }) |
| 156 | + if err != nil { |
| 157 | + return err |
| 158 | + } |
| 159 | + |
| 160 | + user := ev.User() |
| 161 | + avatarUrl := "" |
| 162 | + if url := user.AvatarURL(); url != nil { |
| 163 | + avatarUrl = *url |
| 164 | + } else if url := user.DefaultAvatarURL(); url != "" { |
| 165 | + avatarUrl = url |
| 166 | + } |
| 167 | + embed := discord.NewEmbedBuilder(). |
| 168 | + SetTitle(title). |
| 169 | + SetDescription(description). |
| 170 | + SetColor(0x4848FF). |
| 171 | + SetAuthor(user.Username, "", avatarUrl). |
| 172 | + Build() |
| 173 | + |
| 174 | + message, err := ev.Client().Rest().CreateMessage( |
| 175 | + thread.ID(), |
| 176 | + discord.MessageCreate{ |
| 177 | + Content: fmt.Sprintf("%s%s", |
| 178 | + iif(role != "0", fmt.Sprintf("<@&%s> ", role), ""), |
| 179 | + user.Mention(), |
| 180 | + ), |
| 181 | + Embeds: []discord.Embed{embed}, |
| 182 | + }) |
| 183 | + if err != nil { |
| 184 | + return err |
| 185 | + } |
| 186 | + |
| 187 | + _, err = ev.CreateFollowupMessage(discord.MessageCreate{ |
| 188 | + Content: "Report created!", |
| 189 | + Flags: discord.MessageFlagEphemeral, |
| 190 | + Components: []discord.ContainerComponent{ |
| 191 | + discord.ActionRowComponent{ |
| 192 | + discord.NewLinkButton("View", message.JumpURL()), |
| 193 | + }, |
| 194 | + }, |
| 195 | + }) |
| 196 | + return err |
| 197 | +} |
| 198 | + |
| 199 | +var helpCommand = discord.SlashCommandCreate{ |
| 200 | + Name: "help", |
| 201 | + Description: "Show help for setting up the bot", |
| 202 | + DefaultMemberPermissions: json.NewNullablePtr(discord.PermissionManageGuild), |
| 203 | + DMPermission: ref(true), |
| 204 | +} |
| 205 | + |
| 206 | +//go:embed help.md |
| 207 | +var helpText string |
| 208 | + |
| 209 | +func helpHandler(ev *handler.CommandEvent) error { |
| 210 | + isInGuild := true |
| 211 | + if ev.GuildID() == nil { |
| 212 | + isInGuild = false |
| 213 | + } |
| 214 | + |
| 215 | + return ev.CreateMessage(discord.MessageCreate{ |
| 216 | + Content: helpText, |
| 217 | + Embeds: []discord.Embed{ |
| 218 | + discord.NewEmbedBuilder(). |
| 219 | + SetTitle("Modmail Help"). |
| 220 | + SetDescription(helpText). |
| 221 | + SetColor(0x20FF20). |
| 222 | + Build(), |
| 223 | + }, |
| 224 | + Flags: iif(isInGuild, discord.MessageFlagEphemeral, 0), |
| 225 | + }) |
| 226 | +} |
| 227 | + |
| 228 | +func iif[T any](cond bool, ifTrue, ifFalse T) T { |
| 229 | + if cond { |
| 230 | + return ifTrue |
| 231 | + } |
| 232 | + return ifFalse |
| 233 | +} |
| 234 | + |
| 235 | +func ref[T any](v T) *T { |
| 236 | + return &v |
| 237 | +} |
0 commit comments