Add NotificationBuffer, so Notification are not spammed on every chapter.

This commit is contained in:
Glax 2024-09-22 00:02:43 +02:00
parent 69323d6d60
commit d922842186
7 changed files with 69 additions and 8 deletions

View File

@ -66,10 +66,10 @@ public abstract class GlobalBase
Log(string.Format(fStr, replace)); 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) foreach (NotificationConnector nc in notificationConnectors)
nc.SendNotification(title, text); nc.SendNotification(title, text, buffer);
} }
protected void AddNotificationConnector(NotificationConnector notificationConnector) protected void AddNotificationConnector(NotificationConnector notificationConnector)

View File

@ -37,7 +37,7 @@ public class DownloadChapter : Job
if (success == HttpStatusCode.OK) if (success == HttpStatusCode.OK)
{ {
UpdateLibraries(); UpdateLibraries();
SendNotifications("Chapter downloaded", $"{chapter.parentManga.sortName} - {chapter.chapterNumber}"); SendNotifications("Chapter downloaded", $"{chapter.parentManga.sortName} - {chapter.chapterNumber}", true);
} }
}); });
downloadTask.Start(); downloadTask.Start();

View File

@ -24,7 +24,7 @@ public class Gotify : NotificationConnector
return $"Gotify {endpoint}"; return $"Gotify {endpoint}";
} }
public override void SendNotification(string title, string notificationText) protected override void SendNotificationInternal(string title, string notificationText)
{ {
Log($"Sending notification: {title} - {notificationText}"); Log($"Sending notification: {title} - {notificationText}");
MessageData message = new(title, notificationText); MessageData message = new(title, notificationText);

View File

@ -20,7 +20,7 @@ public class LunaSea : NotificationConnector
return $"LunaSea {id}"; return $"LunaSea {id}";
} }
public override void SendNotification(string title, string notificationText) protected override void SendNotificationInternal(string title, string notificationText)
{ {
Log($"Sending notification: {title} - {notificationText}"); Log($"Sending notification: {title} - {notificationText}");
MessageData message = new(title, notificationText); MessageData message = new(title, notificationText);

View File

@ -3,14 +3,70 @@
public abstract class NotificationConnector : GlobalBase public abstract class NotificationConnector : GlobalBase
{ {
public readonly NotificationConnectorType notificationConnectorType; public readonly NotificationConnectorType notificationConnectorType;
private DateTime? _notificationRequested = null;
private readonly Thread? _notificationBufferThread = null;
private const int NoChangeTimeout = 3, BiggestInterval = 30;
private List<KeyValuePair<string, string>> _notifications = new();
protected NotificationConnector(GlobalBase clone, NotificationConnectorType notificationConnectorType) : base(clone) protected NotificationConnector(GlobalBase clone, NotificationConnectorType notificationConnectorType) : base(clone)
{ {
Log($"Creating notificationConnector {Enum.GetName(notificationConnectorType)}"); Log($"Creating notificationConnector {Enum.GetName(notificationConnectorType)}");
this.notificationConnectorType = 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 enum NotificationConnectorType : byte { Gotify = 0, LunaSea = 1, Ntfy = 2 }
public abstract void SendNotification(string title, string notificationText); 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)})");
}
}
protected abstract void SendNotificationInternal(string title, string notificationText);
} }

View File

@ -54,7 +54,7 @@ public class Ntfy : NotificationConnector
return $"Ntfy {endpoint} {topic}"; 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}"); Log($"Sending notification: {title} - {notificationText}");
MessageData message = new(title, topic, notificationText); MessageData message = new(title, topic, notificationText);

View File

@ -16,6 +16,7 @@ public static class TrangaSettings
public static int apiPortNumber { get; private set; } = 6531; public static int apiPortNumber { get; private set; } = 6531;
public static string userAgent { get; private set; } = DefaultUserAgent; public static string userAgent { get; private set; } = DefaultUserAgent;
public static bool bufferLibraryUpdates { get; private set; } = false; 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 settingsFilePath => Path.Join(workingDirectory, "settings.json");
[JsonIgnore] public static string libraryConnectorsFilePath => Path.Join(workingDirectory, "libraryConnectors.json"); [JsonIgnore] public static string libraryConnectorsFilePath => Path.Join(workingDirectory, "libraryConnectors.json");
[JsonIgnore] public static string notificationConnectorsFilePath => Path.Join(workingDirectory, "notificationConnectors.json"); [JsonIgnore] public static string notificationConnectorsFilePath => Path.Join(workingDirectory, "notificationConnectors.json");
@ -47,7 +48,7 @@ public static class TrangaSettings
ExportSettings(); 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)) if(pWorkingDirectory is null && File.Exists(settingsFilePath))
LoadFromWorkingDirectory(workingDirectory); LoadFromWorkingDirectory(workingDirectory);
@ -57,6 +58,7 @@ public static class TrangaSettings
userAgent = pUserAgent ?? userAgent; userAgent = pUserAgent ?? userAgent;
aprilFoolsMode = pAprilFoolsMode ?? aprilFoolsMode; aprilFoolsMode = pAprilFoolsMode ?? aprilFoolsMode;
bufferLibraryUpdates = pBufferLibraryUpdates ?? bufferLibraryUpdates; bufferLibraryUpdates = pBufferLibraryUpdates ?? bufferLibraryUpdates;
bufferNotifications = pBufferNotifications ?? bufferNotifications;
Directory.CreateDirectory(downloadLocation); Directory.CreateDirectory(downloadLocation);
Directory.CreateDirectory(workingDirectory); Directory.CreateDirectory(workingDirectory);
ExportSettings(); ExportSettings();
@ -164,6 +166,7 @@ public static class TrangaSettings
jobj.Add("version", JToken.FromObject(version)); jobj.Add("version", JToken.FromObject(version));
jobj.Add("requestLimits", JToken.FromObject(requestLimits)); jobj.Add("requestLimits", JToken.FromObject(requestLimits));
jobj.Add("bufferLibraryUpdates", JToken.FromObject(bufferLibraryUpdates)); jobj.Add("bufferLibraryUpdates", JToken.FromObject(bufferLibraryUpdates));
jobj.Add("bufferNotifications", JToken.FromObject(bufferNotifications));
return jobj; return jobj;
} }
@ -186,5 +189,7 @@ public static class TrangaSettings
requestLimits = rl.ToObject<Dictionary<RequestType, int>>()!; requestLimits = rl.ToObject<Dictionary<RequestType, int>>()!;
if (jobj.TryGetValue("bufferLibraryUpdates", out JToken? blu)) if (jobj.TryGetValue("bufferLibraryUpdates", out JToken? blu))
bufferLibraryUpdates = blu.Value<bool>()!; bufferLibraryUpdates = blu.Value<bool>()!;
if (jobj.TryGetValue("bufferNotifications", out JToken? bn))
bufferNotifications = bn.Value<bool>()!;
} }
} }