Skip to content

Commit

Permalink
feat: (interactions) add message application command
Browse files Browse the repository at this point in the history
  • Loading branch information
tyzbit committed Jul 16, 2023
1 parent ab721a6 commit 004e63b
Show file tree
Hide file tree
Showing 3 changed files with 186 additions and 11 deletions.
91 changes: 86 additions & 5 deletions bot/functions.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ const (
)

// handleArchiveRequest takes a Discord session and a message reaction and
// calls go-archiver with a []string of URLs parsed from the message
// It then sends an embed with the resulting archived URLs
// calls go-archiver with a []string of URLs parsed from the message.
// It then returns an embed with the resulting archived URLs,
func (bot *ArchiverBot) handleArchiveRequest(r *discordgo.MessageReactionAdd, newSnapshot bool) (
embeds []*discordgo.MessageEmbed, errs []error) {

Expand All @@ -35,7 +35,7 @@ func (bot *ArchiverBot) handleArchiveRequest(r *discordgo.MessageReactionAdd, ne
typingStop <- true
return []*discordgo.MessageEmbed{
{
Description: "Use `/archive` instead of adding a reaction to a message.",
Description: "Use `/archive` or the `Get snapshots` menu item on the message instead of adding a reaction.",
},
}, errs
}
Expand Down Expand Up @@ -132,8 +132,8 @@ func (bot *ArchiverBot) handleArchiveRequest(r *discordgo.MessageReactionAdd, ne
}

// handleArchiveCommand takes a discordgo.InteractionCreate and
// calls go-archiver with a []string of URLs parsed from the message
// It then sends an embed with the resulting archived URLs
// calls go-archiver with a []string of URLs parsed from the message.
// It then returns an embed with the resulting archived URLs,
func (bot *ArchiverBot) handleArchiveCommand(i *discordgo.InteractionCreate) (
embeds []*discordgo.MessageEmbed, errs []error) {

Expand Down Expand Up @@ -210,6 +210,87 @@ func (bot *ArchiverBot) handleArchiveCommand(i *discordgo.InteractionCreate) (
return embeds, errs
}

// handleArchiveMessage takes a discordgo.InteractionCreate and
// calls go-archiver with a []string of URLs parsed from the message.
// It then returns an embed with the resulting archived URLs,
func (bot *ArchiverBot) handleArchiveMessage(i *discordgo.InteractionCreate) (
embeds []*discordgo.MessageEmbed, errs []error) {

message := &discordgo.Message{}
var archives []ArchiveEvent
commandData := i.Interaction.ApplicationCommandData()
if len(commandData.Options) > 1 {
embeds = append(embeds, &discordgo.MessageEmbed{
Title: "Too many options submitted",
})
} else {
for _, message := range commandData.Resolved.Messages {
messageUrls, errs := bot.extractMessageUrls(message.Content)
for index, err := range errs {
if err != nil {
log.Errorf("unable to extract message url: %s, err: %w", messageUrls[index], err)
}
}

archives, errs := bot.populateArchiveEventCache(messageUrls, true, discordgo.Guild{ID: "", Name: "ArchiveCommand"})
for _, err := range errs {
if err != nil {
log.Error("error populating archive cache: ", err)
}
}

sc := bot.getServerConfig(i.GuildID)

archivedLinks, errs := bot.executeArchiveEventRequest(&archives, sc,
true)
for _, err := range errs {
if err != nil {
log.Error("error populating archive cache: ", err)
}
}

if len(archivedLinks) < len(messageUrls) {
log.Errorf("did not receive the same number of archived links as submitted URLs")
if len(archivedLinks) == 0 {
log.Errorf("did not receive any Archive.org links")
archivedLinks = []string{"I was unable to get any Wayback Machine URLs. " +
"Most of the time, this is " +
"due to rate-limiting by Archive.org. " +
"Please try again"}
}
}

embeds, errs = bot.buildArchiveReply(archivedLinks, messageUrls, sc)

for _, err := range errs {
if err != nil {
log.Error("error building archive reply: ", err)
}
}
}
}

// Don't create an event if there were no archives
if len(archives) > 0 {
// Create a call to Archiver API event
tx := bot.DB.Create(&ArchiveEventEvent{
UUID: archives[0].ArchiveEventEventUUID,
AuthorId: message.Author.ID,
AuthorUsername: message.Author.Username,
ChannelId: message.ChannelID,
MessageId: message.ID,
ServerID: "DirectMessage",
ArchiveEvents: archives,
})

if tx.RowsAffected != 1 {
errs = append(errs, fmt.Errorf("unexpected number of rows affected inserting archive event: %v", tx.RowsAffected))
}
}

return embeds, errs
}

// extractMessageUrls takes a string and returns a slice of URLs parsed from the string
func (bot *ArchiverBot) extractMessageUrls(message string) (messageUrls []string, errs []error) {
xurlsStrict := xurls.Strict
Expand Down
90 changes: 89 additions & 1 deletion bot/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,93 @@ func (bot *ArchiverBot) InteractionHandler(s *discordgo.Session, i *discordgo.In
},
globals.Archive: func(s *discordgo.Session, i *discordgo.InteractionCreate) {
log.Debug("handling archive command request")
// Send a response immediately that says the bot is thinking
bot.DG.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
Type: discordgo.InteractionResponseDeferredChannelMessageWithSource,
Data: &discordgo.InteractionResponseData{
Flags: uint64(discordgo.MessageFlagsEphemeral),
},
})
guild := &discordgo.Guild{}
var err error
if i.GuildID == "" {
guild.Name = "DirectMessage"
} else {
guild, err = bot.DG.Guild(i.Interaction.GuildID)
if err != nil {
guild.Name = "GuildLookupError"
}
}

// If i.Interaction.User is not nil, then this is a DM
if i.Interaction.User != nil {
bot.createInteractionEvent(InteractionEvent{
UserID: i.Interaction.User.ID,
Username: i.Interaction.User.Username,
InteractionId: i.ID,
ChannelId: i.ChannelID,
ServerID: i.GuildID,
ServerName: guild.Name,
})
} else {
bot.createInteractionEvent(InteractionEvent{
UserID: i.Interaction.Member.User.ID,
Username: i.Interaction.Member.User.Username,
InteractionId: i.ID,
ChannelId: i.ChannelID,
ServerID: i.GuildID,
ServerName: guild.Name,
})
}

embeds, errs := bot.handleArchiveCommand(i)
for _, err := range errs {
if err != nil {
log.Errorf("problem handling archive command request: %v", err)
}
}

if len(embeds) == 0 {
log.Warn("no embeds were generated")
return
}

for index, embed := range embeds {
if len(errs) > 0 {
if errs[index] != nil {
guild.Name = "None"
guild.ID = "0"
}
}

if i.Interaction.User != nil {
bot.createMessageEvent(MessageEvent{
AuthorId: i.Interaction.User.ID,
AuthorUsername: i.Interaction.User.Username,
MessageId: "",
ChannelId: i.Interaction.ChannelID,
ServerID: guild.ID,
ServerName: guild.Name,
})
} else {
bot.createMessageEvent(MessageEvent{
AuthorId: i.Interaction.Member.User.ID,
AuthorUsername: i.Interaction.Member.User.Username,
MessageId: "",
ChannelId: i.Interaction.ChannelID,
ServerID: guild.ID,
ServerName: guild.Name,
})
}

err := bot.sendArchiveCommandResponse(i.Interaction, embed)
if err != nil {
log.Errorf("problem sending message: %v", err)
}
}
},
globals.ArchiveMessage: func(s *discordgo.Session, i *discordgo.InteractionCreate) {
log.Debug("handling archive message request")
response := &discordgo.InteractionResponse{
Type: discordgo.InteractionResponseDeferredChannelMessageWithSource,
Data: &discordgo.InteractionResponseData{
Expand All @@ -237,6 +324,7 @@ func (bot *ArchiverBot) InteractionHandler(s *discordgo.Session, i *discordgo.In
}
}

// If i.Interaction.User is not nil, then this is a DM
if i.Interaction.User != nil {
bot.createInteractionEvent(InteractionEvent{
UserID: i.Interaction.User.ID,
Expand All @@ -257,7 +345,7 @@ func (bot *ArchiverBot) InteractionHandler(s *discordgo.Session, i *discordgo.In
})
}

embeds, errs := bot.handleArchiveCommand(i)
embeds, errs := bot.handleArchiveMessage(i)
for _, err := range errs {
if err != nil {
log.Errorf("problem handling archive command request: %v", err)
Expand Down
16 changes: 11 additions & 5 deletions globals/globals.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ const (
Retry = "retry"

// Commands
Stats = "stats"
Settings = "settings"
Archive = "archive"
Help = "help"
Stats = "stats"
Settings = "settings"
Archive = "archive"
ArchiveMessage = "Get snapshots"
Help = "help"

// Bot settings unique handler names
// Booleans
Expand All @@ -33,7 +34,8 @@ const (

// Shown to the user when `/help` is called
BotHelpText = `**Usage**
React to a message that has links with 🏛 (The "classical building" emoji) and the bot will respond in the channel with an archive.org link for the link(s). It saves the page to archive.org if needed.
React to a message that has links with 🏛 (The "classical building" emoji) and the bot will respond in the channel with an archive.org link for the link(s). It saves the page to archive.org if needed.
You can also right-click (or long press) a message and use "Get snapshots" to get a message with snapshots for any link that only you can see.
**This is a pretty good way to get around paywalls to read articles for free.**
Expand Down Expand Up @@ -88,6 +90,10 @@ var (
},
},
},
{
Name: ArchiveMessage,
Type: discordgo.MessageApplicationCommand,
},
{
Name: Stats,
Description: "Show bot stats",
Expand Down

0 comments on commit 004e63b

Please sign in to comment.