Skip to content

Commit

Permalink
feat(secret santa): added nudging match
Browse files Browse the repository at this point in the history
  • Loading branch information
Kesuaheli committed Nov 23, 2024
1 parent 0841805 commit 9358940
Show file tree
Hide file tree
Showing 7 changed files with 213 additions and 13 deletions.
4 changes: 4 additions & 0 deletions config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ event:
name: 🗑️
#id:
#animated: true
secretsanta.invite.nudge_match:
name: 👉
#id:
#animated: true

webserver:
favicon: webserver/favicon.png
Expand Down
12 changes: 11 additions & 1 deletion data/lang/de.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -145,13 +145,23 @@ discord.command:
msg.invite.show_match.title: Dein Partner ist %s
msg.invite.show_match.description: Bitte breite ein Wichtelgeschenk vor und schicke es ihm/ihr. Halte dich dabei an unsere vereinbarten Regeln.
msg.invite.show_match.address: Adresse
msg.invite.show_match.address_not_set: Dein Partner hat noch keine Adresse eingetragen
msg.invite.show_match.address_not_set: Dein Partner hat noch keine Adresse eingetragen.

Falls schon einige Tage vergangen sind, kannst du den "Anstupsen" Knopf drücken. Dein Partner bekommt daraufhin einen Hinweis die Adresse einzutragen.
msg.invite.show_match.nudge_description: Wenn du vermutest, dass die eingetragene Adresse einen Fehler enthält, kannst du unten den den "Anstupsen" Knopf drücken. Dein Partner bekommt daraufhin einen Hinweis die Adresse zu aktualisieren.
msg.invite.set_address: Deine Adresse wurde eingetragen
msg.invite.button.set_address: Deine Adresse eintragen
msg.invite.set_address.changed: Deine Adresse wurde aktualisiert auf
msg.invite.set_address.not_changed: Deine Adresse wurde nicht aktualisiert, weil es die gleiche ist wie vorher.
msg.invite.set_address.match_updated: Dein Partner hat gerade seine/ihre Adresse aktualisiert. Das ist nur um dich zu informieren - Boop Boop 🤖
msg.invite.button.delete: Schließen
msg.invite.button.nudge_match: Anstupsen
msg.invite.nudge_match.confirm: Bist du sicher, dass du deinen Partner anstupsen möchtest?

Bestätige, dass du deinen Partner anstupsen möchtest. Er/Sie bekommt dann einen Hinweis die Adresse zu aktualisieren.
msg.invite.nudge_match.success: Dein Partner wurde erfolgreich angestupst
msg.invite.nudge_match.pending: Du hast deinen Partner angestupst. Ich melde mich, sobald er/sie die Adresse aktualisiert hat.
msg.invite.nudge_received: Dein Wichtel hat dich anstupst. Bitte trage eine Adresse ein falls du es noch nicht gemacht hast oder überprüfe deine bereits eingetragene Adresse ob sie eventuell einen Tippfehler oder ähnliches enthält.

msg.invite.modal.set_address.title: Deine Adresse eintragen
msg.invite.modal.set_address.label: Deine Adresse wird deinem Wichtel angezeigt
Expand Down
12 changes: 11 additions & 1 deletion data/lang/en.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -145,13 +145,23 @@ discord.command:
msg.invite.show_match.title: Your partner is %s
msg.invite.show_match.description: Please prepare and send them a secret gift according to our agreed rules.
msg.invite.show_match.address: Address
msg.invite.show_match.address_not_set: Your partner has not set an address yet
msg.invite.show_match.address_not_set: Your partner has not set an address yet.

If some days passed, you can click the "Nudge" button below. Your partner will receive a notification saying that they enter their address.
msg.invite.show_match.nudge_description: If you think the entered address is wrong, you can click the "Nudge" button below. Your partner will receive a notification saying that they should update their address.
msg.invite.set_address: Your address is set
msg.invite.button.set_address: Set your address
msg.invite.set_address.changed: Your address was updated to
msg.invite.set_address.not_changed: Your address was not updated, because it is the same as before.
msg.invite.set_address.match_updated: Your partner just updated their address. This is just to inform you - Beep Boop 🤖
msg.invite.button.delete: Close
msg.invite.button.nudge_match: Nudge
msg.invite.nudge_match.confirm: Are you sure you want to nudge your partner?

Please confirm that you want to nudge your partner. They will receive a notification that they should update their address.
msg.invite.nudge_match.success: Your partner was nudged!
msg.invite.nudge_match.pending: You nudged your partner. I will notify you, when they updated their address.
msg.invite.nudge_received: Your santa nudged you. Please enter an address if you haven't done it yet or check your already entered address for any typos.

msg.invite.modal.set_address.title: Set your address
msg.invite.modal.set_address.label: Your address will be shown your secret santa
Expand Down
106 changes: 97 additions & 9 deletions modules/secretsanta/handleComponentInvite.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"cake4everybot/data/lang"
"cake4everybot/util"
"fmt"
"strings"

"github.com/bwmarrin/discordgo"
)
Expand All @@ -16,6 +17,11 @@ func (c Component) handleInvite(ids []string) {
case "set_address":
c.handleInviteSetAddress(ids)
return
case "nudge_match":
c.handleInviteNudgeMatch(ids)
case "confirm_nudge":
c.handleInviteConfirmNudge(ids)
return
case "delete":
err := c.Session.ChannelMessageDelete(c.Interaction.ChannelID, c.Interaction.Message.ID)
if err != nil {
Expand Down Expand Up @@ -51,16 +57,26 @@ func (c Component) handleInviteShowMatch(ids []string) {
e := util.AuthoredEmbed(c.Session, player.Match.Member, tp+"display")
e.Title = fmt.Sprintf(lang.GetDefault(tp+"msg.invite.show_match.title"), player.Match.Member.DisplayName())
e.Description = lang.GetDefault(tp + "msg.invite.show_match.description")
e.Color = 0x690042
e.Fields = append(e.Fields, &discordgo.MessageEmbedField{
Name: lang.GetDefault(tp + "msg.invite.show_match.address"),
Value: fmt.Sprintf("```\n%s\n```", player.Match.Address),
Value: fmt.Sprintf("```\n%s\n```\n%s", player.Match.Address, lang.GetDefault(tp+"msg.invite.show_match.nudge_description")),
})
if player.Match.Address == "" {
e.Fields[0].Value = lang.GetDefault(tp + "msg.invite.show_match.address_not_set")
}

util.SetEmbedFooter(c.Session, tp+"display", e)
c.ReplyHiddenEmbed(e)
c.ReplyComponentsHiddenEmbed(
[]discordgo.MessageComponent{discordgo.ActionsRow{Components: []discordgo.MessageComponent{
util.CreateButtonComponent(
fmt.Sprintf("secretsanta.invite.nudge_match.%s", c.Interaction.GuildID),
lang.GetDefault(tp+"msg.invite.button.nudge_match"),
discordgo.SecondaryButton,
util.GetConfigComponentEmoji("secretsanta.invite.nudge_match"),
),
}}},
e)
}

func (c Component) handleInviteSetAddress(ids []string) {
Expand All @@ -77,13 +93,8 @@ func (c Component) handleInviteSetAddress(ids []string) {
return
}

var player *player
for _, p := range players {
if p.User.ID == c.Interaction.User.ID {
player = p
}
}
if player == nil {
player, ok := players[c.Interaction.User.ID]
if !ok {
log.Printf("ERROR: could not find player %s in guild %s: %+v", c.Interaction.User.ID, c.Interaction.GuildID, c.Interaction.User.ID)
c.ReplyError()
return
Expand All @@ -100,3 +111,80 @@ func (c Component) handleInviteSetAddress(ids []string) {
},
}})
}

func (c Component) handleInviteNudgeMatch(ids []string) {
c.ReplyComponentsHiddenSimpleEmbedUpdate(
[]discordgo.MessageComponent{discordgo.ActionsRow{Components: []discordgo.MessageComponent{
util.CreateButtonComponent(
"secretsanta.invite.confirm_nudge."+strings.Join(ids, "."),
lang.GetDefault(tp+"msg.invite.button.nudge_match"),
discordgo.PrimaryButton,
util.GetConfigComponentEmoji("secretsanta.invite.nudge_match"),
),
}}},
0x690042,
lang.GetDefault(tp+"msg.invite.nudge_match.confirm"))
}

func (c Component) handleInviteConfirmNudge(ids []string) {
c.Interaction.GuildID = util.ShiftL(ids)
players, err := c.getPlayers()
if err != nil {
log.Printf("ERROR: could not get players: %+v", err)
c.ReplyError()
return
}
if len(players) == 0 {
log.Printf("ERROR: no players in guild %s", c.Interaction.GuildID)
c.ReplyError()
return
}

player, ok := players[c.Interaction.User.ID]
if !ok {
log.Printf("ERROR: could not find player %s in guild %s: %+v", c.Interaction.User.ID, c.Interaction.GuildID, c.Interaction.User.ID)
c.ReplyError()
return
}
player.Match.PendingNudge = true

matchChannel, err := c.Session.UserChannelCreate(player.Match.User.ID)
if err != nil {
log.Printf("ERROR: could not create DM channel with user %s: %+v", player.Match.User.ID, err)
c.ReplyError()
return
}
_, err = c.Session.ChannelMessageEditEmbed(matchChannel.ID, player.Match.MessageID, player.Match.InviteEmbed(c.Session))
if err != nil {
log.Printf("ERROR: could not edit match message embed: %+v", err)
c.ReplyError()
return
}

data := &discordgo.MessageSend{
Content: lang.GetDefault(tp + "msg.invite.nudge_received"),
Reference: &discordgo.MessageReference{MessageID: player.Match.MessageID},
Components: []discordgo.MessageComponent{discordgo.ActionsRow{Components: []discordgo.MessageComponent{
util.CreateButtonComponent(
"secretsanta.invite.delete",
lang.GetDefault(tp+"msg.invite.button.delete"),
discordgo.DangerButton,
util.GetConfigComponentEmoji("secretsanta.invite.delete"),
),
}}},
}
_, err = c.Session.ChannelMessageSendComplex(matchChannel.ID, data)
if err != nil {
log.Printf("ERROR: could not send nudge message: %+v", err)
c.ReplyError()
return
}

_, err = c.Session.ChannelMessageEditEmbed(c.Interaction.ChannelID, player.MessageID, player.InviteEmbed(c.Session))
if err != nil {
log.Printf("ERROR: could not edit invite message embed: %+v", err)
c.ReplyError()
return
}
c.ReplyHiddenSimpleEmbedUpdate(0x690042, lang.GetDefault(tp+"msg.invite.nudge_match.success"))
}
1 change: 1 addition & 0 deletions modules/secretsanta/handleModal.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ func (c Component) handleModalSetAddress(ids []string) {
}

player.Address = addressFiled.Value
player.PendingNudge = false
err = c.setPlayers(players)
if err != nil {
log.Printf("ERROR: could not set players: %+v", err)
Expand Down
15 changes: 13 additions & 2 deletions modules/secretsanta/secretsantabase.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,16 +108,27 @@ type player struct {
Address string
// MessageID is the message the bot sent to the player
MessageID string
// PendingNudge is true if the player has received a nugde from their santa and they haven't changed their
// address yet i.e. the nudge is still pending.
PendingNudge bool
}

// InviteEmbed returns an embed for the player to be sent by the bot.
func (player *player) InviteEmbed(s *discordgo.Session) (e *discordgo.MessageEmbed) {
var matchValue, addressValue = "❌", "❌"
if player != nil && player.Match.Address != "" {
matchValue = "✅"
if player.Match.PendingNudge {
matchValue = fmt.Sprintf("%s %s", "⌛", lang.GetDefault(tp+"msg.invite.nudge_match.pending"))
} else {
matchValue = "✅"
}
}
if player != nil && player.Address != "" {
addressValue = "✅"
if player.PendingNudge {
addressValue = fmt.Sprintf("%s %s", "⚠️", lang.GetDefault(tp+"msg.invite.nudge_received"))
} else {
addressValue = "✅"
}
}

e = &discordgo.MessageEmbed{
Expand Down
76 changes: 76 additions & 0 deletions util/interaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,17 @@ func (i *InteractionUtil) ReplyHiddenEmbed(embeds ...*discordgo.MessageEmbed) {
i.respond()
}

// ReplyHiddenEmbedUpdate is like [InteractionUtil.ReplyHiddenEmbed] but made for an update for
// components.
func (i *InteractionUtil) ReplyHiddenEmbedUpdate(embeds ...*discordgo.MessageEmbed) {
if !i.respondMessage(true, false) {
return
}
i.response.Data.Embeds = embeds
i.response.Data.Flags = discordgo.MessageFlagsEphemeral
i.respond()
}

// ReplyComponents sends a message along with the provied message components.
func (i *InteractionUtil) ReplyComponents(components []discordgo.MessageComponent, message string) {
i.respondMessage(false, false)
Expand Down Expand Up @@ -259,6 +270,22 @@ func (i *InteractionUtil) ReplySimpleEmbedUpdatef(color int, format string, a ..
i.ReplyEmbedUpdate(e)
}

// ReplyHiddenSimpleEmbedUpdate is like [InteractionUtil.ReplyHiddenSimpleEmbed] but made for an
// update for components.
func (i *InteractionUtil) ReplyHiddenSimpleEmbedUpdate(color int, content string) {
e := &discordgo.MessageEmbed{
Description: content,
Color: color,
}
i.ReplyHiddenEmbedUpdate(e)
}

// ReplyHiddenSimpleEmbedUpdatef is like [InteractionUtil.ReplyHiddenSimpleEmbedf] but made for an
// update for components.
func (i *InteractionUtil) ReplyHiddenSimpleEmbedUpdatef(color int, format string, a ...any) {
i.ReplyHiddenSimpleEmbedUpdate(color, fmt.Sprintf(format, a...))
}

// ReplyComponentsf formats according to a format specifier and sends the result along with the
// provied message components.
func (i *InteractionUtil) ReplyComponentsf(components []discordgo.MessageComponent, format string, a ...any) {
Expand Down Expand Up @@ -302,6 +329,16 @@ func (i *InteractionUtil) ReplyComponentsEmbed(components []discordgo.MessageCom
i.respond()
}

// ReplyComponentsEmbedUpdate is like [InteractionUtil.ReplyComponentsEmbed] but made for an update for components.
func (i *InteractionUtil) ReplyComponentsEmbedUpdate(components []discordgo.MessageComponent, embeds ...*discordgo.MessageEmbed) {
if !i.respondMessage(true, false) {
return
}
i.response.Data.Embeds = embeds
i.response.Data.Components = components
i.respond()
}

// ReplyComponentsHiddenEmbed sends the given embeds as ephemeral reply along with the provided message
// components.
func (i *InteractionUtil) ReplyComponentsHiddenEmbed(components []discordgo.MessageComponent, embeds ...*discordgo.MessageEmbed) {
Expand All @@ -312,6 +349,45 @@ func (i *InteractionUtil) ReplyComponentsHiddenEmbed(components []discordgo.Mess
i.respond()
}

// ReplyComponentsHiddenEmbedUpdate is like [InteractionUtil.ReplyComponentsHiddenEmbed] but made for an update for components.
func (i *InteractionUtil) ReplyComponentsHiddenEmbedUpdate(components []discordgo.MessageComponent, embeds ...*discordgo.MessageEmbed) {
if !i.respondMessage(true, false) {
return
}
i.response.Data.Embeds = embeds
i.response.Data.Components = components
i.response.Data.Flags = discordgo.MessageFlagsEphemeral
i.respond()
}

// ReplyComponentsSimpleEmbedUpdate is like [InteractionUtil.ReplyComponentsSimpleEmbed] but made for an update for components.
func (i *InteractionUtil) ReplyComponentsSimpleEmbedUpdate(components []discordgo.MessageComponent, color int, content string) {
e := &discordgo.MessageEmbed{
Description: content,
Color: color,
}
i.ReplyComponentsEmbedUpdate(components, e)
}

// ReplyComponentsSimpleEmbedUpdatef is like [InteractionUtil.ReplyComponentsSimpleEmbedf] but made for an update for components.
func (i *InteractionUtil) ReplyComponentsSimpleEmbedUpdatef(components []discordgo.MessageComponent, color int, format string, a ...any) {
i.ReplyComponentsSimpleEmbedUpdate(components, color, fmt.Sprintf(format, a...))
}

// ReplyComponentsHiddenSimpleEmbedUpdate is like [InteractionUtil.ReplyComponentsHiddenSimpleEmbed] but made for an update for components.
func (i *InteractionUtil) ReplyComponentsHiddenSimpleEmbedUpdate(components []discordgo.MessageComponent, color int, content string) {
e := &discordgo.MessageEmbed{
Description: content,
Color: color,
}
i.ReplyComponentsHiddenEmbedUpdate(components, e)
}

// ReplyComponentsHiddenSimpleEmbedUpdatef is like [InteractionUtil.ReplyComponentsHiddenSimpleEmbedf] but made for an update for components.
func (i *InteractionUtil) ReplyComponentsHiddenSimpleEmbedUpdatef(components []discordgo.MessageComponent, color int, format string, a ...any) {
i.ReplyComponentsHiddenSimpleEmbedUpdate(components, color, fmt.Sprintf(format, a...))
}

// ReplyAutocomplete returns the given choices to the user. When this is called on an interaction
// type outside form an applicationCommandAutocomplete nothing will happen.
func (i *InteractionUtil) ReplyAutocomplete(choices []*discordgo.ApplicationCommandOptionChoice) {
Expand Down

0 comments on commit 9358940

Please sign in to comment.