12 Commits

Author SHA1 Message Date
Jonas F
b8539b109e Merge pull request #39 from PCJones/develop
Release 0.6
2024-10-11 19:47:24 +02:00
Jonas F
4e030168ee Update docker-compose.yml 2024-10-11 19:47:08 +02:00
Jonas F
5487009306 Update README.md 2024-10-11 19:24:41 +02:00
Jonas F
fc7c0bde28 Add star history to readme 2024-10-11 18:36:17 +02:00
pcjones
fde9b0a5de Remove unnecessary import 2024-09-30 14:03:36 +02:00
pcjones
94b2cf94c4 Don't spam the log with debug info 2024-09-30 14:03:18 +02:00
pcjones
4a628f7c66 Add missing StringComparison.OrdinalIgnoreCase 2024-09-30 14:02:30 +02:00
pcjones
30e1d3aa11 Fix season matching pattern to match up to 4 digit seasons/episodes 2024-09-22 21:14:35 +02:00
pcjones
5e479661fb Fix reachable check 2024-09-10 18:01:34 +02:00
pcjones
4be90e74b3 Fix reachable check for ultra cc seedbox 2024-09-10 17:52:36 +02:00
pcjones
fcf85a5ad1 AllowAutoRedirect for BeReachable check 2024-09-10 17:38:44 +02:00
pcjones
abff4953e8 Read port from appsettings 2024-09-10 17:08:35 +02:00
6 changed files with 95 additions and 46 deletions

View File

@@ -1,15 +1,14 @@
# UmlautAdaptarr # UmlautAdaptarr
## English description coming soon A tool to work around Sonarr, Radarr, Lidarr and Readarrs problems with foreign languages.
## Detailed English description coming soon
## Beschreibung ## Beschreibung
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, Readarr und Lidarr schon Auswirkungen (abgesehen vom Caching).
UmlautAdaptarr löst mehrere Probleme: UmlautAdaptarr löst mehrere Probleme:
- Releases mit Umlauten werden grundsätzlich nicht korrekt von den *Arrs importiert - Releases mit Umlauten werden grundsätzlich nicht korrekt von den *arrs importiert
- Releases mit Umlauten werden oft nicht korrekt gefunden (*Arrs suchen nach "o" statt "ö" & es fehlt häufig die korrekte Zuordnung zur Serie/zum Film beim Indexer) - Releases mit Umlauten werden oft nicht korrekt gefunden (*arrs suchen nach "o" statt "ö" & es fehlt häufig die korrekte Zuordnung zur Serie/zum Film beim Indexer)
- Sonarr & Radarr erwarten immer den englischen Titel von https://thetvdb.com/ bzw. https://www.themoviedb.org/. Das führt bei deutschen Produktionen oder deutschen Übersetzungen oft zu Problemen - falls die *arrs schon mal etwas mit der Meldung `Found matching series/movie via grab history, but release was matched to series by ID. Automatic import is not possible/` nicht importiert haben, dann war das der Grund. - Sonarr & Radarr erwarten immer den englischen Titel von https://thetvdb.com/ bzw. https://www.themoviedb.org/. Das führt bei deutschen Produktionen oder deutschen Übersetzungen oft zu Problemen - falls die *arrs schon mal etwas mit der Meldung `Found matching series/movie via grab history, but release was matched to series by ID. Automatic import is not possible/` nicht importiert haben, dann war das der Grund.
- Releases mit schlechtem Naming (z.B. von der Group TvR die kein "GERMAN" in den Releasename tun) werden korrigiert, so dass Sonarr&Radarr diese korrekt erkennen (optional) - Releases mit schlechtem Naming (z.B. von der Group TvR die kein "GERMAN" in den Releasename tun) werden korrigiert, so dass Sonarr&Radarr diese korrekt erkennen (optional)
- Zusätzlich werden einige andere Fehler behoben, die häufig dazu führen, dass Titel nicht erfolgreich gefunden, geladen oder importiert werden. - Zusätzlich werden einige andere Fehler behoben, die häufig dazu führen, dass Titel nicht erfolgreich gefunden, geladen oder importiert werden.
@@ -24,21 +23,20 @@ Einige Beispiele finden sich [weiter unten](https://github.com/PCJones/UmlautAda
| Feature | Status | | Feature | Status |
|-------------------------------------------------------------------|---------------| |-------------------------------------------------------------------|---------------|
| Prowlarr & NZB Hydra Support | ✓| | Prowlarr & NZB Hydra Support |✓ |
| Sonarr Support | ✓ | | Sonarr Support |✓ |
| Lidarr Support | ✓| | Lidarr Support |✓ |
| Readarr Support | ✓ | | Readarr Support |✓ |
| Releases mit deutschem Titel werden erkannt | ✓ | | Releases mit deutschem Titel werden erkannt |✓ |
| Releases mit TVDB-Alias Titel werden erkannt | ✓ | | Releases mit TVDB-Alias Titel werden erkannt |✓ |
| Korrekte Suche und Erkennung von Titel mit Umlauten | ✓ | | Korrekte Suche und Erkennung von Titel mit Umlauten |✓ |
| Anfragen-Caching für 12 Minuten zur Reduzierung der API-Zugriffe | ✓ | | Anfragen-Caching für 12 Minuten zur Reduzierung der API-Zugriff |✓ |
| Usenet (newznab) Support |✓| | Usenet (newznab) Support |✓ |
| Torrent (torznab) Support |✓| | Torrent (torznab) Support |✓ |
| Support von mehreren *arr-Instanzen des gleichen Typs (z.B. 2x Sonarr) | | Support von mehreren *arr-Instanzen des gleichen Typs (z.B. 2x Sonarr)|✓ |
| Releases mit mit schlechtem Naming werden korrekt umbenannt (optional) | in Arbeit | | Releases mit mit schlechtem Naming werden korrekt umbenannt (optional) | in Arbeit|
| Radarr Support | in Arbeit | | Radarr Support | in Arbeit |
| Webinterface | Geplant | | Webinterface | Geplant |
| Prowlarr Unterstützung für "DE" SceneNZBs Kategorien | Geplant |
| Unterstützung weiterer Sprachen neben Deutsch | Geplant | | Unterstützung weiterer Sprachen neben Deutsch | Geplant |
| Wünsche? | Vorschläge? | | Wünsche? | Vorschläge? |
@@ -48,13 +46,14 @@ Momentan ist Docker dafür nötig, wer kein Docker nutzt muss sich noch etwas ge
[Link zum Docker Image](https://hub.docker.com/r/pcjones/umlautadaptarr) [Link zum Docker Image](https://hub.docker.com/r/pcjones/umlautadaptarr)
Nicht benötigte Umgebungsvariablen, z.B. wenn Readarr oder Lidarr nicht benötigt werden, können entfernt werden. Nicht benötigte Umgebungsvariablen, z.B. falls Readarr oder Lidarr nicht genutzt werden, können entfernt werden.
### Konfiguration in Prowlarr (**empfohlen**) ### Konfiguration in Prowlarr (**empfohlen**)
Das ist die **empfohlene** Methode um den UmlautAdaptarr einzurichten. Sie hat den Vorteil, dass es, sofern man mehrere Indexer nutzt, keinen Geschwindigkeitsverlust bei der Suche geben sollte. Das ist die **empfohlene** Methode um den UmlautAdaptarr einzurichten. Sie hat den Vorteil, dass es, sofern man mehrere Indexer nutzt, keinen Geschwindigkeitsverlust bei der Suche geben sollte.
1) In Prowlarr: Settings>Indexers bzw. Einstellungen>Indexer öffnen 1) Setze die benötigten [Docker Umgebungsvariablen](https://hub.docker.com/r/pcjones/umlautadaptarr) in deiner docker-compose Datei bzw. in deinem docker run Befehl
2) Lege einen neuen HTTP-Proxy an: 2) In Prowlarr: Settings>Indexers bzw. Einstellungen>Indexer öffnen
3) Lege einen neuen HTTP-Proxy an:
![Image](https://github.com/PCJones/UmlautAdaptarr/assets/377223/b97418d8-d972-4e3c-9d2f-3a830a5ac0a3) ![Image](https://github.com/PCJones/UmlautAdaptarr/assets/377223/b97418d8-d972-4e3c-9d2f-3a830a5ac0a3)
@@ -63,19 +62,20 @@ Das ist die **empfohlene** Methode um den UmlautAdaptarr einzurichten. Sie hat d
- Tag: `umlautadaptarr` - Tag: `umlautadaptarr`
- Host: Je nachdem, wie deine Docker-Konfiguration ist, kann es sein, dass du entweder `umlautadaptarr` oder `localhost`, oder ggf. die IP des Host setzen musst. Probiere es sonst einfach aus, indem du auf Test klickst. - Host: Je nachdem, wie deine Docker-Konfiguration ist, kann es sein, dass du entweder `umlautadaptarr` oder `localhost`, oder ggf. die IP des Host setzen musst. Probiere es sonst einfach aus, indem du auf Test klickst.
- Die Username- und Passwort-Felder können leergelassen werden. - Die Username- und Passwort-Felder können leergelassen werden.
3) Gehe zur Indexer-Übersichtsseite 4) Gehe zur Indexer-Übersichtsseite
4) Für alle Indexer/Tracker, die den UmlautAdaptarr nutzen sollen: 5) Für alle Indexer/Tracker, die den UmlautAdaptarr nutzen sollen:
![grafik](https://github.com/PCJones/UmlautAdaptarr/assets/377223/3daea3f1-7c7b-4982-84e2-ea6a42d90fba) ![grafik](https://github.com/PCJones/UmlautAdaptarr/assets/377223/3daea3f1-7c7b-4982-84e2-ea6a42d90fba)
- Füge den `umlautadaptarr` Tag hinzu - Füge den `umlautadaptarr` Tag hinzu
- **Wichtig:** Ändere die URL von `https` zu `http`. (Dies ist erforderlich, damit der UmlautAdaptarr die Anfragen **lokal** abfangen kann. **Ausgehende** Anfragen an den Indexer verwenden natürlich weiterhin https). - **Wichtig:** Ändere die URL von `https` zu `http`. (Dies ist erforderlich, damit der UmlautAdaptarr die Anfragen **lokal** abfangen kann. **Ausgehende** Anfragen an den Indexer verwenden natürlich weiterhin https).
5) Klicke danach auf `Test All Indexers` bzw `Alle Indexer Testen`. Falls du irgendwo noch `https` statt `http` stehen hast, sollte in den UmlautAdaptarr logs eine Warnung auftauchen. Mindestens solltest du aber noch ein zweites Mal alle Indexer durchgehen und überprüfen, ob überall `http` eingestellt ist - Indexer, bei denen noch `https` steht, werden nämlich einwandfrei funktionieren - allerdings ohne, dass der UmlautAdaptarr bei diesen wirken kann. 6) Klicke danach auf `Test All Indexers` bzw `Alle Indexer Testen`. Falls du irgendwo noch `https` statt `http` stehen hast, sollte in den UmlautAdaptarr logs eine Warnung auftauchen. Mindestens solltest du aber noch ein zweites Mal alle Indexer durchgehen und überprüfen, ob überall `http` eingestellt ist - Indexer, bei denen noch `https` steht, werden nämlich einwandfrei funktionieren - allerdings ohne, dass der UmlautAdaptarr bei diesen wirken kann.
### Konfiguration in Sonarr/Radarr oder Prowlarr ohne Proxy ### Konfiguration in Sonarr/Radarr oder Prowlarr ohne Proxy
Falls du kein Prowlarr nutzt oder nur 1-3 Indexer nutzt, kannst du diese alternative Konfigurationsmöglichkeit nutzen. Falls du kein Prowlarr nutzt oder nur 1-3 Indexer nutzt, kannst du diese alternative Konfigurationsmöglichkeit nutzen.
Dafür musst du einfach nur alle Indexer, bei denen der UmlautAdaptarr greifen soll, bearbeiten: 1) Setze die benötigten [Docker Umgebungsvariablen](https://hub.docker.com/r/pcjones/umlautadaptarr) in deiner docker-compose Datei bzw. in deinem docker run Befehl
2) Bearbeite alle Indexer, bei denen der UmlautAdaptarr greifen soll, wie folgt:
Am Beispiel von sceneNZBs: Am Beispiel von sceneNZBs:
@@ -132,3 +132,7 @@ Für andere Spendenmöglichkeiten gerne auf Discord oder Telegram melden - danke
- TV Metadata source: https://thetvdb.com - TV Metadata source: https://thetvdb.com
- Movie Metadata source: https://themoviedb.org - Movie Metadata source: https://themoviedb.org
- Licenses: TODO - Licenses: TODO
## Star History
[![Star History Chart](https://api.star-history.com/svg?repos=pcjones/umlautadaptarr&type=Date)](https://star-history.com/#pcjones/umlautadaptarr&Date)

View File

@@ -1,7 +1,6 @@
using System.Net; using System.Net;
using Serilog; using Serilog;
using Serilog.Filters; using Serilog.Filters;
using UmlautAdaptarr.Options;
using UmlautAdaptarr.Routing; using UmlautAdaptarr.Routing;
using UmlautAdaptarr.Services; using UmlautAdaptarr.Services;
using UmlautAdaptarr.Services.Factory; using UmlautAdaptarr.Services.Factory;
@@ -17,16 +16,7 @@ internal class Program
// add option to sort by nzb age // add option to sort by nzb age
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);
var configuration = builder.Configuration; var configuration = builder.Configuration;
ConfigureLogger(configuration);
// TODO workaround to not log api keys
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(configuration)
.WriteTo.Console(outputTemplate: "[{Timestamp:yyyy-MM-dd HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}")
.Filter.ByExcluding(Matching.FromSource("System.Net.Http.HttpClient"))
.Filter.ByExcluding(Matching.FromSource("Microsoft.Extensions.Http.DefaultHttpClientFactory"))
//.Enrich.With(new ApiKeyMaskingEnricher("appsettings.json")) // TODO - Not working currently
.CreateLogger();
builder.Services.AddSerilog(); builder.Services.AddSerilog();
@@ -99,4 +89,24 @@ internal class Program
new { t = new TRouteConstraint("search") }); new { t = new TRouteConstraint("search") });
app.Run(); app.Run();
} }
private static void ConfigureLogger(ConfigurationManager configuration)
{
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(configuration)
.WriteTo.Console(outputTemplate: "[{Timestamp:yyyy-MM-dd HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}")
#if RELEASE
.Filter.ByExcluding(Matching.FromSource("Microsoft.AspNetCore.Mvc"))
.Filter.ByExcluding(Matching.FromSource("Microsoft.AspNetCore.Routing"))
.Filter.ByExcluding(Matching.FromSource("Microsoft.AspNetCore.Diagnostics"))
.Filter.ByExcluding(Matching.FromSource("Microsoft.AspNetCore.Hosting"))
#endif
// TODO workaround to not log api keys
.Filter.ByExcluding(Matching.FromSource("System.Net.Http.HttpClient"))
.Filter.ByExcluding(Matching.FromSource("Microsoft.Extensions.Http.DefaultHttpClientFactory"))
//.Enrich.With(new ApiKeyMaskingEnricher("appsettings.json")) // TODO - Not working currently
.CreateLogger();
}
} }

View File

@@ -12,11 +12,13 @@ namespace UmlautAdaptarr.Services
private readonly IHttpClientFactory _clientFactory; private readonly IHttpClientFactory _clientFactory;
private readonly HashSet<string> _knownHosts = []; private readonly HashSet<string> _knownHosts = [];
private readonly object _hostsLock = new(); private readonly object _hostsLock = new();
private readonly IConfiguration _configuration;
private static readonly string[] newLineSeparator = ["\r\n"]; private static readonly string[] newLineSeparator = ["\r\n"];
public HttpProxyService(ILogger<HttpProxyService> logger, IHttpClientFactory clientFactory) public HttpProxyService(ILogger<HttpProxyService> logger, IHttpClientFactory clientFactory, IConfiguration configuration)
{ {
_logger = logger; _logger = logger;
_configuration = configuration;
_clientFactory = clientFactory; _clientFactory = clientFactory;
_knownHosts.Add("prowlarr.servarr.com"); _knownHosts.Add("prowlarr.servarr.com");
} }
@@ -91,7 +93,10 @@ namespace UmlautAdaptarr.Services
} }
} }
var modifiedUri = $"http://localhost:5005/_/{uri.Host}{uri.PathAndQuery}"; // TODO read port from appsettings? var url = _configuration["Kestrel:Endpoints:Http:Url"];
var port = new Uri(url).Port;
var modifiedUri = $"http://localhost:{port}/_/{uri.Host}{uri.PathAndQuery}";
using var client = _clientFactory.CreateClient(); using var client = _clientFactory.CreateClient();
var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, modifiedUri); var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, modifiedUri);
httpRequestMessage.Headers.Add("User-Agent", userAgent); httpRequestMessage.Headers.Add("User-Agent", userAgent);

View File

@@ -196,9 +196,9 @@ namespace UmlautAdaptarr.Services
// Workaround for the rare case of e.g. "Frieren: Beyond Journey's End" that also has the alias "Frieren" // Workaround for the rare case of e.g. "Frieren: Beyond Journey's End" that also has the alias "Frieren"
if (expectedTitle!.StartsWith(variation, StringComparison.OrdinalIgnoreCase)) if (expectedTitle!.StartsWith(variation, StringComparison.OrdinalIgnoreCase))
{ {
// See if we already matched the whole title by checking if S01E01 pattern is coming next to avoid false positives // See if we already matched the whole title by checking if S01E01/S2024E123 pattern is coming next to avoid false positives
// - that won't help with movies but with tv shows // - that won't help with movies but with tv shows
var seasonMatchingPattern = $"^{separator}S\\d{{1,2}}E\\d{{1,2}}"; var seasonMatchingPattern = $"^{separator}S\\d{{1,4}}E\\d{{1,4}}";
if (!Regex.IsMatch(suffix, seasonMatchingPattern)) if (!Regex.IsMatch(suffix, seasonMatchingPattern))
{ {
logger.LogWarning($"TitleMatchingService - Didn't rename: '{originalTitle}' because the expected title '{expectedTitle}' starts with the variation '{variation}'"); logger.LogWarning($"TitleMatchingService - Didn't rename: '{originalTitle}' because the expected title '{expectedTitle}' starts with the variation '{variation}'");
@@ -314,7 +314,7 @@ namespace UmlautAdaptarr.Services
{ {
return "book"; return "book";
} }
else if (category == "3000" || category.StartsWith("Audio")) else if (category == "3000" || category.StartsWith("Audio", StringComparison.OrdinalIgnoreCase))
{ {
return "audio"; return "audio";
} }

View File

@@ -38,13 +38,34 @@ public class GlobalInstanceOptionsValidator : AbstractValidator<GlobalInstanceOp
{ {
try try
{ {
var request = WebRequest.Create(url); // TODO use HttpClient here
var request = (HttpWebRequest)WebRequest.Create(url);
request.AllowAutoRedirect = false;
request.Timeout = 3000; request.Timeout = 3000;
using var response = (HttpWebResponse)request.GetResponse(); using var response = (HttpWebResponse)request.GetResponse();
reachable = response.StatusCode == HttpStatusCode.OK; reachable = response.StatusCode == HttpStatusCode.OK;
if (reachable) if (reachable)
{
break; break;
} }
// If status is 301/302 (Found), follow the redirect manually
else if (response.StatusCode == HttpStatusCode.MovedPermanently || response.StatusCode == HttpStatusCode.Found)
{
var redirectUrl = response.Headers["Location"]; // Get the redirect URL
if (!string.IsNullOrEmpty(redirectUrl))
{
// Create a new request for the redirected URL
var redirectRequest = (HttpWebRequest)WebRequest.Create(redirectUrl);
redirectRequest.Timeout = 3000;
using var redirectResponse = (HttpWebResponse)redirectRequest.GetResponse();
reachable = redirectResponse.StatusCode == HttpStatusCode.OK;
if (reachable)
{
break;
}
}
}
}
catch catch
{ {

View File

@@ -23,3 +23,12 @@ services:
- LIDARR__ENABLED=false - LIDARR__ENABLED=false
- LIDARR__HOST=http://localhost:8686 - LIDARR__HOST=http://localhost:8686
- LIDARR__APIKEY=APIKEY - LIDARR__APIKEY=APIKEY
### example for multiple instances of same type
#- SONARR__0__NAME=NAME 1 (optional)
#- SONARR__0__ENABLED=false
#- SONARR__0__HOST=http://localhost:8989
#- SONARR__0__APIKEY=APIKEY
#- SONARR__1__NAME=NAME 2 (optional)
#- SONARR__1__ENABLED=false
#- SONARR__1__HOST=http://localhost:8989
#- SONARR__1__APIKEY=APIKEY