2010-09-28 21:32:19 +02:00
using System ;
2010-10-17 19:22:48 +02:00
using System.Linq ;
2010-09-28 21:32:19 +02:00
using System.Collections.Generic ;
2010-09-28 07:01:54 +02:00
using System.Text.RegularExpressions ;
2010-10-05 08:21:18 +02:00
using NLog ;
2010-10-21 03:49:23 +02:00
using NzbDrone.Core.Model ;
using NzbDrone.Core.Repository ;
2010-09-28 21:32:19 +02:00
using SubSonic.Repository ;
2010-09-28 07:01:54 +02:00
namespace NzbDrone.Core.Providers
{
2010-09-28 22:44:33 +02:00
public class EpisodeProvider : IEpisodeProvider
2010-09-28 07:01:54 +02:00
{
2010-09-28 21:32:19 +02:00
//TODO: Remove parsing of the series name, it should be done in series provider
private readonly IRepository _sonicRepo ;
2010-10-05 08:21:18 +02:00
private readonly ISeriesProvider _series ;
private readonly ISeasonProvider _seasons ;
private readonly ITvDbProvider _tvDb ;
2011-01-29 07:10:22 +01:00
private readonly IHistoryProvider _history ;
2010-10-08 00:17:24 +02:00
private static readonly Logger Logger = LogManager . GetCurrentClassLogger ( ) ;
2010-09-28 21:32:19 +02:00
2010-10-05 08:21:18 +02:00
2011-01-29 07:10:22 +01:00
public EpisodeProvider ( IRepository sonicRepo , ISeriesProvider seriesProvider , ISeasonProvider seasonProvider , ITvDbProvider tvDbProvider , IHistoryProvider history )
2010-09-28 07:01:54 +02:00
{
2010-09-28 21:32:19 +02:00
_sonicRepo = sonicRepo ;
2010-10-05 08:21:18 +02:00
_series = seriesProvider ;
_tvDb = tvDbProvider ;
_seasons = seasonProvider ;
2011-01-29 07:10:22 +01:00
_history = history ;
2010-09-28 21:32:19 +02:00
}
2010-10-21 03:49:23 +02:00
public Episode GetEpisode ( long id )
2010-09-28 21:32:19 +02:00
{
2010-10-24 09:46:58 +02:00
return _sonicRepo . Single < Episode > ( id ) ;
}
public Episode GetEpisode ( int seriesId , int seasonNumber , int episodeNumber )
{
return _sonicRepo . Single < Episode > ( c = > c . SeriesId = = seriesId & & c . SeasonNumber = = seasonNumber & & c . EpisodeNumber = = episodeNumber ) ;
2010-09-28 21:32:19 +02:00
}
2010-10-21 03:49:23 +02:00
public IList < Episode > GetEpisodeBySeries ( long seriesId )
2010-09-28 21:32:19 +02:00
{
2010-10-21 03:49:23 +02:00
return _sonicRepo . Find < Episode > ( e = > e . SeriesId = = seriesId ) ;
2010-09-28 21:32:19 +02:00
}
2010-10-30 04:46:32 +02:00
public IList < Episode > GetEpisodeBySeason ( long seasonId )
{
return _sonicRepo . Find < Episode > ( e = > e . SeasonId = = seasonId ) ;
}
2010-10-21 03:49:23 +02:00
public String GetSabTitle ( Episode episode )
2010-09-28 21:32:19 +02:00
{
2010-10-05 08:21:18 +02:00
var series = _series . GetSeries ( episode . SeriesId ) ;
2010-09-28 21:32:19 +02:00
if ( series = = null ) throw new ArgumentException ( "Unknown series. ID: " + episode . SeriesId ) ;
//TODO: This method should return a standard title for the sab episode.
throw new NotImplementedException ( ) ;
2010-09-28 07:01:54 +02:00
}
2010-09-28 21:32:19 +02:00
/// <summary>
/// Comprehensive check on whether or not this episode is needed.
/// </summary>
/// <param name="episode">Episode that needs to be checked</param>
/// <returns></returns>
2010-10-21 03:49:23 +02:00
public bool IsNeeded ( EpisodeModel episode )
2010-09-28 07:01:54 +02:00
{
2011-01-29 07:10:22 +01:00
//IsSeasonIgnored
//IsQualityWanted
//EpisodeFileExists
//IsInHistory
//IsOnDisk? (How to handle episodes that are downloaded manually?)
if ( IsSeasonIgnored ( episode ) )
return false ;
if ( ! _series . QualityWanted ( episode . SeriesId , episode . Quality ) )
{
Logger . Debug ( "Quality [{0}] is not wanted for: {1}" , episode . Quality , episode . SeriesTitle ) ;
return false ;
}
//Check to see if there is an episode file for this episode
var dbEpisode = GetEpisode ( episode . SeriesId , episode . SeasonNumber , episode . EpisodeNumber ) ;
episode . EpisodeId = dbEpisode . EpisodeId ;
var epWithFiles = _sonicRepo . Single < Episode > ( c = > c . EpisodeId = = episode . EpisodeId & & c . Files . Count > 0 ) ;
if ( epWithFiles ! = null )
{
//If not null we need to see if this episode has the quality as the download (or if it is better)
foreach ( var file in epWithFiles . Files )
{
if ( file . Quality = = episode . Quality )
return false ;
}
}
//IsInHistory? (NZBDrone)
if ( _history . Exists ( dbEpisode . EpisodeId , episode . Quality , episode . Proper ) )
{
Logger . Debug ( "Episode in history: {0}" , episode . ToString ( ) ) ;
return false ;
}
2010-09-28 21:32:19 +02:00
throw new NotImplementedException ( ) ;
}
2010-10-17 19:22:48 +02:00
public void RefreshEpisodeInfo ( int seriesId )
2010-10-05 08:21:18 +02:00
{
Logger . Info ( "Starting episode info refresh for series:{0}" , seriesId ) ;
int successCount = 0 ;
int failCount = 0 ;
var targetSeries = _tvDb . GetSeries ( seriesId , true ) ;
2010-10-17 19:22:48 +02:00
2010-10-21 03:49:23 +02:00
var updateList = new List < Episode > ( ) ;
var newList = new List < Episode > ( ) ;
2010-10-17 19:22:48 +02:00
2010-10-30 04:46:32 +02:00
Logger . Debug ( "Updating season info for series:{0}" , targetSeries . SeriesName ) ;
2010-10-17 19:22:48 +02:00
targetSeries . Episodes . Select ( e = > new { e . SeasonId , e . SeasonNumber } )
. Distinct ( ) . ToList ( )
. ForEach ( s = > _seasons . EnsureSeason ( seriesId , s . SeasonId , s . SeasonNumber ) ) ;
2010-10-05 08:21:18 +02:00
foreach ( var episode in targetSeries . Episodes )
{
try
{
2011-01-29 07:10:22 +01:00
//DateTime throws an error in SQLServer per message below:
//SqlDateTime overflow. Must be between 1/1/1753 12:00:00 AM and 12/31/9999 11:59:59 PM.
//So lets hack it so it works for SQLServer (as well as SQLite), perhaps we can find a better solution
//Todo: Fix this hack
if ( episode . FirstAired < new DateTime ( 1753 , 1 , 1 ) )
episode . FirstAired = new DateTime ( 1753 , 1 , 1 ) ;
2010-10-30 04:46:32 +02:00
Logger . Trace ( "Updating info for series:{0} - episode:{1}" , targetSeries . SeriesName , episode . EpisodeNumber ) ;
2010-10-21 03:49:23 +02:00
var newEpisode = new Episode ( )
2010-10-17 19:22:48 +02:00
{
AirDate = episode . FirstAired ,
EpisodeId = episode . Id ,
EpisodeNumber = episode . EpisodeNumber ,
Language = episode . Language . Abbriviation ,
Overview = episode . Overview ,
SeasonId = episode . SeasonId ,
SeasonNumber = episode . SeasonNumber ,
SeriesId = seriesId ,
Title = episode . EpisodeName
} ;
2010-10-21 03:49:23 +02:00
if ( _sonicRepo . Exists < Episode > ( e = > e . EpisodeId = = newEpisode . EpisodeId ) )
2010-10-05 08:21:18 +02:00
{
2010-10-17 19:22:48 +02:00
updateList . Add ( newEpisode ) ;
}
else
{
newList . Add ( newEpisode ) ;
}
2010-10-05 08:21:18 +02:00
2010-10-17 19:22:48 +02:00
successCount + + ;
2010-10-05 08:21:18 +02:00
}
catch ( Exception e )
{
2010-10-17 19:22:48 +02:00
Logger . FatalException ( String . Format ( "An error has occurred while updating episode info for series {0}" , seriesId ) , e ) ;
2010-10-05 08:21:18 +02:00
failCount + + ;
}
}
2010-10-17 19:22:48 +02:00
_sonicRepo . AddMany ( newList ) ;
_sonicRepo . UpdateMany ( updateList ) ;
2010-10-30 04:46:32 +02:00
Logger . Debug ( "Finished episode refresh for series:{0}. Successful:{1} - Failed:{2} " , targetSeries . SeriesName , successCount , failCount ) ;
2010-10-05 08:21:18 +02:00
}
2011-01-29 07:10:22 +01:00
2011-02-10 07:42:46 +01:00
public void RefreshEpisodeInfo ( Season season )
{
Logger . Info ( "Starting episode info refresh for season {0} of series:{1}" , season . SeasonNumber , season . SeriesId ) ;
int successCount = 0 ;
int failCount = 0 ;
var targetSeries = _tvDb . GetSeries ( season . SeriesId , true ) ;
var updateList = new List < Episode > ( ) ;
var newList = new List < Episode > ( ) ;
foreach ( var episode in targetSeries . Episodes . Where ( e = > e . SeasonId = = season . SeasonId ) )
{
try
{
//DateTime throws an error in SQLServer per message below:
//SqlDateTime overflow. Must be between 1/1/1753 12:00:00 AM and 12/31/9999 11:59:59 PM.
//So lets hack it so it works for SQLServer (as well as SQLite), perhaps we can find a better solution
//Todo: Fix this hack
if ( episode . FirstAired < new DateTime ( 1753 , 1 , 1 ) )
episode . FirstAired = new DateTime ( 1753 , 1 , 1 ) ;
Logger . Trace ( "Updating info for series:{0} - episode:{1}" , targetSeries . SeriesName , episode . EpisodeNumber ) ;
var newEpisode = new Episode ( )
{
AirDate = episode . FirstAired ,
EpisodeId = episode . Id ,
EpisodeNumber = episode . EpisodeNumber ,
Language = episode . Language . Abbriviation ,
Overview = episode . Overview ,
SeasonId = episode . SeasonId ,
SeasonNumber = episode . SeasonNumber ,
SeriesId = season . SeriesId ,
Title = episode . EpisodeName
} ;
if ( _sonicRepo . Exists < Episode > ( e = > e . EpisodeId = = newEpisode . EpisodeId ) )
{
updateList . Add ( newEpisode ) ;
}
else
{
newList . Add ( newEpisode ) ;
}
successCount + + ;
}
catch ( Exception e )
{
Logger . FatalException ( String . Format ( "An error has occurred while updating episode info for season {0} of series {1}" , season . SeasonNumber , season . SeriesId ) , e ) ;
failCount + + ;
}
}
_sonicRepo . AddMany ( newList ) ;
_sonicRepo . UpdateMany ( updateList ) ;
Logger . Debug ( "Finished episode refresh for series:{0}. Successful:{1} - Failed:{2} " , targetSeries . SeriesName , successCount , failCount ) ;
}
2011-01-29 07:10:22 +01:00
private bool IsSeasonIgnored ( EpisodeModel episode )
{
//Check if this Season is ignored
if ( _seasons . IsIgnored ( episode . SeriesId , episode . SeasonNumber ) )
{
Logger . Debug ( "Season {0} is ignored for: {1}" , episode . SeasonNumber , episode . SeriesTitle ) ;
return true ;
}
Logger . Debug ( "Season {0} is wanted for: {1}" , episode . SeasonNumber , episode . SeriesTitle ) ;
return false ;
}
2010-09-28 07:01:54 +02:00
}
}