2011-06-16 19:48:24 -07:00
using System ;
2010-10-20 18:49:23 -07:00
using System.Collections.Generic ;
using System.IO ;
using System.Linq ;
2011-06-13 18:23:04 -07:00
using Ninject ;
2010-10-20 18:49:23 -07:00
using NLog ;
2011-06-06 23:29:07 -07:00
using NzbDrone.Core.Helpers ;
2011-04-03 20:50:12 -07:00
using NzbDrone.Core.Providers.Core ;
2010-10-20 18:49:23 -07:00
using NzbDrone.Core.Repository ;
2011-06-06 23:29:07 -07:00
using NzbDrone.Core.Repository.Quality ;
2011-06-16 20:29:39 -07:00
using PetaPoco ;
2011-11-20 16:35:29 -08:00
using NzbDrone.Common ;
2010-10-20 18:49:23 -07:00
namespace NzbDrone.Core.Providers
{
2011-04-09 18:34:36 -07:00
public class MediaFileProvider
2010-10-20 18:49:23 -07:00
{
private static readonly Logger Logger = LogManager . GetCurrentClassLogger ( ) ;
2011-06-06 23:29:07 -07:00
private readonly ConfigProvider _configProvider ;
2011-06-16 20:29:39 -07:00
private readonly IDatabase _database ;
2011-06-19 20:25:04 -07:00
private readonly EpisodeProvider _episodeProvider ;
2010-10-20 18:49:23 -07:00
2011-06-13 18:23:04 -07:00
[Inject]
2011-06-19 20:04:08 -07:00
public MediaFileProvider ( EpisodeProvider episodeProvider , ConfigProvider configProvider , IDatabase database )
2010-10-20 18:49:23 -07:00
{
_episodeProvider = episodeProvider ;
2011-06-06 23:29:07 -07:00
_configProvider = configProvider ;
2011-06-16 20:29:39 -07:00
_database = database ;
2010-10-20 18:49:23 -07:00
}
2011-06-19 20:25:04 -07:00
public MediaFileProvider ( )
{
}
2010-10-24 00:46:58 -07:00
2011-06-21 18:12:20 -07:00
public virtual int Add ( EpisodeFile episodeFile )
{
return Convert . ToInt32 ( _database . Insert ( episodeFile ) ) ;
}
2011-05-17 22:32:23 -07:00
public virtual void Update ( EpisodeFile episodeFile )
2011-02-17 22:49:23 -08:00
{
2011-06-16 20:29:39 -07:00
_database . Update ( episodeFile ) ;
2011-06-19 18:59:31 -07:00
}
2011-02-17 22:49:23 -08:00
2011-06-21 18:12:20 -07:00
public virtual void Delete ( int episodeFileId )
{
2011-06-22 00:26:36 -07:00
_database . Delete < EpisodeFile > ( episodeFileId ) ;
2011-06-21 18:12:20 -07:00
}
public virtual bool Exists ( string path )
{
2011-11-20 16:35:29 -08:00
return _database . Exists < EpisodeFile > ( "WHERE Path =@0" , path . NormalizePath ( ) ) ;
2011-06-21 18:12:20 -07:00
}
2012-04-17 14:44:20 -07:00
public virtual EpisodeFile GetFileByPath ( string path )
{
return _database . SingleOrDefault < EpisodeFile > ( "WHERE Path =@0" , path . NormalizePath ( ) ) ;
}
2011-05-17 22:32:23 -07:00
public virtual EpisodeFile GetEpisodeFile ( int episodeFileId )
2011-02-17 22:49:23 -08:00
{
2011-06-18 16:03:58 -07:00
return _database . Single < EpisodeFile > ( episodeFileId ) ;
2011-02-17 22:49:23 -08:00
}
2011-05-17 22:32:23 -07:00
public virtual List < EpisodeFile > GetEpisodeFiles ( )
2011-02-21 22:22:40 -08:00
{
2011-06-16 20:29:39 -07:00
return _database . Fetch < EpisodeFile > ( ) ;
2011-02-21 22:22:40 -08:00
}
2011-06-19 13:43:33 -07:00
public virtual IList < EpisodeFile > GetSeriesFiles ( int seriesId )
2011-02-23 16:40:11 -08:00
{
2011-08-21 17:48:37 -07:00
return _database . Fetch < EpisodeFile > ( "WHERE SeriesId= @0" , seriesId ) ;
}
public virtual IList < EpisodeFile > GetSeasonFiles ( int seriesId , int seasonNumber )
{
return _database . Fetch < EpisodeFile > ( "WHERE SeriesId= @0 AND SeasonNumber = @1" , seriesId , seasonNumber ) ;
2011-02-23 16:40:11 -08:00
}
2011-06-02 20:04:39 -07:00
public virtual Tuple < int , int > GetEpisodeFilesCount ( int seriesId )
{
2011-06-14 16:39:09 -07:00
var allEpisodes = _episodeProvider . GetEpisodeBySeries ( seriesId ) . ToList ( ) ;
2011-06-02 20:04:39 -07:00
2011-06-22 23:56:17 -07:00
var episodeTotal = allEpisodes . Where ( e = > ! e . Ignored & & e . AirDate ! = null & & e . AirDate < = DateTime . Today ) . ToList ( ) ;
2011-06-14 16:39:09 -07:00
var avilableEpisodes = episodeTotal . Where ( e = > e . EpisodeFileId > 0 ) . ToList ( ) ;
2011-06-02 20:04:39 -07:00
2011-06-14 16:39:09 -07:00
return new Tuple < int , int > ( avilableEpisodes . Count , episodeTotal . Count ) ;
2011-06-02 20:04:39 -07:00
}
2011-06-19 20:04:08 -07:00
public virtual FileInfo CalculateFilePath ( Series series , int seasonNumber , string fileName , string extention )
2011-06-06 23:29:07 -07:00
{
2011-06-19 20:25:04 -07:00
string path = series . Path ;
2011-06-19 20:04:08 -07:00
if ( series . SeasonFolder )
2011-06-06 23:29:07 -07:00
{
2011-07-07 20:36:02 -07:00
var seasonFolder = _configProvider . SortingSeasonFolderFormat
2011-06-21 20:40:24 -07:00
. Replace ( "%0s" , seasonNumber . ToString ( "00" ) )
. Replace ( "%s" , seasonNumber . ToString ( ) ) ;
path = Path . Combine ( path , seasonFolder ) ;
2011-06-06 23:29:07 -07:00
}
2011-06-07 14:19:11 -07:00
2011-06-19 20:04:08 -07:00
path = Path . Combine ( path , fileName + extention ) ;
2011-06-07 14:19:11 -07:00
2011-06-19 20:04:08 -07:00
return new FileInfo ( path ) ;
2011-06-06 23:29:07 -07:00
}
2012-01-16 20:05:36 -08:00
public virtual void CleanUpDatabase ( )
2011-06-20 18:49:16 -07:00
{
2012-01-16 20:05:36 -08:00
Logger . Trace ( "Verifying Episode > Episode file relationships." ) ;
string updateString = "UPDATE Episodes SET EpisodeFileId = 0, GrabDate = NULL, PostDownloadStatus = 0" ;
if ( _configProvider . AutoIgnorePreviouslyDownloadedEpisodes )
{
updateString + = ", Ignored = 1" ;
}
var updated = _database . Execute ( updateString +
@ "WHERE EpisodeFileId IN
( SELECT Episodes . EpisodeFileId FROM Episodes
LEFT OUTER JOIN EpisodeFiles
ON Episodes . EpisodeFileId = EpisodeFiles . EpisodeFileId
WHERE Episodes . EpisodeFileId > 0 AND EpisodeFiles . EpisodeFileId IS NULL ) ");
2011-06-20 23:34:45 -07:00
if ( updated > 0 )
{
2011-06-21 23:34:33 -07:00
Logger . Debug ( "Removed {0} invalid links to episode files." , updated ) ;
2011-06-20 23:34:45 -07:00
}
2011-07-06 00:36:49 -07:00
Logger . Trace ( "Deleting orphan files." ) ;
2011-06-20 23:34:45 -07:00
2012-01-16 20:05:36 -08:00
updated = _database . Execute ( @ "DELETE FROM EpisodeFiles
2011-06-20 18:49:16 -07:00
WHERE EpisodeFileId IN
( SELECT EpisodeFiles . EpisodeFileId FROM EpisodeFiles
LEFT OUTER JOIN Episodes
ON EpisodeFiles . EpisodeFileId = Episodes . EpisodeFileId
2012-01-16 20:05:36 -08:00
WHERE Episodes . EpisodeFileId IS NULL ) ");
2011-06-20 23:34:45 -07:00
if ( updated > 0 )
{
2012-04-17 14:44:20 -07:00
Logger . Debug ( "Removed {0} orphan file(s) from database." , updated ) ;
2011-06-20 23:34:45 -07:00
}
2011-06-20 18:49:16 -07:00
}
2012-08-03 00:01:34 -07:00
public virtual string GetNewFilename ( IList < Episode > episodes , string seriesTitle , QualityTypes quality , bool proper , EpisodeFile episodeFile )
2011-06-06 23:29:07 -07:00
{
2012-08-03 00:01:34 -07:00
if ( _configProvider . SortingUseSceneName )
{
Logger . Trace ( "Attempting to use scene name" ) ;
if ( String . IsNullOrWhiteSpace ( episodeFile . SceneName ) )
{
var name = Path . GetFileNameWithoutExtension ( episodeFile . Path ) ;
Logger . Trace ( "Unable to use scene name, because it is null, sticking with current name: {0}" , name ) ;
return name ;
}
return episodeFile . SceneName ;
}
2012-02-12 14:11:08 -08:00
var sortedEpisodes = episodes . OrderBy ( e = > e . EpisodeNumber ) ;
2011-07-07 20:36:02 -07:00
var separatorStyle = EpisodeSortingHelper . GetSeparatorStyle ( _configProvider . SortingSeparatorStyle ) ;
var numberStyle = EpisodeSortingHelper . GetNumberStyle ( _configProvider . SortingNumberStyle ) ;
2011-06-06 23:29:07 -07:00
2012-10-14 22:52:12 -07:00
var episodeNames = new List < String > ( ) ;
episodeNames . Add ( Parser . CleanupEpisodeTitle ( sortedEpisodes . First ( ) . Title ) ) ;
2011-06-06 23:29:07 -07:00
2011-06-19 20:25:04 -07:00
string result = String . Empty ;
2011-06-06 23:29:07 -07:00
2011-07-07 20:36:02 -07:00
if ( _configProvider . SortingIncludeSeriesName )
2011-06-06 23:29:07 -07:00
{
2011-06-19 19:33:43 -07:00
result + = seriesTitle + separatorStyle . Pattern ;
2011-06-06 23:29:07 -07:00
}
2012-02-12 14:11:08 -08:00
result + = numberStyle . Pattern . Replace ( "%0e" , String . Format ( "{0:00}" , sortedEpisodes . First ( ) . EpisodeNumber ) ) ;
2011-06-06 23:29:07 -07:00
2011-06-19 18:59:31 -07:00
if ( episodes . Count > 1 )
2011-06-06 23:29:07 -07:00
{
2011-07-07 20:36:02 -07:00
var multiEpisodeStyle = EpisodeSortingHelper . GetMultiEpisodeStyle ( _configProvider . SortingMultiEpisodeStyle ) ;
2011-06-06 23:29:07 -07:00
2012-02-12 14:11:08 -08:00
foreach ( var episode in sortedEpisodes . Skip ( 1 ) )
2011-06-06 23:29:07 -07:00
{
2011-06-19 18:59:31 -07:00
if ( multiEpisodeStyle . Name = = "Duplicate" )
{
result + = separatorStyle . Pattern + numberStyle . Pattern ;
}
else
{
result + = multiEpisodeStyle . Pattern ;
}
2011-06-06 23:29:07 -07:00
2011-06-19 18:59:31 -07:00
result = result . Replace ( "%0e" , String . Format ( "{0:00}" , episode . EpisodeNumber ) ) ;
2012-10-14 22:52:12 -07:00
episodeNames . Add ( Parser . CleanupEpisodeTitle ( episode . Title ) ) ;
2011-06-19 18:59:31 -07:00
}
2011-06-06 23:29:07 -07:00
}
2011-06-19 18:59:31 -07:00
result = result
. Replace ( "%s" , String . Format ( "{0}" , episodes . First ( ) . SeasonNumber ) )
. Replace ( "%0s" , String . Format ( "{0:00}" , episodes . First ( ) . SeasonNumber ) )
. Replace ( "%x" , numberStyle . EpisodeSeparator )
. Replace ( "%p" , separatorStyle . Pattern ) ;
2011-06-06 23:29:07 -07:00
2011-07-07 20:57:44 -07:00
if ( _configProvider . SortingIncludeEpisodeTitle )
2011-06-06 23:29:07 -07:00
{
2012-10-14 22:52:12 -07:00
if ( episodeNames . Distinct ( ) . Count ( ) = = 1 )
result + = separatorStyle . Pattern + episodeNames . First ( ) ;
else
result + = separatorStyle . Pattern + String . Join ( " + " , episodeNames ) ;
2011-06-06 23:29:07 -07:00
}
2011-07-07 20:36:02 -07:00
if ( _configProvider . SortingAppendQuality )
2012-01-22 11:25:59 -08:00
{
2011-06-19 18:59:31 -07:00
result + = String . Format ( " [{0}]" , quality ) ;
2011-06-06 23:29:07 -07:00
2012-01-22 11:25:59 -08:00
if ( proper )
result + = " [Proper]" ;
}
2011-07-07 20:36:02 -07:00
if ( _configProvider . SortingReplaceSpaces )
2011-06-19 18:59:31 -07:00
result = result . Replace ( ' ' , '.' ) ;
2011-06-06 23:29:07 -07:00
2011-07-06 00:36:49 -07:00
Logger . Trace ( "New File Name is: [{0}]" , result . Trim ( ) ) ;
2011-06-20 16:46:54 -07:00
return CleanFilename ( result . Trim ( ) ) ;
}
2012-09-03 16:26:52 -07:00
public virtual void ChangeQuality ( int episodeFileId , QualityTypes quality )
{
_database . Execute ( "UPDATE EpisodeFiles SET Quality = @quality WHERE EpisodeFileId = @episodeFileId" , new { episodeFileId , quality } ) ;
}
public virtual void ChangeQuality ( int seriesId , int seasonNumber , QualityTypes quality )
{
_database . Execute ( "UPDATE EpisodeFiles SET Quality = @quality WHERE SeriesId = @seriesId AND SeasonNumber = @seasonNumber" , new { seriesId , seasonNumber , quality } ) ;
}
2011-06-20 16:46:54 -07:00
public static string CleanFilename ( string name )
{
string result = name ;
string [ ] badCharacters = { "\\" , "/" , "<" , ">" , "?" , "*" , ":" , "|" , "\"" } ;
string [ ] goodCharacters = { "+" , "+" , "{" , "}" , "!" , "@" , "-" , "#" , "`" } ;
for ( int i = 0 ; i < badCharacters . Length ; i + + )
result = result . Replace ( badCharacters [ i ] , goodCharacters [ i ] ) ;
2011-06-19 18:59:31 -07:00
return result . Trim ( ) ;
2011-06-06 23:29:07 -07:00
}
2010-10-20 18:49:23 -07:00
}
2011-04-09 19:44:01 -07:00
}