< Summary - Jellyfin

Information
Class: MediaBrowser.Controller.Entities.TV.Episode
Assembly: MediaBrowser.Controller
File(s): /srv/git/jellyfin/MediaBrowser.Controller/Entities/TV/Episode.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 103
Coverable lines: 103
Total lines: 345
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 78
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100

Metrics

File(s)

/srv/git/jellyfin/MediaBrowser.Controller/Entities/TV/Episode.cs

#LineLine coverage
 1#nullable disable
 2
 3#pragma warning disable CS1591
 4
 5using System;
 6using System.Collections.Generic;
 7using System.Globalization;
 8using System.Linq;
 9using System.Text.Json.Serialization;
 10using Jellyfin.Data.Enums;
 11using Jellyfin.Extensions;
 12using MediaBrowser.Controller.Providers;
 13using MediaBrowser.Model.Entities;
 14using MediaBrowser.Model.IO;
 15using MediaBrowser.Model.Providers;
 16using Microsoft.Extensions.Logging;
 17
 18namespace MediaBrowser.Controller.Entities.TV
 19{
 20    /// <summary>
 21    /// Class Episode.
 22    /// </summary>
 23    public class Episode : Video, IHasTrailers, IHasLookupInfo<EpisodeInfo>, IHasSeries
 24    {
 25        /// <inheritdoc />
 26        [JsonIgnore]
 027        public IReadOnlyList<BaseItem> LocalTrailers => GetExtras()
 028            .Where(extra => extra.ExtraType == Model.Entities.ExtraType.Trailer)
 029            .ToArray();
 30
 31        /// <summary>
 32        /// Gets or sets the season in which it aired.
 33        /// </summary>
 34        /// <value>The aired season.</value>
 35        public int? AirsBeforeSeasonNumber { get; set; }
 36
 37        public int? AirsAfterSeasonNumber { get; set; }
 38
 39        public int? AirsBeforeEpisodeNumber { get; set; }
 40
 41        /// <summary>
 42        /// Gets or sets the ending episode number for double episodes.
 43        /// </summary>
 44        /// <value>The index number.</value>
 45        public int? IndexNumberEnd { get; set; }
 46
 47        [JsonIgnore]
 048        protected override bool SupportsOwnedItems => IsStacked || MediaSourceCount > 1;
 49
 50        [JsonIgnore]
 051        public override bool SupportsInheritedParentImages => true;
 52
 53        [JsonIgnore]
 054        public override bool SupportsPeople => true;
 55
 56        [JsonIgnore]
 057        public int? AiredSeasonNumber => AirsAfterSeasonNumber ?? AirsBeforeSeasonNumber ?? ParentIndexNumber;
 58
 59        [JsonIgnore]
 060        public override Folder LatestItemsIndexContainer => Series;
 61
 62        [JsonIgnore]
 063        public override Guid DisplayParentId => SeasonId;
 64
 65        [JsonIgnore]
 066        protected override bool EnableDefaultVideoUserDataKeys => false;
 67
 68        /// <summary>
 69        /// Gets the Episode's Series Instance.
 70        /// </summary>
 71        /// <value>The series.</value>
 72        [JsonIgnore]
 73        public Series Series
 74        {
 75            get
 76            {
 077                var seriesId = SeriesId;
 078                if (seriesId.IsEmpty())
 79                {
 080                    seriesId = FindSeriesId();
 81                }
 82
 083                return seriesId.IsEmpty() ? null : (LibraryManager.GetItemById(seriesId) as Series);
 84            }
 85        }
 86
 87        [JsonIgnore]
 88        public Season Season
 89        {
 90            get
 91            {
 092                var seasonId = SeasonId;
 093                if (seasonId.IsEmpty())
 94                {
 095                    seasonId = FindSeasonId();
 96                }
 97
 098                return seasonId.IsEmpty() ? null : (LibraryManager.GetItemById(seasonId) as Season);
 99            }
 100        }
 101
 102        [JsonIgnore]
 0103        public bool IsInSeasonFolder => FindParent<Season>() is not null;
 104
 105        [JsonIgnore]
 106        public string SeriesPresentationUniqueKey { get; set; }
 107
 108        [JsonIgnore]
 109        public string SeriesName { get; set; }
 110
 111        [JsonIgnore]
 112        public string SeasonName { get; set; }
 113
 114        [JsonIgnore]
 115        public override bool SupportsRemoteImageDownloading
 116        {
 117            get
 118            {
 0119                if (IsMissingEpisode)
 120                {
 0121                    return false;
 122                }
 123
 0124                return true;
 125            }
 126        }
 127
 128        [JsonIgnore]
 0129        public bool IsMissingEpisode => LocationType == LocationType.Virtual;
 130
 131        [JsonIgnore]
 132        public Guid SeasonId { get; set; }
 133
 134        [JsonIgnore]
 135        public Guid SeriesId { get; set; }
 136
 137        public string FindSeriesSortName()
 138        {
 0139            var series = Series;
 0140            return series is null ? SeriesName : series.SortName;
 141        }
 142
 143        public override double GetDefaultPrimaryImageAspectRatio()
 144        {
 145            // hack for tv plugins
 0146            if (SourceType == SourceType.Channel)
 147            {
 0148                return 0;
 149            }
 150
 0151            return 16.0 / 9;
 152        }
 153
 154        public override List<string> GetUserDataKeys()
 155        {
 0156            var list = base.GetUserDataKeys();
 157
 0158            var series = Series;
 0159            if (series is not null && ParentIndexNumber.HasValue && IndexNumber.HasValue)
 160            {
 0161                var seriesUserDataKeys = series.GetUserDataKeys();
 0162                var take = seriesUserDataKeys.Count;
 0163                if (seriesUserDataKeys.Count > 1)
 164                {
 0165                    take--;
 166                }
 167
 0168                var newList = seriesUserDataKeys.GetRange(0, take);
 0169                var suffix = ParentIndexNumber.Value.ToString("000", CultureInfo.InvariantCulture) + IndexNumber.Value.T
 0170                for (int i = 0; i < take; i++)
 171                {
 0172                    newList[i] = newList[i] + suffix;
 173                }
 174
 0175                newList.AddRange(list);
 0176                list = newList;
 177            }
 178
 0179            return list;
 180        }
 181
 182        public string FindSeriesPresentationUniqueKey()
 0183            => Series?.PresentationUniqueKey;
 184
 185        public string FindSeasonName()
 186        {
 0187            var season = Season;
 188
 0189            if (season is null)
 190            {
 0191                if (ParentIndexNumber.HasValue)
 192                {
 0193                    return "Season " + ParentIndexNumber.Value.ToString(CultureInfo.InvariantCulture);
 194                }
 195
 0196                return "Season Unknown";
 197            }
 198
 0199            return season.Name;
 200        }
 201
 202        public string FindSeriesName()
 203        {
 0204            var series = Series;
 0205            return series is null ? SeriesName : series.Name;
 206        }
 207
 208        public Guid FindSeasonId()
 209        {
 0210            var season = FindParent<Season>();
 211
 212            // Episodes directly in series folder
 0213            if (season is null)
 214            {
 0215                var series = Series;
 216
 0217                if (series is not null && ParentIndexNumber.HasValue)
 218                {
 0219                    var findNumber = ParentIndexNumber.Value;
 220
 0221                    season = series.Children
 0222                        .OfType<Season>()
 0223                        .FirstOrDefault(i => i.IndexNumber.HasValue && i.IndexNumber.Value == findNumber);
 224                }
 225            }
 226
 0227            return season is null ? Guid.Empty : season.Id;
 228        }
 229
 230        /// <summary>
 231        /// Creates the name of the sort.
 232        /// </summary>
 233        /// <returns>System.String.</returns>
 234        protected override string CreateSortName()
 235        {
 0236            return (ParentIndexNumber is not null ? ParentIndexNumber.Value.ToString("000 - ", CultureInfo.InvariantCult
 0237                    + (IndexNumber is not null ? IndexNumber.Value.ToString("0000 - ", CultureInfo.InvariantCulture) : s
 238        }
 239
 240        /// <summary>
 241        /// Determines whether [contains episode number] [the specified number].
 242        /// </summary>
 243        /// <param name="number">The number.</param>
 244        /// <returns><c>true</c> if [contains episode number] [the specified number]; otherwise, <c>false</c>.</returns>
 245        public bool ContainsEpisodeNumber(int number)
 246        {
 0247            if (IndexNumber.HasValue)
 248            {
 0249                if (IndexNumberEnd.HasValue)
 250                {
 0251                    return number >= IndexNumber.Value && number <= IndexNumberEnd.Value;
 252                }
 253
 0254                return IndexNumber.Value == number;
 255            }
 256
 0257            return false;
 258        }
 259
 260        public Guid FindSeriesId()
 261        {
 0262            var series = FindParent<Series>();
 0263            return series is null ? Guid.Empty : series.Id;
 264        }
 265
 266        public override IEnumerable<Guid> GetAncestorIds()
 267        {
 0268            var list = base.GetAncestorIds().ToList();
 269
 0270            var seasonId = SeasonId;
 271
 0272            if (!seasonId.IsEmpty() && !list.Contains(seasonId))
 273            {
 0274                list.Add(seasonId);
 275            }
 276
 0277            return list;
 278        }
 279
 280        public override IEnumerable<FileSystemMetadata> GetDeletePaths()
 281        {
 0282            return new[]
 0283            {
 0284                new FileSystemMetadata
 0285                {
 0286                    FullName = Path,
 0287                    IsDirectory = IsFolder
 0288                }
 0289            }.Concat(GetLocalMetadataFilesToDelete());
 290        }
 291
 292        public override UnratedItem GetBlockUnratedType()
 293        {
 0294            return UnratedItem.Series;
 295        }
 296
 297        public EpisodeInfo GetLookupInfo()
 298        {
 0299            var id = GetItemLookupInfo<EpisodeInfo>();
 300
 0301            var series = Series;
 302
 0303            if (series is not null)
 304            {
 0305                id.SeriesProviderIds = series.ProviderIds;
 0306                id.SeriesDisplayOrder = series.DisplayOrder;
 307            }
 308
 0309            if (Season is not null)
 310            {
 0311                id.SeasonProviderIds = Season.ProviderIds;
 312            }
 313
 0314            id.IsMissingEpisode = IsMissingEpisode;
 0315            id.IndexNumberEnd = IndexNumberEnd;
 316
 0317            return id;
 318        }
 319
 320        public override bool BeforeMetadataRefresh(bool replaceAllMetadata)
 321        {
 0322            var hasChanges = base.BeforeMetadataRefresh(replaceAllMetadata);
 323
 0324            if (!IsLocked)
 325            {
 0326                if (SourceType == SourceType.Library || SourceType == SourceType.LiveTV)
 327                {
 328                    try
 329                    {
 0330                        if (LibraryManager.FillMissingEpisodeNumbersFromPath(this, replaceAllMetadata))
 331                        {
 0332                            hasChanges = true;
 333                        }
 0334                    }
 0335                    catch (Exception ex)
 336                    {
 0337                        Logger.LogError(ex, "Error in FillMissingEpisodeNumbersFromPath. Episode: {Episode}", Path ?? Na
 0338                    }
 339                }
 340            }
 341
 0342            return hasChanges;
 343        }
 344    }
 345}