2010-10-21 01:49:23 +00:00
using System ;
using System.Collections.Generic ;
using System.IO ;
using System.Linq ;
using System.Text ;
using System.Text.RegularExpressions ;
using NLog ;
2010-10-24 07:46:58 +00:00
using NzbDrone.Core.Model ;
2010-10-21 01:49:23 +00:00
using NzbDrone.Core.Repository ;
2010-10-24 07:46:58 +00:00
using SubSonic.Repository ;
2010-10-21 01:49:23 +00:00
namespace NzbDrone.Core.Providers
{
public class MediaFileProvider : IMediaFileProvider
{
2010-10-24 07:46:58 +00:00
private readonly IRepository _repository ;
2010-10-30 02:46:32 +00:00
private readonly IConfigProvider _configProvider ;
2010-10-21 01:49:23 +00:00
private readonly IDiskProvider _diskProvider ;
private readonly IEpisodeProvider _episodeProvider ;
private static readonly Logger Logger = LogManager . GetCurrentClassLogger ( ) ;
private static readonly string [ ] MediaExtentions = new [ ] { "*.mkv" , "*.avi" , "*.wmv" } ;
2011-03-03 08:50:33 +00:00
public MediaFileProvider ( IRepository repository , IConfigProvider configProvider , IDiskProvider diskProvider , IEpisodeProvider episodeProvider )
2010-10-21 01:49:23 +00:00
{
2010-10-24 07:46:58 +00:00
_repository = repository ;
2011-03-03 08:50:33 +00:00
_configProvider = configProvider ;
2010-10-21 01:49:23 +00:00
_diskProvider = diskProvider ;
_episodeProvider = episodeProvider ;
}
/// <summary>
/// Scans the specified series folder for media files
/// </summary>
/// <param name="series">The series to be scanned</param>
2011-03-03 08:50:33 +00:00
public List < EpisodeFile > Scan ( Series series )
2010-10-21 01:49:23 +00:00
{
2010-10-24 07:46:58 +00:00
var mediaFileList = GetMediaFileList ( series . Path ) ;
2011-03-03 08:50:33 +00:00
var fileList = new List < EpisodeFile > ( ) ;
2010-10-24 07:46:58 +00:00
foreach ( var filePath in mediaFileList )
{
2011-03-03 08:50:33 +00:00
var file = ImportFile ( series , filePath ) ;
if ( file ! = null )
fileList . Add ( file ) ;
2010-10-24 07:46:58 +00:00
}
2011-03-03 08:50:33 +00:00
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 ;
2010-10-24 07:46:58 +00:00
}
public EpisodeFile ImportFile ( Series series , string filePath )
{
Logger . Trace ( "Importing file to database [{0}]" , filePath ) ;
if ( ! _repository . Exists < EpisodeFile > ( e = > e . Path = = Parser . NormalizePath ( filePath ) ) )
{
var episodesInFile = Parser . ParseEpisodeInfo ( filePath ) ;
2011-02-23 00:26:03 +00:00
//Stores the list of episodes to add to the EpisodeFile
2011-02-22 08:13:16 +00:00
var episodes = new List < Episode > ( ) ;
2011-02-23 00:26:03 +00:00
2010-10-24 07:46:58 +00:00
foreach ( var parsedEpisode in episodesInFile )
{
EpisodeParseResult closureEpisode = parsedEpisode ;
2011-02-22 08:13:16 +00:00
var episode = _episodeProvider . GetEpisode ( series . SeriesId , closureEpisode . SeasonNumber ,
closureEpisode . EpisodeNumber ) ;
2010-10-24 07:46:58 +00:00
if ( episode ! = null )
{
2011-02-23 00:26:03 +00:00
episodes . Add ( episode ) ;
2010-10-24 07:46:58 +00:00
}
2011-02-23 00:26:03 +00:00
else
Logger . Warn ( "Unable to find Series:{0} Season:{1} Episode:{2} in the database. File:{3}" , series . Title , closureEpisode . SeasonNumber , closureEpisode . EpisodeNumber , filePath ) ;
2010-10-24 07:46:58 +00:00
}
2011-02-23 00:26:03 +00:00
//Return null if no Episodes exist in the DB for the parsed episodes from file
if ( episodes . Count < 1 )
return null ;
2011-03-03 08:50:33 +00:00
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 ;
}
2011-02-23 00:26:03 +00:00
var episodeFile = new EpisodeFile ( ) ;
episodeFile . DateAdded = DateTime . Now ;
episodeFile . SeriesId = series . SeriesId ;
episodeFile . Path = Parser . NormalizePath ( filePath ) ;
2011-03-03 08:50:33 +00:00
episodeFile . Size = size ;
2011-02-23 00:26:03 +00:00
episodeFile . Quality = Parser . ParseQuality ( filePath ) ;
episodeFile . Proper = Parser . ParseProper ( filePath ) ;
2011-02-23 06:23:59 +00:00
var fileId = ( int ) _repository . Add ( episodeFile ) ;
2011-02-23 00:26:03 +00:00
2011-02-23 06:23:59 +00:00
//This is for logging + updating the episodes that are linked to this EpisodeFile
2011-02-23 00:26:03 +00:00
string episodeList = String . Empty ;
foreach ( var ep in episodes )
{
2011-02-24 00:40:11 +00:00
ep . EpisodeFileId = fileId ;
2011-02-23 06:23:59 +00:00
_episodeProvider . UpdateEpisode ( ep ) ;
2011-02-23 00:26:03 +00:00
episodeList + = String . Format ( ", {0}" , ep . EpisodeId ) . Trim ( ' ' , ',' ) ;
}
2011-02-24 00:40:11 +00:00
Logger . Trace ( "File {0}:{1} attached to episode(s): '{2}'" , episodeFile . EpisodeFileId , filePath , episodeList ) ;
2011-02-23 00:26:03 +00:00
return episodeFile ;
2010-10-21 01:49:23 +00:00
}
2011-02-23 00:26:03 +00:00
Logger . Trace ( "[{0}] already exists in the database. skipping." , filePath ) ;
2010-10-24 07:46:58 +00:00
return null ;
}
2010-10-21 01:49:23 +00:00
2010-10-24 07:46:58 +00:00
/// <summary>
/// Removes files that no longer exist from the database
/// </summary>
/// <param name="files">list of files to verify</param>
public void CleanUp ( List < EpisodeFile > files )
{
foreach ( var episodeFile in files )
2010-10-21 01:49:23 +00:00
{
2010-10-24 07:46:58 +00:00
if ( ! _diskProvider . FileExists ( episodeFile . Path ) )
{
Logger . Trace ( "File {0} no longer exists on disk. removing from database." , episodeFile . Path ) ;
2011-02-25 03:52:06 +00:00
_repository . Delete < EpisodeFile > ( episodeFile . EpisodeFileId ) ;
2010-10-24 07:46:58 +00:00
}
2010-10-21 01:49:23 +00:00
}
}
2010-10-24 07:46:58 +00:00
2010-10-30 02:46:32 +00:00
public string GenerateEpisodePath ( EpisodeModel episode )
{
var episodeNamePattern = _configProvider . EpisodeNameFormat ;
episodeNamePattern = episodeNamePattern . Replace ( "{series}" , "{0}" ) ;
episodeNamePattern = episodeNamePattern . Replace ( "{episode" , "{1" ) ;
episodeNamePattern = episodeNamePattern . Replace ( "{season" , "{2" ) ;
episodeNamePattern = episodeNamePattern . Replace ( "{title}" , "{3}" ) ;
episodeNamePattern = episodeNamePattern . Replace ( "{quality}" , "{4}" ) ;
return String . Format ( episodeNamePattern , episode . SeriesTitle , episode . EpisodeNumber , episode . SeasonNumber , episode . EpisodeTitle , episode . Quality ) ;
}
2011-02-18 06:49:23 +00:00
public void DeleteFromDb ( int fileId )
{
_repository . Delete < EpisodeFile > ( fileId ) ;
}
public void DeleteFromDisk ( int fileId , string path )
{
_diskProvider . DeleteFile ( path ) ;
_repository . Delete < EpisodeFile > ( fileId ) ;
}
2011-02-22 06:22:40 +00:00
public void Update ( EpisodeFile episodeFile )
{
_repository . Update ( episodeFile ) ;
}
public EpisodeFile GetEpisodeFile ( int episodeFileId )
{
return _repository . Single < EpisodeFile > ( episodeFileId ) ;
}
2011-02-24 00:40:11 +00:00
public List < EpisodeFile > GetEpisodeFiles ( )
{
return _repository . All < EpisodeFile > ( ) . ToList ( ) ;
}
2010-10-24 07:46:58 +00:00
private List < string > GetMediaFileList ( string path )
{
2010-10-30 02:46:32 +00:00
Logger . Debug ( "Scanning '{0}' for episodes" , path ) ;
2010-10-24 07:46:58 +00:00
var mediaFileList = new List < string > ( ) ;
foreach ( var ext in MediaExtentions )
{
mediaFileList . AddRange ( _diskProvider . GetFiles ( path , ext , SearchOption . AllDirectories ) ) ;
}
2010-10-30 02:46:32 +00:00
Logger . Trace ( "{0} media files were found in {1}" , mediaFileList . Count , path ) ;
2010-10-24 07:46:58 +00:00
return mediaFileList ;
}
2010-10-21 01:49:23 +00:00
}
}