Skip to content

Commit

Permalink
Ephemeral Responses (#37)
Browse files Browse the repository at this point in the history
* Added ephemeral response helpers to help with addressing #35

* #35 added ephemeral errors to bot_info.go

* Made /help response ephemeral

* Attempt to gracefully exit if a panic arises while handling an interaction

* /build-a-meme previews are now ephemeral messages instead of DMs

* Removed response type from interactionRespondWithEphemeralErrorAndNotifyOwner

* Added ephemeral follow up errors for /build-a-meme

* Added button to allow for optional anonymous error reporting.

* Prefixed error report button with 'anonymous' when that option was selected

* /del-bot-command now responds ephemerally

* Added stack info to error reports

* Added ephemeral error responses to /compliments

* Added ephemeral error checking to /creepy-dm

* Added ephemeral error responses to /loglevel

* Added ephemeral error responses to /roll

* Improved error message on loglevel for unauthorized users

* Added ephemeral error responses to /pasta

* Added ephemeral error responses to /reddit-roulette

* Added ephemeral error responses to /story-time

* Added ephemeral error responses to /uwu

* Added ephemeral error responses to /what-are-the-odds

* Updated docker-compose for v1.8.5

* Apply suggestions from code review
  • Loading branch information
Kardbord authored Dec 10, 2021
1 parent 6db5b20 commit fd104fd
Show file tree
Hide file tree
Showing 19 changed files with 549 additions and 120 deletions.
4 changes: 2 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
version: "3.9"
services:
kardbot:
image: tkvarfordt/kardbot:v1.8.4
container_name: kardbot-v1.8.4
image: tkvarfordt/kardbot:v1.8.5
container_name: kardbot-v1.8.5
volumes:
- ./config:/app/config
- ./assets/pasta:/app/assets/pasta
Expand Down
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ require (
github.com/deadshot465/owoify-go v1.0.1
github.com/gabriel-vasile/mimetype v1.4.0
github.com/go-co-op/gocron v1.9.0
github.com/google/uuid v1.3.0
github.com/joho/godotenv v1.4.0
github.com/lucasb-eyer/go-colorful v1.2.0
github.com/orcaman/concurrent-map v0.0.0-20210501183033-44dafcb38ecc
github.com/sirupsen/logrus v1.8.1
github.com/vartanbeno/go-reddit/v2 v2.0.1
go.uber.org/atomic v1.9.0
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@ github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hf
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/gorilla/schema v1.2.0 h1:YufUaxZYCKGFuAq3c96BOhjgd5nmXiOY9NGzF247Tsc=
Expand All @@ -135,6 +137,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/orcaman/concurrent-map v0.0.0-20210501183033-44dafcb38ecc h1:Ak86L+yDSOzKFa7WM5bf5itSOo1e3Xh8bm5YCMUXIjQ=
github.com/orcaman/concurrent-map v0.0.0-20210501183033-44dafcb38ecc/go.mod h1:Lu3tH6HLW3feq74c2GC+jIMS/K2CFcDWnWD9XkenwhI=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
Expand Down
6 changes: 6 additions & 0 deletions kardbot/bot_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ func botInfo(s *discordgo.Session, i *discordgo.InteractionCreate) {

if isSelf, err := authorIsSelf(s, i); err != nil {
log.Error(err)
interactionRespondEphemeralError(s, i, true, err)
return
} else if isSelf {
log.Trace("Ignoring message from self")
Expand All @@ -32,17 +33,20 @@ func botInfo(s *discordgo.Session, i *discordgo.InteractionCreate) {
fd, err := os.Open(roboCatPng)
if err != nil {
log.Error(err)
interactionRespondEphemeralError(s, i, true, err)
return
}
defer fd.Close()
mimeType, err := mimetype.DetectReader(fd)
if err != nil {
log.Error(err)
interactionRespondEphemeralError(s, i, true, err)
return
}
_, err = fd.Seek(0, 0)
if err != nil {
log.Error(err)
interactionRespondEphemeralError(s, i, true, err)
return
}

Expand All @@ -61,6 +65,7 @@ func botInfo(s *discordgo.Session, i *discordgo.InteractionCreate) {
err = s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
Type: discordgo.InteractionResponseChannelMessageWithSource,
Data: &discordgo.InteractionResponseData{
Flags: InteractionResponseFlagEphemeral,
Embeds: []*discordgo.MessageEmbed{embed.Truncate().MessageEmbed},
Files: []*discordgo.File{
{
Expand All @@ -73,5 +78,6 @@ func botInfo(s *discordgo.Session, i *discordgo.InteractionCreate) {
})
if err != nil {
log.Error(err)
interactionRespondEphemeralError(s, i, true, err)
}
}
33 changes: 23 additions & 10 deletions kardbot/botdms.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ func deleteBotDMs(s *discordgo.Session, i *discordgo.InteractionCreate) {
fromSelf, err := authorIsSelf(s, i)
if err != nil {
log.Error(err)
interactionRespondEphemeralError(s, i, true, err)
return
}
if fromSelf {
Expand All @@ -30,58 +31,69 @@ func deleteBotDMs(s *discordgo.Session, i *discordgo.InteractionCreate) {
imeta, err := getInteractionMetaData(i)
if err != nil {
log.Error(err)
interactionRespondEphemeralError(s, i, true, err)
return
}

err = s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
Type: discordgo.InteractionResponseDeferredChannelMessageWithSource,
Data: &discordgo.InteractionResponseData{
Flags: InteractionResponseFlagEphemeral,
},
})
if err != nil {
log.Error(err)
interactionFollowUpEphemeralError(s, i, true, err)
return
}

ch, err := s.Channel(imeta.ChannelID)
if err != nil {
log.Error(err)
interactionFollowUpEphemeralError(s, i, true, err)
return
}
if ch.Type != discordgo.ChannelTypeDM {
uc, err := s.UserChannelCreate(imeta.AuthorID)
if err != nil {
log.Error(err)
interactionFollowUpEphemeralError(s, i, true, err)
return
}

_, err = s.ChannelMessageSend(uc.ID, fmt.Sprintf("Looks like you tried to use `/%s` outside of our DMs. Run it from here instead! :)", delBotDMCmd))
if err != nil {
log.Error(err)
interactionFollowUpEphemeralError(s, i, true, err)
return
}

time.Sleep(time.Millisecond * 100)
err = s.InteractionResponseDelete(s.State.User.ID, i.Interaction)
if err != nil {
log.Error(err)
}
s.InteractionResponseEdit(s.State.User.ID, i.Interaction, &discordgo.WebhookEdit{
Content: fmt.Sprintf("looks like you tried to use `/%s` outside of our DMs. Run it from there instead! :)", delBotDMCmd),
})
return
}

msgsToDelete := int(i.ApplicationCommandData().Options[0].IntValue())
if msgsToDelete <= 0 {
_, err = s.InteractionResponseEdit(s.State.User.ID, i.Interaction, &discordgo.WebhookEdit{
Content: fmt.Sprintf("Cannot delete %d messages", msgsToDelete),
})
if err != nil {
log.Error(err)
}
interactionFollowUpEphemeralError(s, i, false, fmt.Errorf("you must specify a positive, non-zero number of messages to delete"))
return
}

msgs, err := s.ChannelMessages(ch.ID, MinOf(msgsToDelete, msgLimit), ch.LastMessageID, "", "")
if err != nil {
log.Error(err)
interactionFollowUpEphemeralError(s, i, true, err)
return
} else {
lastMsg, err := s.ChannelMessage(ch.ID, ch.LastMessageID)
if err != nil {
log.Error(err)
interactionFollowUpEphemeralError(s, i, true, err)
return
}
msgs = append(msgs, lastMsg)
}

// No way to bulk delete messages in a DM channel
Expand Down Expand Up @@ -112,5 +124,6 @@ func deleteBotDMs(s *discordgo.Session, i *discordgo.InteractionCreate) {
})
if err != nil {
log.Error(err)
interactionFollowUpEphemeralError(s, i, true, err)
}
}
6 changes: 6 additions & 0 deletions kardbot/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -381,3 +381,9 @@ func validateCmdRegex() bool {

return conforms
}

func getComponentImpls() map[string]onInteractionHandler {
return map[string]onInteractionHandler{
selectMenuErrorReport: handleErrorReportSelection,
}
}
28 changes: 26 additions & 2 deletions kardbot/compliments.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ func morningComplimentOptIn(s *discordgo.Session, i *discordgo.InteractionCreate
metadata, err := getInteractionMetaData(i)
if err != nil {
log.Error(err)
interactionRespondEphemeralError(s, i, true, err)
return
}

Expand All @@ -151,10 +152,12 @@ func morningComplimentOptIn(s *discordgo.Session, i *discordgo.InteractionCreate
Type: discordgo.InteractionResponseChannelMessageWithSource,
Data: &discordgo.InteractionResponseData{
Content: fmt.Sprintf("%s, you are subscribed to receive morning compliments as long as the bot is up, but there was an error persisting your subscription. Please try to opt-in again.", metadata.AuthorUsername),
Flags: InteractionResponseFlagEphemeral,
},
})
if err != nil {
log.Error(err)
interactionRespondEphemeralError(s, i, true, err)
}
return
}
Expand All @@ -168,13 +171,15 @@ func morningComplimentOptIn(s *discordgo.Session, i *discordgo.InteractionCreate
})
if err != nil {
log.Error(err)
interactionRespondEphemeralError(s, i, true, err)
}
}

func morningComplimentOptOut(s *discordgo.Session, i *discordgo.InteractionCreate) {
metadata, err := getInteractionMetaData(i)
if err != nil {
log.Error(err)
interactionRespondEphemeralError(s, i, true, err)
return
}

Expand All @@ -189,10 +194,12 @@ func morningComplimentOptOut(s *discordgo.Session, i *discordgo.InteractionCreat
Type: discordgo.InteractionResponseChannelMessageWithSource,
Data: &discordgo.InteractionResponseData{
Content: fmt.Sprintf("%s, you are unsubscribed from morning compliments as long as the bot is up, but there was an error persisting your opt-out. Please try to opt-out again.", metadata.AuthorUsername),
Flags: InteractionResponseFlagEphemeral,
},
})
if err != nil {
log.Error(err)
interactionRespondEphemeralError(s, i, true, err)
}
return
}
Expand All @@ -207,13 +214,15 @@ func morningComplimentOptOut(s *discordgo.Session, i *discordgo.InteractionCreat
})
if err != nil {
log.Error(err)
interactionRespondEphemeralError(s, i, true, err)
}
}

func eveningComplimentOptIn(s *discordgo.Session, i *discordgo.InteractionCreate) {
metadata, err := getInteractionMetaData(i)
if err != nil {
log.Error(err)
interactionRespondEphemeralError(s, i, true, err)
return
}

Expand All @@ -228,10 +237,12 @@ func eveningComplimentOptIn(s *discordgo.Session, i *discordgo.InteractionCreate
Type: discordgo.InteractionResponseChannelMessageWithSource,
Data: &discordgo.InteractionResponseData{
Content: fmt.Sprintf("%s, you are subscribed to receive evening compliments as long as the bot is up, but there was an error persisting your subscription. Please try to opt-in again.", metadata.AuthorUsername),
Flags: InteractionResponseFlagEphemeral,
},
})
if err != nil {
log.Error(err)
interactionRespondEphemeralError(s, i, true, err)
}
return
}
Expand All @@ -245,13 +256,15 @@ func eveningComplimentOptIn(s *discordgo.Session, i *discordgo.InteractionCreate
})
if err != nil {
log.Error(err)
interactionRespondEphemeralError(s, i, true, err)
}
}

func eveningComplimentOptOut(s *discordgo.Session, i *discordgo.InteractionCreate) {
metadata, err := getInteractionMetaData(i)
if err != nil {
log.Error(err)
interactionRespondEphemeralError(s, i, true, err)
return
}

Expand All @@ -266,10 +279,12 @@ func eveningComplimentOptOut(s *discordgo.Session, i *discordgo.InteractionCreat
Type: discordgo.InteractionResponseChannelMessageWithSource,
Data: &discordgo.InteractionResponseData{
Content: fmt.Sprintf("%s, you are unsubscribed from evening compliments as long as the bot is up, but there was an error persisting your opt-out. Please try to opt-out again.", metadata.AuthorUsername),
Flags: InteractionResponseFlagEphemeral,
},
})
if err != nil {
log.Error(err)
interactionRespondEphemeralError(s, i, true, err)
}
return
}
Expand All @@ -283,13 +298,15 @@ func eveningComplimentOptOut(s *discordgo.Session, i *discordgo.InteractionCreat
})
if err != nil {
log.Error(err)
interactionRespondEphemeralError(s, i, true, err)
}
}

func getCompliment(s *discordgo.Session, i *discordgo.InteractionCreate) {
metadata, err := getInteractionMetaData(i)
if err != nil {
log.Error(err)
interactionRespondEphemeralError(s, i, true, err)
return
}

Expand All @@ -303,9 +320,13 @@ func getCompliment(s *discordgo.Session, i *discordgo.InteractionCreate) {
if sendAsDM {
err := s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
Type: discordgo.InteractionResponseDeferredChannelMessageWithSource,
Data: &discordgo.InteractionResponseData{
Flags: InteractionResponseFlagEphemeral,
},
})
if err != nil {
log.Error(err)
interactionRespondEphemeralError(s, i, true, err)
return
}

Expand All @@ -320,9 +341,12 @@ func getCompliment(s *discordgo.Session, i *discordgo.InteractionCreate) {
log.Infof("Told %s that '%s'", metadata.AuthorUsername, compliment)

time.Sleep(time.Millisecond * 250) // give a bit for the initial response to be received
err = s.InteractionResponseDelete(s.State.User.ID, i.Interaction)
_, err = s.InteractionResponseEdit(s.State.User.ID, i.Interaction, &discordgo.WebhookEdit{
Content: "Sent you a compliment! 💛",
})
if err != nil {
log.Error(err)
interactionFollowUpEphemeralError(s, i, true, err)
}
return
}
Expand All @@ -335,8 +359,8 @@ func getCompliment(s *discordgo.Session, i *discordgo.InteractionCreate) {
})
if err != nil {
log.Error(err)
interactionFollowUpEphemeralError(s, i, true, err)
}
log.Infof("To %s: \"%s\"", metadata.AuthorUsername, compliment)
}

func sendMorningCompliments() {
Expand Down
Loading

0 comments on commit fd104fd

Please sign in to comment.