diff --git a/Lantean.QBTMud/Helpers/DisplayHelpers.cs b/Lantean.QBTMud/Helpers/DisplayHelpers.cs
index c9c68fd..19d1753 100644
--- a/Lantean.QBTMud/Helpers/DisplayHelpers.cs
+++ b/Lantean.QBTMud/Helpers/DisplayHelpers.cs
@@ -19,28 +19,28 @@ namespace Lantean.QBTMud.Helpers
{
if (seconds is null)
{
- return "";
+ return string.Empty;
}
- if (seconds == 8640000)
+ const long InfiniteEtaSentinelSeconds = 8_640_000; // ~100 days, used by qBittorrent for "infinite" ETA.
+ var value = seconds.Value;
+
+ if (value >= long.MaxValue || value >= (long)TimeSpan.MaxValue.TotalSeconds || value == InfiniteEtaSentinelSeconds)
{
return "∞";
}
- if (seconds < 60)
+ if (value <= 0)
{
return "< 1m";
}
- TimeSpan time;
- try
+ var time = TimeSpan.FromSeconds(value);
+ if (time.TotalMinutes < 1)
{
- time = TimeSpan.FromSeconds(seconds.Value);
- }
- catch
- {
- return "∞";
+ return "< 1m";
}
+
var sb = new StringBuilder();
if (prefix is not null)
{
@@ -83,6 +83,7 @@ namespace Lantean.QBTMud.Helpers
return sb.ToString();
}
+
///
/// Formats a file size in bytes into an appropriate unit based on the size.
///
@@ -418,4 +419,4 @@ namespace Lantean.QBTMud.Helpers
};
}
}
-}
\ No newline at end of file
+}
diff --git a/Lantean.QBTMud/Helpers/FilterHelper.cs b/Lantean.QBTMud/Helpers/FilterHelper.cs
index 4c9f5e2..c5ab51e 100644
--- a/Lantean.QBTMud/Helpers/FilterHelper.cs
+++ b/Lantean.QBTMud/Helpers/FilterHelper.cs
@@ -119,34 +119,34 @@ namespace Lantean.QBTMud.Helpers
switch (category)
{
case CATEGORY_ALL:
- break;
+ return true;
case CATEGORY_UNCATEGORIZED:
if (!string.IsNullOrEmpty(torrent.Category))
{
return false;
}
- break;
+ return true;
default:
+ if (string.IsNullOrEmpty(torrent.Category))
+ {
+ return false;
+ }
+
if (!useSubcategories)
{
- if (torrent.Category != category)
- {
- return false;
- }
- else
- {
- if (!torrent.Category.StartsWith(category))
- {
- return false;
- }
- }
+ return string.Equals(torrent.Category, category, StringComparison.Ordinal);
}
- break;
- }
- return true;
+ if (string.Equals(torrent.Category, category, StringComparison.Ordinal))
+ {
+ return true;
+ }
+
+ var prefix = string.Concat(category, "/");
+ return torrent.Category.StartsWith(prefix, StringComparison.Ordinal);
+ }
}
public static bool FilterTag(Torrent torrent, string tag)
@@ -284,4 +284,4 @@ namespace Lantean.QBTMud.Helpers
};
}
}
-}
\ No newline at end of file
+}
diff --git a/Lantean.QBTMud/Services/DataManager.cs b/Lantean.QBTMud/Services/DataManager.cs
index 7a5e8aa..3552331 100644
--- a/Lantean.QBTMud/Services/DataManager.cs
+++ b/Lantean.QBTMud/Services/DataManager.cs
@@ -39,12 +39,19 @@ namespace Lantean.QBTMud.Services
}
}
- var tags = new List(mainData.Tags?.Count ?? 0);
+ var tags = new List();
if (mainData.Tags is not null)
{
+ var seenTags = new HashSet(StringComparer.Ordinal);
foreach (var tag in mainData.Tags)
{
- tags.Add(tag);
+ var normalizedTag = NormalizeTag(tag);
+ if (string.IsNullOrEmpty(normalizedTag) || !seenTags.Add(normalizedTag))
+ {
+ continue;
+ }
+
+ tags.Add(normalizedTag);
}
}
@@ -157,8 +164,14 @@ namespace Lantean.QBTMud.Services
{
foreach (var tag in mainData.TagsRemoved)
{
- torrentList.Tags.Remove(tag);
- torrentList.TagState.Remove(tag);
+ var normalizedTag = NormalizeTag(tag);
+ if (string.IsNullOrEmpty(normalizedTag))
+ {
+ continue;
+ }
+
+ torrentList.Tags.Remove(normalizedTag);
+ torrentList.TagState.Remove(normalizedTag);
}
}
@@ -200,7 +213,19 @@ namespace Lantean.QBTMud.Services
{
foreach (var tag in mainData.Tags)
{
- torrentList.Tags.Add(tag);
+ var normalizedTag = NormalizeTag(tag);
+ if (string.IsNullOrEmpty(normalizedTag))
+ {
+ continue;
+ }
+
+ torrentList.Tags.Add(normalizedTag);
+ if (!torrentList.TagState.ContainsKey(normalizedTag))
+ {
+ torrentList.TagState[normalizedTag] = torrentList.Torrents.Values
+ .Where(t => FilterHelper.FilterTag(t, normalizedTag))
+ .ToHashesHashSet();
+ }
}
}
@@ -508,6 +533,12 @@ namespace Lantean.QBTMud.Services
public Torrent CreateTorrent(string hash, QBitTorrentClient.Models.Torrent torrent)
{
+ var normalizedTags = torrent.Tags?
+ .Select(NormalizeTag)
+ .Where(static tag => !string.IsNullOrEmpty(tag))
+ .ToList()
+ ?? new List();
+
return new Torrent(
hash,
torrent.AddedOn.GetValueOrDefault(),
@@ -548,7 +579,7 @@ namespace Lantean.QBTMud.Services
torrent.Size.GetValueOrDefault(),
torrent.State!,
torrent.SuperSeeding.GetValueOrDefault(),
- torrent.Tags!,
+ normalizedTags,
torrent.TimeActive.GetValueOrDefault(),
torrent.TotalSize.GetValueOrDefault(),
torrent.Tracker!,
@@ -561,6 +592,19 @@ namespace Lantean.QBTMud.Services
torrent.MaxInactiveSeedingTime.GetValueOrDefault());
}
+ private static string NormalizeTag(string? tag)
+ {
+ if (string.IsNullOrEmpty(tag))
+ {
+ return string.Empty;
+ }
+
+ var separatorIndex = tag.IndexOf('\t');
+ var normalized = (separatorIndex >= 0) ? tag[..separatorIndex] : tag;
+
+ return normalized.Trim();
+ }
+
private static void UpdateCategory(Category existingCategory, QBitTorrentClient.Models.Category category)
{
existingCategory.SavePath = category.SavePath ?? existingCategory.SavePath;
@@ -609,7 +653,14 @@ namespace Lantean.QBTMud.Services
if (torrent.Tags is not null)
{
existingTorrent.Tags.Clear();
- existingTorrent.Tags.AddRange(torrent.Tags);
+ foreach (var tag in torrent.Tags)
+ {
+ var normalizedTag = NormalizeTag(tag);
+ if (!string.IsNullOrEmpty(normalizedTag))
+ {
+ existingTorrent.Tags.Add(normalizedTag);
+ }
+ }
}
existingTorrent.TimeActive = torrent.TimeActive ?? existingTorrent.TimeActive;
existingTorrent.TotalSize = torrent.TotalSize ?? existingTorrent.TotalSize;
@@ -1175,4 +1226,4 @@ namespace Lantean.QBTMud.Services
return new RssList(feeds, articles);
}
}
-}
\ No newline at end of file
+}