mirror of
https://github.com/jellyfin/jellyfin.git
synced 2024-09-07 03:48:06 +02:00
fixes #643 - Support episodes directly in series folder
This commit is contained in:
parent
d2332264b3
commit
61a78e2be9
2 changed files with 64 additions and 5 deletions
|
@ -149,16 +149,34 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||||
return IndexNumber != null ? IndexNumber.Value.ToString("0000") : Name;
|
return IndexNumber != null ? IndexNumber.Value.ToString("0000") : Name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private IEnumerable<Episode> GetEpisodes()
|
||||||
|
{
|
||||||
|
var series = Series;
|
||||||
|
|
||||||
|
if (series != null && series.ContainsEpisodesWithoutSeasonFolders)
|
||||||
|
{
|
||||||
|
var seasonNumber = IndexNumber;
|
||||||
|
|
||||||
|
if (seasonNumber.HasValue)
|
||||||
|
{
|
||||||
|
return series.RecursiveChildren.OfType<Episode>()
|
||||||
|
.Where(i => i.ParentIndexNumber.HasValue && i.ParentIndexNumber.Value == seasonNumber.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Children.OfType<Episode>();
|
||||||
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public bool IsMissingSeason
|
public bool IsMissingSeason
|
||||||
{
|
{
|
||||||
get { return LocationType == Model.Entities.LocationType.Virtual && Children.OfType<Episode>().All(i => i.IsMissingEpisode); }
|
get { return LocationType == Model.Entities.LocationType.Virtual && GetEpisodes().All(i => i.IsMissingEpisode); }
|
||||||
}
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public bool IsUnaired
|
public bool IsUnaired
|
||||||
{
|
{
|
||||||
get { return Children.OfType<Episode>().All(i => i.IsUnaired); }
|
get { return GetEpisodes().All(i => i.IsUnaired); }
|
||||||
}
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
|
@ -170,7 +188,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public bool IsMissingOrVirtualUnaired
|
public bool IsMissingOrVirtualUnaired
|
||||||
{
|
{
|
||||||
get { return LocationType == Model.Entities.LocationType.Virtual && Children.OfType<Episode>().All(i => i.IsVirtualUnaired || i.IsMissingEpisode); }
|
get { return LocationType == Model.Entities.LocationType.Virtual && GetEpisodes().All(i => i.IsVirtualUnaired || i.IsMissingEpisode); }
|
||||||
}
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using MediaBrowser.Common.Extensions;
|
using MediaBrowser.Common.Extensions;
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Entities.TV;
|
using MediaBrowser.Controller.Entities.TV;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
|
@ -150,6 +151,12 @@ namespace MediaBrowser.Providers.TV
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
var hasNewEpisodes = false;
|
var hasNewEpisodes = false;
|
||||||
|
var hasNewSeasons = false;
|
||||||
|
|
||||||
|
if (series.ContainsEpisodesWithoutSeasonFolders)
|
||||||
|
{
|
||||||
|
hasNewSeasons = await AddDummySeasonFolders(series, cancellationToken).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
if (_config.Configuration.EnableInternetProviders)
|
if (_config.Configuration.EnableInternetProviders)
|
||||||
{
|
{
|
||||||
|
@ -157,7 +164,7 @@ namespace MediaBrowser.Providers.TV
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasNewEpisodes || anySeasonsRemoved || anyEpisodesRemoved)
|
if (hasNewSeasons || hasNewEpisodes || anySeasonsRemoved || anyEpisodesRemoved)
|
||||||
{
|
{
|
||||||
await series.RefreshMetadata(cancellationToken, true)
|
await series.RefreshMetadata(cancellationToken, true)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
@ -167,6 +174,40 @@ namespace MediaBrowser.Providers.TV
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// For series with episodes directly under the series folder, this adds dummy seasons to enable regular browsing and metadata
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="series"></param>
|
||||||
|
/// <param name="cancellationToken"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private async Task<bool> AddDummySeasonFolders(Series series, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var existingEpisodes = series.RecursiveChildren
|
||||||
|
.OfType<Episode>()
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
var hasChanges = false;
|
||||||
|
|
||||||
|
// Loop through the unique season numbers
|
||||||
|
foreach (var seasonNumber in existingEpisodes.Select(i => i.ParentIndexNumber ?? -1)
|
||||||
|
.Where(i => i >= 0)
|
||||||
|
.Distinct()
|
||||||
|
.ToList())
|
||||||
|
{
|
||||||
|
var hasSeason = series.Children.OfType<Season>()
|
||||||
|
.Any(i => i.IndexNumber.HasValue && i.IndexNumber.Value == seasonNumber);
|
||||||
|
|
||||||
|
if (!hasSeason)
|
||||||
|
{
|
||||||
|
await AddSeason(series, seasonNumber, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
|
hasChanges = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return hasChanges;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds the missing episodes.
|
/// Adds the missing episodes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
Loading…
Reference in a new issue