discordo/internal/notifications/notifications.go
2025-04-17 19:31:30 -04:00

117 lines
2.8 KiB
Go

package notifications
import (
"io"
"log/slog"
"net/http"
"os"
"path/filepath"
"strings"
"github.com/ayn2op/discordo/internal/config"
"github.com/ayn2op/discordo/internal/consts"
"github.com/diamondburned/arikawa/v3/discord"
"github.com/diamondburned/arikawa/v3/gateway"
"github.com/diamondburned/ningen/v3"
"github.com/diamondburned/ningen/v3/discordmd"
)
func HandleIncomingMessage(s ningen.State, m *gateway.MessageCreateEvent, cfg *config.Config) error {
// Only display notification if enabled and unmuted
if !cfg.Notifications.Enabled || s.MessageMentions(&m.Message) == 0 || cfg.Identify.Status == discord.DoNotDisturbStatus {
return nil
}
ch, err := s.Cabinet.Channel(m.ChannelID)
if err != nil {
return err
}
isChannelDM := ch.Type == discord.DirectMessage || ch.Type == discord.GroupDM
guild := (*discord.Guild)(nil)
if !isChannelDM {
guild, err = s.Cabinet.Guild(ch.GuildID)
if err != nil {
return err
}
}
// Render message
src := []byte(m.Content)
ast := discordmd.ParseWithMessage(src, *s.Cabinet, &m.Message, false)
buff := strings.Builder{}
if err := PlainTextRenderer.Render(&buff, src, ast); err != nil {
return err
}
// Handle sent files
notifContent := buff.String()
if m.Message.Content == "" && len(m.Message.Attachments) > 0 {
notifContent = "Uploaded " + m.Message.Attachments[0].Filename
}
if m.Author.DisplayOrTag() == "" || notifContent == "" {
return nil
}
notifTitle := m.Author.DisplayOrTag()
if guild != nil {
member, _ := s.Member(ch.GuildID, m.Author.ID)
if member.Nick != "" {
notifTitle = member.Nick
}
notifTitle = notifTitle + " (#" + ch.Name + ", " + guild.Name + ")"
}
hash := m.Author.Avatar
if hash == "" {
hash = "default"
}
imagePath, err := getCachedProfileImage(hash, m.Author.AvatarURLWithType(discord.PNGImage))
if err != nil {
slog.Error("Failed to retrieve avatar image for notification", "err", err)
}
shouldChime := cfg.Notifications.Sound.Enabled && (!cfg.Notifications.Sound.OnlyOnPing || (isChannelDM || s.MessageMentions(&m.Message) == 3))
if err := sendDesktopNotification(notifTitle, notifContent, imagePath, shouldChime, cfg.Notifications.Duration); err != nil {
return err
}
return nil
}
func getCachedProfileImage(avatarHash discord.Hash, url string) (string, error) {
path, err := os.UserCacheDir()
if err != nil {
return "", err
}
path = filepath.Join(path, consts.Name)
if err := os.MkdirAll(path, os.ModePerm); err != nil {
return "", err
}
path = filepath.Join(path, avatarHash+".png")
if _, err := os.Stat(path); err == nil {
return path, nil
}
image, err := os.Create(path)
if err != nil {
return "", err
}
defer image.Close()
resp, err := http.Get(url)
if err != nil {
return "", err
}
defer resp.Body.Close()
if _, err := io.Copy(image, resp.Body); err != nil {
return "", err
}
return path, nil
}