#680 - begin resolution feature

pull/702/head
Luke Pulverenti 11 years ago
parent 1235283279
commit a29e1eb036

@ -328,16 +328,12 @@ namespace MediaBrowser.Model.Configuration
public string SeasonZeroFolderName { get; set; } public string SeasonZeroFolderName { get; set; }
public string EpisodeNamePattern { get; set; } public string EpisodeNamePattern { get; set; }
public string MultiEpisodeNamePattern { get; set; }
public bool OverwriteExistingEpisodes { get; set; } public bool OverwriteExistingEpisodes { get; set; }
public bool DeleteEmptyFolders { get; set; } public bool DeleteEmptyFolders { get; set; }
/// <summary>
/// Will log results but will not actually make any changes
/// </summary>
public bool EnableTrialMode { get; set; }
public TvFileOrganizationOptions() public TvFileOrganizationOptions()
{ {
MinFileSizeMb = 50; MinFileSizeMb = 50;
@ -347,10 +343,9 @@ namespace MediaBrowser.Model.Configuration
WatchLocations = new string[] { }; WatchLocations = new string[] { };
EpisodeNamePattern = "%sn - %sx%0e - %en.%ext"; EpisodeNamePattern = "%sn - %sx%0e - %en.%ext";
MultiEpisodeNamePattern = "%sn - %sx%0e-x%0ed - %en.%ext";
SeasonFolderPattern = "Season %s"; SeasonFolderPattern = "Season %s";
SeasonZeroFolderName = "Season 0"; SeasonZeroFolderName = "Season 0";
EnableTrialMode = true;
} }
} }
} }

@ -33,6 +33,24 @@ namespace MediaBrowser.Model.FileOrganization
/// </summary> /// </summary>
/// <value>The extracted year.</value> /// <value>The extracted year.</value>
public int? ExtractedYear { get; set; } public int? ExtractedYear { get; set; }
/// <summary>
/// Gets or sets the extracted season number.
/// </summary>
/// <value>The extracted season number.</value>
public int? ExtractedSeasonNumber { get; set; }
/// <summary>
/// Gets or sets the extracted episode number.
/// </summary>
/// <value>The extracted episode number.</value>
public int? ExtractedEpisodeNumber { get; set; }
/// <summary>
/// Gets or sets the extracted ending episode number.
/// </summary>
/// <value>The extracted ending episode number.</value>
public int? ExtractedEndingEpisodeNumber { get; set; }
/// <summary> /// <summary>
/// Gets or sets the target path. /// Gets or sets the target path.
@ -69,8 +87,7 @@ namespace MediaBrowser.Model.FileOrganization
{ {
Success, Success,
Failure, Failure,
SkippedExisting, SkippedExisting
SkippedTrial
} }
public enum FileOrganizerType public enum FileOrganizerType

@ -43,7 +43,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
throw new ArgumentNullException("result"); throw new ArgumentNullException("result");
} }
result.Id = (result.OriginalPath + (result.TargetPath ?? string.Empty)).GetMD5().ToString("N"); result.Id = result.OriginalPath.GetMD5().ToString("N");
return _repo.SaveResult(result, cancellationToken); return _repo.SaveResult(result, cancellationToken);
} }

@ -67,7 +67,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
{ {
var result = await SortFile(file.FullName, options, allSeries).ConfigureAwait(false); var result = await SortFile(file.FullName, options, allSeries).ConfigureAwait(false);
if (result.Status == FileSortingStatus.Success && !options.EnableTrialMode) if (result.Status == FileSortingStatus.Success)
{ {
scanLibrary = true; scanLibrary = true;
} }
@ -83,19 +83,16 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
progress.Report(99); progress.Report(99);
if (!options.EnableTrialMode) foreach (var path in watchLocations)
{ {
foreach (var path in watchLocations) if (options.LeftOverFileExtensionsToDelete.Length > 0)
{ {
if (options.LeftOverFileExtensionsToDelete.Length > 0) DeleteLeftOverFiles(path, options.LeftOverFileExtensionsToDelete);
{ }
DeleteLeftOverFiles(path, options.LeftOverFileExtensionsToDelete);
}
if (options.DeleteEmptyFolders) if (options.DeleteEmptyFolders)
{ {
DeleteEmptyFolders(path); DeleteEmptyFolders(path);
}
} }
} }
@ -153,16 +150,24 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
{ {
var season = TVUtils.GetSeasonNumberFromEpisodeFile(path); var season = TVUtils.GetSeasonNumberFromEpisodeFile(path);
result.ExtractedSeasonNumber = season;
if (season.HasValue) if (season.HasValue)
{ {
// Passing in true will include a few extra regex's // Passing in true will include a few extra regex's
var episode = TVUtils.GetEpisodeNumberFromFile(path, true); var episode = TVUtils.GetEpisodeNumberFromFile(path, true);
result.ExtractedEpisodeNumber = episode;
if (episode.HasValue) if (episode.HasValue)
{ {
_logger.Debug("Extracted information from {0}. Series name {1}, Season {2}, Episode {3}", path, seriesName, season, episode); _logger.Debug("Extracted information from {0}. Series name {1}, Season {2}, Episode {3}", path, seriesName, season, episode);
SortFile(path, seriesName, season.Value, episode.Value, options, allSeries, result); var endingEpisodeNumber = TVUtils.GetEndingEpisodeNumberFromFile(path);
result.ExtractedEndingEpisodeNumber = endingEpisodeNumber;
SortFile(path, seriesName, season.Value, episode.Value, endingEpisodeNumber, options, allSeries, result);
} }
else else
{ {
@ -200,10 +205,11 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
/// <param name="seriesName">Name of the series.</param> /// <param name="seriesName">Name of the series.</param>
/// <param name="seasonNumber">The season number.</param> /// <param name="seasonNumber">The season number.</param>
/// <param name="episodeNumber">The episode number.</param> /// <param name="episodeNumber">The episode number.</param>
/// <param name="endingEpiosdeNumber">The ending epiosde number.</param>
/// <param name="options">The options.</param> /// <param name="options">The options.</param>
/// <param name="allSeries">All series.</param> /// <param name="allSeries">All series.</param>
/// <param name="result">The result.</param> /// <param name="result">The result.</param>
private void SortFile(string path, string seriesName, int seasonNumber, int episodeNumber, TvFileOrganizationOptions options, IEnumerable<Series> allSeries, FileOrganizationResult result) private void SortFile(string path, string seriesName, int seasonNumber, int episodeNumber, int? endingEpiosdeNumber, TvFileOrganizationOptions options, IEnumerable<Series> allSeries, FileOrganizationResult result)
{ {
var series = GetMatchingSeries(seriesName, allSeries, result); var series = GetMatchingSeries(seriesName, allSeries, result);
@ -219,7 +225,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
_logger.Info("Sorting file {0} into series {1}", path, series.Path); _logger.Info("Sorting file {0} into series {1}", path, series.Path);
// Proceed to sort the file // Proceed to sort the file
var newPath = GetNewPath(path, series, seasonNumber, episodeNumber, options); var newPath = GetNewPath(path, series, seasonNumber, episodeNumber, endingEpiosdeNumber, options);
if (string.IsNullOrEmpty(newPath)) if (string.IsNullOrEmpty(newPath))
{ {
@ -233,12 +239,6 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
_logger.Info("Sorting file {0} to new path {1}", path, newPath); _logger.Info("Sorting file {0} to new path {1}", path, newPath);
result.TargetPath = newPath; result.TargetPath = newPath;
if (options.EnableTrialMode)
{
result.Status = FileSortingStatus.SkippedTrial;
return;
}
var targetExists = File.Exists(result.TargetPath); var targetExists = File.Exists(result.TargetPath);
if (!options.OverwriteExistingEpisodes && targetExists) if (!options.OverwriteExistingEpisodes && targetExists)
{ {
@ -315,12 +315,17 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
/// <param name="series">The series.</param> /// <param name="series">The series.</param>
/// <param name="seasonNumber">The season number.</param> /// <param name="seasonNumber">The season number.</param>
/// <param name="episodeNumber">The episode number.</param> /// <param name="episodeNumber">The episode number.</param>
/// <param name="endingEpisodeNumber">The ending episode number.</param>
/// <param name="options">The options.</param> /// <param name="options">The options.</param>
/// <returns>System.String.</returns> /// <returns>System.String.</returns>
private string GetNewPath(string sourcePath, Series series, int seasonNumber, int episodeNumber, TvFileOrganizationOptions options) private string GetNewPath(string sourcePath, Series series, int seasonNumber, int episodeNumber, int? endingEpisodeNumber, TvFileOrganizationOptions options)
{ {
// If season and episode numbers match
var currentEpisodes = series.RecursiveChildren.OfType<Episode>() var currentEpisodes = series.RecursiveChildren.OfType<Episode>()
.Where(i => i.IndexNumber.HasValue && i.IndexNumber.Value == episodeNumber && i.ParentIndexNumber.HasValue && i.ParentIndexNumber.Value == seasonNumber) .Where(i => i.IndexNumber.HasValue &&
i.IndexNumber.Value == episodeNumber &&
i.ParentIndexNumber.HasValue &&
i.ParentIndexNumber.Value == seasonNumber)
.ToList(); .ToList();
if (currentEpisodes.Count == 0) if (currentEpisodes.Count == 0)
@ -328,33 +333,27 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
return null; return null;
} }
var newPath = currentEpisodes var newPath = GetSeasonFolderPath(series, seasonNumber, options);
.Where(i => i.LocationType == LocationType.FileSystem)
.Select(i => i.Path)
.FirstOrDefault();
if (string.IsNullOrEmpty(newPath))
{
newPath = GetSeasonFolderPath(series, seasonNumber, options);
var episode = currentEpisodes.First(); var episode = currentEpisodes.First();
var episodeFileName = GetEpisodeFileName(sourcePath, series.Name, seasonNumber, episodeNumber, episode.Name, options); var episodeFileName = GetEpisodeFileName(sourcePath, series.Name, seasonNumber, episodeNumber, endingEpisodeNumber, episode.Name, options);
newPath = Path.Combine(newPath, episodeFileName); newPath = Path.Combine(newPath, episodeFileName);
}
return newPath; return newPath;
} }
private string GetEpisodeFileName(string sourcePath, string seriesName, int seasonNumber, int episodeNumber, string episodeTitle, TvFileOrganizationOptions options) private string GetEpisodeFileName(string sourcePath, string seriesName, int seasonNumber, int episodeNumber, int? endingEpisodeNumber, string episodeTitle, TvFileOrganizationOptions options)
{ {
seriesName = _fileSystem.GetValidFilename(seriesName); seriesName = _fileSystem.GetValidFilename(seriesName);
episodeTitle = _fileSystem.GetValidFilename(episodeTitle); episodeTitle = _fileSystem.GetValidFilename(episodeTitle);
var sourceExtension = (Path.GetExtension(sourcePath) ?? string.Empty).TrimStart('.'); var sourceExtension = (Path.GetExtension(sourcePath) ?? string.Empty).TrimStart('.');
return options.EpisodeNamePattern.Replace("%sn", seriesName) var pattern = endingEpisodeNumber.HasValue ? options.MultiEpisodeNamePattern : options.EpisodeNamePattern;
var result = pattern.Replace("%sn", seriesName)
.Replace("%s.n", seriesName.Replace(" ", ".")) .Replace("%s.n", seriesName.Replace(" ", "."))
.Replace("%s_n", seriesName.Replace(" ", "_")) .Replace("%s_n", seriesName.Replace(" ", "_"))
.Replace("%s", seasonNumber.ToString(UsCulture)) .Replace("%s", seasonNumber.ToString(UsCulture))
@ -363,8 +362,16 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
.Replace("%ext", sourceExtension) .Replace("%ext", sourceExtension)
.Replace("%en", episodeTitle) .Replace("%en", episodeTitle)
.Replace("%e.n", episodeTitle.Replace(" ", ".")) .Replace("%e.n", episodeTitle.Replace(" ", "."))
.Replace("%e_n", episodeTitle.Replace(" ", "_")) .Replace("%e_n", episodeTitle.Replace(" ", "_"));
.Replace("%e", episodeNumber.ToString(UsCulture))
if (endingEpisodeNumber.HasValue)
{
result = result.Replace("%ed", endingEpisodeNumber.Value.ToString(UsCulture))
.Replace("%0ed", endingEpisodeNumber.Value.ToString("00", UsCulture))
.Replace("%00ed", endingEpisodeNumber.Value.ToString("000", UsCulture));
}
return result.Replace("%e", episodeNumber.ToString(UsCulture))
.Replace("%0e", episodeNumber.ToString("00", UsCulture)) .Replace("%0e", episodeNumber.ToString("00", UsCulture))
.Replace("%00e", episodeNumber.ToString("000", UsCulture)); .Replace("%00e", episodeNumber.ToString("000", UsCulture));
} }

@ -47,7 +47,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
string[] queries = { string[] queries = {
"create table if not exists organizationresults (ResultId GUID PRIMARY KEY, OriginalPath TEXT, TargetPath TEXT, OrganizationDate datetime, Status TEXT, OrganizationType TEXT, StatusMessage TEXT, ExtractedName TEXT, ExtractedYear int null)", "create table if not exists organizationresults (ResultId GUID PRIMARY KEY, OriginalPath TEXT, TargetPath TEXT, OrganizationDate datetime, Status TEXT, OrganizationType TEXT, StatusMessage TEXT, ExtractedName TEXT, ExtractedYear int null, ExtractedSeasonNumber int null, ExtractedEpisodeNumber int null, ExtractedEndingEpisodeNumber int null)",
"create index if not exists idx_organizationresults on organizationresults(ResultId)", "create index if not exists idx_organizationresults on organizationresults(ResultId)",
//pragmas //pragmas
@ -66,7 +66,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
private void PrepareStatements() private void PrepareStatements()
{ {
_saveResultCommand = _connection.CreateCommand(); _saveResultCommand = _connection.CreateCommand();
_saveResultCommand.CommandText = "replace into organizationresults (ResultId, OriginalPath, TargetPath, OrganizationDate, Status, OrganizationType, StatusMessage, ExtractedName, ExtractedYear) values (@ResultId, @OriginalPath, @TargetPath, @OrganizationDate, @Status, @OrganizationType, @StatusMessage, @ExtractedName, @ExtractedYear)"; _saveResultCommand.CommandText = "replace into organizationresults (ResultId, OriginalPath, TargetPath, OrganizationDate, Status, OrganizationType, StatusMessage, ExtractedName, ExtractedYear, ExtractedSeasonNumber, ExtractedEpisodeNumber, ExtractedEndingEpisodeNumber) values (@ResultId, @OriginalPath, @TargetPath, @OrganizationDate, @Status, @OrganizationType, @StatusMessage, @ExtractedName, @ExtractedYear, @ExtractedSeasonNumber, @ExtractedEpisodeNumber, @ExtractedEndingEpisodeNumber)";
_saveResultCommand.Parameters.Add(_saveResultCommand, "@ResultId"); _saveResultCommand.Parameters.Add(_saveResultCommand, "@ResultId");
_saveResultCommand.Parameters.Add(_saveResultCommand, "@OriginalPath"); _saveResultCommand.Parameters.Add(_saveResultCommand, "@OriginalPath");
@ -77,6 +77,9 @@ namespace MediaBrowser.Server.Implementations.Persistence
_saveResultCommand.Parameters.Add(_saveResultCommand, "@StatusMessage"); _saveResultCommand.Parameters.Add(_saveResultCommand, "@StatusMessage");
_saveResultCommand.Parameters.Add(_saveResultCommand, "@ExtractedName"); _saveResultCommand.Parameters.Add(_saveResultCommand, "@ExtractedName");
_saveResultCommand.Parameters.Add(_saveResultCommand, "@ExtractedYear"); _saveResultCommand.Parameters.Add(_saveResultCommand, "@ExtractedYear");
_saveResultCommand.Parameters.Add(_saveResultCommand, "@ExtractedSeasonNumber");
_saveResultCommand.Parameters.Add(_saveResultCommand, "@ExtractedEpisodeNumber");
_saveResultCommand.Parameters.Add(_saveResultCommand, "@ExtractedEndingEpisodeNumber");
_deleteResultCommand = _connection.CreateCommand(); _deleteResultCommand = _connection.CreateCommand();
_deleteResultCommand.CommandText = "delete from organizationresults where ResultId = @ResultId"; _deleteResultCommand.CommandText = "delete from organizationresults where ResultId = @ResultId";
@ -110,6 +113,9 @@ namespace MediaBrowser.Server.Implementations.Persistence
_saveResultCommand.GetParameter(6).Value = result.StatusMessage; _saveResultCommand.GetParameter(6).Value = result.StatusMessage;
_saveResultCommand.GetParameter(7).Value = result.ExtractedName; _saveResultCommand.GetParameter(7).Value = result.ExtractedName;
_saveResultCommand.GetParameter(8).Value = result.ExtractedYear; _saveResultCommand.GetParameter(8).Value = result.ExtractedYear;
_saveResultCommand.GetParameter(9).Value = result.ExtractedSeasonNumber;
_saveResultCommand.GetParameter(10).Value = result.ExtractedEpisodeNumber;
_saveResultCommand.GetParameter(11).Value = result.ExtractedEndingEpisodeNumber;
_saveResultCommand.Transaction = transaction; _saveResultCommand.Transaction = transaction;
@ -211,7 +217,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
using (var cmd = _connection.CreateCommand()) using (var cmd = _connection.CreateCommand())
{ {
cmd.CommandText = "SELECT ResultId, OriginalPath, TargetPath, OrganizationDate, Status, OrganizationType, StatusMessage, ExtractedName, ExtractedYear from organizationresults"; cmd.CommandText = "SELECT ResultId, OriginalPath, TargetPath, OrganizationDate, Status, OrganizationType, StatusMessage, ExtractedName, ExtractedYear, ExtractedSeasonNumber, ExtractedEpisodeNumber, ExtractedEndingEpisodeNumber from organizationresults";
if (query.StartIndex.HasValue && query.StartIndex.Value > 0) if (query.StartIndex.HasValue && query.StartIndex.Value > 0)
{ {
@ -263,7 +269,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
using (var cmd = _connection.CreateCommand()) using (var cmd = _connection.CreateCommand())
{ {
cmd.CommandText = "select ResultId, OriginalPath, TargetPath, OrganizationDate, Status, OrganizationType, StatusMessage, ExtractedName, ExtractedYear from organizationresults where ResultId=@Id"; cmd.CommandText = "select ResultId, OriginalPath, TargetPath, OrganizationDate, Status, OrganizationType, StatusMessage, ExtractedName, ExtractedYear, ExtractedSeasonNumber, ExtractedEpisodeNumber, ExtractedEndingEpisodeNumber from organizationresults where ResultId=@Id";
cmd.Parameters.Add(cmd, "@Id", DbType.Guid).Value = guid; cmd.Parameters.Add(cmd, "@Id", DbType.Guid).Value = guid;
@ -317,6 +323,21 @@ namespace MediaBrowser.Server.Implementations.Persistence
result.ExtractedYear = reader.GetInt32(8); result.ExtractedYear = reader.GetInt32(8);
} }
if (!reader.IsDBNull(9))
{
result.ExtractedSeasonNumber = reader.GetInt32(9);
}
if (!reader.IsDBNull(10))
{
result.ExtractedEpisodeNumber = reader.GetInt32(10);
}
if (!reader.IsDBNull(11))
{
result.ExtractedEndingEpisodeNumber = reader.GetInt32(11);
}
return result; return result;
} }

Loading…
Cancel
Save