mirror of
https://github.com/Sonarr/Sonarr.git
synced 2024-10-30 15:32:31 +01:00
Fixed: Replaced trakt with tvdb as data source
This commit is contained in:
parent
0f56bfac2f
commit
19f5427dbf
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
/*
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using FluentAssertions;
|
||||
@ -134,3 +135,4 @@ namespace NzbDrone.Core.Test.MetadataSourceTests
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
@ -0,0 +1,138 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Core.MediaCover;
|
||||
using NzbDrone.Core.MetadataSource;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.Test.Common;
|
||||
using NzbDrone.Test.Common.Categories;
|
||||
|
||||
namespace NzbDrone.Core.Test.MetadataSourceTests
|
||||
{
|
||||
[TestFixture]
|
||||
[IntegrationTest]
|
||||
public class TvdbDataProxyFixture : CoreTest<TvDbProxy>
|
||||
{
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
UseRealHttp();
|
||||
}
|
||||
|
||||
[TestCase("The Simpsons", "The Simpsons")]
|
||||
[TestCase("South Park", "South Park")]
|
||||
[TestCase("Franklin & Bash", "Franklin & Bash")]
|
||||
[TestCase("House", "House")]
|
||||
[TestCase("Mr. D", "Mr. D")]
|
||||
[TestCase("Rob & Big", "Rob & Big")]
|
||||
[TestCase("M*A*S*H", "M*A*S*H")]
|
||||
//[TestCase("imdb:tt0436992", "Doctor Who (2005)")]
|
||||
//[TestCase("tvdb:78804", "Doctor Who (2005)")]
|
||||
public void successful_search(string title, string expected)
|
||||
{
|
||||
var result = Subject.SearchForNewSeries(title);
|
||||
|
||||
result.Should().NotBeEmpty();
|
||||
|
||||
result[0].Title.Should().Be(expected);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void no_search_result()
|
||||
{
|
||||
var result = Subject.SearchForNewSeries(Guid.NewGuid().ToString());
|
||||
result.Should().BeEmpty();
|
||||
}
|
||||
|
||||
[TestCase(75978, "Family Guy")]
|
||||
[TestCase(83462, "Castle (2009)")]
|
||||
[TestCase(266189, "The Blacklist")]
|
||||
public void should_be_able_to_get_series_detail(Int32 tvdbId, String title)
|
||||
{
|
||||
var details = Subject.GetSeriesInfo(tvdbId);
|
||||
|
||||
ValidateSeries(details.Item1);
|
||||
ValidateEpisodes(details.Item2);
|
||||
|
||||
details.Item1.Title.Should().Be(title);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void getting_details_of_invalid_series()
|
||||
{
|
||||
Assert.Throws<WebException>(() => Subject.GetSeriesInfo(Int32.MaxValue));
|
||||
|
||||
//ExceptionVerification.ExpectedWarns(1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_have_period_at_start_of_title_slug()
|
||||
{
|
||||
var details = Subject.GetSeriesInfo(79099);
|
||||
|
||||
details.Item1.TitleSlug.Should().Be("dothack");
|
||||
}
|
||||
|
||||
private void ValidateSeries(Series series)
|
||||
{
|
||||
series.Should().NotBeNull();
|
||||
series.Title.Should().NotBeNullOrWhiteSpace();
|
||||
series.CleanTitle.Should().Be(Parser.Parser.CleanSeriesTitle(series.Title));
|
||||
series.SortTitle.Should().Be(SeriesTitleNormalizer.Normalize(series.Title, series.TvdbId));
|
||||
series.Overview.Should().NotBeNullOrWhiteSpace();
|
||||
series.AirTime.Should().NotBeNullOrWhiteSpace();
|
||||
series.FirstAired.Should().HaveValue();
|
||||
series.FirstAired.Value.Kind.Should().Be(DateTimeKind.Utc);
|
||||
series.Images.Should().NotBeEmpty();
|
||||
series.ImdbId.Should().NotBeNullOrWhiteSpace();
|
||||
series.Network.Should().NotBeNullOrWhiteSpace();
|
||||
series.Runtime.Should().BeGreaterThan(0);
|
||||
series.TitleSlug.Should().NotBeNullOrWhiteSpace();
|
||||
//series.TvRageId.Should().BeGreaterThan(0);
|
||||
series.TvdbId.Should().BeGreaterThan(0);
|
||||
}
|
||||
|
||||
private void ValidateEpisodes(List<Episode> episodes)
|
||||
{
|
||||
episodes.Should().NotBeEmpty();
|
||||
|
||||
var episodeGroup = episodes.GroupBy(e => e.SeasonNumber.ToString("000") + e.EpisodeNumber.ToString("000"));
|
||||
episodeGroup.Should().OnlyContain(c => c.Count() == 1);
|
||||
|
||||
episodes.Should().Contain(c => c.SeasonNumber > 0);
|
||||
episodes.Should().Contain(c => !string.IsNullOrWhiteSpace(c.Overview));
|
||||
|
||||
foreach (var episode in episodes)
|
||||
{
|
||||
ValidateEpisode(episode);
|
||||
|
||||
//if atleast one episdoe has title it means parse it working.
|
||||
episodes.Should().Contain(c => !string.IsNullOrWhiteSpace(c.Title));
|
||||
}
|
||||
}
|
||||
|
||||
private void ValidateEpisode(Episode episode)
|
||||
{
|
||||
episode.Should().NotBeNull();
|
||||
|
||||
//TODO: Is there a better way to validate that episode number or season number is greater than zero?
|
||||
(episode.EpisodeNumber + episode.SeasonNumber).Should().NotBe(0);
|
||||
|
||||
episode.Should().NotBeNull();
|
||||
|
||||
if (episode.AirDateUtc.HasValue)
|
||||
{
|
||||
episode.AirDateUtc.Value.Kind.Should().Be(DateTimeKind.Utc);
|
||||
}
|
||||
|
||||
episode.Images.Any(i => i.CoverType == MediaCoverTypes.Screenshot && i.Url.Contains("-940."))
|
||||
.Should()
|
||||
.BeFalse();
|
||||
}
|
||||
}
|
||||
}
|
@ -227,6 +227,7 @@
|
||||
<Compile Include="MediaFiles\EpisodeImport\Specifications\UpgradeSpecificationFixture.cs" />
|
||||
<Compile Include="MediaFiles\ImportApprovedEpisodesFixture.cs" />
|
||||
<Compile Include="MediaFiles\MediaFileRepositoryFixture.cs" />
|
||||
<Compile Include="MetadataSourceTests\TvdbDataProxyFixture.cs" />
|
||||
<Compile Include="MetadataSourceTests\TraktSearchSeriesComparerFixture.cs" />
|
||||
<Compile Include="OrganizerTests\FileNameBuilderTests\CleanTitleFixture.cs" />
|
||||
<Compile Include="OrganizerTests\FileNameBuilderTests\EpisodeTitleCollapseFixture.cs" />
|
||||
|
@ -26,7 +26,7 @@ namespace NzbDrone.Core.Test.TvTests
|
||||
{
|
||||
UseRealHttp();
|
||||
|
||||
_gameOfThrones = Mocker.Resolve<TraktProxy>().GetSeriesInfo(121361);//Game of thrones
|
||||
_gameOfThrones = Mocker.Resolve<TvDbProxy>().GetSeriesInfo(121361);//Game of thrones
|
||||
|
||||
// Remove specials.
|
||||
_gameOfThrones.Item2.RemoveAll(v => v.SeasonNumber == 0);
|
||||
|
@ -13,7 +13,7 @@ using Episode = NzbDrone.Core.Tv.Episode;
|
||||
|
||||
namespace NzbDrone.Core.MetadataSource
|
||||
{
|
||||
public class TraktProxy : ISearchForNewSeries, IProvideSeriesInfo
|
||||
public class TraktProxy //: ISearchForNewSeries, IProvideSeriesInfo
|
||||
{
|
||||
private readonly Logger _logger;
|
||||
private readonly IHttpClient _httpClient;
|
||||
|
342
src/NzbDrone.Core/MetadataSource/TvDbProxy.cs
Normal file
342
src/NzbDrone.Core/MetadataSource/TvDbProxy.cs
Normal file
@ -0,0 +1,342 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Web;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Core.MediaCover;
|
||||
using NzbDrone.Core.MetadataSource.Trakt;
|
||||
using NzbDrone.Core.Tv;
|
||||
using TVDBSharp.Models.Enums;
|
||||
|
||||
namespace NzbDrone.Core.MetadataSource
|
||||
{
|
||||
public class TvDbProxy : ISearchForNewSeries, IProvideSeriesInfo
|
||||
{
|
||||
private readonly Logger _logger;
|
||||
private readonly IHttpClient _httpClient;
|
||||
private static readonly Regex CollapseSpaceRegex = new Regex(@"\s+", RegexOptions.Compiled);
|
||||
private static readonly Regex InvalidSearchCharRegex = new Regex(@"(?:\*|\(|\)|'|!|@|\+)", RegexOptions.Compiled);
|
||||
private static readonly Regex ExpandCamelCaseRegEx = new Regex(@"(?<!^|[A-Z]\.?|[^\w.])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])|(?<!^|\d\.?|[^\w.])(?=\d)", RegexOptions.IgnorePatternWhitespace | RegexOptions.Compiled);
|
||||
|
||||
private readonly HttpRequestBuilder _requestBuilder;
|
||||
private TVDBSharp.TVDB tvdb;
|
||||
|
||||
public TvDbProxy(Logger logger, IHttpClient httpClient)
|
||||
{
|
||||
_requestBuilder = new HttpRequestBuilder("http://api.trakt.tv/{path}/{resource}.json/bc3c2c460f22cbb01c264022b540e191");
|
||||
_logger = logger;
|
||||
_httpClient = httpClient;
|
||||
|
||||
|
||||
tvdb = new TVDBSharp.TVDB("5D2D188E86E07F4F");
|
||||
}
|
||||
|
||||
private IEnumerable<TVDBSharp.Models.Show> SearchTrakt(string title)
|
||||
{
|
||||
/* Common.Http.HttpRequest request;
|
||||
|
||||
var lowerTitle = title.ToLowerInvariant();
|
||||
|
||||
if (lowerTitle.StartsWith("tvdb:") || lowerTitle.StartsWith("tvdbid:") /*|| lowerTitle.StartsWith("slug:")#1#)
|
||||
{
|
||||
var slug = lowerTitle.Split(':')[1].Trim();
|
||||
|
||||
if (slug.IsNullOrWhiteSpace() || slug.Any(char.IsWhiteSpace))
|
||||
{
|
||||
return Enumerable.Empty<TVDBSharp.Models.Show>();
|
||||
}
|
||||
|
||||
request = _requestBuilder.Build("/{slug}/extended");
|
||||
|
||||
request.AddSegment("path", "show");
|
||||
request.AddSegment("resource", "summary");
|
||||
request.AddSegment("slug", GetSearchTerm(slug));
|
||||
|
||||
return new List<Show> { _httpClient.Get<Show>(request).Resource };
|
||||
}
|
||||
|
||||
if (lowerTitle.StartsWith("imdb:") || lowerTitle.StartsWith("imdbid:"))
|
||||
{
|
||||
var slug = lowerTitle.Split(':')[1].TrimStart('t').Trim();
|
||||
|
||||
if (slug.IsNullOrWhiteSpace() || !slug.All(char.IsDigit) || slug.Length < 7)
|
||||
{
|
||||
return Enumerable.Empty<Show>();
|
||||
}
|
||||
|
||||
title = "tt" + slug;
|
||||
}*/
|
||||
|
||||
|
||||
return tvdb.Search(GetSearchTerm(title));
|
||||
|
||||
}
|
||||
|
||||
public List<Series> SearchForNewSeries(string title)
|
||||
{
|
||||
try
|
||||
{
|
||||
var tvdbSeries = SearchTrakt(title.Trim());
|
||||
|
||||
var series = tvdbSeries.Select(MapSeries).ToList();
|
||||
|
||||
series.Sort(new TraktSearchSeriesComparer(title));
|
||||
|
||||
return series;
|
||||
}
|
||||
catch (Common.Http.HttpException)
|
||||
{
|
||||
throw new TraktException("Search for '{0}' failed. Unable to communicate with Trakt.", title);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.WarnException(ex.Message, ex);
|
||||
throw new TraktException("Search for '{0}' failed. Invalid response received from Trakt.", title);
|
||||
}
|
||||
}
|
||||
|
||||
public Tuple<Series, List<Tv.Episode>> GetSeriesInfo(int tvdbSeriesId)
|
||||
{
|
||||
|
||||
var request = _requestBuilder.Build("/{tvdbId}/extended");
|
||||
|
||||
request.AddSegment("path", "show");
|
||||
request.AddSegment("resource", "summary");
|
||||
request.AddSegment("tvdbId", tvdbSeriesId.ToString());
|
||||
|
||||
var tvdbSeries = tvdb.GetShow(tvdbSeriesId);
|
||||
|
||||
var episodes = tvdbSeries.Episodes.Select(MapEpisode);
|
||||
|
||||
episodes = RemoveDuplicates(episodes);
|
||||
|
||||
var series = MapSeries(tvdbSeries);
|
||||
|
||||
return new Tuple<Series, List<Tv.Episode>>(series, episodes.ToList());
|
||||
}
|
||||
|
||||
private static IEnumerable<Tv.Episode> RemoveDuplicates(IEnumerable<Tv.Episode> episodes)
|
||||
{
|
||||
//http://support.trakt.tv/forums/188762-general/suggestions/4430690-anger-management-duplicate-episode
|
||||
var episodeGroup = episodes.GroupBy(e => e.SeasonNumber.ToString("0000") + e.EpisodeNumber.ToString("0000"));
|
||||
return episodeGroup.Select(g => g.First());
|
||||
}
|
||||
|
||||
private static Series MapSeries(TVDBSharp.Models.Show show)
|
||||
{
|
||||
var series = new Series();
|
||||
series.TvdbId = show.Id;
|
||||
//series.TvRageId = show.tvrage_id;
|
||||
series.ImdbId = show.ImdbId;
|
||||
series.Title = show.Name;
|
||||
series.CleanTitle = Parser.Parser.CleanSeriesTitle(show.Name);
|
||||
series.SortTitle = SeriesTitleNormalizer.Normalize(show.Name, show.Id);
|
||||
|
||||
if (show.FirstAired != null)
|
||||
{
|
||||
series.Year = show.FirstAired.Value.Year;
|
||||
series.FirstAired = show.FirstAired.Value.ToUniversalTime();
|
||||
}
|
||||
|
||||
series.Overview = show.Description;
|
||||
|
||||
if (show.Runtime != null)
|
||||
{
|
||||
series.Runtime = show.Runtime.Value;
|
||||
}
|
||||
|
||||
series.Network = show.Network;
|
||||
|
||||
if (show.AirTime != null)
|
||||
{
|
||||
series.AirTime = show.AirTime.Value.ToString();
|
||||
}
|
||||
|
||||
series.TitleSlug = GenerateSlug(show.Name);
|
||||
series.Status = GetSeriesStatus(show.Status);
|
||||
series.Ratings = GetRatings(show.RatingCount, show.Rating);
|
||||
series.Genres = show.Genres;
|
||||
series.Certification = show.ContentRating.ToString().ToUpper();
|
||||
series.Actors = new List<Tv.Actor>();
|
||||
series.Seasons = GetSeasons(show);
|
||||
|
||||
series.Images.Add(new MediaCover.MediaCover { CoverType = MediaCoverTypes.Banner, Url = show.Banner.ToString() });
|
||||
series.Images.Add(new MediaCover.MediaCover { CoverType = MediaCoverTypes.Poster, Url = show.Poster.ToString() });
|
||||
series.Images.Add(new MediaCover.MediaCover { CoverType = MediaCoverTypes.Fanart, Url = show.Fanart.ToString() });
|
||||
|
||||
return series;
|
||||
}
|
||||
|
||||
private static Tv.Episode MapEpisode(TVDBSharp.Models.Episode traktEpisode)
|
||||
{
|
||||
var episode = new Tv.Episode();
|
||||
episode.Overview = traktEpisode.Description;
|
||||
episode.SeasonNumber = traktEpisode.SeasonNumber;
|
||||
episode.EpisodeNumber = traktEpisode.EpisodeNumber;
|
||||
episode.Title = traktEpisode.Title;
|
||||
|
||||
if (traktEpisode.FirstAired != null)
|
||||
{
|
||||
episode.AirDate = traktEpisode.FirstAired.Value.ToString("yyyy-MM-dd");
|
||||
episode.AirDateUtc = traktEpisode.FirstAired.Value.ToUniversalTime();
|
||||
}
|
||||
|
||||
episode.Ratings = GetRatings(traktEpisode.RatingCount, traktEpisode.Rating);
|
||||
|
||||
//Don't include series fanart images as episode screenshot
|
||||
episode.Images.Add(new MediaCover.MediaCover(MediaCoverTypes.Screenshot, traktEpisode.EpisodeImage.ToString()));
|
||||
|
||||
return episode;
|
||||
}
|
||||
|
||||
private static string GetPosterThumbnailUrl(string posterUrl)
|
||||
{
|
||||
if (posterUrl.Contains("poster-small.jpg") || posterUrl.Contains("poster-dark.jpg")) return posterUrl;
|
||||
|
||||
var extension = Path.GetExtension(posterUrl);
|
||||
var withoutExtension = posterUrl.Substring(0, posterUrl.Length - extension.Length);
|
||||
return withoutExtension + "-300" + extension;
|
||||
}
|
||||
|
||||
private static SeriesStatusType GetSeriesStatus(Status status)
|
||||
{
|
||||
if (status == Status.Ended)
|
||||
{
|
||||
return SeriesStatusType.Ended;
|
||||
}
|
||||
|
||||
return SeriesStatusType.Continuing;
|
||||
}
|
||||
|
||||
private static DateTime? FromIso(string iso)
|
||||
{
|
||||
DateTime result;
|
||||
|
||||
if (!DateTime.TryParse(iso, out result))
|
||||
return null;
|
||||
|
||||
return result.ToUniversalTime();
|
||||
}
|
||||
|
||||
private static string FromIsoToString(string iso)
|
||||
{
|
||||
if (String.IsNullOrWhiteSpace(iso)) return null;
|
||||
|
||||
var match = Regex.Match(iso, @"^\d{4}\W\d{2}\W\d{2}");
|
||||
|
||||
if (!match.Success) return null;
|
||||
|
||||
return match.Captures[0].Value;
|
||||
}
|
||||
|
||||
private static string GetSearchTerm(string phrase)
|
||||
{
|
||||
phrase = phrase.RemoveAccent();
|
||||
phrase = InvalidSearchCharRegex.Replace(phrase, "");
|
||||
|
||||
// if (!phrase.Any(char.IsWhiteSpace) && phrase.Any(char.IsUpper) && phrase.Any(char.IsLower) && phrase.Length > 4)
|
||||
// {
|
||||
// phrase = ExpandCamelCaseRegEx.Replace(phrase, " ");
|
||||
// }
|
||||
|
||||
phrase = CollapseSpaceRegex.Replace(phrase, " ").Trim();
|
||||
phrase = phrase.Trim('-');
|
||||
|
||||
phrase = HttpUtility.UrlEncode(phrase.ToLower());
|
||||
|
||||
return phrase;
|
||||
}
|
||||
|
||||
private static int GetYear(int year, int firstAired)
|
||||
{
|
||||
if (year > 1969) return year;
|
||||
|
||||
if (firstAired == 0) return DateTime.Today.Year;
|
||||
|
||||
return year;
|
||||
}
|
||||
|
||||
private static Tv.Ratings GetRatings(int ratingCount, double? rating)
|
||||
{
|
||||
|
||||
var result = new Tv.Ratings { Votes = ratingCount };
|
||||
|
||||
if (rating != null)
|
||||
{
|
||||
result.Percentage = (int)(rating.Value * 100);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static List<Tv.Actor> GetActors(People people)
|
||||
{
|
||||
if (people == null)
|
||||
{
|
||||
return new List<Tv.Actor>();
|
||||
}
|
||||
|
||||
return GetActors(people.actors).ToList();
|
||||
}
|
||||
|
||||
private static IEnumerable<Tv.Actor> GetActors(IEnumerable<Trakt.Actor> trakcActors)
|
||||
{
|
||||
foreach (var traktActor in trakcActors)
|
||||
{
|
||||
var actor = new Tv.Actor
|
||||
{
|
||||
Name = traktActor.name,
|
||||
Character = traktActor.character,
|
||||
};
|
||||
|
||||
actor.Images.Add(new MediaCover.MediaCover(MediaCoverTypes.Headshot, traktActor.images.headshot));
|
||||
|
||||
yield return actor;
|
||||
}
|
||||
}
|
||||
|
||||
private static List<Tv.Season> GetSeasons(TVDBSharp.Models.Show show)
|
||||
{
|
||||
var seasons = new List<Tv.Season>();
|
||||
|
||||
foreach (var seasonNumber in show.Episodes.Select(c => c.SeasonNumber).Distinct().OrderByDescending(c => c))
|
||||
{
|
||||
var season = new Tv.Season
|
||||
{
|
||||
SeasonNumber = seasonNumber
|
||||
};
|
||||
|
||||
/* if (season.images != null)
|
||||
{
|
||||
season.Images.Add(new MediaCover.MediaCover(MediaCoverTypes.Poster, season.images.poster));
|
||||
}*/
|
||||
|
||||
seasons.Add(season);
|
||||
}
|
||||
|
||||
return seasons;
|
||||
}
|
||||
|
||||
|
||||
private static readonly Regex RemoveRegex = new Regex(@"[^\w-]", RegexOptions.Compiled);
|
||||
|
||||
public static string GenerateSlug(string showTitle)
|
||||
{
|
||||
if (showTitle.StartsWith("."))
|
||||
{
|
||||
showTitle = "dot" + showTitle.Substring(1);
|
||||
}
|
||||
showTitle = showTitle.Replace(" ", "-");
|
||||
showTitle = showTitle.Replace("&", "and");
|
||||
showTitle = RemoveRegex.Replace(showTitle, String.Empty);
|
||||
showTitle = showTitle.RemoveAccent();
|
||||
showTitle = showTitle.ToLowerInvariant();
|
||||
|
||||
return showTitle;
|
||||
}
|
||||
}
|
||||
}
|
@ -595,6 +595,7 @@
|
||||
<Compile Include="Messaging\Events\IEventAggregator.cs" />
|
||||
<Compile Include="Messaging\Events\IHandle.cs" />
|
||||
<Compile Include="Messaging\IProcessMessage.cs" />
|
||||
<Compile Include="MetadataSource\TvDbProxy.cs" />
|
||||
<Compile Include="MetadataSource\TraktSearchSeriesComparer.cs" />
|
||||
<Compile Include="Metadata\Consumers\MediaBrowser\MediaBrowserMetadata.cs" />
|
||||
<Compile Include="Metadata\Consumers\MediaBrowser\MediaBrowserMetadataSettings.cs" />
|
||||
@ -899,6 +900,10 @@
|
||||
<Project>{F2BE0FDF-6E47-4827-A420-DD4EF82407F8}</Project>
|
||||
<Name>NzbDrone.Common</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\TVDBSharp\TVDBSharp.csproj">
|
||||
<Project>{0cc493d7-0a9f-4199-9615-0a977945d716}</Project>
|
||||
<Name>TVDBSharp</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="..\..\Logo\64.png">
|
||||
|
@ -176,6 +176,11 @@ namespace NzbDrone.Core.Tv
|
||||
}
|
||||
}
|
||||
|
||||
if (series.TvRageId == 0)
|
||||
{
|
||||
series.TvRageId = storedSeries.TvRageId;
|
||||
}
|
||||
|
||||
var updatedSeries = _seriesRepository.Update(series);
|
||||
_eventAggregator.PublishEvent(new SeriesEditedEvent(updatedSeries, storedSeries));
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 2013
|
||||
VisualStudioVersion = 12.0.31101.0
|
||||
VisualStudioVersion = 12.0.30723.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{57A04B72-8088-4F75-A582-1158CF8291F7}"
|
||||
EndProject
|
||||
@ -82,6 +82,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LogentriesCore", "Logentrie
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LogentriesNLog", "LogentriesNLog\LogentriesNLog.csproj", "{9DC31DE3-79FF-47A8-96B4-6BA18F6BB1CB}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TVDBSharp", "TVDBSharp\TVDBSharp.csproj", "{0CC493D7-0A9F-4199-9615-0A977945D716}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x86 = Debug|x86
|
||||
@ -262,6 +264,12 @@ Global
|
||||
{9DC31DE3-79FF-47A8-96B4-6BA18F6BB1CB}.Mono|x86.Build.0 = Release|x86
|
||||
{9DC31DE3-79FF-47A8-96B4-6BA18F6BB1CB}.Release|x86.ActiveCfg = Release|x86
|
||||
{9DC31DE3-79FF-47A8-96B4-6BA18F6BB1CB}.Release|x86.Build.0 = Release|x86
|
||||
{0CC493D7-0A9F-4199-9615-0A977945D716}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{0CC493D7-0A9F-4199-9615-0A977945D716}.Debug|x86.Build.0 = Debug|x86
|
||||
{0CC493D7-0A9F-4199-9615-0A977945D716}.Mono|x86.ActiveCfg = Release|x86
|
||||
{0CC493D7-0A9F-4199-9615-0A977945D716}.Mono|x86.Build.0 = Release|x86
|
||||
{0CC493D7-0A9F-4199-9615-0A977945D716}.Release|x86.ActiveCfg = Release|x86
|
||||
{0CC493D7-0A9F-4199-9615-0A977945D716}.Release|x86.Build.0 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@ -294,6 +302,7 @@ Global
|
||||
{411A9E0E-FDC6-4E25-828A-0C2CD1CD96F8} = {F6E3A728-AE77-4D02-BAC8-82FBC1402DDA}
|
||||
{90D6E9FC-7B88-4E1B-B018-8FA742274558} = {F6E3A728-AE77-4D02-BAC8-82FBC1402DDA}
|
||||
{9DC31DE3-79FF-47A8-96B4-6BA18F6BB1CB} = {F6E3A728-AE77-4D02-BAC8-82FBC1402DDA}
|
||||
{0CC493D7-0A9F-4199-9615-0A977945D716} = {F6E3A728-AE77-4D02-BAC8-82FBC1402DDA}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
EnterpriseLibraryConfigurationToolBinariesPath = packages\Unity.2.1.505.0\lib\NET35;packages\Unity.2.1.505.2\lib\NET35
|
||||
|
6
src/TVDBSharp/App.config
Normal file
6
src/TVDBSharp/App.config
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
|
||||
</startup>
|
||||
</configuration>
|
279
src/TVDBSharp/Models/Builder.cs
Normal file
279
src/TVDBSharp/Models/Builder.cs
Normal file
@ -0,0 +1,279 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Xml.Linq;
|
||||
using TVDBSharp.Models.DAO;
|
||||
using TVDBSharp.Models.Enums;
|
||||
using TVDBSharp.Utilities;
|
||||
|
||||
namespace TVDBSharp.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides builder classes for complex entities.
|
||||
/// </summary>
|
||||
public class Builder
|
||||
{
|
||||
private const string UriPrefix = "http://thetvdb.com/banners/";
|
||||
private readonly IDataProvider _dataProvider;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new Builder object with the given <see cref="IDataProvider" />.
|
||||
/// </summary>
|
||||
/// <param name="dataProvider">The DataProvider used to retrieve XML responses.</param>
|
||||
public Builder(IDataProvider dataProvider)
|
||||
{
|
||||
_dataProvider = dataProvider;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Builds a show object from the given show ID.
|
||||
/// </summary>
|
||||
/// <param name="showID">ID of the show to serialize into a <see cref="Show" /> object.</param>
|
||||
/// <returns>Returns the Show object.</returns>
|
||||
public Show BuildShow(int showID)
|
||||
{
|
||||
var builder = new ShowBuilder(_dataProvider.GetShow(showID));
|
||||
return builder.GetResult();
|
||||
}
|
||||
|
||||
public Episode BuildEpisode(int episodeId, string lang)
|
||||
{
|
||||
var builder = new EpisodeBuilder(_dataProvider.GetEpisode(episodeId, lang).Descendants("Episode").First());
|
||||
return builder.GetResult();
|
||||
}
|
||||
|
||||
public Updates BuildUpdates(Interval interval)
|
||||
{
|
||||
var builder = new UpdatesBuilder(_dataProvider.GetUpdates(interval));
|
||||
return builder.GetResult();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a list of <see cref="Show" /> objects that match the given query.
|
||||
/// </summary>
|
||||
/// <param name="query">Query the search is performed with.</param>
|
||||
/// <param name="results">Maximal amount of shows the resultset should return.</param>
|
||||
/// <returns>Returns a list of show objects.</returns>
|
||||
public List<Show> Search(string query, int results)
|
||||
{
|
||||
var shows = new List<Show>();
|
||||
var doc = _dataProvider.Search(query);
|
||||
|
||||
foreach (var element in doc.Descendants("Series").Take(results))
|
||||
{
|
||||
var id = int.Parse(element.GetXmlData("seriesid"));
|
||||
|
||||
try
|
||||
{
|
||||
var response = _dataProvider.GetShow(id);
|
||||
shows.Add(new ShowBuilder(response).GetResult());
|
||||
}
|
||||
catch (WebException ex)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return shows;
|
||||
}
|
||||
|
||||
private static Uri GetBannerUri(string uriSuffix)
|
||||
{
|
||||
return new Uri(UriPrefix + uriSuffix, UriKind.Absolute);
|
||||
}
|
||||
|
||||
private class ShowBuilder
|
||||
{
|
||||
private readonly Show _show;
|
||||
|
||||
public ShowBuilder(XDocument doc)
|
||||
{
|
||||
_show = new Show();
|
||||
_show.Id = int.Parse(doc.GetSeriesData("id"));
|
||||
_show.ImdbId = doc.GetSeriesData("IMDB_ID");
|
||||
_show.Name = doc.GetSeriesData("SeriesName");
|
||||
_show.Language = doc.GetSeriesData("Language");
|
||||
_show.Network = doc.GetSeriesData("Network");
|
||||
_show.Description = doc.GetSeriesData("Overview");
|
||||
_show.Rating = string.IsNullOrWhiteSpace(doc.GetSeriesData("Rating"))
|
||||
? (double?) null
|
||||
: Convert.ToDouble(doc.GetSeriesData("Rating"),
|
||||
System.Globalization.CultureInfo.InvariantCulture);
|
||||
_show.RatingCount = string.IsNullOrWhiteSpace(doc.GetSeriesData("RatingCount"))
|
||||
? 0
|
||||
: Convert.ToInt32(doc.GetSeriesData("RatingCount"));
|
||||
_show.Runtime = string.IsNullOrWhiteSpace(doc.GetSeriesData("Runtime"))
|
||||
? (int?) null
|
||||
: Convert.ToInt32(doc.GetSeriesData("Runtime"));
|
||||
_show.Banner = GetBannerUri(doc.GetSeriesData("banner"));
|
||||
_show.Fanart = GetBannerUri(doc.GetSeriesData("fanart"));
|
||||
_show.LastUpdated = string.IsNullOrWhiteSpace(doc.GetSeriesData("lastupdated"))
|
||||
? (long?) null
|
||||
: Convert.ToInt64(doc.GetSeriesData("lastupdated"));
|
||||
_show.Poster = GetBannerUri(doc.GetSeriesData("poster"));
|
||||
_show.Zap2ItID = doc.GetSeriesData("zap2it_id");
|
||||
_show.FirstAired = string.IsNullOrWhiteSpace(doc.GetSeriesData("FirstAired"))
|
||||
? (DateTime?) null
|
||||
: Utils.ParseDate(doc.GetSeriesData("FirstAired"));
|
||||
_show.AirTime = string.IsNullOrWhiteSpace(doc.GetSeriesData("Airs_Time"))
|
||||
? (TimeSpan?) null
|
||||
: Utils.ParseTime(doc.GetSeriesData("Airs_Time"));
|
||||
_show.AirDay = string.IsNullOrWhiteSpace(doc.GetSeriesData("Airs_DayOfWeek"))
|
||||
? (Frequency?) null
|
||||
: (Frequency) Enum.Parse(typeof (Frequency), doc.GetSeriesData("Airs_DayOfWeek"));
|
||||
_show.Status = string.IsNullOrWhiteSpace(doc.GetSeriesData("Status"))
|
||||
? Status.Unknown
|
||||
: (Status) Enum.Parse(typeof (Status), doc.GetSeriesData("Status"));
|
||||
_show.ContentRating = Utils.GetContentRating(doc.GetSeriesData("ContentRating"));
|
||||
_show.Genres =
|
||||
new List<string>(doc.GetSeriesData("Genre")
|
||||
.Split(new[] {'|'}, StringSplitOptions.RemoveEmptyEntries));
|
||||
_show.Actors =
|
||||
new List<string>(doc.GetSeriesData("Actors")
|
||||
.Split(new[] {'|'}, StringSplitOptions.RemoveEmptyEntries));
|
||||
_show.Episodes = new EpisodesBuilder(doc).BuildEpisodes();
|
||||
}
|
||||
|
||||
public Show GetResult()
|
||||
{
|
||||
return _show;
|
||||
}
|
||||
}
|
||||
|
||||
public class EpisodeBuilder
|
||||
{
|
||||
private readonly Episode _episode;
|
||||
|
||||
public EpisodeBuilder(XElement episodeNode)
|
||||
{
|
||||
_episode = new Episode
|
||||
{
|
||||
Id = int.Parse(episodeNode.GetXmlData("id")),
|
||||
Title = episodeNode.GetXmlData("EpisodeName"),
|
||||
Description = episodeNode.GetXmlData("Overview"),
|
||||
EpisodeNumber = int.Parse(episodeNode.GetXmlData("EpisodeNumber")),
|
||||
Director = episodeNode.GetXmlData("Director"),
|
||||
EpisodeImage = GetBannerUri(episodeNode.GetXmlData("filename")),
|
||||
FirstAired =
|
||||
string.IsNullOrWhiteSpace(episodeNode.GetXmlData("FirstAired"))
|
||||
? (DateTime?) null
|
||||
: Utils.ParseDate(episodeNode.GetXmlData("FirstAired")),
|
||||
GuestStars =
|
||||
new List<string>(episodeNode.GetXmlData("GuestStars")
|
||||
.Split(new[] {'|'}, StringSplitOptions.RemoveEmptyEntries)),
|
||||
ImdbId = episodeNode.GetXmlData("IMDB_ID"),
|
||||
Language = episodeNode.GetXmlData("Language"),
|
||||
LastUpdated =
|
||||
string.IsNullOrWhiteSpace(episodeNode.GetXmlData("lastupdated"))
|
||||
? 0L
|
||||
: Convert.ToInt64(episodeNode.GetXmlData("lastupdated")),
|
||||
Rating =
|
||||
string.IsNullOrWhiteSpace(episodeNode.GetXmlData("Rating"))
|
||||
? (double?) null
|
||||
: Convert.ToDouble(episodeNode.GetXmlData("Rating"),
|
||||
System.Globalization.CultureInfo.InvariantCulture),
|
||||
RatingCount =
|
||||
string.IsNullOrWhiteSpace(episodeNode.GetXmlData("RatingCount"))
|
||||
? 0
|
||||
: Convert.ToInt32(episodeNode.GetXmlData("RatingCount")),
|
||||
SeasonId = int.Parse(episodeNode.GetXmlData("seasonid")),
|
||||
SeasonNumber = int.Parse(episodeNode.GetXmlData("SeasonNumber")),
|
||||
SeriesId = int.Parse(episodeNode.GetXmlData("seriesid")),
|
||||
ThumbHeight =
|
||||
string.IsNullOrWhiteSpace(episodeNode.GetXmlData("thumb_height"))
|
||||
? (int?) null
|
||||
: Convert.ToInt32(episodeNode.GetXmlData("thumb_height")),
|
||||
ThumbWidth =
|
||||
string.IsNullOrWhiteSpace(episodeNode.GetXmlData("thumb_width"))
|
||||
? (int?) null
|
||||
: Convert.ToInt32(episodeNode.GetXmlData("thumb_width")),
|
||||
TmsExport = episodeNode.GetXmlData("tms_export"),
|
||||
Writers =
|
||||
new List<string>(episodeNode.GetXmlData("Writer")
|
||||
.Split(new[] {'|'}, StringSplitOptions.RemoveEmptyEntries))
|
||||
};
|
||||
}
|
||||
|
||||
public Episode GetResult()
|
||||
{
|
||||
return _episode;
|
||||
}
|
||||
}
|
||||
|
||||
private class EpisodesBuilder
|
||||
{
|
||||
private readonly XDocument _doc;
|
||||
|
||||
public EpisodesBuilder(XDocument doc)
|
||||
{
|
||||
_doc = doc;
|
||||
}
|
||||
|
||||
public List<Episode> BuildEpisodes()
|
||||
{
|
||||
var result = new List<Episode>();
|
||||
|
||||
foreach (var episodeNode in _doc.Descendants("Episode"))
|
||||
{
|
||||
var episode = new EpisodeBuilder(episodeNode).GetResult();
|
||||
result.Add(episode);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public class UpdatesBuilder
|
||||
{
|
||||
private readonly Updates _updates;
|
||||
|
||||
public UpdatesBuilder(XDocument doc)
|
||||
{
|
||||
if (doc.Root != null)
|
||||
{
|
||||
_updates = new Updates
|
||||
{
|
||||
Time = int.Parse(doc.Root.Attribute("time").Value),
|
||||
UpdatedSeries = doc.Root.Elements("Series")
|
||||
.Select(elt => new UpdatedSerie
|
||||
{
|
||||
Id = int.Parse(elt.Element("id").Value),
|
||||
Time = int.Parse(elt.Element("time").Value)
|
||||
})
|
||||
.ToList(),
|
||||
UpdatedEpisodes = doc.Root.Elements("Episode")
|
||||
.Select(elt => new UpdatedEpisode
|
||||
{
|
||||
Id = int.Parse(elt.Element("id").Value),
|
||||
SerieId = int.Parse(elt.Element("Series").Value),
|
||||
Time = int.Parse(elt.Element("time").Value)
|
||||
})
|
||||
.ToList(),
|
||||
UpdatedBanners = doc.Root.Elements("Banner")
|
||||
.Select(elt => new UpdatedBanner
|
||||
{
|
||||
SerieId = int.Parse(elt.Element("Series").Value),
|
||||
Format = elt.Element("format").Value,
|
||||
Language =
|
||||
elt.Elements("language").Select(n => n.Value).FirstOrDefault() ?? string.Empty,
|
||||
Path = elt.Element("path").Value,
|
||||
Type = elt.Element("type").Value,
|
||||
SeasonNumber = elt.Elements("SeasonNumber").Any()
|
||||
? int.Parse(elt.Element("SeasonNumber").Value)
|
||||
: (int?) null,
|
||||
Time = int.Parse(elt.Element("time").Value)
|
||||
})
|
||||
.ToList()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public Updates GetResult()
|
||||
{
|
||||
return _updates;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
43
src/TVDBSharp/Models/DAO/DataProvider.cs
Normal file
43
src/TVDBSharp/Models/DAO/DataProvider.cs
Normal file
@ -0,0 +1,43 @@
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Xml.Linq;
|
||||
using TVDBSharp.Models.Enums;
|
||||
|
||||
namespace TVDBSharp.Models.DAO
|
||||
{
|
||||
/// <summary>
|
||||
/// Standard implementation of the <see cref="IDataProvider" /> interface.
|
||||
/// </summary>
|
||||
public class DataProvider : IDataProvider
|
||||
{
|
||||
public string ApiKey { get; set; }
|
||||
private const string BaseUrl = "http://thetvdb.com";
|
||||
|
||||
public XDocument GetShow(int showID)
|
||||
{
|
||||
return GetXDocumentFromUrl(string.Format("{0}/api/{1}/series/{2}/all/", BaseUrl, ApiKey, showID));
|
||||
}
|
||||
|
||||
public XDocument GetEpisode(int episodeId, string lang)
|
||||
{
|
||||
return GetXDocumentFromUrl(string.Format("{0}/api/{1}/episodes/{2}/{3}.xml", BaseUrl, ApiKey, episodeId, lang));
|
||||
}
|
||||
|
||||
public XDocument GetUpdates(Interval interval)
|
||||
{
|
||||
return GetXDocumentFromUrl(string.Format("{0}/api/{1}/updates/updates_{2}.xml", BaseUrl, ApiKey, IntervalHelpers.Print(interval)));
|
||||
}
|
||||
|
||||
public XDocument Search(string query)
|
||||
{
|
||||
return GetXDocumentFromUrl(string.Format("{0}/api/GetSeries.php?seriesname={1}", BaseUrl, query));
|
||||
}
|
||||
|
||||
private static XDocument GetXDocumentFromUrl(string url)
|
||||
{
|
||||
using (var web = new WebClient())
|
||||
using (var memoryStream = new MemoryStream(web.DownloadData(url)))
|
||||
return XDocument.Load(memoryStream);
|
||||
}
|
||||
}
|
||||
}
|
45
src/TVDBSharp/Models/DAO/IDataProvider.cs
Normal file
45
src/TVDBSharp/Models/DAO/IDataProvider.cs
Normal file
@ -0,0 +1,45 @@
|
||||
using System.Xml.Linq;
|
||||
using TVDBSharp.Models.Enums;
|
||||
|
||||
namespace TVDBSharp.Models.DAO
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines a Dataprovider API.
|
||||
/// </summary>
|
||||
public interface IDataProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// The API key provided by TVDB.
|
||||
/// </summary>
|
||||
string ApiKey { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the show with the given id and returns the corresponding XML tree.
|
||||
/// </summary>
|
||||
/// <param name="showID">ID of the show you wish to lookup.</param>
|
||||
/// <returns>Returns an XML tree of the show object.</returns>
|
||||
XDocument GetShow(int showID);
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the episode with the given id and returns the corresponding XML tree.
|
||||
/// </summary>
|
||||
/// <param name="episodeId">ID of the episode to retrieve</param>
|
||||
/// <param name="lang">ISO 639-1 language code of the episode</param>
|
||||
/// <returns>XML tree of the episode object</returns>
|
||||
XDocument GetEpisode(int episodeId, string lang);
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves updates on tvdb (Shows, Episodes and Banners)
|
||||
/// </summary>
|
||||
/// <param name="interval">The interval for the updates</param>
|
||||
/// <returns>XML tree of the Updates object</returns>
|
||||
XDocument GetUpdates(Interval interval);
|
||||
|
||||
/// <summary>
|
||||
/// Returns an XML tree representing a search query for the given parameter.
|
||||
/// </summary>
|
||||
/// <param name="query">Query to perform the search with.</param>
|
||||
/// <returns>Returns an XML tree of a search result.</returns>
|
||||
XDocument Search(string query);
|
||||
}
|
||||
}
|
43
src/TVDBSharp/Models/Enums/ContentRating.cs
Normal file
43
src/TVDBSharp/Models/Enums/ContentRating.cs
Normal file
@ -0,0 +1,43 @@
|
||||
namespace TVDBSharp.Models.Enums
|
||||
{
|
||||
/// <summary>
|
||||
/// Different content ratings. View <c>http://en.wikipedia.org/wiki/TV_Parental_Guidelines</c> for more info.
|
||||
/// </summary>
|
||||
public enum ContentRating
|
||||
{
|
||||
/// <summary>
|
||||
/// Not suitable for children under 14.
|
||||
/// </summary>
|
||||
TV14,
|
||||
|
||||
/// <summary>
|
||||
/// This program contains material that parents may find unsuitable for younger children.
|
||||
/// </summary>
|
||||
TVPG,
|
||||
|
||||
/// <summary>
|
||||
/// This program is designed to be appropriate for all children.
|
||||
/// </summary>
|
||||
TVY,
|
||||
|
||||
/// <summary>
|
||||
/// This program is designed for children age 7 and above.
|
||||
/// </summary>
|
||||
TVY7,
|
||||
|
||||
/// <summary>
|
||||
/// Most parents would find this program suitable for all ages.
|
||||
/// </summary>
|
||||
TVG,
|
||||
|
||||
/// <summary>
|
||||
/// This program is specifically designed to be viewed by adults and therefore may be unsuitable for children under 17.
|
||||
/// </summary>
|
||||
TVMA,
|
||||
|
||||
/// <summary>
|
||||
/// Default value if no rating is given.
|
||||
/// </summary>
|
||||
Unknown
|
||||
}
|
||||
}
|
14
src/TVDBSharp/Models/Enums/Frequency.cs
Normal file
14
src/TVDBSharp/Models/Enums/Frequency.cs
Normal file
@ -0,0 +1,14 @@
|
||||
namespace TVDBSharp.Models.Enums
|
||||
{
|
||||
public enum Frequency
|
||||
{
|
||||
Monday,
|
||||
Tuesday,
|
||||
Wednesday,
|
||||
Thursday,
|
||||
Friday,
|
||||
Saturday,
|
||||
Sunday,
|
||||
Daily
|
||||
}
|
||||
}
|
32
src/TVDBSharp/Models/Enums/Interval.cs
Normal file
32
src/TVDBSharp/Models/Enums/Interval.cs
Normal file
@ -0,0 +1,32 @@
|
||||
using System;
|
||||
|
||||
namespace TVDBSharp.Models.Enums
|
||||
{
|
||||
public enum Interval
|
||||
{
|
||||
Day,
|
||||
Week,
|
||||
Month,
|
||||
All
|
||||
}
|
||||
|
||||
public static class IntervalHelpers
|
||||
{
|
||||
public static string Print(Interval interval)
|
||||
{
|
||||
switch (interval)
|
||||
{
|
||||
case Interval.Day:
|
||||
return "day";
|
||||
case Interval.Week:
|
||||
return "week";
|
||||
case Interval.Month:
|
||||
return "month";
|
||||
case Interval.All:
|
||||
return "all";
|
||||
default:
|
||||
throw new ArgumentException("Unsupported interval enum: " + interval);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
23
src/TVDBSharp/Models/Enums/Status.cs
Normal file
23
src/TVDBSharp/Models/Enums/Status.cs
Normal file
@ -0,0 +1,23 @@
|
||||
namespace TVDBSharp.Models.Enums
|
||||
{
|
||||
/// <summary>
|
||||
/// Describes the current status of a show.
|
||||
/// </summary>
|
||||
public enum Status
|
||||
{
|
||||
/// <summary>
|
||||
/// No more episodes are being released.
|
||||
/// </summary>
|
||||
Ended,
|
||||
|
||||
/// <summary>
|
||||
/// The show is ongoing.
|
||||
/// </summary>
|
||||
Continuing,
|
||||
|
||||
/// <summary>
|
||||
/// Default value if no status is specified.
|
||||
/// </summary>
|
||||
Unknown
|
||||
}
|
||||
}
|
111
src/TVDBSharp/Models/Episode.cs
Normal file
111
src/TVDBSharp/Models/Episode.cs
Normal file
@ -0,0 +1,111 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace TVDBSharp.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Entity describing an episode of a <see cref="Show" />show.
|
||||
/// </summary>
|
||||
public class Episode
|
||||
{
|
||||
/// <summary>
|
||||
/// Unique identifier for an episode.
|
||||
/// </summary>
|
||||
public int Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Director of the episode.
|
||||
/// </summary>
|
||||
public string Director { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// This episode's title.
|
||||
/// </summary>
|
||||
public string Title { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// This episode's number in the appropriate season.
|
||||
/// </summary>
|
||||
public int EpisodeNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// This episode's season.
|
||||
/// </summary>
|
||||
public int SeasonNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The date of the first time this episode has aired.
|
||||
/// </summary>
|
||||
public DateTime? FirstAired { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A list of guest stars.
|
||||
/// </summary>
|
||||
public List<string> GuestStars { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Unique identifier on IMDb.
|
||||
/// </summary>
|
||||
public string ImdbId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Main language spoken in the episode.
|
||||
/// </summary>
|
||||
public string Language { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A short description of the episode.
|
||||
/// </summary>
|
||||
public string Description { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Average rating as shown on IMDb.
|
||||
/// </summary>
|
||||
public double? Rating { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Amount of votes cast.
|
||||
/// </summary>
|
||||
public int RatingCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Writers(s) of the episode.
|
||||
/// </summary>
|
||||
public List<String> Writers { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Let me know if you find out what this is.
|
||||
/// </summary>
|
||||
public Uri EpisodeImage { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Timestamp of the last update to this episode.
|
||||
/// </summary>
|
||||
public long? LastUpdated { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Unique identifier of the season.
|
||||
/// </summary>
|
||||
public int SeasonId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Unique identifier of the show.
|
||||
/// </summary>
|
||||
public int SeriesId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Height dimension of the thumbnail in pixels.
|
||||
/// </summary>
|
||||
public int? ThumbHeight { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Width dimension of the thumbnail in pixels;
|
||||
/// </summary>
|
||||
public int? ThumbWidth { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Let me know if you find out what this is.
|
||||
/// </summary>
|
||||
public string TmsExport { get; set; }
|
||||
}
|
||||
}
|
122
src/TVDBSharp/Models/Show.cs
Normal file
122
src/TVDBSharp/Models/Show.cs
Normal file
@ -0,0 +1,122 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using TVDBSharp.Models.Enums;
|
||||
|
||||
namespace TVDBSharp.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Entity describing a show.
|
||||
/// </summary>
|
||||
public class Show
|
||||
{
|
||||
/// <summary>
|
||||
/// Unique identifier used by IMDb.
|
||||
/// </summary>
|
||||
public string ImdbId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Unique identifier used by TVDB and TVDBSharp.
|
||||
/// </summary>
|
||||
public int Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// List of all actors in the show.
|
||||
/// </summary>
|
||||
public List<string> Actors { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Day of the week when the show airs.
|
||||
/// </summary>
|
||||
public Frequency? AirDay { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Time of the day when the show airs.
|
||||
/// </summary>
|
||||
public TimeSpan? AirTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Rating of the content provided by an official organ.
|
||||
/// </summary>
|
||||
public ContentRating ContentRating { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The date the show aired for the first time.
|
||||
/// </summary>
|
||||
public DateTime? FirstAired { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A list of genres the show is associated with.
|
||||
/// </summary>
|
||||
public List<string> Genres { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Main language of the show.
|
||||
/// </summary>
|
||||
public string Language { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Network that broadcasts the show.
|
||||
/// </summary>
|
||||
public string Network { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A short overview of the show.
|
||||
/// </summary>
|
||||
public string Description { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Average rating as shown on IMDb.
|
||||
/// </summary>
|
||||
public double? Rating { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Amount of votes cast.
|
||||
/// </summary>
|
||||
public int RatingCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Let me know if you find out what this is.
|
||||
/// </summary>
|
||||
public int? Runtime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Name of the show.
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Current status of the show.
|
||||
/// </summary>
|
||||
public Status Status { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Link to the banner image.
|
||||
/// </summary>
|
||||
public Uri Banner { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Link to a fanart image.
|
||||
/// </summary>
|
||||
public Uri Fanart { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Timestamp of the latest update.
|
||||
/// </summary>
|
||||
public long? LastUpdated { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Let me know if you find out what this is.
|
||||
/// </summary>
|
||||
public Uri Poster { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// No clue
|
||||
/// </summary>
|
||||
public string Zap2ItID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A list of all episodes associated with this show.
|
||||
/// </summary>
|
||||
public List<Episode> Episodes { get; set; }
|
||||
}
|
||||
}
|
49
src/TVDBSharp/Models/Updates.cs
Normal file
49
src/TVDBSharp/Models/Updates.cs
Normal file
@ -0,0 +1,49 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace TVDBSharp.Models
|
||||
{
|
||||
public class Updates : UnixTimestampedObject
|
||||
{
|
||||
public List<UpdatedBanner> UpdatedBanners { get; set; }
|
||||
public List<UpdatedEpisode> UpdatedEpisodes { get; set; }
|
||||
public List<UpdatedSerie> UpdatedSeries { get; set; }
|
||||
}
|
||||
|
||||
public class UnixTimestampedObject
|
||||
{
|
||||
private static DateTime _startDate = new DateTime(1970, 1, 1);
|
||||
private int _unixTimestamp;
|
||||
|
||||
public DateTime Timestamp
|
||||
{
|
||||
get { return _startDate.AddSeconds(_unixTimestamp); }
|
||||
}
|
||||
|
||||
public int Time
|
||||
{
|
||||
set { _unixTimestamp = value; }
|
||||
}
|
||||
}
|
||||
|
||||
public class UpdatedSerie : UnixTimestampedObject
|
||||
{
|
||||
public int Id { get; set; }
|
||||
}
|
||||
|
||||
public class UpdatedEpisode : UnixTimestampedObject
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public int SerieId { get; set; }
|
||||
}
|
||||
|
||||
public class UpdatedBanner : UnixTimestampedObject
|
||||
{
|
||||
public int SerieId { get; set; }
|
||||
public string Format { get; set; }
|
||||
public string Language { get; set; }
|
||||
public string Path { get; set; }
|
||||
public string Type { get; set; }
|
||||
public int? SeasonNumber { get; set; }
|
||||
}
|
||||
}
|
39
src/TVDBSharp/Properties/AssemblyInfo.cs
Normal file
39
src/TVDBSharp/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,39 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
|
||||
[assembly: AssemblyTitle("TVDBSharp")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("TVDBSharp")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2014")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
|
||||
[assembly: Guid("c78961a8-afda-4a36-910b-bf5a090eebb3")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
72
src/TVDBSharp/TVDB.cs
Normal file
72
src/TVDBSharp/TVDB.cs
Normal file
@ -0,0 +1,72 @@
|
||||
using System.Collections.Generic;
|
||||
using TVDBSharp.Models;
|
||||
using TVDBSharp.Models.DAO;
|
||||
using TVDBSharp.Models.Enums;
|
||||
|
||||
namespace TVDBSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// The main class which will handle all user interaction.
|
||||
/// </summary>
|
||||
public class TVDB
|
||||
{
|
||||
private readonly IDataProvider _dataProvider;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance with the provided API key and dataProvider.
|
||||
/// </summary>
|
||||
/// <param name="apiKey">The API key provided by TVDB.</param>
|
||||
/// <param name="dataProvider">Specify your own <see cref="IDataProvider" /> instance.</param>
|
||||
public TVDB(string apiKey, IDataProvider dataProvider)
|
||||
{
|
||||
_dataProvider = dataProvider;
|
||||
_dataProvider.ApiKey = apiKey;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance with the provided API key and standard <see cref="IDataProvider" />.
|
||||
/// </summary>
|
||||
/// <param name="apiKey">The API key provided by TVDB.</param>
|
||||
public TVDB(string apiKey)
|
||||
{
|
||||
_dataProvider = new DataProvider {ApiKey = apiKey};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Search for a show in the database.
|
||||
/// </summary>
|
||||
/// <param name="query">Query that identifies the show.</param>
|
||||
/// <param name="results">Maximal amount of results in the returning set. Default is 5.</param>
|
||||
/// <returns>Returns a list of shows.</returns>
|
||||
public List<Show> Search(string query, int results = 5)
|
||||
{
|
||||
return new Builder(_dataProvider).Search(query, results);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a specific show based on its ID.
|
||||
/// </summary>
|
||||
/// <param name="showId">ID of the show.</param>
|
||||
/// <returns>Returns the corresponding show.</returns>
|
||||
public Show GetShow(int showId)
|
||||
{
|
||||
return new Builder(_dataProvider).BuildShow(showId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a specific episode based on its ID.
|
||||
/// </summary>
|
||||
/// <param name="episodeId">ID of the episode</param>
|
||||
/// <param name="lang">ISO 639-1 language code for the episode</param>
|
||||
/// <returns>The corresponding episode</returns>
|
||||
public Episode GetEpisode(int episodeId, string lang = "en")
|
||||
{
|
||||
return new Builder(_dataProvider).BuildEpisode(episodeId, lang);
|
||||
}
|
||||
|
||||
public Updates GetUpdates(Interval interval)
|
||||
{
|
||||
return new Builder(_dataProvider).BuildUpdates(interval);
|
||||
}
|
||||
}
|
||||
}
|
74
src/TVDBSharp/TVDBSharp.csproj
Normal file
74
src/TVDBSharp/TVDBSharp.csproj
Normal file
@ -0,0 +1,74 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{0CC493D7-0A9F-4199-9615-0A977945D716}</ProjectGuid>
|
||||
<ProjectGuid>{0CC493D7-0A9F-4199-9615-0A977945D716}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>TVDBSharp</RootNamespace>
|
||||
<AssemblyName>TVDBSharp</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<StartupObject />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\x86\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
||||
<OutputPath>bin\x86\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Models\Builder.cs" />
|
||||
<Compile Include="Models\DAO\DataProvider.cs" />
|
||||
<Compile Include="Models\DAO\IDataProvider.cs" />
|
||||
<Compile Include="Models\Enums\ContentRating.cs" />
|
||||
<Compile Include="Models\Enums\Frequency.cs" />
|
||||
<Compile Include="Models\Enums\Interval.cs" />
|
||||
<Compile Include="Models\Enums\Status.cs" />
|
||||
<Compile Include="Models\Episode.cs" />
|
||||
<Compile Include="Models\Show.cs" />
|
||||
<Compile Include="Models\Updates.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="TVDB.cs" />
|
||||
<Compile Include="Utilities\Extensions.cs" />
|
||||
<Compile Include="Utilities\Utils.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
58
src/TVDBSharp/Utilities/Extensions.cs
Normal file
58
src/TVDBSharp/Utilities/Extensions.cs
Normal file
@ -0,0 +1,58 @@
|
||||
using System.Xml.Linq;
|
||||
using System.Xml.Schema;
|
||||
|
||||
namespace TVDBSharp.Utilities
|
||||
{
|
||||
/// <summary>
|
||||
/// Extension methods used to simplify data extraction.
|
||||
/// </summary>
|
||||
public static class Extensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Retrieves a value from an XML tree representing a show.
|
||||
/// </summary>
|
||||
/// <param name="doc">XML tree representing a show.</param>
|
||||
/// <param name="element">Name of the element with the data.</param>
|
||||
/// <returns>Returns the value corresponding to the given element name.</returns>
|
||||
/// <exception cref="XmlSchemaException">Thrown when the element doesn't exist or the XML tree is incorrect.</exception>
|
||||
public static string GetSeriesData(this XDocument doc, string element)
|
||||
{
|
||||
var root = doc.Element("Data");
|
||||
if (root != null)
|
||||
{
|
||||
var xElement = root.Element("Series");
|
||||
if (xElement != null)
|
||||
{
|
||||
var result = xElement.Element(element);
|
||||
if (result != null)
|
||||
{
|
||||
return result.Value;
|
||||
}
|
||||
throw new XmlSchemaException("Could not find element <" + element + ">");
|
||||
}
|
||||
throw new XmlSchemaException("Could not find element <Series>");
|
||||
}
|
||||
throw new XmlSchemaException("Could not find element <Data>");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves a value from an XML tree.
|
||||
/// </summary>
|
||||
/// <param name="xmlObject">The given XML (sub)tree.</param>
|
||||
/// <param name="element">Name of the element with the data.</param>
|
||||
/// <returns>Returns the value corresponding to the given element name;</returns>
|
||||
/// <exception cref="XmlSchemaException">Thrown when the element doesn't exist.</exception>
|
||||
public static string GetXmlData(this XElement xmlObject, string element)
|
||||
{
|
||||
var result = xmlObject.Element(element);
|
||||
|
||||
return result != null ? result.Value : null;
|
||||
|
||||
// Removed in favor of returning a null value
|
||||
// This will allow us to catch a non-existing tag with the null-coalescing operator
|
||||
// Never trust the XML provider.
|
||||
|
||||
//throw new XmlSchemaException("Element <" + element + "> could not be found.");
|
||||
}
|
||||
}
|
||||
}
|
73
src/TVDBSharp/Utilities/Utils.cs
Normal file
73
src/TVDBSharp/Utilities/Utils.cs
Normal file
@ -0,0 +1,73 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using TVDBSharp.Models.Enums;
|
||||
|
||||
namespace TVDBSharp.Utilities
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides static utility methods.
|
||||
/// </summary>
|
||||
public static class Utils
|
||||
{
|
||||
/// <summary>
|
||||
/// Parses a string of format yyyy-MM-dd to a <see cref="DateTime" /> object.
|
||||
/// </summary>
|
||||
/// <param name="value">String to be parsed.</param>
|
||||
/// <returns>Returns a <see cref="DateTime" /> representation.</returns>
|
||||
public static DateTime ParseDate(string value)
|
||||
{
|
||||
DateTime date;
|
||||
DateTime.TryParseExact(value, "yyyy-MM-dd", CultureInfo.CurrentCulture, DateTimeStyles.AssumeLocal, out date);
|
||||
return date;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses a string of format hh:mm tt to a <see cref="TimeSpan" /> object.
|
||||
/// </summary>
|
||||
/// <param name="value">String to be parsed.</param>
|
||||
/// <returns>Returns a <see cref="TimeSpan" /> representation.</returns>
|
||||
public static TimeSpan ParseTime(string value)
|
||||
{
|
||||
DateTime date;
|
||||
|
||||
if (!DateTime.TryParse(value, out date))
|
||||
{
|
||||
return new TimeSpan();
|
||||
}
|
||||
return date.TimeOfDay;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Translates the incoming string to a <see cref="ContentRating" /> enum, if applicable.
|
||||
/// </summary>
|
||||
/// <param name="rating">The rating in string format.</param>
|
||||
/// <returns>Returns the appropriate <see cref="ContentRating" /> value.</returns>
|
||||
/// <exception cref="ArgumentException">Throws an exception if no conversion could be applied.</exception>
|
||||
public static ContentRating GetContentRating(string rating)
|
||||
{
|
||||
switch (rating)
|
||||
{
|
||||
case "TV-14":
|
||||
return ContentRating.TV14;
|
||||
|
||||
case "TV-PG":
|
||||
return ContentRating.TVPG;
|
||||
|
||||
case "TV-Y":
|
||||
return ContentRating.TVY;
|
||||
|
||||
case "TV-Y7":
|
||||
return ContentRating.TVY7;
|
||||
|
||||
case "TV-G":
|
||||
return ContentRating.TVG;
|
||||
|
||||
case "TV-MA":
|
||||
return ContentRating.TVMA;
|
||||
|
||||
default:
|
||||
return ContentRating.Unknown;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user