2018-05-03 06:34:05 +00:00
using System ;
2013-09-10 05:22:38 +00:00
using System.Collections.Generic ;
2013-08-20 15:35:39 +00:00
using System.IO ;
2013-06-02 19:29:00 +00:00
using System.Linq ;
using NLog ;
2014-12-02 06:26:25 +00:00
using NzbDrone.Common.Extensions ;
2014-07-23 23:43:54 +00:00
using NzbDrone.Common.Instrumentation.Extensions ;
2018-10-13 20:41:38 +00:00
using NzbDrone.Core.Configuration ;
2015-08-12 18:45:44 +00:00
using NzbDrone.Core.Exceptions ;
2014-03-22 05:32:57 +00:00
using NzbDrone.Core.MediaFiles ;
2022-08-12 00:27:49 +00:00
using NzbDrone.Core.MediaFiles.Events ;
2013-09-14 06:42:09 +00:00
using NzbDrone.Core.Messaging.Commands ;
using NzbDrone.Core.Messaging.Events ;
2013-06-02 19:29:00 +00:00
using NzbDrone.Core.MetadataSource ;
2013-06-03 05:39:42 +00:00
using NzbDrone.Core.Tv.Commands ;
2013-06-02 19:29:00 +00:00
using NzbDrone.Core.Tv.Events ;
namespace NzbDrone.Core.Tv
{
2015-01-16 00:30:09 +00:00
public class RefreshSeriesService : IExecute < RefreshSeriesCommand >
2013-06-02 19:29:00 +00:00
{
private readonly IProvideSeriesInfo _seriesInfo ;
private readonly ISeriesService _seriesService ;
2013-08-01 02:02:36 +00:00
private readonly IRefreshEpisodeService _refreshEpisodeService ;
2013-09-14 06:36:07 +00:00
private readonly IEventAggregator _eventAggregator ;
2014-03-22 05:32:57 +00:00
private readonly IDiskScanService _diskScanService ;
2014-03-21 04:15:01 +00:00
private readonly ICheckIfSeriesShouldBeRefreshed _checkIfSeriesShouldBeRefreshed ;
2018-10-13 20:41:38 +00:00
private readonly IConfigService _configService ;
2013-06-02 19:29:00 +00:00
private readonly Logger _logger ;
2014-03-21 04:15:01 +00:00
public RefreshSeriesService ( IProvideSeriesInfo seriesInfo ,
ISeriesService seriesService ,
IRefreshEpisodeService refreshEpisodeService ,
IEventAggregator eventAggregator ,
2014-03-22 05:32:57 +00:00
IDiskScanService diskScanService ,
2014-03-21 04:15:01 +00:00
ICheckIfSeriesShouldBeRefreshed checkIfSeriesShouldBeRefreshed ,
2018-10-13 20:41:38 +00:00
IConfigService configService ,
2014-03-21 04:15:01 +00:00
Logger logger )
2013-06-02 19:29:00 +00:00
{
_seriesInfo = seriesInfo ;
_seriesService = seriesService ;
2013-08-01 02:02:36 +00:00
_refreshEpisodeService = refreshEpisodeService ;
2013-09-14 06:36:07 +00:00
_eventAggregator = eventAggregator ;
2014-03-22 05:32:57 +00:00
_diskScanService = diskScanService ;
2014-03-21 04:15:01 +00:00
_checkIfSeriesShouldBeRefreshed = checkIfSeriesShouldBeRefreshed ;
2018-10-13 20:41:38 +00:00
_configService = configService ;
2013-06-02 19:29:00 +00:00
_logger = logger ;
}
2020-08-02 18:47:03 +00:00
private Series RefreshSeriesInfo ( int seriesId )
2013-06-02 19:29:00 +00:00
{
2020-08-02 18:47:03 +00:00
// Get the series before updating, that way any changes made to the series after the refresh started,
// but before this series was refreshed won't be lost.
var series = _seriesService . GetSeries ( seriesId ) ;
2017-02-11 06:46:39 +00:00
_logger . ProgressInfo ( "Updating {0}" , series . Title ) ;
2015-08-12 18:45:44 +00:00
2019-10-19 15:15:28 +00:00
Series seriesInfo ;
List < Episode > episodes ;
2013-06-02 19:29:00 +00:00
2019-10-19 15:15:28 +00:00
try
{
var tuple = _seriesInfo . GetSeriesInfo ( series . TvdbId ) ;
seriesInfo = tuple . Item1 ;
episodes = tuple . Item2 ;
}
catch ( SeriesNotFoundException )
{
if ( series . Status ! = SeriesStatusType . Deleted )
{
series . Status = SeriesStatusType . Deleted ;
2020-01-06 21:29:27 +00:00
_seriesService . UpdateSeries ( series , publishUpdatedEvent : false ) ;
2019-10-19 15:15:28 +00:00
_logger . Debug ( "Series marked as deleted on tvdb for {0}" , series . Title ) ;
_eventAggregator . PublishEvent ( new SeriesUpdatedEvent ( series ) ) ;
}
2021-08-03 04:43:28 +00:00
2019-10-19 15:15:28 +00:00
throw ;
}
2013-06-02 19:29:00 +00:00
2015-08-12 18:45:44 +00:00
if ( series . TvdbId ! = seriesInfo . TvdbId )
{
_logger . Warn ( "Series '{0}' (tvdbid {1}) was replaced with '{2}' (tvdbid {3}), because the original was a duplicate." , series . Title , series . TvdbId , seriesInfo . Title , seriesInfo . TvdbId ) ;
series . TvdbId = seriesInfo . TvdbId ;
}
2013-06-02 19:29:00 +00:00
series . Title = seriesInfo . Title ;
2020-08-31 18:00:27 +00:00
series . Year = seriesInfo . Year ;
2014-05-19 19:14:41 +00:00
series . TitleSlug = seriesInfo . TitleSlug ;
2014-07-10 20:16:41 +00:00
series . TvRageId = seriesInfo . TvRageId ;
2015-10-09 20:22:28 +00:00
series . TvMazeId = seriesInfo . TvMazeId ;
2014-08-07 15:24:23 +00:00
series . ImdbId = seriesInfo . ImdbId ;
2013-06-02 19:29:00 +00:00
series . AirTime = seriesInfo . AirTime ;
series . Overview = seriesInfo . Overview ;
2022-10-03 01:29:53 +00:00
series . OriginalLanguage = seriesInfo . OriginalLanguage ;
2013-06-02 19:29:00 +00:00
series . Status = seriesInfo . Status ;
2013-08-01 02:02:36 +00:00
series . CleanTitle = seriesInfo . CleanTitle ;
2014-06-21 00:36:28 +00:00
series . SortTitle = seriesInfo . SortTitle ;
2013-06-03 05:39:42 +00:00
series . LastInfoSync = DateTime . UtcNow ;
2013-06-02 19:29:00 +00:00
series . Runtime = seriesInfo . Runtime ;
series . Images = seriesInfo . Images ;
series . Network = seriesInfo . Network ;
series . FirstAired = seriesInfo . FirstAired ;
2014-01-22 05:22:09 +00:00
series . Ratings = seriesInfo . Ratings ;
series . Actors = seriesInfo . Actors ;
series . Genres = seriesInfo . Genres ;
series . Certification = seriesInfo . Certification ;
2013-07-19 01:52:31 +00:00
2013-08-20 15:35:39 +00:00
try
{
series . Path = new DirectoryInfo ( series . Path ) . FullName ;
series . Path = series . Path . GetActualCasing ( ) ;
}
catch ( Exception e )
{
2016-02-11 21:13:42 +00:00
_logger . Warn ( e , "Couldn't update series path for " + series . Path ) ;
2013-08-20 15:35:39 +00:00
}
2013-09-10 05:22:38 +00:00
series . Seasons = UpdateSeasons ( series , seriesInfo ) ;
2020-01-06 21:29:27 +00:00
_seriesService . UpdateSeries ( series , publishUpdatedEvent : false ) ;
2019-10-19 15:15:28 +00:00
_refreshEpisodeService . RefreshEpisodeInfo ( series , episodes ) ;
2013-06-02 19:29:00 +00:00
2013-09-11 06:33:47 +00:00
_logger . Debug ( "Finished series refresh for {0}" , series . Title ) ;
2013-09-14 06:36:07 +00:00
_eventAggregator . PublishEvent ( new SeriesUpdatedEvent ( series ) ) ;
2020-08-02 18:47:03 +00:00
return series ;
2013-06-02 19:29:00 +00:00
}
2013-09-04 05:01:28 +00:00
2013-09-10 05:22:38 +00:00
private List < Season > UpdateSeasons ( Series series , Series seriesInfo )
{
2016-04-30 18:02:40 +00:00
var seasons = seriesInfo . Seasons . DistinctBy ( s = > s . SeasonNumber ) . ToList ( ) ;
foreach ( var season in seasons )
2013-09-10 05:22:38 +00:00
{
2016-04-30 18:02:40 +00:00
var existingSeason = series . Seasons . FirstOrDefault ( s = > s . SeasonNumber = = season . SeasonNumber ) ;
2013-09-13 03:50:12 +00:00
//Todo: Should this should use the previous season's monitored state?
if ( existingSeason = = null )
{
2014-05-26 01:47:54 +00:00
if ( season . SeasonNumber = = 0 )
{
2020-02-01 21:03:11 +00:00
_logger . Debug ( "Ignoring season 0 for series [{0}] {1} by default" , series . TvdbId , series . Title ) ;
2014-05-26 01:47:54 +00:00
season . Monitored = false ;
continue ;
}
2020-02-01 21:03:11 +00:00
_logger . Debug ( "New season ({0}) for series: [{1}] {2}, setting monitored to {3}" , season . SeasonNumber , series . TvdbId , series . Title , series . Monitored . ToString ( ) . ToLowerInvariant ( ) ) ;
season . Monitored = series . Monitored ;
2013-09-13 03:50:12 +00:00
}
else
2013-09-10 05:22:38 +00:00
{
season . Monitored = existingSeason . Monitored ;
}
}
2016-04-30 18:02:40 +00:00
return seasons ;
2013-09-10 05:22:38 +00:00
}
2018-10-13 20:41:38 +00:00
private void RescanSeries ( Series series , bool isNew , CommandTrigger trigger )
2018-05-03 06:34:05 +00:00
{
2018-10-13 20:41:38 +00:00
var rescanAfterRefresh = _configService . RescanAfterRefresh ;
if ( isNew )
{
2019-11-27 01:40:36 +00:00
_logger . Trace ( "Forcing rescan of {0}. Reason: New series" , series ) ;
2018-10-13 20:41:38 +00:00
}
else if ( rescanAfterRefresh = = RescanAfterRefreshType . Never )
{
2019-11-27 01:40:36 +00:00
_logger . Trace ( "Skipping rescan of {0}. Reason: never rescan after refresh" , series ) ;
2022-08-12 00:27:49 +00:00
_eventAggregator . PublishEvent ( new SeriesScanSkippedEvent ( series , SeriesScanSkippedReason . NeverRescanAfterRefresh ) ) ;
return ;
2018-10-13 20:41:38 +00:00
}
else if ( rescanAfterRefresh = = RescanAfterRefreshType . AfterManual & & trigger ! = CommandTrigger . Manual )
{
2019-11-27 01:40:36 +00:00
_logger . Trace ( "Skipping rescan of {0}. Reason: not after automatic scans" , series ) ;
2022-08-12 00:27:49 +00:00
_eventAggregator . PublishEvent ( new SeriesScanSkippedEvent ( series , SeriesScanSkippedReason . RescanAfterManualRefreshOnly ) ) ;
2018-10-13 20:41:38 +00:00
return ;
}
2018-05-03 06:34:05 +00:00
try
{
_diskScanService . Scan ( series ) ;
}
catch ( Exception e )
{
_logger . Error ( e , "Couldn't rescan series {0}" , series ) ;
}
}
2013-09-04 05:01:28 +00:00
public void Execute ( RefreshSeriesCommand message )
{
2018-10-13 20:41:38 +00:00
var trigger = message . Trigger ;
var isNew = message . IsNewSeries ;
_eventAggregator . PublishEvent ( new SeriesRefreshStartingEvent ( trigger = = CommandTrigger . Manual ) ) ;
2014-01-10 01:41:08 +00:00
2013-09-04 05:01:28 +00:00
if ( message . SeriesId . HasValue )
{
var series = _seriesService . GetSeries ( message . SeriesId . Value ) ;
2018-05-03 06:34:05 +00:00
try
{
2020-08-02 18:47:03 +00:00
series = RefreshSeriesInfo ( message . SeriesId . Value ) ;
2018-10-13 20:41:38 +00:00
RescanSeries ( series , isNew , trigger ) ;
}
catch ( SeriesNotFoundException )
{
_logger . Error ( "Series '{0}' (tvdbid {1}) was not found, it may have been removed from TheTVDB." , series . Title , series . TvdbId ) ;
2018-05-03 06:34:05 +00:00
}
catch ( Exception e )
{
_logger . Error ( e , "Couldn't refresh info for {0}" , series ) ;
2018-10-13 20:41:38 +00:00
RescanSeries ( series , isNew , trigger ) ;
2018-05-03 06:34:05 +00:00
throw ;
}
2013-09-04 05:01:28 +00:00
}
else
{
2015-06-08 06:33:08 +00:00
var allSeries = _seriesService . GetAllSeries ( ) . OrderBy ( c = > c . SortTitle ) . ToList ( ) ;
2013-09-04 05:01:28 +00:00
foreach ( var series in allSeries )
{
2020-08-02 18:47:03 +00:00
var seriesLocal = series ;
if ( trigger = = CommandTrigger . Manual | | _checkIfSeriesShouldBeRefreshed . ShouldRefresh ( seriesLocal ) )
2013-09-04 05:01:28 +00:00
{
2014-03-21 04:15:01 +00:00
try
{
2020-08-02 18:47:03 +00:00
seriesLocal = RefreshSeriesInfo ( seriesLocal . Id ) ;
2014-03-21 04:15:01 +00:00
}
2018-10-13 20:41:38 +00:00
catch ( SeriesNotFoundException )
{
2020-08-02 18:47:03 +00:00
_logger . Error ( "Series '{0}' (tvdbid {1}) was not found, it may have been removed from TheTVDB." , seriesLocal . Title , seriesLocal . TvdbId ) ;
2018-10-13 20:41:38 +00:00
continue ;
}
2014-03-21 04:15:01 +00:00
catch ( Exception e )
{
2020-08-02 18:47:03 +00:00
_logger . Error ( e , "Couldn't refresh info for {0}" , seriesLocal ) ;
2014-03-21 04:15:01 +00:00
}
2018-10-13 20:41:38 +00:00
2020-08-02 18:47:03 +00:00
RescanSeries ( seriesLocal , false , trigger ) ;
2013-09-04 05:01:28 +00:00
}
2014-03-21 04:15:01 +00:00
else
2013-09-04 05:01:28 +00:00
{
2020-08-02 18:47:03 +00:00
_logger . Info ( "Skipping refresh of series: {0}" , seriesLocal . Title ) ;
RescanSeries ( seriesLocal , false , trigger ) ;
2013-09-04 05:01:28 +00:00
}
}
}
2019-12-04 17:06:59 +00:00
_eventAggregator . PublishEvent ( new SeriesRefreshCompleteEvent ( ) ) ;
2013-09-04 05:01:28 +00:00
}
2013-06-02 19:29:00 +00:00
}
2014-12-10 02:20:50 +00:00
}