Post Processing has been implemented, still need to finish app for SAB to NzbDrone.

This commit is contained in:
markus101 2011-03-03 00:50:33 -08:00
parent ce79ab2827
commit 1314d00c97
18 changed files with 345 additions and 50 deletions

View File

@ -0,0 +1,37 @@
using System;
using NzbDrone.Core.Model;
namespace NzbDrone.Core.Helpers
{
public static class EpisodeRenameHelper
{
public static string GetNewName(EpisodeRenameModel erm)
{
//Todo: Get the users preferred naming convention instead of hard-coding it
if (erm.EpisodeFile.Episodes.Count == 1)
{
return String.Format("{0} - S{1:00}E{2:00} - {3}", erm.SeriesName,
erm.EpisodeFile.Episodes[0].SeasonNumber, erm.EpisodeFile.Episodes[0].EpisodeNumber,
erm.EpisodeFile.Episodes[0].Title);
}
var epNumberString = String.Empty;
var epNameString = String.Empty;
foreach (var episode in erm.EpisodeFile.Episodes)
{
epNumberString = epNumberString + String.Format("E{0:00}", episode.EpisodeNumber);
epNameString = epNameString + String.Format("+ {0}", episode.Title).Trim(' ', '+');
}
return String.Format("{0} - S{1:00}E{2} - {3}", erm.SeriesName, erm.EpisodeFile.Episodes[0].SeasonNumber,
epNumberString, epNameString);
}
public static string GetSeasonFolder(int seasonNumber, string seasonFolderFormat)
{
return seasonFolderFormat.Replace("%s", seasonNumber.ToString()).Replace("%0s", seasonNumber.ToString("00"));
}
}
}

View File

@ -1,10 +1,8 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NzbDrone.Core.Model;
namespace NzbDrone.Core
namespace NzbDrone.Core.Helpers
{
public static class EpisodeSortingHelper
{

View File

@ -156,7 +156,8 @@
<Reference Include="UPnP, Version=1.0.3932.37442, Culture=neutral, processorArchitecture=MSIL" />
</ItemGroup>
<ItemGroup>
<Compile Include="EpisodeSortingHelper.cs" />
<Compile Include="Helpers\EpisodeRenameHelper.cs" />
<Compile Include="Helpers\EpisodeSortingHelper.cs" />
<Compile Include="Instrumentation\ILogProvider.cs" />
<Compile Include="Instrumentation\LogLevel.cs" />
<Compile Include="Instrumentation\LogProvider.cs" />

View File

@ -71,6 +71,38 @@ namespace NzbDrone.Core
return result;
}
/// <summary>
/// Parses a post title to find the series that relates to it
/// </summary>
/// <param name="title">Title of the report</param>
/// <returns>Normalized Series Name</returns>
internal static string ParseSeriesName(string title)
{
Logger.Trace("Parsing string '{0}'", title);
foreach (var regex in ReportTitleRegex)
{
var match = regex.Matches(title);
if (match.Count != 0)
{
var seriesName = NormalizeTitle(match[0].Groups["title"].Value);
var year = 0;
Int32.TryParse(match[0].Groups["year"].Value, out year);
if (year < 1900 || year > DateTime.Now.Year + 1)
{
year = 0;
}
Logger.Trace("Series Parsed. {0}", seriesName);
return seriesName;
}
}
return String.Empty;
}
/// <summary>
/// Parses proper status out of a report title
/// </summary>

View File

@ -29,7 +29,9 @@ namespace NzbDrone.Core.Providers
public long GetSize(string path)
{
return new FileInfo(path).Length;
var fi = new FileInfo(path);
return fi.Length;
//return new FileInfo(path).Length;
}
public String CreateDirectory(string path)

View File

@ -10,8 +10,8 @@ namespace NzbDrone.Core.Providers
/// Scans the specified series folder for media files
/// </summary>
/// <param name="series">The series to be scanned</param>
void Scan(Series series);
List<EpisodeFile> Scan(Series series);
List<EpisodeFile> Scan(Series series, string path);
EpisodeFile ImportFile(Series series, string filePath);
string GenerateEpisodePath(EpisodeModel episode);
void CleanUp(List<EpisodeFile> files);

View File

@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace NzbDrone.Core.Providers
{
public interface IPostProcessingProvider
{
void ProcessEpisode(string dir, string nzbName);
}
}

View File

@ -11,5 +11,6 @@ namespace NzbDrone.Core.Providers
void RenameSeries(int seriesId);
void RenameSeason(int seasonId);
void RenameEpisode(int episodeId);
void RenameEpisodeFile(int episodeFileId);
}
}

View File

@ -21,10 +21,10 @@ namespace NzbDrone.Core.Providers
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
private static readonly string[] MediaExtentions = new[] { "*.mkv", "*.avi", "*.wmv" };
public MediaFileProvider(IRepository repository, IConfigProvider _configProvider, IDiskProvider diskProvider, IEpisodeProvider episodeProvider)
public MediaFileProvider(IRepository repository, IConfigProvider configProvider, IDiskProvider diskProvider, IEpisodeProvider episodeProvider)
{
_repository = repository;
this._configProvider = _configProvider;
_configProvider = configProvider;
_diskProvider = diskProvider;
_episodeProvider = episodeProvider;
}
@ -33,14 +33,36 @@ namespace NzbDrone.Core.Providers
/// Scans the specified series folder for media files
/// </summary>
/// <param name="series">The series to be scanned</param>
public void Scan(Series series)
public List<EpisodeFile> Scan(Series series)
{
var mediaFileList = GetMediaFileList(series.Path);
var fileList = new List<EpisodeFile>();
foreach (var filePath in mediaFileList)
{
ImportFile(series, filePath);
var file = ImportFile(series, filePath);
if (file != null)
fileList.Add(file);
}
return fileList;
}
/// <summary>
/// Scans the specified series folder for media files
/// </summary>
/// <param name="series">The series to be scanned</param>
public List<EpisodeFile> Scan(Series series, string path)
{
var mediaFileList = GetMediaFileList(path);
var fileList = new List<EpisodeFile>();
foreach (var filePath in mediaFileList)
{
var file = ImportFile(series, filePath);
if (file != null)
fileList.Add(file);
}
return fileList;
}
public EpisodeFile ImportFile(Series series, string filePath)
@ -72,11 +94,20 @@ namespace NzbDrone.Core.Providers
if (episodes.Count < 1)
return null;
var size = _diskProvider.GetSize(filePath);
//If Size is less than 50MB and contains sample. Check for Size to ensure its not an episode with sample in the title
if (size < 50000000 && filePath.ToLower().Contains("sample"))
{
Logger.Trace("[{0}] appears to be a sample... skipping.", filePath);
return null;
}
var episodeFile = new EpisodeFile();
episodeFile.DateAdded = DateTime.Now;
episodeFile.SeriesId = series.SeriesId;
episodeFile.Path = Parser.NormalizePath(filePath);
episodeFile.Size = _diskProvider.GetSize(filePath);
episodeFile.Size = size;
episodeFile.Quality = Parser.ParseQuality(filePath);
episodeFile.Proper = Parser.ParseProper(filePath);
var fileId = (int)_repository.Add(episodeFile);
@ -167,6 +198,5 @@ namespace NzbDrone.Core.Providers
Logger.Trace("{0} media files were found in {1}", mediaFileList.Count, path);
return mediaFileList;
}
}
}

View File

@ -0,0 +1,49 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using NzbDrone.Core.Helpers;
namespace NzbDrone.Core.Providers
{
public class PostProcessingProvider : IPostProcessingProvider
{
private readonly ISeriesProvider _seriesProvider;
private readonly IConfigProvider _configProvider;
private readonly IMediaFileProvider _mediaFileProvider;
private readonly IRenameProvider _renameProvider;
public PostProcessingProvider(ISeriesProvider seriesProvider, IConfigProvider configProvider,
IMediaFileProvider mediaFileProvider, IRenameProvider renameProvider)
{
_seriesProvider = seriesProvider;
_configProvider = configProvider;
_mediaFileProvider = mediaFileProvider;
_renameProvider = renameProvider;
}
#region IPostProcessingProvider Members
public void ProcessEpisode(string dir, string nzbName)
{
var parsedSeries = Parser.ParseSeriesName(nzbName);
var series = _seriesProvider.FindSeries(parsedSeries);
if (series == null)
return;
//Import the files, and then rename the newly added ones.
var fileList = _mediaFileProvider.Scan(series, dir);
foreach (var file in fileList)
{
//Todo: Where should we handle XBMC notifying/library updating etc? RenameProvider seems like a likely place, since we want to update XBMC after renaming (might as well)
_renameProvider.RenameEpisodeFile(file.EpisodeFileId);
}
}
#endregion
}
}

View File

@ -5,6 +5,7 @@ using System.Linq;
using System.Text;
using System.Threading;
using NLog;
using NzbDrone.Core.Helpers;
using NzbDrone.Core.Model;
using NzbDrone.Core.Repository;
@ -48,7 +49,7 @@ namespace NzbDrone.Core.Providers
erm.Folder = series.Path;
if (series.SeasonFolder)
erm.Folder += Path.DirectorySeparatorChar + GetSeasonFolder(episodeFile.Episodes[0].SeasonNumber);
erm.Folder += Path.DirectorySeparatorChar + EpisodeRenameHelper.GetSeasonFolder(episodeFile.Episodes[0].SeasonNumber, _configProvider.GetValue("Sorting_SeasonFolderFormat", "Season %s", true));
erm.EpisodeFile = episodeFile;
_epsToRename.Add(erm);
@ -70,7 +71,7 @@ namespace NzbDrone.Core.Providers
erm.Folder = series.Path;
if (series.SeasonFolder)
erm.Folder += Path.DirectorySeparatorChar + GetSeasonFolder(episodeFile.Episodes[0].SeasonNumber);
erm.Folder += Path.DirectorySeparatorChar + EpisodeRenameHelper.GetSeasonFolder(episodeFile.Episodes[0].SeasonNumber, _configProvider.GetValue("Sorting_SeasonFolderFormat", "Season %s", true));
erm.EpisodeFile = episodeFile;
_epsToRename.Add(erm);
@ -92,7 +93,7 @@ namespace NzbDrone.Core.Providers
erm.Folder = series.Path;
if (series.SeasonFolder)
erm.Folder += Path.DirectorySeparatorChar + GetSeasonFolder(episodeFile.Episodes[0].SeasonNumber);
erm.Folder += Path.DirectorySeparatorChar + EpisodeRenameHelper.GetSeasonFolder(episodeFile.Episodes[0].SeasonNumber, _configProvider.GetValue("Sorting_SeasonFolderFormat", "Season %s", true));
erm.EpisodeFile = episodeFile;
_epsToRename.Add(erm);
@ -114,7 +115,26 @@ namespace NzbDrone.Core.Providers
erm.Folder = series.Path;
if (series.SeasonFolder)
erm.Folder += Path.DirectorySeparatorChar + GetSeasonFolder(episodeFile.Episodes[0].SeasonNumber);
erm.Folder += Path.DirectorySeparatorChar + EpisodeRenameHelper.GetSeasonFolder(episodeFile.Episodes[0].SeasonNumber, _configProvider.GetValue("Sorting_SeasonFolderFormat", "Season %s", true));
erm.EpisodeFile = episodeFile;
_epsToRename.Add(erm);
StartRename();
}
public void RenameEpisodeFile(int episodeFileId)
{
//This will properly rename multi-episode files if asked to rename either of the episode
var episodeFile = _mediaFileProvider.GetEpisodeFile(episodeFileId);
var series = _seriesProvider.GetSeries(episodeFile.Series.SeriesId);
var erm = new EpisodeRenameModel();
erm.SeriesName = series.Title;
erm.Folder = series.Path;
if (series.SeasonFolder)
erm.Folder += Path.DirectorySeparatorChar + EpisodeRenameHelper.GetSeasonFolder(episodeFile.Episodes[0].SeasonNumber, _configProvider.GetValue("Sorting_SeasonFolderFormat", "Season %s", true));
erm.EpisodeFile = episodeFile;
_epsToRename.Add(erm);
@ -159,7 +179,7 @@ namespace NzbDrone.Core.Providers
{
//Update EpisodeFile if successful
Logger.Debug("Renaming Episode: {0}", Path.GetFileName(erm.EpisodeFile.Path));
var newName = GetNewName(erm);
var newName = EpisodeRenameHelper.GetNewName(erm);
var ext = Path.GetExtension(erm.EpisodeFile.Path);
var newFilename = erm.Folder + Path.DirectorySeparatorChar + newName + ext;
@ -180,36 +200,5 @@ namespace NzbDrone.Core.Providers
Logger.Warn("Unable to Rename Episode: {0}", Path.GetFileName(erm.EpisodeFile.Path));
}
}
private string GetNewName(EpisodeRenameModel erm)
{
//Todo: Get the users preferred naming convention instead of hard-coding it
if (erm.EpisodeFile.Episodes.Count == 1)
{
return String.Format("{0} - S{1:00}E{2:00} - {3}", erm.SeriesName,
erm.EpisodeFile.Episodes[0].SeasonNumber, erm.EpisodeFile.Episodes[0].EpisodeNumber,
erm.EpisodeFile.Episodes[0].Title);
}
var epNumberString = String.Empty;
var epNameString = String.Empty;
foreach (var episode in erm.EpisodeFile.Episodes)
{
epNumberString = epNumberString + String.Format("E{0:00}", episode.EpisodeNumber);
epNameString = epNameString + String.Format("+ {0}", episode.Title).Trim(' ', '+');
}
return String.Format("{0} - S{1:00}E{2} - {3}", erm.SeriesName, erm.EpisodeFile.Episodes[0].SeasonNumber,
epNumberString, epNameString);
}
private string GetSeasonFolder(int seasonNumber)
{
return
_configProvider.GetValue("Sorting_SeasonFolderFormat", "Season %s", true).Replace("%s", seasonNumber.ToString()).
Replace("%0s", seasonNumber.ToString("00"));
}
}
}

View File

@ -0,0 +1,52 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{0C679573-736D-4F77-B934-FD8931AC1AA1}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>NzbDrone.PostProcessor</RootNamespace>
<AssemblyName>NzbDrone.PostProcessor</AssemblyName>
<TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<PlatformTarget>x86</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<PlatformTarget>x86</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace NzbDrone.PostProcessor
{
class Program
{
static void Main(string[] args)
{
}
}
}

View File

@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("NzbDrone.PostProcessor")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("TIO Networks Corp")]
[assembly: AssemblyProduct("NzbDrone.PostProcessor")]
[assembly: AssemblyCopyright("Copyright © TIO Networks Corp 2011")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("6521fcb0-15dc-4324-b08a-f18f87d78859")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Xml.Linq;
using NzbDrone.Core;
using NzbDrone.Core.Providers;
namespace NzbDrone.Web.Controllers
{
public class ApiController : Controller
{
private readonly IPostProcessingProvider _postProcessingProvider;
public ApiController(IPostProcessingProvider postProcessingProvider)
{
_postProcessingProvider = postProcessingProvider;
}
public ActionResult ProcessEpisode(string dir, string nzbName)
{
_postProcessingProvider.ProcessEpisode(dir, nzbName);
return Content("ok");
}
}
}

View File

@ -6,6 +6,7 @@ using System.Web;
using System.Web.Mvc;
using NLog;
using NzbDrone.Core;
using NzbDrone.Core.Helpers;
using NzbDrone.Core.Model;
using NzbDrone.Core.Providers;
using NzbDrone.Core.Repository.Quality;

View File

@ -73,6 +73,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Controllers\AccountController.cs" />
<Compile Include="Controllers\ApiController.cs" />
<Compile Include="Controllers\HomeController.cs" />
<Compile Include="Controllers\LogController.cs" />
<Compile Include="Controllers\NotificationController.cs" />

View File

@ -13,6 +13,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NzbDrone.Web.Tests", "NzbDr
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{57A04B72-8088-4F75-A582-1158CF8291F7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NzbDrone.PostProcessor", "NzbDrone.PostProcessor\NzbDrone.PostProcessor.csproj", "{0C679573-736D-4F77-B934-FD8931AC1AA1}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -92,6 +94,18 @@ Global
{99CDD5DC-698F-4624-B431-2D6381CE3A15}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{99CDD5DC-698F-4624-B431-2D6381CE3A15}.Release|x64.ActiveCfg = Release|Any CPU
{99CDD5DC-698F-4624-B431-2D6381CE3A15}.Release|x86.ActiveCfg = Release|Any CPU
{0C679573-736D-4F77-B934-FD8931AC1AA1}.Debug|Any CPU.ActiveCfg = Debug|x86
{0C679573-736D-4F77-B934-FD8931AC1AA1}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
{0C679573-736D-4F77-B934-FD8931AC1AA1}.Debug|Mixed Platforms.Build.0 = Debug|x86
{0C679573-736D-4F77-B934-FD8931AC1AA1}.Debug|x64.ActiveCfg = Debug|x86
{0C679573-736D-4F77-B934-FD8931AC1AA1}.Debug|x86.ActiveCfg = Debug|x86
{0C679573-736D-4F77-B934-FD8931AC1AA1}.Debug|x86.Build.0 = Debug|x86
{0C679573-736D-4F77-B934-FD8931AC1AA1}.Release|Any CPU.ActiveCfg = Release|x86
{0C679573-736D-4F77-B934-FD8931AC1AA1}.Release|Mixed Platforms.ActiveCfg = Release|x86
{0C679573-736D-4F77-B934-FD8931AC1AA1}.Release|Mixed Platforms.Build.0 = Release|x86
{0C679573-736D-4F77-B934-FD8931AC1AA1}.Release|x64.ActiveCfg = Release|x86
{0C679573-736D-4F77-B934-FD8931AC1AA1}.Release|x86.ActiveCfg = Release|x86
{0C679573-736D-4F77-B934-FD8931AC1AA1}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE