Skip to content

Commit

Permalink
Daily Episode Support #2
Browse files Browse the repository at this point in the history
This commit adds support for handling series episodes containing a date
in the filenme instead of season/episode numbers
  • Loading branch information
softworkz committed Dec 13, 2015
1 parent 5a6535e commit 418ceb9
Show file tree
Hide file tree
Showing 5 changed files with 323 additions and 140 deletions.
18 changes: 17 additions & 1 deletion MediaBrowser.Controller/Entities/TV/Episode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace MediaBrowser.Controller.Entities.TV
/// <summary>
/// Class Episode
/// </summary>
public class Episode : Video, IHasLookupInfo<EpisodeInfo>, IHasSeries
public class Episode : Video, IHasLookupInfo<EpisodeInfo>, IHasLookupInfo<DailyEpisodeInfo>, IHasSeries
{
/// <summary>
/// Gets the season in which it aired.
Expand Down Expand Up @@ -293,6 +293,22 @@ public EpisodeInfo GetLookupInfo()
return id;
}

DailyEpisodeInfo IHasLookupInfo<DailyEpisodeInfo>.GetLookupInfo()
{
var id = GetItemLookupInfo<DailyEpisodeInfo>();

var series = Series;

if (series != null)
{
id.SeriesProviderIds = series.ProviderIds;
}

id.AiredDate = this.PremiereDate;

return id;
}

public override bool BeforeMetadataRefresh()
{
var hasChanges = base.BeforeMetadataRefresh();
Expand Down
1 change: 1 addition & 0 deletions MediaBrowser.Controller/MediaBrowser.Controller.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@
<Compile Include="Providers\DirectoryService.cs" />
<Compile Include="Providers\DynamicImageInfo.cs" />
<Compile Include="Providers\DynamicImageResponse.cs" />
<Compile Include="Providers\DailyEpisodeInfo.cs" />
<Compile Include="Providers\EpisodeInfo.cs" />
<Compile Include="Providers\ExtraInfo.cs" />
<Compile Include="Providers\ExtraSource.cs" />
Expand Down
17 changes: 17 additions & 0 deletions MediaBrowser.Controller/Providers/DailyEpisodeInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;

namespace MediaBrowser.Controller.Providers
{
public class DailyEpisodeInfo : ItemLookupInfo
{
public Dictionary<string, string> SeriesProviderIds { get; set; }

public DateTime? AiredDate { get; set; }

public DailyEpisodeInfo()
{
SeriesProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
}
}
}
175 changes: 170 additions & 5 deletions MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ namespace MediaBrowser.Providers.TV
/// <summary>
/// Class RemoteEpisodeProvider
/// </summary>
class TvdbEpisodeProvider : IRemoteMetadataProvider<Episode, EpisodeInfo>, IItemIdentityProvider<EpisodeInfo>, IHasChangeMonitor
class TvdbEpisodeProvider : IRemoteMetadataProvider<Episode, EpisodeInfo>, IRemoteMetadataProvider<Episode, DailyEpisodeInfo>, IItemIdentityProvider<EpisodeInfo>, IHasChangeMonitor
{
private static readonly string FullIdKey = MetadataProviders.Tvdb + "-Full";

Expand Down Expand Up @@ -54,7 +54,7 @@ public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(EpisodeInfo
var searchNumbers = new EpisodeNumbers();
searchNumbers.EpisodeNumber = searchInfo.IndexNumber.Value;
searchNumbers.SeasonNumber = searchInfo.ParentIndexNumber;
searchNumbers.EpisodeNumberEnd = searchInfo.IndexNumberEnd ?? searchNumbers.EpisodeNumber;
searchNumbers.EpisodeNumberEnd = searchInfo.IndexNumberEnd ?? searchNumbers.EpisodeNumber;

try
{
Expand Down Expand Up @@ -90,6 +90,47 @@ public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(EpisodeInfo
return list;
}

public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(DailyEpisodeInfo searchInfo, CancellationToken cancellationToken)
{
var list = new List<RemoteSearchResult>();

if (TvdbSeriesProvider.IsValidSeries(searchInfo.SeriesProviderIds) && searchInfo.AiredDate.HasValue)
{
var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, searchInfo.SeriesProviderIds);

try
{
var metadataResult = FetchEpisodeDataByAiredDate(searchInfo, seriesDataPath, cancellationToken);

if (metadataResult != null)
{
var item = metadataResult.Item;

list.Add(new RemoteSearchResult
{
IndexNumber = item.IndexNumber,
Name = item.Name,
ParentIndexNumber = item.ParentIndexNumber,
PremiereDate = searchInfo.AiredDate.Value,
ProductionYear = searchInfo.AiredDate.Value.Year,
ProviderIds = item.ProviderIds,
SearchProviderName = Name
});
}
}
catch (FileNotFoundException)
{
// Don't fail the provider because this will just keep on going and going.
}
catch (DirectoryNotFoundException)
{
// Don't fail the provider because this will just keep on going and going.
}
}

return list;
}

public string Name
{
get { return "TheTVDB"; }
Expand Down Expand Up @@ -118,7 +159,7 @@ public async Task<MetadataResult<Episode>> GetMetadata(EpisodeInfo searchInfo, C
var seasonOffset = TvdbSeriesProvider.GetSeriesOffset(searchInfo.SeriesProviderIds) ?? 0;
searchNumbers.SeasonNumber = identity.Value.SeasonIndex + seasonOffset;
searchNumbers.EpisodeNumberEnd = identity.Value.EpisodeNumberEnd ?? searchNumbers.EpisodeNumber;

try
{
result = FetchEpisodeData(searchInfo, searchNumbers, seriesDataPath, cancellationToken);
Expand All @@ -139,7 +180,7 @@ public async Task<MetadataResult<Episode>> GetMetadata(EpisodeInfo searchInfo, C
var searchNumbers = new EpisodeNumbers();
searchNumbers.EpisodeNumber = searchInfo.IndexNumber.Value;
searchNumbers.SeasonNumber = searchInfo.ParentIndexNumber;
searchNumbers.EpisodeNumberEnd = searchInfo.IndexNumberEnd ?? searchNumbers.EpisodeNumber;
searchNumbers.EpisodeNumberEnd = searchInfo.IndexNumberEnd ?? searchNumbers.EpisodeNumber;

try
{
Expand All @@ -162,6 +203,12 @@ public async Task<MetadataResult<Episode>> GetMetadata(EpisodeInfo searchInfo, C
return result;
}

public async Task<MetadataResult<Episode>> GetMetadata(DailyEpisodeInfo searchInfo, CancellationToken cancellationToken)
{
// Not yet sure if we need that in certain cases...
throw new NotImplementedException();
}

public bool HasChanged(IHasMetadata item, IDirectoryService directoryService, DateTime date)
{
// Only enable for virtual items
Expand Down Expand Up @@ -352,6 +399,30 @@ private MetadataResult<Episode> FetchEpisodeData(EpisodeInfo id, EpisodeNumbers
return result;
}

/// <summary>
/// Fetches the episode data.
/// </summary>
/// <param name="id">The identifier.</param>
/// <param name="searchNumbers">The search numbers.</param>
/// <param name="seriesDataPath">The series data path.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{System.Boolean}.</returns>
private MetadataResult<Episode> FetchEpisodeDataByAiredDate(DailyEpisodeInfo id, string seriesDataPath, CancellationToken cancellationToken)
{
string file;

try
{
file = Path.Combine(seriesDataPath, string.Format("{0}.xml", id.MetadataLanguage));
var result = GetEpisodeInfoByAiredDate(id.AiredDate.Value, file, cancellationToken);
return result;
}
catch (FileNotFoundException)
{
throw;
}
}

private readonly CultureInfo _usCulture = new CultureInfo("en-US");

private void FetchMainEpisodeInfo(MetadataResult<Episode> result, string xmlFile, CancellationToken cancellationToken)
Expand All @@ -370,7 +441,7 @@ private void FetchMainEpisodeInfo(MetadataResult<Episode> result, string xmlFile
}))
{
reader.MoveToContent();

result.ResetPeople();

// Loop through each element
Expand Down Expand Up @@ -639,6 +710,100 @@ private void FetchMainEpisodeInfo(MetadataResult<Episode> result, string xmlFile
}
}

private MetadataResult<Episode> GetEpisodeInfoByAiredDate(DateTime airedDate, string xmlFile, CancellationToken cancellationToken)
{
using (var streamReader = new StreamReader(xmlFile, Encoding.UTF8))
{
// Use XmlReader for best performance
using (var reader = XmlReader.Create(streamReader, new XmlReaderSettings
{
CheckCharacters = false,
IgnoreProcessingInstructions = true,
IgnoreComments = true,
ValidationType = ValidationType.None
}))
{
reader.MoveToContent();

string episodeNumber = string.Empty;
string seasonNumber = string.Empty;
bool found = false;

// Loop through each element
while (reader.Read())
{
cancellationToken.ThrowIfCancellationRequested();

if (found && reader.NodeType == XmlNodeType.EndElement && reader.Name == "Episode")
{
var result = new MetadataResult<Episode>()
{
Item = new Episode
{
IndexNumber = int.Parse(episodeNumber),
ParentIndexNumber = int.Parse(seasonNumber),
PremiereDate = airedDate
}
};

return result;
}

if (reader.NodeType == XmlNodeType.Element)
{
switch (reader.Name)
{
case "Episode":
{
episodeNumber = string.Empty;
seasonNumber = string.Empty;
break;
}

case "FirstAired":
{
var val = reader.ReadElementContentAsString();

if (!string.IsNullOrWhiteSpace(val))
{
DateTime date;
if (DateTime.TryParse(val, out date))
{
if (date.Date == airedDate)
{
found = true;
}
}
}

break;
}

case "EpisodeNumber":
{
episodeNumber = reader.ReadElementContentAsString();
break;
}

case "SeasonNumber":
{
seasonNumber = reader.ReadElementContentAsString();
break;
}


default:
reader.Skip();
break;
}
}
}
}
}

return null;
}

private void AddPeople<T>(MetadataResult<T> result, string val, string personType)
{
// Sometimes tvdb actors have leading spaces
Expand Down
Loading

0 comments on commit 418ceb9

Please sign in to comment.