automatically download banner,poster, fanart. without a job :D

This commit is contained in:
kay.one 2013-03-03 21:53:02 -08:00
commit 1ccbb3c9d8
42 changed files with 245 additions and 483 deletions

View file

@ -0,0 +1,164 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using NLog;
using NzbDrone.Core.MediaCover;
using NzbDrone.Core.Tv;
using NzbDrone.Common;
namespace NzbDrone.Core.MetadataSource
{
public class TvDbProxy
{
public const string TVDB_APIKEY = "5D2D188E86E07F4F";
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
private readonly Tvdb.Tvdb _handlerV2;
public TvDbProxy()
{
_handlerV2 = new Tvdb.Tvdb(TVDB_APIKEY);
}
public virtual List<Series> SearchSeries(string title)
{
logger.Debug("Searching TVDB for '{0}'", title);
if (title.Contains(" & "))
{
title = title.Replace(" & ", " ");
}
var searchResult = _handlerV2.SearchSeries(title).Select(tvdbSeriesSearchItem => new Series
{
TvDbId = tvdbSeriesSearchItem.seriesid,
Title = tvdbSeriesSearchItem.SeriesName,
FirstAired = tvdbSeriesSearchItem.FirstAired,
Overview = tvdbSeriesSearchItem.Overview
}).ToList();
logger.Debug("Search for '{0}' returned {1} possible results", title, searchResult.Count);
return searchResult;
}
public virtual Series GetSeries(int tvDbSeriesId)
{
var tvDbSeries = _handlerV2.GetSeriesBaseRecord("http://thetvdb.com", tvDbSeriesId);
var series = new Series();
series.Title = tvDbSeries.SeriesName;
series.AirTime = CleanAirsTime(tvDbSeries.Airs_Time);
series.Overview = tvDbSeries.Overview;
series.Status = tvDbSeries.Status;
series.Language = tvDbSeries.Language ?? string.Empty;
series.CleanTitle = Parser.NormalizeTitle(tvDbSeries.SeriesName);
series.LastInfoSync = DateTime.Now;
if (tvDbSeries.Runtime.HasValue)
{
series.Runtime = Convert.ToInt32(tvDbSeries.Runtime);
}
series.Covers = new List<MediaCover.MediaCover>();
if (!string.IsNullOrWhiteSpace(tvDbSeries.banner))
{
series.Covers.Add(new MediaCover.MediaCover { CoverType = MediaCoverTypes.Banner, Url = tvDbSeries.banner });
}
if (!string.IsNullOrWhiteSpace(tvDbSeries.fanart))
{
series.Covers.Add(new MediaCover.MediaCover { CoverType = MediaCoverTypes.Fanart, Url = tvDbSeries.fanart });
}
if (!string.IsNullOrWhiteSpace(tvDbSeries.poster))
{
series.Covers.Add(new MediaCover.MediaCover { CoverType = MediaCoverTypes.Poster, Url = tvDbSeries.poster });
}
series.Network = tvDbSeries.Network;
if (tvDbSeries.FirstAired.HasValue && tvDbSeries.FirstAired.Value.Year > 1900)
{
series.FirstAired = tvDbSeries.FirstAired.Value.Date;
}
else
{
series.FirstAired = null;
}
return series;
}
public virtual IList<Episode> GetEpisodes(int tvDbSeriesId)
{
var seriesRecord = _handlerV2.GetSeriesFullRecord("http://thetvdb.com", tvDbSeriesId);
var tvdbEpisodes = seriesRecord.Episodes.OrderByDescending(e => e.FirstAired).ThenByDescending(e => e.EpisodeName)
.GroupBy(e => e.seriesid.ToString("000000") + e.SeasonNumber.ToString("000") + e.EpisodeNumber.ToString("000"))
.Select(e => e.First());
var episodes = new List<Episode>();
foreach (var tvDbEpisode in tvdbEpisodes)
{
var episode = new Episode();
episode.TvDbEpisodeId = tvDbEpisode.id;
episode.EpisodeNumber = tvDbEpisode.EpisodeNumber;
episode.SeasonNumber = tvDbEpisode.SeasonNumber;
episode.AbsoluteEpisodeNumber = tvDbEpisode.absolute_number.ParseInt32();
episode.Title = tvDbEpisode.EpisodeName;
episode.Overview = tvDbEpisode.Overview;
if (tvDbEpisode.FirstAired.Year > 1900)
{
episode.AirDate = tvDbEpisode.FirstAired.Date;
}
else
{
episode.AirDate = null;
}
episodes.Add(episode);
}
return episodes;
}
/// <summary>
/// Cleans up the AirsTime Component from TheTVDB since it can be garbage that comes in.
/// </summary>
/// <param name = "rawTime">The TVDB AirsTime</param>
/// <returns>String that contains the AirTimes</returns>
private static readonly Regex timeRegex = new Regex(@"^(?<time>\d+:?\d*)\W*(?<meridiem>am|pm)?", RegexOptions.IgnoreCase | RegexOptions.Compiled);
private static string CleanAirsTime(string rawTime)
{
var match = timeRegex.Match(rawTime);
var time = match.Groups["time"].Value;
var meridiem = match.Groups["meridiem"].Value;
//Lets assume that a string that doesn't contain a Merideim is aired at night... So we'll add it
if (String.IsNullOrEmpty(meridiem))
meridiem = "PM";
DateTime dateTime;
if (String.IsNullOrEmpty(time) || !DateTime.TryParse(time + " " + meridiem.ToUpper(), out dateTime))
return String.Empty;
return dateTime.ToString("hh:mm tt");
}
}
}

View file

@ -0,0 +1,71 @@
using System;
using System.Collections.Generic;
using System.Linq;
using NLog;
using NzbDrone.Core.Providers;
using NzbDrone.Core.ReferenceData;
using NzbDrone.Core.Tv;
using NzbDrone.Core.Model.TvRage;
namespace NzbDrone.Core.MetadataSource
{
public class TvRageMappingProvider
{
private readonly SceneMappingService _sceneMappingService;
private readonly TvRageProxy _tvRageProxy;
private readonly IEpisodeService _episodeService;
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
public TvRageMappingProvider(SceneMappingService sceneMappingService,
TvRageProxy tvRageProxy, IEpisodeService episodeService)
{
_sceneMappingService = sceneMappingService;
_tvRageProxy = tvRageProxy;
_episodeService = episodeService;
}
public TvRageMappingProvider()
{
}
public Series FindMatchingTvRageSeries(Series series)
{
var firstEpisode = _episodeService.GetEpisode(series.Id, 1, 1);
var cleanName = _sceneMappingService.GetCleanName(series.Id);
var results = _tvRageProxy.SearchSeries(series.Title);
var result = ProcessResults(results, series, cleanName, firstEpisode);
if (result != null)
{
logger.Trace("TV Rage: {0} matches TVDB: {1}", result.Name, series.Title);
series.TvRageId = result.ShowId;
series.TvRageTitle = result.Name;
series.UtcOffset = _tvRageProxy.GetSeries(result.ShowId).UtcOffset;
}
return series;
}
public TvRageSearchResult ProcessResults(IList<TvRageSearchResult> searchResults, Series series, string sceneCleanName, Episode firstEpisode)
{
foreach (var result in searchResults)
{
if (Parser.NormalizeTitle(result.Name).Equals(series.CleanTitle))
return result;
if (!String.IsNullOrWhiteSpace(sceneCleanName) && Parser.NormalizeTitle(result.Name).Equals(sceneCleanName))
return result;
if (series.FirstAired.HasValue && result.Started == series.FirstAired.Value)
return result;
if (firstEpisode != null && firstEpisode.AirDate.HasValue && result.Started == firstEpisode.AirDate.Value)
return result;
}
return null;
}
}
}

View file

@ -0,0 +1,166 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using NLog;
using NzbDrone.Common;
using NzbDrone.Core.Helpers;
using NzbDrone.Core.Model.TvRage;
namespace NzbDrone.Core.MetadataSource
{
public class TvRageProxy
{
private readonly HttpProvider _httpProvider;
private const string TVRAGE_APIKEY = "NW4v0PSmQIoVmpbASLdD";
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
public TvRageProxy(HttpProvider httpProvider)
{
_httpProvider = httpProvider;
}
public TvRageProxy()
{
}
public virtual IList<TvRageSearchResult> SearchSeries(string title)
{
var searchResults = new List<TvRageSearchResult>();
var xmlStream = _httpProvider.DownloadStream("http://services.tvrage.com/feeds/full_search.php?show=" + title, null);
var xml = XDocument.Load(xmlStream);
var shows = xml.Descendants("Results").Descendants("show");
foreach (var s in shows)
{
try
{
var show = new TvRageSearchResult();
show.ShowId = s.Element("showid").ConvertTo<Int32>();
show.Name = s.Element("name").Value;
show.Link = s.Element("link").Value;
show.Country = s.Element("country").Value;
show.Started = s.Element("started").ConvertTo<DateTime>();
show.Ended = s.Element("ended").ConvertTo<DateTime>();
if (show.Ended < new DateTime(1900, 1, 1))
show.Ended = null;
show.Seasons = s.Element("seasons").ConvertTo<Int32>();
show.Status = s.Element("status").Value;
show.RunTime = s.Element("seasons").ConvertTo<Int32>();
show.AirTime = s.Element("airtime").ConvertTo<DateTime>();
show.AirDay = s.Element("airday").ConvertToDayOfWeek();
searchResults.Add(show);
}
catch (Exception ex)
{
logger.DebugException("Failed to parse TvRage Search Result. Search Term : " + title, ex);
}
}
return searchResults;
}
public virtual TvRageSeries GetSeries(int id)
{
var url = string.Format("http://services.tvrage.com/feeds/showinfo.php?key={0}&sid={1}", TVRAGE_APIKEY, id);
var xmlStream = _httpProvider.DownloadStream(url, null);
var xml = XDocument.Load(xmlStream);
var s = xml.Descendants("Showinfo").First();
try
{
if(s.Element("showid") == null)
{
logger.Warn("TvRage did not return valid series info for id: {0}", id);
return null;
}
var show = new TvRageSeries();
show.ShowId = s.Element("showid").ConvertTo<Int32>();
show.Name = s.Element("showname").Value;
show.Link = s.Element("showlink").Value;
show.Seasons = s.Element("seasons").ConvertTo<Int32>();
show.Started = s.Element("started").ConvertTo<Int32>();
show.StartDate = s.Element("startdate").ConvertTo<DateTime>();
show.Ended = s.Element("ended").ConvertTo<DateTime>();
show.OriginCountry = s.Element("origin_country").Value;
show.Status = s.Element("status").Value;
show.RunTime = s.Element("runtime").ConvertTo<Int32>();
show.Network = s.Element("network").Value;
show.AirTime = s.Element("airtime").ConvertTo<DateTime>();
show.AirDay = s.Element("airday").ConvertToDayOfWeek();
show.UtcOffset = GetUtcOffset(s.Element("timezone").Value);
return show;
}
catch (Exception ex)
{
logger.DebugException("Failed to parse ShowInfo for ID: " + id, ex);
return null;
}
}
public virtual List<TvRageEpisode> GetEpisodes(int id)
{
var url = String.Format("http://services.tvrage.com/feeds/episode_list.php?key={0}&sid={1}", TVRAGE_APIKEY, id);
var xmlStream = _httpProvider.DownloadStream(url, null);
var xml = XDocument.Load(xmlStream);
var show = xml.Descendants("Show");
var seasons = show.Descendants("Season");
var episodes = new List<TvRageEpisode>();
foreach (var season in seasons)
{
var eps = season.Descendants("episode");
foreach (var e in eps)
{
try
{
var episode = new TvRageEpisode();
episode.EpisodeNumber = e.Element("epnum").ConvertTo<Int32>();
episode.SeasonNumber = e.Element("seasonnum").ConvertTo<Int32>();
episode.ProductionCode = e.Element("prodnum").Value;
episode.AirDate = e.Element("airdate").ConvertTo<DateTime>();
episode.Link = e.Element("link").Value;
episode.Title = e.Element("title").Value;
episodes.Add(episode);
}
catch (Exception ex)
{
logger.DebugException("Failed to parse TV Rage episode", ex);
}
}
}
return episodes;
}
internal int GetUtcOffset(string timeZone)
{
if (String.IsNullOrWhiteSpace(timeZone))
return 0;
var offsetString = timeZone.Substring(3, 2);
int offset;
if (!Int32.TryParse(offsetString, out offset))
return 0;
if (timeZone.IndexOf("+DST", StringComparison.CurrentCultureIgnoreCase) > 0)
offset++;
return offset;
}
}
}