public EpisodeFile MapIt(EpisodeFile episodeFile, Series series, Episode episode) { // Terminating call. Since we can return null from this function // we need to be ready for PetaPoco to callback later with null // parameters if (episodeFile == null) return _current; // Is this the same EpisodeFile as the current one we're processing if (_current != null && _current.EpisodeFileId == episodeFile.EpisodeFileId) { // Yes, just add this post to the current EpisodeFiles's collection of Episodes _current.Episodes.Add(episode); // Return null to indicate we're not done with this EpisodeFiles yet return null; } // This is a different EpisodeFile to the current one, or this is the // first time through and we don't have an EpisodeFile yet // Save the current EpisodeFile var prev = _current; // Setup the new current EpisodeFile _current = episodeFile; _current.Episodes = new List<Episode>(); _current.Episodes.Add(episode); _current.Series = series; // Return the now populated previous EpisodeFile (or null if first time through) return prev; }
public void Setup() { Mocker.Resolve<QualityUpgradeSpecification>(); _upgradeDisk = Mocker.Resolve<UpgradeDiskSpecification>(); firstFile = new EpisodeFile { Quality = QualityTypes.Bluray1080p, Proper = true }; secondFile = new EpisodeFile { Quality = QualityTypes.Bluray1080p, Proper = true }; var singleEpisodeList = new List<Episode> { new Episode { EpisodeFile = firstFile }, new Episode { EpisodeFile = null } }; var doubleEpisodeList = new List<Episode> { new Episode { EpisodeFile = firstFile }, new Episode { EpisodeFile = secondFile }, new Episode { EpisodeFile = null } }; var fakeSeries = Builder<Series>.CreateNew() .With(c => c.QualityProfile = new QualityProfile { Cutoff = QualityTypes.Bluray1080p }) .Build(); parseResultMulti = new EpisodeParseResult { Series = fakeSeries, Quality = new QualityModel(QualityTypes.DVD, true), EpisodeNumbers = new List<int> { 3, 4 }, SeasonNumber = 12, Episodes = doubleEpisodeList }; parseResultSingle = new EpisodeParseResult { Series = fakeSeries, Quality = new QualityModel(QualityTypes.DVD, true), EpisodeNumbers = new List<int> { 3 }, SeasonNumber = 12, Episodes = singleEpisodeList }; }
public void Setup() { WithTempAsAppPath(); series = Builder<Series> .CreateNew() .With(s => s.SeriesId == 79488) .With(s => s.Title == "30 Rock") .Build(); episodeFile = Builder<EpisodeFile>.CreateNew() .With(f => f.SeriesId = 79488) .With(f => f.SeasonNumber = 1) .With(f => f.Path = @"C:\Test\30 Rock\Season 01\30 Rock - S01E01 - Pilot.avi") .Build(); var tvdbEpisodes = Builder<TvdbEpisode>.CreateListOfSize(2) .All() .With(e => e.SeriesId = 79488) .With(e => e.SeasonNumber = 1) .With(e => e.Directors = new List<string>{ "Fake Director" }) .With(e => e.Writer = new List<string>{ "Fake Writer" }) .With(e => e.GuestStars = new List<string> { "Guest Star 1", "Guest Star 2", "Guest Star 3", "" }) .Build(); var seasonBanners = Builder<TvdbSeasonBanner> .CreateListOfSize(4) .TheFirst(2) .With(b => b.Season = 1) .TheLast(2) .With(b => b.Season = 2) .TheFirst(1) .With(b => b.BannerType = TvdbSeasonBanner.Type.season) .With(b => b.BannerPath = "seasons/79488-1-1.jpg") .TheNext(2) .With(b => b.BannerType = TvdbSeasonBanner.Type.seasonwide) .With(b => b.BannerPath = "banners/seasons/79488-test.jpg") .TheLast(1) .With(b => b.BannerType = TvdbSeasonBanner.Type.season) .With(b => b.BannerPath = "seasons/79488-2-1.jpg") .Build(); var seriesActors = Builder<TvdbActor> .CreateListOfSize(5) .All() .With(a => a.ActorImage = Builder<TvdbActorBanner>.CreateNew().Build()) .Build(); tvdbSeries = Builder<TvdbSeries> .CreateNew() .With(s => s.Id = 79488) .With(s => s.SeriesName = "30 Rock") .With(s => s.TvdbActors = seriesActors.ToList()) .With(s => s.Episodes = tvdbEpisodes.ToList()) .Build(); tvdbSeries.Banners.AddRange(seasonBanners); }
public EpisodeFile(EpisodeFile source) { EpisodeFileId = source.EpisodeFileId; SeriesId = source.SeriesId; SeasonNumber = source.SeasonNumber; Path = source.Path; Quality = source.Quality; Proper = source.Proper; Size = source.Size; }
public void Start(ProgressNotification notification, dynamic options) { if (options == null || options.SeriesId <= 0) throw new ArgumentException("options"); if (options.SeasonNumber < 0) throw new ArgumentException("options.SeasonNumber"); var series = _seriesProvider.GetSeries(options.SeriesId); notification.CurrentMessage = String.Format("Renaming episodes for {0} Season {1}", series.Title, options.SeasonNumber); logger.Debug("Getting episodes from database for series: {0} and season: {1}", options.SeriesId, options.SeasonNumber); IList<EpisodeFile> episodeFiles = _mediaFileProvider.GetSeasonFiles(options.SeriesId, options.SeasonNumber); if (episodeFiles == null || !episodeFiles.Any()) { logger.Warn("No episodes in database found for series: {0} and season: {1}.", options.SeriesId, options.SeasonNumber); return; } var newEpisodeFiles = new List<EpisodeFile>(); var oldEpisodeFiles = new List<EpisodeFile>(); foreach (var episodeFile in episodeFiles) { try { var oldFile = new EpisodeFile(episodeFile); var newFile = _diskScanProvider.MoveEpisodeFile(episodeFile); if (newFile != null) { newEpisodeFiles.Add(newFile); oldEpisodeFiles.Add(oldFile); } } catch (Exception e) { logger.WarnException("An error has occurred while renaming file", e); } } //Remove & Create Metadata for episode files _metadataProvider.RemoveForEpisodeFiles(oldEpisodeFiles); _metadataProvider.CreateForEpisodeFiles(newEpisodeFiles); //Start AfterRename var message = String.Format("Renamed: Series {0}, Season: {1}", series.Title, options.SeasonNumber); _externalNotificationProvider.AfterRename(message, series); notification.CurrentMessage = String.Format("Rename completed for {0} Season {1}", series.Title, options.SeasonNumber); }
public void SetUp() { _series = Builder<Series>.CreateNew() .Build(); _episodeFile = Builder<EpisodeFile>.CreateNew() .With(f => f.Quality = QualityTypes.SDTV) .Build(); _episode = Builder<Episode>.CreateNew() .With(e => e.EpisodeFileId = 0) .With(e => e.SeriesId = _series.SeriesId) .With(e => e.Series = _series) .With(e => e.EpisodeFileId = _episodeFile.EpisodeFileId) .With(e => e.EpisodeFile = _episodeFile) .Build(); }
public Season MapIt(Season season, Episode episode, EpisodeFile episodeFile) { // Terminating call. Since we can return null from this function // we need to be ready for PetaPoco to callback later with null // parameters if (season == null) return _current; //Todo: Find a Query that doesn't require this check //Map EpisodeFile to Episode (Map to null if 0, because PetaPoco is returning a POCO when it should be null) episode.EpisodeFile = (episode.EpisodeFileId == 0 ? null : episodeFile); // Is this the same season as the current one we're processing if (_current != null && _current.SeasonId == season.SeasonId) { // Yes, just add this post to the current author's collection of posts _current.Episodes.Add(episode); // Return null to indicate we're not done with this author yet return null; } // This is season different author to the current one, or this is the // first time through and we don't have an season yet // Save the current author var prev = _current; // Setup the new current season _current = season; _current.Episodes = new List<Episode>(); _current.Episodes.Add(episode); // Return the now populated previous season (or null if first time through) return prev; }
public virtual void RemoveForEpisodeFile(EpisodeFile episodeFile) { foreach (var provider in _metadataProviders.Where(i => GetSettings(i.GetType()).Enable)) { provider.RemoveForEpisodeFile(episodeFile); } }
public virtual void CreateForEpisodeFile(EpisodeFile episodeFile, TvdbSeries tvDbSeries) { foreach (var provider in _metadataProviders.Where(i => GetSettings(i.GetType()).Enable)) { provider.CreateForEpisodeFile(episodeFile, tvDbSeries); } }
public virtual void CreateForEpisodeFile(EpisodeFile episodeFile) { var tvDbSeries = _tvDbProvider.GetSeries(episodeFile.SeriesId, true, true); CreateForEpisodeFile(episodeFile, tvDbSeries); }
public void Start(ProgressNotification notification, dynamic options) { List<Series> seriesToRename; if (options == null || options.SeriesId <= 0) { seriesToRename = _seriesProvider.GetAllSeries().ToList(); } else { seriesToRename = new List<Series>{ _seriesProvider.GetSeries(options.SeriesId) }; } foreach(var series in seriesToRename) { notification.CurrentMessage = String.Format("Renaming episodes for '{0}'", series.Title); Logger.Debug("Getting episodes from database for series: {0}", series.SeriesId); var episodeFiles = _mediaFileProvider.GetSeriesFiles(series.SeriesId); if (episodeFiles == null || episodeFiles.Count == 0) { Logger.Warn("No episodes in database found for series: {0}", series.SeriesId); return; } var newEpisodeFiles = new List<EpisodeFile>(); var oldEpisodeFiles = new List<EpisodeFile>(); foreach (var episodeFile in episodeFiles) { try { var oldFile = new EpisodeFile(episodeFile); var newFile = _diskScanProvider.MoveEpisodeFile(episodeFile); if (newFile != null) { newEpisodeFiles.Add(newFile); oldEpisodeFiles.Add(oldFile); } } catch (Exception e) { Logger.WarnException("An error has occurred while renaming file", e); } } //Remove & Create Metadata for episode files _metadataProvider.RemoveForEpisodeFiles(oldEpisodeFiles); _metadataProvider.CreateForEpisodeFiles(newEpisodeFiles); //Start AfterRename var message = String.Format("Renamed: Series {0}", series.Title); _externalNotificationProvider.AfterRename(message, series); notification.CurrentMessage = String.Format("Rename completed for {0}", series.Title); } }
/// <summary> /// Creates metadata for the episode file /// </summary> /// <param name = "episodeFile">The episode file to create the metadata</param> /// <param name = "tvDbSeries">Series information from TheTvDb</param> public abstract void CreateForEpisodeFile(EpisodeFile episodeFile, TvdbSeries tvDbSeries);
private static void VerifyFileImport(EpisodeFile result, AutoMoqer Mocker, Episode fakeEpisode, int size) { Mocker.VerifyAllMocks(); result.Should().NotBeNull(); result.SeriesId.Should().Be(fakeEpisode.SeriesId); result.Size.Should().Be(size); result.DateAdded.Should().HaveDay(DateTime.Now.Day); Mocker.GetMock<MediaFileProvider>().Verify(p => p.Add(It.IsAny<EpisodeFile>()), Times.Once()); //Get the count of episodes linked var count = Mocker.GetMock<EpisodeProvider>().Object.GetEpisodesByParseResult(null).Count; Mocker.GetMock<EpisodeProvider>().Verify(p => p.UpdateEpisode(It.Is<Episode>(e => e.EpisodeFileId == result.EpisodeFileId)), Times.Exactly(count)); }
public virtual EpisodeFile ImportFile(Series series, string filePath) { Logger.Trace("Importing file to database [{0}]", filePath); if (_mediaFileProvider.Exists(filePath)) { Logger.Trace("[{0}] already exists in the database. skipping.", filePath); return null; } long size = _diskProvider.GetSize(filePath); //Skip any file under 40MB - New samples don't even have sample in the name... if (size < Constants.IgnoreFileSize) { Logger.Trace("[{0}] appears to be a sample. skipping.", filePath); return null; } var parseResult = Parser.ParsePath(filePath); if (parseResult == null) return null; if (!_diskProvider.IsChildOfPath(filePath, series.Path)) parseResult.SceneSource = true; parseResult.SeriesTitle = series.Title; //replaces the nasty path as title to help with logging parseResult.Series = series; var episodes = _episodeProvider.GetEpisodesByParseResult(parseResult); if (episodes.Count <= 0) { Logger.Debug("Can't find any matching episodes in the database. Skipping {0}", filePath); return null; } //Make sure this file is an upgrade for ALL episodes already on disk if (episodes.All(e => e.EpisodeFile == null || e.EpisodeFile.QualityWrapper <= parseResult.Quality)) { Logger.Debug("Deleting the existing file(s) on disk to upgrade to: {0}", filePath); //Do the delete for files where there is already an episode on disk episodes.Where(e => e.EpisodeFile != null).Select(e => e.EpisodeFile.Path).Distinct().ToList().ForEach(p => _recycleBinProvider.DeleteFile(p)); } else { //Skip this file because its not an upgrade Logger.Trace("This file isn't an upgrade for all episodes. Skipping {0}", filePath); return null; } var episodeFile = new EpisodeFile(); episodeFile.DateAdded = DateTime.Now; episodeFile.SeriesId = series.SeriesId; episodeFile.Path = filePath.NormalizePath(); episodeFile.Size = size; episodeFile.Quality = parseResult.Quality.Quality; episodeFile.Proper = parseResult.Quality.Proper; episodeFile.SeasonNumber = parseResult.SeasonNumber; episodeFile.SceneName = Path.GetFileNameWithoutExtension(filePath.NormalizePath()); episodeFile.ReleaseGroup = parseResult.ReleaseGroup; var fileId = _mediaFileProvider.Add(episodeFile); //Link file to all episodes foreach (var ep in episodes) { ep.EpisodeFileId = fileId; ep.PostDownloadStatus = PostDownloadStatusType.NoError; _episodeProvider.UpdateEpisode(ep); Logger.Debug("Linking [{0}] > [{1}]", filePath, ep); } return episodeFile; }
public virtual void Update(EpisodeFile episodeFile) { _database.Update(episodeFile); }
public override void RemoveForEpisodeFile(EpisodeFile episodeFile) { //Remove filename.tbn and filename.nfo _logger.Debug("Deleting episode metadata for: {0}", episodeFile); _diskProvider.DeleteFile(episodeFile.Path.Replace(Path.GetExtension(episodeFile.Path), ".nfo")); _diskProvider.DeleteFile(episodeFile.Path.Replace(Path.GetExtension(episodeFile.Path), ".tbn")); }
public virtual int Add(EpisodeFile episodeFile) { return Convert.ToInt32(_database.Insert(episodeFile)); }
public virtual string GetNewFilename(IList<Episode> episodes, string seriesTitle, QualityTypes quality, bool proper, EpisodeFile episodeFile) { 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; } var sortedEpisodes = episodes.OrderBy(e => e.EpisodeNumber); var separatorStyle = EpisodeSortingHelper.GetSeparatorStyle(_configProvider.SortingSeparatorStyle); var numberStyle = EpisodeSortingHelper.GetNumberStyle(_configProvider.SortingNumberStyle); var episodeNames = new List<String>(); episodeNames.Add(Parser.CleanupEpisodeTitle(sortedEpisodes.First().Title)); string result = String.Empty; if (_configProvider.SortingIncludeSeriesName) { result += seriesTitle + separatorStyle.Pattern; } result += numberStyle.Pattern.Replace("%0e", String.Format("{0:00}", sortedEpisodes.First().EpisodeNumber)); if (episodes.Count > 1) { var multiEpisodeStyle = EpisodeSortingHelper.GetMultiEpisodeStyle(_configProvider.SortingMultiEpisodeStyle); foreach (var episode in sortedEpisodes.Skip(1)) { 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)); } } 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); if (_configProvider.SortingIncludeEpisodeTitle) { if (episodeNames.Distinct().Count() == 1) result += separatorStyle.Pattern + episodeNames.First(); else result += separatorStyle.Pattern + String.Join(" + ", episodeNames.Distinct()); } if (_configProvider.SortingAppendQuality) { result += String.Format(" [{0}]", quality); if (proper) result += " [Proper]"; } if (_configProvider.SortingReplaceSpaces) result = result.Replace(' ', '.'); Logger.Trace("New File Name is: [{0}]", result.Trim()); return CleanFilename(result.Trim()); }
/// <summary> /// Removes metadata for the episode file /// </summary> /// <param name = "episodeFile">The episode file to create the metadata</param> public abstract void RemoveForEpisodeFile(EpisodeFile episodeFile);
public void null_string_as_arg_should_not_fail() { var epFile = new EpisodeFile(); Logger.Trace("File {0} no longer exists on disk. removing from database.", epFile.Path); epFile.Path.Should().BeNull(); }
public virtual EpisodeFile MoveEpisodeFile(EpisodeFile episodeFile, bool newDownload = false) { if (episodeFile == null) throw new ArgumentNullException("episodeFile"); var series = _seriesProvider.GetSeries(episodeFile.SeriesId); var episodes = _episodeProvider.GetEpisodesByFileId(episodeFile.EpisodeFileId); string newFileName = _mediaFileProvider.GetNewFilename(episodes, series.Title, episodeFile.Quality, episodeFile.Proper, episodeFile); var newFile = _mediaFileProvider.CalculateFilePath(series, episodes.First().SeasonNumber, newFileName, Path.GetExtension(episodeFile.Path)); //Only rename if existing and new filenames don't match if (DiskProvider.PathEquals(episodeFile.Path, newFile.FullName)) { Logger.Debug("Skipping file rename, source and destination are the same: {0}", episodeFile.Path); return null; } _diskProvider.CreateDirectory(newFile.DirectoryName); Logger.Debug("Moving [{0}] > [{1}]", episodeFile.Path, newFile.FullName); _diskProvider.MoveFile(episodeFile.Path, newFile.FullName); //Wrapped in Try/Catch to prevent this from causing issues with remote NAS boxes, the move worked, which is more important. try { _diskProvider.InheritFolderPermissions(newFile.FullName); } catch (UnauthorizedAccessException ex) { Logger.Debug("Unable to apply folder permissions to: ", newFile.FullName); Logger.TraceException(ex.Message, ex); } episodeFile.Path = newFile.FullName; _mediaFileProvider.Update(episodeFile); var parseResult = Parser.ParsePath(episodeFile.Path); parseResult.Series = series; parseResult.Quality = new QualityModel{ Quality = episodeFile.Quality, Proper = episodeFile.Proper }; parseResult.Episodes = episodes; var message = _downloadProvider.GetDownloadTitle(parseResult); if (newDownload) { _externalNotificationProvider.OnDownload(message, series); foreach(var episode in episodes) _signalRProvider.UpdateEpisodeStatus(episode.EpisodeId, EpisodeStatusType.Ready, parseResult.Quality); } else { _externalNotificationProvider.OnRename(message, series); } return episodeFile; }
public virtual bool MoveEpisodeFile(EpisodeFile episodeFile, bool newDownload = false) { if (episodeFile == null) throw new ArgumentNullException("episodeFile"); var series = _seriesProvider.GetSeries(episodeFile.SeriesId); var episodes = _episodeProvider.GetEpisodesByFileId(episodeFile.EpisodeFileId); string newFileName = _mediaFileProvider.GetNewFilename(episodes, series.Title, episodeFile.Quality, episodeFile.Proper); var newFile = _mediaFileProvider.CalculateFilePath(series, episodes.First().SeasonNumber, newFileName, Path.GetExtension(episodeFile.Path)); //Only rename if existing and new filenames don't match if (DiskProvider.PathEquals(episodeFile.Path, newFile.FullName)) { Logger.Debug("Skipping file rename, source and destination are the same: {0}", episodeFile.Path); return false; } _diskProvider.CreateDirectory(newFile.DirectoryName); Logger.Debug("Moving [{0}] > [{1}]", episodeFile.Path, newFile.FullName); _diskProvider.MoveFile(episodeFile.Path, newFile.FullName); _diskProvider.InheritFolderPermissions(newFile.FullName); episodeFile.Path = newFile.FullName; _mediaFileProvider.Update(episodeFile); var parseResult = Parser.ParsePath(episodeFile.Path); parseResult.Series = series; var message = _downloadProvider.GetDownloadTitle(parseResult); if (newDownload) { _externalNotificationProvider.OnDownload(message, series); foreach(var episode in episodes) _signalRProvider.UpdateEpisodeStatus(episode.EpisodeId, EpisodeStatusType.Ready); } else { _externalNotificationProvider.OnRename(message, series); } return true; }
private static void VerifySkipImport(EpisodeFile result, AutoMoqer Mocker) { Mocker.VerifyAllMocks(); result.Should().BeNull(); Mocker.GetMock<MediaFileProvider>().Verify(p => p.Add(It.IsAny<EpisodeFile>()), Times.Never()); Mocker.GetMock<EpisodeProvider>().Verify(p => p.UpdateEpisode(It.IsAny<Episode>()), Times.Never()); Mocker.GetMock<DiskProvider>().Verify(p => p.DeleteFile(It.IsAny<string>()), Times.Never()); }
public override void CreateForEpisodeFile(EpisodeFile episodeFile, TvdbSeries tvDbSeries) { //Create filename.tbn and filename.nfo var episodes = _episodeProvider.GetEpisodesByFileId(episodeFile.EpisodeFileId); if (!episodes.Any()) { _logger.Debug("No episodes where found for this episode file: {0}", episodeFile.EpisodeFileId); return; } var episodeFileThumbnail = tvDbSeries.Episodes.FirstOrDefault( e => e.SeasonNumber == episodeFile.SeasonNumber && e.EpisodeNumber == episodes.First().EpisodeNumber); if (episodeFileThumbnail == null || String.IsNullOrWhiteSpace(episodeFileThumbnail.BannerPath)) { _logger.Debug("No thumbnail is available for this episode"); return; } if (!_diskProvider.FileExists(episodeFile.Path.Replace(Path.GetExtension(episodeFile.Path), ".tbn"))) { _logger.Debug("Downloading episode thumbnail for: {0}", episodeFile.EpisodeFileId); _bannerProvider.Download(episodeFileThumbnail.BannerPath, episodeFile.Path.Replace(Path.GetExtension(episodeFile.Path), ".tbn")); } _logger.Debug("Generating filename.nfo for: {0}", episodeFile.EpisodeFileId); var xmlResult = String.Empty; foreach (var episode in episodes) { var sb = new StringBuilder(); var xws = new XmlWriterSettings(); xws.OmitXmlDeclaration = true; xws.Indent = false; using (var xw = XmlWriter.Create(sb, xws)) { var doc = new XDocument(); var tvdbEpisode = tvDbSeries.Episodes.FirstOrDefault( e => e.Id == episode.TvDbEpisodeId); if (tvdbEpisode == null) { _logger.Debug("Looking up by TvDbEpisodeId failed, trying to match via season/episode number combination"); tvdbEpisode = tvDbSeries.Episodes.FirstOrDefault( e => e.SeasonNumber == episode.SeasonNumber && e.EpisodeNumber == episode.EpisodeNumber); } if (tvdbEpisode == null) { _logger.Debug("Unable to find episode from TvDb - skipping"); return; } var details = new XElement("episodedetails"); details.Add(new XElement("title", tvdbEpisode.EpisodeName)); details.Add(new XElement("season", tvdbEpisode.SeasonNumber)); details.Add(new XElement("episode", tvdbEpisode.EpisodeNumber)); details.Add(new XElement("aired", tvdbEpisode.FirstAired.ToString("yyyy-MM-dd"))); details.Add(new XElement("plot", tvdbEpisode.Overview)); details.Add(new XElement("displayseason")); details.Add(new XElement("displayepisode")); details.Add(new XElement("thumb", "http://www.thetvdb.com/banners/" + tvdbEpisode.BannerPath)); details.Add(new XElement("watched", "false")); details.Add(new XElement("credits", tvdbEpisode.Writer.FirstOrDefault())); details.Add(new XElement("director", tvdbEpisode.Directors.FirstOrDefault())); details.Add(new XElement("rating", tvdbEpisode.Rating)); foreach(var actor in tvdbEpisode.GuestStars) { if (!String.IsNullOrWhiteSpace(actor)) continue; details.Add(new XElement("actor", new XElement("name", actor) )); } foreach(var actor in tvDbSeries.TvdbActors) { details.Add(new XElement("actor", new XElement("name", actor.Name), new XElement("role", actor.Role), new XElement("thumb", "http://www.thetvdb.com/banners/" + actor.ActorImage.BannerPath) )); } doc.Add(details); doc.Save(xw); xmlResult += doc.ToString(); xmlResult += Environment.NewLine; } } var filename = episodeFile.Path.Replace(Path.GetExtension(episodeFile.Path), ".nfo"); _logger.Debug("Saving episodedetails to: {0}", filename); _diskProvider.WriteAllText(filename, xmlResult.Trim(EnvironmentProvider.NewLineChars)); }
public virtual EpisodeFile ImportFile(Series series, string filePath) { Logger.Trace("Importing file to database [{0}]", filePath); if (_mediaFileProvider.Exists(filePath)) { Logger.Trace("[{0}] already exists in the database. skipping.", filePath); return null; } long size = _diskProvider.GetSize(filePath); //If Size is less than 40MB and contains sample. Check for Size to ensure its not an episode with sample in the title if (size < Constants.IgnoreFileSize && filePath.ToLower().Contains("sample")) { Logger.Trace("[{0}] appears to be a sample. skipping.", filePath); return null; } var parseResult = Parser.ParsePath(filePath); if (parseResult == null) return null; parseResult.SeriesTitle = series.Title; //replaces the nasty path as title to help with logging parseResult.Series = series; var episodes = _episodeProvider.GetEpisodesByParseResult(parseResult); if (episodes.Count <= 0) { Logger.Debug("Can't find any matching episodes in the database. Skipping {0}", filePath); return null; } //Make sure this file is an upgrade for ALL episodes already on disk if (episodes.All(e => e.EpisodeFile == null || e.EpisodeFile.QualityWrapper <= parseResult.Quality)) { Logger.Debug("Deleting the existing file(s) on disk to upgrade to: {0}", filePath); //Do the delete for files where there is already an episode on disk episodes.Where(e => e.EpisodeFile != null).Select(e => e.EpisodeFile.Path).Distinct().ToList().ForEach(p => _diskProvider.DeleteFile(p)); } else { //Skip this file because its not an upgrade Logger.Trace("This file isn't an upgrade for all episodes. Skipping {0}", filePath); return null; } var episodeFile = new EpisodeFile(); episodeFile.DateAdded = DateTime.Now; episodeFile.SeriesId = series.SeriesId; episodeFile.Path = filePath.NormalizePath(); episodeFile.Size = size; episodeFile.Quality = parseResult.Quality.QualityType; episodeFile.Proper = parseResult.Quality.Proper; episodeFile.SeasonNumber = parseResult.SeasonNumber; var fileId = _mediaFileProvider.Add(episodeFile); //Link file to all episodes foreach (var ep in episodes) { ep.EpisodeFileId = fileId; ep.PostDownloadStatus = PostDownloadStatusType.NoError; _episodeProvider.UpdateEpisode(ep); Logger.Debug("Linking [{0}] > [{1}]", filePath, ep); } return episodeFile; }