diff --git a/Jellyfin.Plugin.TubeArchivistMetadata/Providers/EpisodeMetadataProvider.cs b/Jellyfin.Plugin.TubeArchivistMetadata/Providers/EpisodeMetadataProvider.cs
index d62e530..c38e96c 100644
--- a/Jellyfin.Plugin.TubeArchivistMetadata/Providers/EpisodeMetadataProvider.cs
+++ b/Jellyfin.Plugin.TubeArchivistMetadata/Providers/EpisodeMetadataProvider.cs
@@ -65,8 +65,31 @@ namespace Jellyfin.Plugin.TubeArchivistMetadata.Providers
ImageUrl = video.Channel.ThumbUrl,
Type = Data.Enums.PersonKind.Actor,
});
+ PlaylistAssignment? playlistAssignment = null;
+ if (Plugin.Instance?.Configuration.SortSeasonsByPlaylist == true)
+ {
+ var playlistCache = PlaylistCache.GetInstance();
+ playlistAssignment = await playlistCache.GetAssignmentAsync(videoTAId, cancellationToken).ConfigureAwait(true);
+
+ if (playlistAssignment == null)
+ {
+ // Only bucket into "Unsorted" when the playlists were actually retrieved.
+ // If TubeArchivist is unreachable the video falls back to its upload year,
+ // which Jellyfin can still correct on a later refresh.
+ if (await playlistCache.HasPlaylistDataAsync(cancellationToken).ConfigureAwait(true))
+ {
+ _logger.LogDebug("{Message}", string.Format(CultureInfo.CurrentCulture, "No TubeArchivist playlist found for video {0}. Grouping it into the {1} season.", videoTAId, Constants.UnsortedSeasonName));
+ playlistAssignment = new PlaylistAssignment(string.Empty, Constants.UnsortedSeasonName, Constants.UnsortedSeasonNumber, 0);
+ }
+ else
+ {
+ _logger.LogWarning("{Message}", string.Format(CultureInfo.CurrentCulture, "TubeArchivist playlists unavailable. Grouping video {0} by upload year.", videoTAId));
+ }
+ }
+ }
+
result.HasMetadata = true;
- result.Item = video.ToEpisode();
+ result.Item = video.ToEpisode(playlistAssignment);
result.Item.Path = info.Path;
result.Provider = Name;
result.People = peopleInfo;
diff --git a/Jellyfin.Plugin.TubeArchivistMetadata/TubeArchivist/Video/Video.cs b/Jellyfin.Plugin.TubeArchivistMetadata/TubeArchivist/Video/Video.cs
index 22b3f44..9c810c6 100644
--- a/Jellyfin.Plugin.TubeArchivistMetadata/TubeArchivist/Video/Video.cs
+++ b/Jellyfin.Plugin.TubeArchivistMetadata/TubeArchivist/Video/Video.cs
@@ -9,6 +9,7 @@ using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
+using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
namespace Jellyfin.Plugin.TubeArchivistMetadata.TubeArchivist
@@ -121,15 +122,38 @@ namespace Jellyfin.Plugin.TubeArchivistMetadata.TubeArchivist
/// The video equivalent Jellyfin object.
public Episode ToEpisode()
{
+ return ToEpisode(null);
+ }
+
+ ///
+ /// Converts the TubeArchivist API video to a Jellyfin object,
+ /// optionally grouping it into the season representing its TubeArchivist playlist.
+ ///
+ ///
+ /// The playlist the video belongs to, or null to group the video by upload year.
+ ///
+ /// The video equivalent Jellyfin object.
+ public Episode ToEpisode(PlaylistAssignment? playlistAssignment)
+ {
+ // A null assignment always means "group by upload year". Deciding when an unassigned
+ // video belongs in the Unsorted season needs to know whether playlist data was actually
+ // retrieved, so the caller makes that call and passes an Unsorted assignment instead.
+ var seasonNumber = playlistAssignment?.SeasonNumber ?? Published.Year;
+ var seasonName = playlistAssignment?.SeasonName ?? Published.Year.ToString(CultureInfo.CurrentCulture);
+
return new Episode
{
Name = Title,
Overview = Utils.FormatDescription(Description),
- SeasonName = Published.Year.ToString(CultureInfo.CurrentCulture),
- ParentIndexNumber = Published.Year,
+
+ // Jellyfin overwrites SeasonName from the parent Season entity; it is set here only
+ // for consistency. Season naming is handled by SeasonMetadataProvider.
+ SeasonName = seasonName,
+ ParentIndexNumber = seasonNumber,
IndexNumber = Plugin.Instance?.Configuration?.EpisodeNumberingScheme switch
{
NumberingScheme.YYYYMMDD => (Published.Year * 10000) + (Published.Month * 100) + Published.Day,
+ NumberingScheme.PlaylistIndex => playlistAssignment?.Index,
_ => null
},
SeriesName = Channel.Name,