From 91a416e0b16cbe6b2524b516b469fdb057164934 Mon Sep 17 00:00:00 2001 From: Keivan Beigi Date: Wed, 30 Jan 2013 16:42:11 -0800 Subject: [PATCH] added 2nd tvdb .net client that allows us to preform concurrent searches. --- NzbDrone.Core/NzbDrone.Core.csproj | 18 ++ NzbDrone.Core/Providers/TvDbProvider.cs | 37 +-- NzbDrone.Core/Tvdb/Tvdb.Sync.cs | 223 ++++++++++++++++++ NzbDrone.Core/Tvdb/Tvdb.cs | 205 ++++++++++++++++ NzbDrone.Core/Tvdb/TvdbActor.cs | 36 +++ NzbDrone.Core/Tvdb/TvdbAsyncResult.cs | 10 + NzbDrone.Core/Tvdb/TvdbBanner.cs | 86 +++++++ NzbDrone.Core/Tvdb/TvdbEpisodes.cs | 132 +++++++++++ NzbDrone.Core/Tvdb/TvdbLanguages.cs | 30 +++ NzbDrone.Core/Tvdb/TvdbMirrors.cs | 40 ++++ NzbDrone.Core/Tvdb/TvdbSeriesBase.cs | 131 ++++++++++ NzbDrone.Core/Tvdb/TvdbSeriesFull.cs | 21 ++ NzbDrone.Core/Tvdb/TvdbSeriesSearch.cs | 18 ++ NzbDrone.Core/Tvdb/TvdbSeriesSearchItem.cs | 50 ++++ NzbDrone.Core/Tvdb/TvdbServerTime.cs | 13 + NzbDrone.Core/Tvdb/TvdbUpdate.cs | 86 +++++++ NzbDrone.Core/Tvdb/TvdbUpdateItems.cs | 26 ++ NzbDrone.Core/packages.config | 1 + .../Controllers/AddSeriesController.cs | 29 +-- 19 files changed, 1147 insertions(+), 45 deletions(-) create mode 100644 NzbDrone.Core/Tvdb/Tvdb.Sync.cs create mode 100644 NzbDrone.Core/Tvdb/Tvdb.cs create mode 100644 NzbDrone.Core/Tvdb/TvdbActor.cs create mode 100644 NzbDrone.Core/Tvdb/TvdbAsyncResult.cs create mode 100644 NzbDrone.Core/Tvdb/TvdbBanner.cs create mode 100644 NzbDrone.Core/Tvdb/TvdbEpisodes.cs create mode 100644 NzbDrone.Core/Tvdb/TvdbLanguages.cs create mode 100644 NzbDrone.Core/Tvdb/TvdbMirrors.cs create mode 100644 NzbDrone.Core/Tvdb/TvdbSeriesBase.cs create mode 100644 NzbDrone.Core/Tvdb/TvdbSeriesFull.cs create mode 100644 NzbDrone.Core/Tvdb/TvdbSeriesSearch.cs create mode 100644 NzbDrone.Core/Tvdb/TvdbSeriesSearchItem.cs create mode 100644 NzbDrone.Core/Tvdb/TvdbServerTime.cs create mode 100644 NzbDrone.Core/Tvdb/TvdbUpdate.cs create mode 100644 NzbDrone.Core/Tvdb/TvdbUpdateItems.cs diff --git a/NzbDrone.Core/NzbDrone.Core.csproj b/NzbDrone.Core/NzbDrone.Core.csproj index 4a877241c..5f7698363 100644 --- a/NzbDrone.Core/NzbDrone.Core.csproj +++ b/NzbDrone.Core/NzbDrone.Core.csproj @@ -181,6 +181,9 @@ False ..\packages\Prowlin.0.9.4456.26422\lib\net40\Prowlin.dll + + ..\packages\RestSharp.104.1\lib\net4\RestSharp.dll + ..\packages\SignalR.Server.0.5.3\lib\net40\SignalR.dll @@ -587,6 +590,21 @@ + + + + + + + + + + + + + + + diff --git a/NzbDrone.Core/Providers/TvDbProvider.cs b/NzbDrone.Core/Providers/TvDbProvider.cs index c4fb1826f..cbcc748d7 100644 --- a/NzbDrone.Core/Providers/TvDbProvider.cs +++ b/NzbDrone.Core/Providers/TvDbProvider.cs @@ -1,12 +1,12 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; -using System.Text.RegularExpressions; using NLog; using NzbDrone.Common; +using NzbDrone.Core.Tvdb; using TvdbLib; using TvdbLib.Cache; using TvdbLib.Data; +using TvdbLanguage = TvdbLib.Data.TvdbLanguage; namespace NzbDrone.Core.Providers { @@ -14,14 +14,19 @@ namespace NzbDrone.Core.Providers { private readonly EnvironmentProvider _environmentProvider; public const string TVDB_APIKEY = "5D2D188E86E07F4F"; - private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); + private static readonly Logger logger = LogManager.GetCurrentClassLogger(); + + private readonly TvdbHandler _handler; + private readonly Tvdb.Tvdb _handlerV2; + public TvDbProvider(EnvironmentProvider environmentProvider) { _environmentProvider = environmentProvider; _handler = new TvdbHandler(new XmlCacheProvider(_environmentProvider.GetCacheFolder()), TVDB_APIKEY); + _handlerV2 = new Tvdb.Tvdb(TVDB_APIKEY); } public TvDbProvider() @@ -29,30 +34,26 @@ namespace NzbDrone.Core.Providers } - public virtual IList SearchSeries(string title) + public virtual List SearchSeries(string title) { - lock (_handler) - { - Logger.Debug("Searching TVDB for '{0}'", title); + logger.Debug("Searching TVDB for '{0}'", title); - if(title.Contains(" & ")) - { - Logger.Debug("Removing ampersand before searching"); - title = title.Replace(" & ", " "); - } + if (title.Contains(" & ")) + { + title = title.Replace(" & ", " "); + } - var result = _handler.SearchSeries(title); + var result = _handlerV2.SearchSeries(title); - Logger.Debug("Search for '{0}' returned {1} possible results", title, result.Count); - return result; - } + logger.Debug("Search for '{0}' returned {1} possible results", title, result.Count); + return result; } public virtual TvdbSeries GetSeries(int id, bool loadEpisodes, bool loadActors = false) { lock (_handler) { - Logger.Debug("Fetching SeriesId'{0}' from tvdb", id); + logger.Debug("Fetching SeriesId'{0}' from tvdb", id); var result = _handler.GetSeries(id, TvdbLanguage.DefaultLanguage, loadEpisodes, loadActors, true, true); //Remove duplicated episodes diff --git a/NzbDrone.Core/Tvdb/Tvdb.Sync.cs b/NzbDrone.Core/Tvdb/Tvdb.Sync.cs new file mode 100644 index 000000000..6ea0904d9 --- /dev/null +++ b/NzbDrone.Core/Tvdb/Tvdb.Sync.cs @@ -0,0 +1,223 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using RestSharp; +using RestSharp.Deserializers; + +namespace NzbDrone.Core.Tvdb +{ + public partial class Tvdb + { + private T ProcessRequest (RestRequest request) + where T: new() + { + return ProcessRequest(BASE_URL, request); + } + + private T ProcessRequest (string url, RestRequest request) + where T: new() + { + var client = new RestClient(url); + client.AddHandler("text/xml", new DotNetXmlDeserializer()); + + if(Timeout.HasValue) + client.Timeout = Timeout.Value; + +#if !WINDOWS_PHONE + if(Proxy != null) + client.Proxy = Proxy; +#endif + + Error = null; + + //var resp = client.Execute(request); + IRestResponse resp = client.Execute(request); + + ResponseContent = resp.Content; + ResponseHeaders = resp.Headers.ToDictionary(k => k.Name, v => v.Value); + + if(resp.ResponseStatus == ResponseStatus.Completed) + { + return resp.Data; + + // Manual deserialization + //TextReader r = new StringReader(resp.Content); + //XmlSerializer s = new XmlSerializer(typeof(T)); + //return (T)s.Deserialize(r); + } + else + { + if(resp.ErrorException != null) + throw resp.ErrorException; + else + Error = resp.ErrorMessage; + } + + return default(T); + } + + public TvdbMirrors GetMirrors() + { + return ProcessRequest(BuildGetMirrorsRequest()); + } + + /// + /// http://www.thetvdb.com/api/Updates.php?type=none + /// + /// + public TvdbServerTime GetServerTime() + { + return ProcessRequest(BuildGetServerTimeRequest()); + } + + /// + /// http://www.thetvdb.com/api/{apikey}/languages.xml + /// + /// + public List GetLanguages() + { + var root = ProcessRequest(BuildGetLanguagesRequest()); + if(root != null) + return root.Languages; + + return null; + } + + + /// + /// http://www.thetvdb.com/api/GetSeries.php?seriesname={series} + /// + /// + /// + public List SearchSeries(string search) + { + var root = ProcessRequest(BuildGetSearchSeriesRequest(search)); + if(root != null) + return root.Series; + + return null; + } + + /// + /// http://thetvdb.com/api/{apikey}/series/79349/en.xml + /// + /// + /// + /// + /// + public TvdbSeriesBase GetSeriesBaseRecord(string XMLMirror, int SeriesId, string Language) + { + if(string.IsNullOrEmpty(Language)) + Language = "en"; + + var root = ProcessRequest(XMLMirror, + BuildGetSeriesBaseRecordRequest(SeriesId, Language)); + if(root != null) + return root.Series; + + return null; + } + + public TvdbSeriesBase GetSeriesBaseRecord(string XMLMirror, int SeriesId) + { + return GetSeriesBaseRecord(XMLMirror, SeriesId, null); + } + + /// + /// http://thetvdb.com/api/{apikey}/series/79349/all/en.xml + /// + /// + /// + /// + /// + public TvdbSeriesFull GetSeriesFullRecord(string XMLMirror, int SeriesId, string Language) + { + if(string.IsNullOrEmpty(Language)) + Language = "en"; + + return ProcessRequest(XMLMirror, BuildGetSeriesFullRecordRequest(SeriesId, Language)); + } + + public TvdbSeriesFull GetSeriesFullRecord(string MirrorPath, int SeriesId) + { + return GetSeriesFullRecord(MirrorPath, SeriesId, null); + } + + /// + /// http://thetvdb.com/api/{apikey}/series/79349/banners.xml + /// + /// + /// + /// + public List GetSeriesBanners(string XMLMirror, int SeriesId) + { + var root = ProcessRequest(XMLMirror, BuildGetSeriesBannersRequest(SeriesId)); + if(root != null) + return root.Banners; + + return null; + } + + /// + /// http://thetvdb.com/api/{apikey}/series/79349/actors.xml + /// + /// + /// + /// + public List GetSeriesActors(string XMLMirror, int SeriesId) + { + var root = ProcessRequest(XMLMirror, BuildGetSeriesActorsRequest(SeriesId)); + if(root != null) + return root.Actors; + + return null; + } + + public TvdbEpisode GetEpisode(string XMLMirror, int EpisodeId, string Language) + { + if(string.IsNullOrEmpty(Language)) + Language = "en"; + + var root = ProcessRequest(XMLMirror, BuildGetEpisodeRequest(EpisodeId, Language)); + if(root != null) + return root.Episode; + + return null; + } + + public TvdbEpisode GetEpisode(string XMLMirror, int EpisodeId) + { + return GetEpisode(XMLMirror, EpisodeId, null); + } + + public TvdbEpisode GetSeriesEpisode(string XMLMirror, int SeriesId, int SeasonNum, int EpisodeNum, + string Language) + { + if(string.IsNullOrEmpty(Language)) + Language = "en"; + + var root = ProcessRequest(XMLMirror, + BuildGetSeriesEpisodeRequest(SeriesId, SeasonNum, EpisodeNum, + Language)); + if(root != null) + return root.Episode; + + return null; + } + + public TvdbEpisode GetSeriesEpisode(string XMLMirror, int SeriesId, int SeasonNum, int EpisodeNum) + { + return GetSeriesEpisode(XMLMirror, SeriesId, SeasonNum, EpisodeNum, null); + } + + public TvdbUpdates GetUpdates(string XMLMirror, TvdbUpdatePeriod Period) + { + return ProcessRequest(XMLMirror, BuildGetUpdatesRequest(Period)); + } + + public TvdbUpdateItems GetUpdatesSince(string XMLMirror, Int64 LastTime) + { + return ProcessRequest(XMLMirror, BuildGetUpdatesSinceRequest(LastTime)); + } + } +} diff --git a/NzbDrone.Core/Tvdb/Tvdb.cs b/NzbDrone.Core/Tvdb/Tvdb.cs new file mode 100644 index 000000000..4f4fabefc --- /dev/null +++ b/NzbDrone.Core/Tvdb/Tvdb.cs @@ -0,0 +1,205 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using RestSharp; + +namespace NzbDrone.Core.Tvdb +{ + public partial class Tvdb + { + private const string BASE_URL = "http://www.thetvdb.com/api"; + + public string ApiKey { get; set; } + public string Error { get; set; } + + /// + /// String representation of response content + /// + public string ResponseContent { get; set; } + + /// + /// Dictionary of Header values in response + /// http://help.themoviedb.org/kb/api/content-versioning + /// + public Dictionary ResponseHeaders { get; set; } + +#if !WINDOWS_PHONE + /// + /// Proxy to use for requests made. Passed on to underying WebRequest if set. + /// + public IWebProxy Proxy { get; set; } +#endif + + /// + /// Timeout in milliseconds to use for requests made. + /// + public int? Timeout { get; set; } + + public Tvdb(string apiKey) + { + ApiKey = apiKey; + Error = null; + Timeout = null; + } + + #region Helper methods + + public static string GetImageUrl(string BannerMirror, string filename) + { + return string.Format("{0}/banners/{1}", BannerMirror, filename); + } + +#if !WINDOWS_PHONE + public static byte[] GetImage(string BannerMirror, string filename) + { + return GetImage(GetImageUrl(BannerMirror, filename)); + } + + public static byte[] GetImage(string url) + { + return new WebClient().DownloadData(url); + } +#endif + + #endregion + + #region Build Requests + + private RestRequest BuildGetMirrorsRequest(object UserState = null) + { + var request = new RestRequest("{apikey}/mirrors.xml", Method.GET); + request.AddUrlSegment("apikey", ApiKey); + if(UserState != null) + request.UserState = UserState; + + return request; + } + + private static RestRequest BuildGetServerTimeRequest(object UserState = null) + { + var request = new RestRequest("Updates.php", Method.GET); + request.AddParameter("type", "none"); + if(UserState != null) + request.UserState = UserState; + + return request; + } + + private RestRequest BuildGetLanguagesRequest(object UserState = null) + { + var request = new RestRequest("{apikey}/languages.xml", Method.GET); + request.AddUrlSegment("apikey", ApiKey); + if(UserState != null) + request.UserState = UserState; + + return request; + } + + private static RestRequest BuildGetSearchSeriesRequest(string search, object UserState = null) + { + var request = new RestRequest("GetSeries.php", Method.GET); + request.AddParameter("seriesname", search); + if(UserState != null) + request.UserState = UserState; + + return request; + } + + private RestRequest BuildGetSeriesBaseRecordRequest(int SeriesId, string Language, object UserState = null) + { + var request = new RestRequest("api/{apikey}/series/{id}/{lang}.xml"); + request.AddUrlSegment("apikey", ApiKey); + request.AddUrlSegment("id", SeriesId.ToString()); + request.AddUrlSegment("lang", Language); + if(UserState != null) + request.UserState = UserState; + + return request; + } + + private RestRequest BuildGetSeriesFullRecordRequest(int SeriesId, string Language, object UserState = null) + { + var request = new RestRequest("api/{apikey}/series/{id}/all/{lang}.xml"); + request.AddUrlSegment("apikey", ApiKey); + request.AddUrlSegment("id", SeriesId.ToString()); + request.AddUrlSegment("lang", Language); + if(UserState != null) + request.UserState = UserState; + + return request; + } + + private RestRequest BuildGetSeriesBannersRequest(int SeriesId, object UserState = null) + { + var request = new RestRequest("api/{apikey}/series/{id}/banners.xml"); + request.AddUrlSegment("apikey", ApiKey); + request.AddUrlSegment("id", SeriesId.ToString()); + if(UserState != null) + request.UserState = UserState; + + return request; + } + + private RestRequest BuildGetSeriesActorsRequest(int SeriesId, object UserState = null) + { + var request = new RestRequest("api/{apikey}/series/{id}/actors.xml"); + request.AddUrlSegment("apikey", ApiKey); + request.AddUrlSegment("id", SeriesId.ToString()); + if(UserState != null) + request.UserState = UserState; + + return request; + } + + private RestRequest BuildGetEpisodeRequest(int EpisodeId, string Language, object UserState = null) + { + var request = new RestRequest("api/{apikey}/episodes/{id}/{lang}.xml"); + request.AddUrlSegment("apikey", ApiKey); + request.AddUrlSegment("id", EpisodeId.ToString()); + request.AddUrlSegment("lang", Language); + if(UserState != null) + request.UserState = UserState; + + return request; + } + + private RestRequest BuildGetSeriesEpisodeRequest(int SeriesId, int SeasonNum, int EpisodeNum, string Language, + object UserState = null) + { + var request = new RestRequest("api/{apikey}/series/{id}/default/{season}/{episode}/{lang}.xml"); + request.AddUrlSegment("apikey", ApiKey); + request.AddUrlSegment("id", SeriesId.ToString()); + request.AddUrlSegment("season", SeasonNum.ToString()); + request.AddUrlSegment("episode", EpisodeNum.ToString()); + request.AddUrlSegment("lang", Language); + if(UserState != null) + request.UserState = UserState; + + return request; + } + + private RestRequest BuildGetUpdatesRequest(TvdbUpdatePeriod Period, object UserState = null) + { + var request = new RestRequest("api/{apikey}/updates/updates_{period}.xml"); + request.AddUrlSegment("apikey", ApiKey); + request.AddUrlSegment("period", Period.ToString()); + if(UserState != null) + request.UserState = UserState; + + return request; + } + + private static RestRequest BuildGetUpdatesSinceRequest(Int64 LastTime, object UserState = null) + { + var request = new RestRequest("api/Updates.php?type=all&time={time}"); + request.AddUrlSegment("time", LastTime.ToString()); + if(UserState != null) + request.UserState = UserState; + + return request; + } + + #endregion + } +} diff --git a/NzbDrone.Core/Tvdb/TvdbActor.cs b/NzbDrone.Core/Tvdb/TvdbActor.cs new file mode 100644 index 000000000..c6487e6f6 --- /dev/null +++ b/NzbDrone.Core/Tvdb/TvdbActor.cs @@ -0,0 +1,36 @@ +using System.Collections.Generic; +using System.Linq; +using System.Xml.Serialization; + +namespace NzbDrone.Core.Tvdb +{ + [XmlRoot(ElementName = "Actors")] + public class TvdbActorRoot + { + public TvdbActorRoot() + { + Actors = new List(); + } + + [XmlElement(ElementName = "Actor")] + public List Actors { get; set; } + } + + public class TvdbActor + { + [XmlElement] + public int id { get; set; } + + [XmlElement] + public string Image { get; set; } + + [XmlElement] + public string Name { get; set; } + + [XmlElement] + public string Role { get; set; } + + [XmlElement] + public int SortOrder { get; set; } + } +} diff --git a/NzbDrone.Core/Tvdb/TvdbAsyncResult.cs b/NzbDrone.Core/Tvdb/TvdbAsyncResult.cs new file mode 100644 index 000000000..4bb64b31e --- /dev/null +++ b/NzbDrone.Core/Tvdb/TvdbAsyncResult.cs @@ -0,0 +1,10 @@ +using System.Linq; + +namespace NzbDrone.Core.Tvdb +{ + public class TvdbAsyncResult + { + public T Data { get; set; } + public object UserState { get; set; } + } +} diff --git a/NzbDrone.Core/Tvdb/TvdbBanner.cs b/NzbDrone.Core/Tvdb/TvdbBanner.cs new file mode 100644 index 000000000..b1bc5f22a --- /dev/null +++ b/NzbDrone.Core/Tvdb/TvdbBanner.cs @@ -0,0 +1,86 @@ +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Xml.Serialization; + +namespace NzbDrone.Core.Tvdb +{ + [XmlRoot(ElementName = "Banners")] + public class TvdbBannerRoot + { + public TvdbBannerRoot() + { + Banners = new List(); + } + + [XmlElement(ElementName = "Banner")] + public List Banners { get; set; } + } + + public class TvdbBanner + { + [XmlElement] + public int id { get; set; } + + [XmlElement] + public string BannerPath { get; set; } + + [XmlElement] + public string BannerType { get; set; } + + [XmlElement] + public string BannerType2 { get; set; } + + [XmlElement] + public string Colors { get; set; } + + [XmlElement] + public string Language { get; set; } + + [XmlElement("Rating")] + public string RatingString + { + get { return Rating.HasValue ? Rating.Value.ToString() : null; } + set + { + double d; + if(double.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out d)) + Rating = d; + else + Rating = null; + } + } + + [XmlIgnore] + public double? Rating { get; set; } + + [XmlElement] + public int? RatingCount { get; set; } + + [XmlElement(ElementName = "SeriesName")] + public string SeriesNameString + { + get { return SeriesName.HasValue ? SeriesName.Value.ToString() : null; } + set + { + bool b; + if(bool.TryParse(value, out b)) + SeriesName = b; + else + SeriesName = null; + } + } + + [XmlIgnore] + public bool? SeriesName { get; set; } + + [XmlElement] + public string ThumbnailPath { get; set; } + + [XmlElement] + public string VignettePath { get; set; } + + [XmlElement] + public string Season { get; set; } + } +} diff --git a/NzbDrone.Core/Tvdb/TvdbEpisodes.cs b/NzbDrone.Core/Tvdb/TvdbEpisodes.cs new file mode 100644 index 000000000..0a960a06f --- /dev/null +++ b/NzbDrone.Core/Tvdb/TvdbEpisodes.cs @@ -0,0 +1,132 @@ +using System; +using System.Globalization; +using System.Linq; +using System.Xml.Serialization; + +namespace NzbDrone.Core.Tvdb +{ + [XmlRoot(ElementName = "Data")] + public class TvdbEpisodeRoot + { + [XmlElement] + public TvdbEpisode Episode { get; set; } + } + + public class TvdbEpisode + { + [XmlElement] + public int id { get; set; } + + [XmlElement] + public string Combined_episodenumber { get; set; } + + [XmlElement] + public string Combined_season { get; set; } + + [XmlElement] + public string DVD_chapter { get; set; } + + [XmlElement] + public string DVD_discid { get; set; } + + [XmlElement] + public string DVD_episodenumber { get; set; } + + [XmlElement] + public string DVD_season { get; set; } + + [XmlElement] + public string Director { get; set; } + + [XmlElement(ElementName = "EpImgFlag")] + public string EpImgFlagString + { + get { return EpImgFlag.HasValue ? EpImgFlag.Value.ToString() : null; } + set + { + int i; + if(int.TryParse(value, out i)) + EpImgFlag = i; + else + EpImgFlag = null; + } + } + + [XmlIgnore] + public int? EpImgFlag { get; set; } + + [XmlElement] + public string EpisodeName { get; set; } + + [XmlElement] + public int EpisodeNumber { get; set; } + + [XmlIgnore] + public DateTime FirstAired { get; set; } + + [XmlElement] + public string GuestStars { get; set; } + + [XmlElement] + public string IMDB_ID { get; set; } + + [XmlElement] + public string Language { get; set; } + + [XmlElement] + public string Overview { get; set; } + + [XmlElement] + public string ProductionCode { get; set; } + + [XmlElement("Rating")] + public string RatingString + { + get { return Rating.HasValue ? Rating.Value.ToString() : null; } + set + { + double d; + if(double.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out d)) + Rating = d; + else + Rating = null; + } + } + + [XmlIgnore] + public double? Rating { get; set; } + + [XmlElement] + public int? RatingCount { get; set; } + + [XmlElement] + public int SeasonNumber { get; set; } + + [XmlElement] + public string Writer { get; set; } + + [XmlElement] + public string absolute_number { get; set; } + + [XmlElement] + public string airsafter_season { get; set; } + + [XmlElement] + public string airsbefore_episode { get; set; } + + [XmlElement] + public string airsbefore_season { get; set; } + + [XmlElement] + public string filename { get; set; } + + [XmlElement] + public Int64 lastupdated { get; set; } + + [XmlElement] + public int? seasonid { get; set; } + + [XmlElement] + public int? seriesid { get; set; } + } +} diff --git a/NzbDrone.Core/Tvdb/TvdbLanguages.cs b/NzbDrone.Core/Tvdb/TvdbLanguages.cs new file mode 100644 index 000000000..03bf34b3e --- /dev/null +++ b/NzbDrone.Core/Tvdb/TvdbLanguages.cs @@ -0,0 +1,30 @@ +using System.Collections.Generic; +using System.Linq; +using System.Xml.Serialization; + +namespace NzbDrone.Core.Tvdb +{ + [XmlRoot(ElementName = "Languages")] + public class TvdbLanguagesRoot + { + public TvdbLanguagesRoot() + { + Languages = new List(); + } + + [XmlElement(ElementName = "Language")] + public List Languages { get; set; } + } + + public class TvdbLanguage + { + [XmlElement] + public int id { get; set; } + + [XmlElement] + public string name { get; set; } + + [XmlElement] + public string abbreviation { get; set; } + } +} diff --git a/NzbDrone.Core/Tvdb/TvdbMirrors.cs b/NzbDrone.Core/Tvdb/TvdbMirrors.cs new file mode 100644 index 000000000..13f0a4a12 --- /dev/null +++ b/NzbDrone.Core/Tvdb/TvdbMirrors.cs @@ -0,0 +1,40 @@ +using System.Collections.Generic; +using System.Linq; +using System.Xml.Serialization; + +namespace NzbDrone.Core.Tvdb +{ + [XmlRoot(ElementName = "Mirrors")] + public class TvdbMirrors + { + [XmlElement(ElementName = "Mirror")] + public List Mirrors { get; set; } + } + + public class TvdbMirror + { + [XmlElement] + public int id { get; set; } + + [XmlElement] + public string mirrorpath { get; set; } + + [XmlElement] + public int typemask { get; set; } + + public bool IsXMLMirror + { + get { return (typemask & 1) != 0; } + } + + public bool IsBannerMirror + { + get { return (typemask & 2) != 0; } + } + + public bool IsZipMirror + { + get { return (typemask & 4) != 0; } + } + } +} diff --git a/NzbDrone.Core/Tvdb/TvdbSeriesBase.cs b/NzbDrone.Core/Tvdb/TvdbSeriesBase.cs new file mode 100644 index 000000000..dc6290d45 --- /dev/null +++ b/NzbDrone.Core/Tvdb/TvdbSeriesBase.cs @@ -0,0 +1,131 @@ +using System; +using System.Globalization; +using System.Linq; +using System.Xml.Serialization; + +namespace NzbDrone.Core.Tvdb +{ + [XmlRoot(ElementName = "Data")] + public class TvdbSeriesRecordRoot + { + [XmlElement] + public TvdbSeriesBase Series { get; set; } + } + + public class TvdbSeriesBase + { + [XmlElement] + public int id { get; set; } + + [XmlElement] + public string Actors { get; set; } + + [XmlElement] + public string Airs_DayOfWeek { get; set; } + + [XmlElement] + public string Airs_Time { get; set; } + + [XmlElement] + public string ContentRating { get; set; } + + [XmlElement(ElementName = "FirstAired")] + public string FirstAiredString + { + get { return FirstAired.HasValue ? FirstAired.Value.ToString("yyyy-MM-dd") : null; } + set + { + DateTime d; + if(DateTime.TryParse(value, out d)) + FirstAired = d; + else + FirstAired = null; + } + } + + [XmlIgnore] + public DateTime? FirstAired { get; set; } + + [XmlElement] + public string Genre { get; set; } + + [XmlElement] + public string IMDB_ID { get; set; } + + [XmlElement] + public string Language { get; set; } + + [XmlElement] + public string Network { get; set; } + + [XmlElement] + public string Overview { get; set; } + + [XmlElement("Rating")] + public string RatingString + { + get { return Rating.HasValue ? Rating.Value.ToString() : null; } + set + { + double d; + if(double.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out d)) + Rating = d; + else + Rating = null; + } + } + + [XmlIgnore] + public double? Rating { get; set; } + + [XmlElement] + public int? RatingCount { get; set; } + + [XmlElement] + public int? Runtime { get; set; } + + [XmlElement] + public string SeriesIDString + { + get { return SeriesID.HasValue ? SeriesID.Value.ToString() : null; } + set + { + int i; + if(int.TryParse(value, out i)) + SeriesID = i; + else + SeriesID = null; + } + } + + [XmlIgnore] + public int? SeriesID { get; set; } + + [XmlElement] + public string SeriesName { get; set; } + + [XmlElement] + public string Status { get; set; } + + [XmlElement] + public string added { get; set; } + + [XmlElement] + public string addedBy { get; set; } + + [XmlElement] + public string banner { get; set; } + + [XmlElement] + public string fanart { get; set; } + + [XmlElement] + public Int64 lastupdated { get; set; } + + [XmlElement] + public string poster { get; set; } + + [XmlElement] + public string zap2it_id { get; set; } + } +} diff --git a/NzbDrone.Core/Tvdb/TvdbSeriesFull.cs b/NzbDrone.Core/Tvdb/TvdbSeriesFull.cs new file mode 100644 index 000000000..8f51eef3c --- /dev/null +++ b/NzbDrone.Core/Tvdb/TvdbSeriesFull.cs @@ -0,0 +1,21 @@ +using System.Collections.Generic; +using System.Linq; +using System.Xml.Serialization; + +namespace NzbDrone.Core.Tvdb +{ + [XmlRoot(ElementName = "Data")] + public class TvdbSeriesFull + { + public TvdbSeriesFull() + { + Episodes = new List(); + } + + [XmlElement] + public TvdbSeriesBase Series { get; set; } + + [XmlElement(ElementName = "Episode")] + public List Episodes { get; set; } + } +} diff --git a/NzbDrone.Core/Tvdb/TvdbSeriesSearch.cs b/NzbDrone.Core/Tvdb/TvdbSeriesSearch.cs new file mode 100644 index 000000000..cfb13db32 --- /dev/null +++ b/NzbDrone.Core/Tvdb/TvdbSeriesSearch.cs @@ -0,0 +1,18 @@ +using System.Collections.Generic; +using System.Linq; +using System.Xml.Serialization; + +namespace NzbDrone.Core.Tvdb +{ + [XmlRoot(ElementName = "Data")] + public class TvdbSeriesSearchRoot + { + public TvdbSeriesSearchRoot() + { + Series = new List(); + } + + [XmlElement(ElementName = "Series")] + public List Series { get; set; } + } +} diff --git a/NzbDrone.Core/Tvdb/TvdbSeriesSearchItem.cs b/NzbDrone.Core/Tvdb/TvdbSeriesSearchItem.cs new file mode 100644 index 000000000..8411416a0 --- /dev/null +++ b/NzbDrone.Core/Tvdb/TvdbSeriesSearchItem.cs @@ -0,0 +1,50 @@ +using System; +using System.Linq; +using System.Xml.Serialization; + +namespace NzbDrone.Core.Tvdb +{ + public class TvdbSeriesSearchItem + { + [XmlElement] + public int id { get; set; } + + [XmlElement] + public int seriesid { get; set; } + + [XmlElement] + public string language { get; set; } + + [XmlElement] + public string SeriesName { get; set; } + + [XmlElement] + public string banner { get; set; } + + [XmlElement] + public string Overview { get; set; } + + [XmlElement(ElementName = "FirstAired")] + public string FirstAiredString + { + get { return FirstAired.HasValue ? FirstAired.Value.ToString("yyyy-MM-dd") : null; } + set + { + DateTime d; + if(DateTime.TryParse(value, out d)) + FirstAired = d; + else + FirstAired = null; + } + } + + [XmlIgnore] + public DateTime? FirstAired { get; set; } + + [XmlElement] + public string IMDB_ID { get; set; } + + [XmlElement] + public string zap2it_id { get; set; } + } +} \ No newline at end of file diff --git a/NzbDrone.Core/Tvdb/TvdbServerTime.cs b/NzbDrone.Core/Tvdb/TvdbServerTime.cs new file mode 100644 index 000000000..8bac42dea --- /dev/null +++ b/NzbDrone.Core/Tvdb/TvdbServerTime.cs @@ -0,0 +1,13 @@ +using System; +using System.Linq; +using System.Xml.Serialization; + +namespace NzbDrone.Core.Tvdb +{ + [XmlRoot(ElementName = "Items")] + public class TvdbServerTime + { + [XmlElement] + public Int64 Time { get; set; } + } +} diff --git a/NzbDrone.Core/Tvdb/TvdbUpdate.cs b/NzbDrone.Core/Tvdb/TvdbUpdate.cs new file mode 100644 index 000000000..5c4c11aae --- /dev/null +++ b/NzbDrone.Core/Tvdb/TvdbUpdate.cs @@ -0,0 +1,86 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Xml.Serialization; + +namespace NzbDrone.Core.Tvdb +{ + public enum TvdbUpdatePeriod + { + day, + week, + month + }; + + [XmlRoot(ElementName = "Data")] + public class TvdbUpdates + { + public TvdbUpdates() + { + Series = new List(); + } + + [XmlAttribute] + public Int64 time { get; set; } + + [XmlElement(ElementName = "Series")] + public List Series { get; set; } + + [XmlElement(ElementName = "Episode")] + public List Episodes { get; set; } + + [XmlElement(ElementName = "Banner")] + public List Banners { get; set; } + } + + public class TvdbUpdateSeries + { + [XmlElement] + public int id { get; set; } + + [XmlElement] + public Int64 time { get; set; } + } + + public class TvdbUpdateEpisode + { + [XmlElement] + public int id { get; set; } + + [XmlElement] + public int Series { get; set; } + + [XmlElement] + public Int64 time { get; set; } + } + + public class TvdbUpdateBanner + { + /// + /// fanart, poster, season, series, episode, actors + /// + [XmlElement] + public string type { get; set; } + + [XmlElement] + public string format { get; set; } + + [XmlElement] + public int Series { get; set; } + + /// + /// Only appears for season banners + /// + [XmlElement] + public int? SeasonNum { get; set; } + + [XmlElement] + public string language { get; set; } + + [XmlElement] + public string path { get; set; } + + [XmlElement] + public Int64 time { get; set; } + } +} diff --git a/NzbDrone.Core/Tvdb/TvdbUpdateItems.cs b/NzbDrone.Core/Tvdb/TvdbUpdateItems.cs new file mode 100644 index 000000000..66ec26fd2 --- /dev/null +++ b/NzbDrone.Core/Tvdb/TvdbUpdateItems.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Xml.Serialization; + +namespace NzbDrone.Core.Tvdb +{ + [XmlRoot(ElementName = "Items")] + public class TvdbUpdateItems + { + public TvdbUpdateItems() + { + Series = new List(); + Episodes = new List(); + } + + [XmlElement] + public Int64 Time { get; set; } + + [XmlElement(ElementName = "Series")] + public List Series { get; set; } + + [XmlElement(ElementName = "Episode")] + public List Episodes { get; set; } + } +} diff --git a/NzbDrone.Core/packages.config b/NzbDrone.Core/packages.config index b10865175..3eef4794a 100644 --- a/NzbDrone.Core/packages.config +++ b/NzbDrone.Core/packages.config @@ -11,6 +11,7 @@ + diff --git a/NzbDrone.Web/Controllers/AddSeriesController.cs b/NzbDrone.Web/Controllers/AddSeriesController.cs index 415298dcb..beff7c071 100644 --- a/NzbDrone.Web/Controllers/AddSeriesController.cs +++ b/NzbDrone.Web/Controllers/AddSeriesController.cs @@ -91,7 +91,7 @@ namespace NzbDrone.Web.Controllers if (tvdbResult != null) { title = tvdbResult.SeriesName; - seriesId = tvdbResult.Id; + seriesId = tvdbResult.id; } result.ExistingSeries.Add(new Tuple(folder, title, seriesId)); @@ -147,33 +147,8 @@ namespace NzbDrone.Web.Controllers [JsonErrorFilter] public JsonResult LookupSeries(string term) { - try - { - var tvDbResults = _tvDbProvider.SearchSeries(term).Select(r => new TvDbSearchResultModel - { - Id = r.Id, - Title = r.SeriesName, - DisplayedTitle = r.FirstAired.Year > 1900 && !r.SeriesName.EndsWith("(" + r.FirstAired.Year + ")") - ? string.Format("{0} ({1})", r.SeriesName, r.FirstAired.Year) - : r.SeriesName, - Banner = r.Banner.BannerPath, - Url = String.Format("http://www.thetvdb.com/?tab=series&id={0}", r.Id) - }).ToList(); - - return Json(tvDbResults, JsonRequestBehavior.AllowGet); - } - - catch (TvdbNotAvailableException ex) - { - logger.WarnException("Unable to lookup series on TheTVDB", ex); - return JsonNotificationResult.Info("Lookup Failed", "TheTVDB is not available at this time."); - } - catch (Exception ex) - { - logger.WarnException("Unknown Error when looking up series on TheTVDB", ex); - return JsonNotificationResult.Info("Lookup Failed", "Unknown error while connecting to TheTVDB"); - } + return JsonNotificationResult.Info("Lookup Failed", "Unknown error while connecting to TheTVDB"); }