2012-07-10 04:37:24 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Xml;
|
|
|
|
|
using System.Xml.Linq;
|
|
|
|
|
using NzbDrone.Common;
|
2013-02-19 06:01:03 +00:00
|
|
|
|
using NzbDrone.Core.Tv;
|
2012-07-10 04:37:24 +00:00
|
|
|
|
using NzbDrone.Core.Model;
|
|
|
|
|
using NzbDrone.Core.Providers.Core;
|
|
|
|
|
using NzbDrone.Core.Repository;
|
2012-10-17 00:08:47 +00:00
|
|
|
|
using TvdbLib.Data;
|
|
|
|
|
using TvdbLib.Data.Banner;
|
2012-07-10 04:37:24 +00:00
|
|
|
|
|
|
|
|
|
namespace NzbDrone.Core.Providers.Metadata
|
|
|
|
|
{
|
2012-07-12 18:30:43 +00:00
|
|
|
|
public class Xbmc : MetadataBase
|
2012-07-10 04:37:24 +00:00
|
|
|
|
{
|
2012-07-14 08:17:37 +00:00
|
|
|
|
public Xbmc(ConfigProvider configProvider, DiskProvider diskProvider,
|
2013-02-22 00:47:09 +00:00
|
|
|
|
BannerProvider bannerProvider, IEpisodeService episodeService)
|
2013-02-20 02:05:15 +00:00
|
|
|
|
: base(configProvider, diskProvider, bannerProvider, episodeService)
|
2012-07-10 04:37:24 +00:00
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override string Name
|
|
|
|
|
{
|
|
|
|
|
get { return "XBMC"; }
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-12 21:08:21 +00:00
|
|
|
|
public override void CreateForSeries(Series series, TvdbSeries tvDbSeries)
|
2012-07-10 04:37:24 +00:00
|
|
|
|
{
|
2012-07-12 21:08:21 +00:00
|
|
|
|
//Create tvshow.nfo, fanart.jpg, folder.jpg and season##.tbn
|
2012-07-10 04:37:24 +00:00
|
|
|
|
var episodeGuideUrl = GetEpisodeGuideUrl(series.SeriesId);
|
|
|
|
|
|
|
|
|
|
_logger.Debug("Generating tvshow.nfo for: {0}", series.Title);
|
|
|
|
|
var sb = new StringBuilder();
|
|
|
|
|
var xws = new XmlWriterSettings();
|
2012-07-12 21:48:09 +00:00
|
|
|
|
xws.OmitXmlDeclaration = true;
|
2012-07-10 04:37:24 +00:00
|
|
|
|
xws.Indent = false;
|
|
|
|
|
|
|
|
|
|
using (var xw = XmlWriter.Create(sb, xws))
|
|
|
|
|
{
|
|
|
|
|
var tvShow = new XElement("tvshow");
|
2012-07-16 05:56:07 +00:00
|
|
|
|
|
2012-07-10 04:37:24 +00:00
|
|
|
|
tvShow.Add(new XElement("title", tvDbSeries.SeriesName));
|
|
|
|
|
tvShow.Add(new XElement("rating", tvDbSeries.Rating));
|
|
|
|
|
tvShow.Add(new XElement("plot", tvDbSeries.Overview));
|
2012-07-15 22:10:35 +00:00
|
|
|
|
tvShow.Add(new XElement("episodeguide", new XElement("url", episodeGuideUrl)));
|
2012-07-10 04:37:24 +00:00
|
|
|
|
tvShow.Add(new XElement("episodeguideurl", episodeGuideUrl));
|
|
|
|
|
tvShow.Add(new XElement("mpaa", tvDbSeries.ContentRating));
|
2012-07-16 05:56:07 +00:00
|
|
|
|
tvShow.Add(new XElement("id", tvDbSeries.Id));
|
2012-10-17 00:08:47 +00:00
|
|
|
|
tvShow.Add(new XElement("genre", tvDbSeries.GenreString.Trim('|').Split('|')[0]));
|
2012-07-10 04:37:24 +00:00
|
|
|
|
tvShow.Add(new XElement("premiered", tvDbSeries.FirstAired.ToString("yyyy-MM-dd")));
|
2012-10-17 00:08:47 +00:00
|
|
|
|
tvShow.Add(new XElement("studio", tvDbSeries.Network));
|
2012-07-10 04:37:24 +00:00
|
|
|
|
|
|
|
|
|
foreach(var actor in tvDbSeries.TvdbActors)
|
|
|
|
|
{
|
|
|
|
|
tvShow.Add(new XElement("actor",
|
|
|
|
|
new XElement("name", actor.Name),
|
|
|
|
|
new XElement("role", actor.Role),
|
2012-10-17 00:08:47 +00:00
|
|
|
|
new XElement("thumb", "http://www.thetvdb.com/banners/" + actor.ActorImage.BannerPath)
|
2012-07-10 04:37:24 +00:00
|
|
|
|
));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var doc = new XDocument(tvShow);
|
|
|
|
|
doc.Save(xw);
|
2012-07-12 21:48:09 +00:00
|
|
|
|
|
|
|
|
|
_logger.Debug("Saving tvshow.nfo for {0}", series.Title);
|
|
|
|
|
_diskProvider.WriteAllText(Path.Combine(series.Path, "tvshow.nfo"), doc.ToString());
|
2012-07-10 04:37:24 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-12-05 01:41:19 +00:00
|
|
|
|
if(String.IsNullOrWhiteSpace(tvDbSeries.FanartPath))
|
2012-07-10 04:37:24 +00:00
|
|
|
|
{
|
2012-12-05 01:41:19 +00:00
|
|
|
|
_logger.Debug("Fanart does not exist for series: {0}, skipping.", series.Title);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (!_diskProvider.FileExists(Path.Combine(series.Path, "fanart.jpg")))
|
|
|
|
|
{
|
|
|
|
|
_logger.Debug("Downloading fanart for: {0}", series.Title);
|
|
|
|
|
_bannerProvider.Download(tvDbSeries.FanartPath, Path.Combine(series.Path, "fanart.jpg"));
|
|
|
|
|
}
|
2012-07-10 04:37:24 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-07-15 04:27:40 +00:00
|
|
|
|
if (!_diskProvider.FileExists(Path.Combine(series.Path, "folder.jpg")))
|
2012-07-10 04:37:24 +00:00
|
|
|
|
{
|
2012-07-15 04:27:40 +00:00
|
|
|
|
if(_configProvider.MetadataUseBanners)
|
|
|
|
|
{
|
2012-12-05 01:41:19 +00:00
|
|
|
|
if(!String.IsNullOrWhiteSpace(tvDbSeries.BannerPath))
|
|
|
|
|
{
|
|
|
|
|
_logger.Debug("Downloading series banner for: {0}", series.Title);
|
|
|
|
|
_bannerProvider.Download(tvDbSeries.BannerPath, Path.Combine(series.Path, "folder.jpg"));
|
|
|
|
|
}
|
2012-07-15 04:27:40 +00:00
|
|
|
|
|
|
|
|
|
_logger.Debug("Downloading Season banners for {0}", series.Title);
|
2012-10-17 00:08:47 +00:00
|
|
|
|
DownloadSeasonThumbnails(series, tvDbSeries, TvdbSeasonBanner.Type.seasonwide);
|
2012-07-15 04:27:40 +00:00
|
|
|
|
}
|
2012-07-10 04:37:24 +00:00
|
|
|
|
|
2012-07-15 04:27:40 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
2012-12-05 01:41:19 +00:00
|
|
|
|
if(!String.IsNullOrWhiteSpace(tvDbSeries.PosterPath))
|
|
|
|
|
{
|
|
|
|
|
_logger.Debug("Downloading series thumbnail for: {0}", series.Title);
|
|
|
|
|
_bannerProvider.Download(tvDbSeries.PosterPath, Path.Combine(series.Path, "folder.jpg"));
|
|
|
|
|
}
|
2012-07-15 04:27:40 +00:00
|
|
|
|
|
|
|
|
|
_logger.Debug("Downloading Season posters for {0}", series.Title);
|
2012-10-17 00:08:47 +00:00
|
|
|
|
DownloadSeasonThumbnails(series, tvDbSeries, TvdbSeasonBanner.Type.season);
|
2012-07-15 04:27:40 +00:00
|
|
|
|
}
|
2012-07-10 04:37:24 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-12 21:08:21 +00:00
|
|
|
|
public override void CreateForEpisodeFile(EpisodeFile episodeFile, TvdbSeries tvDbSeries)
|
2012-07-10 04:37:24 +00:00
|
|
|
|
{
|
2012-07-12 21:08:21 +00:00
|
|
|
|
//Create filename.tbn and filename.nfo
|
2013-02-20 02:05:15 +00:00
|
|
|
|
var episodes = _episodeService.GetEpisodesByFileId(episodeFile.EpisodeFileId);
|
2012-07-10 04:37:24 +00:00
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
2012-12-05 01:41:19 +00:00
|
|
|
|
if(episodeFileThumbnail == null || String.IsNullOrWhiteSpace(episodeFileThumbnail.BannerPath))
|
2012-07-10 04:37:24 +00:00
|
|
|
|
{
|
|
|
|
|
_logger.Debug("No thumbnail is available for this episode");
|
|
|
|
|
}
|
2012-07-15 04:27:40 +00:00
|
|
|
|
|
2012-12-05 01:41:19 +00:00
|
|
|
|
else
|
2012-07-15 04:27:40 +00:00
|
|
|
|
{
|
2012-12-05 01:41:19 +00:00
|
|
|
|
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"));
|
|
|
|
|
}
|
2012-07-15 04:27:40 +00:00
|
|
|
|
}
|
2012-07-10 04:37:24 +00:00
|
|
|
|
|
2012-12-05 01:41:19 +00:00
|
|
|
|
|
|
|
|
|
|
2012-07-10 04:37:24 +00:00
|
|
|
|
_logger.Debug("Generating filename.nfo for: {0}", episodeFile.EpisodeFileId);
|
|
|
|
|
|
2012-07-12 18:30:43 +00:00
|
|
|
|
var xmlResult = String.Empty;
|
|
|
|
|
foreach (var episode in episodes)
|
2012-07-10 04:37:24 +00:00
|
|
|
|
{
|
2012-07-12 18:30:43 +00:00
|
|
|
|
var sb = new StringBuilder();
|
|
|
|
|
var xws = new XmlWriterSettings();
|
2012-07-12 21:48:09 +00:00
|
|
|
|
xws.OmitXmlDeclaration = true;
|
2012-07-12 18:30:43 +00:00
|
|
|
|
xws.Indent = false;
|
2012-07-10 04:37:24 +00:00
|
|
|
|
|
2012-07-12 18:30:43 +00:00
|
|
|
|
using (var xw = XmlWriter.Create(sb, xws))
|
2012-07-10 04:37:24 +00:00
|
|
|
|
{
|
2012-07-12 18:30:43 +00:00
|
|
|
|
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);
|
|
|
|
|
}
|
2012-07-10 04:37:24 +00:00
|
|
|
|
|
|
|
|
|
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));
|
2012-07-16 06:17:18 +00:00
|
|
|
|
details.Add(new XElement("aired", tvdbEpisode.FirstAired.ToString("yyyy-MM-dd")));
|
2012-07-30 04:47:05 +00:00
|
|
|
|
details.Add(new XElement("plot", tvdbEpisode.Overview));
|
2012-07-10 04:37:24 +00:00
|
|
|
|
details.Add(new XElement("displayseason"));
|
|
|
|
|
details.Add(new XElement("displayepisode"));
|
2012-10-17 00:08:47 +00:00
|
|
|
|
details.Add(new XElement("thumb", "http://www.thetvdb.com/banners/" + tvdbEpisode.BannerPath));
|
2012-07-10 04:37:24 +00:00
|
|
|
|
details.Add(new XElement("watched", "false"));
|
2012-10-17 00:08:47 +00:00
|
|
|
|
details.Add(new XElement("credits", tvdbEpisode.Writer.FirstOrDefault()));
|
2012-07-15 03:43:14 +00:00
|
|
|
|
details.Add(new XElement("director", tvdbEpisode.Directors.FirstOrDefault()));
|
2012-07-29 18:01:10 +00:00
|
|
|
|
details.Add(new XElement("rating", tvdbEpisode.Rating));
|
2012-07-10 04:37:24 +00:00
|
|
|
|
|
|
|
|
|
foreach(var actor in tvdbEpisode.GuestStars)
|
|
|
|
|
{
|
|
|
|
|
if (!String.IsNullOrWhiteSpace(actor))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
details.Add(new XElement("actor",
|
|
|
|
|
new XElement("name", actor)
|
2012-07-12 18:30:43 +00:00
|
|
|
|
));
|
2012-07-10 04:37:24 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach(var actor in tvDbSeries.TvdbActors)
|
|
|
|
|
{
|
|
|
|
|
details.Add(new XElement("actor",
|
|
|
|
|
new XElement("name", actor.Name),
|
|
|
|
|
new XElement("role", actor.Role),
|
2012-10-17 00:08:47 +00:00
|
|
|
|
new XElement("thumb", "http://www.thetvdb.com/banners/" + actor.ActorImage.BannerPath)
|
2012-07-12 18:30:43 +00:00
|
|
|
|
));
|
2012-07-10 04:37:24 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
doc.Add(details);
|
|
|
|
|
doc.Save(xw);
|
2012-07-12 21:48:09 +00:00
|
|
|
|
|
|
|
|
|
xmlResult += doc.ToString();
|
2012-10-13 05:35:47 +00:00
|
|
|
|
xmlResult += Environment.NewLine;
|
2012-07-12 21:48:09 +00:00
|
|
|
|
}
|
2012-07-10 04:37:24 +00:00
|
|
|
|
}
|
2012-07-12 18:30:43 +00:00
|
|
|
|
var filename = episodeFile.Path.Replace(Path.GetExtension(episodeFile.Path), ".nfo");
|
2012-07-10 04:37:24 +00:00
|
|
|
|
_logger.Debug("Saving episodedetails to: {0}", filename);
|
2012-10-13 05:35:47 +00:00
|
|
|
|
_diskProvider.WriteAllText(filename, xmlResult.Trim(EnvironmentProvider.NewLineChars));
|
2012-07-10 04:37:24 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-07-12 21:08:21 +00:00
|
|
|
|
public override void RemoveForSeries(Series series)
|
|
|
|
|
{
|
|
|
|
|
//Remove tvshow.nfo, fanart.jpg, folder.jpg and season##.tbn
|
|
|
|
|
_logger.Debug("Deleting series metadata for: ", series.Title);
|
|
|
|
|
|
|
|
|
|
_diskProvider.DeleteFile(Path.Combine(series.Path, "tvshow.nfo"));
|
|
|
|
|
_diskProvider.DeleteFile(Path.Combine(series.Path, "fanart.jpg"));
|
|
|
|
|
_diskProvider.DeleteFile(Path.Combine(series.Path, "fanart.jpg"));
|
|
|
|
|
|
|
|
|
|
foreach (var file in _diskProvider.GetFiles(series.Path, SearchOption.TopDirectoryOnly))
|
|
|
|
|
{
|
|
|
|
|
if (Path.GetExtension(file) != ".tbn")
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (!Path.GetFileName(file).StartsWith("season"))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
_logger.Debug("Deleting season thumbnail: {0}", file);
|
|
|
|
|
_diskProvider.DeleteFile(file);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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"));
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-10 04:37:24 +00:00
|
|
|
|
private void DownloadSeasonThumbnails(Series series, TvdbSeries tvDbSeries, TvdbSeasonBanner.Type bannerType)
|
|
|
|
|
{
|
2012-10-17 00:08:47 +00:00
|
|
|
|
var seasons = tvDbSeries.SeasonBanners.Where(s => s.BannerType == bannerType).Select(s => s.Season);
|
2012-07-10 04:37:24 +00:00
|
|
|
|
|
|
|
|
|
foreach (var season in seasons)
|
|
|
|
|
{
|
2012-10-17 00:08:47 +00:00
|
|
|
|
var banner = tvDbSeries.SeasonBanners.FirstOrDefault(b => b.BannerType == bannerType && b.Season == season);
|
2012-07-10 04:37:24 +00:00
|
|
|
|
_logger.Debug("Downloading banner for Season: {0} Series: {1}", season, series.Title);
|
2012-07-12 21:48:09 +00:00
|
|
|
|
|
|
|
|
|
if (season == 0)
|
|
|
|
|
{
|
2012-07-15 04:27:40 +00:00
|
|
|
|
if (!_diskProvider.FileExists(Path.Combine(series.Path, "season-specials.tbn")))
|
|
|
|
|
{
|
|
|
|
|
_bannerProvider.Download(banner.BannerPath,
|
|
|
|
|
Path.Combine(series.Path, "season-specials.tbn"));
|
|
|
|
|
}
|
2012-07-12 21:48:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
else
|
|
|
|
|
{
|
2012-07-15 04:27:40 +00:00
|
|
|
|
if (!_diskProvider.FileExists(Path.Combine(series.Path, String.Format("season{0:00}.tbn", season))))
|
|
|
|
|
{
|
|
|
|
|
_bannerProvider.Download(banner.BannerPath,
|
|
|
|
|
Path.Combine(series.Path, String.Format("season{0:00}.tbn", season)));
|
|
|
|
|
}
|
2012-07-12 21:48:09 +00:00
|
|
|
|
}
|
2012-07-10 04:37:24 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|