Skip to content

Commit aa42515

Browse files
committed
Added /hmhreplay command
1 parent 5beadca commit aa42515

5 files changed

Lines changed: 89 additions & 4 deletions

File tree

src/config/config.go.example

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ var Config = HMNConfig{
6868

6969
GuildID: "",
7070
MemberRoleID: "",
71+
HMHReplayRoleID: "",
7172
ShowcaseChannelID: "",
7273
JamChannelID: "",
7374
LibraryChannelID: "",

src/config/types.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ type DiscordConfig struct {
8484

8585
GuildID string
8686
MemberRoleID string
87+
HMHReplayRoleID string
8788
ShowcaseChannelID string
8889
JamChannelID string
8990
LibraryChannelID string

src/discord/commands.go

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"errors"
66
"fmt"
77

8+
"git.handmade.network/hmn/hmn/src/config"
89
"git.handmade.network/hmn/hmn/src/hmndata"
910

1011
"git.handmade.network/hmn/hmn/src/db"
@@ -18,6 +19,8 @@ const SlashCommandProfile = "profile"
1819
const ProfileOptionUser = "user"
1920

2021
const SlashCommandManifesto = "manifesto"
22+
const SlashCommandHMHReplay = "hmhreplay"
23+
const HMHReplayOptionToggle = "toggle"
2124

2225
// User command names
2326
const UserCommandProfile = "HMN Profile"
@@ -54,6 +57,22 @@ func (bot *botInstance) createApplicationCommands(ctx context.Context) {
5457
Name: SlashCommandManifesto,
5558
Description: "Read the Handmade manifesto",
5659
}))
60+
61+
dmPermission := false
62+
doOrWarn(CreateGuildApplicationCommand(ctx, CreateGuildApplicationCommandRequest{
63+
Type: ApplicationCommandTypeChatInput,
64+
Name: SlashCommandHMHReplay,
65+
Description: "Join the Handmade Hero Replay",
66+
DMPermission: &dmPermission,
67+
Options: []ApplicationCommandOption{
68+
{
69+
Type: ApplicationCommandOptionTypeBoolean,
70+
Name: HMHReplayOptionToggle,
71+
Description: "Add or remove the HMH replay role",
72+
Required: false,
73+
},
74+
},
75+
}))
5776
}
5877

5978
func (bot *botInstance) doInteraction(ctx context.Context, i *Interaction) {
@@ -87,6 +106,41 @@ func (bot *botInstance) doInteraction(ctx context.Context, i *Interaction) {
87106
if err != nil {
88107
logging.ExtractLogger(ctx).Error().Err(err).Msg("failed to send manifesto response")
89108
}
109+
case SlashCommandHMHReplay:
110+
join := true
111+
toggleOpt, ok := getInteractionOption(i.Data.Options, HMHReplayOptionToggle)
112+
if ok {
113+
join = toggleOpt.Value.(bool)
114+
}
115+
116+
if join {
117+
logging.ExtractLogger(ctx).Debug().Interface("interaction", i).Msg("Got hmh replay")
118+
err := AddGuildMemberRole(ctx, i.Member.User.ID, config.Config.Discord.HMHReplayRoleID)
119+
if err != nil {
120+
err = sendEphemeralMessageForInteraction(ctx, i, "We failed to set the role. Please inform an admin.")
121+
if err != nil {
122+
logging.ExtractLogger(ctx).Error().Err(err).Msg("failed to send hmh replay add failure response")
123+
}
124+
} else {
125+
err = sendEphemeralMessageForInteraction(ctx, i, "You're in!")
126+
if err != nil {
127+
logging.ExtractLogger(ctx).Error().Err(err).Msg("failed to send hmh replay add response")
128+
}
129+
}
130+
} else {
131+
err := RemoveGuildMemberRole(ctx, i.Member.User.ID, config.Config.Discord.HMHReplayRoleID)
132+
if err != nil {
133+
err = sendEphemeralMessageForInteraction(ctx, i, "We failed to remove the role. Please inform an admin.")
134+
if err != nil {
135+
logging.ExtractLogger(ctx).Error().Err(err).Msg("failed to send hmh replay remove failure response")
136+
}
137+
} else {
138+
err = sendEphemeralMessageForInteraction(ctx, i, "You're out!")
139+
if err != nil {
140+
logging.ExtractLogger(ctx).Error().Err(err).Msg("failed to send hmh replay remove response")
141+
}
142+
}
143+
}
90144
default:
91145
logging.ExtractLogger(ctx).Warn().Str("name", i.Data.Name).Msg("didn't recognize Discord interaction name")
92146
}
@@ -173,6 +227,18 @@ func (bot *botInstance) handleProfileCommand(ctx context.Context, i *Interaction
173227
}
174228
}
175229

230+
func sendEphemeralMessageForInteraction(ctx context.Context, i *Interaction, content string) error {
231+
err := CreateInteractionResponse(ctx, i.ID, i.Token, InteractionResponse{
232+
Type: InteractionCallbackTypeChannelMessageWithSource,
233+
Data: &InteractionCallbackData{
234+
Content: content,
235+
Flags: FlagEphemeral,
236+
},
237+
})
238+
239+
return err
240+
}
241+
176242
func getInteractionOption(opts []ApplicationCommandInteractionDataOption, name string) (ApplicationCommandInteractionDataOption, bool) {
177243
for _, opt := range opts {
178244
if opt.Name == name {

src/discord/payloads.go

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -410,9 +410,10 @@ func GuildFromMap(m interface{}, k string) *Guild {
410410

411411
// https://discord.com/developers/docs/resources/guild#guild-member-object
412412
type GuildMember struct {
413-
User *User `json:"user"`
414-
Nick *string `json:"nick"`
415-
Avatar *string `json:"avatar"`
413+
User *User `json:"user"`
414+
Nick *string `json:"nick"`
415+
Avatar *string `json:"avatar"`
416+
Roles *[]string `json:"roles"`
416417
// more fields not yet handled here
417418
}
418419

@@ -433,9 +434,10 @@ func GuildMemberFromMap(m interface{}, k string) *GuildMember {
433434
}
434435

435436
gm := &GuildMember{
436-
User: UserFromMap(m, "user"),
437+
User: UserFromMap(mmap, "user"),
437438
Nick: maybeStringP(mmap, "nick"),
438439
Avatar: maybeStringP(mmap, "avatar"),
440+
Roles: maybeStringArray(mmap, "roles"),
439441
}
440442

441443
return gm
@@ -1033,3 +1035,17 @@ func maybeArray(m map[string]any, k string) []any {
10331035
}
10341036
return val.([]any)
10351037
}
1038+
1039+
func maybeStringArray(m map[string]any, k string) *[]string {
1040+
val, ok := m[k]
1041+
if ok {
1042+
var result []string
1043+
for _, v := range val.([]any) {
1044+
result = append(result, v.(string))
1045+
}
1046+
1047+
return &result
1048+
} else {
1049+
return nil
1050+
}
1051+
}

src/discord/rest.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -556,6 +556,7 @@ type CreateGuildApplicationCommandRequest struct {
556556
Options []ApplicationCommandOption `json:"options"` // the parameters for the command
557557
DefaultPermission *bool `json:"default_permission"` // whether the command is enabled by default when the app is added to a guild
558558
Type ApplicationCommandType `json:"type"` // the type of command, defaults 1 if not set
559+
DMPermission *bool `json:"dm_permission"` // Technically deprecated, but needs to be set to false in order to get member info in the interaction object
559560
}
560561

561562
// See https://discord.com/developers/docs/interactions/application-commands#create-guild-application-command

0 commit comments

Comments
 (0)