Prepared Seperation of Database components for future multi provider support

This commit is contained in:
JPVenson
2025-01-26 20:45:28 +00:00
parent b318f33599
commit aa811eb1e3
220 changed files with 742 additions and 320 deletions

View File

@@ -1,62 +0,0 @@
using System;
using System.ComponentModel.DataAnnotations.Schema;
using System.Xml.Serialization;
using Jellyfin.Data.Enums;
namespace Jellyfin.Data.Entities
{
/// <summary>
/// An entity representing a user's access schedule.
/// </summary>
public class AccessSchedule
{
/// <summary>
/// Initializes a new instance of the <see cref="AccessSchedule"/> class.
/// </summary>
/// <param name="dayOfWeek">The day of the week.</param>
/// <param name="startHour">The start hour.</param>
/// <param name="endHour">The end hour.</param>
/// <param name="userId">The associated user's id.</param>
public AccessSchedule(DynamicDayOfWeek dayOfWeek, double startHour, double endHour, Guid userId)
{
UserId = userId;
DayOfWeek = dayOfWeek;
StartHour = startHour;
EndHour = endHour;
}
/// <summary>
/// Gets the id of this instance.
/// </summary>
/// <remarks>
/// Identity, Indexed, Required.
/// </remarks>
[XmlIgnore]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; private set; }
/// <summary>
/// Gets the id of the associated user.
/// </summary>
[XmlIgnore]
public Guid UserId { get; private set; }
/// <summary>
/// Gets or sets the day of week.
/// </summary>
/// <value>The day of week.</value>
public DynamicDayOfWeek DayOfWeek { get; set; }
/// <summary>
/// Gets or sets the start hour.
/// </summary>
/// <value>The start hour.</value>
public double StartHour { get; set; }
/// <summary>
/// Gets or sets the end hour.
/// </summary>
/// <value>The end hour.</value>
public double EndHour { get; set; }
}
}

View File

@@ -1,123 +0,0 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Jellyfin.Data.Interfaces;
using Microsoft.Extensions.Logging;
namespace Jellyfin.Data.Entities
{
/// <summary>
/// An entity referencing an activity log entry.
/// </summary>
public class ActivityLog : IHasConcurrencyToken
{
/// <summary>
/// Initializes a new instance of the <see cref="ActivityLog"/> class.
/// Public constructor with required data.
/// </summary>
/// <param name="name">The name.</param>
/// <param name="type">The type.</param>
/// <param name="userId">The user id.</param>
public ActivityLog(string name, string type, Guid userId)
{
ArgumentException.ThrowIfNullOrEmpty(name);
ArgumentException.ThrowIfNullOrEmpty(type);
Name = name;
Type = type;
UserId = userId;
DateCreated = DateTime.UtcNow;
LogSeverity = LogLevel.Information;
}
/// <summary>
/// Gets the identity of this instance.
/// </summary>
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; private set; }
/// <summary>
/// Gets or sets the name.
/// </summary>
/// <remarks>
/// Required, Max length = 512.
/// </remarks>
[MaxLength(512)]
[StringLength(512)]
public string Name { get; set; }
/// <summary>
/// Gets or sets the overview.
/// </summary>
/// <remarks>
/// Max length = 512.
/// </remarks>
[MaxLength(512)]
[StringLength(512)]
public string? Overview { get; set; }
/// <summary>
/// Gets or sets the short overview.
/// </summary>
/// <remarks>
/// Max length = 512.
/// </remarks>
[MaxLength(512)]
[StringLength(512)]
public string? ShortOverview { get; set; }
/// <summary>
/// Gets or sets the type.
/// </summary>
/// <remarks>
/// Required, Max length = 256.
/// </remarks>
[MaxLength(256)]
[StringLength(256)]
public string Type { get; set; }
/// <summary>
/// Gets or sets the user id.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public Guid UserId { get; set; }
/// <summary>
/// Gets or sets the item id.
/// </summary>
/// <remarks>
/// Max length = 256.
/// </remarks>
[MaxLength(256)]
[StringLength(256)]
public string? ItemId { get; set; }
/// <summary>
/// Gets or sets the date created. This should be in UTC.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public DateTime DateCreated { get; set; }
/// <summary>
/// Gets or sets the log severity. Default is <see cref="LogLevel.Trace"/>.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public LogLevel LogSeverity { get; set; }
/// <inheritdoc />
[ConcurrencyCheck]
public uint RowVersion { get; private set; }
/// <inheritdoc />
public void OnSavingChanges()
{
RowVersion++;
}
}
}

View File

@@ -1,29 +0,0 @@
using System;
namespace Jellyfin.Data.Entities;
/// <summary>
/// Represents the relational informations for an <see cref="BaseItemEntity"/>.
/// </summary>
public class AncestorId
{
/// <summary>
/// Gets or Sets the AncestorId.
/// </summary>
public required Guid ParentItemId { get; set; }
/// <summary>
/// Gets or Sets the related BaseItem.
/// </summary>
public required Guid ItemId { get; set; }
/// <summary>
/// Gets or Sets the ParentItem.
/// </summary>
public required BaseItemEntity ParentItem { get; set; }
/// <summary>
/// Gets or Sets the Child item.
/// </summary>
public required BaseItemEntity Item { get; set; }
}

View File

@@ -1,49 +0,0 @@
using System;
namespace Jellyfin.Data.Entities;
/// <summary>
/// Provides informations about an Attachment to an <see cref="BaseItemEntity"/>.
/// </summary>
public class AttachmentStreamInfo
{
/// <summary>
/// Gets or Sets the <see cref="BaseItemEntity"/> reference.
/// </summary>
public required Guid ItemId { get; set; }
/// <summary>
/// Gets or Sets the <see cref="BaseItemEntity"/> reference.
/// </summary>
public required BaseItemEntity Item { get; set; }
/// <summary>
/// Gets or Sets The index within the source file.
/// </summary>
public required int Index { get; set; }
/// <summary>
/// Gets or Sets the codec of the attachment.
/// </summary>
public required string Codec { get; set; }
/// <summary>
/// Gets or Sets the codec tag of the attachment.
/// </summary>
public string? CodecTag { get; set; }
/// <summary>
/// Gets or Sets the comment of the attachment.
/// </summary>
public string? Comment { get; set; }
/// <summary>
/// Gets or Sets the filename of the attachment.
/// </summary>
public string? Filename { get; set; }
/// <summary>
/// Gets or Sets the attachments mimetype.
/// </summary>
public string? MimeType { get; set; }
}

View File

@@ -1,186 +0,0 @@
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
#pragma warning disable CA2227 // Collection properties should be read only
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace Jellyfin.Data.Entities;
public class BaseItemEntity
{
public required Guid Id { get; set; }
public required string Type { get; set; }
public string? Data { get; set; }
public string? Path { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public string? ChannelId { get; set; }
public bool IsMovie { get; set; }
public float? CommunityRating { get; set; }
public string? CustomRating { get; set; }
public int? IndexNumber { get; set; }
public bool IsLocked { get; set; }
public string? Name { get; set; }
public string? OfficialRating { get; set; }
public string? MediaType { get; set; }
public string? Overview { get; set; }
public int? ParentIndexNumber { get; set; }
public DateTime? PremiereDate { get; set; }
public int? ProductionYear { get; set; }
public string? Genres { get; set; }
public string? SortName { get; set; }
public string? ForcedSortName { get; set; }
public long? RunTimeTicks { get; set; }
public DateTime? DateCreated { get; set; }
public DateTime? DateModified { get; set; }
public bool IsSeries { get; set; }
public string? EpisodeTitle { get; set; }
public bool IsRepeat { get; set; }
public string? PreferredMetadataLanguage { get; set; }
public string? PreferredMetadataCountryCode { get; set; }
public DateTime? DateLastRefreshed { get; set; }
public DateTime? DateLastSaved { get; set; }
public bool IsInMixedFolder { get; set; }
public string? Studios { get; set; }
public string? ExternalServiceId { get; set; }
public string? Tags { get; set; }
public bool IsFolder { get; set; }
public int? InheritedParentalRatingValue { get; set; }
public string? UnratedType { get; set; }
public float? CriticRating { get; set; }
public string? CleanName { get; set; }
public string? PresentationUniqueKey { get; set; }
public string? OriginalTitle { get; set; }
public string? PrimaryVersionId { get; set; }
public DateTime? DateLastMediaAdded { get; set; }
public string? Album { get; set; }
public float? LUFS { get; set; }
public float? NormalizationGain { get; set; }
public bool IsVirtualItem { get; set; }
public string? SeriesName { get; set; }
public string? SeasonName { get; set; }
public string? ExternalSeriesId { get; set; }
public string? Tagline { get; set; }
public string? ProductionLocations { get; set; }
public string? ExtraIds { get; set; }
public int? TotalBitrate { get; set; }
public BaseItemExtraType? ExtraType { get; set; }
public string? Artists { get; set; }
public string? AlbumArtists { get; set; }
public string? ExternalId { get; set; }
public string? SeriesPresentationUniqueKey { get; set; }
public string? ShowId { get; set; }
public string? OwnerId { get; set; }
public int? Width { get; set; }
public int? Height { get; set; }
public long? Size { get; set; }
public ProgramAudioEntity? Audio { get; set; }
public Guid? ParentId { get; set; }
public Guid? TopParentId { get; set; }
public Guid? SeasonId { get; set; }
public Guid? SeriesId { get; set; }
public ICollection<PeopleBaseItemMap>? Peoples { get; set; }
public ICollection<UserData>? UserData { get; set; }
public ICollection<ItemValueMap>? ItemValues { get; set; }
public ICollection<MediaStreamInfo>? MediaStreams { get; set; }
public ICollection<Chapter>? Chapters { get; set; }
public ICollection<BaseItemProvider>? Provider { get; set; }
public ICollection<AncestorId>? ParentAncestors { get; set; }
public ICollection<AncestorId>? Children { get; set; }
public ICollection<BaseItemMetadataField>? LockedFields { get; set; }
public ICollection<BaseItemTrailerType>? TrailerTypes { get; set; }
public ICollection<BaseItemImageInfo>? Images { get; set; }
// those are references to __LOCAL__ ids not DB ids ... TODO: Bring the whole folder structure into the DB
// public ICollection<BaseItemEntity>? SeriesEpisodes { get; set; }
// public BaseItemEntity? Series { get; set; }
// public BaseItemEntity? Season { get; set; }
// public BaseItemEntity? Parent { get; set; }
// public ICollection<BaseItemEntity>? DirectChildren { get; set; }
// public BaseItemEntity? TopParent { get; set; }
// public ICollection<BaseItemEntity>? AllChildren { get; set; }
// public ICollection<BaseItemEntity>? SeasonEpisodes { get; set; }
}

View File

@@ -1,18 +0,0 @@
#pragma warning disable CS1591
namespace Jellyfin.Data.Entities;
public enum BaseItemExtraType
{
Unknown = 0,
Clip = 1,
Trailer = 2,
BehindTheScenes = 3,
DeletedScene = 4,
Interview = 5,
Scene = 6,
Sample = 7,
ThemeSong = 8,
ThemeVideo = 9,
Featurette = 10,
Short = 11
}

View File

@@ -1,59 +0,0 @@
#pragma warning disable CA2227
using System;
using System.Collections.Generic;
namespace Jellyfin.Data.Entities;
/// <summary>
/// Enum TrailerTypes.
/// </summary>
public class BaseItemImageInfo
{
/// <summary>
/// Gets or Sets.
/// </summary>
public required Guid Id { get; set; }
/// <summary>
/// Gets or Sets the path to the original image.
/// </summary>
public required string Path { get; set; }
/// <summary>
/// Gets or Sets the time the image was last modified.
/// </summary>
public DateTime DateModified { get; set; }
/// <summary>
/// Gets or Sets the imagetype.
/// </summary>
public ImageInfoImageType ImageType { get; set; }
/// <summary>
/// Gets or Sets the width of the original image.
/// </summary>
public int Width { get; set; }
/// <summary>
/// Gets or Sets the height of the original image.
/// </summary>
public int Height { get; set; }
#pragma warning disable CA1819 // Properties should not return arrays
/// <summary>
/// Gets or Sets the blurhash.
/// </summary>
public byte[]? Blurhash { get; set; }
#pragma warning restore CA1819
/// <summary>
/// Gets or Sets the reference id to the BaseItem.
/// </summary>
public required Guid ItemId { get; set; }
/// <summary>
/// Gets or Sets the referenced Item.
/// </summary>
public required BaseItemEntity Item { get; set; }
}

View File

@@ -1,24 +0,0 @@
using System;
namespace Jellyfin.Data.Entities;
/// <summary>
/// Enum MetadataFields.
/// </summary>
public class BaseItemMetadataField
{
/// <summary>
/// Gets or Sets Numerical ID of this enumeratable.
/// </summary>
public required int Id { get; set; }
/// <summary>
/// Gets or Sets all referenced <see cref="BaseItemEntity"/>.
/// </summary>
public required Guid ItemId { get; set; }
/// <summary>
/// Gets or Sets all referenced <see cref="BaseItemEntity"/>.
/// </summary>
public required BaseItemEntity Item { get; set; }
}

View File

@@ -1,32 +0,0 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace Jellyfin.Data.Entities;
/// <summary>
/// Represents a Key-Value relation of an BaseItem's provider.
/// </summary>
public class BaseItemProvider
{
/// <summary>
/// Gets or Sets the reference ItemId.
/// </summary>
public Guid ItemId { get; set; }
/// <summary>
/// Gets or Sets the reference BaseItem.
/// </summary>
public required BaseItemEntity Item { get; set; }
/// <summary>
/// Gets or Sets the ProvidersId.
/// </summary>
public required string ProviderId { get; set; }
/// <summary>
/// Gets or Sets the Providers Value.
/// </summary>
public required string ProviderValue { get; set; }
}

View File

@@ -1,24 +0,0 @@
using System;
namespace Jellyfin.Data.Entities;
/// <summary>
/// Enum TrailerTypes.
/// </summary>
public class BaseItemTrailerType
{
/// <summary>
/// Gets or Sets Numerical ID of this enumeratable.
/// </summary>
public required int Id { get; set; }
/// <summary>
/// Gets or Sets all referenced <see cref="BaseItemEntity"/>.
/// </summary>
public required Guid ItemId { get; set; }
/// <summary>
/// Gets or Sets all referenced <see cref="BaseItemEntity"/>.
/// </summary>
public required BaseItemEntity Item { get; set; }
}

View File

@@ -1,44 +0,0 @@
using System;
namespace Jellyfin.Data.Entities;
/// <summary>
/// The Chapter entity.
/// </summary>
public class Chapter
{
/// <summary>
/// Gets or Sets the <see cref="BaseItemEntity"/> reference id.
/// </summary>
public required Guid ItemId { get; set; }
/// <summary>
/// Gets or Sets the <see cref="BaseItemEntity"/> reference.
/// </summary>
public required BaseItemEntity Item { get; set; }
/// <summary>
/// Gets or Sets the chapters index in Item.
/// </summary>
public required int ChapterIndex { get; set; }
/// <summary>
/// Gets or Sets the position within the source file.
/// </summary>
public required long StartPositionTicks { get; set; }
/// <summary>
/// Gets or Sets the common name.
/// </summary>
public string? Name { get; set; }
/// <summary>
/// Gets or Sets the image path.
/// </summary>
public string? ImagePath { get; set; }
/// <summary>
/// Gets or Sets the time the image was last modified.
/// </summary>
public DateTime? ImageDateModified { get; set; }
}

View File

@@ -1,80 +0,0 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace Jellyfin.Data.Entities
{
/// <summary>
/// An entity that represents a user's custom display preferences for a specific item.
/// </summary>
public class CustomItemDisplayPreferences
{
/// <summary>
/// Initializes a new instance of the <see cref="CustomItemDisplayPreferences"/> class.
/// </summary>
/// <param name="userId">The user id.</param>
/// <param name="itemId">The item id.</param>
/// <param name="client">The client.</param>
/// <param name="key">The preference key.</param>
/// <param name="value">The preference value.</param>
public CustomItemDisplayPreferences(Guid userId, Guid itemId, string client, string key, string? value)
{
UserId = userId;
ItemId = itemId;
Client = client;
Key = key;
Value = value;
}
/// <summary>
/// Gets the Id.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; private set; }
/// <summary>
/// Gets or sets the user Id.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public Guid UserId { get; set; }
/// <summary>
/// Gets or sets the id of the associated item.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public Guid ItemId { get; set; }
/// <summary>
/// Gets or sets the client string.
/// </summary>
/// <remarks>
/// Required. Max Length = 32.
/// </remarks>
[MaxLength(32)]
[StringLength(32)]
public string Client { get; set; }
/// <summary>
/// Gets or sets the preference key.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public string Key { get; set; }
/// <summary>
/// Gets or sets the preference value.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public string? Value { get; set; }
}
}

View File

@@ -1,150 +0,0 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Jellyfin.Data.Enums;
namespace Jellyfin.Data.Entities
{
/// <summary>
/// An entity representing a user's display preferences.
/// </summary>
public class DisplayPreferences
{
/// <summary>
/// Initializes a new instance of the <see cref="DisplayPreferences"/> class.
/// </summary>
/// <param name="userId">The user's id.</param>
/// <param name="itemId">The item id.</param>
/// <param name="client">The client string.</param>
public DisplayPreferences(Guid userId, Guid itemId, string client)
{
UserId = userId;
ItemId = itemId;
Client = client;
ShowSidebar = false;
ShowBackdrop = true;
SkipForwardLength = 30000;
SkipBackwardLength = 10000;
ScrollDirection = ScrollDirection.Horizontal;
ChromecastVersion = ChromecastVersion.Stable;
HomeSections = new HashSet<HomeSection>();
}
/// <summary>
/// Gets the Id.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; private set; }
/// <summary>
/// Gets or sets the user Id.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public Guid UserId { get; set; }
/// <summary>
/// Gets or sets the id of the associated item.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public Guid ItemId { get; set; }
/// <summary>
/// Gets or sets the client string.
/// </summary>
/// <remarks>
/// Required. Max Length = 32.
/// </remarks>
[MaxLength(32)]
[StringLength(32)]
public string Client { get; set; }
/// <summary>
/// Gets or sets a value indicating whether to show the sidebar.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public bool ShowSidebar { get; set; }
/// <summary>
/// Gets or sets a value indicating whether to show the backdrop.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public bool ShowBackdrop { get; set; }
/// <summary>
/// Gets or sets the scroll direction.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public ScrollDirection ScrollDirection { get; set; }
/// <summary>
/// Gets or sets what the view should be indexed by.
/// </summary>
public IndexingKind? IndexBy { get; set; }
/// <summary>
/// Gets or sets the length of time to skip forwards, in milliseconds.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public int SkipForwardLength { get; set; }
/// <summary>
/// Gets or sets the length of time to skip backwards, in milliseconds.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public int SkipBackwardLength { get; set; }
/// <summary>
/// Gets or sets the Chromecast Version.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public ChromecastVersion ChromecastVersion { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the next video info overlay should be shown.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public bool EnableNextVideoInfoOverlay { get; set; }
/// <summary>
/// Gets or sets the dashboard theme.
/// </summary>
[MaxLength(32)]
[StringLength(32)]
public string? DashboardTheme { get; set; }
/// <summary>
/// Gets or sets the tv home screen.
/// </summary>
[MaxLength(32)]
[StringLength(32)]
public string? TvHome { get; set; }
/// <summary>
/// Gets the home sections.
/// </summary>
public virtual ICollection<HomeSection> HomeSections { get; private set; }
}
}

View File

@@ -1,80 +0,0 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using Jellyfin.Data.Enums;
using Jellyfin.Data.Interfaces;
namespace Jellyfin.Data.Entities
{
/// <summary>
/// An entity representing a group.
/// </summary>
public class Group : IHasPermissions, IHasConcurrencyToken
{
/// <summary>
/// Initializes a new instance of the <see cref="Group"/> class.
/// </summary>
/// <param name="name">The name of the group.</param>
public Group(string name)
{
ArgumentException.ThrowIfNullOrEmpty(name);
Name = name;
Id = Guid.NewGuid();
Permissions = new HashSet<Permission>();
Preferences = new HashSet<Preference>();
}
/// <summary>
/// Gets the id of this group.
/// </summary>
/// <remarks>
/// Identity, Indexed, Required.
/// </remarks>
public Guid Id { get; private set; }
/// <summary>
/// Gets or sets the group's name.
/// </summary>
/// <remarks>
/// Required, Max length = 255.
/// </remarks>
[MaxLength(255)]
[StringLength(255)]
public string Name { get; set; }
/// <inheritdoc />
[ConcurrencyCheck]
public uint RowVersion { get; private set; }
/// <summary>
/// Gets a collection containing the group's permissions.
/// </summary>
public virtual ICollection<Permission> Permissions { get; private set; }
/// <summary>
/// Gets a collection containing the group's preferences.
/// </summary>
public virtual ICollection<Preference> Preferences { get; private set; }
/// <inheritdoc/>
public bool HasPermission(PermissionKind kind)
{
return Permissions.First(p => p.Kind == kind).Value;
}
/// <inheritdoc/>
public void SetPermission(PermissionKind kind, bool value)
{
Permissions.First(p => p.Kind == kind).Value = value;
}
/// <inheritdoc />
public void OnSavingChanges()
{
RowVersion++;
}
}
}

View File

@@ -1,44 +0,0 @@
using System.ComponentModel.DataAnnotations.Schema;
using Jellyfin.Data.Enums;
namespace Jellyfin.Data.Entities
{
/// <summary>
/// An entity representing a section on the user's home page.
/// </summary>
public class HomeSection
{
/// <summary>
/// Gets the id.
/// </summary>
/// <remarks>
/// Identity. Required.
/// </remarks>
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; private set; }
/// <summary>
/// Gets or sets the Id of the associated display preferences.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public int DisplayPreferencesId { get; set; }
/// <summary>
/// Gets or sets the order.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public int Order { get; set; }
/// <summary>
/// Gets or sets the type.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public HomeSectionType Type { get; set; }
}
}

View File

@@ -1,54 +0,0 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace Jellyfin.Data.Entities
{
/// <summary>
/// An entity representing an image.
/// </summary>
public class ImageInfo
{
/// <summary>
/// Initializes a new instance of the <see cref="ImageInfo"/> class.
/// </summary>
/// <param name="path">The path.</param>
public ImageInfo(string path)
{
Path = path;
LastModified = DateTime.UtcNow;
}
/// <summary>
/// Gets the id.
/// </summary>
/// <remarks>
/// Identity, Indexed, Required.
/// </remarks>
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; private set; }
/// <summary>
/// Gets the user id.
/// </summary>
public Guid? UserId { get; private set; }
/// <summary>
/// Gets or sets the path of the image.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
[MaxLength(512)]
[StringLength(512)]
public string Path { get; set; }
/// <summary>
/// Gets or sets the date last modified.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public DateTime LastModified { get; set; }
}
}

View File

@@ -1,76 +0,0 @@
namespace Jellyfin.Data.Entities;
/// <summary>
/// Enum ImageType.
/// </summary>
public enum ImageInfoImageType
{
/// <summary>
/// The primary.
/// </summary>
Primary = 0,
/// <summary>
/// The art.
/// </summary>
Art = 1,
/// <summary>
/// The backdrop.
/// </summary>
Backdrop = 2,
/// <summary>
/// The banner.
/// </summary>
Banner = 3,
/// <summary>
/// The logo.
/// </summary>
Logo = 4,
/// <summary>
/// The thumb.
/// </summary>
Thumb = 5,
/// <summary>
/// The disc.
/// </summary>
Disc = 6,
/// <summary>
/// The box.
/// </summary>
Box = 7,
/// <summary>
/// The screenshot.
/// </summary>
/// <remarks>
/// This enum value is obsolete.
/// XmlSerializer does not serialize/deserialize objects that are marked as [Obsolete].
/// </remarks>
Screenshot = 8,
/// <summary>
/// The menu.
/// </summary>
Menu = 9,
/// <summary>
/// The chapter image.
/// </summary>
Chapter = 10,
/// <summary>
/// The box rear.
/// </summary>
BoxRear = 11,
/// <summary>
/// The user profile image.
/// </summary>
Profile = 12
}

View File

@@ -1,113 +0,0 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Jellyfin.Data.Enums;
namespace Jellyfin.Data.Entities
{
/// <summary>
/// An entity that represents a user's display preferences for a specific item.
/// </summary>
public class ItemDisplayPreferences
{
/// <summary>
/// Initializes a new instance of the <see cref="ItemDisplayPreferences"/> class.
/// </summary>
/// <param name="userId">The user id.</param>
/// <param name="itemId">The item id.</param>
/// <param name="client">The client.</param>
public ItemDisplayPreferences(Guid userId, Guid itemId, string client)
{
UserId = userId;
ItemId = itemId;
Client = client;
SortBy = "SortName";
SortOrder = SortOrder.Ascending;
RememberSorting = false;
RememberIndexing = false;
}
/// <summary>
/// Gets the id.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; private set; }
/// <summary>
/// Gets or sets the user Id.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public Guid UserId { get; set; }
/// <summary>
/// Gets or sets the id of the associated item.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public Guid ItemId { get; set; }
/// <summary>
/// Gets or sets the client string.
/// </summary>
/// <remarks>
/// Required. Max Length = 32.
/// </remarks>
[MaxLength(32)]
[StringLength(32)]
public string Client { get; set; }
/// <summary>
/// Gets or sets the view type.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public ViewType ViewType { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the indexing should be remembered.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public bool RememberIndexing { get; set; }
/// <summary>
/// Gets or sets what the view should be indexed by.
/// </summary>
public IndexingKind? IndexBy { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the sorting type should be remembered.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public bool RememberSorting { get; set; }
/// <summary>
/// Gets or sets what the view should be sorted by.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
[MaxLength(64)]
[StringLength(64)]
public string SortBy { get; set; }
/// <summary>
/// Gets or sets the sort order.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public SortOrder SortOrder { get; set; }
}
}

View File

@@ -1,37 +0,0 @@
using System;
using System.Collections.Generic;
namespace Jellyfin.Data.Entities;
/// <summary>
/// Represents an ItemValue for a BaseItem.
/// </summary>
public class ItemValue
{
/// <summary>
/// Gets or Sets the ItemValueId.
/// </summary>
public required Guid ItemValueId { get; set; }
/// <summary>
/// Gets or Sets the Type.
/// </summary>
public required ItemValueType Type { get; set; }
/// <summary>
/// Gets or Sets the Value.
/// </summary>
public required string Value { get; set; }
/// <summary>
/// Gets or Sets the sanatised Value.
/// </summary>
public required string CleanValue { get; set; }
/// <summary>
/// Gets or Sets all associated BaseItems.
/// </summary>
#pragma warning disable CA2227 // Collection properties should be read only
public ICollection<ItemValueMap>? BaseItemsMap { get; set; }
#pragma warning restore CA2227 // Collection properties should be read only
}

View File

@@ -1,30 +0,0 @@
using System;
using System.Collections.Generic;
namespace Jellyfin.Data.Entities;
/// <summary>
/// Mapping table for the ItemValue BaseItem relation.
/// </summary>
public class ItemValueMap
{
/// <summary>
/// Gets or Sets the ItemId.
/// </summary>
public required Guid ItemId { get; set; }
/// <summary>
/// Gets or Sets the ItemValueId.
/// </summary>
public required Guid ItemValueId { get; set; }
/// <summary>
/// Gets or Sets the referenced <see cref="BaseItemEntity"/>.
/// </summary>
public required BaseItemEntity Item { get; set; }
/// <summary>
/// Gets or Sets the referenced <see cref="ItemValue"/>.
/// </summary>
public required ItemValue ItemValue { get; set; }
}

View File

@@ -1,38 +0,0 @@
#pragma warning disable CA1027 // Mark enums with FlagsAttribute
namespace Jellyfin.Data.Entities;
/// <summary>
/// Provides the Value types for an <see cref="ItemValue"/>.
/// </summary>
public enum ItemValueType
{
/// <summary>
/// Artists.
/// </summary>
Artist = 0,
/// <summary>
/// Album.
/// </summary>
AlbumArtist = 1,
/// <summary>
/// Genre.
/// </summary>
Genre = 2,
/// <summary>
/// Studios.
/// </summary>
Studios = 3,
/// <summary>
/// Tags.
/// </summary>
Tags = 4,
/// <summary>
/// InheritedTags.
/// </summary>
InheritedTags = 6,
}

View File

@@ -1,64 +0,0 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Jellyfin.Data.Enums;
using Jellyfin.Data.Interfaces;
namespace Jellyfin.Data.Entities.Libraries
{
/// <summary>
/// An entity representing artwork.
/// </summary>
public class Artwork : IHasConcurrencyToken
{
/// <summary>
/// Initializes a new instance of the <see cref="Artwork"/> class.
/// </summary>
/// <param name="path">The path.</param>
/// <param name="kind">The kind of art.</param>
public Artwork(string path, ArtKind kind)
{
ArgumentException.ThrowIfNullOrEmpty(path);
Path = path;
Kind = kind;
}
/// <summary>
/// Gets the id.
/// </summary>
/// <remarks>
/// Identity, Indexed, Required.
/// </remarks>
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; private set; }
/// <summary>
/// Gets or sets the path.
/// </summary>
/// <remarks>
/// Required, Max length = 65535.
/// </remarks>
[MaxLength(65535)]
[StringLength(65535)]
public string Path { get; set; }
/// <summary>
/// Gets or sets the kind of artwork.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public ArtKind Kind { get; set; }
/// <inheritdoc />
[ConcurrencyCheck]
public uint RowVersion { get; private set; }
/// <inheritdoc />
public void OnSavingChanges()
{
RowVersion++;
}
}
}

View File

@@ -1,29 +0,0 @@
using System.Collections.Generic;
using Jellyfin.Data.Interfaces;
namespace Jellyfin.Data.Entities.Libraries
{
/// <summary>
/// An entity representing a book.
/// </summary>
public class Book : LibraryItem, IHasReleases
{
/// <summary>
/// Initializes a new instance of the <see cref="Book"/> class.
/// </summary>
/// <param name="library">The library.</param>
public Book(Library library) : base(library)
{
BookMetadata = new HashSet<BookMetadata>();
Releases = new HashSet<Release>();
}
/// <summary>
/// Gets a collection containing the metadata for this book.
/// </summary>
public virtual ICollection<BookMetadata> BookMetadata { get; private set; }
/// <inheritdoc />
public virtual ICollection<Release> Releases { get; private set; }
}
}

View File

@@ -1,34 +0,0 @@
using System.Collections.Generic;
using Jellyfin.Data.Interfaces;
namespace Jellyfin.Data.Entities.Libraries
{
/// <summary>
/// An entity containing metadata for a book.
/// </summary>
public class BookMetadata : ItemMetadata, IHasCompanies
{
/// <summary>
/// Initializes a new instance of the <see cref="BookMetadata"/> class.
/// </summary>
/// <param name="title">The title or name of the object.</param>
/// <param name="language">ISO-639-3 3-character language codes.</param>
public BookMetadata(string title, string language) : base(title, language)
{
Publishers = new HashSet<Company>();
}
/// <summary>
/// Gets or sets the ISBN.
/// </summary>
public long? Isbn { get; set; }
/// <summary>
/// Gets a collection of the publishers for this book.
/// </summary>
public virtual ICollection<Company> Publishers { get; private set; }
/// <inheritdoc />
public ICollection<Company> Companies => Publishers;
}
}

View File

@@ -1,80 +0,0 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Jellyfin.Data.Interfaces;
namespace Jellyfin.Data.Entities.Libraries
{
/// <summary>
/// An entity representing a chapter.
/// </summary>
public class Chapter : IHasConcurrencyToken
{
/// <summary>
/// Initializes a new instance of the <see cref="Chapter"/> class.
/// </summary>
/// <param name="language">ISO-639-3 3-character language codes.</param>
/// <param name="startTime">The start time for this chapter.</param>
public Chapter(string language, long startTime)
{
ArgumentException.ThrowIfNullOrEmpty(language);
Language = language;
StartTime = startTime;
}
/// <summary>
/// Gets the id.
/// </summary>
/// <remarks>
/// Identity, Indexed, Required.
/// </remarks>
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; private set; }
/// <summary>
/// Gets or sets the name.
/// </summary>
/// <remarks>
/// Max length = 1024.
/// </remarks>
[MaxLength(1024)]
[StringLength(1024)]
public string? Name { get; set; }
/// <summary>
/// Gets or sets the language.
/// </summary>
/// <remarks>
/// Required, Min length = 3, Max length = 3
/// ISO-639-3 3-character language codes.
/// </remarks>
[MinLength(3)]
[MaxLength(3)]
[StringLength(3)]
public string Language { get; set; }
/// <summary>
/// Gets or sets the start time.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public long StartTime { get; set; }
/// <summary>
/// Gets or sets the end time.
/// </summary>
public long? EndTime { get; set; }
/// <inheritdoc />
[ConcurrencyCheck]
public uint RowVersion { get; private set; }
/// <inheritdoc />
public void OnSavingChanges()
{
RowVersion++;
}
}
}

View File

@@ -1,57 +0,0 @@
#pragma warning disable CA1711 // Identifiers should not have incorrect suffix
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Jellyfin.Data.Interfaces;
namespace Jellyfin.Data.Entities.Libraries
{
/// <summary>
/// An entity representing a collection.
/// </summary>
public class Collection : IHasConcurrencyToken
{
/// <summary>
/// Initializes a new instance of the <see cref="Collection"/> class.
/// </summary>
public Collection()
{
Items = new HashSet<CollectionItem>();
}
/// <summary>
/// Gets the id.
/// </summary>
/// <remarks>
/// Identity, Indexed, Required.
/// </remarks>
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; private set; }
/// <summary>
/// Gets or sets the name.
/// </summary>
/// <remarks>
/// Max length = 1024.
/// </remarks>
[MaxLength(1024)]
[StringLength(1024)]
public string? Name { get; set; }
/// <inheritdoc />
[ConcurrencyCheck]
public uint RowVersion { get; private set; }
/// <summary>
/// Gets a collection containing this collection's items.
/// </summary>
public virtual ICollection<CollectionItem> Items { get; private set; }
/// <inheritdoc />
public void OnSavingChanges()
{
RowVersion++;
}
}
}

View File

@@ -1,64 +0,0 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Jellyfin.Data.Interfaces;
namespace Jellyfin.Data.Entities.Libraries
{
/// <summary>
/// An entity representing a collection item.
/// </summary>
public class CollectionItem : IHasConcurrencyToken
{
/// <summary>
/// Initializes a new instance of the <see cref="CollectionItem"/> class.
/// </summary>
/// <param name="libraryItem">The library item.</param>
public CollectionItem(LibraryItem libraryItem)
{
LibraryItem = libraryItem;
}
/// <summary>
/// Gets or sets the id.
/// </summary>
/// <remarks>
/// Identity, Indexed, Required.
/// </remarks>
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
/// <inheritdoc />
[ConcurrencyCheck]
public uint RowVersion { get; private set; }
/// <summary>
/// Gets or sets the library item.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public virtual LibraryItem LibraryItem { get; set; }
/// <summary>
/// Gets or sets the next item in the collection.
/// </summary>
/// <remarks>
/// TODO check if this properly updated Dependant and has the proper principal relationship.
/// </remarks>
public virtual CollectionItem? Next { get; set; }
/// <summary>
/// Gets or sets the previous item in the collection.
/// </summary>
/// <remarks>
/// TODO check if this properly updated Dependant and has the proper principal relationship.
/// </remarks>
public virtual CollectionItem? Previous { get; set; }
/// <inheritdoc />
public void OnSavingChanges()
{
RowVersion++;
}
}
}

View File

@@ -1,54 +0,0 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Jellyfin.Data.Interfaces;
namespace Jellyfin.Data.Entities.Libraries
{
/// <summary>
/// An entity representing a company.
/// </summary>
public class Company : IHasCompanies, IHasConcurrencyToken
{
/// <summary>
/// Initializes a new instance of the <see cref="Company"/> class.
/// </summary>
public Company()
{
CompanyMetadata = new HashSet<CompanyMetadata>();
ChildCompanies = new HashSet<Company>();
}
/// <summary>
/// Gets the id.
/// </summary>
/// <remarks>
/// Identity, Indexed, Required.
/// </remarks>
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; private set; }
/// <inheritdoc />
[ConcurrencyCheck]
public uint RowVersion { get; private set; }
/// <summary>
/// Gets a collection containing the metadata.
/// </summary>
public virtual ICollection<CompanyMetadata> CompanyMetadata { get; private set; }
/// <summary>
/// Gets a collection containing this company's child companies.
/// </summary>
public virtual ICollection<Company> ChildCompanies { get; private set; }
/// <inheritdoc />
public ICollection<Company> Companies => ChildCompanies;
/// <inheritdoc />
public void OnSavingChanges()
{
RowVersion++;
}
}
}

View File

@@ -1,59 +0,0 @@
using System.ComponentModel.DataAnnotations;
namespace Jellyfin.Data.Entities.Libraries
{
/// <summary>
/// An entity holding metadata for a <see cref="Company"/>.
/// </summary>
public class CompanyMetadata : ItemMetadata
{
/// <summary>
/// Initializes a new instance of the <see cref="CompanyMetadata"/> class.
/// </summary>
/// <param name="title">The title or name of the object.</param>
/// <param name="language">ISO-639-3 3-character language codes.</param>
public CompanyMetadata(string title, string language) : base(title, language)
{
}
/// <summary>
/// Gets or sets the description.
/// </summary>
/// <remarks>
/// Max length = 65535.
/// </remarks>
[MaxLength(65535)]
[StringLength(65535)]
public string? Description { get; set; }
/// <summary>
/// Gets or sets the headquarters.
/// </summary>
/// <remarks>
/// Max length = 255.
/// </remarks>
[MaxLength(255)]
[StringLength(255)]
public string? Headquarters { get; set; }
/// <summary>
/// Gets or sets the country code.
/// </summary>
/// <remarks>
/// Max length = 2.
/// </remarks>
[MaxLength(2)]
[StringLength(2)]
public string? Country { get; set; }
/// <summary>
/// Gets or sets the homepage.
/// </summary>
/// <remarks>
/// Max length = 1024.
/// </remarks>
[MaxLength(1024)]
[StringLength(1024)]
public string? Homepage { get; set; }
}
}

View File

@@ -1,29 +0,0 @@
using System.Collections.Generic;
using Jellyfin.Data.Interfaces;
namespace Jellyfin.Data.Entities.Libraries
{
/// <summary>
/// An entity representing a custom item.
/// </summary>
public class CustomItem : LibraryItem, IHasReleases
{
/// <summary>
/// Initializes a new instance of the <see cref="CustomItem"/> class.
/// </summary>
/// <param name="library">The library.</param>
public CustomItem(Library library) : base(library)
{
CustomItemMetadata = new HashSet<CustomItemMetadata>();
Releases = new HashSet<Release>();
}
/// <summary>
/// Gets a collection containing the metadata for this item.
/// </summary>
public virtual ICollection<CustomItemMetadata> CustomItemMetadata { get; private set; }
/// <inheritdoc />
public virtual ICollection<Release> Releases { get; private set; }
}
}

View File

@@ -1,17 +0,0 @@
namespace Jellyfin.Data.Entities.Libraries
{
/// <summary>
/// An entity containing metadata for a custom item.
/// </summary>
public class CustomItemMetadata : ItemMetadata
{
/// <summary>
/// Initializes a new instance of the <see cref="CustomItemMetadata"/> class.
/// </summary>
/// <param name="title">The title or name of the object.</param>
/// <param name="language">ISO-639-3 3-character language codes.</param>
public CustomItemMetadata(string title, string language) : base(title, language)
{
}
}
}

View File

@@ -1,34 +0,0 @@
using System.Collections.Generic;
using Jellyfin.Data.Interfaces;
namespace Jellyfin.Data.Entities.Libraries
{
/// <summary>
/// An entity representing an episode.
/// </summary>
public class Episode : LibraryItem, IHasReleases
{
/// <summary>
/// Initializes a new instance of the <see cref="Episode"/> class.
/// </summary>
/// <param name="library">The library.</param>
public Episode(Library library) : base(library)
{
Releases = new HashSet<Release>();
EpisodeMetadata = new HashSet<EpisodeMetadata>();
}
/// <summary>
/// Gets or sets the episode number.
/// </summary>
public int? EpisodeNumber { get; set; }
/// <inheritdoc />
public virtual ICollection<Release> Releases { get; private set; }
/// <summary>
/// Gets a collection containing the metadata for this episode.
/// </summary>
public virtual ICollection<EpisodeMetadata> EpisodeMetadata { get; private set; }
}
}

View File

@@ -1,49 +0,0 @@
using System.ComponentModel.DataAnnotations;
namespace Jellyfin.Data.Entities.Libraries
{
/// <summary>
/// An entity containing metadata for an <see cref="Episode"/>.
/// </summary>
public class EpisodeMetadata : ItemMetadata
{
/// <summary>
/// Initializes a new instance of the <see cref="EpisodeMetadata"/> class.
/// </summary>
/// <param name="title">The title or name of the object.</param>
/// <param name="language">ISO-639-3 3-character language codes.</param>
public EpisodeMetadata(string title, string language) : base(title, language)
{
}
/// <summary>
/// Gets or sets the outline.
/// </summary>
/// <remarks>
/// Max length = 1024.
/// </remarks>
[MaxLength(1024)]
[StringLength(1024)]
public string? Outline { get; set; }
/// <summary>
/// Gets or sets the plot.
/// </summary>
/// <remarks>
/// Max length = 65535.
/// </remarks>
[MaxLength(65535)]
[StringLength(65535)]
public string? Plot { get; set; }
/// <summary>
/// Gets or sets the tagline.
/// </summary>
/// <remarks>
/// Max length = 1024.
/// </remarks>
[MaxLength(1024)]
[StringLength(1024)]
public string? Tagline { get; set; }
}
}

View File

@@ -1,50 +0,0 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Jellyfin.Data.Interfaces;
namespace Jellyfin.Data.Entities.Libraries
{
/// <summary>
/// An entity representing a genre.
/// </summary>
public class Genre : IHasConcurrencyToken
{
/// <summary>
/// Initializes a new instance of the <see cref="Genre"/> class.
/// </summary>
/// <param name="name">The name.</param>
public Genre(string name)
{
Name = name;
}
/// <summary>
/// Gets the id.
/// </summary>
/// <remarks>
/// Identity, Indexed, Required.
/// </remarks>
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; private set; }
/// <summary>
/// Gets or sets the name.
/// </summary>
/// <remarks>
/// Indexed, Required, Max length = 255.
/// </remarks>
[MaxLength(255)]
[StringLength(255)]
public string Name { get; set; }
/// <inheritdoc />
[ConcurrencyCheck]
public uint RowVersion { get; private set; }
/// <inheritdoc />
public void OnSavingChanges()
{
RowVersion++;
}
}
}

View File

@@ -1,141 +0,0 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Jellyfin.Data.Interfaces;
namespace Jellyfin.Data.Entities.Libraries
{
/// <summary>
/// An abstract class that holds metadata.
/// </summary>
public abstract class ItemMetadata : IHasArtwork, IHasConcurrencyToken
{
/// <summary>
/// Initializes a new instance of the <see cref="ItemMetadata"/> class.
/// </summary>
/// <param name="title">The title or name of the object.</param>
/// <param name="language">ISO-639-3 3-character language codes.</param>
protected ItemMetadata(string title, string language)
{
ArgumentException.ThrowIfNullOrEmpty(title);
ArgumentException.ThrowIfNullOrEmpty(language);
Title = title;
Language = language;
DateAdded = DateTime.UtcNow;
DateModified = DateAdded;
PersonRoles = new HashSet<PersonRole>();
Genres = new HashSet<Genre>();
Artwork = new HashSet<Artwork>();
Ratings = new HashSet<Rating>();
Sources = new HashSet<MetadataProviderId>();
}
/// <summary>
/// Gets the id.
/// </summary>
/// <remarks>
/// Identity, Indexed, Required.
/// </remarks>
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; private set; }
/// <summary>
/// Gets or sets the title.
/// </summary>
/// <remarks>
/// Required, Max length = 1024.
/// </remarks>
[MaxLength(1024)]
[StringLength(1024)]
public string Title { get; set; }
/// <summary>
/// Gets or sets the original title.
/// </summary>
/// <remarks>
/// Max length = 1024.
/// </remarks>
[MaxLength(1024)]
[StringLength(1024)]
public string? OriginalTitle { get; set; }
/// <summary>
/// Gets or sets the sort title.
/// </summary>
/// <remarks>
/// Max length = 1024.
/// </remarks>
[MaxLength(1024)]
[StringLength(1024)]
public string? SortTitle { get; set; }
/// <summary>
/// Gets or sets the language.
/// </summary>
/// <remarks>
/// Required, Min length = 3, Max length = 3.
/// ISO-639-3 3-character language codes.
/// </remarks>
[MinLength(3)]
[MaxLength(3)]
[StringLength(3)]
public string Language { get; set; }
/// <summary>
/// Gets or sets the release date.
/// </summary>
public DateTimeOffset? ReleaseDate { get; set; }
/// <summary>
/// Gets the date added.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public DateTime DateAdded { get; private set; }
/// <summary>
/// Gets or sets the date modified.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public DateTime DateModified { get; set; }
/// <inheritdoc />
[ConcurrencyCheck]
public uint RowVersion { get; private set; }
/// <summary>
/// Gets a collection containing the person roles for this item.
/// </summary>
public virtual ICollection<PersonRole> PersonRoles { get; private set; }
/// <summary>
/// Gets a collection containing the genres for this item.
/// </summary>
public virtual ICollection<Genre> Genres { get; private set; }
/// <inheritdoc />
public virtual ICollection<Artwork> Artwork { get; private set; }
/// <summary>
/// Gets a collection containing the ratings for this item.
/// </summary>
public virtual ICollection<Rating> Ratings { get; private set; }
/// <summary>
/// Gets a collection containing the metadata sources for this item.
/// </summary>
public virtual ICollection<MetadataProviderId> Sources { get; private set; }
/// <inheritdoc />
public void OnSavingChanges()
{
RowVersion++;
}
}
}

View File

@@ -1,60 +0,0 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Jellyfin.Data.Interfaces;
namespace Jellyfin.Data.Entities.Libraries
{
/// <summary>
/// An entity representing a library.
/// </summary>
public class Library : IHasConcurrencyToken
{
/// <summary>
/// Initializes a new instance of the <see cref="Library"/> class.
/// </summary>
/// <param name="name">The name of the library.</param>
/// <param name="path">The path of the library.</param>
public Library(string name, string path)
{
Name = name;
Path = path;
}
/// <summary>
/// Gets the id.
/// </summary>
/// <remarks>
/// Identity, Indexed, Required.
/// </remarks>
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; private set; }
/// <summary>
/// Gets or sets the name.
/// </summary>
/// <remarks>
/// Required, Max length = 128.
/// </remarks>
[MaxLength(128)]
[StringLength(128)]
public string Name { get; set; }
/// <summary>
/// Gets or sets the root path of the library.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public string Path { get; set; }
/// <inheritdoc />
[ConcurrencyCheck]
public uint RowVersion { get; private set; }
/// <inheritdoc />
public void OnSavingChanges()
{
RowVersion++;
}
}
}

View File

@@ -1,55 +0,0 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Jellyfin.Data.Interfaces;
namespace Jellyfin.Data.Entities.Libraries
{
/// <summary>
/// An entity representing a library item.
/// </summary>
public abstract class LibraryItem : IHasConcurrencyToken
{
/// <summary>
/// Initializes a new instance of the <see cref="LibraryItem"/> class.
/// </summary>
/// <param name="library">The library of this item.</param>
protected LibraryItem(Library library)
{
DateAdded = DateTime.UtcNow;
Library = library;
}
/// <summary>
/// Gets the id.
/// </summary>
/// <remarks>
/// Identity, Indexed, Required.
/// </remarks>
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; private set; }
/// <summary>
/// Gets the date this library item was added.
/// </summary>
public DateTime DateAdded { get; private set; }
/// <inheritdoc />
[ConcurrencyCheck]
public uint RowVersion { get; private set; }
/// <summary>
/// Gets or sets the library of this item.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public virtual Library Library { get; set; }
/// <inheritdoc />
public void OnSavingChanges()
{
RowVersion++;
}
}
}

View File

@@ -1,72 +0,0 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Jellyfin.Data.Enums;
using Jellyfin.Data.Interfaces;
namespace Jellyfin.Data.Entities.Libraries
{
/// <summary>
/// An entity representing a file on disk.
/// </summary>
public class MediaFile : IHasConcurrencyToken
{
/// <summary>
/// Initializes a new instance of the <see cref="MediaFile"/> class.
/// </summary>
/// <param name="path">The path relative to the LibraryRoot.</param>
/// <param name="kind">The file kind.</param>
public MediaFile(string path, MediaFileKind kind)
{
ArgumentException.ThrowIfNullOrEmpty(path);
Path = path;
Kind = kind;
MediaFileStreams = new HashSet<MediaFileStream>();
}
/// <summary>
/// Gets the id.
/// </summary>
/// <remarks>
/// Identity, Indexed, Required.
/// </remarks>
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; private set; }
/// <summary>
/// Gets or sets the path relative to the library root.
/// </summary>
/// <remarks>
/// Required, Max length = 65535.
/// </remarks>
[MaxLength(65535)]
[StringLength(65535)]
public string Path { get; set; }
/// <summary>
/// Gets or sets the kind of media file.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public MediaFileKind Kind { get; set; }
/// <inheritdoc />
[ConcurrencyCheck]
public uint RowVersion { get; private set; }
/// <summary>
/// Gets a collection containing the streams in this file.
/// </summary>
public virtual ICollection<MediaFileStream> MediaFileStreams { get; private set; }
/// <inheritdoc />
public void OnSavingChanges()
{
RowVersion++;
}
}
}

View File

@@ -1,50 +0,0 @@
#pragma warning disable CA1711 // Identifiers should not have incorrect suffix
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Jellyfin.Data.Interfaces;
namespace Jellyfin.Data.Entities.Libraries
{
/// <summary>
/// An entity representing a stream in a media file.
/// </summary>
public class MediaFileStream : IHasConcurrencyToken
{
/// <summary>
/// Initializes a new instance of the <see cref="MediaFileStream"/> class.
/// </summary>
/// <param name="streamNumber">The number of this stream.</param>
public MediaFileStream(int streamNumber)
{
StreamNumber = streamNumber;
}
/// <summary>
/// Gets the id.
/// </summary>
/// <remarks>
/// Identity, Indexed, Required.
/// </remarks>
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; private set; }
/// <summary>
/// Gets or sets the stream number.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public int StreamNumber { get; set; }
/// <inheritdoc />
[ConcurrencyCheck]
public uint RowVersion { get; private set; }
/// <inheritdoc />
public void OnSavingChanges()
{
RowVersion++;
}
}
}

View File

@@ -1,53 +0,0 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Jellyfin.Data.Interfaces;
namespace Jellyfin.Data.Entities.Libraries
{
/// <summary>
/// An entity representing a metadata provider.
/// </summary>
public class MetadataProvider : IHasConcurrencyToken
{
/// <summary>
/// Initializes a new instance of the <see cref="MetadataProvider"/> class.
/// </summary>
/// <param name="name">The name of the metadata provider.</param>
public MetadataProvider(string name)
{
ArgumentException.ThrowIfNullOrEmpty(name);
Name = name;
}
/// <summary>
/// Gets the id.
/// </summary>
/// <remarks>
/// Identity, Indexed, Required.
/// </remarks>
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; private set; }
/// <summary>
/// Gets or sets the name.
/// </summary>
/// <remarks>
/// Required, Max length = 1024.
/// </remarks>
[MaxLength(1024)]
[StringLength(1024)]
public string Name { get; set; }
/// <inheritdoc />
[ConcurrencyCheck]
public uint RowVersion { get; private set; }
/// <inheritdoc />
public void OnSavingChanges()
{
RowVersion++;
}
}
}

View File

@@ -1,63 +0,0 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Jellyfin.Data.Interfaces;
namespace Jellyfin.Data.Entities.Libraries
{
/// <summary>
/// An entity representing a unique identifier for a metadata provider.
/// </summary>
public class MetadataProviderId : IHasConcurrencyToken
{
/// <summary>
/// Initializes a new instance of the <see cref="MetadataProviderId"/> class.
/// </summary>
/// <param name="providerId">The provider id.</param>
/// <param name="metadataProvider">The metadata provider.</param>
public MetadataProviderId(string providerId, MetadataProvider metadataProvider)
{
ArgumentException.ThrowIfNullOrEmpty(providerId);
ProviderId = providerId;
MetadataProvider = metadataProvider;
}
/// <summary>
/// Gets the id.
/// </summary>
/// <remarks>
/// Identity, Indexed, Required.
/// </remarks>
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; private set; }
/// <summary>
/// Gets or sets the provider id.
/// </summary>
/// <remarks>
/// Required, Max length = 255.
/// </remarks>
[MaxLength(255)]
[StringLength(255)]
public string ProviderId { get; set; }
/// <inheritdoc />
[ConcurrencyCheck]
public uint RowVersion { get; private set; }
/// <summary>
/// Gets or sets the metadata provider.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public virtual MetadataProvider MetadataProvider { get; set; }
/// <inheritdoc />
public void OnSavingChanges()
{
RowVersion++;
}
}
}

View File

@@ -1,29 +0,0 @@
using System.Collections.Generic;
using Jellyfin.Data.Interfaces;
namespace Jellyfin.Data.Entities.Libraries
{
/// <summary>
/// An entity representing a movie.
/// </summary>
public class Movie : LibraryItem, IHasReleases
{
/// <summary>
/// Initializes a new instance of the <see cref="Movie"/> class.
/// </summary>
/// <param name="library">The library.</param>
public Movie(Library library) : base(library)
{
Releases = new HashSet<Release>();
MovieMetadata = new HashSet<MovieMetadata>();
}
/// <inheritdoc />
public virtual ICollection<Release> Releases { get; private set; }
/// <summary>
/// Gets a collection containing the metadata for this movie.
/// </summary>
public virtual ICollection<MovieMetadata> MovieMetadata { get; private set; }
}
}

View File

@@ -1,70 +0,0 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using Jellyfin.Data.Interfaces;
namespace Jellyfin.Data.Entities.Libraries
{
/// <summary>
/// An entity holding the metadata for a movie.
/// </summary>
public class MovieMetadata : ItemMetadata, IHasCompanies
{
/// <summary>
/// Initializes a new instance of the <see cref="MovieMetadata"/> class.
/// </summary>
/// <param name="title">The title or name of the movie.</param>
/// <param name="language">ISO-639-3 3-character language codes.</param>
public MovieMetadata(string title, string language) : base(title, language)
{
Studios = new HashSet<Company>();
}
/// <summary>
/// Gets or sets the outline.
/// </summary>
/// <remarks>
/// Max length = 1024.
/// </remarks>
[MaxLength(1024)]
[StringLength(1024)]
public string? Outline { get; set; }
/// <summary>
/// Gets or sets the tagline.
/// </summary>
/// <remarks>
/// Max length = 1024.
/// </remarks>
[MaxLength(1024)]
[StringLength(1024)]
public string? Tagline { get; set; }
/// <summary>
/// Gets or sets the plot.
/// </summary>
/// <remarks>
/// Max length = 65535.
/// </remarks>
[MaxLength(65535)]
[StringLength(65535)]
public string? Plot { get; set; }
/// <summary>
/// Gets or sets the country code.
/// </summary>
/// <remarks>
/// Max length = 2.
/// </remarks>
[MaxLength(2)]
[StringLength(2)]
public string? Country { get; set; }
/// <summary>
/// Gets the studios that produced this movie.
/// </summary>
public virtual ICollection<Company> Studios { get; private set; }
/// <inheritdoc />
public ICollection<Company> Companies => Studios;
}
}

View File

@@ -1,30 +0,0 @@
using System.Collections.Generic;
namespace Jellyfin.Data.Entities.Libraries
{
/// <summary>
/// An entity representing a music album.
/// </summary>
public class MusicAlbum : LibraryItem
{
/// <summary>
/// Initializes a new instance of the <see cref="MusicAlbum"/> class.
/// </summary>
/// <param name="library">The library.</param>
public MusicAlbum(Library library) : base(library)
{
MusicAlbumMetadata = new HashSet<MusicAlbumMetadata>();
Tracks = new HashSet<Track>();
}
/// <summary>
/// Gets a collection containing the album metadata.
/// </summary>
public virtual ICollection<MusicAlbumMetadata> MusicAlbumMetadata { get; private set; }
/// <summary>
/// Gets a collection containing the tracks.
/// </summary>
public virtual ICollection<Track> Tracks { get; private set; }
}
}

View File

@@ -1,56 +0,0 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace Jellyfin.Data.Entities.Libraries
{
/// <summary>
/// An entity holding the metadata for a music album.
/// </summary>
public class MusicAlbumMetadata : ItemMetadata
{
/// <summary>
/// Initializes a new instance of the <see cref="MusicAlbumMetadata"/> class.
/// </summary>
/// <param name="title">The title or name of the album.</param>
/// <param name="language">ISO-639-3 3-character language codes.</param>
public MusicAlbumMetadata(string title, string language) : base(title, language)
{
Labels = new HashSet<Company>();
}
/// <summary>
/// Gets or sets the barcode.
/// </summary>
/// <remarks>
/// Max length = 255.
/// </remarks>
[MaxLength(255)]
[StringLength(255)]
public string? Barcode { get; set; }
/// <summary>
/// Gets or sets the label number.
/// </summary>
/// <remarks>
/// Max length = 255.
/// </remarks>
[MaxLength(255)]
[StringLength(255)]
public string? LabelNumber { get; set; }
/// <summary>
/// Gets or sets the country code.
/// </summary>
/// <remarks>
/// Max length = 2.
/// </remarks>
[MaxLength(2)]
[StringLength(2)]
public string? Country { get; set; }
/// <summary>
/// Gets a collection containing the labels.
/// </summary>
public virtual ICollection<Company> Labels { get; private set; }
}
}

View File

@@ -1,89 +0,0 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Jellyfin.Data.Interfaces;
namespace Jellyfin.Data.Entities.Libraries
{
/// <summary>
/// An entity representing a person.
/// </summary>
public class Person : IHasConcurrencyToken
{
/// <summary>
/// Initializes a new instance of the <see cref="Person"/> class.
/// </summary>
/// <param name="name">The name of the person.</param>
public Person(string name)
{
ArgumentException.ThrowIfNullOrEmpty(name);
Name = name;
DateAdded = DateTime.UtcNow;
DateModified = DateAdded;
Sources = new HashSet<MetadataProviderId>();
}
/// <summary>
/// Gets the id.
/// </summary>
/// <remarks>
/// Identity, Indexed, Required.
/// </remarks>
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; private set; }
/// <summary>
/// Gets or sets the name.
/// </summary>
/// <remarks>
/// Required, Max length = 1024.
/// </remarks>
[MaxLength(1024)]
[StringLength(1024)]
public string Name { get; set; }
/// <summary>
/// Gets or sets the source id.
/// </summary>
/// <remarks>
/// Max length = 255.
/// </remarks>
[MaxLength(256)]
[StringLength(256)]
public string? SourceId { get; set; }
/// <summary>
/// Gets the date added.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public DateTime DateAdded { get; private set; }
/// <summary>
/// Gets or sets the date modified.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public DateTime DateModified { get; set; }
/// <inheritdoc />
[ConcurrencyCheck]
public uint RowVersion { get; private set; }
/// <summary>
/// Gets a list of metadata sources for this person.
/// </summary>
public virtual ICollection<MetadataProviderId> Sources { get; private set; }
/// <inheritdoc />
public void OnSavingChanges()
{
RowVersion++;
}
}
}

View File

@@ -1,80 +0,0 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Jellyfin.Data.Enums;
using Jellyfin.Data.Interfaces;
namespace Jellyfin.Data.Entities.Libraries
{
/// <summary>
/// An entity representing a person's role in media.
/// </summary>
public class PersonRole : IHasArtwork, IHasConcurrencyToken
{
/// <summary>
/// Initializes a new instance of the <see cref="PersonRole"/> class.
/// </summary>
/// <param name="type">The role type.</param>
/// <param name="person">The person.</param>
public PersonRole(PersonRoleType type, Person person)
{
Type = type;
Person = person;
Artwork = new HashSet<Artwork>();
Sources = new HashSet<MetadataProviderId>();
}
/// <summary>
/// Gets the id.
/// </summary>
/// <remarks>
/// Identity, Indexed, Required.
/// </remarks>
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; private set; }
/// <summary>
/// Gets or sets the name of the person's role.
/// </summary>
/// <remarks>
/// Max length = 1024.
/// </remarks>
[MaxLength(1024)]
[StringLength(1024)]
public string? Role { get; set; }
/// <summary>
/// Gets or sets the person's role type.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public PersonRoleType Type { get; set; }
/// <inheritdoc />
[ConcurrencyCheck]
public uint RowVersion { get; private set; }
/// <summary>
/// Gets or sets the person.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public virtual Person Person { get; set; }
/// <inheritdoc />
public virtual ICollection<Artwork> Artwork { get; private set; }
/// <summary>
/// Gets a collection containing the metadata sources for this person role.
/// </summary>
public virtual ICollection<MetadataProviderId> Sources { get; private set; }
/// <inheritdoc />
public void OnSavingChanges()
{
RowVersion++;
}
}
}

View File

@@ -1,29 +0,0 @@
using System.Collections.Generic;
using Jellyfin.Data.Interfaces;
namespace Jellyfin.Data.Entities.Libraries
{
/// <summary>
/// An entity representing a photo.
/// </summary>
public class Photo : LibraryItem, IHasReleases
{
/// <summary>
/// Initializes a new instance of the <see cref="Photo"/> class.
/// </summary>
/// <param name="library">The library.</param>
public Photo(Library library) : base(library)
{
PhotoMetadata = new HashSet<PhotoMetadata>();
Releases = new HashSet<Release>();
}
/// <summary>
/// Gets a collection containing the photo metadata.
/// </summary>
public virtual ICollection<PhotoMetadata> PhotoMetadata { get; private set; }
/// <inheritdoc />
public virtual ICollection<Release> Releases { get; private set; }
}
}

View File

@@ -1,17 +0,0 @@
namespace Jellyfin.Data.Entities.Libraries
{
/// <summary>
/// An entity that holds metadata for a photo.
/// </summary>
public class PhotoMetadata : ItemMetadata
{
/// <summary>
/// Initializes a new instance of the <see cref="PhotoMetadata"/> class.
/// </summary>
/// <param name="title">The title or name of the photo.</param>
/// <param name="language">ISO-639-3 3-character language codes.</param>
public PhotoMetadata(string title, string language) : base(title, language)
{
}
}
}

View File

@@ -1,59 +0,0 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Jellyfin.Data.Interfaces;
namespace Jellyfin.Data.Entities.Libraries
{
/// <summary>
/// An entity representing a rating for an entity.
/// </summary>
public class Rating : IHasConcurrencyToken
{
/// <summary>
/// Initializes a new instance of the <see cref="Rating"/> class.
/// </summary>
/// <param name="value">The value.</param>
public Rating(double value)
{
Value = value;
}
/// <summary>
/// Gets the id.
/// </summary>
/// <remarks>
/// Identity, Indexed, Required.
/// </remarks>
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; private set; }
/// <summary>
/// Gets or sets the value.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public double Value { get; set; }
/// <summary>
/// Gets or sets the number of votes.
/// </summary>
public int? Votes { get; set; }
/// <inheritdoc />
[ConcurrencyCheck]
public uint RowVersion { get; private set; }
/// <summary>
/// Gets or sets the rating type.
/// If this is <c>null</c> it's the internal user rating.
/// </summary>
public virtual RatingSource? RatingType { get; set; }
/// <inheritdoc />
public void OnSavingChanges()
{
RowVersion++;
}
}
}

View File

@@ -1,73 +0,0 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Jellyfin.Data.Interfaces;
namespace Jellyfin.Data.Entities.Libraries
{
/// <summary>
/// This is the entity to store review ratings, not age ratings.
/// </summary>
public class RatingSource : IHasConcurrencyToken
{
/// <summary>
/// Initializes a new instance of the <see cref="RatingSource"/> class.
/// </summary>
/// <param name="minimumValue">The minimum value.</param>
/// <param name="maximumValue">The maximum value.</param>
public RatingSource(double minimumValue, double maximumValue)
{
MinimumValue = minimumValue;
MaximumValue = maximumValue;
}
/// <summary>
/// Gets the id.
/// </summary>
/// <remarks>
/// Identity, Indexed, Required.
/// </remarks>
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; private set; }
/// <summary>
/// Gets or sets the name.
/// </summary>
/// <remarks>
/// Max length = 1024.
/// </remarks>
[MaxLength(1024)]
[StringLength(1024)]
public string? Name { get; set; }
/// <summary>
/// Gets or sets the minimum value.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public double MinimumValue { get; set; }
/// <summary>
/// Gets or sets the maximum value.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public double MaximumValue { get; set; }
/// <inheritdoc />
[ConcurrencyCheck]
public uint RowVersion { get; private set; }
/// <summary>
/// Gets or sets the metadata source.
/// </summary>
public virtual MetadataProviderId? Source { get; set; }
/// <inheritdoc />
public void OnSavingChanges()
{
RowVersion++;
}
}
}

View File

@@ -1,67 +0,0 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Jellyfin.Data.Interfaces;
namespace Jellyfin.Data.Entities.Libraries
{
/// <summary>
/// An entity representing a release for a library item, eg. Director's cut vs. standard.
/// </summary>
public class Release : IHasConcurrencyToken
{
/// <summary>
/// Initializes a new instance of the <see cref="Release"/> class.
/// </summary>
/// <param name="name">The name of this release.</param>
public Release(string name)
{
ArgumentException.ThrowIfNullOrEmpty(name);
Name = name;
MediaFiles = new HashSet<MediaFile>();
Chapters = new HashSet<Chapter>();
}
/// <summary>
/// Gets the id.
/// </summary>
/// <remarks>
/// Identity, Indexed, Required.
/// </remarks>
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; private set; }
/// <summary>
/// Gets or sets the name.
/// </summary>
/// <remarks>
/// Required, Max length = 1024.
/// </remarks>
[MaxLength(1024)]
[StringLength(1024)]
public string Name { get; set; }
/// <inheritdoc />
[ConcurrencyCheck]
public uint RowVersion { get; private set; }
/// <summary>
/// Gets a collection containing the media files for this release.
/// </summary>
public virtual ICollection<MediaFile> MediaFiles { get; private set; }
/// <summary>
/// Gets a collection containing the chapters for this release.
/// </summary>
public virtual ICollection<Chapter> Chapters { get; private set; }
/// <inheritdoc />
public void OnSavingChanges()
{
RowVersion++;
}
}
}

View File

@@ -1,35 +0,0 @@
using System.Collections.Generic;
namespace Jellyfin.Data.Entities.Libraries
{
/// <summary>
/// An entity representing a season.
/// </summary>
public class Season : LibraryItem
{
/// <summary>
/// Initializes a new instance of the <see cref="Season"/> class.
/// </summary>
/// <param name="library">The library.</param>
public Season(Library library) : base(library)
{
Episodes = new HashSet<Episode>();
SeasonMetadata = new HashSet<SeasonMetadata>();
}
/// <summary>
/// Gets or sets the season number.
/// </summary>
public int? SeasonNumber { get; set; }
/// <summary>
/// Gets the season metadata.
/// </summary>
public virtual ICollection<SeasonMetadata> SeasonMetadata { get; private set; }
/// <summary>
/// Gets a collection containing the number of episodes.
/// </summary>
public virtual ICollection<Episode> Episodes { get; private set; }
}
}

View File

@@ -1,29 +0,0 @@
using System.ComponentModel.DataAnnotations;
namespace Jellyfin.Data.Entities.Libraries
{
/// <summary>
/// An entity that holds metadata for seasons.
/// </summary>
public class SeasonMetadata : ItemMetadata
{
/// <summary>
/// Initializes a new instance of the <see cref="SeasonMetadata"/> class.
/// </summary>
/// <param name="title">The title or name of the object.</param>
/// <param name="language">ISO-639-3 3-character language codes.</param>
public SeasonMetadata(string title, string language) : base(title, language)
{
}
/// <summary>
/// Gets or sets the outline.
/// </summary>
/// <remarks>
/// Max length = 1024.
/// </remarks>
[MaxLength(1024)]
[StringLength(1024)]
public string? Outline { get; set; }
}
}

View File

@@ -1,46 +0,0 @@
using System;
using System.Collections.Generic;
namespace Jellyfin.Data.Entities.Libraries
{
/// <summary>
/// An entity representing a a series.
/// </summary>
public class Series : LibraryItem
{
/// <summary>
/// Initializes a new instance of the <see cref="Series"/> class.
/// </summary>
/// <param name="library">The library.</param>
public Series(Library library) : base(library)
{
Seasons = new HashSet<Season>();
SeriesMetadata = new HashSet<SeriesMetadata>();
}
/// <summary>
/// Gets or sets the days of week.
/// </summary>
public DayOfWeek? AirsDayOfWeek { get; set; }
/// <summary>
/// Gets or sets the time the show airs, ignore the date portion.
/// </summary>
public DateTimeOffset? AirsTime { get; set; }
/// <summary>
/// Gets or sets the date the series first aired.
/// </summary>
public DateTime? FirstAired { get; set; }
/// <summary>
/// Gets a collection containing the series metadata.
/// </summary>
public virtual ICollection<SeriesMetadata> SeriesMetadata { get; private set; }
/// <summary>
/// Gets a collection containing the seasons.
/// </summary>
public virtual ICollection<Season> Seasons { get; private set; }
}
}

View File

@@ -1,70 +0,0 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using Jellyfin.Data.Interfaces;
namespace Jellyfin.Data.Entities.Libraries
{
/// <summary>
/// An entity representing series metadata.
/// </summary>
public class SeriesMetadata : ItemMetadata, IHasCompanies
{
/// <summary>
/// Initializes a new instance of the <see cref="SeriesMetadata"/> class.
/// </summary>
/// <param name="title">The title or name of the object.</param>
/// <param name="language">ISO-639-3 3-character language codes.</param>
public SeriesMetadata(string title, string language) : base(title, language)
{
Networks = new HashSet<Company>();
}
/// <summary>
/// Gets or sets the outline.
/// </summary>
/// <remarks>
/// Max length = 1024.
/// </remarks>
[MaxLength(1024)]
[StringLength(1024)]
public string? Outline { get; set; }
/// <summary>
/// Gets or sets the plot.
/// </summary>
/// <remarks>
/// Max length = 65535.
/// </remarks>
[MaxLength(65535)]
[StringLength(65535)]
public string? Plot { get; set; }
/// <summary>
/// Gets or sets the tagline.
/// </summary>
/// <remarks>
/// Max length = 1024.
/// </remarks>
[MaxLength(1024)]
[StringLength(1024)]
public string? Tagline { get; set; }
/// <summary>
/// Gets or sets the country code.
/// </summary>
/// <remarks>
/// Max length = 2.
/// </remarks>
[MaxLength(2)]
[StringLength(2)]
public string? Country { get; set; }
/// <summary>
/// Gets a collection containing the networks.
/// </summary>
public virtual ICollection<Company> Networks { get; private set; }
/// <inheritdoc />
public ICollection<Company> Companies => Networks;
}
}

View File

@@ -1,34 +0,0 @@
using System.Collections.Generic;
using Jellyfin.Data.Interfaces;
namespace Jellyfin.Data.Entities.Libraries
{
/// <summary>
/// An entity representing a track.
/// </summary>
public class Track : LibraryItem, IHasReleases
{
/// <summary>
/// Initializes a new instance of the <see cref="Track"/> class.
/// </summary>
/// <param name="library">The library.</param>
public Track(Library library) : base(library)
{
Releases = new HashSet<Release>();
TrackMetadata = new HashSet<TrackMetadata>();
}
/// <summary>
/// Gets or sets the track number.
/// </summary>
public int? TrackNumber { get; set; }
/// <inheritdoc />
public virtual ICollection<Release> Releases { get; private set; }
/// <summary>
/// Gets a collection containing the track metadata.
/// </summary>
public virtual ICollection<TrackMetadata> TrackMetadata { get; private set; }
}
}

View File

@@ -1,17 +0,0 @@
namespace Jellyfin.Data.Entities.Libraries
{
/// <summary>
/// An entity holding metadata for a track.
/// </summary>
public class TrackMetadata : ItemMetadata
{
/// <summary>
/// Initializes a new instance of the <see cref="TrackMetadata"/> class.
/// </summary>
/// <param name="title">The title or name of the object.</param>
/// <param name="language">ISO-639-3 3-character language codes.</param>
public TrackMetadata(string title, string language) : base(title, language)
{
}
}
}

View File

@@ -1,42 +0,0 @@
using System;
using System.ComponentModel.DataAnnotations.Schema;
using Jellyfin.Data.Enums;
namespace Jellyfin.Data.Entities;
/// <summary>
/// An entity representing the metadata for a group of trickplay tiles.
/// </summary>
public class MediaSegment
{
/// <summary>
/// Gets or sets the id of the media segment.
/// </summary>
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid Id { get; set; }
/// <summary>
/// Gets or sets the id of the associated item.
/// </summary>
public Guid ItemId { get; set; }
/// <summary>
/// Gets or sets the Type of content this segment defines.
/// </summary>
public MediaSegmentType Type { get; set; }
/// <summary>
/// Gets or sets the end of the segment.
/// </summary>
public long EndTicks { get; set; }
/// <summary>
/// Gets or sets the start of the segment.
/// </summary>
public long StartTicks { get; set; }
/// <summary>
/// Gets or sets Id of the media segment provider this entry originates from.
/// </summary>
public required string SegmentProviderId { get; set; }
}

View File

@@ -1,103 +0,0 @@
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
using System;
using System.Diagnostics.CodeAnalysis;
namespace Jellyfin.Data.Entities;
public class MediaStreamInfo
{
public required Guid ItemId { get; set; }
public required BaseItemEntity Item { get; set; }
public int StreamIndex { get; set; }
public required MediaStreamTypeEntity StreamType { get; set; }
public string? Codec { get; set; }
public string? Language { get; set; }
public string? ChannelLayout { get; set; }
public string? Profile { get; set; }
public string? AspectRatio { get; set; }
public string? Path { get; set; }
public bool? IsInterlaced { get; set; }
public int? BitRate { get; set; }
public int? Channels { get; set; }
public int? SampleRate { get; set; }
public bool IsDefault { get; set; }
public bool IsForced { get; set; }
public bool IsExternal { get; set; }
public int? Height { get; set; }
public int? Width { get; set; }
public float? AverageFrameRate { get; set; }
public float? RealFrameRate { get; set; }
public float? Level { get; set; }
public string? PixelFormat { get; set; }
public int? BitDepth { get; set; }
public bool? IsAnamorphic { get; set; }
public int? RefFrames { get; set; }
public string? CodecTag { get; set; }
public string? Comment { get; set; }
public string? NalLengthSize { get; set; }
public bool? IsAvc { get; set; }
public string? Title { get; set; }
public string? TimeBase { get; set; }
public string? CodecTimeBase { get; set; }
public string? ColorPrimaries { get; set; }
public string? ColorSpace { get; set; }
public string? ColorTransfer { get; set; }
public int? DvVersionMajor { get; set; }
public int? DvVersionMinor { get; set; }
public int? DvProfile { get; set; }
public int? DvLevel { get; set; }
public int? RpuPresentFlag { get; set; }
public int? ElPresentFlag { get; set; }
public int? BlPresentFlag { get; set; }
public int? DvBlSignalCompatibilityId { get; set; }
public bool? IsHearingImpaired { get; set; }
public int? Rotation { get; set; }
public string? KeyFrames { get; set; }
}

View File

@@ -1,37 +0,0 @@
namespace Jellyfin.Data.Entities;
/// <summary>
/// Enum MediaStreamType.
/// </summary>
public enum MediaStreamTypeEntity
{
/// <summary>
/// The audio.
/// </summary>
Audio = 0,
/// <summary>
/// The video.
/// </summary>
Video = 1,
/// <summary>
/// The subtitle.
/// </summary>
Subtitle = 2,
/// <summary>
/// The embedded image.
/// </summary>
EmbeddedImage = 3,
/// <summary>
/// The data.
/// </summary>
Data = 4,
/// <summary>
/// The lyric.
/// </summary>
Lyric = 5
}

View File

@@ -1,32 +0,0 @@
#pragma warning disable CA2227 // Collection properties should be read only
using System;
using System.Collections.Generic;
namespace Jellyfin.Data.Entities;
/// <summary>
/// People entity.
/// </summary>
public class People
{
/// <summary>
/// Gets or Sets the PeopleId.
/// </summary>
public required Guid Id { get; set; }
/// <summary>
/// Gets or Sets the Persons Name.
/// </summary>
public required string Name { get; set; }
/// <summary>
/// Gets or Sets the Type.
/// </summary>
public string? PersonType { get; set; }
/// <summary>
/// Gets or Sets the mapping of People to BaseItems.
/// </summary>
public ICollection<PeopleBaseItemMap>? BaseItems { get; set; }
}

View File

@@ -1,44 +0,0 @@
using System;
namespace Jellyfin.Data.Entities;
/// <summary>
/// Mapping table for People to BaseItems.
/// </summary>
public class PeopleBaseItemMap
{
/// <summary>
/// Gets or Sets the SortOrder.
/// </summary>
public int? SortOrder { get; set; }
/// <summary>
/// Gets or Sets the ListOrder.
/// </summary>
public int? ListOrder { get; set; }
/// <summary>
/// Gets or Sets the Role name the assosiated actor played in the <see cref="BaseItemEntity"/>.
/// </summary>
public string? Role { get; set; }
/// <summary>
/// Gets or Sets The ItemId.
/// </summary>
public required Guid ItemId { get; set; }
/// <summary>
/// Gets or Sets Reference Item.
/// </summary>
public required BaseItemEntity Item { get; set; }
/// <summary>
/// Gets or Sets The PeopleId.
/// </summary>
public required Guid PeopleId { get; set; }
/// <summary>
/// Gets or Sets Reference People.
/// </summary>
public required People People { get; set; }
}

View File

@@ -1,68 +0,0 @@
#pragma warning disable CA1711 // Identifiers should not have incorrect suffix
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Jellyfin.Data.Enums;
using Jellyfin.Data.Interfaces;
namespace Jellyfin.Data.Entities
{
/// <summary>
/// An entity representing whether the associated user has a specific permission.
/// </summary>
public class Permission : IHasConcurrencyToken
{
/// <summary>
/// Initializes a new instance of the <see cref="Permission"/> class.
/// Public constructor with required data.
/// </summary>
/// <param name="kind">The permission kind.</param>
/// <param name="value">The value of this permission.</param>
public Permission(PermissionKind kind, bool value)
{
Kind = kind;
Value = value;
}
/// <summary>
/// Gets the id of this permission.
/// </summary>
/// <remarks>
/// Identity, Indexed, Required.
/// </remarks>
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; private set; }
/// <summary>
/// Gets or sets the id of the associated user.
/// </summary>
public Guid? UserId { get; set; }
/// <summary>
/// Gets the type of this permission.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public PermissionKind Kind { get; private set; }
/// <summary>
/// Gets or sets a value indicating whether the associated user has this permission.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public bool Value { get; set; }
/// <inheritdoc />
[ConcurrencyCheck]
public uint RowVersion { get; private set; }
/// <inheritdoc/>
public void OnSavingChanges()
{
RowVersion++;
}
}
}

View File

@@ -1,68 +0,0 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Jellyfin.Data.Enums;
using Jellyfin.Data.Interfaces;
namespace Jellyfin.Data.Entities
{
/// <summary>
/// An entity representing a preference attached to a user or group.
/// </summary>
public class Preference : IHasConcurrencyToken
{
/// <summary>
/// Initializes a new instance of the <see cref="Preference"/> class.
/// Public constructor with required data.
/// </summary>
/// <param name="kind">The preference kind.</param>
/// <param name="value">The value.</param>
public Preference(PreferenceKind kind, string value)
{
Kind = kind;
Value = value ?? throw new ArgumentNullException(nameof(value));
}
/// <summary>
/// Gets the id of this preference.
/// </summary>
/// <remarks>
/// Identity, Indexed, Required.
/// </remarks>
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; private set; }
/// <summary>
/// Gets or sets the id of the associated user.
/// </summary>
public Guid? UserId { get; set; }
/// <summary>
/// Gets the type of this preference.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public PreferenceKind Kind { get; private set; }
/// <summary>
/// Gets or sets the value of this preference.
/// </summary>
/// <remarks>
/// Required, Max length = 65535.
/// </remarks>
[MaxLength(65535)]
[StringLength(65535)]
public string Value { get; set; }
/// <inheritdoc/>
[ConcurrencyCheck]
public uint RowVersion { get; private set; }
/// <inheritdoc/>
public void OnSavingChanges()
{
RowVersion++;
}
}
}

View File

@@ -1,37 +0,0 @@
namespace Jellyfin.Data.Entities;
/// <summary>
/// Lists types of Audio.
/// </summary>
public enum ProgramAudioEntity
{
/// <summary>
/// Mono.
/// </summary>
Mono = 0,
/// <summary>
/// Sterio.
/// </summary>
Stereo = 1,
/// <summary>
/// Dolby.
/// </summary>
Dolby = 2,
/// <summary>
/// DolbyDigital.
/// </summary>
DolbyDigital = 3,
/// <summary>
/// Thx.
/// </summary>
Thx = 4,
/// <summary>
/// Atmos.
/// </summary>
Atmos = 5
}

View File

@@ -1,56 +0,0 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Globalization;
namespace Jellyfin.Data.Entities.Security
{
/// <summary>
/// An entity representing an API key.
/// </summary>
public class ApiKey
{
/// <summary>
/// Initializes a new instance of the <see cref="ApiKey"/> class.
/// </summary>
/// <param name="name">The name.</param>
public ApiKey(string name)
{
Name = name;
AccessToken = Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture);
DateCreated = DateTime.UtcNow;
}
/// <summary>
/// Gets the id.
/// </summary>
/// <remarks>
/// Identity, Indexed, Required.
/// </remarks>
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; private set; }
/// <summary>
/// Gets or sets the date created.
/// </summary>
public DateTime DateCreated { get; set; }
/// <summary>
/// Gets or sets the date of last activity.
/// </summary>
public DateTime DateLastActivity { get; set; }
/// <summary>
/// Gets or sets the name.
/// </summary>
[MaxLength(64)]
[StringLength(64)]
public string Name { get; set; }
/// <summary>
/// Gets or sets the access token.
/// </summary>
public string AccessToken { get; set; }
}
}

View File

@@ -1,107 +0,0 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Globalization;
namespace Jellyfin.Data.Entities.Security
{
/// <summary>
/// An entity representing a device.
/// </summary>
public class Device
{
/// <summary>
/// Initializes a new instance of the <see cref="Device"/> class.
/// </summary>
/// <param name="userId">The user id.</param>
/// <param name="appName">The app name.</param>
/// <param name="appVersion">The app version.</param>
/// <param name="deviceName">The device name.</param>
/// <param name="deviceId">The device id.</param>
public Device(Guid userId, string appName, string appVersion, string deviceName, string deviceId)
{
UserId = userId;
AppName = appName;
AppVersion = appVersion;
DeviceName = deviceName;
DeviceId = deviceId;
AccessToken = Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture);
DateCreated = DateTime.UtcNow;
DateModified = DateCreated;
DateLastActivity = DateCreated;
// Non-nullable for EF Core, as this is a required relationship.
User = null!;
}
/// <summary>
/// Gets the id.
/// </summary>
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; private set; }
/// <summary>
/// Gets the user id.
/// </summary>
public Guid UserId { get; private set; }
/// <summary>
/// Gets or sets the access token.
/// </summary>
public string AccessToken { get; set; }
/// <summary>
/// Gets or sets the app name.
/// </summary>
[MaxLength(64)]
[StringLength(64)]
public string AppName { get; set; }
/// <summary>
/// Gets or sets the app version.
/// </summary>
[MaxLength(32)]
[StringLength(32)]
public string AppVersion { get; set; }
/// <summary>
/// Gets or sets the device name.
/// </summary>
[MaxLength(64)]
[StringLength(64)]
public string DeviceName { get; set; }
/// <summary>
/// Gets or sets the device id.
/// </summary>
[MaxLength(256)]
[StringLength(256)]
public string DeviceId { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this device is active.
/// </summary>
public bool IsActive { get; set; }
/// <summary>
/// Gets or sets the date created.
/// </summary>
public DateTime DateCreated { get; set; }
/// <summary>
/// Gets or sets the date modified.
/// </summary>
public DateTime DateModified { get; set; }
/// <summary>
/// Gets or sets the date of last activity.
/// </summary>
public DateTime DateLastActivity { get; set; }
/// <summary>
/// Gets the user.
/// </summary>
public User User { get; private set; }
}
}

View File

@@ -1,35 +0,0 @@
using System.ComponentModel.DataAnnotations.Schema;
namespace Jellyfin.Data.Entities.Security
{
/// <summary>
/// An entity representing custom options for a device.
/// </summary>
public class DeviceOptions
{
/// <summary>
/// Initializes a new instance of the <see cref="DeviceOptions"/> class.
/// </summary>
/// <param name="deviceId">The device id.</param>
public DeviceOptions(string deviceId)
{
DeviceId = deviceId;
}
/// <summary>
/// Gets the id.
/// </summary>
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; private set; }
/// <summary>
/// Gets the device id.
/// </summary>
public string DeviceId { get; private set; }
/// <summary>
/// Gets or sets the custom name.
/// </summary>
public string? CustomName { get; set; }
}
}

View File

@@ -1,75 +0,0 @@
using System;
using System.Text.Json.Serialization;
namespace Jellyfin.Data.Entities;
/// <summary>
/// An entity representing the metadata for a group of trickplay tiles.
/// </summary>
public class TrickplayInfo
{
/// <summary>
/// Gets or sets the id of the associated item.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
[JsonIgnore]
public Guid ItemId { get; set; }
/// <summary>
/// Gets or sets width of an individual thumbnail.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public int Width { get; set; }
/// <summary>
/// Gets or sets height of an individual thumbnail.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public int Height { get; set; }
/// <summary>
/// Gets or sets amount of thumbnails per row.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public int TileWidth { get; set; }
/// <summary>
/// Gets or sets amount of thumbnails per column.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public int TileHeight { get; set; }
/// <summary>
/// Gets or sets total amount of non-black thumbnails.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public int ThumbnailCount { get; set; }
/// <summary>
/// Gets or sets interval in milliseconds between each trickplay thumbnail.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public int Interval { get; set; }
/// <summary>
/// Gets or sets peak bandwith usage in bits per second.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public int Bandwidth { get; set; }
}

View File

@@ -1,534 +0,0 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text.Json.Serialization;
using Jellyfin.Data.Enums;
using Jellyfin.Data.Interfaces;
namespace Jellyfin.Data.Entities
{
/// <summary>
/// An entity representing a user.
/// </summary>
public class User : IHasPermissions, IHasConcurrencyToken
{
/// <summary>
/// The values being delimited here are Guids, so commas work as they do not appear in Guids.
/// </summary>
private const char Delimiter = ',';
/// <summary>
/// Initializes a new instance of the <see cref="User"/> class.
/// Public constructor with required data.
/// </summary>
/// <param name="username">The username for the new user.</param>
/// <param name="authenticationProviderId">The Id of the user's authentication provider.</param>
/// <param name="passwordResetProviderId">The Id of the user's password reset provider.</param>
public User(string username, string authenticationProviderId, string passwordResetProviderId)
{
ArgumentException.ThrowIfNullOrEmpty(username);
ArgumentException.ThrowIfNullOrEmpty(authenticationProviderId);
ArgumentException.ThrowIfNullOrEmpty(passwordResetProviderId);
Username = username;
AuthenticationProviderId = authenticationProviderId;
PasswordResetProviderId = passwordResetProviderId;
AccessSchedules = new HashSet<AccessSchedule>();
DisplayPreferences = new HashSet<DisplayPreferences>();
ItemDisplayPreferences = new HashSet<ItemDisplayPreferences>();
// Groups = new HashSet<Group>();
Permissions = new HashSet<Permission>();
Preferences = new HashSet<Preference>();
// ProviderMappings = new HashSet<ProviderMapping>();
// Set default values
Id = Guid.NewGuid();
InvalidLoginAttemptCount = 0;
EnableUserPreferenceAccess = true;
MustUpdatePassword = false;
DisplayMissingEpisodes = false;
DisplayCollectionsView = false;
HidePlayedInLatest = true;
RememberAudioSelections = true;
RememberSubtitleSelections = true;
EnableNextEpisodeAutoPlay = true;
EnableAutoLogin = false;
PlayDefaultAudioTrack = true;
SubtitleMode = SubtitlePlaybackMode.Default;
SyncPlayAccess = SyncPlayUserAccessType.CreateAndJoinGroups;
}
/// <summary>
/// Gets or sets the Id of the user.
/// </summary>
/// <remarks>
/// Identity, Indexed, Required.
/// </remarks>
[JsonIgnore]
public Guid Id { get; set; }
/// <summary>
/// Gets or sets the user's name.
/// </summary>
/// <remarks>
/// Required, Max length = 255.
/// </remarks>
[MaxLength(255)]
[StringLength(255)]
public string Username { get; set; }
/// <summary>
/// Gets or sets the user's password, or <c>null</c> if none is set.
/// </summary>
/// <remarks>
/// Max length = 65535.
/// </remarks>
[MaxLength(65535)]
[StringLength(65535)]
public string? Password { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the user must update their password.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public bool MustUpdatePassword { get; set; }
/// <summary>
/// Gets or sets the audio language preference.
/// </summary>
/// <remarks>
/// Max length = 255.
/// </remarks>
[MaxLength(255)]
[StringLength(255)]
public string? AudioLanguagePreference { get; set; }
/// <summary>
/// Gets or sets the authentication provider id.
/// </summary>
/// <remarks>
/// Required, Max length = 255.
/// </remarks>
[MaxLength(255)]
[StringLength(255)]
public string AuthenticationProviderId { get; set; }
/// <summary>
/// Gets or sets the password reset provider id.
/// </summary>
/// <remarks>
/// Required, Max length = 255.
/// </remarks>
[MaxLength(255)]
[StringLength(255)]
public string PasswordResetProviderId { get; set; }
/// <summary>
/// Gets or sets the invalid login attempt count.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public int InvalidLoginAttemptCount { get; set; }
/// <summary>
/// Gets or sets the last activity date.
/// </summary>
public DateTime? LastActivityDate { get; set; }
/// <summary>
/// Gets or sets the last login date.
/// </summary>
public DateTime? LastLoginDate { get; set; }
/// <summary>
/// Gets or sets the number of login attempts the user can make before they are locked out.
/// </summary>
public int? LoginAttemptsBeforeLockout { get; set; }
/// <summary>
/// Gets or sets the maximum number of active sessions the user can have at once.
/// </summary>
public int MaxActiveSessions { get; set; }
/// <summary>
/// Gets or sets the subtitle mode.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public SubtitlePlaybackMode SubtitleMode { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the default audio track should be played.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public bool PlayDefaultAudioTrack { get; set; }
/// <summary>
/// Gets or sets the subtitle language preference.
/// </summary>
/// <remarks>
/// Max length = 255.
/// </remarks>
[MaxLength(255)]
[StringLength(255)]
public string? SubtitleLanguagePreference { get; set; }
/// <summary>
/// Gets or sets a value indicating whether missing episodes should be displayed.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public bool DisplayMissingEpisodes { get; set; }
/// <summary>
/// Gets or sets a value indicating whether to display the collections view.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public bool DisplayCollectionsView { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the user has a local password.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public bool EnableLocalPassword { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the server should hide played content in "Latest".
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public bool HidePlayedInLatest { get; set; }
/// <summary>
/// Gets or sets a value indicating whether to remember audio selections on played content.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public bool RememberAudioSelections { get; set; }
/// <summary>
/// Gets or sets a value indicating whether to remember subtitle selections on played content.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public bool RememberSubtitleSelections { get; set; }
/// <summary>
/// Gets or sets a value indicating whether to enable auto-play for the next episode.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public bool EnableNextEpisodeAutoPlay { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the user should auto-login.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public bool EnableAutoLogin { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the user can change their preferences.
/// </summary>
/// <remarks>
/// Required.
/// </remarks>
public bool EnableUserPreferenceAccess { get; set; }
/// <summary>
/// Gets or sets the maximum parental age rating.
/// </summary>
public int? MaxParentalAgeRating { get; set; }
/// <summary>
/// Gets or sets the remote client bitrate limit.
/// </summary>
public int? RemoteClientBitrateLimit { get; set; }
/// <summary>
/// Gets or sets the internal id.
/// This is a temporary stopgap for until the library db is migrated.
/// This corresponds to the value of the index of this user in the library db.
/// </summary>
public long InternalId { get; set; }
/// <summary>
/// Gets or sets the user's profile image. Can be <c>null</c>.
/// </summary>
// [ForeignKey("UserId")]
public virtual ImageInfo? ProfileImage { get; set; }
/// <summary>
/// Gets the user's display preferences.
/// </summary>
public virtual ICollection<DisplayPreferences> DisplayPreferences { get; private set; }
/// <summary>
/// Gets or sets the level of sync play permissions this user has.
/// </summary>
public SyncPlayUserAccessType SyncPlayAccess { get; set; }
/// <summary>
/// Gets or sets the cast receiver id.
/// </summary>
[StringLength(32)]
public string? CastReceiverId { get; set; }
/// <inheritdoc />
[ConcurrencyCheck]
public uint RowVersion { get; private set; }
/// <summary>
/// Gets the list of access schedules this user has.
/// </summary>
public virtual ICollection<AccessSchedule> AccessSchedules { get; private set; }
/// <summary>
/// Gets the list of item display preferences.
/// </summary>
public virtual ICollection<ItemDisplayPreferences> ItemDisplayPreferences { get; private set; }
/*
/// <summary>
/// Gets the list of groups this user is a member of.
/// </summary>
public virtual ICollection<Group> Groups { get; private set; }
*/
/// <summary>
/// Gets the list of permissions this user has.
/// </summary>
[ForeignKey("Permission_Permissions_Guid")]
public virtual ICollection<Permission> Permissions { get; private set; }
/*
/// <summary>
/// Gets the list of provider mappings this user has.
/// </summary>
public virtual ICollection<ProviderMapping> ProviderMappings { get; private set; }
*/
/// <summary>
/// Gets the list of preferences this user has.
/// </summary>
[ForeignKey("Preference_Preferences_Guid")]
public virtual ICollection<Preference> Preferences { get; private set; }
/// <inheritdoc/>
public void OnSavingChanges()
{
RowVersion++;
}
/// <summary>
/// Checks whether the user has the specified permission.
/// </summary>
/// <param name="kind">The permission kind.</param>
/// <returns><c>True</c> if the user has the specified permission.</returns>
public bool HasPermission(PermissionKind kind)
{
return Permissions.FirstOrDefault(p => p.Kind == kind)?.Value ?? false;
}
/// <summary>
/// Sets the given permission kind to the provided value.
/// </summary>
/// <param name="kind">The permission kind.</param>
/// <param name="value">The value to set.</param>
public void SetPermission(PermissionKind kind, bool value)
{
var currentPermission = Permissions.FirstOrDefault(p => p.Kind == kind);
if (currentPermission is null)
{
Permissions.Add(new Permission(kind, value));
}
else
{
currentPermission.Value = value;
}
}
/// <summary>
/// Gets the user's preferences for the given preference kind.
/// </summary>
/// <param name="preference">The preference kind.</param>
/// <returns>A string array containing the user's preferences.</returns>
public string[] GetPreference(PreferenceKind preference)
{
var val = Preferences.FirstOrDefault(p => p.Kind == preference)?.Value;
return string.IsNullOrEmpty(val) ? Array.Empty<string>() : val.Split(Delimiter);
}
/// <summary>
/// Gets the user's preferences for the given preference kind.
/// </summary>
/// <param name="preference">The preference kind.</param>
/// <typeparam name="T">Type of preference.</typeparam>
/// <returns>A {T} array containing the user's preference.</returns>
public T[] GetPreferenceValues<T>(PreferenceKind preference)
{
var val = Preferences.FirstOrDefault(p => p.Kind == preference)?.Value;
if (string.IsNullOrEmpty(val))
{
return Array.Empty<T>();
}
// Convert array of {string} to array of {T}
var converter = TypeDescriptor.GetConverter(typeof(T));
var stringValues = val.Split(Delimiter);
var convertedCount = 0;
var parsedValues = new T[stringValues.Length];
for (var i = 0; i < stringValues.Length; i++)
{
try
{
var parsedValue = converter.ConvertFromString(stringValues[i].Trim());
if (parsedValue is not null)
{
parsedValues[convertedCount++] = (T)parsedValue;
}
}
catch (FormatException)
{
// Unable to convert value
}
}
return parsedValues[..convertedCount];
}
/// <summary>
/// Sets the specified preference to the given value.
/// </summary>
/// <param name="preference">The preference kind.</param>
/// <param name="values">The values.</param>
public void SetPreference(PreferenceKind preference, string[] values)
{
var value = string.Join(Delimiter, values);
var currentPreference = Preferences.FirstOrDefault(p => p.Kind == preference);
if (currentPreference is null)
{
Preferences.Add(new Preference(preference, value));
}
else
{
currentPreference.Value = value;
}
}
/// <summary>
/// Sets the specified preference to the given value.
/// </summary>
/// <param name="preference">The preference kind.</param>
/// <param name="values">The values.</param>
/// <typeparam name="T">The type of value.</typeparam>
public void SetPreference<T>(PreferenceKind preference, T[] values)
{
var value = string.Join(Delimiter, values);
var currentPreference = Preferences.FirstOrDefault(p => p.Kind == preference);
if (currentPreference is null)
{
Preferences.Add(new Preference(preference, value));
}
else
{
currentPreference.Value = value;
}
}
/// <summary>
/// Checks whether this user is currently allowed to use the server.
/// </summary>
/// <returns><c>True</c> if the current time is within an access schedule, or there are no access schedules.</returns>
public bool IsParentalScheduleAllowed()
{
return AccessSchedules.Count == 0
|| AccessSchedules.Any(i => IsParentalScheduleAllowed(i, DateTime.UtcNow));
}
/// <summary>
/// Checks whether the provided folder is in this user's grouped folders.
/// </summary>
/// <param name="id">The Guid of the folder.</param>
/// <returns><c>True</c> if the folder is in the user's grouped folders.</returns>
public bool IsFolderGrouped(Guid id)
{
return Array.IndexOf(GetPreferenceValues<Guid>(PreferenceKind.GroupedFolders), id) != -1;
}
/// <summary>
/// Initializes the default permissions for a user. Should only be called on user creation.
/// </summary>
// TODO: make these user configurable?
public void AddDefaultPermissions()
{
Permissions.Add(new Permission(PermissionKind.IsAdministrator, false));
Permissions.Add(new Permission(PermissionKind.IsDisabled, false));
Permissions.Add(new Permission(PermissionKind.IsHidden, true));
Permissions.Add(new Permission(PermissionKind.EnableAllChannels, true));
Permissions.Add(new Permission(PermissionKind.EnableAllDevices, true));
Permissions.Add(new Permission(PermissionKind.EnableAllFolders, true));
Permissions.Add(new Permission(PermissionKind.EnableContentDeletion, false));
Permissions.Add(new Permission(PermissionKind.EnableContentDownloading, true));
Permissions.Add(new Permission(PermissionKind.EnableMediaConversion, true));
Permissions.Add(new Permission(PermissionKind.EnableMediaPlayback, true));
Permissions.Add(new Permission(PermissionKind.EnablePlaybackRemuxing, true));
Permissions.Add(new Permission(PermissionKind.EnablePublicSharing, true));
Permissions.Add(new Permission(PermissionKind.EnableRemoteAccess, true));
Permissions.Add(new Permission(PermissionKind.EnableSyncTranscoding, true));
Permissions.Add(new Permission(PermissionKind.EnableAudioPlaybackTranscoding, true));
Permissions.Add(new Permission(PermissionKind.EnableLiveTvAccess, true));
Permissions.Add(new Permission(PermissionKind.EnableLiveTvManagement, true));
Permissions.Add(new Permission(PermissionKind.EnableSharedDeviceControl, true));
Permissions.Add(new Permission(PermissionKind.EnableVideoPlaybackTranscoding, true));
Permissions.Add(new Permission(PermissionKind.ForceRemoteSourceTranscoding, false));
Permissions.Add(new Permission(PermissionKind.EnableRemoteControlOfOtherUsers, false));
Permissions.Add(new Permission(PermissionKind.EnableCollectionManagement, false));
Permissions.Add(new Permission(PermissionKind.EnableSubtitleManagement, false));
Permissions.Add(new Permission(PermissionKind.EnableLyricManagement, false));
}
/// <summary>
/// Initializes the default preferences. Should only be called on user creation.
/// </summary>
public void AddDefaultPreferences()
{
foreach (var val in Enum.GetValues<PreferenceKind>())
{
Preferences.Add(new Preference(val, string.Empty));
}
}
private static bool IsParentalScheduleAllowed(AccessSchedule schedule, DateTime date)
{
var localTime = date.ToLocalTime();
var hour = localTime.TimeOfDay.TotalHours;
var currentDayOfWeek = localTime.DayOfWeek;
return schedule.DayOfWeek.Contains(currentDayOfWeek)
&& hour >= schedule.StartHour
&& hour <= schedule.EndHour;
}
}
}

View File

@@ -1,92 +0,0 @@
using System;
using System.ComponentModel.DataAnnotations.Schema;
namespace Jellyfin.Data.Entities;
/// <summary>
/// Provides <see cref="BaseItemEntity"/> and <see cref="User"/> related data.
/// </summary>
public class UserData
{
/// <summary>
/// Gets or sets the custom data key.
/// </summary>
/// <value>The rating.</value>
public required string CustomDataKey { get; set; }
/// <summary>
/// Gets or sets the users 0-10 rating.
/// </summary>
/// <value>The rating.</value>
public double? Rating { get; set; }
/// <summary>
/// Gets or sets the playback position ticks.
/// </summary>
/// <value>The playback position ticks.</value>
public long PlaybackPositionTicks { get; set; }
/// <summary>
/// Gets or sets the play count.
/// </summary>
/// <value>The play count.</value>
public int PlayCount { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this instance is favorite.
/// </summary>
/// <value><c>true</c> if this instance is favorite; otherwise, <c>false</c>.</value>
public bool IsFavorite { get; set; }
/// <summary>
/// Gets or sets the last played date.
/// </summary>
/// <value>The last played date.</value>
public DateTime? LastPlayedDate { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this <see cref="UserData" /> is played.
/// </summary>
/// <value><c>true</c> if played; otherwise, <c>false</c>.</value>
public bool Played { get; set; }
/// <summary>
/// Gets or sets the index of the audio stream.
/// </summary>
/// <value>The index of the audio stream.</value>
public int? AudioStreamIndex { get; set; }
/// <summary>
/// Gets or sets the index of the subtitle stream.
/// </summary>
/// <value>The index of the subtitle stream.</value>
public int? SubtitleStreamIndex { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the item is liked or not.
/// This should never be serialized.
/// </summary>
/// <value><c>null</c> if [likes] contains no value, <c>true</c> if [likes]; otherwise, <c>false</c>.</value>
public bool? Likes { get; set; }
/// <summary>
/// Gets or sets the key.
/// </summary>
/// <value>The key.</value>
public required Guid ItemId { get; set; }
/// <summary>
/// Gets or Sets the BaseItem.
/// </summary>
public required BaseItemEntity? Item { get; set; }
/// <summary>
/// Gets or Sets the UserId.
/// </summary>
public required Guid UserId { get; set; }
/// <summary>
/// Gets or Sets the User.
/// </summary>
public required User? User { get; set; }
}

View File

@@ -1,33 +0,0 @@
namespace Jellyfin.Data.Enums
{
/// <summary>
/// An enum representing types of art.
/// </summary>
public enum ArtKind
{
/// <summary>
/// Another type of art, not covered by the other members.
/// </summary>
Other = 0,
/// <summary>
/// A poster.
/// </summary>
Poster = 1,
/// <summary>
/// A banner.
/// </summary>
Banner = 2,
/// <summary>
/// A thumbnail.
/// </summary>
Thumbnail = 3,
/// <summary>
/// A logo.
/// </summary>
Logo = 4
}
}

View File

@@ -1,18 +0,0 @@
namespace Jellyfin.Data.Enums
{
/// <summary>
/// An enum representing the version of Chromecast to be used by clients.
/// </summary>
public enum ChromecastVersion
{
/// <summary>
/// Stable Chromecast version.
/// </summary>
Stable = 0,
/// <summary>
/// Unstable Chromecast version.
/// </summary>
Unstable = 1
}
}

View File

@@ -1,58 +0,0 @@
namespace Jellyfin.Data.Enums
{
/// <summary>
/// An enum that represents a day of the week, weekdays, weekends, or all days.
/// </summary>
public enum DynamicDayOfWeek
{
/// <summary>
/// Sunday.
/// </summary>
Sunday = 0,
/// <summary>
/// Monday.
/// </summary>
Monday = 1,
/// <summary>
/// Tuesday.
/// </summary>
Tuesday = 2,
/// <summary>
/// Wednesday.
/// </summary>
Wednesday = 3,
/// <summary>
/// Thursday.
/// </summary>
Thursday = 4,
/// <summary>
/// Friday.
/// </summary>
Friday = 5,
/// <summary>
/// Saturday.
/// </summary>
Saturday = 6,
/// <summary>
/// All days of the week.
/// </summary>
Everyday = 7,
/// <summary>
/// A week day, or Monday-Friday.
/// </summary>
Weekday = 8,
/// <summary>
/// Saturday and Sunday.
/// </summary>
Weekend = 9
}
}

View File

@@ -1,58 +0,0 @@
namespace Jellyfin.Data.Enums
{
/// <summary>
/// An enum representing the different options for the home screen sections.
/// </summary>
public enum HomeSectionType
{
/// <summary>
/// None.
/// </summary>
None = 0,
/// <summary>
/// My Media.
/// </summary>
SmallLibraryTiles = 1,
/// <summary>
/// My Media Small.
/// </summary>
LibraryButtons = 2,
/// <summary>
/// Active Recordings.
/// </summary>
ActiveRecordings = 3,
/// <summary>
/// Continue Watching.
/// </summary>
Resume = 4,
/// <summary>
/// Continue Listening.
/// </summary>
ResumeAudio = 5,
/// <summary>
/// Latest Media.
/// </summary>
LatestMedia = 6,
/// <summary>
/// Next Up.
/// </summary>
NextUp = 7,
/// <summary>
/// Live TV.
/// </summary>
LiveTv = 8,
/// <summary>
/// Continue Reading.
/// </summary>
ResumeBook = 9
}
}

View File

@@ -1,23 +0,0 @@
namespace Jellyfin.Data.Enums
{
/// <summary>
/// An enum representing a type of indexing in a user's display preferences.
/// </summary>
public enum IndexingKind
{
/// <summary>
/// Index by the premiere date.
/// </summary>
PremiereDate = 0,
/// <summary>
/// Index by the production year.
/// </summary>
ProductionYear = 1,
/// <summary>
/// Index by the community rating.
/// </summary>
CommunityRating = 2
}
}

View File

@@ -1,33 +0,0 @@
namespace Jellyfin.Data.Enums
{
/// <summary>
/// An enum representing the type of media file.
/// </summary>
public enum MediaFileKind
{
/// <summary>
/// The main file.
/// </summary>
Main = 0,
/// <summary>
/// A sidecar file.
/// </summary>
Sidecar = 1,
/// <summary>
/// An additional part to the main file.
/// </summary>
AdditionalPart = 2,
/// <summary>
/// An alternative format to the main file.
/// </summary>
AlternativeFormat = 3,
/// <summary>
/// An additional stream for the main file.
/// </summary>
AdditionalStream = 4
}
}

View File

@@ -1,39 +0,0 @@
using Jellyfin.Data.Entities;
namespace Jellyfin.Data.Enums;
/// <summary>
/// Defines the types of content an individual <see cref="MediaSegment"/> represents.
/// </summary>
public enum MediaSegmentType
{
/// <summary>
/// Default media type or custom one.
/// </summary>
Unknown = 0,
/// <summary>
/// Commercial.
/// </summary>
Commercial = 1,
/// <summary>
/// Preview.
/// </summary>
Preview = 2,
/// <summary>
/// Recap.
/// </summary>
Recap = 3,
/// <summary>
/// Outro.
/// </summary>
Outro = 4,
/// <summary>
/// Intro.
/// </summary>
Intro = 5
}

View File

@@ -1,128 +0,0 @@
namespace Jellyfin.Data.Enums
{
/// <summary>
/// The types of user permissions.
/// </summary>
public enum PermissionKind
{
/// <summary>
/// Whether the user is an administrator.
/// </summary>
IsAdministrator = 0,
/// <summary>
/// Whether the user is hidden.
/// </summary>
IsHidden = 1,
/// <summary>
/// Whether the user is disabled.
/// </summary>
IsDisabled = 2,
/// <summary>
/// Whether the user can control shared devices.
/// </summary>
EnableSharedDeviceControl = 3,
/// <summary>
/// Whether the user can access the server remotely.
/// </summary>
EnableRemoteAccess = 4,
/// <summary>
/// Whether the user can manage live tv.
/// </summary>
EnableLiveTvManagement = 5,
/// <summary>
/// Whether the user can access live tv.
/// </summary>
EnableLiveTvAccess = 6,
/// <summary>
/// Whether the user can play media.
/// </summary>
EnableMediaPlayback = 7,
/// <summary>
/// Whether the server should transcode audio for the user if requested.
/// </summary>
EnableAudioPlaybackTranscoding = 8,
/// <summary>
/// Whether the server should transcode video for the user if requested.
/// </summary>
EnableVideoPlaybackTranscoding = 9,
/// <summary>
/// Whether the user can delete content.
/// </summary>
EnableContentDeletion = 10,
/// <summary>
/// Whether the user can download content.
/// </summary>
EnableContentDownloading = 11,
/// <summary>
/// Whether to enable sync transcoding for the user.
/// </summary>
EnableSyncTranscoding = 12,
/// <summary>
/// Whether the user can do media conversion.
/// </summary>
EnableMediaConversion = 13,
/// <summary>
/// Whether the user has access to all devices.
/// </summary>
EnableAllDevices = 14,
/// <summary>
/// Whether the user has access to all channels.
/// </summary>
EnableAllChannels = 15,
/// <summary>
/// Whether the user has access to all folders.
/// </summary>
EnableAllFolders = 16,
/// <summary>
/// Whether to enable public sharing for the user.
/// </summary>
EnablePublicSharing = 17,
/// <summary>
/// Whether the user can remotely control other users.
/// </summary>
EnableRemoteControlOfOtherUsers = 18,
/// <summary>
/// Whether the user is permitted to do playback remuxing.
/// </summary>
EnablePlaybackRemuxing = 19,
/// <summary>
/// Whether the server should force transcoding on remote connections for the user.
/// </summary>
ForceRemoteSourceTranscoding = 20,
/// <summary>
/// Whether the user can create, modify and delete collections.
/// </summary>
EnableCollectionManagement = 21,
/// <summary>
/// Whether the user can edit subtitles.
/// </summary>
EnableSubtitleManagement = 22,
/// <summary>
/// Whether the user can edit lyrics.
/// </summary>
EnableLyricManagement = 23,
}
}

View File

@@ -1,68 +0,0 @@
namespace Jellyfin.Data.Enums
{
/// <summary>
/// An enum representing a person's role in a specific media item.
/// </summary>
public enum PersonRoleType
{
/// <summary>
/// Another role, not covered by the other types.
/// </summary>
Other = 0,
/// <summary>
/// The director of the media.
/// </summary>
Director = 1,
/// <summary>
/// An artist.
/// </summary>
Artist = 2,
/// <summary>
/// The original artist.
/// </summary>
OriginalArtist = 3,
/// <summary>
/// An actor.
/// </summary>
Actor = 4,
/// <summary>
/// A voice actor.
/// </summary>
VoiceActor = 5,
/// <summary>
/// A producer.
/// </summary>
Producer = 6,
/// <summary>
/// A remixer.
/// </summary>
Remixer = 7,
/// <summary>
/// A conductor.
/// </summary>
Conductor = 8,
/// <summary>
/// A composer.
/// </summary>
Composer = 9,
/// <summary>
/// An author.
/// </summary>
Author = 10,
/// <summary>
/// An editor.
/// </summary>
Editor = 11
}
}

View File

@@ -1,73 +0,0 @@
namespace Jellyfin.Data.Enums
{
/// <summary>
/// The types of user preferences.
/// </summary>
public enum PreferenceKind
{
/// <summary>
/// A list of blocked tags.
/// </summary>
BlockedTags = 0,
/// <summary>
/// A list of blocked channels.
/// </summary>
BlockedChannels = 1,
/// <summary>
/// A list of blocked media folders.
/// </summary>
BlockedMediaFolders = 2,
/// <summary>
/// A list of enabled devices.
/// </summary>
EnabledDevices = 3,
/// <summary>
/// A list of enabled channels.
/// </summary>
EnabledChannels = 4,
/// <summary>
/// A list of enabled folders.
/// </summary>
EnabledFolders = 5,
/// <summary>
/// A list of folders to allow content deletion from.
/// </summary>
EnableContentDeletionFromFolders = 6,
/// <summary>
/// A list of latest items to exclude.
/// </summary>
LatestItemExcludes = 7,
/// <summary>
/// A list of media to exclude.
/// </summary>
MyMediaExcludes = 8,
/// <summary>
/// A list of grouped folders.
/// </summary>
GroupedFolders = 9,
/// <summary>
/// A list of unrated items to block.
/// </summary>
BlockUnratedItems = 10,
/// <summary>
/// A list of ordered views.
/// </summary>
OrderedViews = 11,
/// <summary>
/// A list of allowed tags.
/// </summary>
AllowedTags = 12
}
}

View File

@@ -1,18 +0,0 @@
namespace Jellyfin.Data.Enums
{
/// <summary>
/// An enum representing the axis that should be scrolled.
/// </summary>
public enum ScrollDirection
{
/// <summary>
/// Horizontal scrolling direction.
/// </summary>
Horizontal = 0,
/// <summary>
/// Vertical scrolling direction.
/// </summary>
Vertical = 1
}
}

View File

@@ -1,18 +0,0 @@
namespace Jellyfin.Data.Enums
{
/// <summary>
/// An enum representing the sorting order.
/// </summary>
public enum SortOrder
{
/// <summary>
/// Sort in increasing order.
/// </summary>
Ascending = 0,
/// <summary>
/// Sort in decreasing order.
/// </summary>
Descending = 1
}
}

View File

@@ -1,33 +0,0 @@
namespace Jellyfin.Data.Enums
{
/// <summary>
/// An enum representing a subtitle playback mode.
/// </summary>
public enum SubtitlePlaybackMode
{
/// <summary>
/// The default subtitle playback mode.
/// </summary>
Default = 0,
/// <summary>
/// Always show subtitles.
/// </summary>
Always = 1,
/// <summary>
/// Only show forced subtitles.
/// </summary>
OnlyForced = 2,
/// <summary>
/// Don't show subtitles.
/// </summary>
None = 3,
/// <summary>
/// Only show subtitles when the current audio stream is in a different language.
/// </summary>
Smart = 4
}
}

View File

@@ -1,23 +0,0 @@
namespace Jellyfin.Data.Enums
{
/// <summary>
/// Enum SyncPlayUserAccessType.
/// </summary>
public enum SyncPlayUserAccessType
{
/// <summary>
/// User can create groups and join them.
/// </summary>
CreateAndJoinGroups = 0,
/// <summary>
/// User can only join already existing groups.
/// </summary>
JoinGroups = 1,
/// <summary>
/// SyncPlay is disabled for the user.
/// </summary>
None = 2
}
}

View File

@@ -1,113 +0,0 @@
namespace Jellyfin.Data.Enums
{
/// <summary>
/// An enum representing the type of view for a library or collection.
/// </summary>
public enum ViewType
{
/// <summary>
/// Shows albums.
/// </summary>
Albums = 0,
/// <summary>
/// Shows album artists.
/// </summary>
AlbumArtists = 1,
/// <summary>
/// Shows artists.
/// </summary>
Artists = 2,
/// <summary>
/// Shows channels.
/// </summary>
Channels = 3,
/// <summary>
/// Shows collections.
/// </summary>
Collections = 4,
/// <summary>
/// Shows episodes.
/// </summary>
Episodes = 5,
/// <summary>
/// Shows favorites.
/// </summary>
Favorites = 6,
/// <summary>
/// Shows genres.
/// </summary>
Genres = 7,
/// <summary>
/// Shows guide.
/// </summary>
Guide = 8,
/// <summary>
/// Shows movies.
/// </summary>
Movies = 9,
/// <summary>
/// Shows networks.
/// </summary>
Networks = 10,
/// <summary>
/// Shows playlists.
/// </summary>
Playlists = 11,
/// <summary>
/// Shows programs.
/// </summary>
Programs = 12,
/// <summary>
/// Shows recordings.
/// </summary>
Recordings = 13,
/// <summary>
/// Shows schedule.
/// </summary>
Schedule = 14,
/// <summary>
/// Shows series.
/// </summary>
Series = 15,
/// <summary>
/// Shows shows.
/// </summary>
Shows = 16,
/// <summary>
/// Shows songs.
/// </summary>
Songs = 17,
/// <summary>
/// Shows songs.
/// </summary>
Suggestions = 18,
/// <summary>
/// Shows trailers.
/// </summary>
Trailers = 19,
/// <summary>
/// Shows upcoming.
/// </summary>
Upcoming = 20
}
}

View File

@@ -1,16 +0,0 @@
using System.Collections.Generic;
using Jellyfin.Data.Entities.Libraries;
namespace Jellyfin.Data.Interfaces
{
/// <summary>
/// An interface abstracting an entity that has artwork.
/// </summary>
public interface IHasArtwork
{
/// <summary>
/// Gets a collection containing this entity's artwork.
/// </summary>
ICollection<Artwork> Artwork { get; }
}
}

View File

@@ -1,16 +0,0 @@
using System.Collections.Generic;
using Jellyfin.Data.Entities.Libraries;
namespace Jellyfin.Data.Interfaces
{
/// <summary>
/// An abstraction representing an entity that has companies.
/// </summary>
public interface IHasCompanies
{
/// <summary>
/// Gets a collection containing this entity's companies.
/// </summary>
ICollection<Company> Companies { get; }
}
}

View File

@@ -1,18 +0,0 @@
namespace Jellyfin.Data.Interfaces
{
/// <summary>
/// An interface abstracting an entity that has a concurrency token.
/// </summary>
public interface IHasConcurrencyToken
{
/// <summary>
/// Gets the version of this row. Acts as a concurrency token.
/// </summary>
uint RowVersion { get; }
/// <summary>
/// Called when saving changes to this entity.
/// </summary>
void OnSavingChanges();
}
}

View File

@@ -1,31 +0,0 @@
using System.Collections.Generic;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
namespace Jellyfin.Data.Interfaces
{
/// <summary>
/// An abstraction representing an entity that has permissions.
/// </summary>
public interface IHasPermissions
{
/// <summary>
/// Gets a collection containing this entity's permissions.
/// </summary>
ICollection<Permission> Permissions { get; }
/// <summary>
/// Checks whether this entity has the specified permission kind.
/// </summary>
/// <param name="kind">The kind of permission.</param>
/// <returns><c>true</c> if this entity has the specified permission, <c>false</c> otherwise.</returns>
bool HasPermission(PermissionKind kind);
/// <summary>
/// Sets the specified permission to the provided value.
/// </summary>
/// <param name="kind">The kind of permission.</param>
/// <param name="value">The value to set.</param>
void SetPermission(PermissionKind kind, bool value);
}
}

View File

@@ -1,16 +0,0 @@
using System.Collections.Generic;
using Jellyfin.Data.Entities.Libraries;
namespace Jellyfin.Data.Interfaces
{
/// <summary>
/// An abstraction representing an entity that has releases.
/// </summary>
public interface IHasReleases
{
/// <summary>
/// Gets a collection containing this entity's releases.
/// </summary>
ICollection<Release> Releases { get; }
}
}

View File

@@ -38,6 +38,10 @@
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" PrivateAssets="All" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Jellyfin.Database\Jellyfin.Database.Implementations\Jellyfin.Database.Implementations.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging" />
</ItemGroup>

View File

@@ -0,0 +1,220 @@
using System;
using System.ComponentModel;
using System.Linq;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using Jellyfin.Data.Interfaces;
namespace Jellyfin.Data;
/// <summary>
/// Contains extension methods for manipulation of <see cref="User"/> entities.
/// </summary>
public static class UserEntityExtensions
{
/// <summary>
/// The values being delimited here are Guids, so commas work as they do not appear in Guids.
/// </summary>
private const char Delimiter = ',';
/// <summary>
/// Checks whether the user has the specified permission.
/// </summary>
/// <param name="entity">The entity to update.</param>
/// <param name="kind">The permission kind.</param>
/// <returns><c>True</c> if the user has the specified permission.</returns>
public static bool HasPermission(this IHasPermissions entity, PermissionKind kind)
{
return entity.Permissions.FirstOrDefault(p => p.Kind == kind)?.Value ?? false;
}
/// <summary>
/// Sets the given permission kind to the provided value.
/// </summary>
/// <param name="entity">The entity to update.</param>
/// <param name="kind">The permission kind.</param>
/// <param name="value">The value to set.</param>
public static void SetPermission(this IHasPermissions entity, PermissionKind kind, bool value)
{
var currentPermission = entity.Permissions.FirstOrDefault(p => p.Kind == kind);
if (currentPermission is null)
{
entity.Permissions.Add(new Permission(kind, value));
}
else
{
currentPermission.Value = value;
}
}
/// <summary>
/// Gets the user's preferences for the given preference kind.
/// </summary>
/// <param name="entity">The entity to update.</param>
/// <param name="preference">The preference kind.</param>
/// <returns>A string array containing the user's preferences.</returns>
public static string[] GetPreference(this User entity, PreferenceKind preference)
{
var val = entity.Preferences.FirstOrDefault(p => p.Kind == preference)?.Value;
return string.IsNullOrEmpty(val) ? Array.Empty<string>() : val.Split(Delimiter);
}
/// <summary>
/// Gets the user's preferences for the given preference kind.
/// </summary>
/// <param name="entity">The entity to update.</param>
/// <param name="preference">The preference kind.</param>
/// <typeparam name="T">Type of preference.</typeparam>
/// <returns>A {T} array containing the user's preference.</returns>
public static T[] GetPreferenceValues<T>(this User entity, PreferenceKind preference)
{
var val = entity.Preferences.FirstOrDefault(p => p.Kind == preference)?.Value;
if (string.IsNullOrEmpty(val))
{
return Array.Empty<T>();
}
// Convert array of {string} to array of {T}
var converter = TypeDescriptor.GetConverter(typeof(T));
var stringValues = val.Split(Delimiter);
var convertedCount = 0;
var parsedValues = new T[stringValues.Length];
for (var i = 0; i < stringValues.Length; i++)
{
try
{
var parsedValue = converter.ConvertFromString(stringValues[i].Trim());
if (parsedValue is not null)
{
parsedValues[convertedCount++] = (T)parsedValue;
}
}
catch (FormatException)
{
// Unable to convert value
}
}
return parsedValues[..convertedCount];
}
/// <summary>
/// Sets the specified preference to the given value.
/// </summary>
/// <param name="entity">The entity to update.</param>
/// <param name="preference">The preference kind.</param>
/// <param name="values">The values.</param>
public static void SetPreference(this User entity, PreferenceKind preference, string[] values)
{
var value = string.Join(Delimiter, values);
var currentPreference = entity.Preferences.FirstOrDefault(p => p.Kind == preference);
if (currentPreference is null)
{
entity.Preferences.Add(new Preference(preference, value));
}
else
{
currentPreference.Value = value;
}
}
/// <summary>
/// Sets the specified preference to the given value.
/// </summary>
/// <param name="entity">The entity to update.</param>
/// <param name="preference">The preference kind.</param>
/// <param name="values">The values.</param>
/// <typeparam name="T">The type of value.</typeparam>
public static void SetPreference<T>(this User entity, PreferenceKind preference, T[] values)
{
var value = string.Join(Delimiter, values);
var currentPreference = entity.Preferences.FirstOrDefault(p => p.Kind == preference);
if (currentPreference is null)
{
entity.Preferences.Add(new Preference(preference, value));
}
else
{
currentPreference.Value = value;
}
}
/// <summary>
/// Checks whether this user is currently allowed to use the server.
/// </summary>
/// <param name="entity">The entity to update.</param>
/// <returns><c>True</c> if the current time is within an access schedule, or there are no access schedules.</returns>
public static bool IsParentalScheduleAllowed(this User entity)
{
return entity.AccessSchedules.Count == 0
|| entity.AccessSchedules.Any(i => IsParentalScheduleAllowed(i, DateTime.UtcNow));
}
/// <summary>
/// Checks whether the provided folder is in this user's grouped folders.
/// </summary>
/// <param name="entity">The entity to update.</param>
/// <param name="id">The Guid of the folder.</param>
/// <returns><c>True</c> if the folder is in the user's grouped folders.</returns>
public static bool IsFolderGrouped(this User entity, Guid id)
{
return Array.IndexOf(GetPreferenceValues<Guid>(entity, PreferenceKind.GroupedFolders), id) != -1;
}
/// <summary>
/// Initializes the default permissions for a user. Should only be called on user creation.
/// </summary>
/// <param name="entity">The entity to update.</param>
// TODO: make these user configurable?
public static void AddDefaultPermissions(this User entity)
{
entity.Permissions.Add(new Permission(PermissionKind.IsAdministrator, false));
entity.Permissions.Add(new Permission(PermissionKind.IsDisabled, false));
entity.Permissions.Add(new Permission(PermissionKind.IsHidden, true));
entity.Permissions.Add(new Permission(PermissionKind.EnableAllChannels, true));
entity.Permissions.Add(new Permission(PermissionKind.EnableAllDevices, true));
entity.Permissions.Add(new Permission(PermissionKind.EnableAllFolders, true));
entity.Permissions.Add(new Permission(PermissionKind.EnableContentDeletion, false));
entity.Permissions.Add(new Permission(PermissionKind.EnableContentDownloading, true));
entity.Permissions.Add(new Permission(PermissionKind.EnableMediaConversion, true));
entity.Permissions.Add(new Permission(PermissionKind.EnableMediaPlayback, true));
entity.Permissions.Add(new Permission(PermissionKind.EnablePlaybackRemuxing, true));
entity.Permissions.Add(new Permission(PermissionKind.EnablePublicSharing, true));
entity.Permissions.Add(new Permission(PermissionKind.EnableRemoteAccess, true));
entity.Permissions.Add(new Permission(PermissionKind.EnableSyncTranscoding, true));
entity.Permissions.Add(new Permission(PermissionKind.EnableAudioPlaybackTranscoding, true));
entity.Permissions.Add(new Permission(PermissionKind.EnableLiveTvAccess, true));
entity.Permissions.Add(new Permission(PermissionKind.EnableLiveTvManagement, true));
entity.Permissions.Add(new Permission(PermissionKind.EnableSharedDeviceControl, true));
entity.Permissions.Add(new Permission(PermissionKind.EnableVideoPlaybackTranscoding, true));
entity.Permissions.Add(new Permission(PermissionKind.ForceRemoteSourceTranscoding, false));
entity.Permissions.Add(new Permission(PermissionKind.EnableRemoteControlOfOtherUsers, false));
entity.Permissions.Add(new Permission(PermissionKind.EnableCollectionManagement, false));
entity.Permissions.Add(new Permission(PermissionKind.EnableSubtitleManagement, false));
entity.Permissions.Add(new Permission(PermissionKind.EnableLyricManagement, false));
}
/// <summary>
/// Initializes the default preferences. Should only be called on user creation.
/// </summary>
/// <param name="entity">The entity to update.</param>
public static void AddDefaultPreferences(this User entity)
{
foreach (var val in Enum.GetValues<PreferenceKind>())
{
entity.Preferences.Add(new Preference(val, string.Empty));
}
}
private static bool IsParentalScheduleAllowed(AccessSchedule schedule, DateTime date)
{
var localTime = date.ToLocalTime();
var hour = localTime.TimeOfDay.TotalHours;
var currentDayOfWeek = localTime.DayOfWeek;
return schedule.DayOfWeek.Contains(currentDayOfWeek)
&& hour >= schedule.StartHour
&& hour <= schedule.EndHour;
}
}