Add emoji notification fields

This commit is contained in:
Mikei386
2026-06-21 21:52:21 +02:00
parent 7016992014
commit c014a5f502
8 changed files with 70 additions and 26 deletions
-1
View File
@@ -1 +0,0 @@
ccd839060bbcc55fe1c634eb64869d3e98e2e56f3e8c878d04dc28cbee761d74 urbm-2026.06.21.r011-x86_64-1.txz
+1
View File
@@ -0,0 +1 @@
9c909e42cbe12ca04b7e27661f4f7c1152ca66904f39083d7782fd31c19701ef urbm-2026.06.21.r012-x86_64-1.txz
+6 -2
View File
@@ -2,13 +2,17 @@
<!DOCTYPE PLUGIN [ <!DOCTYPE PLUGIN [
<!ENTITY name "urbm"> <!ENTITY name "urbm">
<!ENTITY author "Michael Roll"> <!ENTITY author "Michael Roll">
<!ENTITY version "2026.06.21.r011"> <!ENTITY version "2026.06.21.r012">
<!ENTITY pluginURL "https://git.casaderoll.de/michael/URBM/raw/branch/main/dist/urbm.plg"> <!ENTITY pluginURL "https://git.casaderoll.de/michael/URBM/raw/branch/main/dist/urbm.plg">
<!ENTITY packageURL "https://git.casaderoll.de/michael/URBM/raw/branch/main/dist/urbm-&version;-x86_64-1.txz"> <!ENTITY packageURL "https://git.casaderoll.de/michael/URBM/raw/branch/main/dist/urbm-&version;-x86_64-1.txz">
<!ENTITY packageSHA256 "ccd839060bbcc55fe1c634eb64869d3e98e2e56f3e8c878d04dc28cbee761d74"> <!ENTITY packageSHA256 "9c909e42cbe12ca04b7e27661f4f7c1152ca66904f39083d7782fd31c19701ef">
]> ]>
<PLUGIN name="&name;" author="&author;" version="&version;" pluginURL="&pluginURL;" min="7.0.0" support="https://git.casaderoll.de/michael/URBM/issues" icon="urbm.png"> <PLUGIN name="&name;" author="&author;" version="&version;" pluginURL="&pluginURL;" min="7.0.0" support="https://git.casaderoll.de/michael/URBM/issues" icon="urbm.png">
<CHANGES> <CHANGES>
### 2026.06.21.r012
- Add emoji-labelled fields to Unraid and Gotify backup notifications.
- Shorten long Restic snapshot IDs in notifications to keep mobile notification cards readable.
### 2026.06.21.r011 ### 2026.06.21.r011
- Increase spacing between folder disclosure controls and checkboxes in all selectable tree browsers. - Increase spacing between folder disclosure controls and checkboxes in all selectable tree browsers.
+2 -2
View File
@@ -11,9 +11,9 @@ import (
func TestNotificationMessageIncludesBackupStatistics(t *testing.T) { func TestNotificationMessageIncludesBackupStatistics(t *testing.T) {
started := time.Date(2026, 6, 14, 12, 0, 0, 0, time.UTC) started := time.Date(2026, 6, 14, 12, 0, 0, 0, time.UTC)
finished := started.Add(2*time.Minute + 8*time.Second) finished := started.Add(2*time.Minute + 8*time.Second)
run := model.Run{TaskType: "backup", Status: "success", StartedAt: &started, FinishedAt: &finished, SnapshotID: "abc123", BytesAdded: 1536, FilesNew: 7, FilesChanged: 2, BytesProcessed: 5 * 1024 * 1024, FilesProcessed: 120} run := model.Run{TaskType: "backup", Status: "success", StartedAt: &started, FinishedAt: &finished, SnapshotID: "abc123456789abcdef", BytesAdded: 1536, FilesNew: 7, FilesChanged: 2, BytesProcessed: 5 * 1024 * 1024, FilesProcessed: 120}
message := notificationMessage("Freigaben", "LV-426", run, finished) message := notificationMessage("Freigaben", "LV-426", run, finished)
for _, expected := range []string{"📊 URBM-Zusammenfassung", "Status: Erfolgreich", "Job: Freigaben", "Repository: LV-426", "Dauer: 2 Min. 8 Sek.", "Snapshot: abc123", "Verarbeitete Daten: 5.0 MiB", "Verarbeitete Dateien: 120", "Neu gespeichert: 1.5 KiB", "Neue Dateien: 7", "Geänderte Dateien: 2"} { for _, expected := range []string{"📊 Backup-Zusammenfassung", "📦 Repository: LV-426", "🗂️ Job: Freigaben", "📸 Snapshot: abc123456789", "⏱️ Dauer: 2 Min. 8 Sek.", "📂 Dateien: 120 verarbeitet", "💾 Verarbeitet: 5.0 MiB", " Neu: 7 Dateien", "✏️ Geändert: 2 Dateien", "📤 Neu gespeichert: 1.5 KiB", "🔐 Ziel: Restic Repository", "✅ Status: Erfolgreich"} {
if !strings.Contains(message, expected) { if !strings.Contains(message, expected) {
t.Errorf("message %q does not contain %q", message, expected) t.Errorf("message %q does not contain %q", message, expected)
} }
+52 -16
View File
@@ -795,12 +795,15 @@ func notificationMessage(name, repository string, run model.Run, now time.Time)
if status == "" { if status == "" {
status = run.Status status = run.Status
} }
lines := []string{"📊 URBM-Zusammenfassung", "", "Status: " + status} lines := []string{"📊 Backup-Zusammenfassung", ""}
if name != "" {
lines = append(lines, "Job: "+name)
}
if repository != "" { if repository != "" {
lines = append(lines, "Repository: "+repository) lines = append(lines, "📦 Repository: "+repository)
}
if name != "" {
lines = append(lines, "🗂️ Job: "+name)
}
if run.TaskType == "backup" && run.SnapshotID != "" {
lines = append(lines, "📸 Snapshot: "+shortID(run.SnapshotID))
} }
if run.StartedAt != nil { if run.StartedAt != nil {
finished := now finished := now
@@ -808,33 +811,66 @@ func notificationMessage(name, repository string, run model.Run, now time.Time)
finished = *run.FinishedAt finished = *run.FinishedAt
} }
if duration := finished.Sub(*run.StartedAt); duration >= 0 { if duration := finished.Sub(*run.StartedAt); duration >= 0 {
lines = append(lines, "Dauer: "+formatDuration(duration)) lines = append(lines, "", "⏱️ Dauer: "+formatDuration(duration))
} }
} }
if (run.TaskType == "backup" || run.TaskType == "rsync") && (run.Status == "success" || run.Status == "warning") { if (run.TaskType == "backup" || run.TaskType == "rsync") && (run.Status == "success" || run.Status == "warning") {
if run.TaskType == "backup" && run.SnapshotID != "" {
lines = append(lines, "Snapshot: "+run.SnapshotID)
}
lines = append(lines, lines = append(lines,
"Verarbeitete Daten: "+formatBytes(run.BytesProcessed), fmt.Sprintf("📂 Dateien: %d verarbeitet", run.FilesProcessed),
fmt.Sprintf("Verarbeitete Dateien: %d", run.FilesProcessed), "💾 Verarbeitet: "+formatBytes(run.BytesProcessed),
) )
if run.TaskType == "backup" { if run.TaskType == "backup" {
lines = append(lines, lines = append(lines,
"Neu gespeichert: "+formatBytes(run.BytesAdded), fmt.Sprintf(" Neu: %d Dateien", run.FilesNew),
fmt.Sprintf("Neue Dateien: %d", run.FilesNew), fmt.Sprintf("✏️ Geändert: %d Dateien", run.FilesChanged),
fmt.Sprintf("Geänderte Dateien: %d", run.FilesChanged), "📤 Neu gespeichert: "+formatBytes(run.BytesAdded),
) )
} else { } else {
lines = append(lines, "Kopierte Daten: "+formatBytes(run.BytesAdded)) lines = append(lines, "📤 Kopiert: "+formatBytes(run.BytesAdded))
} }
} }
lines = append(lines, "", "🔐 Ziel: "+notificationTargetLabel(run.TaskType), statusIcon(run.Status)+" Status: "+status)
if run.Message != "" && run.Message != "backup completed" && run.Message != "rsync completed" { if run.Message != "" && run.Message != "backup completed" && run.Message != "rsync completed" {
lines = append(lines, "Details: "+run.Message) lines = append(lines, "⚠️ Details: "+run.Message)
} }
return strings.Join(lines, "\n") return strings.Join(lines, "\n")
} }
func statusIcon(status string) string {
switch status {
case "success":
return "✅"
case "warning":
return "⚠️"
case "failed":
return "❌"
default:
return "️"
}
}
func notificationTargetLabel(taskType string) string {
switch taskType {
case "backup":
return "Restic Repository"
case "rsync":
return "Rsync Ziel"
case "restore":
return "Restore Ziel"
case "check", "prune":
return "Restic Repository"
default:
return "URBM"
}
}
func shortID(value string) string {
if len(value) <= 12 {
return value
}
return value[:12]
}
func formatBytes(value int64) string { func formatBytes(value int64) string {
const unit = int64(1024) const unit = int64(1024)
if value < unit { if value < unit {
+5 -1
View File
@@ -2,13 +2,17 @@
<!DOCTYPE PLUGIN [ <!DOCTYPE PLUGIN [
<!ENTITY name "urbm"> <!ENTITY name "urbm">
<!ENTITY author "Michael Roll"> <!ENTITY author "Michael Roll">
<!ENTITY version "2026.06.21.r011"> <!ENTITY version "2026.06.21.r012">
<!ENTITY pluginURL "https://git.casaderoll.de/michael/URBM/raw/branch/main/dist/urbm.plg"> <!ENTITY pluginURL "https://git.casaderoll.de/michael/URBM/raw/branch/main/dist/urbm.plg">
<!ENTITY packageURL "https://git.casaderoll.de/michael/URBM/raw/branch/main/dist/urbm-&version;-x86_64-1.txz"> <!ENTITY packageURL "https://git.casaderoll.de/michael/URBM/raw/branch/main/dist/urbm-&version;-x86_64-1.txz">
<!ENTITY packageSHA256 "REPLACE_DURING_RELEASE"> <!ENTITY packageSHA256 "REPLACE_DURING_RELEASE">
]> ]>
<PLUGIN name="&name;" author="&author;" version="&version;" pluginURL="&pluginURL;" min="7.0.0" support="https://git.casaderoll.de/michael/URBM/issues" icon="urbm.png"> <PLUGIN name="&name;" author="&author;" version="&version;" pluginURL="&pluginURL;" min="7.0.0" support="https://git.casaderoll.de/michael/URBM/issues" icon="urbm.png">
<CHANGES> <CHANGES>
### 2026.06.21.r012
- Add emoji-labelled fields to Unraid and Gotify backup notifications.
- Shorten long Restic snapshot IDs in notifications to keep mobile notification cards readable.
### 2026.06.21.r011 ### 2026.06.21.r011
- Increase spacing between folder disclosure controls and checkboxes in all selectable tree browsers. - Increase spacing between folder disclosure controls and checkboxes in all selectable tree browsers.
+4 -4
View File
@@ -9,12 +9,12 @@ Tag="URBM Unraid Restic Backup Manager backup snapshots restore"
<?php <?php
$pluginRoot = '/plugins/urbm'; $pluginRoot = '/plugins/urbm';
?> ?>
<link rel="stylesheet" href="<?= $pluginRoot ?>/assets/urbm.css?v=20260621r011"> <link rel="stylesheet" href="<?= $pluginRoot ?>/assets/urbm.css?v=20260621r012">
<div id="urbm-app" data-api="<?= $pluginRoot ?>/api.php"> <div id="urbm-app" data-api="<?= $pluginRoot ?>/api.php">
<header class="bu-header"> <header class="bu-header">
<div class="bu-brand"> <div class="bu-brand">
<img class="bu-logo" src="<?= $pluginRoot ?>/images/urbm.png?v=20260621r011" alt="URBM-Logo"> <img class="bu-logo" src="<?= $pluginRoot ?>/images/urbm.png?v=20260621r012" alt="URBM-Logo">
<div><h1>URBM <span class="bu-version">2026.06.21.r011</span></h1><p>Restic Backup Manager für Unraid</p></div> <div><h1>URBM <span class="bu-version">2026.06.21.r012</span></h1><p>Restic Backup Manager für Unraid</p></div>
</div> </div>
<div id="bu-health" class="bu-health" tabindex="0" data-tooltip="Zeigt, ob die URBM-Hintergrundkomponente erreichbar ist. Beispiel: 'Daemon online' bedeutet, dass Jobs gestartet werden können.">Verbindung wird hergestellt...</div> <div id="bu-health" class="bu-health" tabindex="0" data-tooltip="Zeigt, ob die URBM-Hintergrundkomponente erreichbar ist. Beispiel: 'Daemon online' bedeutet, dass Jobs gestartet werden können.">Verbindung wird hergestellt...</div>
</header> </header>
@@ -32,4 +32,4 @@ $pluginRoot = '/plugins/urbm';
<div id="bu-tooltip" role="tooltip" aria-hidden="true"></div> <div id="bu-tooltip" role="tooltip" aria-hidden="true"></div>
</div> </div>
<script>window.URBM_CSRF = <?= json_encode($var['csrf_token'] ?? '') ?>;</script> <script>window.URBM_CSRF = <?= json_encode($var['csrf_token'] ?? '') ?>;</script>
<script src="<?= $pluginRoot ?>/assets/urbm-2026.06.21.r011.js"></script> <script src="<?= $pluginRoot ?>/assets/urbm-2026.06.21.r012.js"></script>