unarr/internal/engine/notify.go
Deivid Soto 197e33956a feat: improve daemon resilience, streaming, and usenet downloads
- Add daemon state persistence and stale resume file cleanup
- Add TriggerPoll for WebSocket resume actions
- Improve stream server with graceful shutdown and connection tracking
- Add desktop notifications for download completion
- Add media file organization with Movies/TV Shows detection
- Improve usenet downloader with progress tracking and resume support
- Add self-update package with GitHub release verification
- Downgrade tablewriter to v0.0.5 (v1.x API breaking change)
2026-03-28 21:36:12 +01:00

51 lines
1.7 KiB
Go

package engine
import (
"os/exec"
"runtime"
)
// desktopNotify sends a best-effort desktop notification.
// Silent failure — never blocks or errors.
func desktopNotify(title, body string) {
switch runtime.GOOS {
case "linux":
exec.Command("notify-send", title, body, "--icon=dialog-information", "--app-name=unarr").Start()
case "darwin":
script := `display notification "` + escapeAppleScript(body) + `" with title "` + escapeAppleScript(title) + `"`
exec.Command("osascript", "-e", script).Start()
case "windows":
// Use PowerShell toast notification (Windows 10+)
script := `[Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime] > $null;` +
`$xml = [Windows.UI.Notifications.ToastNotificationManager]::GetTemplateContent(1);` +
`$text = $xml.GetElementsByTagName('text');` +
`$text[0].AppendChild($xml.CreateTextNode('` + escapePowerShell(title) + `')) > $null;` +
`$text[1].AppendChild($xml.CreateTextNode('` + escapePowerShell(body) + `')) > $null;` +
`$toast = [Windows.UI.Notifications.ToastNotification]::new($xml);` +
`[Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier('unarr').Show($toast)`
exec.Command("powershell", "-NoProfile", "-Command", script).Start()
}
}
func escapePowerShell(s string) string {
out := make([]byte, 0, len(s))
for i := 0; i < len(s); i++ {
if s[i] == '\'' {
out = append(out, '\'', '\'') // double single-quote to escape
} else {
out = append(out, s[i])
}
}
return string(out)
}
func escapeAppleScript(s string) string {
out := make([]byte, 0, len(s))
for i := 0; i < len(s); i++ {
if s[i] == '"' || s[i] == '\\' {
out = append(out, '\\')
}
out = append(out, s[i])
}
return string(out)
}