From d9228421866ee358a463e126c14bd8639013ae76 Mon Sep 17 00:00:00 2001 From: Glax Date: Sun, 22 Sep 2024 00:02:43 +0200 Subject: [PATCH] Add NotificationBuffer, so Notification are not spammed on every chapter. --- Tranga/GlobalBase.cs | 4 +- Tranga/Jobs/DownloadChapter.cs | 2 +- Tranga/NotificationConnectors/Gotify.cs | 2 +- Tranga/NotificationConnectors/LunaSea.cs | 2 +- .../NotificationConnector.cs | 58 ++++++++++++++++++- Tranga/NotificationConnectors/Ntfy.cs | 2 +- Tranga/TrangaSettings.cs | 7 ++- 7 files changed, 69 insertions(+), 8 deletions(-) diff --git a/Tranga/GlobalBase.cs b/Tranga/GlobalBase.cs index 49a0d79..5466cd1 100644 --- a/Tranga/GlobalBase.cs +++ b/Tranga/GlobalBase.cs @@ -66,10 +66,10 @@ public abstract class GlobalBase Log(string.Format(fStr, replace)); } - protected void SendNotifications(string title, string text) + protected void SendNotifications(string title, string text, bool buffer = false) { foreach (NotificationConnector nc in notificationConnectors) - nc.SendNotification(title, text); + nc.SendNotification(title, text, buffer); } protected void AddNotificationConnector(NotificationConnector notificationConnector) diff --git a/Tranga/Jobs/DownloadChapter.cs b/Tranga/Jobs/DownloadChapter.cs index 434736e..4e8456b 100644 --- a/Tranga/Jobs/DownloadChapter.cs +++ b/Tranga/Jobs/DownloadChapter.cs @@ -37,7 +37,7 @@ public class DownloadChapter : Job if (success == HttpStatusCode.OK) { UpdateLibraries(); - SendNotifications("Chapter downloaded", $"{chapter.parentManga.sortName} - {chapter.chapterNumber}"); + SendNotifications("Chapter downloaded", $"{chapter.parentManga.sortName} - {chapter.chapterNumber}", true); } }); downloadTask.Start(); diff --git a/Tranga/NotificationConnectors/Gotify.cs b/Tranga/NotificationConnectors/Gotify.cs index cbe3d9c..3dc7f28 100644 --- a/Tranga/NotificationConnectors/Gotify.cs +++ b/Tranga/NotificationConnectors/Gotify.cs @@ -24,7 +24,7 @@ public class Gotify : NotificationConnector return $"Gotify {endpoint}"; } - public override void SendNotification(string title, string notificationText) + protected override void SendNotificationInternal(string title, string notificationText) { Log($"Sending notification: {title} - {notificationText}"); MessageData message = new(title, notificationText); diff --git a/Tranga/NotificationConnectors/LunaSea.cs b/Tranga/NotificationConnectors/LunaSea.cs index 41c220a..e124192 100644 --- a/Tranga/NotificationConnectors/LunaSea.cs +++ b/Tranga/NotificationConnectors/LunaSea.cs @@ -20,7 +20,7 @@ public class LunaSea : NotificationConnector return $"LunaSea {id}"; } - public override void SendNotification(string title, string notificationText) + protected override void SendNotificationInternal(string title, string notificationText) { Log($"Sending notification: {title} - {notificationText}"); MessageData message = new(title, notificationText); diff --git a/Tranga/NotificationConnectors/NotificationConnector.cs b/Tranga/NotificationConnectors/NotificationConnector.cs index 51b9469..b75813d 100644 --- a/Tranga/NotificationConnectors/NotificationConnector.cs +++ b/Tranga/NotificationConnectors/NotificationConnector.cs @@ -3,14 +3,70 @@ public abstract class NotificationConnector : GlobalBase { public readonly NotificationConnectorType notificationConnectorType; + private DateTime? _notificationRequested = null; + private readonly Thread? _notificationBufferThread = null; + private const int NoChangeTimeout = 3, BiggestInterval = 30; + private List> _notifications = new(); protected NotificationConnector(GlobalBase clone, NotificationConnectorType notificationConnectorType) : base(clone) { Log($"Creating notificationConnector {Enum.GetName(notificationConnectorType)}"); this.notificationConnectorType = notificationConnectorType; + + + if (TrangaSettings.bufferLibraryUpdates) + { + _notificationBufferThread = new(CheckNotificationBuffer); + _notificationBufferThread.Start(); + } + } + + private void CheckNotificationBuffer() + { + while (true) + { + if (_notificationRequested is not null && DateTime.Now.Subtract((DateTime)_notificationRequested) > TimeSpan.FromMinutes(NoChangeTimeout)) //If no updates have been requested for NoChangeTimeout minutes, update library + { + string[] uniqueTitles = _notifications.DistinctBy(n => n.Key).Select(n => n.Key).ToArray(); + Log($"Notification Buffer sending! {string.Join(", ", uniqueTitles)}"); + foreach (string ut in uniqueTitles) + { + string[] texts = _notifications.Where(n => n.Key == ut).Select(n => n.Value).ToArray(); + SendNotificationInternal(ut, string.Join('\n', texts)); + } + _notificationRequested = null; + } + Thread.Sleep(100); + } } public enum NotificationConnectorType : byte { Gotify = 0, LunaSea = 1, Ntfy = 2 } + + public void SendNotification(string title, string notificationText, bool buffer = false) + { + _notificationRequested ??= DateTime.Now; + if (!TrangaSettings.bufferLibraryUpdates || !buffer) + { + SendNotificationInternal(title, notificationText); + return; + } + _notifications.Add(new(title, notificationText)); + if (_notificationRequested is not null && + DateTime.Now.Subtract((DateTime)_notificationRequested) > TimeSpan.FromMinutes(BiggestInterval)) //If the last update has been more than BiggestInterval minutes ago, update library + { + string[] uniqueTitles = _notifications.DistinctBy(n => n.Key).Select(n => n.Key).ToArray(); + foreach (string ut in uniqueTitles) + { + string[] texts = _notifications.Where(n => n.Key == ut).Select(n => n.Value).ToArray(); + SendNotificationInternal(ut, string.Join('\n', texts)); + } + _notificationRequested = null; + } + else if(_notificationRequested is not null) + { + Log($"Buffering Notifications (Updates in latest {((DateTime)_notificationRequested).Add(TimeSpan.FromMinutes(BiggestInterval)).Subtract(DateTime.Now)} or {((DateTime)_notificationRequested).Add(TimeSpan.FromMinutes(NoChangeTimeout)).Subtract(DateTime.Now)})"); + } + } - public abstract void SendNotification(string title, string notificationText); + protected abstract void SendNotificationInternal(string title, string notificationText); } \ No newline at end of file diff --git a/Tranga/NotificationConnectors/Ntfy.cs b/Tranga/NotificationConnectors/Ntfy.cs index f19fe34..afad9a6 100644 --- a/Tranga/NotificationConnectors/Ntfy.cs +++ b/Tranga/NotificationConnectors/Ntfy.cs @@ -54,7 +54,7 @@ public class Ntfy : NotificationConnector return $"Ntfy {endpoint} {topic}"; } - public override void SendNotification(string title, string notificationText) + protected override void SendNotificationInternal(string title, string notificationText) { Log($"Sending notification: {title} - {notificationText}"); MessageData message = new(title, topic, notificationText); diff --git a/Tranga/TrangaSettings.cs b/Tranga/TrangaSettings.cs index 3615d63..ccfa997 100644 --- a/Tranga/TrangaSettings.cs +++ b/Tranga/TrangaSettings.cs @@ -16,6 +16,7 @@ public static class TrangaSettings public static int apiPortNumber { get; private set; } = 6531; public static string userAgent { get; private set; } = DefaultUserAgent; public static bool bufferLibraryUpdates { get; private set; } = false; + public static bool bufferNotifications { get; private set; } = false; [JsonIgnore] public static string settingsFilePath => Path.Join(workingDirectory, "settings.json"); [JsonIgnore] public static string libraryConnectorsFilePath => Path.Join(workingDirectory, "libraryConnectors.json"); [JsonIgnore] public static string notificationConnectorsFilePath => Path.Join(workingDirectory, "notificationConnectors.json"); @@ -47,7 +48,7 @@ public static class TrangaSettings ExportSettings(); } - public static void CreateOrUpdate(string? downloadDirectory = null, string? pWorkingDirectory = null, int? pApiPortNumber = null, string? pUserAgent = null, bool? pAprilFoolsMode = null, bool? pBufferLibraryUpdates = null) + public static void CreateOrUpdate(string? downloadDirectory = null, string? pWorkingDirectory = null, int? pApiPortNumber = null, string? pUserAgent = null, bool? pAprilFoolsMode = null, bool? pBufferLibraryUpdates = null, bool? pBufferNotifications = null) { if(pWorkingDirectory is null && File.Exists(settingsFilePath)) LoadFromWorkingDirectory(workingDirectory); @@ -57,6 +58,7 @@ public static class TrangaSettings userAgent = pUserAgent ?? userAgent; aprilFoolsMode = pAprilFoolsMode ?? aprilFoolsMode; bufferLibraryUpdates = pBufferLibraryUpdates ?? bufferLibraryUpdates; + bufferNotifications = pBufferNotifications ?? bufferNotifications; Directory.CreateDirectory(downloadLocation); Directory.CreateDirectory(workingDirectory); ExportSettings(); @@ -164,6 +166,7 @@ public static class TrangaSettings jobj.Add("version", JToken.FromObject(version)); jobj.Add("requestLimits", JToken.FromObject(requestLimits)); jobj.Add("bufferLibraryUpdates", JToken.FromObject(bufferLibraryUpdates)); + jobj.Add("bufferNotifications", JToken.FromObject(bufferNotifications)); return jobj; } @@ -186,5 +189,7 @@ public static class TrangaSettings requestLimits = rl.ToObject>()!; if (jobj.TryGetValue("bufferLibraryUpdates", out JToken? blu)) bufferLibraryUpdates = blu.Value()!; + if (jobj.TryGetValue("bufferNotifications", out JToken? bn)) + bufferNotifications = bn.Value()!; } } \ No newline at end of file