apply correlation IDs to modal submits and message actions

new-sql-view
William Perron 11 months ago
parent 7f78dcdc67
commit 008d025fa0
Signed by: wperron
GPG Key ID: BFDB4EF72D73C5F2

@ -7,6 +7,7 @@ import (
"flag" "flag"
"fmt" "fmt"
"net/http" "net/http"
"net/url"
"os" "os"
"os/signal" "os/signal"
"sort" "sort"
@ -465,10 +466,22 @@ func main() {
} }
}, },
"flush": func(ctx context.Context, s *discordgo.Session, i *discordgo.InteractionCreate) { "flush": func(ctx context.Context, s *discordgo.Session, i *discordgo.InteractionCreate) {
cid := correlation.FromContext(ctx)
baggage := make(url.Values)
baggage.Set("correlation_id", cid.String())
state := baggage.Encode()
sb := strings.Builder{}
sb.WriteString("modal_flush")
if state != "" {
sb.WriteRune(':')
sb.WriteString(state)
}
if err := s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ if err := s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
Type: discordgo.InteractionResponseModal, Type: discordgo.InteractionResponseModal,
Data: &discordgo.InteractionResponseData{ Data: &discordgo.InteractionResponseData{
CustomID: "modals_flush_" + i.Interaction.Member.User.ID, CustomID: sb.String(),
Title: "Are you sure?", Title: "Are you sure?",
Components: []discordgo.MessageComponent{ Components: []discordgo.MessageComponent{
discordgo.ActionsRow{ discordgo.ActionsRow{
@ -740,28 +753,42 @@ func registerHandlers(sess *discordgo.Session, handlers map[string]Handler) {
log.Info().Str("user_id", fmt.Sprintf("%s#%s", s.State.User.Username, s.State.User.Discriminator)).Msg("logged in") log.Info().Str("user_id", fmt.Sprintf("%s#%s", s.State.User.Username, s.State.User.Discriminator)).Msg("logged in")
}) })
sess.AddHandler(func(s *discordgo.Session, i *discordgo.InteractionCreate) { sess.AddHandler(func(s *discordgo.Session, i *discordgo.InteractionCreate) {
switch i.Type {
case discordgo.InteractionApplicationCommand:
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel() defer cancel()
ctx = context.WithValue(ctx, "correlation_id", gen.Next()) ctx = context.WithValue(ctx, "correlation_id", gen.Next())
switch i.Type {
case discordgo.InteractionApplicationCommand:
if h, ok := handlers[i.ApplicationCommandData().Name]; ok { if h, ok := handlers[i.ApplicationCommandData().Name]; ok {
withLogging(i.ApplicationCommandData().Name, h)(ctx, s, i) withLogging(i.ApplicationCommandData().Name, h)(ctx, s, i)
} }
// TODO(wperron) apply correlation IDs to the other interation types
// TODO(wperron) is it possible to correlate a modal submit or message
// component to the original interaction?
case discordgo.InteractionModalSubmit: case discordgo.InteractionModalSubmit:
if strings.HasPrefix(i.ModalSubmitData().CustomID, "modals_flush_") { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
state, err := parseCustomIDState(i.ModalSubmitData().CustomID)
if err != nil {
log.Error().Ctx(ctx).Err(err).Msg("unexpected error occured while parsing state from custom id, returning early.")
return
}
cid := state.Get("correlation_id")
if cid != "" {
ctx = context.WithValue(ctx, "correlation_id", cid)
} else {
ctx = context.WithValue(ctx, "correlation_id", gen.Next())
}
if strings.HasPrefix(i.ModalSubmitData().CustomID, "modal_flush") {
sub := i.ModalSubmitData().Components[0].(*discordgo.ActionsRow).Components[0].(*discordgo.TextInput).Value sub := i.ModalSubmitData().Components[0].(*discordgo.ActionsRow).Components[0].(*discordgo.TextInput).Value
sub = strings.ToLower(sub) sub = strings.ToLower(sub)
log.Debug().Str("value", sub).Msg("flush modal submitted") log.Debug().Ctx(ctx).Str("value", sub).Msg("flush modal submitted")
if sub == "y" || sub == "ye" || sub == "yes" { if sub == "y" || sub == "ye" || sub == "yes" {
err := store.Flush(context.Background(), i.Member.User.ID) err := store.Flush(context.Background(), i.Member.User.ID)
msg := "Flushed all claims!" msg := "Flushed all claims!"
if err != nil { if err != nil {
log.Error().Err(err).Msg("failed to flush claims") log.Error().Ctx(ctx).Err(err).Msg("failed to flush claims")
msg = "failed to flush claims from database" msg = "failed to flush claims from database"
} }
@ -772,7 +799,7 @@ func registerHandlers(sess *discordgo.Session, handlers map[string]Handler) {
}, },
}) })
if err != nil { if err != nil {
log.Error().Err(err).Msg("failed to respond to interaction") log.Error().Ctx(ctx).Err(err).Msg("failed to respond to interaction")
} }
return return
} }
@ -784,14 +811,32 @@ func registerHandlers(sess *discordgo.Session, handlers map[string]Handler) {
}, },
}) })
if err != nil { if err != nil {
log.Error().Err(err).Msg("failed to respond to interaction") log.Error().Ctx(ctx).Err(err).Msg("failed to respond to interaction")
} }
return return
} }
case discordgo.InteractionMessageComponent: case discordgo.InteractionMessageComponent:
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
state, err := parseCustomIDState(i.MessageComponentData().CustomID)
if err != nil {
log.Error().Ctx(ctx).Err(err).Msg("unexpected error occured while parsing state from custom id, returning early.")
return
}
cid := state.Get("correlation_id")
if cid != "" {
ctx = context.WithValue(ctx, "correlation_id", cid)
} else {
ctx = context.WithValue(ctx, "correlation_id", gen.Next())
}
switch i.MessageComponentData().CustomID { switch i.MessageComponentData().CustomID {
case "schedule-response": case "schedule-response":
userId := i.Member.User.ID userId := i.Member.User.ID
log.Info().Ctx(ctx).Str("message_component", "schedule-response").Str("userid", userId).Msg("handling message component interaction")
if err := store.AddAbsence(context.TODO(), themis.NextMonday(), userId); err != nil { if err := store.AddAbsence(context.TODO(), themis.NextMonday(), userId); err != nil {
if err := s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ if err := s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
Type: discordgo.InteractionResponseChannelMessageWithSource, Type: discordgo.InteractionResponseChannelMessageWithSource,
@ -949,3 +994,16 @@ func min(a, b int) int {
} }
return b return b
} }
func parseCustomIDState(qs string) (url.Values, error) {
parts := strings.Split(qs, ":")
if len(parts) == 1 {
return make(url.Values), nil
}
v, err := url.ParseQuery(parts[1])
if err != nil {
return nil, err
}
return v, nil
}

Loading…
Cancel
Save