Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f02547c0e3 | ||
|
|
61e93b5b24 | ||
|
|
f88daf4955 | ||
|
|
93c667422f | ||
|
|
e1978d869c | ||
|
|
cfdfa89009 | ||
|
|
9bee42d7dd | ||
|
|
797ff2b97e | ||
|
|
a67d5c2d1e | ||
|
|
d1d05f8264 | ||
|
|
939b902be3 | ||
|
|
f56d071642 | ||
|
|
7513e7d227 | ||
|
|
7a791dab23 | ||
|
|
402a4deba3 | ||
|
|
d31508fef3 | ||
|
|
1c329e886d |
@@ -5,7 +5,7 @@
|
||||
## Erste Testversion
|
||||
Wer möchte kann den UmlautAdaptarr jetzt gerne testen! Über Feedback würde ich mich sehr freuen!
|
||||
|
||||
Es sollte mit allen *arrs funktionieren, hat aber nur bei Sonarr und Lidarr schon Auswirkungen (abgesehen vom Caching).
|
||||
Es sollte mit allen *arrs funktionieren, hat aber nur bei Sonarr, Readarr und Lidarr schon Auswirkungen (abgesehen vom Caching).
|
||||
|
||||
Momentan ist docker dafür nötig, wer kein Docker nutzt muss sich noch etwas gedulden.
|
||||
|
||||
@@ -30,7 +30,7 @@ UmlautAdaptarr löst mehrere Probleme:
|
||||
|
||||
# Wie macht UmlautAdaptarr das?
|
||||
UmlautAdaptarr tut so, als wäre es ein Indexer. In Wahrheit schaltet sich UmlautAdaptarr aber nur zwischen die *arrs und den echten Indexer und kann somit die Suchen sowie die Ergebnisse abfangen und bearbeiten.
|
||||
Am Ende werden die gefundenen Releases immer so umbenannt, das die Arrs sie einwandfrei erkennen.
|
||||
Am Ende werden die gefundenen Releases immer so umbenannt, dass die Arrs sie einwandfrei erkennen.
|
||||
Einige Beispiele findet ihr unter Features.
|
||||
|
||||
|
||||
@@ -46,6 +46,8 @@ Einige Beispiele findet ihr unter Features.
|
||||
| Releases mit TVDB-Alias Titel werden erkannt | ✓ |
|
||||
| Korrekte Suche und Erkennung von Titel mit Umlauten | ✓ |
|
||||
| Anfragen-Caching für 5 Minuten zur Reduzierung der API-Zugriffe | ✓ |
|
||||
| Usenet (newznab) Support |✓|
|
||||
| Torrent (torznab) Support |✓|
|
||||
| Radarr Support | Geplant |
|
||||
| Prowlarr Unterstützung für "DE" SceneNZBs Kategorien | Geplant |
|
||||
| Unterstützung weiterer Sprachen neben Deutsch | Geplant |
|
||||
|
||||
@@ -98,7 +98,7 @@ namespace UmlautAdaptarr.Providers
|
||||
mediaType: _mediaType
|
||||
);
|
||||
|
||||
logger.LogInformation($"Successfully fetched show {searchItem} from Sonarr.");
|
||||
logger.LogInformation($"Successfully fetched show {searchItem.Title} from Sonarr.");
|
||||
return searchItem;
|
||||
}
|
||||
}
|
||||
@@ -156,7 +156,7 @@ namespace UmlautAdaptarr.Providers
|
||||
mediaType: _mediaType
|
||||
);
|
||||
|
||||
logger.LogInformation($"Successfully fetched show {searchItem} from Sonarr.");
|
||||
logger.LogInformation($"Successfully fetched show {searchItem.Title} from Sonarr.");
|
||||
return searchItem;
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
@@ -96,30 +96,51 @@ namespace UmlautAdaptarr.Services
|
||||
// Use the first few characters of the normalized title for cache prefix search
|
||||
var cacheSearchPrefix = normalizedTitle[..Math.Min(VARIATION_LOOKUP_CACHE_LENGTH, normalizedTitle.Length)];
|
||||
|
||||
SearchItem? bestSearchItemMatch = null;
|
||||
var bestVariationMatchLength = 0;
|
||||
HashSet<string> checkedSearchItems = [];
|
||||
|
||||
if (VariationIndex.TryGetValue(cacheSearchPrefix, out var cacheKeys))
|
||||
{
|
||||
foreach (var cacheKey in cacheKeys)
|
||||
{
|
||||
if (cache.TryGetValue(cacheKey, out SearchItem? item))
|
||||
{
|
||||
if (item?.MediaType != mediaType)
|
||||
if (item == null || item.MediaType != mediaType)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var searchItemIdentifier = $"{item.MediaType}_{item.ExternalId}";
|
||||
|
||||
if (checkedSearchItems.Contains(searchItemIdentifier))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
checkedSearchItems.Add(searchItemIdentifier);
|
||||
}
|
||||
|
||||
// After finding a potential item, compare normalizedTitle with each German title variation
|
||||
foreach (var variation in item?.TitleMatchVariations ?? [])
|
||||
foreach (var variation in item.TitleMatchVariations ?? [])
|
||||
{
|
||||
var normalizedVariation = variation.RemoveAccentButKeepGermanUmlauts().ToLower();
|
||||
if (normalizedTitle.StartsWith(variation, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return item;
|
||||
// If we find a variation match that is "longer" then most likely that one is correct and the earlier match was wrong (if it was from another searchItem)
|
||||
if (variation.Length > bestVariationMatchLength)
|
||||
{
|
||||
bestSearchItemMatch = item;
|
||||
bestVariationMatchLength = variation.Length;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
return bestSearchItemMatch;
|
||||
}
|
||||
|
||||
public SearchItem? GetSearchItemByExternalId(string mediaType, string externalId)
|
||||
|
||||
@@ -11,6 +11,7 @@ namespace UmlautAdaptarr.Services
|
||||
private readonly ILogger<ProxyService> _logger;
|
||||
private readonly IMemoryCache _cache;
|
||||
private static readonly ConcurrentDictionary<string, DateTimeOffset> _lastRequestTimes = new();
|
||||
private static readonly TimeSpan MINIMUM_DELAY_FOR_SAME_HOST = new(0, 0, 0, 1);
|
||||
|
||||
public ProxyService(IHttpClientFactory clientFactory, IConfiguration configuration, ILogger<ProxyService> logger, IMemoryCache cache)
|
||||
{
|
||||
@@ -26,9 +27,9 @@ namespace UmlautAdaptarr.Services
|
||||
if (_lastRequestTimes.TryGetValue(host, out var lastRequestTime))
|
||||
{
|
||||
var timeSinceLastRequest = DateTimeOffset.Now - lastRequestTime;
|
||||
if (timeSinceLastRequest < TimeSpan.FromMilliseconds(1500))
|
||||
if (timeSinceLastRequest < MINIMUM_DELAY_FOR_SAME_HOST)
|
||||
{
|
||||
await Task.Delay(TimeSpan.FromMilliseconds(1500) - timeSinceLastRequest);
|
||||
await Task.Delay(MINIMUM_DELAY_FOR_SAME_HOST - timeSinceLastRequest);
|
||||
}
|
||||
}
|
||||
_lastRequestTimes[host] = DateTimeOffset.Now;
|
||||
|
||||
@@ -262,23 +262,23 @@ namespace UmlautAdaptarr.Services
|
||||
return null;
|
||||
}
|
||||
|
||||
if (category.StartsWith("EBook", StringComparison.OrdinalIgnoreCase) || category.StartsWith("Book", StringComparison.OrdinalIgnoreCase))
|
||||
if (category == "7000" || category.StartsWith("EBook", StringComparison.OrdinalIgnoreCase) || category.StartsWith("Book", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return "book";
|
||||
}
|
||||
else if (category.StartsWith("Movies", StringComparison.OrdinalIgnoreCase))
|
||||
else if (category == "2000" || category.StartsWith("Movies", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return "movies";
|
||||
}
|
||||
else if (category.StartsWith("TV", StringComparison.OrdinalIgnoreCase))
|
||||
else if (category == "5000" || category.StartsWith("TV", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return "tv";
|
||||
}
|
||||
else if (category.Contains("Audiobook", StringComparison.OrdinalIgnoreCase))
|
||||
else if (category == "3030" || category.Contains("Audiobook", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return "book";
|
||||
}
|
||||
else if (category.StartsWith("Audio"))
|
||||
else if (category == "3000" || category.StartsWith("Audio"))
|
||||
{
|
||||
return "audio";
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace UmlautAdaptarr.Utilities
|
||||
// RegEx für eine einfache URL-Validierung ohne http:// und ohne abschließenden Schrägstrich
|
||||
// Erlaubt optionale Subdomains, Domainnamen und TLDs, aber keine Pfade oder Protokolle
|
||||
var regex = UrlMatchingRegex();
|
||||
return regex.IsMatch(domain) && !domain.EndsWith("/");
|
||||
return regex.IsMatch(domain);
|
||||
}
|
||||
|
||||
public static string BuildUrl(string domain, IDictionary<string, string> queryParameters)
|
||||
|
||||
Reference in New Issue
Block a user