Skip to content

Commit

Permalink
Merge pull request #19 from PCJones/develop
Browse files Browse the repository at this point in the history
v0.5 release
  • Loading branch information
PCJones committed Apr 23, 2024
2 parents f02547c + aa70c91 commit 81dae8c
Show file tree
Hide file tree
Showing 29 changed files with 673 additions and 276 deletions.
71 changes: 50 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,21 @@

## English description coming soon

## Erste Testversion
## 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).

Momentan ist docker dafür nötig, wer kein Docker nutzt muss sich noch etwas gedulden.

[Link zum Docker Image](https://hub.docker.com/r/pcjones/umlautadaptarr)

Zusätzlich müsst ihr in Sonarr oder Prowlarr einen neuen Indexer hinzufügen (für jeden Indexer, bei dem UmlautAdapdarr greifen soll).

Am Beispiel von sceneNZBs:

![grafik](https://github.com/PCJones/UmlautAdaptarr/assets/377223/07c7ca45-e0e5-4a82-af63-365bb23c55c9)

Also alles wie immer, nur dass ihr als API-URL nicht direkt z.B. `https://scenenzbs.com` eingebt, sondern
`http://localhost:5005/_/scenenzbs.com`

Den API-Key müsst ihr natürlich auch ganz normal setzen.

## Was macht UmlautAdaptarr überhaupt?
UmlautAdaptarr löst mehrere Probleme:
- 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)
- 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.
- Zusätzlich werden einige andere Fehler behoben, die häufig dazu führen, dass Titel nicht erfolgreich gefunden, geladen oder importiert werden.

# Wie macht UmlautAdaptarr das?
## 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, dass die Arrs sie einwandfrei erkennen.
Einige Beispiele findet ihr unter Features.
Einige Beispiele finden sich [weiter unten](https://github.com/PCJones/UmlautAdaptarr/edit/develop/README.md#beispiel-funktionalit%C3%A4t).


## Features
Expand All @@ -45,14 +30,58 @@ Einige Beispiele findet ihr unter Features.
| Releases mit deutschem Titel werden erkannt ||
| 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 ||
| Anfragen-Caching für 12 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 |
| Wünsche? | Vorschläge? |


## Installation
Momentan ist Docker dafür nötig, wer kein Docker nutzt muss sich noch etwas gedulden. Eine Unraid-App gibt es auch, einfach nach `umlautadaptarr` suchen.

[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.

### 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.

1) In Prowlarr: Settings>Indexers bzw. Einstellungen>Indexer öffnen
2) Lege einen neuen HTTP-Proxy an:

![Image](https://github.com/PCJones/UmlautAdaptarr/assets/377223/b97418d8-d972-4e3c-9d2f-3a830a5ac0a3)

- Name: UmlautAdaptarr HTTP Proxy (Beispiel)
- Port: `5006` (Port beachten!)
- 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.
- Die Username- und Passwort-Felder können leergelassen werden.
3) Gehe zur Indexer-Übersichtsseite
4) Für alle Indexer/Tracker, die den UmlautAdaptarr nutzen sollen:

![grafik](https://github.com/PCJones/UmlautAdaptarr/assets/377223/3daea3f1-7c7b-4982-84e2-ea6a42d90fba)

- 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).
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.

### 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.

Dafür musst du einfach nur alle Indexer, bei denen der UmlautAdaptarr greifen soll, bearbeiten:

Am Beispiel von sceneNZBs:

![grafik](https://github.com/PCJones/UmlautAdaptarr/assets/377223/07c7ca45-e0e5-4a82-af63-365bb23c55c9)

Also alles wie immer, nur dass als API-URL nicht direkt z.B. `https://scenenzbs.com` gesetzt wird, sondern
`http://localhost:5005/_/scenenzbs.com`

Der API-Key muss natürlich auch ganz normal gesetzt werden.

## Beispiel-Funktionalität
In den Klammern am Ende des Releasenamens (Bild 2 & 4) steht zu Anschauungszwecken der deutsche Titel der vorher nicht gefunden bzw. akzeptiert wurde. Das bleibt natürlich nicht so ;)

Expand All @@ -66,7 +95,7 @@ In den Klammern am Ende des Releasenamens (Bild 2 & 4) steht zu Anschauungszweck
**Vorher:** Es werden nur Releases mit dem englischen Titel der Serie gefunden
![Vorherige Suche, englische Titel](https://github.com/PCJones/UmlautAdaptarr/assets/377223/ed7ca0fa-ac36-4584-87ac-b29f32dd9ace)

**Jetzt:** Es werden auch Titel mit dem deutschen Namen gefunden :D (haben nicht alle Suchergebnisse auf den Screenshot gepasst)
**Jetzt:** Es werden auch Titel mit dem deutschen Namen gefunden :D
![Jetzige Suche, deutsche und englische Titel](https://github.com/PCJones/UmlautAdaptarr/assets/377223/1c2dbe1a-5943-4fc4-91ef-29708082900e)


Expand Down
6 changes: 3 additions & 3 deletions UmlautAdaptarr/Controllers/CapsController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@

namespace UmlautAdaptarr.Controllers
{
public class CapsController(ProxyService proxyService) : ControllerBase
public class CapsController(ProxyRequestService proxyRequestService) : ControllerBase
{
private readonly ProxyService _proxyService = proxyService;
private readonly ProxyRequestService _proxyRequestService = proxyRequestService;

[HttpGet]
public async Task<IActionResult> Caps([FromRoute] string options, [FromRoute] string domain, [FromQuery] string? apikey)
Expand All @@ -20,7 +20,7 @@ public async Task<IActionResult> Caps([FromRoute] string options, [FromRoute] st

var requestUrl = UrlUtilities.BuildUrl(domain, "caps", apikey);

var responseMessage = await _proxyService.ProxyRequestAsync(HttpContext, requestUrl);
var responseMessage = await _proxyRequestService.ProxyRequestAsync(HttpContext, requestUrl);

var content = await responseMessage.Content.ReadAsStringAsync();
var encoding = responseMessage.Content.Headers.ContentType?.CharSet != null ?
Expand Down
10 changes: 5 additions & 5 deletions UmlautAdaptarr/Controllers/SearchController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

namespace UmlautAdaptarr.Controllers
{
public abstract class SearchControllerBase(ProxyService proxyService, TitleMatchingService titleMatchingService) : ControllerBase
public abstract class SearchControllerBase(ProxyRequestService proxyRequestService, TitleMatchingService titleMatchingService) : ControllerBase
{
// TODO evaluate if this should be set to true by default
private readonly bool TODO_FORCE_TEXT_SEARCH_ORIGINAL_TITLE = true;
Expand Down Expand Up @@ -96,7 +96,7 @@ protected async Task<IActionResult> BaseSearch(string options,
private async Task<IActionResult> PerformSingleSearchRequest(string domain, IDictionary<string, string> queryParameters)
{
var requestUrl = UrlUtilities.BuildUrl(domain, queryParameters);
var responseMessage = await proxyService.ProxyRequestAsync(HttpContext, requestUrl);
var responseMessage = await proxyRequestService.ProxyRequestAsync(HttpContext, requestUrl);
var content = await responseMessage.Content.ReadAsStringAsync();

var encoding = responseMessage.Content.Headers.ContentType?.CharSet != null ?
Expand Down Expand Up @@ -130,7 +130,7 @@ public async Task<AggregatedSearchResult> AggregateSearchResults(
{
queryParameters["q"] = titleVariation; // Replace the "q" parameter for each variation
var requestUrl = UrlUtilities.BuildUrl(domain, queryParameters);
var responseMessage = await proxyService.ProxyRequestAsync(HttpContext, requestUrl);
var responseMessage = await proxyRequestService.ProxyRequestAsync(HttpContext, requestUrl);
var content = await responseMessage.Content.ReadAsStringAsync();

// Only update encoding from the first response
Expand All @@ -152,9 +152,9 @@ public async Task<AggregatedSearchResult> AggregateSearchResults(
}
}

public class SearchController(ProxyService proxyService,
public class SearchController(ProxyRequestService proxyRequestService,
TitleMatchingService titleMatchingService,
SearchItemLookupService searchItemLookupService) : SearchControllerBase(proxyService, titleMatchingService)
SearchItemLookupService searchItemLookupService) : SearchControllerBase(proxyRequestService, titleMatchingService)
{
public readonly string[] LIDARR_CATEGORY_IDS = ["3000", "3010", "3020", "3040", "3050"];
public readonly string[] READARR_CATEGORY_IDS = ["3030", "3130", "7000", "7010", "7020", "7030", "7100", "7110", "7120", "7130"];
Expand Down
23 changes: 23 additions & 0 deletions UmlautAdaptarr/Options/ArrOptions/ArrApplicationBaseOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
namespace UmlautAdaptarr.Options.ArrOptions
{
/// <summary>
/// Base Options for ARR applications
/// </summary>
public class ArrApplicationBaseOptions
{
/// <summary>
/// Indicates whether the Arr application is enabled.
/// </summary>
public bool Enabled { get; set; }

/// <summary>
/// The host of the ARR application.
/// </summary>
public string Host { get; set; }

/// <summary>
/// The API key of the ARR application.
/// </summary>
public string ApiKey { get; set; }
}
}
9 changes: 9 additions & 0 deletions UmlautAdaptarr/Options/ArrOptions/LidarrInstanceOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace UmlautAdaptarr.Options.ArrOptions
{
/// <summary>
/// Lidarr Options
/// </summary>
public class LidarrInstanceOptions : ArrApplicationBaseOptions
{
}
}
9 changes: 9 additions & 0 deletions UmlautAdaptarr/Options/ArrOptions/ReadarrInstanceOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace UmlautAdaptarr.Options.ArrOptions
{
/// <summary>
/// Readarr Options
/// </summary>
public class ReadarrInstanceOptions : ArrApplicationBaseOptions
{
}
}
9 changes: 9 additions & 0 deletions UmlautAdaptarr/Options/ArrOptions/SonarrInstanceOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace UmlautAdaptarr.Options.ArrOptions
{
/// <summary>
/// Sonarr Options
/// </summary>
public class SonarrInstanceOptions : ArrApplicationBaseOptions
{
}
}
18 changes: 18 additions & 0 deletions UmlautAdaptarr/Options/GlobalOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
namespace UmlautAdaptarr.Options
{
/// <summary>
/// Global options for the UmlautAdaptarr application.
/// </summary>
public class GlobalOptions
{
/// <summary>
/// The host of the UmlautAdaptarr API.
/// </summary>
public string UmlautAdaptarrApiHost { get; set; }

/// <summary>
/// The User-Agent string used in HTTP requests.
/// </summary>
public string UserAgent { get; set; }
}
}
27 changes: 27 additions & 0 deletions UmlautAdaptarr/Options/Proxy.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
namespace UmlautAdaptarr.Options;

/// <summary>
/// Represents options for proxy configuration.
/// </summary>
public class Proxy
{
/// <summary>
/// Gets or sets a value indicating whether to use a proxy.
/// </summary>
public bool Enabled { get; set; }

/// <summary>
/// Gets or sets the address of the proxy.
/// </summary>
public string? Address { get; set; }

/// <summary>
/// Gets or sets the username for proxy authentication.
/// </summary>
public string? Username { get; set; }

/// <summary>
/// Gets or sets the password for proxy authentication.
/// </summary>
public string? Password { get; set; }
}
32 changes: 32 additions & 0 deletions UmlautAdaptarr/Options/ProxyOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
namespace UmlautAdaptarr.Options;

/// <summary>
/// Represents options for proxy configuration.
/// </summary>
public class ProxyOptions
{
/// <summary>
/// Gets or sets a value indicating whether to use a proxy.
/// </summary>
public bool Enabled { get; set; }

/// <summary>
/// Gets or sets the address of the proxy.
/// </summary>
public string? Address { get; set; }

/// <summary>
/// Gets or sets the username for proxy authentication.
/// </summary>
public string? Username { get; set; }

/// <summary>
/// Gets or sets the password for proxy authentication.
/// </summary>
public string? Password { get; set; }

/// <summary>
/// Bypass Local Ip Addresses , Proxy will ignore local Ip Addresses
/// </summary>
public bool BypassOnLocal { get; set; }
}
20 changes: 12 additions & 8 deletions UmlautAdaptarr/Program.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
using Microsoft.Extensions.Configuration;
using System.Net;
using UmlautAdaptarr.Providers;
using UmlautAdaptarr.Options;
using UmlautAdaptarr.Routing;
using UmlautAdaptarr.Services;
using UmlautAdaptarr.Utilities;

internal class Program
{
Expand All @@ -24,11 +24,14 @@ private static void Main(string[] args)
AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate | DecompressionMethods.Brotli
};
var proxyOptions = configuration.GetSection("Proxy").Get<ProxyOptions>();
handler.ConfigureProxy(proxyOptions);
return handler;
});

builder.Services.AddMemoryCache(options =>
{
// TODO cache size limit? option?
//options.SizeLimit = 20000;
});

Expand All @@ -46,19 +49,20 @@ private static void Main(string[] args)

builder.Services.AddControllers();
builder.Services.AddHostedService<ArrSyncBackgroundService>();
builder.Services.AddSingleton<TitleApiService>();
builder.AddTitleLookupService();
builder.Services.AddSingleton<SearchItemLookupService>();
builder.Services.AddSingleton<TitleMatchingService>();
builder.Services.AddSingleton<SonarrClient>();
builder.Services.AddSingleton<LidarrClient>();
builder.Services.AddSingleton<ReadarrClient>();
builder.AddSonarrSupport();
builder.AddLidarrSupport();
builder.AddReadarrSupport();
builder.Services.AddSingleton<CacheService>();
builder.Services.AddSingleton<ProxyService>();
builder.Services.AddSingleton<ProxyRequestService>();
builder.Services.AddSingleton<IHostedService, HttpProxyService>();

var app = builder.Build();

GlobalStaticLogger.Initialize(app.Services.GetService<ILoggerFactory>()!);
app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllerRoute(name: "caps",
Expand Down
17 changes: 17 additions & 0 deletions UmlautAdaptarr/Providers/ArrClientFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
namespace UmlautAdaptarr.Providers
{
public static class ArrClientFactory
{
// TODO, still uses old IConfiguration
// TODO not used yet
public static IEnumerable<TClient> CreateClients<TClient>(
Func<string, TClient> constructor, IConfiguration configuration, string configKey) where TClient : ArrClientBase
{
var hosts = configuration.GetValue<string>(configKey)?.Split(',') ?? throw new ArgumentException($"{configKey} environment variable must be set if the app is enabled");
foreach (var host in hosts)
{
yield return constructor(host.Trim());
}
}
}
}
Loading

0 comments on commit 81dae8c

Please sign in to comment.