Skip to content

Commit

Permalink
feat: (commands) optionally specify new snapshot with commands
Browse files Browse the repository at this point in the history
  • Loading branch information
tyzbit committed Jul 20, 2023
1 parent 274b7dd commit 5a51095
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 100 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Otherwise, it will save stats to a local sqlite database at `/var/go-discord-arc

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 snapshot" to get a message with snapshots that only you can see.
- You can also right-click (or long press) a message and use "Get snapshot" to get a message with snapshots that only you can see or select "Take snapshot" to take a snapshot of the live page.

**This is a pretty good way to get around paywalls to read articles for free.**

Expand All @@ -34,7 +34,7 @@ Configure the bot:

`/settings`

Get a snapshot for one URL in a message visible only to you:
Get a snapshot for one URL in a message visible only to you (It will ask if you want to try to find an existing snapshot or take a new one):

`/archive`

Expand Down
12 changes: 6 additions & 6 deletions bot/discord_handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,8 +203,9 @@ func (bot *ArchiverBot) InteractionHandler(s *discordgo.Session, i *discordgo.In
}
},
// bot.archiveInteraction can handle both the archive slash command and the app menu function
globals.Archive: func(s *discordgo.Session, i *discordgo.InteractionCreate) { bot.archiveInteraction(i, true) },
globals.ArchiveMessage: func(s *discordgo.Session, i *discordgo.InteractionCreate) { bot.archiveInteraction(i, true) },
globals.Archive: func(s *discordgo.Session, i *discordgo.InteractionCreate) { bot.archiveInteraction(i, false, true) },
globals.ArchiveMessage: func(s *discordgo.Session, i *discordgo.InteractionCreate) { bot.archiveInteraction(i, false, true) },
globals.ArchiveMessageNewSnapshot: func(s *discordgo.Session, i *discordgo.InteractionCreate) { bot.archiveInteraction(i, true, true) },
// Stats does not create an InteractionEvent
globals.Stats: func(s *discordgo.Session, i *discordgo.InteractionCreate) {
directMessage := (i.GuildID == "")
Expand Down Expand Up @@ -466,9 +467,8 @@ func (bot *ArchiverBot) InteractionHandler(s *discordgo.Session, i *discordgo.In
}
}

// archiveInteraction is called by adding 🏛️ to a message, using /archive
// and using the "Get snapshots" app function.
func (bot *ArchiverBot) archiveInteraction(i *discordgo.InteractionCreate, ephemeral bool) {
// archiveInteraction is called by using /archive and using the "Get snapshots" app function.
func (bot *ArchiverBot) archiveInteraction(i *discordgo.InteractionCreate, newSnapshot bool, ephemeral bool) {
log.Debug("handling archive command request")
var flags uint64
if ephemeral {
Expand Down Expand Up @@ -513,7 +513,7 @@ func (bot *ArchiverBot) archiveInteraction(i *discordgo.InteractionCreate, ephem
})
}

messagesToSend, errs := bot.buildInteractionResponse(i)
messagesToSend, errs := bot.buildInteractionResponse(i, newSnapshot)
for _, err := range errs {
if err != nil {
log.Errorf("problem handling archive command request: %v", err)
Expand Down
113 changes: 54 additions & 59 deletions bot/responses.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,78 +168,73 @@ func (bot *ArchiverBot) buildMessageResponse(m *discordgo.Message, newSnapshot b
// calls go-archiver with a []string of URLs parsed from the message.
// It then returns a slice of *discordgo.MessageSend with the resulting
// archived URLs.
func (bot *ArchiverBot) buildInteractionResponse(i *discordgo.InteractionCreate) (
func (bot *ArchiverBot) buildInteractionResponse(i *discordgo.InteractionCreate, newSnapshot bool) (
messagesToSend []*discordgo.MessageSend, errs []error) {

message := &discordgo.Message{}
var archives []ArchiveEvent
commandData := i.Interaction.ApplicationCommandData()
if len(commandData.Options) > 1 {
messagesToSend = append(messagesToSend, &discordgo.MessageSend{
Embeds: []*discordgo.MessageEmbed{
{
Title: "Too many options submitted",
},
},
})
} else {
var messageUrls []string
var errs []error

// The message content is in different places depending on
// how the bot was called
if commandData.Name == globals.Archive {
messageUrls, errs = bot.extractMessageUrls(commandData.Options[0].StringValue())
} else if commandData.Name == globals.ArchiveMessage {
for _, message := range commandData.Resolved.Messages {
urlGroup, urlErrs := bot.extractMessageUrls(message.Content)
messageUrls = append(messageUrls, urlGroup...)
errs = append(errs, urlErrs...)
var messageUrls []string

// The message content is in different places depending on
// how the bot was called
if commandData.Name == globals.Archive {
for _, command := range commandData.Options {
if command.Name == globals.UrlOption {
messageUrls, errs = bot.extractMessageUrls(command.StringValue())
}
} else {
log.Errorf("unexpected command name: %s", commandData.Name)
if command.Name == globals.TakeNewSnapshotOption {
newSnapshot = command.BoolValue()
}
}
} else if commandData.Name == globals.ArchiveMessage || commandData.Name == globals.ArchiveMessageNewSnapshot {
for _, message := range commandData.Resolved.Messages {
urlGroup, urlErrs := bot.extractMessageUrls(message.Content)
messageUrls = append(messageUrls, urlGroup...)
errs = append(errs, urlErrs...)
}
} else {
log.Errorf("unexpected command name: %s", commandData.Name)
}

for index, err := range errs {
if err != nil {
log.Errorf("unable to extract message url: %s, err: %s", messageUrls[index], err)
}
for index, err := range errs {
if err != nil {
log.Errorf("unable to extract message url: %s, err: %s", messageUrls[index], err)
}
}

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

sc := bot.getServerConfig(i.GuildID)
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)
archivedLinks = append(archivedLinks, fmt.Sprintf("Error: %+v", err))
}
archivedLinks, errs := bot.executeArchiveEventRequest(&archives, sc, newSnapshot)
for _, err := range errs {
if err != nil {
log.Error("error populating archive cache: ", err)
archivedLinks = append(archivedLinks, fmt.Sprintf("Error: %+v", 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"}
}
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"}
}
}

messagesToSend, errs = bot.buildArchiveReply(archives, archivedLinks, messageUrls, sc, true)
messagesToSend, errs = bot.buildArchiveReply(archives, archivedLinks, messageUrls, sc, true)

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

Expand All @@ -248,10 +243,10 @@ func (bot *ArchiverBot) buildInteractionResponse(i *discordgo.InteractionCreate)
// 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,
AuthorId: i.Interaction.Member.User.ID,
AuthorUsername: i.Interaction.Member.User.Username,
ChannelId: i.Interaction.ChannelID,
MessageId: i.Interaction.ID,
ServerID: "DirectMessage",
ArchiveEvents: archives,
})
Expand Down
35 changes: 26 additions & 9 deletions globals/globals.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
package globals

import "github.com/bwmarrin/discordgo"
import (
"github.com/bwmarrin/discordgo"
)

const (
// Interactive command aliases
Retry = "retry"

// Commands
Stats = "stats"
Settings = "settings"
Archive = "archive"
ArchiveMessage = "Get snapshot"
Help = "help"
Stats = "stats"
Settings = "settings"
Archive = "archive"
ArchiveMessage = "Get snapshot"
ArchiveMessageNewSnapshot = "Take snapshot"
Help = "help"

// Command options
UrlOption = "url"
TakeNewSnapshotOption = "new"

// Bot settings unique handler names
// Booleans
Expand All @@ -36,15 +43,15 @@ const (
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.
- You can also right-click (or long press) a message and use "Get snapshot" to get a message with snapshots that only you can see.
- You can also right-click (or long press) a message and use "Get snapshot" to get a message with snapshots that only you can see- You can also right-click (or long press) a message and use "Get snapshot" to get a message with snapshots that only you can see or select "Take snapshot" to take a snapshot of the live page.
**This is a pretty good way to get around paywalls to read articles for free.**
Configure the bot:
` + "`/settings`" + `
Get a snapshot for one URL in a message visible only to you:
Get a snapshot for one URL in a message visible only to you (It will ask if you want to try to find an existing snapshot or take a new one):
` + "`/archive`" + `
Expand Down Expand Up @@ -88,17 +95,27 @@ var (
Type: discordgo.ChatApplicationCommand,
Options: []*discordgo.ApplicationCommandOption{
{
Name: "url",
Name: UrlOption,
Description: "URL to get a Wayback Machine snapshot for",
Type: discordgo.ApplicationCommandOptionString,
Required: true,
},
{
Name: TakeNewSnapshotOption,
Description: "Whether to take a new snapshot (True) or try to look for an existing one first (False)",
Type: discordgo.ApplicationCommandOptionBoolean,
Required: true,
},
},
},
{
Name: ArchiveMessage,
Type: discordgo.MessageApplicationCommand,
},
{
Name: ArchiveMessageNewSnapshot,
Type: discordgo.MessageApplicationCommand,
},
{
Name: Stats,
Description: "Show bot stats",
Expand Down
Loading

0 comments on commit 5a51095

Please sign in to comment.