owobot/internal/systems/starboard/handlers.go

145 lines
3.6 KiB
Go

package starboard
import (
"fmt"
"mime"
"net/url"
"path"
"strings"
"github.com/bwmarrin/discordgo"
"go.elara.ws/logger/log"
"go.elara.ws/owobot/internal/db"
"go.elara.ws/owobot/internal/systems/eventlog"
"mvdan.cc/xurls/v2"
)
// onReaction detects star reactions, and if the message qualifies for starboard
// based on the guild's settings, it replies to it and adds it to the starboard.
func onReaction(s *discordgo.Session, mra *discordgo.MessageReactionAdd) {
if mra.Emoji.Name != starEmoji {
return
}
msgExists, err := db.ExistsInStarboard(mra.MessageID)
if err != nil {
log.Warn("Error checking if the message exists in the starboard").Err(err).Send()
return
}
// If the message has already been added to the starboard,
// we can skip it.
if msgExists {
return
}
guild, err := db.GuildByID(mra.GuildID)
if err != nil {
log.Warn("Error getting guild from the database").Str("id", mra.GuildID).Err(err).Send()
return
}
// If the guild has no starboard channel ID set, we can
// skip this message.
if guild.StarboardChanID == "" {
return
}
reactions, err := s.MessageReactions(mra.ChannelID, mra.MessageID, starEmoji, guild.StarboardStars, "", "")
if err != nil {
log.Warn("Error getting message reactions").Err(err).Send()
return
}
if len(reactions) >= guild.StarboardStars {
msg, err := s.ChannelMessage(mra.ChannelID, mra.MessageID)
if err != nil {
log.Warn("Error getting channel message").Err(err).Send()
return
}
ch, err := s.Channel(mra.ChannelID)
if err != nil {
log.Warn("Error getting channel").Err(err).Send()
return
}
_, err = s.ChannelMessageSendReply(
msg.ChannelID,
fmt.Sprintf("Congrats %s! You've made it to <#%s>!!", msg.Author.Mention(), guild.StarboardChanID),
msg.Reference(),
)
if err != nil {
log.Warn("Error sending message reply").Err(err).Send()
return
}
embed := &discordgo.MessageEmbed{
Title: fmt.Sprintf("%s - #%s - %s has made it!", starEmoji, ch.Name, msg.Author.Username),
Author: &discordgo.MessageEmbedAuthor{
Name: msg.Author.Username,
IconURL: msg.Author.AvatarURL(""),
},
Description: fmt.Sprintf(
"[**Jump to Message**](https://discord.com/channels/%s/%s/%s)",
mra.GuildID,
msg.ChannelID,
msg.ID,
),
Color: embedColor,
}
eventlog.AddTimeToEmbed(guild.TimeFormat, embed)
if imageURL := getImageURL(msg); imageURL != "" {
// If the message has an image, add it to the embed
embed.Image = &discordgo.MessageEmbedImage{URL: imageURL}
}
if msg.Content != "" {
// If the message has content, we add it above the
// jump to message link currently in the embed description.
embed.Description = fmt.Sprintf(
"**Message Content**\n%s\n\n%s",
msg.Content,
embed.Description,
)
}
_, err = s.ChannelMessageSendEmbed(guild.StarboardChanID, embed)
if err != nil {
log.Warn("Error sending starboard message").Err(err).Send()
return
}
err = db.AddToStarboard(mra.MessageID)
if err != nil {
log.Warn("Error adding message to starboard").Err(err).Send()
return
}
}
}
// getImageURL looks through the message content and attachments
// to try to find images. If it finds one, it returns the URL.
// Otherwise, it returns an empty string.
func getImageURL(msg *discordgo.Message) string {
if xurl := xurls.Strict().FindString(msg.Content); xurl != "" {
u, err := url.Parse(xurl)
if err == nil {
mt := mime.TypeByExtension(path.Ext(u.Path))
if strings.HasPrefix(mt, "image/") {
return xurl
}
}
}
for _, attachment := range msg.Attachments {
if strings.HasPrefix(attachment.ContentType, "image/") {
return attachment.URL
}
}
return ""
}