diff --git a/MediaBrowser.Api/Library/FileOrganizationService.cs b/MediaBrowser.Api/Library/FileOrganizationService.cs index 1224fa9570..849e9cf0db 100644 --- a/MediaBrowser.Api/Library/FileOrganizationService.cs +++ b/MediaBrowser.Api/Library/FileOrganizationService.cs @@ -6,6 +6,7 @@ using MediaBrowser.Model.Querying; using ServiceStack; using System.Threading.Tasks; using MediaBrowser.Model.Dto; +using MediaBrowser.Model.Serialization; namespace MediaBrowser.Api.Library { @@ -54,7 +55,7 @@ namespace MediaBrowser.Api.Library public string Id { get; set; } } - [Route("/Library/FileOrganizations/{Id}/Episode/Organize", "POST", Summary = "Performs an organization")] + [Route("/Library/FileOrganizations/{Id}/Episode/Organize", "POST", Summary = "Performs organization of a tv episode")] public class OrganizeEpisode { [ApiMember(Name = "Id", Description = "Result Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] @@ -74,6 +75,18 @@ namespace MediaBrowser.Api.Library [ApiMember(Name = "RememberCorrection", Description = "Whether or not to apply the same correction to future episodes of the same series.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "POST")] public bool RememberCorrection { get; set; } + + [ApiMember(Name = "NewSeriesProviderIds", Description = "A list of provider IDs identifying a new series.", IsRequired = false, DataType = "Dictionary", ParameterType = "query", Verb = "POST")] + public Dictionary NewSeriesProviderIds { get; set; } + + [ApiMember(Name = "NewSeriesName", Description = "Name of a series to add.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")] + public string NewSeriesName { get; set; } + + [ApiMember(Name = "NewSeriesYear", Description = "Year of a series to add.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")] + public string NewSeriesYear { get; set; } + + [ApiMember(Name = "TargetFolder", Description = "Target Folder", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")] + public string TargetFolder { get; set; } } [Route("/Library/FileOrganizations/SmartMatches", "GET", Summary = "Gets smart match entries")] @@ -106,9 +119,14 @@ namespace MediaBrowser.Api.Library { private readonly IFileOrganizationService _iFileOrganizationService; - public FileOrganizationService(IFileOrganizationService iFileOrganizationService) + /// The _json serializer + /// + private readonly IJsonSerializer _jsonSerializer; + + public FileOrganizationService(IFileOrganizationService iFileOrganizationService, IJsonSerializer jsonSerializer) { _iFileOrganizationService = iFileOrganizationService; + _jsonSerializer = jsonSerializer; } public object Get(GetFileOrganizationActivity request) @@ -145,6 +163,13 @@ namespace MediaBrowser.Api.Library public void Post(OrganizeEpisode request) { + var dicNewProviderIds = new Dictionary(); + + if (request.NewSeriesProviderIds != null) + { + dicNewProviderIds = request.NewSeriesProviderIds; + } + var task = _iFileOrganizationService.PerformEpisodeOrganization(new EpisodeFileOrganizationRequest { EndingEpisodeNumber = request.EndingEpisodeNumber, @@ -152,9 +177,17 @@ namespace MediaBrowser.Api.Library RememberCorrection = request.RememberCorrection, ResultId = request.Id, SeasonNumber = request.SeasonNumber, - SeriesId = request.SeriesId + SeriesId = request.SeriesId, + NewSeriesName = request.NewSeriesName, + NewSeriesYear = request.NewSeriesYear, + NewSeriesProviderIds = dicNewProviderIds, + TargetFolder = request.TargetFolder }); + // For async processing (close dialog early instead of waiting until the file has been copied) + //var tasks = new Task[] { task }; + //Task.WaitAll(tasks, 8000); + Task.WaitAll(task); } diff --git a/MediaBrowser.Model/FileOrganization/EpisodeFileOrganizationRequest.cs b/MediaBrowser.Model/FileOrganization/EpisodeFileOrganizationRequest.cs index 0b12ebc51d..b20e43e544 100644 --- a/MediaBrowser.Model/FileOrganization/EpisodeFileOrganizationRequest.cs +++ b/MediaBrowser.Model/FileOrganization/EpisodeFileOrganizationRequest.cs @@ -1,4 +1,6 @@ -namespace MediaBrowser.Model.FileOrganization +using System.Collections.Generic; + +namespace MediaBrowser.Model.FileOrganization { public class EpisodeFileOrganizationRequest { @@ -13,5 +15,12 @@ public int? EndingEpisodeNumber { get; set; } public bool RememberCorrection { get; set; } + public string NewSeriesName { get; set; } + + public string NewSeriesYear { get; set; } + + public string TargetFolder { get; set; } + + public Dictionary NewSeriesProviderIds { get; set; } } } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs b/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs index 42f88a5c0d..24e8c71374 100644 --- a/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs +++ b/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs @@ -157,7 +157,43 @@ namespace MediaBrowser.Server.Implementations.FileOrganization { var result = _organizationService.GetResult(request.ResultId); - var series = (Series)_libraryManager.GetItemById(new Guid(request.SeriesId)); + Series series = null; + + if (request.NewSeriesProviderIds.Count > 0) + { + // We're having a new series here + SeriesInfo seriesRequest = new SeriesInfo(); + seriesRequest.ProviderIds = request.NewSeriesProviderIds; + + var refreshOptions = new MetadataRefreshOptions(_fileSystem); + series = new Series(); + series.Id = Guid.NewGuid(); + series.Name = request.NewSeriesName; + + int year; + if (int.TryParse(request.NewSeriesYear, out year)) + { + series.ProductionYear = year; + } + + var seriesFolderName = series.Name; + if (series.ProductionYear.HasValue) + { + seriesFolderName = string.Format("{0} ({1})", seriesFolderName, series.ProductionYear); + } + + series.Path = Path.Combine(request.TargetFolder, seriesFolderName); + + series.ProviderIds = request.NewSeriesProviderIds; + + await series.RefreshMetadata(refreshOptions, cancellationToken); + } + + if (series == null) + { + // Existing Series + series = (Series)_libraryManager.GetItemById(new Guid(request.SeriesId)); + } await OrganizeEpisode(result.OriginalPath, series,