2011-06-17 02:48:24 +00:00
using System ;
2010-10-21 01:49:23 +00:00
using System.Collections.Generic ;
using System.IO ;
using System.Linq ;
using NLog ;
2013-02-24 06:48:52 +00:00
using NzbDrone.Core.Configuration ;
2013-02-19 06:01:03 +00:00
using NzbDrone.Core.Tv ;
2011-06-07 06:29:07 +00:00
using NzbDrone.Core.Helpers ;
2011-04-04 03:50:12 +00:00
using NzbDrone.Core.Providers.Core ;
2010-10-21 01:49:23 +00:00
using NzbDrone.Core.Repository ;
2011-06-07 06:29:07 +00:00
using NzbDrone.Core.Repository.Quality ;
2011-06-17 03:29:39 +00:00
using PetaPoco ;
2011-11-21 00:35:29 +00:00
using NzbDrone.Common ;
2010-10-21 01:49:23 +00:00
namespace NzbDrone.Core.Providers
{
2011-04-10 01:34:36 +00:00
public class MediaFileProvider
2010-10-21 01:49:23 +00:00
{
private static readonly Logger Logger = LogManager . GetCurrentClassLogger ( ) ;
2013-02-24 06:48:52 +00:00
private readonly IConfigService _configService ;
2011-06-17 03:29:39 +00:00
private readonly IDatabase _database ;
2013-02-22 00:47:09 +00:00
private readonly IEpisodeService _episodeService ;
2010-10-21 01:49:23 +00:00
2013-02-24 06:48:52 +00:00
public MediaFileProvider ( IEpisodeService episodeService , IConfigService configService , IDatabase database )
2010-10-21 01:49:23 +00:00
{
2013-02-20 02:05:15 +00:00
_episodeService = episodeService ;
2013-02-24 06:48:52 +00:00
_configService = configService ;
2011-06-17 03:29:39 +00:00
_database = database ;
2010-10-21 01:49:23 +00:00
}
2011-06-20 03:25:04 +00:00
public MediaFileProvider ( )
{
}
2010-10-24 07:46:58 +00:00
2011-06-22 01:12:20 +00:00
public virtual int Add ( EpisodeFile episodeFile )
{
return Convert . ToInt32 ( _database . Insert ( episodeFile ) ) ;
}
2011-05-18 05:32:23 +00:00
public virtual void Update ( EpisodeFile episodeFile )
2011-02-18 06:49:23 +00:00
{
2011-06-17 03:29:39 +00:00
_database . Update ( episodeFile ) ;
2011-06-20 01:59:31 +00:00
}
2011-02-18 06:49:23 +00:00
2011-06-22 01:12:20 +00:00
public virtual void Delete ( int episodeFileId )
{
2011-06-22 07:26:36 +00:00
_database . Delete < EpisodeFile > ( episodeFileId ) ;
2011-06-22 01:12:20 +00:00
}
public virtual bool Exists ( string path )
{
2011-11-21 00:35:29 +00:00
return _database . Exists < EpisodeFile > ( "WHERE Path =@0" , path . NormalizePath ( ) ) ;
2011-06-22 01:12:20 +00:00
}
2012-04-17 21:44:20 +00:00
public virtual EpisodeFile GetFileByPath ( string path )
{
return _database . SingleOrDefault < EpisodeFile > ( "WHERE Path =@0" , path . NormalizePath ( ) ) ;
}
2011-05-18 05:32:23 +00:00
public virtual EpisodeFile GetEpisodeFile ( int episodeFileId )
2011-02-18 06:49:23 +00:00
{
2011-06-18 23:03:58 +00:00
return _database . Single < EpisodeFile > ( episodeFileId ) ;
2011-02-18 06:49:23 +00:00
}
2011-05-18 05:32:23 +00:00
public virtual List < EpisodeFile > GetEpisodeFiles ( )
2011-02-22 06:22:40 +00:00
{
2011-06-17 03:29:39 +00:00
return _database . Fetch < EpisodeFile > ( ) ;
2011-02-22 06:22:40 +00:00
}
2011-06-19 20:43:33 +00:00
public virtual IList < EpisodeFile > GetSeriesFiles ( int seriesId )
2011-02-24 00:40:11 +00:00
{
2011-08-22 00:48:37 +00: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-24 00:40:11 +00:00
}
2011-06-03 03:04:39 +00:00
public virtual Tuple < int , int > GetEpisodeFilesCount ( int seriesId )
{
2013-02-20 02:05:15 +00:00
var allEpisodes = _episodeService . GetEpisodeBySeries ( seriesId ) . ToList ( ) ;
2011-06-03 03:04:39 +00:00
2011-06-23 06:56:17 +00:00
var episodeTotal = allEpisodes . Where ( e = > ! e . Ignored & & e . AirDate ! = null & & e . AirDate < = DateTime . Today ) . ToList ( ) ;
2011-06-14 23:39:09 +00:00
var avilableEpisodes = episodeTotal . Where ( e = > e . EpisodeFileId > 0 ) . ToList ( ) ;
2011-06-03 03:04:39 +00:00
2011-06-14 23:39:09 +00:00
return new Tuple < int , int > ( avilableEpisodes . Count , episodeTotal . Count ) ;
2011-06-03 03:04:39 +00:00
}
2011-06-20 03:04:08 +00:00
public virtual FileInfo CalculateFilePath ( Series series , int seasonNumber , string fileName , string extention )
2011-06-07 06:29:07 +00:00
{
2011-06-20 03:25:04 +00:00
string path = series . Path ;
2011-06-20 03:04:08 +00:00
if ( series . SeasonFolder )
2011-06-07 06:29:07 +00:00
{
2013-02-24 06:48:52 +00:00
var seasonFolder = _configService . SortingSeasonFolderFormat
2011-06-22 03:40:24 +00:00
. Replace ( "%0s" , seasonNumber . ToString ( "00" ) )
. Replace ( "%s" , seasonNumber . ToString ( ) ) ;
path = Path . Combine ( path , seasonFolder ) ;
2011-06-07 06:29:07 +00:00
}
2011-06-07 21:19:11 +00:00
2011-06-20 03:04:08 +00:00
path = Path . Combine ( path , fileName + extention ) ;
2011-06-07 21:19:11 +00:00
2011-06-20 03:04:08 +00:00
return new FileInfo ( path ) ;
2011-06-07 06:29:07 +00:00
}
2012-01-17 04:05:36 +00:00
public virtual void CleanUpDatabase ( )
2011-06-21 01:49:16 +00:00
{
2012-01-17 04:05:36 +00:00
Logger . Trace ( "Verifying Episode > Episode file relationships." ) ;
string updateString = "UPDATE Episodes SET EpisodeFileId = 0, GrabDate = NULL, PostDownloadStatus = 0" ;
2013-02-24 06:48:52 +00:00
if ( _configService . AutoIgnorePreviouslyDownloadedEpisodes )
2012-01-17 04:05:36 +00:00
{
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-21 06:34:45 +00:00
if ( updated > 0 )
{
2011-06-22 06:34:33 +00:00
Logger . Debug ( "Removed {0} invalid links to episode files." , updated ) ;
2011-06-21 06:34:45 +00:00
}
2011-07-06 07:36:49 +00:00
Logger . Trace ( "Deleting orphan files." ) ;
2011-06-21 06:34:45 +00:00
2012-01-17 04:05:36 +00:00
updated = _database . Execute ( @ "DELETE FROM EpisodeFiles
2011-06-21 01:49:16 +00:00
WHERE EpisodeFileId IN
( SELECT EpisodeFiles . EpisodeFileId FROM EpisodeFiles
LEFT OUTER JOIN Episodes
ON EpisodeFiles . EpisodeFileId = Episodes . EpisodeFileId
2012-01-17 04:05:36 +00:00
WHERE Episodes . EpisodeFileId IS NULL ) ");
2011-06-21 06:34:45 +00:00
if ( updated > 0 )
{
2012-04-17 21:44:20 +00:00
Logger . Debug ( "Removed {0} orphan file(s) from database." , updated ) ;
2011-06-21 06:34:45 +00:00
}
2011-06-21 01:49:16 +00:00
}
2012-12-27 03:51:04 +00:00
public virtual string GetNewFilename ( IList < Episode > episodes , Series series , QualityTypes quality , bool proper , EpisodeFile episodeFile )
2011-06-07 06:29:07 +00:00
{
2013-02-24 06:48:52 +00:00
if ( _configService . SortingUseSceneName )
2012-08-03 07:01:34 +00:00
{
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 22:11:08 +00:00
var sortedEpisodes = episodes . OrderBy ( e = > e . EpisodeNumber ) ;
2013-02-24 06:48:52 +00:00
var separatorStyle = EpisodeSortingHelper . GetSeparatorStyle ( _configService . SortingSeparatorStyle ) ;
var numberStyle = EpisodeSortingHelper . GetNumberStyle ( _configService . SortingNumberStyle ) ;
2011-06-07 06:29:07 +00:00
2012-10-15 05:52:12 +00:00
var episodeNames = new List < String > ( ) ;
episodeNames . Add ( Parser . CleanupEpisodeTitle ( sortedEpisodes . First ( ) . Title ) ) ;
2011-06-07 06:29:07 +00:00
2011-06-20 03:25:04 +00:00
string result = String . Empty ;
2011-06-07 06:29:07 +00:00
2013-02-24 06:48:52 +00:00
if ( _configService . SortingIncludeSeriesName )
2011-06-07 06:29:07 +00:00
{
2012-12-27 03:51:04 +00:00
result + = series . Title + separatorStyle . Pattern ;
2011-06-07 06:29:07 +00:00
}
2013-02-20 02:05:15 +00:00
if ( series . SeriesType = = SeriesType . Standard )
2011-06-07 06:29:07 +00:00
{
2012-12-27 04:12:23 +00:00
result + = numberStyle . Pattern . Replace ( "%0e" ,
String . Format ( "{0:00}" , sortedEpisodes . First ( ) . EpisodeNumber ) ) ;
2011-06-07 06:29:07 +00:00
2012-12-27 04:12:23 +00:00
if ( episodes . Count > 1 )
2011-06-07 06:29:07 +00:00
{
2012-12-27 04:12:23 +00:00
var multiEpisodeStyle =
2013-02-24 06:48:52 +00:00
EpisodeSortingHelper . GetMultiEpisodeStyle ( _configService . SortingMultiEpisodeStyle ) ;
2012-12-27 04:12:23 +00:00
foreach ( var episode in sortedEpisodes . Skip ( 1 ) )
2011-06-20 01:59:31 +00:00
{
2012-12-27 04:12:23 +00:00
if ( multiEpisodeStyle . Name = = "Duplicate" )
{
result + = separatorStyle . Pattern + numberStyle . Pattern ;
}
else
{
result + = multiEpisodeStyle . Pattern ;
}
result = result . Replace ( "%0e" , String . Format ( "{0:00}" , episode . EpisodeNumber ) ) ;
episodeNames . Add ( Parser . CleanupEpisodeTitle ( episode . Title ) ) ;
2011-06-20 01:59:31 +00:00
}
}
2012-12-27 04:12:23 +00: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-07 06:29:07 +00:00
}
2012-12-27 04:12:23 +00:00
else
{
if ( episodes . First ( ) . AirDate . HasValue )
result + = episodes . First ( ) . AirDate . Value . ToString ( "yyyy-MM-dd" ) ;
else
result + = "Unknown" ;
}
2011-06-07 06:29:07 +00:00
2013-02-24 06:48:52 +00:00
if ( _configService . SortingIncludeEpisodeTitle )
2011-06-07 06:29:07 +00:00
{
2012-10-15 05:52:12 +00:00
if ( episodeNames . Distinct ( ) . Count ( ) = = 1 )
result + = separatorStyle . Pattern + episodeNames . First ( ) ;
else
2012-10-18 00:06:14 +00:00
result + = separatorStyle . Pattern + String . Join ( " + " , episodeNames . Distinct ( ) ) ;
2011-06-07 06:29:07 +00:00
}
2013-02-24 06:48:52 +00:00
if ( _configService . SortingAppendQuality )
2012-01-22 19:25:59 +00:00
{
2011-06-20 01:59:31 +00:00
result + = String . Format ( " [{0}]" , quality ) ;
2011-06-07 06:29:07 +00:00
2012-01-22 19:25:59 +00:00
if ( proper )
result + = " [Proper]" ;
}
2013-02-24 06:48:52 +00:00
if ( _configService . SortingReplaceSpaces )
2011-06-20 01:59:31 +00:00
result = result . Replace ( ' ' , '.' ) ;
2011-06-07 06:29:07 +00:00
2011-07-06 07:36:49 +00:00
Logger . Trace ( "New File Name is: [{0}]" , result . Trim ( ) ) ;
2011-06-20 23:46:54 +00:00
return CleanFilename ( result . Trim ( ) ) ;
}
2012-09-03 23:26:52 +00: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 23:46:54 +00: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-20 01:59:31 +00:00
return result . Trim ( ) ;
2011-06-07 06:29:07 +00:00
}
2010-10-21 01:49:23 +00:00
}
2011-04-10 02:44:01 +00:00
}