mirror of
https://github.com/Sonarr/Sonarr
synced 2026-01-26 01:11:47 +01:00
Add v5 manual import endpoints
This commit is contained in:
parent
4c13a01c8e
commit
8da611ea58
3 changed files with 203 additions and 0 deletions
82
src/Sonarr.Api.V5/ManualImport/ManualImportController.cs
Normal file
82
src/Sonarr.Api.V5/ManualImport/ManualImportController.cs
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
using Microsoft.AspNetCore.Mvc;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Languages;
|
||||
using NzbDrone.Core.MediaFiles.EpisodeImport.Manual;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using Sonarr.Http;
|
||||
using Sonarr.Http.REST;
|
||||
|
||||
namespace Sonarr.Api.V5.ManualImport;
|
||||
|
||||
[V5ApiController]
|
||||
public class ManualImportController : Controller
|
||||
{
|
||||
private readonly IManualImportService _manualImportService;
|
||||
|
||||
public ManualImportController(IManualImportService manualImportService)
|
||||
{
|
||||
_manualImportService = manualImportService;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Produces("application/json")]
|
||||
public List<ManualImportResource> GetMediaFiles(string? folder, string? downloadId, int? seriesId, int? seasonNumber, bool filterExistingFiles = true)
|
||||
{
|
||||
if (seriesId.HasValue && downloadId.IsNullOrWhiteSpace())
|
||||
{
|
||||
return _manualImportService.GetMediaFiles(seriesId.Value, seasonNumber).ToResource().Select(AddQualityWeight).ToList();
|
||||
}
|
||||
|
||||
return _manualImportService.GetMediaFiles(folder, downloadId, seriesId, filterExistingFiles).ToResource().Select(AddQualityWeight).ToList();
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Consumes("application/json")]
|
||||
public List<ManualImportResource> ReprocessItems([FromBody] List<ManualImportReprocessResource> items)
|
||||
{
|
||||
if (items is { Count: 0 })
|
||||
{
|
||||
throw new BadRequestException("items must be provided");
|
||||
}
|
||||
|
||||
var updatedItems = new List<ManualImportItem>();
|
||||
|
||||
foreach (var item in items)
|
||||
{
|
||||
var processedItem = _manualImportService.ReprocessItem(item.Path, item.DownloadId, item.SeriesId, item.SeasonNumber, item.EpisodeIds ?? new List<int>(), item.ReleaseGroup, item.Quality, item.Languages, item.IndexerFlags, item.ReleaseType);
|
||||
|
||||
// Only use the processed item's languages, quality, and release group if the user hasn't specified them.
|
||||
// Languages won't be returned when reprocessing if the season/episode isn't filled in yet and we don't want to return no languages to the client.
|
||||
if (processedItem.Languages.Empty() || item.Languages.Count > 1 || (item.Languages.SingleOrDefault() ?? Language.Unknown) == Language.Unknown)
|
||||
{
|
||||
processedItem.Languages = item.Languages;
|
||||
}
|
||||
|
||||
if (item.Quality?.Quality != Quality.Unknown)
|
||||
{
|
||||
processedItem.Quality = item.Quality;
|
||||
}
|
||||
|
||||
if (item.ReleaseGroup.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
processedItem.ReleaseGroup = item.ReleaseGroup;
|
||||
}
|
||||
|
||||
updatedItems.Add(processedItem);
|
||||
}
|
||||
|
||||
return updatedItems.ToResource();
|
||||
}
|
||||
|
||||
private ManualImportResource AddQualityWeight(ManualImportResource item)
|
||||
{
|
||||
if (item.Quality != null)
|
||||
{
|
||||
item.QualityWeight = Quality.DefaultQualityDefinitions.Single(q => q.Quality == item.Quality.Quality).Weight;
|
||||
item.QualityWeight += item.Quality.Revision.Real * 10;
|
||||
item.QualityWeight += item.Quality.Revision.Version;
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
using NzbDrone.Core.Languages;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using Sonarr.Api.V5.CustomFormats;
|
||||
using Sonarr.Api.V5.Episodes;
|
||||
using Sonarr.Http.REST;
|
||||
|
||||
namespace Sonarr.Api.V5.ManualImport;
|
||||
|
||||
public class ManualImportReprocessResource : RestResource
|
||||
{
|
||||
public string? Path { get; set; }
|
||||
public int SeriesId { get; set; }
|
||||
public int? SeasonNumber { get; set; }
|
||||
public List<EpisodeResource> Episodes { get; set; } = [];
|
||||
public List<int>? EpisodeIds { get; set; }
|
||||
public QualityModel? Quality { get; set; }
|
||||
public List<Language> Languages { get; set; } = [];
|
||||
public string? ReleaseGroup { get; set; }
|
||||
public string? DownloadId { get; set; }
|
||||
public List<CustomFormatResource> CustomFormats { get; set; } = [];
|
||||
public int CustomFormatScore { get; set; }
|
||||
public int IndexerFlags { get; set; }
|
||||
public ReleaseType ReleaseType { get; set; }
|
||||
public IEnumerable<ImportRejectionResource> Rejections { get; set; } = [];
|
||||
}
|
||||
95
src/Sonarr.Api.V5/ManualImport/ManualImportResource.cs
Normal file
95
src/Sonarr.Api.V5/ManualImport/ManualImportResource.cs
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
using NzbDrone.Common.Crypto;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Languages;
|
||||
using NzbDrone.Core.MediaFiles.EpisodeImport;
|
||||
using NzbDrone.Core.MediaFiles.EpisodeImport.Manual;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using Sonarr.Api.V5.CustomFormats;
|
||||
using Sonarr.Api.V5.Episodes;
|
||||
using Sonarr.Api.V5.Series;
|
||||
using Sonarr.Http.REST;
|
||||
|
||||
namespace Sonarr.Api.V5.ManualImport;
|
||||
|
||||
public class ManualImportResource : RestResource
|
||||
{
|
||||
public string? Path { get; set; }
|
||||
public string? RelativePath { get; set; }
|
||||
public string? FolderName { get; set; }
|
||||
public string? Name { get; set; }
|
||||
public long Size { get; set; }
|
||||
public SeriesResource? Series { get; set; }
|
||||
public int? SeasonNumber { get; set; }
|
||||
public List<EpisodeResource> Episodes { get; set; } = [];
|
||||
public int? EpisodeFileId { get; set; }
|
||||
public string? ReleaseGroup { get; set; }
|
||||
public QualityModel? Quality { get; set; }
|
||||
public List<Language> Languages { get; set; } = [];
|
||||
public int QualityWeight { get; set; }
|
||||
public string? DownloadId { get; set; }
|
||||
public List<CustomFormatResource> CustomFormats { get; set; } = [];
|
||||
public int CustomFormatScore { get; set; }
|
||||
public int IndexerFlags { get; set; }
|
||||
public ReleaseType ReleaseType { get; set; }
|
||||
public IEnumerable<ImportRejectionResource> Rejections { get; set; } = [];
|
||||
}
|
||||
|
||||
public static class ManualImportResourceMapper
|
||||
{
|
||||
public static ManualImportResource ToResource(this ManualImportItem model)
|
||||
{
|
||||
var customFormats = model.CustomFormats;
|
||||
var customFormatScore = model.Series?.QualityProfile?.Value?.CalculateCustomFormatScore(customFormats) ?? 0;
|
||||
|
||||
return new ManualImportResource
|
||||
{
|
||||
Id = HashConverter.GetHashInt31(model.Path),
|
||||
Path = model.Path,
|
||||
RelativePath = model.RelativePath,
|
||||
FolderName = model.FolderName,
|
||||
Name = model.Name,
|
||||
Size = model.Size,
|
||||
Series = model.Series?.ToResource(),
|
||||
SeasonNumber = model.SeasonNumber,
|
||||
Episodes = model.Episodes.ToResource(),
|
||||
EpisodeFileId = model.EpisodeFileId,
|
||||
ReleaseGroup = model.ReleaseGroup,
|
||||
Quality = model.Quality,
|
||||
Languages = model.Languages,
|
||||
CustomFormats = customFormats.ToResource(false),
|
||||
CustomFormatScore = customFormatScore,
|
||||
|
||||
// QualityWeight
|
||||
DownloadId = model.DownloadId,
|
||||
IndexerFlags = model.IndexerFlags,
|
||||
ReleaseType = model.ReleaseType,
|
||||
Rejections = model.Rejections.Select(r => r.ToResource())
|
||||
};
|
||||
}
|
||||
|
||||
public static List<ManualImportResource> ToResource(this IEnumerable<ManualImportItem> models)
|
||||
{
|
||||
return models.Select(ToResource).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
public class ImportRejectionResource
|
||||
{
|
||||
public ImportRejectionReason Reason { get; set; }
|
||||
public string? Message { get; set; }
|
||||
public RejectionType Type { get; set; }
|
||||
}
|
||||
|
||||
public static class ImportRejectionResourceMapper
|
||||
{
|
||||
public static ImportRejectionResource ToResource(this ImportRejection rejection)
|
||||
{
|
||||
return new ImportRejectionResource
|
||||
{
|
||||
Reason = rejection.Reason,
|
||||
Message = rejection.Message,
|
||||
Type = rejection.Type
|
||||
};
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue