Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f35abdefe5 |
@@ -59,29 +59,6 @@ This tool is actively developed and still a work in progress. Join the Discord s
|
|||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
### Docker
|
|
||||||
|
|
||||||
```
|
|
||||||
docker run -d \
|
|
||||||
-e TRIGGERS__QUEUECLEANER="0 0/5 * * * ?" \
|
|
||||||
-e QBITTORRENT__ENABLED=true \
|
|
||||||
-e QBITTORRENT__URL="http://localhost:8080" \
|
|
||||||
-e QBITTORRENT__USERNAME="user" \
|
|
||||||
-e QBITTORRENT__PASSWORD="pass" \
|
|
||||||
-e SONARR__ENABLED=true \
|
|
||||||
-e SONARR__INSTANCES__0__URL="http://localhost:8989" \
|
|
||||||
-e SONARR__INSTANCES__0__APIKEY="secret1" \
|
|
||||||
-e SONARR__INSTANCES__1__URL="http://localhost:8990" \
|
|
||||||
-e SONARR__INSTANCES__1__APIKEY="secret2" \
|
|
||||||
-e RADARR__ENABLED=true \
|
|
||||||
-e RADARR__INSTANCES__0__URL="http://localhost:7878" \
|
|
||||||
-e RADARR__INSTANCES__0__APIKEY="secret3" \
|
|
||||||
-e RADARR__INSTANCES__1__URL="http://localhost:7879" \
|
|
||||||
-e RADARR__INSTANCES__1__APIKEY="secret4" \
|
|
||||||
...
|
|
||||||
flaminel/cleanuperr:latest
|
|
||||||
```
|
|
||||||
|
|
||||||
### Docker compose yaml
|
### Docker compose yaml
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -94,6 +71,7 @@ services:
|
|||||||
- LOGGING__LOGLEVEL=Information
|
- LOGGING__LOGLEVEL=Information
|
||||||
- LOGGING__FILE__ENABLED=false
|
- LOGGING__FILE__ENABLED=false
|
||||||
- LOGGING__FILE__PATH=/var/logs/
|
- LOGGING__FILE__PATH=/var/logs/
|
||||||
|
- LOGGING__ENHANCED=true
|
||||||
|
|
||||||
- TRIGGERS__QUEUECLEANER=0 0/5 * * * ?
|
- TRIGGERS__QUEUECLEANER=0 0/5 * * * ?
|
||||||
- TRIGGERS__CONTENTBLOCKER=0 0/5 * * * ?
|
- TRIGGERS__CONTENTBLOCKER=0 0/5 * * * ?
|
||||||
@@ -123,6 +101,7 @@ services:
|
|||||||
# - TRANSMISSION__PASSWORD=testing
|
# - TRANSMISSION__PASSWORD=testing
|
||||||
|
|
||||||
- SONARR__ENABLED=true
|
- SONARR__ENABLED=true
|
||||||
|
- SONARR__SEARCHTYPE=Episode
|
||||||
- SONARR__INSTANCES__0__URL=http://localhost:8989
|
- SONARR__INSTANCES__0__URL=http://localhost:8989
|
||||||
- SONARR__INSTANCES__0__APIKEY=secret1
|
- SONARR__INSTANCES__0__APIKEY=secret1
|
||||||
- SONARR__INSTANCES__1__URL=http://localhost:8990
|
- SONARR__INSTANCES__1__URL=http://localhost:8990
|
||||||
@@ -133,7 +112,7 @@ services:
|
|||||||
- RADARR__INSTANCES__0__APIKEY=secret3
|
- RADARR__INSTANCES__0__APIKEY=secret3
|
||||||
- RADARR__INSTANCES__1__URL=http://localhost:7879
|
- RADARR__INSTANCES__1__URL=http://localhost:7879
|
||||||
- RADARR__INSTANCES__1__APIKEY=secret4
|
- RADARR__INSTANCES__1__APIKEY=secret4
|
||||||
image: flaminel/cleanuperr:latest
|
image: ghcr.io/flmorg/cleanuperr:latest
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -144,6 +123,7 @@ services:
|
|||||||
| LOGGING__LOGLEVEL | No | Can be `Verbose`, `Debug`, `Information`, `Warning`, `Error` or `Fatal` | `Information` |
|
| LOGGING__LOGLEVEL | No | Can be `Verbose`, `Debug`, `Information`, `Warning`, `Error` or `Fatal` | `Information` |
|
||||||
| LOGGING__FILE__ENABLED | No | Enable or disable logging to file | false |
|
| LOGGING__FILE__ENABLED | No | Enable or disable logging to file | false |
|
||||||
| LOGGING__FILE__PATH | No | Directory where to save the log files | empty |
|
| LOGGING__FILE__PATH | No | Directory where to save the log files | empty |
|
||||||
|
| LOGGING__ENHANCED | No | Enhance logs whenever possible<br>A more detailed description is provided [here](variables.md#LOGGING__ENHANCED) | true |
|
||||||
|||||
|
|||||
|
||||||
| TRIGGERS__QUEUECLEANER | Yes if queue cleaner is enabled | [Quartz cron trigger](https://www.quartz-scheduler.org/documentation/quartz-2.3.0/tutorials/crontrigger.html) | 0 0/5 * * * ? |
|
| TRIGGERS__QUEUECLEANER | Yes if queue cleaner is enabled | [Quartz cron trigger](https://www.quartz-scheduler.org/documentation/quartz-2.3.0/tutorials/crontrigger.html) | 0 0/5 * * * ? |
|
||||||
| TRIGGERS__CONTENTBLOCKER | Yes if content blocker is enabled | [Quartz cron trigger](https://www.quartz-scheduler.org/documentation/quartz-2.3.0/tutorials/crontrigger.html) | 0 0/5 * * * ? |
|
| TRIGGERS__CONTENTBLOCKER | Yes if content blocker is enabled | [Quartz cron trigger](https://www.quartz-scheduler.org/documentation/quartz-2.3.0/tutorials/crontrigger.html) | 0 0/5 * * * ? |
|
||||||
@@ -172,6 +152,7 @@ services:
|
|||||||
| TRANSMISSION__PASSWORD | No | Transmission password | empty |
|
| TRANSMISSION__PASSWORD | No | Transmission password | empty |
|
||||||
|||||
|
|||||
|
||||||
| SONARR__ENABLED | No | Enable or disable Sonarr cleanup | true |
|
| SONARR__ENABLED | No | Enable or disable Sonarr cleanup | true |
|
||||||
|
| SONARR__SEARCHTYPE | No | What to search for after removing a queue item<br>Can be `Episode`, `Season` or `Series` | `Episode` |
|
||||||
| SONARR__INSTANCES__0__URL | Yes | First Sonarr instance url | http://localhost:8989 |
|
| SONARR__INSTANCES__0__URL | Yes | First Sonarr instance url | http://localhost:8989 |
|
||||||
| SONARR__INSTANCES__0__APIKEY | Yes | First Sonarr instance API key | empty |
|
| SONARR__INSTANCES__0__APIKEY | Yes | First Sonarr instance API key | empty |
|
||||||
|||||
|
|||||
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace Common.Configuration;
|
namespace Common.Configuration.Arr;
|
||||||
|
|
||||||
public abstract record ArrConfig
|
public abstract record ArrConfig
|
||||||
{
|
{
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
namespace Common.Configuration;
|
namespace Common.Configuration.Arr;
|
||||||
|
|
||||||
public sealed class ArrInstance
|
public sealed class ArrInstance
|
||||||
{
|
{
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
namespace Common.Configuration;
|
namespace Common.Configuration.Arr;
|
||||||
|
|
||||||
public sealed record RadarrConfig : ArrConfig
|
public sealed record RadarrConfig : ArrConfig
|
||||||
{
|
{
|
||||||
+3
-1
@@ -1,6 +1,8 @@
|
|||||||
namespace Common.Configuration;
|
namespace Common.Configuration.Arr;
|
||||||
|
|
||||||
public sealed record SonarrConfig : ArrConfig
|
public sealed record SonarrConfig : ArrConfig
|
||||||
{
|
{
|
||||||
public const string SectionName = "Sonarr";
|
public const string SectionName = "Sonarr";
|
||||||
|
|
||||||
|
public SonarrSearchType SearchType { get; init; }
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
namespace Common.Configuration.Arr;
|
||||||
|
|
||||||
|
public enum SonarrSearchType
|
||||||
|
{
|
||||||
|
Episode,
|
||||||
|
Season,
|
||||||
|
Series
|
||||||
|
}
|
||||||
+1
-3
@@ -1,6 +1,4 @@
|
|||||||
using System.Security;
|
namespace Common.Configuration.DownloadClient;
|
||||||
|
|
||||||
namespace Common.Configuration;
|
|
||||||
|
|
||||||
public sealed record DelugeConfig : IConfig
|
public sealed record DelugeConfig : IConfig
|
||||||
{
|
{
|
||||||
+1
-3
@@ -1,6 +1,4 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
namespace Common.Configuration.DownloadClient;
|
||||||
|
|
||||||
namespace Common.Configuration;
|
|
||||||
|
|
||||||
public sealed class QBitConfig : IConfig
|
public sealed class QBitConfig : IConfig
|
||||||
{
|
{
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
namespace Common.Configuration;
|
namespace Common.Configuration.DownloadClient;
|
||||||
|
|
||||||
public record TransmissionConfig
|
public record TransmissionConfig
|
||||||
{
|
{
|
||||||
@@ -8,6 +8,8 @@ public class LoggingConfig : IConfig
|
|||||||
|
|
||||||
public LogEventLevel LogLevel { get; set; }
|
public LogEventLevel LogLevel { get; set; }
|
||||||
|
|
||||||
|
public bool Enhanced { get; set; }
|
||||||
|
|
||||||
public FileLogConfig? File { get; set; }
|
public FileLogConfig? File { get; set; }
|
||||||
|
|
||||||
public void Validate()
|
public void Validate()
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ public record QueueRecord
|
|||||||
{
|
{
|
||||||
public int SeriesId { get; init; }
|
public int SeriesId { get; init; }
|
||||||
public int EpisodeId { get; init; }
|
public int EpisodeId { get; init; }
|
||||||
|
public int SeasonNumber { get; init; }
|
||||||
public int MovieId { get; init; }
|
public int MovieId { get; init; }
|
||||||
public required string Title { get; init; }
|
public required string Title { get; init; }
|
||||||
public string Status { get; init; }
|
public string Status { get; init; }
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
namespace Domain.Models.Arr;
|
||||||
|
|
||||||
|
public class SearchItem
|
||||||
|
{
|
||||||
|
public long Id { get; set; }
|
||||||
|
|
||||||
|
public override bool Equals(object? obj)
|
||||||
|
{
|
||||||
|
if (obj is not SearchItem other)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Id == other.Id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return Id.GetHashCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
namespace Domain.Models.Arr;
|
||||||
|
|
||||||
|
public sealed class SonarrSearchItem : SearchItem
|
||||||
|
{
|
||||||
|
public long SeriesId { get; set; }
|
||||||
|
|
||||||
|
public override bool Equals(object? obj)
|
||||||
|
{
|
||||||
|
if (obj is not SonarrSearchItem other)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Id == other.Id && SeriesId == other.SeriesId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return HashCode.Combine(Id, SeriesId);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
namespace Domain.Models.Radarr;
|
||||||
|
|
||||||
|
public sealed record Movie
|
||||||
|
{
|
||||||
|
public required long Id { get; init; }
|
||||||
|
|
||||||
|
public required string Title { get; init; }
|
||||||
|
}
|
||||||
@@ -4,5 +4,5 @@ public sealed record RadarrCommand
|
|||||||
{
|
{
|
||||||
public required string Name { get; init; }
|
public required string Name { get; init; }
|
||||||
|
|
||||||
public required HashSet<int> MovieIds { get; init; }
|
public required List<long> MovieIds { get; init; }
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
namespace Domain.Models.Sonarr;
|
||||||
|
|
||||||
|
public sealed record Episode
|
||||||
|
{
|
||||||
|
public long Id { get; set; }
|
||||||
|
|
||||||
|
public int EpisodeNumber { get; set; }
|
||||||
|
|
||||||
|
public int SeasonNumber { get; set; }
|
||||||
|
|
||||||
|
public long SeriesId { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
namespace Domain.Models.Sonarr;
|
||||||
|
|
||||||
|
public sealed record Series
|
||||||
|
{
|
||||||
|
public required long Id { get; init; }
|
||||||
|
|
||||||
|
public required string Title { get; init; }
|
||||||
|
}
|
||||||
@@ -2,7 +2,11 @@
|
|||||||
|
|
||||||
public sealed record SonarrCommand
|
public sealed record SonarrCommand
|
||||||
{
|
{
|
||||||
public required string Name { get; init; }
|
public string Name { get; set; }
|
||||||
|
|
||||||
public required int SeriesId { get; set; }
|
public long? SeriesId { get; set; }
|
||||||
|
|
||||||
|
public long? SeasonNumber { get; set; }
|
||||||
|
|
||||||
|
public List<long>? EpisodeIds { get; set; }
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,8 @@
|
|||||||
using Common.Configuration;
|
using Common.Configuration;
|
||||||
|
using Common.Configuration.Arr;
|
||||||
using Common.Configuration.ContentBlocker;
|
using Common.Configuration.ContentBlocker;
|
||||||
|
using Common.Configuration.DownloadClient;
|
||||||
|
using Common.Configuration.Logging;
|
||||||
|
|
||||||
namespace Executable.DependencyInjection;
|
namespace Executable.DependencyInjection;
|
||||||
|
|
||||||
@@ -12,5 +15,6 @@ public static class ConfigurationDI
|
|||||||
.Configure<DelugeConfig>(configuration.GetSection(DelugeConfig.SectionName))
|
.Configure<DelugeConfig>(configuration.GetSection(DelugeConfig.SectionName))
|
||||||
.Configure<TransmissionConfig>(configuration.GetSection(TransmissionConfig.SectionName))
|
.Configure<TransmissionConfig>(configuration.GetSection(TransmissionConfig.SectionName))
|
||||||
.Configure<SonarrConfig>(configuration.GetSection(SonarrConfig.SectionName))
|
.Configure<SonarrConfig>(configuration.GetSection(SonarrConfig.SectionName))
|
||||||
.Configure<RadarrConfig>(configuration.GetSection(RadarrConfig.SectionName));
|
.Configure<RadarrConfig>(configuration.GetSection(RadarrConfig.SectionName))
|
||||||
|
.Configure<LoggingConfig>(configuration.GetSection(LoggingConfig.SectionName));
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"Logging": {
|
"Logging": {
|
||||||
"LogLevel": "Debug",
|
"LogLevel": "Debug",
|
||||||
|
"Enhanced": true,
|
||||||
"File": {
|
"File": {
|
||||||
"Enabled": false,
|
"Enabled": false,
|
||||||
"Path": ""
|
"Path": ""
|
||||||
@@ -44,6 +45,7 @@
|
|||||||
},
|
},
|
||||||
"Sonarr": {
|
"Sonarr": {
|
||||||
"Enabled": true,
|
"Enabled": true,
|
||||||
|
"SearchType": "Episode",
|
||||||
"Instances": [
|
"Instances": [
|
||||||
{
|
{
|
||||||
"Url": "http://localhost:8989",
|
"Url": "http://localhost:8989",
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"Logging": {
|
"Logging": {
|
||||||
"LogLevel": "Information",
|
"LogLevel": "Information",
|
||||||
|
"Enhanced": true,
|
||||||
"File": {
|
"File": {
|
||||||
"Enabled": false,
|
"Enabled": false,
|
||||||
"Path": ""
|
"Path": ""
|
||||||
@@ -44,6 +45,7 @@
|
|||||||
},
|
},
|
||||||
"Sonarr": {
|
"Sonarr": {
|
||||||
"Enabled": true,
|
"Enabled": true,
|
||||||
|
"SearchType": "Episode",
|
||||||
"Instances": [
|
"Instances": [
|
||||||
{
|
{
|
||||||
"Url": "http://localhost:8989",
|
"Url": "http://localhost:8989",
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
@@ -14,7 +14,6 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="FLM.Transmission" Version="1.0.0" />
|
<PackageReference Include="FLM.Transmission" Version="1.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Http" Version="8.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Http" Version="8.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Options" Version="8.0.1" />
|
|
||||||
<PackageReference Include="QBittorrent.Client" Version="1.9.24285.1" />
|
<PackageReference Include="QBittorrent.Client" Version="1.9.24285.1" />
|
||||||
<PackageReference Include="Quartz" Version="3.13.1" />
|
<PackageReference Include="Quartz" Version="3.13.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -1,19 +1,25 @@
|
|||||||
using Common.Configuration;
|
using Common.Configuration;
|
||||||
|
using Common.Configuration.Arr;
|
||||||
|
using Common.Configuration.Logging;
|
||||||
using Domain.Arr.Queue;
|
using Domain.Arr.Queue;
|
||||||
|
using Domain.Models.Arr;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace Infrastructure.Verticals.Arr;
|
namespace Infrastructure.Verticals.Arr;
|
||||||
|
|
||||||
public abstract class ArrClient
|
public abstract class ArrClient
|
||||||
{
|
{
|
||||||
private protected ILogger<ArrClient> _logger;
|
protected readonly ILogger<ArrClient> _logger;
|
||||||
private protected HttpClient _httpClient;
|
protected readonly HttpClient _httpClient;
|
||||||
|
protected readonly LoggingConfig _loggingConfig;
|
||||||
|
|
||||||
protected ArrClient(ILogger<ArrClient> logger, IHttpClientFactory httpClientFactory)
|
protected ArrClient(ILogger<ArrClient> logger, IHttpClientFactory httpClientFactory, IOptions<LoggingConfig> loggingConfig)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_httpClient = httpClientFactory.CreateClient();
|
_httpClient = httpClientFactory.CreateClient();
|
||||||
|
_loggingConfig = loggingConfig.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual async Task<QueueListResponse> GetQueueItemsAsync(ArrInstance arrInstance, int page)
|
public virtual async Task<QueueListResponse> GetQueueItemsAsync(ArrInstance arrInstance, int page)
|
||||||
@@ -68,7 +74,7 @@ public abstract class ArrClient
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract Task RefreshItemsAsync(ArrInstance arrInstance, HashSet<int> itemIds);
|
public abstract Task RefreshItemsAsync(ArrInstance arrInstance, ArrConfig config, HashSet<SearchItem>? items);
|
||||||
|
|
||||||
protected virtual void SetApiKey(HttpRequestMessage request, string apiKey)
|
protected virtual void SetApiKey(HttpRequestMessage request, string apiKey)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Common.Configuration;
|
using Common.Configuration;
|
||||||
|
using Common.Configuration.Arr;
|
||||||
using Domain.Arr.Queue;
|
using Domain.Arr.Queue;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
|||||||
@@ -1,30 +1,38 @@
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using Common.Configuration;
|
using Common.Configuration.Arr;
|
||||||
|
using Common.Configuration.Logging;
|
||||||
|
using Domain.Models.Arr;
|
||||||
using Domain.Models.Radarr;
|
using Domain.Models.Radarr;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace Infrastructure.Verticals.Arr;
|
namespace Infrastructure.Verticals.Arr;
|
||||||
|
|
||||||
public sealed class RadarrClient : ArrClient
|
public sealed class RadarrClient : ArrClient
|
||||||
{
|
{
|
||||||
public RadarrClient(ILogger<ArrClient> logger, IHttpClientFactory httpClientFactory)
|
public RadarrClient(
|
||||||
: base(logger, httpClientFactory)
|
ILogger<ArrClient> logger,
|
||||||
|
IHttpClientFactory httpClientFactory,
|
||||||
|
IOptions<LoggingConfig> loggingConfig
|
||||||
|
) : base(logger, httpClientFactory, loggingConfig)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task RefreshItemsAsync(ArrInstance arrInstance, HashSet<int> itemIds)
|
public override async Task RefreshItemsAsync(ArrInstance arrInstance, ArrConfig config, HashSet<SearchItem>? items)
|
||||||
{
|
{
|
||||||
if (itemIds.Count is 0)
|
if (items?.Count is null or 0)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<long> ids = items.Select(item => item.Id).ToList();
|
||||||
|
|
||||||
Uri uri = new(arrInstance.Url, "/api/v3/command");
|
Uri uri = new(arrInstance.Url, "/api/v3/command");
|
||||||
RadarrCommand command = new()
|
RadarrCommand command = new()
|
||||||
{
|
{
|
||||||
Name = "MoviesSearch",
|
Name = "MoviesSearch",
|
||||||
MovieIds = itemIds
|
MovieIds = ids,
|
||||||
};
|
};
|
||||||
|
|
||||||
using HttpRequestMessage request = new(HttpMethod.Post, uri);
|
using HttpRequestMessage request = new(HttpMethod.Post, uri);
|
||||||
@@ -36,17 +44,72 @@ public sealed class RadarrClient : ArrClient
|
|||||||
SetApiKey(request, arrInstance.ApiKey);
|
SetApiKey(request, arrInstance.ApiKey);
|
||||||
|
|
||||||
using HttpResponseMessage response = await _httpClient.SendAsync(request);
|
using HttpResponseMessage response = await _httpClient.SendAsync(request);
|
||||||
|
string? logContext = await ComputeCommandLogContextAsync(arrInstance, command);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
response.EnsureSuccessStatusCode();
|
response.EnsureSuccessStatusCode();
|
||||||
|
|
||||||
_logger.LogInformation("movie search triggered | {url} | movie ids: {ids}", arrInstance.Url, string.Join(",", itemIds));
|
_logger.LogInformation("{log}", GetSearchLog(arrInstance.Url, command, true, logContext));
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
_logger.LogError("movie search failed | {url} | movie ids: {ids}", arrInstance.Url, string.Join(",", itemIds));
|
_logger.LogError("{log}", GetSearchLog(arrInstance.Url, command, false, logContext));
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string GetSearchLog(Uri instanceUrl, RadarrCommand command, bool success, string? logContext)
|
||||||
|
{
|
||||||
|
string status = success ? "triggered" : "failed";
|
||||||
|
string message = logContext ?? $"movie ids: {string.Join(',', command.MovieIds)}";
|
||||||
|
|
||||||
|
return $"movie search {status} | {instanceUrl} | {message}";
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<string?> ComputeCommandLogContextAsync(ArrInstance arrInstance, RadarrCommand command)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!_loggingConfig.Enhanced)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder log = new();
|
||||||
|
|
||||||
|
foreach (long movieId in command.MovieIds)
|
||||||
|
{
|
||||||
|
Movie? movie = await GetMovie(arrInstance, movieId);
|
||||||
|
|
||||||
|
if (movie is null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Append($"[{movie.Title}]");
|
||||||
|
}
|
||||||
|
|
||||||
|
return log.ToString();
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
_logger.LogDebug(exception, "failed to compute log context");
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<Movie?> GetMovie(ArrInstance arrInstance, long movieId)
|
||||||
|
{
|
||||||
|
Uri uri = new(arrInstance.Url, $"api/v3/movie/{movieId}");
|
||||||
|
using HttpRequestMessage request = new(HttpMethod.Get, uri);
|
||||||
|
SetApiKey(request, arrInstance.ApiKey);
|
||||||
|
|
||||||
|
using HttpResponseMessage response = await _httpClient.SendAsync(request);
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
|
||||||
|
string responseBody = await response.Content.ReadAsStringAsync();
|
||||||
|
return JsonConvert.DeserializeObject<Movie>(responseBody);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,50 +1,244 @@
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using Common.Configuration;
|
using Common.Configuration.Arr;
|
||||||
|
using Common.Configuration.Logging;
|
||||||
|
using Domain.Models.Arr;
|
||||||
using Domain.Models.Sonarr;
|
using Domain.Models.Sonarr;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace Infrastructure.Verticals.Arr;
|
namespace Infrastructure.Verticals.Arr;
|
||||||
|
|
||||||
public sealed class SonarrClient : ArrClient
|
public sealed class SonarrClient : ArrClient
|
||||||
{
|
{
|
||||||
public SonarrClient(ILogger<SonarrClient> logger, IHttpClientFactory httpClientFactory)
|
public SonarrClient(
|
||||||
: base(logger, httpClientFactory)
|
ILogger<SonarrClient> logger,
|
||||||
|
IHttpClientFactory httpClientFactory,
|
||||||
|
IOptions<LoggingConfig> loggingConfig
|
||||||
|
) : base(logger, httpClientFactory, loggingConfig)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task RefreshItemsAsync(ArrInstance arrInstance, HashSet<int> itemIds)
|
public override async Task RefreshItemsAsync(ArrInstance arrInstance, ArrConfig config, HashSet<SearchItem>? items)
|
||||||
{
|
{
|
||||||
foreach (int itemId in itemIds)
|
if (items?.Count is null or 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SonarrConfig sonarrConfig = (SonarrConfig)config;
|
||||||
|
|
||||||
|
Uri uri = new(arrInstance.Url, "/api/v3/command");
|
||||||
|
|
||||||
|
foreach (SonarrCommand command in GetSearchCommands(sonarrConfig.SearchType, items))
|
||||||
{
|
{
|
||||||
Uri uri = new(arrInstance.Url, "/api/v3/command");
|
|
||||||
SonarrCommand command = new()
|
|
||||||
{
|
|
||||||
Name = "SeriesSearch",
|
|
||||||
SeriesId = itemId
|
|
||||||
};
|
|
||||||
|
|
||||||
using HttpRequestMessage request = new(HttpMethod.Post, uri);
|
using HttpRequestMessage request = new(HttpMethod.Post, uri);
|
||||||
request.Content = new StringContent(
|
request.Content = new StringContent(
|
||||||
JsonConvert.SerializeObject(command),
|
JsonConvert.SerializeObject(command, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }),
|
||||||
Encoding.UTF8,
|
Encoding.UTF8,
|
||||||
"application/json"
|
"application/json"
|
||||||
);
|
);
|
||||||
SetApiKey(request, arrInstance.ApiKey);
|
SetApiKey(request, arrInstance.ApiKey);
|
||||||
|
|
||||||
using HttpResponseMessage response = await _httpClient.SendAsync(request);
|
using HttpResponseMessage response = await _httpClient.SendAsync(request);
|
||||||
|
string? logContext = await ComputeCommandLogContextAsync(arrInstance, command, sonarrConfig.SearchType);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
response.EnsureSuccessStatusCode();
|
response.EnsureSuccessStatusCode();
|
||||||
|
|
||||||
_logger.LogInformation("series search triggered | {url} | series id: {id}", arrInstance.Url, itemId);
|
_logger.LogInformation("{log}", GetSearchLog(sonarrConfig.SearchType, arrInstance.Url, command, true, logContext));
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
_logger.LogError("series search failed | {url} | series id: {id}", arrInstance.Url, itemId);
|
_logger.LogError("{log}", GetSearchLog(sonarrConfig.SearchType, arrInstance.Url, command, false, logContext));
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string GetSearchLog(
|
||||||
|
SonarrSearchType searchType,
|
||||||
|
Uri instanceUrl,
|
||||||
|
SonarrCommand command,
|
||||||
|
bool success,
|
||||||
|
string? logContext
|
||||||
|
)
|
||||||
|
{
|
||||||
|
string status = success ? "triggered" : "failed";
|
||||||
|
|
||||||
|
return searchType switch
|
||||||
|
{
|
||||||
|
SonarrSearchType.Episode =>
|
||||||
|
$"episodes search {status} | {instanceUrl} | {logContext ?? $"episode ids: {string.Join(',', command.EpisodeIds)}"}",
|
||||||
|
SonarrSearchType.Season =>
|
||||||
|
$"season search {status} | {instanceUrl} | {logContext ?? $"season: {command.SeasonNumber} series id: {command.SeriesId}"}",
|
||||||
|
SonarrSearchType.Series => $"series search {status} | {instanceUrl} | {logContext ?? $"series id: {command.SeriesId}"}",
|
||||||
|
_ => throw new ArgumentOutOfRangeException(nameof(searchType), searchType, null)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<string?> ComputeCommandLogContextAsync(ArrInstance arrInstance, SonarrCommand command, SonarrSearchType searchType)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!_loggingConfig.Enhanced)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder log = new();
|
||||||
|
|
||||||
|
if (searchType is SonarrSearchType.Episode)
|
||||||
|
{
|
||||||
|
var episodes = await GetEpisodesAsync(arrInstance, command.EpisodeIds);
|
||||||
|
|
||||||
|
if (episodes?.Count is null or 0)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var seriesIds = episodes
|
||||||
|
.Select(x => x.SeriesId)
|
||||||
|
.Distinct()
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
List<Series> series = [];
|
||||||
|
|
||||||
|
foreach (long id in seriesIds)
|
||||||
|
{
|
||||||
|
Series? show = await GetSeriesAsync(arrInstance, id);
|
||||||
|
|
||||||
|
if (show is null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
series.Add(show);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var group in command.EpisodeIds.GroupBy(id => episodes.First(x => x.Id == id).SeriesId))
|
||||||
|
{
|
||||||
|
var show = series.First(x => x.Id == group.Key);
|
||||||
|
var episode = episodes
|
||||||
|
.Where(ep => group.Any(x => x == ep.Id))
|
||||||
|
.OrderBy(x => x.SeasonNumber)
|
||||||
|
.ThenBy(x => x.EpisodeNumber)
|
||||||
|
.Select(x => $"S{x.SeasonNumber.ToString().PadLeft(2, '0')}E{x.EpisodeNumber.ToString().PadLeft(2, '0')}")
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
log.Append($"[{show.Title} {string.Join(',', episode)}]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (searchType is SonarrSearchType.Season)
|
||||||
|
{
|
||||||
|
Series? show = await GetSeriesAsync(arrInstance, command.SeriesId.Value);
|
||||||
|
|
||||||
|
if (show is null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Append($"[{show.Title} season {command.SeasonNumber}]");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (searchType is SonarrSearchType.Series)
|
||||||
|
{
|
||||||
|
Series? show = await GetSeriesAsync(arrInstance, command.SeriesId.Value);
|
||||||
|
|
||||||
|
if (show is null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Append($"[{show.Title}]");
|
||||||
|
}
|
||||||
|
|
||||||
|
return log.ToString();
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
_logger.LogDebug(exception, "failed to compute log context");
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<List<Episode>?> GetEpisodesAsync(ArrInstance arrInstance, List<long> episodeIds)
|
||||||
|
{
|
||||||
|
Uri uri = new(arrInstance.Url, $"api/v3/episode?{string.Join('&', episodeIds.Select(x => $"episodeIds={x}"))}");
|
||||||
|
using HttpRequestMessage request = new(HttpMethod.Get, uri);
|
||||||
|
SetApiKey(request, arrInstance.ApiKey);
|
||||||
|
|
||||||
|
using HttpResponseMessage response = await _httpClient.SendAsync(request);
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
|
||||||
|
string responseBody = await response.Content.ReadAsStringAsync();
|
||||||
|
return JsonConvert.DeserializeObject<List<Episode>>(responseBody);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<Series?> GetSeriesAsync(ArrInstance arrInstance, long seriesId)
|
||||||
|
{
|
||||||
|
Uri uri = new(arrInstance.Url, $"api/v3/series/{seriesId}");
|
||||||
|
using HttpRequestMessage request = new(HttpMethod.Get, uri);
|
||||||
|
SetApiKey(request, arrInstance.ApiKey);
|
||||||
|
|
||||||
|
using HttpResponseMessage response = await _httpClient.SendAsync(request);
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
|
||||||
|
string responseBody = await response.Content.ReadAsStringAsync();
|
||||||
|
return JsonConvert.DeserializeObject<Series>(responseBody);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<SonarrCommand> GetSearchCommands(SonarrSearchType searchType, HashSet<SearchItem> items)
|
||||||
|
{
|
||||||
|
const string episodeSearch = "EpisodeSearch";
|
||||||
|
const string seasonSearch = "SeasonSearch";
|
||||||
|
const string seriesSearch = "SeriesSearch";
|
||||||
|
|
||||||
|
List<SonarrCommand> commands = new();
|
||||||
|
|
||||||
|
foreach (SearchItem item in items)
|
||||||
|
{
|
||||||
|
SonarrCommand command = searchType is SonarrSearchType.Episode
|
||||||
|
? commands.FirstOrDefault() ?? new() { Name = episodeSearch, EpisodeIds = new() }
|
||||||
|
: new();
|
||||||
|
|
||||||
|
switch (searchType)
|
||||||
|
{
|
||||||
|
case SonarrSearchType.Episode when command.EpisodeIds is null:
|
||||||
|
command.EpisodeIds = [item.Id];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SonarrSearchType.Episode when command.EpisodeIds is not null:
|
||||||
|
command.EpisodeIds.Add(item.Id);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SonarrSearchType.Season:
|
||||||
|
command.Name = seasonSearch;
|
||||||
|
command.SeasonNumber = item.Id;
|
||||||
|
command.SeriesId = ((SonarrSearchItem)item).SeriesId;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SonarrSearchType.Series:
|
||||||
|
command.Name = seriesSearch;
|
||||||
|
command.SeriesId = item.Id;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(searchType), searchType, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (searchType is SonarrSearchType.Episode && commands.Count > 0)
|
||||||
|
{
|
||||||
|
// only one command will be generated for episodes search
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
commands.Add(command);
|
||||||
|
}
|
||||||
|
|
||||||
|
return commands;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using Common.Configuration;
|
using Common.Configuration;
|
||||||
|
using Common.Configuration.Arr;
|
||||||
using Domain.Arr.Queue;
|
using Domain.Arr.Queue;
|
||||||
using Domain.Enums;
|
using Domain.Enums;
|
||||||
using Infrastructure.Verticals.Arr;
|
using Infrastructure.Verticals.Arr;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System.Net.Http.Headers;
|
using System.Net.Http.Headers;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
using Common.Configuration;
|
using Common.Configuration;
|
||||||
|
using Common.Configuration.DownloadClient;
|
||||||
using Domain.Models.Deluge.Exceptions;
|
using Domain.Models.Deluge.Exceptions;
|
||||||
using Domain.Models.Deluge.Request;
|
using Domain.Models.Deluge.Request;
|
||||||
using Domain.Models.Deluge.Response;
|
using Domain.Models.Deluge.Response;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Common.Configuration;
|
using Common.Configuration;
|
||||||
|
using Common.Configuration.DownloadClient;
|
||||||
using Domain.Models.Deluge.Response;
|
using Domain.Models.Deluge.Response;
|
||||||
using Infrastructure.Verticals.ContentBlocker;
|
using Infrastructure.Verticals.ContentBlocker;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Common.Configuration;
|
using Common.Configuration;
|
||||||
|
using Common.Configuration.DownloadClient;
|
||||||
using Infrastructure.Verticals.DownloadClient.Deluge;
|
using Infrastructure.Verticals.DownloadClient.Deluge;
|
||||||
using Infrastructure.Verticals.DownloadClient.QBittorrent;
|
using Infrastructure.Verticals.DownloadClient.QBittorrent;
|
||||||
using Infrastructure.Verticals.DownloadClient.Transmission;
|
using Infrastructure.Verticals.DownloadClient.Transmission;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Common.Configuration;
|
using Common.Configuration;
|
||||||
|
using Common.Configuration.DownloadClient;
|
||||||
using Infrastructure.Verticals.ContentBlocker;
|
using Infrastructure.Verticals.ContentBlocker;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Common.Configuration;
|
using Common.Configuration;
|
||||||
|
using Common.Configuration.DownloadClient;
|
||||||
using Infrastructure.Verticals.ContentBlocker;
|
using Infrastructure.Verticals.ContentBlocker;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using Common.Configuration;
|
using Common.Configuration.Arr;
|
||||||
using Domain.Arr.Queue;
|
using Domain.Arr.Queue;
|
||||||
using Domain.Enums;
|
using Domain.Enums;
|
||||||
|
using Domain.Models.Arr;
|
||||||
using Infrastructure.Verticals.Arr;
|
using Infrastructure.Verticals.Arr;
|
||||||
using Infrastructure.Verticals.DownloadClient;
|
using Infrastructure.Verticals.DownloadClient;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
@@ -51,7 +52,7 @@ public abstract class GenericHandler : IDisposable
|
|||||||
|
|
||||||
protected abstract Task ProcessInstanceAsync(ArrInstance instance, InstanceType instanceType);
|
protected abstract Task ProcessInstanceAsync(ArrInstance instance, InstanceType instanceType);
|
||||||
|
|
||||||
protected async Task ProcessArrConfigAsync(ArrConfig config, InstanceType instanceType)
|
private async Task ProcessArrConfigAsync(ArrConfig config, InstanceType instanceType)
|
||||||
{
|
{
|
||||||
if (!config.Enabled)
|
if (!config.Enabled)
|
||||||
{
|
{
|
||||||
@@ -78,13 +79,36 @@ public abstract class GenericHandler : IDisposable
|
|||||||
InstanceType.Radarr => _radarrClient,
|
InstanceType.Radarr => _radarrClient,
|
||||||
_ => throw new NotImplementedException($"instance type {type} is not yet supported")
|
_ => throw new NotImplementedException($"instance type {type} is not yet supported")
|
||||||
};
|
};
|
||||||
|
|
||||||
protected int GetRecordId(InstanceType type, QueueRecord record) =>
|
protected ArrConfig GetConfig(InstanceType type) =>
|
||||||
type switch
|
type switch
|
||||||
{
|
{
|
||||||
// TODO add episode id
|
InstanceType.Sonarr => _sonarrConfig,
|
||||||
InstanceType.Sonarr => record.SeriesId,
|
InstanceType.Radarr => _radarrConfig,
|
||||||
InstanceType.Radarr => record.MovieId,
|
_ => throw new NotImplementedException($"instance type {type} is not yet supported")
|
||||||
|
};
|
||||||
|
|
||||||
|
protected SearchItem GetRecordSearchItem(InstanceType type, QueueRecord record) =>
|
||||||
|
type switch
|
||||||
|
{
|
||||||
|
InstanceType.Sonarr when _sonarrConfig.SearchType is SonarrSearchType.Episode => new SonarrSearchItem
|
||||||
|
{
|
||||||
|
Id = record.EpisodeId,
|
||||||
|
SeriesId = record.SeriesId
|
||||||
|
},
|
||||||
|
InstanceType.Sonarr when _sonarrConfig.SearchType is SonarrSearchType.Season => new SonarrSearchItem
|
||||||
|
{
|
||||||
|
Id = record.SeasonNumber,
|
||||||
|
SeriesId = record.SeriesId
|
||||||
|
},
|
||||||
|
InstanceType.Sonarr when _sonarrConfig.SearchType is SonarrSearchType.Series => new SonarrSearchItem
|
||||||
|
{
|
||||||
|
Id = record.SeriesId,
|
||||||
|
},
|
||||||
|
InstanceType.Radarr => new SearchItem
|
||||||
|
{
|
||||||
|
Id = record.MovieId,
|
||||||
|
},
|
||||||
_ => throw new NotImplementedException($"instance type {type} is not yet supported")
|
_ => throw new NotImplementedException($"instance type {type} is not yet supported")
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
using Common.Configuration;
|
using Common.Configuration;
|
||||||
|
using Common.Configuration.Arr;
|
||||||
using Domain.Arr.Queue;
|
using Domain.Arr.Queue;
|
||||||
using Domain.Enums;
|
using Domain.Enums;
|
||||||
|
using Domain.Models.Arr;
|
||||||
using Infrastructure.Verticals.Arr;
|
using Infrastructure.Verticals.Arr;
|
||||||
using Infrastructure.Verticals.DownloadClient;
|
using Infrastructure.Verticals.DownloadClient;
|
||||||
using Infrastructure.Verticals.Jobs;
|
using Infrastructure.Verticals.Jobs;
|
||||||
@@ -25,7 +27,7 @@ public sealed class QueueCleaner : GenericHandler
|
|||||||
|
|
||||||
protected override async Task ProcessInstanceAsync(ArrInstance instance, InstanceType instanceType)
|
protected override async Task ProcessInstanceAsync(ArrInstance instance, InstanceType instanceType)
|
||||||
{
|
{
|
||||||
HashSet<int> itemsToBeRefreshed = [];
|
HashSet<SearchItem> itemsToBeRefreshed = [];
|
||||||
ArrClient arrClient = GetClient(instanceType);
|
ArrClient arrClient = GetClient(instanceType);
|
||||||
|
|
||||||
await _arrArrQueueIterator.Iterate(arrClient, instance, async items =>
|
await _arrArrQueueIterator.Iterate(arrClient, instance, async items =>
|
||||||
@@ -49,12 +51,12 @@ public sealed class QueueCleaner : GenericHandler
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
itemsToBeRefreshed.Add(GetRecordId(instanceType, record));
|
itemsToBeRefreshed.Add(GetRecordSearchItem(instanceType, record));
|
||||||
|
|
||||||
await arrClient.DeleteQueueItemAsync(instance, record);
|
await arrClient.DeleteQueueItemAsync(instance, record);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
await arrClient.RefreshItemsAsync(instance, itemsToBeRefreshed);
|
await arrClient.RefreshItemsAsync(instance, GetConfig(instanceType), itemsToBeRefreshed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
<rss version="2.0">
|
<rss version="2.0">
|
||||||
<channel>
|
<channel>
|
||||||
<title>Test feed</title>
|
<title>Test feed</title>
|
||||||
<link>http://nginx/custom/radarr_bad_single.xml</link>
|
<link>http://nginx/custom/radarr.xml</link>
|
||||||
<description>
|
<description>
|
||||||
Test
|
Test
|
||||||
</description>
|
</description>
|
||||||
@@ -11,6 +11,17 @@
|
|||||||
<lastBuildDate>Tue, 5 Nov 2024 22:02:13 -0400</lastBuildDate>
|
<lastBuildDate>Tue, 5 Nov 2024 22:02:13 -0400</lastBuildDate>
|
||||||
<docs>https://validator.w3.org/feed/docs/rss2.html</docs>
|
<docs>https://validator.w3.org/feed/docs/rss2.html</docs>
|
||||||
<ttl>30</ttl>
|
<ttl>30</ttl>
|
||||||
|
<item>
|
||||||
|
<title>Speak.No.Evil.2024.2160p.MA.WEB-DL.DDP5.1.Atmos.H.265-HHWEB</title>
|
||||||
|
<description>Test</description>
|
||||||
|
<size>4138858110</size>
|
||||||
|
<link>http://nginx/custom/radarr_bad_nested.torrent</link>
|
||||||
|
<guid isPermaLink="false">
|
||||||
|
174674a88c8927f6f9057ac3f81efde384ed216cade43564ec450f2cb4677554
|
||||||
|
</guid>
|
||||||
|
<pubDate>Sat, 24 Sep 2022 22:02:13 -0300</pubDate>
|
||||||
|
</item>
|
||||||
|
|
||||||
<item>
|
<item>
|
||||||
<title>The.Wild.Robot.2024.2160p.AMZN.WEB-DL.DDP5.1.Atmos.H.265-FLUX</title>
|
<title>The.Wild.Robot.2024.2160p.AMZN.WEB-DL.DDP5.1.Atmos.H.265-FLUX</title>
|
||||||
<description>Test</description>
|
<description>Test</description>
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
<rss version="2.0">
|
|
||||||
<channel>
|
|
||||||
<title>Test feed</title>
|
|
||||||
<link>http://nginx/custom/radarr_bad_nested.xml</link>
|
|
||||||
<description>
|
|
||||||
Test
|
|
||||||
</description>
|
|
||||||
<language>en-CA</language>
|
|
||||||
<copyright> Test </copyright>
|
|
||||||
<pubDate>Tue, 5 Nov 2024 22:02:13 -0400</pubDate>
|
|
||||||
<lastBuildDate>Tue, 5 Nov 2024 22:02:13 -0400</lastBuildDate>
|
|
||||||
<docs>https://validator.w3.org/feed/docs/rss2.html</docs>
|
|
||||||
<ttl>30</ttl>
|
|
||||||
<item>
|
|
||||||
<title>Speak.No.Evil.2024.2160p.MA.WEB-DL.DDP5.1.Atmos.H.265-HHWEB</title>
|
|
||||||
<description>Test</description>
|
|
||||||
<size>4138858110</size>
|
|
||||||
<link>http://nginx/custom/radarr_bad_nested.torrent</link>
|
|
||||||
<guid isPermaLink="false">
|
|
||||||
174674a88c8947f6f9057ac3f81efde384ed216cade43564ec450f2cb4677554
|
|
||||||
</guid>
|
|
||||||
<pubDate>Sat, 24 Sep 2022 22:02:13 -0300</pubDate>
|
|
||||||
</item>
|
|
||||||
</channel>
|
|
||||||
</rss>
|
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
<rss version="2.0">
|
||||||
|
<channel>
|
||||||
|
<title>Test feed</title>
|
||||||
|
<link>http://nginx/custom/sonarr.xml</link>
|
||||||
|
<description>
|
||||||
|
Test
|
||||||
|
</description>
|
||||||
|
<language>en-CA</language>
|
||||||
|
<copyright> Test </copyright>
|
||||||
|
<pubDate>Tue, 5 Nov 2024 22:02:13 -0400</pubDate>
|
||||||
|
<lastBuildDate>Tue, 5 Nov 2024 22:02:13 -0400</lastBuildDate>
|
||||||
|
<docs>https://validator.w3.org/feed/docs/rss2.html</docs>
|
||||||
|
<ttl>30</ttl>
|
||||||
|
<item>
|
||||||
|
<title>Agatha.All.Along.S01E01.Seekest.Thou.the.Road.2160p.APPS.WEB-DL.DDP5.1.Atmos.H.265-VARYG</title>
|
||||||
|
<description>Test</description>
|
||||||
|
<size>4138858110</size>
|
||||||
|
<link>http://nginx/custom/sonarr_bad_nested.torrent</link>
|
||||||
|
<guid isPermaLink="false">
|
||||||
|
174674a88c8947f6f9057a23f81efde384ed216cade43564ec450f2cb4677554
|
||||||
|
</guid>
|
||||||
|
<pubDate>Sat, 24 Sep 2022 22:02:13 -0300</pubDate>
|
||||||
|
</item>
|
||||||
|
|
||||||
|
<item>
|
||||||
|
<title>Agatha.All.Along.S01E02.Circle.Sewn.With.Fate.Unlock.Thy.Hidden.Gate.2160p.DSNP.WEB-DL.DDP5.1.Atmos.DV.HDR.H.265-FLUX</title>
|
||||||
|
<description>Test</description>
|
||||||
|
<size>4138858110</size>
|
||||||
|
<link>http://nginx/custom/sonarr_bad_single.torrent</link>
|
||||||
|
<guid isPermaLink="false">
|
||||||
|
174674a88c8947f689057ac3f81efde384ed216cade43564ec450f2cb4677554
|
||||||
|
</guid>
|
||||||
|
<pubDate>Sat, 24 Sep 2022 22:02:13 -0300</pubDate>
|
||||||
|
</item>
|
||||||
|
|
||||||
|
<item>
|
||||||
|
<title>Top.Gear.S23E01.720p.x265.HDTV.HEVC.-.YSTEAM</title>
|
||||||
|
<description>Test</description>
|
||||||
|
<size>4138858110</size>
|
||||||
|
<link>magnet:?xt=urn:btih:cf82cf859b110af0ad3d94b846e006828417b193&dn=TPG.2301.720p.x265.yourserie.com.mkv</link>
|
||||||
|
<guid isPermaLink="false">
|
||||||
|
174674a88c8947f6f5057ac3f81efde384ed216cade43564ec450f2cb4677554
|
||||||
|
</guid>
|
||||||
|
<pubDate>Sat, 24 Sep 2022 22:02:13 -0300</pubDate>
|
||||||
|
</item>
|
||||||
|
|
||||||
|
<item>
|
||||||
|
<title>Top.Gear.S23E01.720p.x265.HDTV.HEVC.-.YSTEAM</title>
|
||||||
|
<description>Test</description>
|
||||||
|
<size>4138858110</size>
|
||||||
|
<link>http://nginx/custom/sonarr_bad_stuck_stalled.torrent</link>
|
||||||
|
<guid isPermaLink="false">
|
||||||
|
174674a88c8947f6f9057ac3f81efde384ed216cade43564ec450f2cb4677554
|
||||||
|
</guid>
|
||||||
|
<pubDate>Sat, 24 Sep 2022 22:02:13 -0300</pubDate>
|
||||||
|
</item>
|
||||||
|
|
||||||
|
<item>
|
||||||
|
<title>Top.Gear.S23E02.720p.x265.HDTV.HEVC.-.YSTEAM</title>
|
||||||
|
<description>Test</description>
|
||||||
|
<size>4138858110</size>
|
||||||
|
<link>http://nginx/custom/sonarr_bad_nested_top.torrent</link>
|
||||||
|
<guid isPermaLink="false">
|
||||||
|
174674a88c8947f6f9057ac3f82efde384ed216cade43564ec450f2cb4677554
|
||||||
|
</guid>
|
||||||
|
<pubDate>Sat, 24 Sep 2022 22:02:13 -0300</pubDate>
|
||||||
|
</item>
|
||||||
|
</channel>
|
||||||
|
</rss>
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
<rss version="2.0">
|
|
||||||
<channel>
|
|
||||||
<title>Test feed</title>
|
|
||||||
<link>http://nginx/custom/sonarr_bad_nested.xml</link>
|
|
||||||
<description>
|
|
||||||
Test
|
|
||||||
</description>
|
|
||||||
<language>en-CA</language>
|
|
||||||
<copyright> Test </copyright>
|
|
||||||
<pubDate>Tue, 5 Nov 2024 22:02:13 -0400</pubDate>
|
|
||||||
<lastBuildDate>Tue, 5 Nov 2024 22:02:13 -0400</lastBuildDate>
|
|
||||||
<docs>https://validator.w3.org/feed/docs/rss2.html</docs>
|
|
||||||
<ttl>30</ttl>
|
|
||||||
<item>
|
|
||||||
<title>Agatha.All.Along.S01E01.Seekest.Thou.the.Road.2160p.APPS.WEB-DL.DDP5.1.Atmos.H.265-VARYG</title>
|
|
||||||
<description>Test</description>
|
|
||||||
<size>4138858110</size>
|
|
||||||
<link>http://nginx/custom/sonarr_bad_nested.torrent</link>
|
|
||||||
<guid isPermaLink="false">
|
|
||||||
174674a88c8947f6f9057ac3f81efde384ed216cade43564ec450f2cb4677554
|
|
||||||
</guid>
|
|
||||||
<pubDate>Sat, 24 Sep 2022 22:02:13 -0300</pubDate>
|
|
||||||
</item>
|
|
||||||
</channel>
|
|
||||||
</rss>
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
d8:announce28:http://tracker:6969/announce10:created by26:Enhanced-CTorrent/dnh3.3.213:creation datei1732896923e4:infod5:filesld6:lengthi2604e4:pathl4:Dir15:Dir1111:test11.zipxeed6:lengthi2604e4:pathl4:Dir110:sample.txteed6:lengthi2604e4:pathl4:Dir210:test2.zipxeed6:lengthi2604e4:pathl9:test.zipxeed6:lengthi2604e4:pathl49:Top.Gear.S23E02.720p.x265.HDTV.HEVC.-.YSTEAM.zipxeee4:name44:Top.Gear.S23E02.720p.x265.HDTV.HEVC.-.YSTEAM12:piece lengthi262144e6:pieces20:w¤ŸÌ³RÇþ'6Fíoð}ä°ee
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
<rss version="2.0">
|
|
||||||
<channel>
|
|
||||||
<title>Test feed</title>
|
|
||||||
<link>http://nginx/custom/sonarr_bad_single.xml</link>
|
|
||||||
<description>
|
|
||||||
Test
|
|
||||||
</description>
|
|
||||||
<language>en-CA</language>
|
|
||||||
<copyright> Test </copyright>
|
|
||||||
<pubDate>Tue, 5 Nov 2024 22:02:13 -0400</pubDate>
|
|
||||||
<lastBuildDate>Tue, 5 Nov 2024 22:02:13 -0400</lastBuildDate>
|
|
||||||
<docs>https://validator.w3.org/feed/docs/rss2.html</docs>
|
|
||||||
<ttl>30</ttl>
|
|
||||||
<item>
|
|
||||||
<title>Agatha.All.Along.S01E02.Circle.Sewn.With.Fate.Unlock.Thy.Hidden.Gate.2160p.DSNP.WEB-DL.DDP5.1.Atmos.DV.HDR.H.265-FLUX</title>
|
|
||||||
<description>Test</description>
|
|
||||||
<size>4138858110</size>
|
|
||||||
<link>http://nginx/custom/sonarr_bad_single.torrent</link>
|
|
||||||
<guid isPermaLink="false">
|
|
||||||
174674a88c8947f6f9057ac3f81efde384ed216cade43564ec450f2cb4677554
|
|
||||||
</guid>
|
|
||||||
<pubDate>Sat, 24 Sep 2022 22:02:13 -0300</pubDate>
|
|
||||||
</item>
|
|
||||||
</channel>
|
|
||||||
</rss>
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
<rss version="2.0">
|
|
||||||
<channel>
|
|
||||||
<title>Test feed</title>
|
|
||||||
<link>http://nginx/custom/sonarr_bad_stuck_metadata.xml</link>
|
|
||||||
<description>
|
|
||||||
Test
|
|
||||||
</description>
|
|
||||||
<language>en-CA</language>
|
|
||||||
<copyright> Test </copyright>
|
|
||||||
<pubDate>Tue, 5 Nov 2024 22:02:13 -0400</pubDate>
|
|
||||||
<lastBuildDate>Tue, 5 Nov 2024 22:02:13 -0400</lastBuildDate>
|
|
||||||
<docs>https://validator.w3.org/feed/docs/rss2.html</docs>
|
|
||||||
<ttl>30</ttl>
|
|
||||||
<item>
|
|
||||||
<title>Top.Gear.S23E01.720p.x265.HDTV.HEVC.-.YSTEAM</title>
|
|
||||||
<description>Test</description>
|
|
||||||
<size>4138858110</size>
|
|
||||||
<link>magnet:?xt=urn:btih:cf82cf859b110af0ad3d94b846e006828417b193&dn=TPG.2301.720p.x265.yourserie.com.mkv</link>
|
|
||||||
<guid isPermaLink="false">
|
|
||||||
174674a88c8947f6f9057ac3f81efde384ed216cade43564ec450f2cb4677554
|
|
||||||
</guid>
|
|
||||||
<pubDate>Sat, 24 Sep 2022 22:02:13 -0300</pubDate>
|
|
||||||
</item>
|
|
||||||
</channel>
|
|
||||||
</rss>
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
<rss version="2.0">
|
|
||||||
<channel>
|
|
||||||
<title>Test feed</title>
|
|
||||||
<link>http://nginx/custom/sonarr_bad_stuck_metadata.xml</link>
|
|
||||||
<description>
|
|
||||||
Test
|
|
||||||
</description>
|
|
||||||
<language>en-CA</language>
|
|
||||||
<copyright> Test </copyright>
|
|
||||||
<pubDate>Tue, 5 Nov 2024 22:02:13 -0400</pubDate>
|
|
||||||
<lastBuildDate>Tue, 5 Nov 2024 22:02:13 -0400</lastBuildDate>
|
|
||||||
<docs>https://validator.w3.org/feed/docs/rss2.html</docs>
|
|
||||||
<ttl>30</ttl>
|
|
||||||
<item>
|
|
||||||
<title>Top.Gear.S23E01.720p.x265.HDTV.HEVC.-.YSTEAM</title>
|
|
||||||
<description>Test</description>
|
|
||||||
<size>4138858110</size>
|
|
||||||
<link>http://nginx/custom/sonarr_bad_stuck_stalled.torrent</link>
|
|
||||||
<guid isPermaLink="false">
|
|
||||||
174674a88c8947f6f9057ac3f81efde384ed216cade43564ec450f2cb4677554
|
|
||||||
</guid>
|
|
||||||
<pubDate>Sat, 24 Sep 2022 22:02:13 -0300</pubDate>
|
|
||||||
</item>
|
|
||||||
</channel>
|
|
||||||
</rss>
|
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
b72541215214be2a1d96ef6b29ca1305f5e5e1f6
|
|
||||||
a4a1d1dd1db25763caa8f5e4d25ad72ef304094b
|
|
||||||
2b2ec156461d77bc48b8fe4d62cede50dcdff8e0
|
2b2ec156461d77bc48b8fe4d62cede50dcdff8e0
|
||||||
|
a4a1d1dd1db25763caa8f5e4d25ad72ef304094b
|
||||||
|
b72541215214be2a1d96ef6b29ca1305f5e5e1f6
|
||||||
59ab2bc053430fe53e06a93e2eadb7acb6a6bf2c
|
59ab2bc053430fe53e06a93e2eadb7acb6a6bf2c
|
||||||
|
11cece7f8721c484126b66f609d52738ff1bbf1e
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
[Stats]
|
[Stats]
|
||||||
AllStats=@Variant(\0\0\0\x1c\0\0\0\x2\0\0\0\x12\0\x41\0l\0l\0t\0i\0m\0\x65\0\x44\0L\0\0\0\x4\0\0\0\0\0\x61La\0\0\0\x12\0\x41\0l\0l\0t\0i\0m\0\x65\0U\0L\0\0\0\x4\0\0\0\0\0\x9bGV)
|
AllStats=@Variant(\0\0\0\x1c\0\0\0\x2\0\0\0\x12\0\x41\0l\0l\0t\0i\0m\0\x65\0\x44\0L\0\0\0\x4\0\0\0\0\0\x61\xc0\xdf\0\0\0\x12\0\x41\0l\0l\0t\0i\0m\0\x65\0U\0L\0\0\0\x4\0\0\0\0\0\x9b\xf9\x8a)
|
||||||
|
|||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
testtesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttest
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
testtesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttest
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
testtesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttest
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
testtesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttest
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
testtesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttest
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
d8:announce28:http://tracker:6969/announce10:created by26:Enhanced-CTorrent/dnh3.3.213:creation datei1732896923e4:infod5:filesld6:lengthi2604e4:pathl4:Dir15:Dir1111:test11.zipxeed6:lengthi2604e4:pathl4:Dir110:sample.txteed6:lengthi2604e4:pathl4:Dir210:test2.zipxeed6:lengthi2604e4:pathl9:test.zipxeed6:lengthi2604e4:pathl49:Top.Gear.S23E02.720p.x265.HDTV.HEVC.-.YSTEAM.zipxeee4:name44:Top.Gear.S23E02.720p.x265.HDTV.HEVC.-.YSTEAM12:piece lengthi262144e6:pieces20:w¤ŸÌ³RÇþ'6Fíoð}ä°ee
|
||||||
+1
-1
@@ -1 +1 @@
|
|||||||
{"update":{"sid":"87056ff6106c4bcf8fc90506d02be642","did":"92eba3c5-a8d0-44d5-836d-25bc4aa81a85","init":true,"started":"2024-11-20T08:51:02.9022577+00:00","timestamp":"2024-11-20T08:51:02.902865+00:00","seq":0,"duration":0,"errors":0,"attrs":{"release":"Radarr@5.14.0.9383-master","environment":"master"}}}
|
{"update":{"sid":"743459ae24ef4f4c8a85171b21fd99a8","did":"92eba3c5-a8d0-44d5-836d-25bc4aa81a85","init":true,"started":"2024-11-29T15:46:38.3721409+00:00","timestamp":"2024-11-29T15:46:38.3728803+00:00","seq":0,"duration":0,"errors":0,"attrs":{"release":"Radarr@5.14.0.9383-master","environment":"master"}}}
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1 +1 @@
|
|||||||
145
|
144
|
||||||
@@ -1 +0,0 @@
|
|||||||
{"update":{"sid":"726ab1cef3114e11a386851d89cb6de4","did":"1df9f2cc-17dc-4130-9753-9b694f82f1b5","init":true,"started":"2024-11-20T08:51:02.5386604+00:00","timestamp":"2024-11-20T08:51:02.5393706+00:00","seq":0,"duration":0,"errors":0,"attrs":{"release":"4.0.10.2544-main","environment":"main"}}}
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1 +1 @@
|
|||||||
145
|
146
|
||||||
@@ -168,12 +168,13 @@ services:
|
|||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|
||||||
cleanuperr:
|
cleanuperr:
|
||||||
image: flaminel/cleanuperr:latest
|
image: ghcr.io/flmorg/cleanuperr:latest
|
||||||
container_name: cleanuperr
|
container_name: cleanuperr
|
||||||
environment:
|
environment:
|
||||||
- LOGGING__LOGLEVEL=Debug
|
- LOGGING__LOGLEVEL=Debug
|
||||||
- LOGGING__FILE__ENABLED=false
|
- LOGGING__FILE__ENABLED=false
|
||||||
- LOGGING__FILE__PATH=/var/logs
|
- LOGGING__FILE__PATH=/var/logs
|
||||||
|
- LOGGING__ENHANCED=true
|
||||||
|
|
||||||
- TRIGGERS__QUEUECLEANER=0/30 * * * * ?
|
- TRIGGERS__QUEUECLEANER=0/30 * * * * ?
|
||||||
- TRIGGERS__CONTENTBLOCKER=0/30 * * * * ?
|
- TRIGGERS__CONTENTBLOCKER=0/30 * * * * ?
|
||||||
@@ -203,6 +204,7 @@ services:
|
|||||||
# - TRANSMISSION__PASSWORD=testing
|
# - TRANSMISSION__PASSWORD=testing
|
||||||
|
|
||||||
- SONARR__ENABLED=true
|
- SONARR__ENABLED=true
|
||||||
|
- SONARR__SEARCHTYPE=Episode
|
||||||
- SONARR__INSTANCES__0__URL=http://sonarr:8989
|
- SONARR__INSTANCES__0__URL=http://sonarr:8989
|
||||||
- SONARR__INSTANCES__0__APIKEY=96736c3eb3144936b8f1d62d27be8cee
|
- SONARR__INSTANCES__0__APIKEY=96736c3eb3144936b8f1d62d27be8cee
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
## LOGGING__ENHANCED
|
||||||
|
|
||||||
|
Some logs may contain information that is hard to read. Enhancing these logs usually comes with the cost of additional calls to the APIs.
|
||||||
|
|
||||||
|
If enabled, logs like this
|
||||||
|
|
||||||
|
```movie search triggered | http://localhost:7878/ | movie ids: 1, 2```
|
||||||
|
|
||||||
|
will transform into
|
||||||
|
|
||||||
|
```movie search triggered | http://localhost:7878/ | [Speak No Evil][The Wild Robot]```
|
||||||
Reference in New Issue
Block a user