|
|
|
@ -21,6 +21,8 @@ import (
|
|
|
|
|
"github.com/rs/zerolog/log"
|
|
|
|
|
|
|
|
|
|
"go.wperron.io/themis"
|
|
|
|
|
"go.wperron.io/themis/correlation"
|
|
|
|
|
zerologcompat "go.wperron.io/themis/correlation/compat/zerolog"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
const (
|
|
|
|
@ -32,9 +34,11 @@ var (
|
|
|
|
|
debug = flag.Bool("debug", false, "Set log level to DEBUG.")
|
|
|
|
|
|
|
|
|
|
store *themis.Store
|
|
|
|
|
seq = &correlation.CryptoRandSequencer{}
|
|
|
|
|
gen = correlation.NewGenerator(seq)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type Handler func(s *discordgo.Session, i *discordgo.InteractionCreate)
|
|
|
|
|
type Handler func(ctx context.Context, s *discordgo.Session, i *discordgo.InteractionCreate)
|
|
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
|
log.Info().Msg("startup.")
|
|
|
|
@ -50,6 +54,7 @@ func main() {
|
|
|
|
|
zerolog.SetGlobalLevel(zerolog.DebugLevel)
|
|
|
|
|
}
|
|
|
|
|
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stdout})
|
|
|
|
|
log.Logger = log.Logger.Hook(zerologcompat.CorrelationHook{})
|
|
|
|
|
zerolog.DurationFieldUnit = time.Millisecond
|
|
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
@ -209,8 +214,8 @@ func main() {
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
handlers := map[string]Handler{
|
|
|
|
|
"info": func(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
|
|
|
|
uptime, err := themis.Uptime()
|
|
|
|
|
"info": func(ctx context.Context, s *discordgo.Session, i *discordgo.InteractionCreate) {
|
|
|
|
|
uptime, err := themis.Uptime(ctx)
|
|
|
|
|
if err != nil {
|
|
|
|
|
err := s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
|
|
|
|
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
|
|
|
@ -219,9 +224,9 @@ func main() {
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
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")
|
|
|
|
|
}
|
|
|
|
|
log.Error().Err(err).Msg("failed to get server uptime")
|
|
|
|
|
log.Error().Ctx(ctx).Err(err).Msg("failed to get server uptime")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -234,9 +239,9 @@ func main() {
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
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")
|
|
|
|
|
}
|
|
|
|
|
log.Error().Err(err).Msg("failed to count claims")
|
|
|
|
|
log.Error().Ctx(ctx).Err(err).Msg("failed to count claims")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -251,9 +256,9 @@ func main() {
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
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")
|
|
|
|
|
}
|
|
|
|
|
log.Error().Err(err).Msg("failed get last flush event")
|
|
|
|
|
log.Error().Ctx(ctx).Err(err).Msg("failed get last flush event")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
lastFlush = "never"
|
|
|
|
@ -268,10 +273,10 @@ func main() {
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
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")
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
"list-claims": func(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
|
|
|
|
"list-claims": func(ctx context.Context, s *discordgo.Session, i *discordgo.InteractionCreate) {
|
|
|
|
|
claims, err := store.ListClaims(ctx)
|
|
|
|
|
if err != nil {
|
|
|
|
|
err := s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
|
|
|
@ -281,9 +286,9 @@ func main() {
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
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")
|
|
|
|
|
}
|
|
|
|
|
log.Error().Err(err).Msg("failed to list claims")
|
|
|
|
|
log.Error().Ctx(ctx).Err(err).Msg("failed to list claims")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -300,12 +305,12 @@ func main() {
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
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")
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
"claim": func(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
|
|
|
|
"claim": func(ctx context.Context, s *discordgo.Session, i *discordgo.InteractionCreate) {
|
|
|
|
|
if i.Type == discordgo.InteractionApplicationCommandAutocomplete {
|
|
|
|
|
log.Debug().Msg("command type interaction autocomplete")
|
|
|
|
|
log.Debug().Ctx(ctx).Msg("command type interaction autocomplete")
|
|
|
|
|
handleClaimAutocomplete(ctx, store, s, i)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
@ -319,7 +324,7 @@ func main() {
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
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
|
|
|
|
|
}
|
|
|
|
@ -333,9 +338,9 @@ func main() {
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
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")
|
|
|
|
|
}
|
|
|
|
|
log.Error().Err(err).Str("claim_type", opts[0].StringValue()).Msg("failed to parse claim")
|
|
|
|
|
log.Error().Ctx(ctx).Err(err).Str("claim_type", opts[0].StringValue()).Msg("failed to parse claim")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
name := opts[1].StringValue()
|
|
|
|
@ -365,7 +370,7 @@ func main() {
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
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
|
|
|
|
|
}
|
|
|
|
@ -377,9 +382,9 @@ func main() {
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
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")
|
|
|
|
|
}
|
|
|
|
|
log.Error().Err(err).Msg("failed to acquire claim")
|
|
|
|
|
log.Error().Ctx(ctx).Err(err).Msg("failed to acquire claim")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -390,10 +395,10 @@ func main() {
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
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")
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
"describe-claim": func(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
|
|
|
|
"describe-claim": func(ctx context.Context, s *discordgo.Session, i *discordgo.InteractionCreate) {
|
|
|
|
|
id := i.ApplicationCommandData().Options[0]
|
|
|
|
|
detail, err := store.DescribeClaim(ctx, int(id.IntValue()))
|
|
|
|
|
if err != nil {
|
|
|
|
@ -404,9 +409,9 @@ func main() {
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
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")
|
|
|
|
|
}
|
|
|
|
|
log.Error().Err(err).Msg("failed to describe claim")
|
|
|
|
|
log.Error().Ctx(ctx).Err(err).Msg("failed to describe claim")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -423,10 +428,10 @@ func main() {
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
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")
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
"delete-claim": func(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
|
|
|
|
"delete-claim": func(ctx context.Context, s *discordgo.Session, i *discordgo.InteractionCreate) {
|
|
|
|
|
id := i.ApplicationCommandData().Options[0]
|
|
|
|
|
userId := i.Member.User.ID
|
|
|
|
|
err := store.DeleteClaim(ctx, int(id.IntValue()), userId)
|
|
|
|
@ -442,10 +447,10 @@ func main() {
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
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")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
log.Error().Err(err).Msg("failed to delete claim")
|
|
|
|
|
log.Error().Ctx(ctx).Err(err).Msg("failed to delete claim")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -456,10 +461,10 @@ func main() {
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
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")
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
"flush": func(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
|
|
|
|
"flush": func(ctx context.Context, s *discordgo.Session, i *discordgo.InteractionCreate) {
|
|
|
|
|
if err := s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
|
|
|
|
Type: discordgo.InteractionResponseModal,
|
|
|
|
|
Data: &discordgo.InteractionResponseData{
|
|
|
|
@ -483,13 +488,13 @@ func main() {
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}); err != nil {
|
|
|
|
|
log.Error().Err(err).Msg("failed to respond to interaction")
|
|
|
|
|
log.Error().Ctx(ctx).Err(err).Msg("failed to respond to interaction")
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
"query": func(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
|
|
|
|
"query": func(ctx context.Context, s *discordgo.Session, i *discordgo.InteractionCreate) {
|
|
|
|
|
roDB, err := sql.Open("sqlite3", fmt.Sprintf("file:%s?cache=private&mode=ro", *dbFile))
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Error().Err(err).Msg("failed to open read-only copy of database")
|
|
|
|
|
log.Error().Ctx(ctx).Err(err).Msg("failed to open read-only copy of database")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -498,13 +503,13 @@ func main() {
|
|
|
|
|
defer cancelDeadline()
|
|
|
|
|
rows, err := roDB.QueryContext(deadlined, q)
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Error().Err(err).Msg("failed to exec user-provided query")
|
|
|
|
|
log.Error().Ctx(ctx).Err(err).Msg("failed to exec user-provided query")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fmtd, err := themis.FormatRows(rows)
|
|
|
|
|
fmtd, err := themis.FormatRows(ctx, rows)
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Error().Err(err).Msg("failed to format rows")
|
|
|
|
|
log.Error().Ctx(ctx).Err(err).Msg("failed to format rows")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -519,10 +524,10 @@ func main() {
|
|
|
|
|
Content: table,
|
|
|
|
|
},
|
|
|
|
|
}); err != nil {
|
|
|
|
|
log.Error().Err(err).Msg("failed to respond to interaction")
|
|
|
|
|
log.Error().Ctx(ctx).Err(err).Msg("failed to respond to interaction")
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
"schedule": func(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
|
|
|
|
"schedule": func(ctx context.Context, s *discordgo.Session, i *discordgo.InteractionCreate) {
|
|
|
|
|
// get schedule from now to 4 mondays into the future
|
|
|
|
|
sched, err := store.GetSchedule(ctx, themis.NextMonday(), themis.NextMonday().Add(4*7*24*time.Hour))
|
|
|
|
|
if err != nil {
|
|
|
|
@ -532,9 +537,9 @@ func main() {
|
|
|
|
|
Content: "failed to get schedule, check logs for more info.",
|
|
|
|
|
},
|
|
|
|
|
}); err != nil {
|
|
|
|
|
log.Error().Err(err).Msg("failed to respond to interaction")
|
|
|
|
|
log.Error().Ctx(ctx).Err(err).Msg("failed to respond to interaction")
|
|
|
|
|
}
|
|
|
|
|
log.Error().Err(err).Msg("failed to get schedule")
|
|
|
|
|
log.Error().Ctx(ctx).Err(err).Msg("failed to get schedule")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -564,10 +569,10 @@ func main() {
|
|
|
|
|
Content: sb.String(),
|
|
|
|
|
},
|
|
|
|
|
}); err != nil {
|
|
|
|
|
log.Error().Err(err).Msg("failed to respond to interaction")
|
|
|
|
|
log.Error().Ctx(ctx).Err(err).Msg("failed to respond to interaction")
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
"send-schedule": func(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
|
|
|
|
"send-schedule": func(ctx context.Context, s *discordgo.Session, i *discordgo.InteractionCreate) {
|
|
|
|
|
notifier.Send()
|
|
|
|
|
|
|
|
|
|
if err := s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
|
|
|
@ -576,10 +581,10 @@ func main() {
|
|
|
|
|
Content: "Done.",
|
|
|
|
|
},
|
|
|
|
|
}); err != nil {
|
|
|
|
|
log.Error().Err(err).Msg("failed to respond to interaction")
|
|
|
|
|
log.Error().Ctx(ctx).Err(err).Msg("failed to respond to interaction")
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
"absent": func(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
|
|
|
|
"absent": func(ctx context.Context, s *discordgo.Session, i *discordgo.InteractionCreate) {
|
|
|
|
|
var rawDate string
|
|
|
|
|
if len(i.ApplicationCommandData().Options) == 0 {
|
|
|
|
|
rawDate = themis.NextMonday().Format(time.DateOnly)
|
|
|
|
@ -595,7 +600,7 @@ func main() {
|
|
|
|
|
Content: "failed to parse provided date, make sure to use the YYYY-MM-DD format.",
|
|
|
|
|
},
|
|
|
|
|
}); 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
|
|
|
|
|
}
|
|
|
|
@ -607,7 +612,7 @@ func main() {
|
|
|
|
|
Content: "The date must be some time in the future.",
|
|
|
|
|
},
|
|
|
|
|
}); 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
|
|
|
|
|
}
|
|
|
|
@ -619,7 +624,7 @@ func main() {
|
|
|
|
|
Content: "The date you provided is not a Monday.",
|
|
|
|
|
},
|
|
|
|
|
}); err != nil {
|
|
|
|
|
log.Error().Err(err).Msg("failed to respond to interaction")
|
|
|
|
|
log.Error().Ctx(ctx).Err(err).Msg("failed to respond to interaction")
|
|
|
|
|
}
|
|
|
|
|
// TODO(wperron) suggest Mondays before and after?
|
|
|
|
|
return
|
|
|
|
@ -633,7 +638,7 @@ func main() {
|
|
|
|
|
Content: "something went wrong recording your absence, check logs for more info.",
|
|
|
|
|
},
|
|
|
|
|
}); 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
|
|
|
|
|
}
|
|
|
|
@ -645,7 +650,7 @@ func main() {
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
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")
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
@ -735,11 +740,18 @@ 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")
|
|
|
|
|
})
|
|
|
|
|
sess.AddHandler(func(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
|
|
|
|
defer cancel()
|
|
|
|
|
ctx = context.WithValue(ctx, "correlation_id", gen.Next())
|
|
|
|
|
|
|
|
|
|
switch i.Type {
|
|
|
|
|
case discordgo.InteractionApplicationCommand:
|
|
|
|
|
if h, ok := handlers[i.ApplicationCommandData().Name]; ok {
|
|
|
|
|
withLogging(i.ApplicationCommandData().Name, h)(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:
|
|
|
|
|
if strings.HasPrefix(i.ModalSubmitData().CustomID, "modals_flush_") {
|
|
|
|
|
sub := i.ModalSubmitData().Components[0].(*discordgo.ActionsRow).Components[0].(*discordgo.TextInput).Value
|
|
|
|
@ -880,17 +892,18 @@ func serve(address string) error {
|
|
|
|
|
return http.ListenAndServe(address, nil)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func withLogging(name string, f func(s *discordgo.Session, i *discordgo.InteractionCreate)) func(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
|
|
|
|
return func(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
|
|
|
|
func withLogging(name string, h Handler) Handler {
|
|
|
|
|
return func(ctx context.Context, s *discordgo.Session, i *discordgo.InteractionCreate) {
|
|
|
|
|
start := time.Now()
|
|
|
|
|
logCommandInvocation(name, s, i)
|
|
|
|
|
f(s, i)
|
|
|
|
|
debugCommandCompletion(name, time.Since(start), s, i)
|
|
|
|
|
logCommandInvocation(ctx, name, s, i)
|
|
|
|
|
h(ctx, s, i)
|
|
|
|
|
debugCommandCompletion(ctx, name, time.Since(start), s, i)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func logCommandInvocation(name string, s *discordgo.Session, i *discordgo.InteractionCreate) {
|
|
|
|
|
func logCommandInvocation(ctx context.Context, name string, s *discordgo.Session, i *discordgo.InteractionCreate) {
|
|
|
|
|
log.Info().
|
|
|
|
|
Ctx(ctx).
|
|
|
|
|
Str("userid", i.Member.User.ID).
|
|
|
|
|
Str("username", i.Member.User.Username).
|
|
|
|
|
Str("command", name).
|
|
|
|
@ -920,8 +933,9 @@ func logCommandInvocation(name string, s *discordgo.Session, i *discordgo.Intera
|
|
|
|
|
Msg("command invoked")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func debugCommandCompletion(name string, dur time.Duration, s *discordgo.Session, i *discordgo.InteractionCreate) {
|
|
|
|
|
log.Debug().
|
|
|
|
|
func debugCommandCompletion(ctx context.Context, name string, dur time.Duration, s *discordgo.Session, i *discordgo.InteractionCreate) {
|
|
|
|
|
log.Info().
|
|
|
|
|
Ctx(ctx).
|
|
|
|
|
Str("userid", i.Member.User.ID).
|
|
|
|
|
Str("username", i.Member.User.Username).
|
|
|
|
|
Str("command", name).
|
|
|
|
|