Sfoglia il codice sorgente

Merge branch 'master' into simplify-https-config

Mark Monteiro 5 anni fa
parent
commit
dc5165b97f
100 ha cambiato i file con 8859 aggiunte e 228 eliminazioni
  1. 0 59
      .copr/Makefile
  2. 1 0
      .copr/Makefile
  3. 7 10
      .editorconfig
  4. 3 0
      .github/CODEOWNERS
  5. 12 7
      .gitignore
  6. 2 0
      DvdLib/BigEndianBinaryReader.cs
  7. 1 0
      DvdLib/DvdLib.csproj
  8. 2 0
      DvdLib/Ifo/Cell.cs
  9. 2 0
      DvdLib/Ifo/CellPlaybackInfo.cs
  10. 2 0
      DvdLib/Ifo/CellPositionInfo.cs
  11. 2 0
      DvdLib/Ifo/Chapter.cs
  12. 2 0
      DvdLib/Ifo/Dvd.cs
  13. 2 0
      DvdLib/Ifo/DvdTime.cs
  14. 2 0
      DvdLib/Ifo/Program.cs
  15. 2 0
      DvdLib/Ifo/ProgramChain.cs
  16. 2 0
      DvdLib/Ifo/Title.cs
  17. 2 0
      DvdLib/Ifo/UserOperation.cs
  18. 10 7
      Emby.Naming/Audio/AlbumParser.cs
  19. 2 1
      Emby.Naming/Audio/AudioFileParser.cs
  20. 1 6
      Emby.Naming/Common/EpisodeExpression.cs
  21. 4 8
      Emby.Naming/Subtitles/SubtitleParser.cs
  22. 3 3
      Emby.Naming/Video/VideoResolver.cs
  23. 1 1
      Emby.Notifications/NotificationEntryPoint.cs
  24. 7 0
      Emby.Server.Implementations/ApplicationHost.cs
  25. 0 1
      Emby.Server.Implementations/ConfigurationOptions.cs
  26. 10 0
      Emby.Server.Implementations/Data/SqliteUserDataRepository.cs
  27. 1 0
      Emby.Server.Implementations/Emby.Server.Implementations.csproj
  28. 1 1
      Emby.Server.Implementations/HttpServer/HttpResultFactory.cs
  29. 4 0
      Emby.Server.Implementations/HttpServer/ResponseFilter.cs
  30. 4 2
      Emby.Server.Implementations/Library/MediaStreamSelector.cs
  31. 12 10
      Emby.Server.Implementations/Library/PathExtensions.cs
  32. 2 0
      Emby.Server.Implementations/Library/ResolverHelper.cs
  33. 25 0
      Emby.Server.Implementations/Library/UserManager.cs
  34. 1 1
      Emby.Server.Implementations/Localization/Core/af.json
  35. 24 2
      Emby.Server.Implementations/Localization/Core/el.json
  36. 1 1
      Emby.Server.Implementations/Localization/Core/es-MX.json
  37. 1 1
      Emby.Server.Implementations/Localization/Core/es.json
  38. 13 13
      Emby.Server.Implementations/Localization/Core/fi.json
  39. 19 1
      Emby.Server.Implementations/Localization/Core/fr-CA.json
  40. 46 35
      Emby.Server.Implementations/Localization/Core/gsw.json
  41. 1 1
      Emby.Server.Implementations/Localization/Core/he.json
  42. 10 2
      Emby.Server.Implementations/Localization/Core/hr.json
  43. 8 1
      Emby.Server.Implementations/Localization/Core/mk.json
  44. 3 3
      Emby.Server.Implementations/Localization/Core/nl.json
  45. 23 1
      Emby.Server.Implementations/Localization/Core/pl.json
  46. 22 1
      Emby.Server.Implementations/Localization/Core/sl-SI.json
  47. 4 3
      Emby.Server.Implementations/Localization/Core/sv.json
  48. 36 0
      Emby.Server.Implementations/Localization/Core/uk.json
  49. 5 2
      Emby.Server.Implementations/Localization/Core/zh-HK.json
  50. 2 14
      Emby.Server.Implementations/Services/StringMapTypeDeserializer.cs
  51. 4 16
      Emby.Server.Implementations/Services/UrlExtensions.cs
  52. 10 14
      Emby.Server.Implementations/SocketSharp/WebSocketSharpRequest.cs
  53. 1140 0
      Jellyfin.Data/DbContexts/Jellyfin.cs
  54. 208 0
      Jellyfin.Data/Entities/Artwork.cs
  55. 84 0
      Jellyfin.Data/Entities/Book.cs
  56. 123 0
      Jellyfin.Data/Entities/BookMetadata.cs
  57. 274 0
      Jellyfin.Data/Entities/Chapter.cs
  58. 131 0
      Jellyfin.Data/Entities/Collection.cs
  59. 151 0
      Jellyfin.Data/Entities/CollectionItem.cs
  60. 147 0
      Jellyfin.Data/Entities/Company.cs
  61. 234 0
      Jellyfin.Data/Entities/CompanyMetadata.cs
  62. 84 0
      Jellyfin.Data/Entities/CustomItem.cs
  63. 86 0
      Jellyfin.Data/Entities/CustomItemMetadata.cs
  64. 127 0
      Jellyfin.Data/Entities/Episode.cs
  65. 197 0
      Jellyfin.Data/Entities/EpisodeMetadata.cs
  66. 163 0
      Jellyfin.Data/Entities/Genre.cs
  67. 115 0
      Jellyfin.Data/Entities/Group.cs
  68. 158 0
      Jellyfin.Data/Entities/Library.cs
  69. 180 0
      Jellyfin.Data/Entities/LibraryItem.cs
  70. 202 0
      Jellyfin.Data/Entities/LibraryRoot.cs
  71. 209 0
      Jellyfin.Data/Entities/MediaFile.cs
  72. 160 0
      Jellyfin.Data/Entities/MediaFileStream.cs
  73. 385 0
      Jellyfin.Data/Entities/Metadata.cs
  74. 158 0
      Jellyfin.Data/Entities/MetadataProvider.cs
  75. 189 0
      Jellyfin.Data/Entities/MetadataProviderId.cs
  76. 84 0
      Jellyfin.Data/Entities/Movie.cs
  77. 239 0
      Jellyfin.Data/Entities/MovieMetadata.cs
  78. 84 0
      Jellyfin.Data/Entities/MusicAlbum.cs
  79. 202 0
      Jellyfin.Data/Entities/MusicAlbumMetadata.cs
  80. 152 0
      Jellyfin.Data/Entities/Permission.cs
  81. 40 0
      Jellyfin.Data/Entities/PermissionKind.cs
  82. 312 0
      Jellyfin.Data/Entities/Person.cs
  83. 215 0
      Jellyfin.Data/Entities/PersonRole.cs
  84. 84 0
      Jellyfin.Data/Entities/Photo.cs
  85. 86 0
      Jellyfin.Data/Entities/PhotoMetadata.cs
  86. 117 0
      Jellyfin.Data/Entities/Preference.cs
  87. 27 0
      Jellyfin.Data/Entities/PreferenceKind.cs
  88. 133 0
      Jellyfin.Data/Entities/ProviderMapping.cs
  89. 197 0
      Jellyfin.Data/Entities/Rating.cs
  90. 242 0
      Jellyfin.Data/Entities/RatingSource.cs
  91. 197 0
      Jellyfin.Data/Entities/Release.cs
  92. 127 0
      Jellyfin.Data/Entities/Season.cs
  93. 123 0
      Jellyfin.Data/Entities/SeasonMetadata.cs
  94. 183 0
      Jellyfin.Data/Entities/Series.cs
  95. 239 0
      Jellyfin.Data/Entities/SeriesMetadata.cs
  96. 127 0
      Jellyfin.Data/Entities/Track.cs
  97. 86 0
      Jellyfin.Data/Entities/TrackMetadata.cs
  98. 242 0
      Jellyfin.Data/Entities/User.cs
  99. 25 0
      Jellyfin.Data/Enums/ArtKind.cs
  100. 25 0
      Jellyfin.Data/Enums/MediaFileKind.cs

+ 0 - 59
.copr/Makefile

@@ -1,59 +0,0 @@
-VERSION := $(shell sed -ne '/^Version:/s/.*  *//p'                      \
-                   deployment/fedora-package-x64/pkg-src/jellyfin.spec)
-
-deployment/fedora-package-x64/pkg-src/jellyfin-web-$(VERSION).tar.gz:
-	curl -f -L -o deployment/fedora-package-x64/pkg-src/jellyfin-web-$(VERSION).tar.gz \
-         https://github.com/jellyfin/jellyfin-web/archive/v$(VERSION).tar.gz \
-	|| curl -f -L -o deployment/fedora-package-x64/pkg-src/jellyfin-web-$(VERSION).tar.gz \
-         https://github.com/jellyfin/jellyfin-web/archive/master.tar.gz \
-
-srpm: deployment/fedora-package-x64/pkg-src/jellyfin-web-$(VERSION).tar.gz
-	cd deployment/fedora-package-x64;                                             \
-    SOURCE_DIR=../..                                                              \
-    WORKDIR="$${PWD}";                                                            \
-    package_temporary_dir="$${WORKDIR}/pkg-dist-tmp";                             \
-    pkg_src_dir="$${WORKDIR}/pkg-src";                                            \
-    GNU_TAR=1;                                                                    \
-    tar                                                                           \
-    --transform "s,^\.,jellyfin-$(VERSION),"                                      \
-    --exclude='.git*'                                                             \
-    --exclude='**/.git'                                                           \
-    --exclude='**/.hg'                                                            \
-    --exclude='**/.vs'                                                            \
-    --exclude='**/.vscode'                                                        \
-    --exclude='deployment'                                                        \
-    --exclude='**/bin'                                                            \
-    --exclude='**/obj'                                                            \
-    --exclude='**/.nuget'                                                         \
-    --exclude='*.deb'                                                             \
-    --exclude='*.rpm'                                                             \
-    -czf "pkg-src/jellyfin-$(VERSION).tar.gz"                                     \
-    -C $${SOURCE_DIR} ./ || GNU_TAR=0;                                            \
-    if [ $${GNU_TAR} -eq 0 ]; then                                                \
-        package_temporary_dir="$$(mktemp -d)";                                    \
-        mkdir -p "$${package_temporary_dir}/jellyfin";                            \
-        tar                                                                       \
-        --exclude='.git*'                                                         \
-        --exclude='**/.git'                                                       \
-        --exclude='**/.hg'                                                        \
-        --exclude='**/.vs'                                                        \
-        --exclude='**/.vscode'                                                    \
-        --exclude='deployment'                                                    \
-        --exclude='**/bin'                                                        \
-        --exclude='**/obj'                                                        \
-        --exclude='**/.nuget'                                                     \
-        --exclude='*.deb'                                                         \
-        --exclude='*.rpm'                                                         \
-        -czf "$${package_temporary_dir}/jellyfin/jellyfin-$(VERSION).tar.gz"      \
-        -C $${SOURCE_DIR} ./;                                                     \
-        mkdir -p "$${package_temporary_dir}/jellyfin-$(VERSION)";                 \
-        tar -xzf "$${package_temporary_dir}/jellyfin/jellyfin-$(VERSION).tar.gz"  \
-            -C "$${package_temporary_dir}/jellyfin-$(VERSION);                    \
-        rm -f "$${package_temporary_dir}/jellyfin/jellyfin-$(VERSION).tar.gz";    \
-        tar -czf "$${SOURCE_DIR}/SOURCES/pkg-src/jellyfin-$(VERSION).tar.gz"      \
-            -C "$${package_temporary_dir}" "jellyfin-$(VERSION);                  \
-        rm -rf $${package_temporary_dir};                                         \
-	fi;                                                                           \
-	rpmbuild -bs pkg-src/jellyfin.spec                                            \
-	         --define "_sourcedir $$PWD/pkg-src/"                                 \
-	         --define "_srcrpmdir $(outdir)"

+ 1 - 0
.copr/Makefile

@@ -0,0 +1 @@
+../fedora/Makefile

+ 7 - 10
.editorconfig

@@ -13,7 +13,7 @@ charset = utf-8
 trim_trailing_whitespace = true
 trim_trailing_whitespace = true
 insert_final_newline = true
 insert_final_newline = true
 end_of_line = lf
 end_of_line = lf
-max_line_length = null
+max_line_length = off
 
 
 # YAML indentation
 # YAML indentation
 [*.{yml,yaml}]
 [*.{yml,yaml}]
@@ -22,6 +22,7 @@ indent_size = 2
 # XML indentation
 # XML indentation
 [*.{csproj,xml}]
 [*.{csproj,xml}]
 indent_size = 2
 indent_size = 2
+
 ###############################
 ###############################
 # .NET Coding Conventions     #
 # .NET Coding Conventions     #
 ###############################
 ###############################
@@ -51,11 +52,12 @@ dotnet_style_explicit_tuple_names = true:suggestion
 dotnet_style_null_propagation = true:suggestion
 dotnet_style_null_propagation = true:suggestion
 dotnet_style_coalesce_expression = true:suggestion
 dotnet_style_coalesce_expression = true:suggestion
 dotnet_style_prefer_is_null_check_over_reference_equality_method = true:silent
 dotnet_style_prefer_is_null_check_over_reference_equality_method = true:silent
-dotnet_prefer_inferred_tuple_names = true:suggestion
-dotnet_prefer_inferred_anonymous_type_member_names = true:suggestion
+dotnet_style_prefer_inferred_tuple_names = true:suggestion
+dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
 dotnet_style_prefer_auto_properties = true:silent
 dotnet_style_prefer_auto_properties = true:silent
 dotnet_style_prefer_conditional_expression_over_assignment = true:silent
 dotnet_style_prefer_conditional_expression_over_assignment = true:silent
 dotnet_style_prefer_conditional_expression_over_return = true:silent
 dotnet_style_prefer_conditional_expression_over_return = true:silent
+
 ###############################
 ###############################
 # Naming Conventions          #
 # Naming Conventions          #
 ###############################
 ###############################
@@ -67,7 +69,7 @@ dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.symbols = non
 dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.style = non_private_static_field_style
 dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.style = non_private_static_field_style
 
 
 dotnet_naming_symbols.non_private_static_fields.applicable_kinds = field
 dotnet_naming_symbols.non_private_static_fields.applicable_kinds = field
-dotnet_naming_symbols.non_private_static_fields.applicable_accessibilities = public, protected, internal, protected internal, private protected
+dotnet_naming_symbols.non_private_static_fields.applicable_accessibilities = public, protected, internal, protected_internal, private_protected
 dotnet_naming_symbols.non_private_static_fields.required_modifiers = static
 dotnet_naming_symbols.non_private_static_fields.required_modifiers = static
 
 
 dotnet_naming_style.non_private_static_field_style.capitalization = pascal_case
 dotnet_naming_style.non_private_static_field_style.capitalization = pascal_case
@@ -159,6 +161,7 @@ csharp_style_deconstructed_variable_declaration = true:suggestion
 csharp_prefer_simple_default_expression = true:suggestion
 csharp_prefer_simple_default_expression = true:suggestion
 csharp_style_pattern_local_over_anonymous_function = true:suggestion
 csharp_style_pattern_local_over_anonymous_function = true:suggestion
 csharp_style_inlined_variable_declaration = true:suggestion
 csharp_style_inlined_variable_declaration = true:suggestion
+
 ###############################
 ###############################
 # C# Formatting Rules         #
 # C# Formatting Rules         #
 ###############################
 ###############################
@@ -189,9 +192,3 @@ csharp_space_between_method_call_empty_parameter_list_parentheses = false
 # Wrapping preferences
 # Wrapping preferences
 csharp_preserve_single_line_statements = true
 csharp_preserve_single_line_statements = true
 csharp_preserve_single_line_blocks = true
 csharp_preserve_single_line_blocks = true
-###############################
-# VB Coding Conventions       #
-###############################
-[*.vb]
-# Modifier preferences
-visual_basic_preferred_modifier_order = Partial,Default,Private,Protected,Public,Friend,NotOverridable,Overridable,MustOverride,Overloads,Overrides,MustInherit,NotInheritable,Static,Shared,Shadows,ReadOnly,WriteOnly,Dim,Const,WithEvents,Widening,Narrowing,Custom,Async:suggestion

+ 3 - 0
.github/CODEOWNERS

@@ -0,0 +1,3 @@
+# Joshua must review all changes to deployment and build.sh
+deployment/*    @joshuaboniface
+build.sh        @joshuaboniface

+ 12 - 7
.gitignore

@@ -245,14 +245,14 @@ pip-log.txt
 #########################
 #########################
 
 
 # Artifacts for debian-x64
 # Artifacts for debian-x64
-deployment/debian-package-x64/pkg-src/.debhelper/
-deployment/debian-package-x64/pkg-src/*.debhelper
-deployment/debian-package-x64/pkg-src/debhelper-build-stamp
-deployment/debian-package-x64/pkg-src/files
-deployment/debian-package-x64/pkg-src/jellyfin.substvars
-deployment/debian-package-x64/pkg-src/jellyfin/
+debian/.debhelper/
+debian/*.debhelper
+debian/debhelper-build-stamp
+debian/files
+debian/jellyfin.substvars
+debian/jellyfin/
 # Don't ignore the debian/bin folder
 # Don't ignore the debian/bin folder
-!deployment/debian-package-x64/pkg-src/bin/
+!debian/bin/
 
 
 deployment/**/dist/
 deployment/**/dist/
 deployment/**/pkg-dist/
 deployment/**/pkg-dist/
@@ -272,3 +272,8 @@ dist
 
 
 # BenchmarkDotNet artifacts
 # BenchmarkDotNet artifacts
 BenchmarkDotNet.Artifacts
 BenchmarkDotNet.Artifacts
+
+# Ignore web artifacts from native builds
+web/
+web-src.*
+MediaBrowser.WebDashboard/jellyfin-web/

+ 2 - 0
DvdLib/BigEndianBinaryReader.cs

@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
 using System.Buffers.Binary;
 using System.Buffers.Binary;
 using System.IO;
 using System.IO;
 
 

+ 1 - 0
DvdLib/DvdLib.csproj

@@ -13,6 +13,7 @@
     <TargetFramework>netstandard2.1</TargetFramework>
     <TargetFramework>netstandard2.1</TargetFramework>
     <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
     <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
     <GenerateDocumentationFile>true</GenerateDocumentationFile>
     <GenerateDocumentationFile>true</GenerateDocumentationFile>
+    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
   </PropertyGroup>
   </PropertyGroup>
 
 
 </Project>
 </Project>

+ 2 - 0
DvdLib/Ifo/Cell.cs

@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
 using System.IO;
 using System.IO;
 
 
 namespace DvdLib.Ifo
 namespace DvdLib.Ifo

+ 2 - 0
DvdLib/Ifo/CellPlaybackInfo.cs

@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
 using System.IO;
 using System.IO;
 
 
 namespace DvdLib.Ifo
 namespace DvdLib.Ifo

+ 2 - 0
DvdLib/Ifo/CellPositionInfo.cs

@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
 using System.IO;
 using System.IO;
 
 
 namespace DvdLib.Ifo
 namespace DvdLib.Ifo

+ 2 - 0
DvdLib/Ifo/Chapter.cs

@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
 namespace DvdLib.Ifo
 namespace DvdLib.Ifo
 {
 {
     public class Chapter
     public class Chapter

+ 2 - 0
DvdLib/Ifo/Dvd.cs

@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.IO;
 using System.IO;

+ 2 - 0
DvdLib/Ifo/DvdTime.cs

@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
 using System;
 using System;
 
 
 namespace DvdLib.Ifo
 namespace DvdLib.Ifo

+ 2 - 0
DvdLib/Ifo/Program.cs

@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
 using System.Collections.Generic;
 using System.Collections.Generic;
 
 
 namespace DvdLib.Ifo
 namespace DvdLib.Ifo

+ 2 - 0
DvdLib/Ifo/ProgramChain.cs

@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.IO;
 using System.IO;
 using System.Linq;
 using System.Linq;

+ 2 - 0
DvdLib/Ifo/Title.cs

@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.IO;
 using System.IO;
 
 

+ 2 - 0
DvdLib/Ifo/UserOperation.cs

@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
 using System;
 using System;
 
 
 namespace DvdLib.Ifo
 namespace DvdLib.Ifo

+ 10 - 7
Emby.Naming/Audio/AlbumParser.cs

@@ -1,9 +1,9 @@
+#nullable enable
 #pragma warning disable CS1591
 #pragma warning disable CS1591
 
 
 using System;
 using System;
 using System.Globalization;
 using System.Globalization;
 using System.IO;
 using System.IO;
-using System.Linq;
 using System.Text.RegularExpressions;
 using System.Text.RegularExpressions;
 using Emby.Naming.Common;
 using Emby.Naming.Common;
 
 
@@ -21,8 +21,7 @@ namespace Emby.Naming.Audio
         public bool IsMultiPart(string path)
         public bool IsMultiPart(string path)
         {
         {
             var filename = Path.GetFileName(path);
             var filename = Path.GetFileName(path);
-
-            if (string.IsNullOrEmpty(filename))
+            if (filename.Length == 0)
             {
             {
                 return false;
                 return false;
             }
             }
@@ -39,18 +38,22 @@ namespace Emby.Naming.Audio
             filename = filename.Replace(')', ' ');
             filename = filename.Replace(')', ' ');
             filename = Regex.Replace(filename, @"\s+", " ");
             filename = Regex.Replace(filename, @"\s+", " ");
 
 
-            filename = filename.TrimStart();
+            ReadOnlySpan<char> trimmedFilename = filename.TrimStart();
 
 
             foreach (var prefix in _options.AlbumStackingPrefixes)
             foreach (var prefix in _options.AlbumStackingPrefixes)
             {
             {
-                if (filename.IndexOf(prefix, StringComparison.OrdinalIgnoreCase) != 0)
+                if (!trimmedFilename.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))
                 {
                 {
                     continue;
                     continue;
                 }
                 }
 
 
-                var tmp = filename.Substring(prefix.Length);
+                var tmp = trimmedFilename.Slice(prefix.Length).Trim();
 
 
-                tmp = tmp.Trim().Split(' ').FirstOrDefault() ?? string.Empty;
+                int index = tmp.IndexOf(' ');
+                if (index != -1)
+                {
+                    tmp = tmp.Slice(0, index);
+                }
 
 
                 if (int.TryParse(tmp, NumberStyles.Integer, CultureInfo.InvariantCulture, out _))
                 if (int.TryParse(tmp, NumberStyles.Integer, CultureInfo.InvariantCulture, out _))
                 {
                 {

+ 2 - 1
Emby.Naming/Audio/AudioFileParser.cs

@@ -1,3 +1,4 @@
+#nullable enable
 #pragma warning disable CS1591
 #pragma warning disable CS1591
 
 
 using System;
 using System;
@@ -11,7 +12,7 @@ namespace Emby.Naming.Audio
     {
     {
         public static bool IsAudioFile(string path, NamingOptions options)
         public static bool IsAudioFile(string path, NamingOptions options)
         {
         {
-            var extension = Path.GetExtension(path) ?? string.Empty;
+            var extension = Path.GetExtension(path);
             return options.AudioFileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase);
             return options.AudioFileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase);
         }
         }
     }
     }

+ 1 - 6
Emby.Naming/Common/EpisodeExpression.cs

@@ -23,11 +23,6 @@ namespace Emby.Naming.Common
         {
         {
         }
         }
 
 
-        public EpisodeExpression()
-            : this(null)
-        {
-        }
-
         public string Expression
         public string Expression
         {
         {
             get => _expression;
             get => _expression;
@@ -48,6 +43,6 @@ namespace Emby.Naming.Common
 
 
         public string[] DateTimeFormats { get; set; }
         public string[] DateTimeFormats { get; set; }
 
 
-        public Regex Regex => _regex ?? (_regex = new Regex(Expression, RegexOptions.IgnoreCase | RegexOptions.Compiled));
+        public Regex Regex => _regex ??= new Regex(Expression, RegexOptions.IgnoreCase | RegexOptions.Compiled);
     }
     }
 }
 }

+ 4 - 8
Emby.Naming/Subtitles/SubtitleParser.cs

@@ -1,3 +1,4 @@
+#nullable enable
 #pragma warning disable CS1591
 #pragma warning disable CS1591
 
 
 using System;
 using System;
@@ -16,11 +17,11 @@ namespace Emby.Naming.Subtitles
             _options = options;
             _options = options;
         }
         }
 
 
-        public SubtitleInfo ParseFile(string path)
+        public SubtitleInfo? ParseFile(string path)
         {
         {
-            if (string.IsNullOrEmpty(path))
+            if (path.Length == 0)
             {
             {
-                throw new ArgumentNullException(nameof(path));
+                throw new ArgumentException("File path can't be empty.", nameof(path));
             }
             }
 
 
             var extension = Path.GetExtension(path);
             var extension = Path.GetExtension(path);
@@ -52,11 +53,6 @@ namespace Emby.Naming.Subtitles
 
 
         private string[] GetFlags(string path)
         private string[] GetFlags(string path)
         {
         {
-            if (string.IsNullOrEmpty(path))
-            {
-                throw new ArgumentNullException(nameof(path));
-            }
-
             // Note: the tags need be be surrounded be either a space ( ), hyphen -, dot . or underscore _.
             // Note: the tags need be be surrounded be either a space ( ), hyphen -, dot . or underscore _.
 
 
             var file = Path.GetFileName(path);
             var file = Path.GetFileName(path);

+ 3 - 3
Emby.Naming/Video/VideoResolver.cs

@@ -89,14 +89,14 @@ namespace Emby.Naming.Video
             if (parseName)
             if (parseName)
             {
             {
                 var cleanDateTimeResult = CleanDateTime(name);
                 var cleanDateTimeResult = CleanDateTime(name);
+                name = cleanDateTimeResult.Name;
+                year = cleanDateTimeResult.Year;
 
 
                 if (extraResult.ExtraType == null
                 if (extraResult.ExtraType == null
-                    && TryCleanString(cleanDateTimeResult.Name, out ReadOnlySpan<char> newName))
+                    && TryCleanString(name, out ReadOnlySpan<char> newName))
                 {
                 {
                     name = newName.ToString();
                     name = newName.ToString();
                 }
                 }
-
-                year = cleanDateTimeResult.Year;
             }
             }
 
 
             return new VideoFileInfo
             return new VideoFileInfo

+ 1 - 1
Emby.Notifications/NotificationEntryPoint.cs

@@ -143,7 +143,7 @@ namespace Emby.Notifications
 
 
             var notification = new NotificationRequest
             var notification = new NotificationRequest
             {
             {
-                Description = "Please see jellyfin.media for details.",
+                Description = "Please see jellyfin.org for details.",
                 NotificationType = type,
                 NotificationType = type,
                 Name = _localization.GetLocalizedString("NewVersionIsAvailable")
                 Name = _localization.GetLocalizedString("NewVersionIsAvailable")
             };
             };

+ 7 - 0
Emby.Server.Implementations/ApplicationHost.cs

@@ -105,6 +105,7 @@ using Microsoft.AspNetCore.Http.Extensions;
 using Microsoft.Extensions.DependencyInjection;
 using Microsoft.Extensions.DependencyInjection;
 using Microsoft.Extensions.Logging;
 using Microsoft.Extensions.Logging;
 using OperatingSystem = MediaBrowser.Common.System.OperatingSystem;
 using OperatingSystem = MediaBrowser.Common.System.OperatingSystem;
+using Prometheus.DotNetRuntime;
 
 
 namespace Emby.Server.Implementations
 namespace Emby.Server.Implementations
 {
 {
@@ -258,6 +259,12 @@ namespace Emby.Server.Implementations
 
 
             _startupOptions = options;
             _startupOptions = options;
 
 
+            // Initialize runtime stat collection
+            if (ServerConfigurationManager.Configuration.EnableMetrics)
+            {
+                DotNetRuntimeStatsBuilder.Default().StartCollecting();
+            }
+
             fileSystem.AddShortcutHandler(new MbLinkShortcutHandler(fileSystem));
             fileSystem.AddShortcutHandler(new MbLinkShortcutHandler(fileSystem));
 
 
             _networkManager.NetworkChanged += OnNetworkChanged;
             _networkManager.NetworkChanged += OnNetworkChanged;

+ 0 - 1
Emby.Server.Implementations/ConfigurationOptions.cs

@@ -1,7 +1,6 @@
 using System.Collections.Generic;
 using System.Collections.Generic;
 using Emby.Server.Implementations.HttpServer;
 using Emby.Server.Implementations.HttpServer;
 using Emby.Server.Implementations.Updates;
 using Emby.Server.Implementations.Updates;
-using MediaBrowser.Providers.Music;
 using static MediaBrowser.Controller.Extensions.ConfigurationExtensions;
 using static MediaBrowser.Controller.Extensions.ConfigurationExtensions;
 
 
 namespace Emby.Server.Implementations
 namespace Emby.Server.Implementations

+ 10 - 0
Emby.Server.Implementations/Data/SqliteUserDataRepository.cs

@@ -375,5 +375,15 @@ namespace Emby.Server.Implementations.Data
 
 
             return userData;
             return userData;
         }
         }
+
+        /// <inheritdoc/>
+        /// <remarks>
+        /// There is nothing to dispose here since <see cref="BaseSqliteRepository.WriteLock"/> and
+        /// <see cref="BaseSqliteRepository.WriteConnection"/> are managed by <see cref="SqliteItemRepository"/>.
+        /// See <see cref="Initialize(IUserManager, SemaphoreSlim, SQLiteDatabaseConnection)"/>.
+        /// </remarks>
+        protected override void Dispose(bool dispose)
+        {
+        }
     }
     }
 }
 }

+ 1 - 0
Emby.Server.Implementations/Emby.Server.Implementations.csproj

@@ -39,6 +39,7 @@
     <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.1.3" />
     <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.1.3" />
     <PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="3.1.3" />
     <PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="3.1.3" />
     <PackageReference Include="Mono.Nat" Version="2.0.1" />
     <PackageReference Include="Mono.Nat" Version="2.0.1" />
+    <PackageReference Include="prometheus-net.DotNetRuntime" Version="3.3.1" />
     <PackageReference Include="ServiceStack.Text.Core" Version="5.8.0" />
     <PackageReference Include="ServiceStack.Text.Core" Version="5.8.0" />
     <PackageReference Include="sharpcompress" Version="0.25.0" />
     <PackageReference Include="sharpcompress" Version="0.25.0" />
     <PackageReference Include="SQLitePCL.pretty.netstandard" Version="2.1.0" />
     <PackageReference Include="SQLitePCL.pretty.netstandard" Version="2.1.0" />

+ 1 - 1
Emby.Server.Implementations/HttpServer/HttpResultFactory.cs

@@ -426,7 +426,7 @@ namespace Emby.Server.Implementations.HttpServer
 
 
             if (!noCache)
             if (!noCache)
             {
             {
-                if (!DateTime.TryParseExact(requestContext.Headers[HeaderNames.IfModifiedSince], HttpDateFormat, _enUSculture, DateTimeStyles.AssumeUniversal, out var ifModifiedSinceHeader))
+                if (!DateTime.TryParseExact(requestContext.Headers[HeaderNames.IfModifiedSince], HttpDateFormat, _enUSculture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal, out var ifModifiedSinceHeader))
                 {
                 {
                     _logger.LogDebug("Failed to parse If-Modified-Since header date: {0}", requestContext.Headers[HeaderNames.IfModifiedSince]);
                     _logger.LogDebug("Failed to parse If-Modified-Since header date: {0}", requestContext.Headers[HeaderNames.IfModifiedSince]);
                     return null;
                     return null;

+ 4 - 0
Emby.Server.Implementations/HttpServer/ResponseFilter.cs

@@ -82,6 +82,10 @@ namespace Emby.Server.Implementations.HttpServer
             {
             {
                 return null;
                 return null;
             }
             }
+            else if (inString.Length == 0)
+            {
+                return inString;
+            }
 
 
             var newString = new StringBuilder(inString.Length);
             var newString = new StringBuilder(inString.Length);
 
 

+ 4 - 2
Emby.Server.Implementations/Library/MediaStreamSelector.cs

@@ -35,7 +35,8 @@ namespace Emby.Server.Implementations.Library
             return null;
             return null;
         }
         }
 
 
-        public static int? GetDefaultSubtitleStreamIndex(List<MediaStream> streams,
+        public static int? GetDefaultSubtitleStreamIndex(
+            List<MediaStream> streams,
             string[] preferredLanguages,
             string[] preferredLanguages,
             SubtitlePlaybackMode mode,
             SubtitlePlaybackMode mode,
             string audioTrackLanguage)
             string audioTrackLanguage)
@@ -115,7 +116,8 @@ namespace Emby.Server.Implementations.Library
                  .ThenBy(i => i.Index);
                  .ThenBy(i => i.Index);
         }
         }
 
 
-        public static void SetSubtitleStreamScores(List<MediaStream> streams,
+        public static void SetSubtitleStreamScores(
+            List<MediaStream> streams,
             string[] preferredLanguages,
             string[] preferredLanguages,
             SubtitlePlaybackMode mode,
             SubtitlePlaybackMode mode,
             string audioTrackLanguage)
             string audioTrackLanguage)

+ 12 - 10
Emby.Server.Implementations/Library/PathExtensions.cs

@@ -1,3 +1,5 @@
+#nullable enable
+
 using System;
 using System;
 using System.Text.RegularExpressions;
 using System.Text.RegularExpressions;
 
 
@@ -12,24 +14,24 @@ namespace Emby.Server.Implementations.Library
         /// Gets the attribute value.
         /// Gets the attribute value.
         /// </summary>
         /// </summary>
         /// <param name="str">The STR.</param>
         /// <param name="str">The STR.</param>
-        /// <param name="attrib">The attrib.</param>
+        /// <param name="attribute">The attrib.</param>
         /// <returns>System.String.</returns>
         /// <returns>System.String.</returns>
-        /// <exception cref="ArgumentNullException">attrib</exception>
-        public static string GetAttributeValue(this string str, string attrib)
+        /// <exception cref="ArgumentException"><paramref name="str" /> or <paramref name="attribute" /> is empty.</exception>
+        public static string? GetAttributeValue(this string str, string attribute)
         {
         {
-            if (string.IsNullOrEmpty(str))
+            if (str.Length == 0)
             {
             {
-                throw new ArgumentNullException(nameof(str));
+                throw new ArgumentException("String can't be empty.", nameof(str));
             }
             }
 
 
-            if (string.IsNullOrEmpty(attrib))
+            if (attribute.Length == 0)
             {
             {
-                throw new ArgumentNullException(nameof(attrib));
+                throw new ArgumentException("String can't be empty.", nameof(attribute));
             }
             }
 
 
-            string srch = "[" + attrib + "=";
+            string srch = "[" + attribute + "=";
             int start = str.IndexOf(srch, StringComparison.OrdinalIgnoreCase);
             int start = str.IndexOf(srch, StringComparison.OrdinalIgnoreCase);
-            if (start > -1)
+            if (start != -1)
             {
             {
                 start += srch.Length;
                 start += srch.Length;
                 int end = str.IndexOf(']', start);
                 int end = str.IndexOf(']', start);
@@ -37,7 +39,7 @@ namespace Emby.Server.Implementations.Library
             }
             }
 
 
             // for imdbid we also accept pattern matching
             // for imdbid we also accept pattern matching
-            if (string.Equals(attrib, "imdbid", StringComparison.OrdinalIgnoreCase))
+            if (string.Equals(attribute, "imdbid", StringComparison.OrdinalIgnoreCase))
             {
             {
                 var m = Regex.Match(str, "tt([0-9]{7,8})", RegexOptions.IgnoreCase);
                 var m = Regex.Match(str, "tt([0-9]{7,8})", RegexOptions.IgnoreCase);
                 return m.Success ? m.Value : null;
                 return m.Success ? m.Value : null;

+ 2 - 0
Emby.Server.Implementations/Library/ResolverHelper.cs

@@ -118,10 +118,12 @@ namespace Emby.Server.Implementations.Library
             {
             {
                 throw new ArgumentNullException(nameof(fileSystem));
                 throw new ArgumentNullException(nameof(fileSystem));
             }
             }
+
             if (item == null)
             if (item == null)
             {
             {
                 throw new ArgumentNullException(nameof(item));
                 throw new ArgumentNullException(nameof(item));
             }
             }
+
             if (args == null)
             if (args == null)
             {
             {
                 throw new ArgumentNullException(nameof(args));
                 throw new ArgumentNullException(nameof(args));

+ 25 - 0
Emby.Server.Implementations/Library/UserManager.cs

@@ -608,6 +608,31 @@ namespace Emby.Server.Implementations.Library
             return dto;
             return dto;
         }
         }
 
 
+        public PublicUserDto GetPublicUserDto(User user, string remoteEndPoint = null)
+        {
+            if (user == null)
+            {
+                throw new ArgumentNullException(nameof(user));
+            }
+
+            IAuthenticationProvider authenticationProvider = GetAuthenticationProvider(user);
+            bool hasConfiguredPassword = authenticationProvider.HasPassword(user);
+            bool hasConfiguredEasyPassword = !string.IsNullOrEmpty(authenticationProvider.GetEasyPasswordHash(user));
+
+            bool hasPassword = user.Configuration.EnableLocalPassword &&
+                !string.IsNullOrEmpty(remoteEndPoint) &&
+                _networkManager.IsInLocalNetwork(remoteEndPoint) ? hasConfiguredEasyPassword : hasConfiguredPassword;
+
+            PublicUserDto dto = new PublicUserDto
+            {
+                Name = user.Name,
+                HasPassword = hasPassword,
+                HasConfiguredPassword = hasConfiguredPassword,
+            };
+
+            return dto;
+        }
+
         public UserDto GetOfflineUserDto(User user)
         public UserDto GetOfflineUserDto(User user)
         {
         {
             var dto = GetUserDto(user);
             var dto = GetUserDto(user);

+ 1 - 1
Emby.Server.Implementations/Localization/Core/af.json

@@ -4,7 +4,7 @@
     "Folders": "Fouers",
     "Folders": "Fouers",
     "Favorites": "Gunstelinge",
     "Favorites": "Gunstelinge",
     "HeaderFavoriteShows": "Gunsteling Vertonings",
     "HeaderFavoriteShows": "Gunsteling Vertonings",
-    "ValueSpecialEpisodeName": "Spesiaal - {0}",
+    "ValueSpecialEpisodeName": "Spesiale - {0}",
     "HeaderAlbumArtists": "Album Kunstenaars",
     "HeaderAlbumArtists": "Album Kunstenaars",
     "Books": "Boeke",
     "Books": "Boeke",
     "HeaderNextUp": "Volgende",
     "HeaderNextUp": "Volgende",

+ 24 - 2
Emby.Server.Implementations/Localization/Core/el.json

@@ -1,5 +1,5 @@
 {
 {
-    "Albums": "Άλμπουμ",
+    "Albums": "Άλμπουμς",
     "AppDeviceValues": "Εφαρμογή: {0}, Συσκευή: {1}",
     "AppDeviceValues": "Εφαρμογή: {0}, Συσκευή: {1}",
     "Application": "Εφαρμογή",
     "Application": "Εφαρμογή",
     "Artists": "Καλλιτέχνες",
     "Artists": "Καλλιτέχνες",
@@ -92,5 +92,27 @@
     "UserStoppedPlayingItemWithValues": "{0} τελείωσε να παίζει {1} σε {2}",
     "UserStoppedPlayingItemWithValues": "{0} τελείωσε να παίζει {1} σε {2}",
     "ValueHasBeenAddedToLibrary": "{0} προστέθηκαν στη βιβλιοθήκη πολυμέσων σας",
     "ValueHasBeenAddedToLibrary": "{0} προστέθηκαν στη βιβλιοθήκη πολυμέσων σας",
     "ValueSpecialEpisodeName": "Σπέσιαλ - {0}",
     "ValueSpecialEpisodeName": "Σπέσιαλ - {0}",
-    "VersionNumber": "Έκδοση {0}"
+    "VersionNumber": "Έκδοση {0}",
+    "TaskRefreshPeople": "Ανανέωση Ατόμων",
+    "TaskCleanLogsDescription": "Διαγράφει τα αρχεία καταγραφής που είναι άνω των {0} ημερών.",
+    "TaskCleanLogs": "Καθαρισμός Καταλόγου Καταγραφής",
+    "TaskRefreshLibraryDescription": "Σαρώνει την βιβλιοθήκη πολυμέσων σας για νέα αρχεία και αναζωογονεί τα μεταδεδομένα.",
+    "TaskRefreshLibrary": "Βιβλιοθήκη Σάρωσης Πολυμέσων",
+    "TaskRefreshChapterImagesDescription": "Δημιουργεί μικρογραφίες για βίντεο με κεφάλαια.",
+    "TaskRefreshChapterImages": "Εξαγωγή Εικόνων Κεφαλαίου",
+    "TaskCleanCacheDescription": "Τα διαγραμμένα αρχεία προσωρινής μνήμης που δεν χρειάζονται πλέον από το σύστημα.",
+    "TaskCleanCache": "Καθαρισμός Καταλόγου Προσωρινής Μνήμης",
+    "TasksChannelsCategory": "Κανάλια Διαδικτύου",
+    "TasksApplicationCategory": "Εφαρμογή",
+    "TasksLibraryCategory": "Βιβλιοθήκη",
+    "TasksMaintenanceCategory": "Συντήρηση",
+    "TaskDownloadMissingSubtitlesDescription": "Αναζητήσεις στο διαδίκτυο όπου λείπουν υπότιτλους με βάση τη διαμόρφωση μεταδεδομένων.",
+    "TaskDownloadMissingSubtitles": "Λήψη υπότιτλων που λείπουν",
+    "TaskRefreshChannelsDescription": "Ανανεώνει τις πληροφορίες καναλιού στο διαδικτύου.",
+    "TaskRefreshChannels": "Ανανέωση Καναλιών",
+    "TaskCleanTranscodeDescription": "Διαγράφει αρχείου διακωδικοποιητή περισσότερο από μία ημέρα.",
+    "TaskCleanTranscode": "Καθαρισμός Kαταλόγου Διακωδικοποιητή",
+    "TaskUpdatePluginsDescription": "Κατεβάζει και εγκαθιστά ενημερώσεις για τις προσθήκες που έχουν ρυθμιστεί για αυτόματη ενημέρωση.",
+    "TaskUpdatePlugins": "Ενημέρωση Προσθηκών",
+    "TaskRefreshPeopleDescription": "Ενημερώνει μεταδεδομένα για ηθοποιούς και σκηνοθέτες στην βιβλιοθήκη των πολυμέσων σας."
 }
 }

+ 1 - 1
Emby.Server.Implementations/Localization/Core/es-MX.json

@@ -11,7 +11,7 @@
     "Collections": "Colecciones",
     "Collections": "Colecciones",
     "DeviceOfflineWithName": "{0} se ha desconectado",
     "DeviceOfflineWithName": "{0} se ha desconectado",
     "DeviceOnlineWithName": "{0} está conectado",
     "DeviceOnlineWithName": "{0} está conectado",
-    "FailedLoginAttemptWithUserName": "Intento fallido de inicio de sesión de {0}",
+    "FailedLoginAttemptWithUserName": "Intento fallido de inicio de sesión desde {0}",
     "Favorites": "Favoritos",
     "Favorites": "Favoritos",
     "Folders": "Carpetas",
     "Folders": "Carpetas",
     "Genres": "Géneros",
     "Genres": "Géneros",

+ 1 - 1
Emby.Server.Implementations/Localization/Core/es.json

@@ -71,7 +71,7 @@
     "ScheduledTaskFailedWithName": "{0} falló",
     "ScheduledTaskFailedWithName": "{0} falló",
     "ScheduledTaskStartedWithName": "{0} iniciada",
     "ScheduledTaskStartedWithName": "{0} iniciada",
     "ServerNameNeedsToBeRestarted": "{0} necesita ser reiniciado",
     "ServerNameNeedsToBeRestarted": "{0} necesita ser reiniciado",
-    "Shows": "Series",
+    "Shows": "Mostrar",
     "Songs": "Canciones",
     "Songs": "Canciones",
     "StartupEmbyServerIsLoading": "Jellyfin Server se está cargando. Vuelve a intentarlo en breve.",
     "StartupEmbyServerIsLoading": "Jellyfin Server se está cargando. Vuelve a intentarlo en breve.",
     "SubtitleDownloadFailureForItem": "Error al descargar subtítulos para {0}",
     "SubtitleDownloadFailureForItem": "Error al descargar subtítulos para {0}",

+ 13 - 13
Emby.Server.Implementations/Localization/Core/fi.json

@@ -1,5 +1,5 @@
 {
 {
-    "HeaderLiveTV": "Suorat lähetykset",
+    "HeaderLiveTV": "Live-TV",
     "NewVersionIsAvailable": "Uusi versio Jellyfin palvelimesta on ladattavissa.",
     "NewVersionIsAvailable": "Uusi versio Jellyfin palvelimesta on ladattavissa.",
     "NameSeasonUnknown": "Tuntematon Kausi",
     "NameSeasonUnknown": "Tuntematon Kausi",
     "NameSeasonNumber": "Kausi {0}",
     "NameSeasonNumber": "Kausi {0}",
@@ -12,7 +12,7 @@
     "MessageNamedServerConfigurationUpdatedWithValue": "Palvelimen asetusryhmä {0} on päivitetty",
     "MessageNamedServerConfigurationUpdatedWithValue": "Palvelimen asetusryhmä {0} on päivitetty",
     "MessageApplicationUpdatedTo": "Jellyfin palvelin on päivitetty versioon {0}",
     "MessageApplicationUpdatedTo": "Jellyfin palvelin on päivitetty versioon {0}",
     "MessageApplicationUpdated": "Jellyfin palvelin on päivitetty",
     "MessageApplicationUpdated": "Jellyfin palvelin on päivitetty",
-    "Latest": "Viimeisin",
+    "Latest": "Uusimmat",
     "LabelRunningTimeValue": "Toiston kesto: {0}",
     "LabelRunningTimeValue": "Toiston kesto: {0}",
     "LabelIpAddressValue": "IP-osoite: {0}",
     "LabelIpAddressValue": "IP-osoite: {0}",
     "ItemRemovedWithName": "{0} poistettiin kirjastosta",
     "ItemRemovedWithName": "{0} poistettiin kirjastosta",
@@ -41,7 +41,7 @@
     "CameraImageUploadedFrom": "Uusi kamerakuva on ladattu {0}",
     "CameraImageUploadedFrom": "Uusi kamerakuva on ladattu {0}",
     "Books": "Kirjat",
     "Books": "Kirjat",
     "AuthenticationSucceededWithUserName": "{0} todennus onnistui",
     "AuthenticationSucceededWithUserName": "{0} todennus onnistui",
-    "Artists": "Esiintyjät",
+    "Artists": "Artistit",
     "Application": "Sovellus",
     "Application": "Sovellus",
     "AppDeviceValues": "Sovellus: {0}, Laite: {1}",
     "AppDeviceValues": "Sovellus: {0}, Laite: {1}",
     "Albums": "Albumit",
     "Albums": "Albumit",
@@ -67,21 +67,21 @@
     "UserDownloadingItemWithValues": "{0} lataa {1}",
     "UserDownloadingItemWithValues": "{0} lataa {1}",
     "UserDeletedWithName": "Käyttäjä {0} poistettu",
     "UserDeletedWithName": "Käyttäjä {0} poistettu",
     "UserCreatedWithName": "Käyttäjä {0} luotu",
     "UserCreatedWithName": "Käyttäjä {0} luotu",
-    "TvShows": "TV-Ohjelmat",
+    "TvShows": "TV-sarjat",
     "Sync": "Synkronoi",
     "Sync": "Synkronoi",
-    "SubtitleDownloadFailureFromForItem": "Tekstityksen lataaminen epäonnistui {0} - {1}",
+    "SubtitleDownloadFailureFromForItem": "Tekstitysten lataus ({0} -> {1}) epäonnistui //this string would have to be generated for each provider and movie because of finnish cases, sorry",
     "StartupEmbyServerIsLoading": "Jellyfin palvelin latautuu. Kokeile hetken kuluttua uudelleen.",
     "StartupEmbyServerIsLoading": "Jellyfin palvelin latautuu. Kokeile hetken kuluttua uudelleen.",
     "Songs": "Kappaleet",
     "Songs": "Kappaleet",
-    "Shows": "Ohjelmat",
-    "ServerNameNeedsToBeRestarted": "{0} vaatii uudelleenkäynnistyksen",
+    "Shows": "Sarjat",
+    "ServerNameNeedsToBeRestarted": "{0} täytyy käynnistää uudelleen",
     "ProviderValue": "Tarjoaja: {0}",
     "ProviderValue": "Tarjoaja: {0}",
     "Plugin": "Liitännäinen",
     "Plugin": "Liitännäinen",
     "NotificationOptionVideoPlaybackStopped": "Videon toisto pysäytetty",
     "NotificationOptionVideoPlaybackStopped": "Videon toisto pysäytetty",
-    "NotificationOptionVideoPlayback": "Videon toisto aloitettu",
-    "NotificationOptionUserLockedOut": "Käyttäjä lukittu",
+    "NotificationOptionVideoPlayback": "Videota toistetaan",
+    "NotificationOptionUserLockedOut": "Käyttäjä kirjautui ulos",
     "NotificationOptionTaskFailed": "Ajastettu tehtävä epäonnistui",
     "NotificationOptionTaskFailed": "Ajastettu tehtävä epäonnistui",
-    "NotificationOptionServerRestartRequired": "Palvelimen uudelleenkäynnistys vaaditaan",
-    "NotificationOptionPluginUpdateInstalled": "Lisäosan päivitys asennettu",
+    "NotificationOptionServerRestartRequired": "Palvelin pitää käynnistää uudelleen",
+    "NotificationOptionPluginUpdateInstalled": "Liitännäinen päivitetty",
     "NotificationOptionPluginUninstalled": "Liitännäinen poistettu",
     "NotificationOptionPluginUninstalled": "Liitännäinen poistettu",
     "NotificationOptionPluginInstalled": "Liitännäinen asennettu",
     "NotificationOptionPluginInstalled": "Liitännäinen asennettu",
     "NotificationOptionPluginError": "Ongelma liitännäisessä",
     "NotificationOptionPluginError": "Ongelma liitännäisessä",
@@ -90,8 +90,8 @@
     "NotificationOptionCameraImageUploaded": "Kameran kuva ladattu",
     "NotificationOptionCameraImageUploaded": "Kameran kuva ladattu",
     "NotificationOptionAudioPlaybackStopped": "Äänen toisto lopetettu",
     "NotificationOptionAudioPlaybackStopped": "Äänen toisto lopetettu",
     "NotificationOptionAudioPlayback": "Toistetaan ääntä",
     "NotificationOptionAudioPlayback": "Toistetaan ääntä",
-    "NotificationOptionApplicationUpdateInstalled": "Uusi sovellusversio asennettu",
-    "NotificationOptionApplicationUpdateAvailable": "Sovelluksesta on uusi versio saatavilla",
+    "NotificationOptionApplicationUpdateInstalled": "Sovelluspäivitys asennettu",
+    "NotificationOptionApplicationUpdateAvailable": "Ohjelmistopäivitys saatavilla",
     "TasksMaintenanceCategory": "Ylläpito",
     "TasksMaintenanceCategory": "Ylläpito",
     "TaskDownloadMissingSubtitlesDescription": "Etsii puuttuvia tekstityksiä videon metadatatietojen pohjalta.",
     "TaskDownloadMissingSubtitlesDescription": "Etsii puuttuvia tekstityksiä videon metadatatietojen pohjalta.",
     "TaskDownloadMissingSubtitles": "Lataa puuttuvat tekstitykset",
     "TaskDownloadMissingSubtitles": "Lataa puuttuvat tekstitykset",

+ 19 - 1
Emby.Server.Implementations/Localization/Core/fr-CA.json

@@ -94,5 +94,23 @@
     "ValueSpecialEpisodeName": "Spécial - {0}",
     "ValueSpecialEpisodeName": "Spécial - {0}",
     "VersionNumber": "Version {0}",
     "VersionNumber": "Version {0}",
     "TasksLibraryCategory": "Bibliothèque",
     "TasksLibraryCategory": "Bibliothèque",
-    "TasksMaintenanceCategory": "Entretien"
+    "TasksMaintenanceCategory": "Entretien",
+    "TaskDownloadMissingSubtitlesDescription": "Recherche l'internet pour des sous-titres manquants à base de métadonnées configurées.",
+    "TaskDownloadMissingSubtitles": "Télécharger des sous-titres manquants",
+    "TaskRefreshChannelsDescription": "Rafraîchit des informations des chaines d'internet.",
+    "TaskRefreshChannels": "Rafraîchir des chaines",
+    "TaskCleanTranscodeDescription": "Retirer des fichiers de transcodage de plus qu'un jour.",
+    "TaskCleanTranscode": "Nettoyer le directoire de transcodage",
+    "TaskUpdatePluginsDescription": "Télécharger et installer des mises à jours des plugins qui sont configurés m.à.j. automisés.",
+    "TaskUpdatePlugins": "Mise à jour des plugins",
+    "TaskRefreshPeopleDescription": "Met à jour les métadonnées pour les acteurs et réalisateurs dans votre bibliothèque.",
+    "TaskRefreshPeople": "Rafraîchir les acteurs",
+    "TaskCleanLogsDescription": "Retire les données qui ont plus que {0} jours.",
+    "TaskCleanLogs": "Nettoyer les données de directoire",
+    "TaskRefreshLibraryDescription": "Analyse votre bibliothèque média pour des nouveaux fichiers et rafraîchit les métadonnées.",
+    "TaskRefreshChapterImages": "Extraire des images du chapitre",
+    "TaskRefreshChapterImagesDescription": "Créer des vignettes pour des vidéos qui ont des chapitres",
+    "TaskRefreshLibrary": "Analyser la bibliothèque de média",
+    "TaskCleanCache": "Nettoyer le cache de directoire",
+    "TasksApplicationCategory": "Application"
 }
 }

+ 46 - 35
Emby.Server.Implementations/Localization/Core/gsw.json

@@ -1,41 +1,41 @@
 {
 {
-    "Albums": "Albom",
-    "AppDeviceValues": "App: {0}, Grät: {1}",
-    "Application": "Aawändig",
-    "Artists": "Könstler",
-    "AuthenticationSucceededWithUserName": "{0} het sech aagmäudet",
-    "Books": "Büecher",
-    "CameraImageUploadedFrom": "Es nöis Foti esch ufeglade worde vo {0}",
-    "Channels": "Kanäu",
-    "ChapterNameValue": "Kapitu {0}",
-    "Collections": "Sammlige",
-    "DeviceOfflineWithName": "{0} esch offline gange",
-    "DeviceOnlineWithName": "{0} esch online cho",
-    "FailedLoginAttemptWithUserName": "Fäugschlagne Aamäudeversuech vo {0}",
-    "Favorites": "Favorite",
+    "Albums": "Alben",
+    "AppDeviceValues": "App: {0}, Gerät: {1}",
+    "Application": "Anwendung",
+    "Artists": "Künstler",
+    "AuthenticationSucceededWithUserName": "{0} hat sich angemeldet",
+    "Books": "Bücher",
+    "CameraImageUploadedFrom": "Ein neues Foto wurde von {0} hochgeladen",
+    "Channels": "Kanäle",
+    "ChapterNameValue": "Kapitel {0}",
+    "Collections": "Sammlungen",
+    "DeviceOfflineWithName": "{0} wurde getrennt",
+    "DeviceOnlineWithName": "{0} ist verbunden",
+    "FailedLoginAttemptWithUserName": "Fehlgeschlagener Anmeldeversuch von {0}",
+    "Favorites": "Favoriten",
     "Folders": "Ordner",
     "Folders": "Ordner",
     "Genres": "Genres",
     "Genres": "Genres",
-    "HeaderAlbumArtists": "Albom-Könstler",
+    "HeaderAlbumArtists": "Album-Künstler",
     "HeaderCameraUploads": "Kamera-Uploads",
     "HeaderCameraUploads": "Kamera-Uploads",
-    "HeaderContinueWatching": "Wiiterluege",
-    "HeaderFavoriteAlbums": "Lieblingsalbe",
-    "HeaderFavoriteArtists": "Lieblings-Interprete",
-    "HeaderFavoriteEpisodes": "Lieblingsepisode",
-    "HeaderFavoriteShows": "Lieblingsserie",
+    "HeaderContinueWatching": "weiter schauen",
+    "HeaderFavoriteAlbums": "Lieblingsalben",
+    "HeaderFavoriteArtists": "Lieblings-Künstler",
+    "HeaderFavoriteEpisodes": "Lieblingsepisoden",
+    "HeaderFavoriteShows": "Lieblingsserien",
     "HeaderFavoriteSongs": "Lieblingslieder",
     "HeaderFavoriteSongs": "Lieblingslieder",
-    "HeaderLiveTV": "Live-Färnseh",
-    "HeaderNextUp": "Als nächts",
-    "HeaderRecordingGroups": "Ufnahmegruppe",
-    "HomeVideos": "Heimfilmli",
-    "Inherit": "Hinzuefüege",
-    "ItemAddedWithName": "{0} esch de Bibliothek dezuegfüegt worde",
-    "ItemRemovedWithName": "{0} esch vo de Bibliothek entfärnt worde",
-    "LabelIpAddressValue": "IP-Adrässe: {0}",
-    "LabelRunningTimeValue": "Loufziit: {0}",
-    "Latest": "Nöischti",
-    "MessageApplicationUpdated": "Jellyfin Server esch aktualisiert worde",
-    "MessageApplicationUpdatedTo": "Jellyfin Server esch of Version {0} aktualisiert worde",
-    "MessageNamedServerConfigurationUpdatedWithValue": "De Serveriistöuigsberiich {0} esch aktualisiert worde",
+    "HeaderLiveTV": "Live-Fernseh",
+    "HeaderNextUp": "Als Nächstes",
+    "HeaderRecordingGroups": "Aufnahme-Gruppen",
+    "HomeVideos": "Heimvideos",
+    "Inherit": "Vererben",
+    "ItemAddedWithName": "{0} wurde der Bibliothek hinzugefügt",
+    "ItemRemovedWithName": "{0} wurde aus der Bibliothek entfernt",
+    "LabelIpAddressValue": "IP-Adresse: {0}",
+    "LabelRunningTimeValue": "Laufzeit: {0}",
+    "Latest": "Neueste",
+    "MessageApplicationUpdated": "Jellyfin-Server wurde aktualisiert",
+    "MessageApplicationUpdatedTo": "Jellyfin-Server wurde auf Version {0} aktualisiert",
+    "MessageNamedServerConfigurationUpdatedWithValue": "Der Server-Einstellungsbereich {0} wurde aktualisiert",
     "MessageServerConfigurationUpdated": "Serveriistöuige send aktualisiert worde",
     "MessageServerConfigurationUpdated": "Serveriistöuige send aktualisiert worde",
     "MixedContent": "Gmeschti Inhäut",
     "MixedContent": "Gmeschti Inhäut",
     "Movies": "Film",
     "Movies": "Film",
@@ -50,7 +50,7 @@
     "NotificationOptionAudioPlayback": "Audiowedergab gstartet",
     "NotificationOptionAudioPlayback": "Audiowedergab gstartet",
     "NotificationOptionAudioPlaybackStopped": "Audiwedergab gstoppt",
     "NotificationOptionAudioPlaybackStopped": "Audiwedergab gstoppt",
     "NotificationOptionCameraImageUploaded": "Foti ueglade",
     "NotificationOptionCameraImageUploaded": "Foti ueglade",
-    "NotificationOptionInstallationFailed": "Installationsfäuer",
+    "NotificationOptionInstallationFailed": "Installationsfehler",
     "NotificationOptionNewLibraryContent": "Nöie Inhaut hinzuegfüegt",
     "NotificationOptionNewLibraryContent": "Nöie Inhaut hinzuegfüegt",
     "NotificationOptionPluginError": "Plugin-Fäuer",
     "NotificationOptionPluginError": "Plugin-Fäuer",
     "NotificationOptionPluginInstalled": "Plugin installiert",
     "NotificationOptionPluginInstalled": "Plugin installiert",
@@ -92,5 +92,16 @@
     "UserStoppedPlayingItemWithValues": "{0} het d'Wedergab vo {1} of {2} gstoppt",
     "UserStoppedPlayingItemWithValues": "{0} het d'Wedergab vo {1} of {2} gstoppt",
     "ValueHasBeenAddedToLibrary": "{0} esch dinnere Biblithek hinzuegfüegt worde",
     "ValueHasBeenAddedToLibrary": "{0} esch dinnere Biblithek hinzuegfüegt worde",
     "ValueSpecialEpisodeName": "Extra - {0}",
     "ValueSpecialEpisodeName": "Extra - {0}",
-    "VersionNumber": "Version {0}"
+    "VersionNumber": "Version {0}",
+    "TaskCleanLogs": "Lösche Log Pfad",
+    "TaskRefreshLibraryDescription": "Scanne alle Bibliotheken für hinzugefügte Datein und erneuere Metadaten.",
+    "TaskRefreshLibrary": "Scanne alle Bibliotheken",
+    "TaskRefreshChapterImagesDescription": "Kreiert Vorschaubilder für Videos welche Kapitel haben.",
+    "TaskRefreshChapterImages": "Extrahiere Kapitel-Bilder",
+    "TaskCleanCacheDescription": "Löscht Zwischenspeicherdatein die nicht länger von System gebraucht werden.",
+    "TaskCleanCache": "Leere Cache Pfad",
+    "TasksChannelsCategory": "Internet Kanäle",
+    "TasksApplicationCategory": "Applikation",
+    "TasksLibraryCategory": "Bibliothek",
+    "TasksMaintenanceCategory": "Verwaltung"
 }
 }

+ 1 - 1
Emby.Server.Implementations/Localization/Core/he.json

@@ -62,7 +62,7 @@
     "NotificationOptionVideoPlayback": "Video playback started",
     "NotificationOptionVideoPlayback": "Video playback started",
     "NotificationOptionVideoPlaybackStopped": "Video playback stopped",
     "NotificationOptionVideoPlaybackStopped": "Video playback stopped",
     "Photos": "תמונות",
     "Photos": "תמונות",
-    "Playlists": "רשימות ניגון",
+    "Playlists": "רשימות הפעלה",
     "Plugin": "Plugin",
     "Plugin": "Plugin",
     "PluginInstalledWithName": "{0} was installed",
     "PluginInstalledWithName": "{0} was installed",
     "PluginUninstalledWithName": "{0} was uninstalled",
     "PluginUninstalledWithName": "{0} was uninstalled",

+ 10 - 2
Emby.Server.Implementations/Localization/Core/hr.json

@@ -30,7 +30,7 @@
     "Inherit": "Naslijedi",
     "Inherit": "Naslijedi",
     "ItemAddedWithName": "{0} je dodano u biblioteku",
     "ItemAddedWithName": "{0} je dodano u biblioteku",
     "ItemRemovedWithName": "{0} je uklonjen iz biblioteke",
     "ItemRemovedWithName": "{0} je uklonjen iz biblioteke",
-    "LabelIpAddressValue": "Ip adresa: {0}",
+    "LabelIpAddressValue": "IP adresa: {0}",
     "LabelRunningTimeValue": "Vrijeme rada: {0}",
     "LabelRunningTimeValue": "Vrijeme rada: {0}",
     "Latest": "Najnovije",
     "Latest": "Najnovije",
     "MessageApplicationUpdated": "Jellyfin Server je ažuriran",
     "MessageApplicationUpdated": "Jellyfin Server je ažuriran",
@@ -92,5 +92,13 @@
     "UserStoppedPlayingItemWithValues": "{0} je zaustavio {1}",
     "UserStoppedPlayingItemWithValues": "{0} je zaustavio {1}",
     "ValueHasBeenAddedToLibrary": "{0} has been added to your media library",
     "ValueHasBeenAddedToLibrary": "{0} has been added to your media library",
     "ValueSpecialEpisodeName": "Specijal - {0}",
     "ValueSpecialEpisodeName": "Specijal - {0}",
-    "VersionNumber": "Verzija {0}"
+    "VersionNumber": "Verzija {0}",
+    "TaskRefreshLibraryDescription": "Skenira vašu medijsku knjižnicu sa novim datotekama i osvježuje metapodatke.",
+    "TaskRefreshLibrary": "Skeniraj medijsku knjižnicu",
+    "TaskRefreshChapterImagesDescription": "Stvara sličice za videozapise koji imaju poglavlja.",
+    "TaskRefreshChapterImages": "Raspakiraj slike poglavlja",
+    "TaskCleanCacheDescription": "Briše priručne datoteke nepotrebne za sistem.",
+    "TaskCleanCache": "Očisti priručnu memoriju",
+    "TasksApplicationCategory": "Aplikacija",
+    "TasksMaintenanceCategory": "Održavanje"
 }
 }

+ 8 - 1
Emby.Server.Implementations/Localization/Core/mk.json

@@ -91,5 +91,12 @@
     "Songs": "Песни",
     "Songs": "Песни",
     "Shows": "Серии",
     "Shows": "Серии",
     "ServerNameNeedsToBeRestarted": "{0} треба да се рестартира",
     "ServerNameNeedsToBeRestarted": "{0} треба да се рестартира",
-    "ScheduledTaskStartedWithName": "{0} започна"
+    "ScheduledTaskStartedWithName": "{0} започна",
+    "TaskRefreshChapterImages": "Извези Слики од Поглавје",
+    "TaskCleanCacheDescription": "Ги брише кешираните фајлови што не се повеќе потребни од системот.",
+    "TaskCleanCache": "Исчисти Го Кешот",
+    "TasksChannelsCategory": "Интернет Канали",
+    "TasksApplicationCategory": "Апликација",
+    "TasksLibraryCategory": "Библиотека",
+    "TasksMaintenanceCategory": "Одржување"
 }
 }

+ 3 - 3
Emby.Server.Implementations/Localization/Core/nl.json

@@ -5,7 +5,7 @@
     "Artists": "Artiesten",
     "Artists": "Artiesten",
     "AuthenticationSucceededWithUserName": "{0} is succesvol geverifieerd",
     "AuthenticationSucceededWithUserName": "{0} is succesvol geverifieerd",
     "Books": "Boeken",
     "Books": "Boeken",
-    "CameraImageUploadedFrom": "Er is een nieuwe afbeelding toegevoegd via {0}",
+    "CameraImageUploadedFrom": "Er is een nieuwe camera afbeelding toegevoegd via {0}",
     "Channels": "Kanalen",
     "Channels": "Kanalen",
     "ChapterNameValue": "Hoofdstuk {0}",
     "ChapterNameValue": "Hoofdstuk {0}",
     "Collections": "Verzamelingen",
     "Collections": "Verzamelingen",
@@ -26,7 +26,7 @@
     "HeaderLiveTV": "Live TV",
     "HeaderLiveTV": "Live TV",
     "HeaderNextUp": "Volgende",
     "HeaderNextUp": "Volgende",
     "HeaderRecordingGroups": "Opnamegroepen",
     "HeaderRecordingGroups": "Opnamegroepen",
-    "HomeVideos": "Start video's",
+    "HomeVideos": "Home video's",
     "Inherit": "Overerven",
     "Inherit": "Overerven",
     "ItemAddedWithName": "{0} is toegevoegd aan de bibliotheek",
     "ItemAddedWithName": "{0} is toegevoegd aan de bibliotheek",
     "ItemRemovedWithName": "{0} is verwijderd uit de bibliotheek",
     "ItemRemovedWithName": "{0} is verwijderd uit de bibliotheek",
@@ -50,7 +50,7 @@
     "NotificationOptionAudioPlayback": "Muziek gestart",
     "NotificationOptionAudioPlayback": "Muziek gestart",
     "NotificationOptionAudioPlaybackStopped": "Muziek gestopt",
     "NotificationOptionAudioPlaybackStopped": "Muziek gestopt",
     "NotificationOptionCameraImageUploaded": "Camera-afbeelding geüpload",
     "NotificationOptionCameraImageUploaded": "Camera-afbeelding geüpload",
-    "NotificationOptionInstallationFailed": "Installatie mislukking",
+    "NotificationOptionInstallationFailed": "Installatie mislukt",
     "NotificationOptionNewLibraryContent": "Nieuwe content toegevoegd",
     "NotificationOptionNewLibraryContent": "Nieuwe content toegevoegd",
     "NotificationOptionPluginError": "Plug-in fout",
     "NotificationOptionPluginError": "Plug-in fout",
     "NotificationOptionPluginInstalled": "Plug-in geïnstalleerd",
     "NotificationOptionPluginInstalled": "Plug-in geïnstalleerd",

+ 23 - 1
Emby.Server.Implementations/Localization/Core/pl.json

@@ -92,5 +92,27 @@
     "UserStoppedPlayingItemWithValues": "{0} zakończył odtwarzanie {1} na {2}",
     "UserStoppedPlayingItemWithValues": "{0} zakończył odtwarzanie {1} na {2}",
     "ValueHasBeenAddedToLibrary": "{0} został dodany do biblioteki mediów",
     "ValueHasBeenAddedToLibrary": "{0} został dodany do biblioteki mediów",
     "ValueSpecialEpisodeName": "Specjalne - {0}",
     "ValueSpecialEpisodeName": "Specjalne - {0}",
-    "VersionNumber": "Wersja {0}"
+    "VersionNumber": "Wersja {0}",
+    "TaskDownloadMissingSubtitlesDescription": "Przeszukuje internet w poszukiwaniu brakujących napisów w oparciu o konfigurację metadanych.",
+    "TaskDownloadMissingSubtitles": "Pobierz brakujące napisy",
+    "TaskRefreshChannelsDescription": "Odświeża informacje o kanałach internetowych.",
+    "TaskRefreshChannels": "Odśwież kanały",
+    "TaskCleanTranscodeDescription": "Usuwa transkodowane pliki starsze niż 1 dzień.",
+    "TaskCleanTranscode": "Wyczyść folder transkodowania",
+    "TaskUpdatePluginsDescription": "Pobiera i instaluje aktualizacje dla pluginów które są skonfigurowane do automatycznej aktualizacji.",
+    "TaskUpdatePlugins": "Aktualizuj pluginy",
+    "TaskRefreshPeopleDescription": "Odświeża metadane o aktorów i reżyserów w Twojej bibliotece mediów.",
+    "TaskRefreshPeople": "Odśwież obsadę",
+    "TaskCleanLogsDescription": "Kasuje pliki logów starsze niż {0} dni.",
+    "TaskCleanLogs": "Wyczyść folder logów",
+    "TaskRefreshLibraryDescription": "Skanuje Twoją bibliotekę mediów dla nowych plików i odświeżenia metadanych.",
+    "TaskRefreshLibrary": "Skanuj bibliotekę mediów",
+    "TaskRefreshChapterImagesDescription": "Tworzy miniatury dla filmów posiadających rozdziały.",
+    "TaskRefreshChapterImages": "Wydobądź grafiki rozdziałów",
+    "TaskCleanCacheDescription": "Usuwa niepotrzebne i przestarzałe pliki cache.",
+    "TaskCleanCache": "Wyczyść folder Cache",
+    "TasksChannelsCategory": "Kanały internetowe",
+    "TasksApplicationCategory": "Aplikacja",
+    "TasksLibraryCategory": "Biblioteka",
+    "TasksMaintenanceCategory": "Konserwacja"
 }
 }

+ 22 - 1
Emby.Server.Implementations/Localization/Core/sl-SI.json

@@ -92,5 +92,26 @@
     "UserStoppedPlayingItemWithValues": "{0} je nehal predvajati {1} na {2}",
     "UserStoppedPlayingItemWithValues": "{0} je nehal predvajati {1} na {2}",
     "ValueHasBeenAddedToLibrary": "{0} je bil dodan vaši knjižnici",
     "ValueHasBeenAddedToLibrary": "{0} je bil dodan vaši knjižnici",
     "ValueSpecialEpisodeName": "Poseben - {0}",
     "ValueSpecialEpisodeName": "Poseben - {0}",
-    "VersionNumber": "Različica {0}"
+    "VersionNumber": "Različica {0}",
+    "TaskDownloadMissingSubtitles": "Prenesi manjkajoče podnapise",
+    "TaskRefreshChannelsDescription": "Osveži podatke spletnih kanalov.",
+    "TaskRefreshChannels": "Osveži kanale",
+    "TaskCleanTranscodeDescription": "Izbriše več kot dan stare datoteke prekodiranja.",
+    "TaskCleanTranscode": "Počisti mapo prekodiranja",
+    "TaskUpdatePluginsDescription": "Prenese in namesti posodobitve za dodatke, ki imajo omogočene samodejne posodobitve.",
+    "TaskUpdatePlugins": "Posodobi dodatke",
+    "TaskRefreshPeopleDescription": "Osveži metapodatke za igralce in režiserje v vaši knjižnici.",
+    "TaskRefreshPeople": "Osveži osebe",
+    "TaskCleanLogsDescription": "Izbriše dnevniške datoteke starejše od {0} dni.",
+    "TaskCleanLogs": "Počisti mapo dnevnika",
+    "TaskRefreshLibraryDescription": "Preišče vašo knjižnico za nove datoteke in osveži metapodatke.",
+    "TaskRefreshLibrary": "Preišči knjižnico predstavnosti",
+    "TaskRefreshChapterImagesDescription": "Ustvari sličice za poglavja videoposnetkov.",
+    "TaskRefreshChapterImages": "Izvleči slike poglavij",
+    "TaskCleanCacheDescription": "Izbriše predpomnjene datoteke, ki niso več potrebne.",
+    "TaskCleanCache": "Počisti mapo predpomnilnika",
+    "TasksChannelsCategory": "Spletni kanali",
+    "TasksApplicationCategory": "Aplikacija",
+    "TasksLibraryCategory": "Knjižnica",
+    "TasksMaintenanceCategory": "Vzdrževanje"
 }
 }

+ 4 - 3
Emby.Server.Implementations/Localization/Core/sv.json

@@ -9,7 +9,7 @@
     "Channels": "Kanaler",
     "Channels": "Kanaler",
     "ChapterNameValue": "Kapitel {0}",
     "ChapterNameValue": "Kapitel {0}",
     "Collections": "Samlingar",
     "Collections": "Samlingar",
-    "DeviceOfflineWithName": "{0} har tappat anslutningen",
+    "DeviceOfflineWithName": "{0} har kopplat från",
     "DeviceOnlineWithName": "{0} är ansluten",
     "DeviceOnlineWithName": "{0} är ansluten",
     "FailedLoginAttemptWithUserName": "Misslyckat inloggningsförsök från {0}",
     "FailedLoginAttemptWithUserName": "Misslyckat inloggningsförsök från {0}",
     "Favorites": "Favoriter",
     "Favorites": "Favoriter",
@@ -50,7 +50,7 @@
     "NotificationOptionAudioPlayback": "Ljuduppspelning har påbörjats",
     "NotificationOptionAudioPlayback": "Ljuduppspelning har påbörjats",
     "NotificationOptionAudioPlaybackStopped": "Ljuduppspelning stoppades",
     "NotificationOptionAudioPlaybackStopped": "Ljuduppspelning stoppades",
     "NotificationOptionCameraImageUploaded": "Kamerabild har laddats upp",
     "NotificationOptionCameraImageUploaded": "Kamerabild har laddats upp",
-    "NotificationOptionInstallationFailed": "Fel vid installation",
+    "NotificationOptionInstallationFailed": "Installationen misslyckades",
     "NotificationOptionNewLibraryContent": "Nytt innehåll har lagts till",
     "NotificationOptionNewLibraryContent": "Nytt innehåll har lagts till",
     "NotificationOptionPluginError": "Fel uppstod med tillägget",
     "NotificationOptionPluginError": "Fel uppstod med tillägget",
     "NotificationOptionPluginInstalled": "Tillägg har installerats",
     "NotificationOptionPluginInstalled": "Tillägg har installerats",
@@ -113,5 +113,6 @@
     "TasksChannelsCategory": "Internetkanaler",
     "TasksChannelsCategory": "Internetkanaler",
     "TasksApplicationCategory": "Applikation",
     "TasksApplicationCategory": "Applikation",
     "TasksLibraryCategory": "Bibliotek",
     "TasksLibraryCategory": "Bibliotek",
-    "TasksMaintenanceCategory": "Underhåll"
+    "TasksMaintenanceCategory": "Underhåll",
+    "TaskRefreshPeople": "Uppdatera Personer"
 }
 }

+ 36 - 0
Emby.Server.Implementations/Localization/Core/uk.json

@@ -0,0 +1,36 @@
+{
+    "MusicVideos": "Музичні відео",
+    "Music": "Музика",
+    "Movies": "Фільми",
+    "MessageApplicationUpdatedTo": "Jellyfin Server був оновлений до версії {0}",
+    "MessageApplicationUpdated": "Jellyfin Server був оновлений",
+    "Latest": "Останні",
+    "LabelIpAddressValue": "IP-адреси: {0}",
+    "ItemRemovedWithName": "{0} видалено з бібліотеки",
+    "ItemAddedWithName": "{0} додано до бібліотеки",
+    "HeaderNextUp": "Наступний",
+    "HeaderLiveTV": "Ефірне ТБ",
+    "HeaderFavoriteSongs": "Улюблені пісні",
+    "HeaderFavoriteShows": "Улюблені шоу",
+    "HeaderFavoriteEpisodes": "Улюблені серії",
+    "HeaderFavoriteArtists": "Улюблені виконавці",
+    "HeaderFavoriteAlbums": "Улюблені альбоми",
+    "HeaderContinueWatching": "Продовжити перегляд",
+    "HeaderCameraUploads": "Завантажено з камери",
+    "HeaderAlbumArtists": "Виконавці альбомів",
+    "Genres": "Жанри",
+    "Folders": "Директорії",
+    "Favorites": "Улюблені",
+    "DeviceOnlineWithName": "{0} під'єднано",
+    "DeviceOfflineWithName": "{0} від'єднано",
+    "Collections": "Колекції",
+    "ChapterNameValue": "Глава {0}",
+    "Channels": "Канали",
+    "CameraImageUploadedFrom": "Нова фотографія завантажена з {0}",
+    "Books": "Книги",
+    "AuthenticationSucceededWithUserName": "{0} успішно авторизовані",
+    "Artists": "Виконавці",
+    "Application": "Додаток",
+    "AppDeviceValues": "Додаток: {0}, Пристрій: {1}",
+    "Albums": "Альбоми"
+}

+ 5 - 2
Emby.Server.Implementations/Localization/Core/zh-HK.json

@@ -1,6 +1,6 @@
 {
 {
     "Albums": "專輯",
     "Albums": "專輯",
-    "AppDeviceValues": "軟: {0}, 設備: {1}",
+    "AppDeviceValues": "軟: {0}, 設備: {1}",
     "Application": "應用程式",
     "Application": "應用程式",
     "Artists": "藝人",
     "Artists": "藝人",
     "AuthenticationSucceededWithUserName": "{0} 授權成功",
     "AuthenticationSucceededWithUserName": "{0} 授權成功",
@@ -92,5 +92,8 @@
     "UserStoppedPlayingItemWithValues": "{0} 已在 {2} 上停止播放 {1}",
     "UserStoppedPlayingItemWithValues": "{0} 已在 {2} 上停止播放 {1}",
     "ValueHasBeenAddedToLibrary": "{0} 已添加到你的媒體庫",
     "ValueHasBeenAddedToLibrary": "{0} 已添加到你的媒體庫",
     "ValueSpecialEpisodeName": "特典 - {0}",
     "ValueSpecialEpisodeName": "特典 - {0}",
-    "VersionNumber": "版本{0}"
+    "VersionNumber": "版本{0}",
+    "TaskDownloadMissingSubtitles": "下載遺失的字幕",
+    "TaskUpdatePlugins": "更新插件",
+    "TasksApplicationCategory": "應用程式"
 }
 }

+ 2 - 14
Emby.Server.Implementations/Services/StringMapTypeDeserializer.cs

@@ -1,6 +1,7 @@
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.Reflection;
 using System.Reflection;
+using MediaBrowser.Common.Extensions;
 
 
 namespace Emby.Server.Implementations.Services
 namespace Emby.Server.Implementations.Services
 {
 {
@@ -81,7 +82,7 @@ namespace Emby.Server.Implementations.Services
                 if (propertySerializerEntry.PropertyType == typeof(bool))
                 if (propertySerializerEntry.PropertyType == typeof(bool))
                 {
                 {
                     //InputExtensions.cs#530 MVC Checkbox helper emits extra hidden input field, generating 2 values, first is the real value
                     //InputExtensions.cs#530 MVC Checkbox helper emits extra hidden input field, generating 2 values, first is the real value
-                    propertyTextValue = LeftPart(propertyTextValue, ',');
+                    propertyTextValue = StringExtensions.LeftPart(propertyTextValue, ',').ToString();
                 }
                 }
 
 
                 var value = propertySerializerEntry.PropertyParseStringFn(propertyTextValue);
                 var value = propertySerializerEntry.PropertyParseStringFn(propertyTextValue);
@@ -95,19 +96,6 @@ namespace Emby.Server.Implementations.Services
 
 
             return instance;
             return instance;
         }
         }
-
-        public static string LeftPart(string strVal, char needle)
-        {
-            if (strVal == null)
-            {
-                return null;
-            }
-
-            var pos = strVal.IndexOf(needle);
-            return pos == -1
-                ? strVal
-                : strVal.Substring(0, pos);
-        }
     }
     }
 
 
     internal static class TypeAccessor
     internal static class TypeAccessor

+ 4 - 16
Emby.Server.Implementations/Services/UrlExtensions.cs

@@ -1,4 +1,5 @@
 using System;
 using System;
+using MediaBrowser.Common.Extensions;
 
 
 namespace Emby.Server.Implementations.Services
 namespace Emby.Server.Implementations.Services
 {
 {
@@ -13,25 +14,12 @@ namespace Emby.Server.Implementations.Services
         public static string GetMethodName(this Type type)
         public static string GetMethodName(this Type type)
         {
         {
             var typeName = type.FullName != null // can be null, e.g. generic types
             var typeName = type.FullName != null // can be null, e.g. generic types
-                ? LeftPart(type.FullName, "[[")   // Generic Fullname
-                    .Replace(type.Namespace + ".", string.Empty) // Trim Namespaces
-                    .Replace("+", ".") // Convert nested into normal type
+                ? StringExtensions.LeftPart(type.FullName, "[[", StringComparison.Ordinal).ToString() // Generic Fullname
+                    .Replace(type.Namespace + ".", string.Empty, StringComparison.Ordinal) // Trim Namespaces
+                    .Replace("+", ".", StringComparison.Ordinal) // Convert nested into normal type
                 : type.Name;
                 : type.Name;
 
 
             return type.IsGenericParameter ? "'" + typeName : typeName;
             return type.IsGenericParameter ? "'" + typeName : typeName;
         }
         }
-
-        private static string LeftPart(string strVal, string needle)
-        {
-            if (strVal == null)
-            {
-                return null;
-            }
-
-            var pos = strVal.IndexOf(needle, StringComparison.OrdinalIgnoreCase);
-            return pos == -1
-                ? strVal
-                : strVal.Substring(0, pos);
-        }
     }
     }
 }
 }

+ 10 - 14
Emby.Server.Implementations/SocketSharp/WebSocketSharpRequest.cs

@@ -3,6 +3,7 @@ using System.Collections.Generic;
 using System.IO;
 using System.IO;
 using System.Net;
 using System.Net;
 using System.Net.Mime;
 using System.Net.Mime;
+using MediaBrowser.Common.Extensions;
 using MediaBrowser.Common.Net;
 using MediaBrowser.Common.Net;
 using Microsoft.AspNetCore.Http;
 using Microsoft.AspNetCore.Http;
 using Microsoft.AspNetCore.Http.Extensions;
 using Microsoft.AspNetCore.Http.Extensions;
@@ -62,6 +63,9 @@ namespace Emby.Server.Implementations.SocketSharp
                     if (!IPAddress.TryParse(GetHeader(CustomHeaderNames.XRealIP), out ip))
                     if (!IPAddress.TryParse(GetHeader(CustomHeaderNames.XRealIP), out ip))
                     {
                     {
                         ip = Request.HttpContext.Connection.RemoteIpAddress;
                         ip = Request.HttpContext.Connection.RemoteIpAddress;
+
+                        // Default to the loopback address if no RemoteIpAddress is specified (i.e. during integration tests)
+                        ip ??= IPAddress.Loopback;
                     }
                     }
                 }
                 }
 
 
@@ -89,7 +93,10 @@ namespace Emby.Server.Implementations.SocketSharp
 
 
         public IQueryCollection QueryString => Request.Query;
         public IQueryCollection QueryString => Request.Query;
 
 
-        public bool IsLocal => Request.HttpContext.Connection.LocalIpAddress.Equals(Request.HttpContext.Connection.RemoteIpAddress);
+        public bool IsLocal =>
+            (Request.HttpContext.Connection.LocalIpAddress == null
+            && Request.HttpContext.Connection.RemoteIpAddress == null)
+            || Request.HttpContext.Connection.LocalIpAddress.Equals(Request.HttpContext.Connection.RemoteIpAddress);
 
 
         public string HttpMethod => Request.Method;
         public string HttpMethod => Request.Method;
 
 
@@ -216,14 +223,14 @@ namespace Emby.Server.Implementations.SocketSharp
                     pi = pi.Slice(1);
                     pi = pi.Slice(1);
                 }
                 }
 
 
-                format = LeftPart(pi, '/');
+                format = pi.LeftPart('/');
                 if (format.Length > FormatMaxLength)
                 if (format.Length > FormatMaxLength)
                 {
                 {
                     return null;
                     return null;
                 }
                 }
             }
             }
 
 
-            format = LeftPart(format, '.');
+            format = format.LeftPart('.');
             if (format.Contains("json", StringComparison.OrdinalIgnoreCase))
             if (format.Contains("json", StringComparison.OrdinalIgnoreCase))
             {
             {
                 return "application/json";
                 return "application/json";
@@ -235,16 +242,5 @@ namespace Emby.Server.Implementations.SocketSharp
 
 
             return null;
             return null;
         }
         }
-
-        public static ReadOnlySpan<char> LeftPart(ReadOnlySpan<char> strVal, char needle)
-        {
-            if (strVal == null)
-            {
-                return null;
-            }
-
-            var pos = strVal.IndexOf(needle);
-            return pos == -1 ? strVal : strVal.Slice(0, pos);
-        }
     }
     }
 }
 }

+ 1140 - 0
Jellyfin.Data/DbContexts/Jellyfin.cs

@@ -0,0 +1,1140 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated from a template.
+//
+//     Manual changes to this file may cause unexpected behavior in your application.
+//     Manual changes to this file will be overwritten if the code is regenerated.
+//
+//     Produced by Entity Framework Visual Editor
+//     https://github.com/msawczyn/EFDesigner
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.ComponentModel.DataAnnotations.Schema;
+using Microsoft.EntityFrameworkCore;
+
+namespace Jellyfin.Data.DbContexts
+{
+   /// <inheritdoc/>
+   public partial class Jellyfin : DbContext
+   {
+      #region DbSets
+      public virtual Microsoft.EntityFrameworkCore.DbSet<global::Jellyfin.Data.Entities.Artwork> Artwork { get; set; }
+      public virtual Microsoft.EntityFrameworkCore.DbSet<global::Jellyfin.Data.Entities.Book> Books { get; set; }
+      public virtual Microsoft.EntityFrameworkCore.DbSet<global::Jellyfin.Data.Entities.BookMetadata> BookMetadata { get; set; }
+      public virtual Microsoft.EntityFrameworkCore.DbSet<global::Jellyfin.Data.Entities.Chapter> Chapters { get; set; }
+      public virtual Microsoft.EntityFrameworkCore.DbSet<global::Jellyfin.Data.Entities.Collection> Collections { get; set; }
+      public virtual Microsoft.EntityFrameworkCore.DbSet<global::Jellyfin.Data.Entities.CollectionItem> CollectionItems { get; set; }
+      public virtual Microsoft.EntityFrameworkCore.DbSet<global::Jellyfin.Data.Entities.Company> Companies { get; set; }
+      public virtual Microsoft.EntityFrameworkCore.DbSet<global::Jellyfin.Data.Entities.CompanyMetadata> CompanyMetadata { get; set; }
+      public virtual Microsoft.EntityFrameworkCore.DbSet<global::Jellyfin.Data.Entities.CustomItem> CustomItems { get; set; }
+      public virtual Microsoft.EntityFrameworkCore.DbSet<global::Jellyfin.Data.Entities.CustomItemMetadata> CustomItemMetadata { get; set; }
+      public virtual Microsoft.EntityFrameworkCore.DbSet<global::Jellyfin.Data.Entities.Episode> Episodes { get; set; }
+      public virtual Microsoft.EntityFrameworkCore.DbSet<global::Jellyfin.Data.Entities.EpisodeMetadata> EpisodeMetadata { get; set; }
+      public virtual Microsoft.EntityFrameworkCore.DbSet<global::Jellyfin.Data.Entities.Genre> Genres { get; set; }
+      public virtual Microsoft.EntityFrameworkCore.DbSet<global::Jellyfin.Data.Entities.Group> Groups { get; set; }
+      public virtual Microsoft.EntityFrameworkCore.DbSet<global::Jellyfin.Data.Entities.Library> Libraries { get; set; }
+      public virtual Microsoft.EntityFrameworkCore.DbSet<global::Jellyfin.Data.Entities.LibraryItem> LibraryItems { get; set; }
+      public virtual Microsoft.EntityFrameworkCore.DbSet<global::Jellyfin.Data.Entities.LibraryRoot> LibraryRoot { get; set; }
+      public virtual Microsoft.EntityFrameworkCore.DbSet<global::Jellyfin.Data.Entities.MediaFile> MediaFiles { get; set; }
+      public virtual Microsoft.EntityFrameworkCore.DbSet<global::Jellyfin.Data.Entities.MediaFileStream> MediaFileStream { get; set; }
+      public virtual Microsoft.EntityFrameworkCore.DbSet<global::Jellyfin.Data.Entities.Metadata> Metadata { get; set; }
+      public virtual Microsoft.EntityFrameworkCore.DbSet<global::Jellyfin.Data.Entities.MetadataProvider> MetadataProviders { get; set; }
+      public virtual Microsoft.EntityFrameworkCore.DbSet<global::Jellyfin.Data.Entities.MetadataProviderId> MetadataProviderIds { get; set; }
+      public virtual Microsoft.EntityFrameworkCore.DbSet<global::Jellyfin.Data.Entities.Movie> Movies { get; set; }
+      public virtual Microsoft.EntityFrameworkCore.DbSet<global::Jellyfin.Data.Entities.MovieMetadata> MovieMetadata { get; set; }
+      public virtual Microsoft.EntityFrameworkCore.DbSet<global::Jellyfin.Data.Entities.MusicAlbum> MusicAlbums { get; set; }
+      public virtual Microsoft.EntityFrameworkCore.DbSet<global::Jellyfin.Data.Entities.MusicAlbumMetadata> MusicAlbumMetadata { get; set; }
+      public virtual Microsoft.EntityFrameworkCore.DbSet<global::Jellyfin.Data.Entities.Permission> Permissions { get; set; }
+      public virtual Microsoft.EntityFrameworkCore.DbSet<global::Jellyfin.Data.Entities.Person> People { get; set; }
+      public virtual Microsoft.EntityFrameworkCore.DbSet<global::Jellyfin.Data.Entities.PersonRole> PersonRoles { get; set; }
+      public virtual Microsoft.EntityFrameworkCore.DbSet<global::Jellyfin.Data.Entities.Photo> Photo { get; set; }
+      public virtual Microsoft.EntityFrameworkCore.DbSet<global::Jellyfin.Data.Entities.PhotoMetadata> PhotoMetadata { get; set; }
+      public virtual Microsoft.EntityFrameworkCore.DbSet<global::Jellyfin.Data.Entities.Preference> Preferences { get; set; }
+      public virtual Microsoft.EntityFrameworkCore.DbSet<global::Jellyfin.Data.Entities.ProviderMapping> ProviderMappings { get; set; }
+      public virtual Microsoft.EntityFrameworkCore.DbSet<global::Jellyfin.Data.Entities.Rating> Ratings { get; set; }
+
+      /// <summary>
+      /// Repository for global::Jellyfin.Data.Entities.RatingSource - This is the entity to
+      /// store review ratings, not age ratings
+      /// </summary>
+      public virtual Microsoft.EntityFrameworkCore.DbSet<global::Jellyfin.Data.Entities.RatingSource> RatingSources { get; set; }
+      public virtual Microsoft.EntityFrameworkCore.DbSet<global::Jellyfin.Data.Entities.Release> Releases { get; set; }
+      public virtual Microsoft.EntityFrameworkCore.DbSet<global::Jellyfin.Data.Entities.Season> Seasons { get; set; }
+      public virtual Microsoft.EntityFrameworkCore.DbSet<global::Jellyfin.Data.Entities.SeasonMetadata> SeasonMetadata { get; set; }
+      public virtual Microsoft.EntityFrameworkCore.DbSet<global::Jellyfin.Data.Entities.Series> Series { get; set; }
+      public virtual Microsoft.EntityFrameworkCore.DbSet<global::Jellyfin.Data.Entities.SeriesMetadata> SeriesMetadata { get; set; }
+      public virtual Microsoft.EntityFrameworkCore.DbSet<global::Jellyfin.Data.Entities.Track> Tracks { get; set; }
+      public virtual Microsoft.EntityFrameworkCore.DbSet<global::Jellyfin.Data.Entities.TrackMetadata> TrackMetadata { get; set; }
+      public virtual Microsoft.EntityFrameworkCore.DbSet<global::Jellyfin.Data.Entities.User> Users { get; set; }
+      #endregion DbSets
+
+      /// <summary>
+      /// Default connection string
+      /// </summary>
+      public static string ConnectionString { get; set; } = @"Data Source=jellyfin.db";
+
+      /// <inheritdoc />
+      public Jellyfin(DbContextOptions<Jellyfin> options) : base(options)
+      {
+      }
+
+      partial void CustomInit(DbContextOptionsBuilder optionsBuilder);
+
+      /// <inheritdoc />
+      protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
+      {
+         CustomInit(optionsBuilder);
+      }
+
+      partial void OnModelCreatingImpl(ModelBuilder modelBuilder);
+      partial void OnModelCreatedImpl(ModelBuilder modelBuilder);
+
+      /// <inheritdoc />
+      protected override void OnModelCreating(ModelBuilder modelBuilder)
+      {
+         base.OnModelCreating(modelBuilder);
+         OnModelCreatingImpl(modelBuilder);
+
+         modelBuilder.HasDefaultSchema("jellyfin");
+
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Artwork>()
+                     .ToTable("Artwork")
+                     .HasKey(t => t.Id);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Artwork>()
+                     .Property(t => t.Id)
+                     .IsRequired()
+                     .HasField("_Id")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property)
+                     .ValueGeneratedOnAdd();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Artwork>()
+                     .Property(t => t.Path)
+                     .HasMaxLength(65535)
+                     .IsRequired()
+                     .HasField("_Path")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Artwork>()
+                     .Property(t => t.Kind)
+                     .IsRequired()
+                     .HasField("_Kind")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Artwork>().HasIndex(t => t.Kind);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Artwork>()
+                     .Property(t => t.Timestamp)
+                     .IsRequired()
+                     .HasField("_Timestamp")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property)
+                     .IsRowVersion();
+
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Book>()
+                     .HasMany(x => x.BookMetadata)
+                     .WithOne()
+                     .HasForeignKey("BookMetadata_BookMetadata_Id")
+                     .IsRequired();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Book>()
+                     .HasMany(x => x.Releases)
+                     .WithOne()
+                     .HasForeignKey("Release_Releases_Id")
+                     .IsRequired();
+
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.BookMetadata>()
+                     .Property(t => t.ISBN)
+                     .HasField("_ISBN")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.BookMetadata>()
+                     .HasMany(x => x.Publishers)
+                     .WithOne()
+                     .HasForeignKey("Company_Publishers_Id")
+                     .IsRequired();
+
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Chapter>()
+                     .ToTable("Chapter")
+                     .HasKey(t => t.Id);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Chapter>()
+                     .Property(t => t.Id)
+                     .IsRequired()
+                     .HasField("_Id")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property)
+                     .ValueGeneratedOnAdd();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Chapter>()
+                     .Property(t => t.Name)
+                     .HasMaxLength(1024)
+                     .HasField("_Name")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Chapter>()
+                     .Property(t => t.Language)
+                     .HasMaxLength(3)
+                     .IsRequired()
+                     .HasField("_Language")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Chapter>()
+                     .Property(t => t.TimeStart)
+                     .IsRequired()
+                     .HasField("_TimeStart")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Chapter>()
+                     .Property(t => t.TimeEnd)
+                     .HasField("_TimeEnd")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Chapter>()
+                     .Property(t => t.Timestamp)
+                     .IsRequired()
+                     .HasField("_Timestamp")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property)
+                     .IsRowVersion();
+
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Collection>()
+                     .ToTable("Collection")
+                     .HasKey(t => t.Id);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Collection>()
+                     .Property(t => t.Id)
+                     .IsRequired()
+                     .HasField("_Id")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property)
+                     .ValueGeneratedOnAdd();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Collection>()
+                     .Property(t => t.Name)
+                     .HasMaxLength(1024)
+                     .HasField("_Name")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Collection>()
+                     .Property(t => t.Timestamp)
+                     .IsRequired()
+                     .HasField("_Timestamp")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property)
+                     .IsRowVersion();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Collection>()
+                     .HasMany(x => x.CollectionItem)
+                     .WithOne()
+                     .HasForeignKey("CollectionItem_CollectionItem_Id")
+                     .IsRequired();
+
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.CollectionItem>()
+                     .ToTable("CollectionItem")
+                     .HasKey(t => t.Id);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.CollectionItem>()
+                     .Property(t => t.Id)
+                     .IsRequired()
+                     .HasField("_Id")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property)
+                     .ValueGeneratedOnAdd();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.CollectionItem>()
+                     .Property(t => t.Timestamp)
+                     .IsRequired()
+                     .HasField("_Timestamp")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property)
+                     .IsRowVersion();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.CollectionItem>()
+                     .HasOne(x => x.LibraryItem)
+                     .WithOne()
+                     .HasForeignKey<global::Jellyfin.Data.Entities.CollectionItem>("LibraryItem_Id")
+                     .IsRequired();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.CollectionItem>()
+                     .HasOne(x => x.Next)
+                     .WithOne()
+                     .HasForeignKey<global::Jellyfin.Data.Entities.CollectionItem>("CollectionItem_Next_Id")
+                     .IsRequired();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.CollectionItem>()
+                     .HasOne(x => x.Previous)
+                     .WithOne()
+                     .HasForeignKey<global::Jellyfin.Data.Entities.CollectionItem>("CollectionItem_Previous_Id")
+                     .IsRequired();
+
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Company>()
+                     .ToTable("Company")
+                     .HasKey(t => t.Id);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Company>()
+                     .Property(t => t.Id)
+                     .IsRequired()
+                     .HasField("_Id")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property)
+                     .ValueGeneratedOnAdd();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Company>()
+                     .Property(t => t.Timestamp)
+                     .IsRequired()
+                     .HasField("_Timestamp")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property)
+                     .IsRowVersion();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Company>()
+                     .HasMany(x => x.CompanyMetadata)
+                     .WithOne()
+                     .HasForeignKey("CompanyMetadata_CompanyMetadata_Id")
+                     .IsRequired();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Company>()
+                     .HasOne(x => x.Parent)
+                     .WithOne()
+                     .HasForeignKey<global::Jellyfin.Data.Entities.Company>("Company_Parent_Id")
+                     .IsRequired();
+
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.CompanyMetadata>()
+                     .Property(t => t.Description)
+                     .HasMaxLength(65535)
+                     .HasField("_Description")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.CompanyMetadata>()
+                     .Property(t => t.Headquarters)
+                     .HasMaxLength(255)
+                     .HasField("_Headquarters")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.CompanyMetadata>()
+                     .Property(t => t.Country)
+                     .HasMaxLength(2)
+                     .HasField("_Country")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.CompanyMetadata>()
+                     .Property(t => t.Homepage)
+                     .HasMaxLength(1024)
+                     .HasField("_Homepage")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.CustomItem>()
+                     .HasMany(x => x.CustomItemMetadata)
+                     .WithOne()
+                     .HasForeignKey("CustomItemMetadata_CustomItemMetadata_Id")
+                     .IsRequired();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.CustomItem>()
+                     .HasMany(x => x.Releases)
+                     .WithOne()
+                     .HasForeignKey("Release_Releases_Id")
+                     .IsRequired();
+
+
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Episode>()
+                     .Property(t => t.EpisodeNumber)
+                     .HasField("_EpisodeNumber")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Episode>()
+                     .HasMany(x => x.Releases)
+                     .WithOne()
+                     .HasForeignKey("Release_Releases_Id")
+                     .IsRequired();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Episode>()
+                     .HasMany(x => x.EpisodeMetadata)
+                     .WithOne()
+                     .HasForeignKey("EpisodeMetadata_EpisodeMetadata_Id")
+                     .IsRequired();
+
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.EpisodeMetadata>()
+                     .Property(t => t.Outline)
+                     .HasMaxLength(1024)
+                     .HasField("_Outline")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.EpisodeMetadata>()
+                     .Property(t => t.Plot)
+                     .HasMaxLength(65535)
+                     .HasField("_Plot")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.EpisodeMetadata>()
+                     .Property(t => t.Tagline)
+                     .HasMaxLength(1024)
+                     .HasField("_Tagline")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Genre>()
+                     .ToTable("Genre")
+                     .HasKey(t => t.Id);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Genre>()
+                     .Property(t => t.Id)
+                     .IsRequired()
+                     .HasField("_Id")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property)
+                     .ValueGeneratedOnAdd();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Genre>()
+                     .Property(t => t.Name)
+                     .HasMaxLength(255)
+                     .IsRequired()
+                     .HasField("_Name")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Genre>().HasIndex(t => t.Name)
+                     .IsUnique();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Genre>()
+                     .Property(t => t.Timestamp)
+                     .IsRequired()
+                     .HasField("_Timestamp")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property)
+                     .IsRowVersion();
+
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Group>()
+                     .ToTable("Groups")
+                     .HasKey(t => t.Id);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Group>()
+                     .Property(t => t.Id)
+                     .IsRequired()
+                     .ValueGeneratedOnAdd();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Group>()
+                     .Property(t => t.Name)
+                     .HasMaxLength(255)
+                     .IsRequired();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Group>().Property<byte[]>("Timestamp").IsConcurrencyToken();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Group>()
+                     .HasMany(x => x.GroupPermissions)
+                     .WithOne()
+                     .HasForeignKey("Permission_GroupPermissions_Id")
+                     .IsRequired();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Group>()
+                     .HasMany(x => x.ProviderMappings)
+                     .WithOne()
+                     .HasForeignKey("ProviderMapping_ProviderMappings_Id")
+                     .IsRequired();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Group>()
+                     .HasMany(x => x.Preferences)
+                     .WithOne()
+                     .HasForeignKey("Preference_Preferences_Id")
+                     .IsRequired();
+
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Library>()
+                     .ToTable("Library")
+                     .HasKey(t => t.Id);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Library>()
+                     .Property(t => t.Id)
+                     .IsRequired()
+                     .HasField("_Id")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property)
+                     .ValueGeneratedOnAdd();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Library>()
+                     .Property(t => t.Name)
+                     .HasMaxLength(1024)
+                     .IsRequired()
+                     .HasField("_Name")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Library>()
+                     .Property(t => t.Timestamp)
+                     .IsRequired()
+                     .HasField("_Timestamp")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property)
+                     .IsRowVersion();
+
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.LibraryItem>()
+                     .ToTable("LibraryItem")
+                     .HasKey(t => t.Id);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.LibraryItem>()
+                     .Property(t => t.Id)
+                     .IsRequired()
+                     .HasField("_Id")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property)
+                     .ValueGeneratedOnAdd();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.LibraryItem>()
+                     .Property(t => t.UrlId)
+                     .IsRequired()
+                     .HasField("_UrlId")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.LibraryItem>().HasIndex(t => t.UrlId)
+                     .IsUnique();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.LibraryItem>()
+                     .Property(t => t.DateAdded)
+                     .IsRequired()
+                     .HasField("_DateAdded")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.LibraryItem>()
+                     .Property(t => t.Timestamp)
+                     .IsRequired()
+                     .HasField("_Timestamp")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property)
+                     .IsRowVersion();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.LibraryItem>()
+                     .HasOne(x => x.LibraryRoot)
+                     .WithOne()
+                     .HasForeignKey<global::Jellyfin.Data.Entities.LibraryItem>("LibraryRoot_Id")
+                     .IsRequired();
+
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.LibraryRoot>()
+                     .ToTable("LibraryRoot")
+                     .HasKey(t => t.Id);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.LibraryRoot>()
+                     .Property(t => t.Id)
+                     .IsRequired()
+                     .HasField("_Id")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property)
+                     .ValueGeneratedOnAdd();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.LibraryRoot>()
+                     .Property(t => t.Path)
+                     .HasMaxLength(65535)
+                     .IsRequired()
+                     .HasField("_Path")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.LibraryRoot>()
+                     .Property(t => t.NetworkPath)
+                     .HasMaxLength(65535)
+                     .HasField("_NetworkPath")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.LibraryRoot>()
+                     .Property(t => t.Timestamp)
+                     .IsRequired()
+                     .HasField("_Timestamp")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property)
+                     .IsRowVersion();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.LibraryRoot>()
+                     .HasOne(x => x.Library)
+                     .WithOne()
+                     .HasForeignKey<global::Jellyfin.Data.Entities.LibraryRoot>("Library_Id")
+                     .IsRequired();
+
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.MediaFile>()
+                     .ToTable("MediaFile")
+                     .HasKey(t => t.Id);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.MediaFile>()
+                     .Property(t => t.Id)
+                     .IsRequired()
+                     .HasField("_Id")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property)
+                     .ValueGeneratedOnAdd();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.MediaFile>()
+                     .Property(t => t.Path)
+                     .HasMaxLength(65535)
+                     .IsRequired()
+                     .HasField("_Path")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.MediaFile>()
+                     .Property(t => t.Kind)
+                     .IsRequired()
+                     .HasField("_Kind")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.MediaFile>()
+                     .Property(t => t.Timestamp)
+                     .IsRequired()
+                     .HasField("_Timestamp")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property)
+                     .IsRowVersion();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.MediaFile>()
+                     .HasMany(x => x.MediaFileStreams)
+                     .WithOne()
+                     .HasForeignKey("MediaFileStream_MediaFileStreams_Id")
+                     .IsRequired();
+
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.MediaFileStream>()
+                     .ToTable("MediaFileStream")
+                     .HasKey(t => t.Id);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.MediaFileStream>()
+                     .Property(t => t.Id)
+                     .IsRequired()
+                     .HasField("_Id")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property)
+                     .ValueGeneratedOnAdd();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.MediaFileStream>()
+                     .Property(t => t.StreamNumber)
+                     .IsRequired()
+                     .HasField("_StreamNumber")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.MediaFileStream>()
+                     .Property(t => t.Timestamp)
+                     .IsRequired()
+                     .HasField("_Timestamp")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property)
+                     .IsRowVersion();
+
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Metadata>()
+                     .ToTable("Metadata")
+                     .HasKey(t => t.Id);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Metadata>()
+                     .Property(t => t.Id)
+                     .IsRequired()
+                     .HasField("_Id")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property)
+                     .ValueGeneratedOnAdd();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Metadata>()
+                     .Property(t => t.Title)
+                     .HasMaxLength(1024)
+                     .IsRequired()
+                     .HasField("_Title")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Metadata>()
+                     .Property(t => t.OriginalTitle)
+                     .HasMaxLength(1024)
+                     .HasField("_OriginalTitle")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Metadata>()
+                     .Property(t => t.SortTitle)
+                     .HasMaxLength(1024)
+                     .HasField("_SortTitle")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Metadata>()
+                     .Property(t => t.Language)
+                     .HasMaxLength(3)
+                     .IsRequired()
+                     .HasField("_Language")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Metadata>()
+                     .Property(t => t.ReleaseDate)
+                     .HasField("_ReleaseDate")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Metadata>()
+                     .Property(t => t.DateAdded)
+                     .IsRequired()
+                     .HasField("_DateAdded")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Metadata>()
+                     .Property(t => t.DateModified)
+                     .IsRequired()
+                     .HasField("_DateModified")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Metadata>()
+                     .Property(t => t.Timestamp)
+                     .IsRequired()
+                     .HasField("_Timestamp")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property)
+                     .IsRowVersion();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Metadata>()
+                     .HasMany(x => x.PersonRoles)
+                     .WithOne()
+                     .HasForeignKey("PersonRole_PersonRoles_Id")
+                     .IsRequired();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Metadata>()
+                     .HasMany(x => x.Genres)
+                     .WithOne()
+                     .HasForeignKey("Genre_Genres_Id")
+                     .IsRequired();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Metadata>()
+                     .HasMany(x => x.Artwork)
+                     .WithOne()
+                     .HasForeignKey("Artwork_Artwork_Id")
+                     .IsRequired();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Metadata>()
+                     .HasMany(x => x.Ratings)
+                     .WithOne()
+                     .HasForeignKey("Rating_Ratings_Id")
+                     .IsRequired();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Metadata>()
+                     .HasMany(x => x.Sources)
+                     .WithOne()
+                     .HasForeignKey("MetadataProviderId_Sources_Id")
+                     .IsRequired();
+
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.MetadataProvider>()
+                     .ToTable("MetadataProvider")
+                     .HasKey(t => t.Id);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.MetadataProvider>()
+                     .Property(t => t.Id)
+                     .IsRequired()
+                     .HasField("_Id")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property)
+                     .ValueGeneratedOnAdd();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.MetadataProvider>()
+                     .Property(t => t.Name)
+                     .HasMaxLength(1024)
+                     .IsRequired()
+                     .HasField("_Name")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.MetadataProvider>()
+                     .Property(t => t.Timestamp)
+                     .IsRequired()
+                     .HasField("_Timestamp")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property)
+                     .IsRowVersion();
+
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.MetadataProviderId>()
+                     .ToTable("MetadataProviderId")
+                     .HasKey(t => t.Id);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.MetadataProviderId>()
+                     .Property(t => t.Id)
+                     .IsRequired()
+                     .HasField("_Id")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property)
+                     .ValueGeneratedOnAdd();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.MetadataProviderId>()
+                     .Property(t => t.ProviderId)
+                     .HasMaxLength(255)
+                     .IsRequired()
+                     .HasField("_ProviderId")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.MetadataProviderId>()
+                     .Property(t => t.Timestamp)
+                     .IsRequired()
+                     .HasField("_Timestamp")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property)
+                     .IsRowVersion();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.MetadataProviderId>()
+                     .HasOne(x => x.MetadataProvider)
+                     .WithOne()
+                     .HasForeignKey<global::Jellyfin.Data.Entities.MetadataProviderId>("MetadataProvider_Id")
+                     .IsRequired();
+
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Movie>()
+                     .HasMany(x => x.Releases)
+                     .WithOne()
+                     .HasForeignKey("Release_Releases_Id")
+                     .IsRequired();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Movie>()
+                     .HasMany(x => x.MovieMetadata)
+                     .WithOne()
+                     .HasForeignKey("MovieMetadata_MovieMetadata_Id")
+                     .IsRequired();
+
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.MovieMetadata>()
+                     .Property(t => t.Outline)
+                     .HasMaxLength(1024)
+                     .HasField("_Outline")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.MovieMetadata>()
+                     .Property(t => t.Plot)
+                     .HasMaxLength(65535)
+                     .HasField("_Plot")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.MovieMetadata>()
+                     .Property(t => t.Tagline)
+                     .HasMaxLength(1024)
+                     .HasField("_Tagline")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.MovieMetadata>()
+                     .Property(t => t.Country)
+                     .HasMaxLength(2)
+                     .HasField("_Country")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.MovieMetadata>()
+                     .HasMany(x => x.Studios)
+                     .WithOne()
+                     .HasForeignKey("Company_Studios_Id")
+                     .IsRequired();
+
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.MusicAlbum>()
+                     .HasMany(x => x.MusicAlbumMetadata)
+                     .WithOne()
+                     .HasForeignKey("MusicAlbumMetadata_MusicAlbumMetadata_Id")
+                     .IsRequired();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.MusicAlbum>()
+                     .HasMany(x => x.Tracks)
+                     .WithOne()
+                     .HasForeignKey("Track_Tracks_Id")
+                     .IsRequired();
+
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.MusicAlbumMetadata>()
+                     .Property(t => t.Barcode)
+                     .HasMaxLength(255)
+                     .HasField("_Barcode")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.MusicAlbumMetadata>()
+                     .Property(t => t.LabelNumber)
+                     .HasMaxLength(255)
+                     .HasField("_LabelNumber")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.MusicAlbumMetadata>()
+                     .Property(t => t.Country)
+                     .HasMaxLength(2)
+                     .HasField("_Country")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.MusicAlbumMetadata>()
+                     .HasMany(x => x.Labels)
+                     .WithOne()
+                     .HasForeignKey("Company_Labels_Id")
+                     .IsRequired();
+
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Permission>()
+                     .ToTable("Permissions")
+                     .HasKey(t => t.Id);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Permission>()
+                     .Property(t => t.Id)
+                     .IsRequired()
+                     .ValueGeneratedOnAdd();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Permission>()
+                     .Property(t => t.Kind)
+                     .IsRequired()
+                     .HasField("_Kind")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Permission>()
+                     .Property(t => t.Value)
+                     .IsRequired();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Permission>().Property<byte[]>("Timestamp").IsConcurrencyToken();
+
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Person>()
+                     .ToTable("Person")
+                     .HasKey(t => t.Id);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Person>()
+                     .Property(t => t.Id)
+                     .IsRequired()
+                     .HasField("_Id")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property)
+                     .ValueGeneratedOnAdd();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Person>()
+                     .Property(t => t.UrlId)
+                     .IsRequired()
+                     .HasField("_UrlId")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Person>()
+                     .Property(t => t.Name)
+                     .HasMaxLength(1024)
+                     .IsRequired()
+                     .HasField("_Name")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Person>()
+                     .Property(t => t.SourceId)
+                     .HasMaxLength(255)
+                     .HasField("_SourceId")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Person>()
+                     .Property(t => t.DateAdded)
+                     .IsRequired()
+                     .HasField("_DateAdded")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Person>()
+                     .Property(t => t.DateModified)
+                     .IsRequired()
+                     .HasField("_DateModified")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Person>()
+                     .Property(t => t.Timestamp)
+                     .IsRequired()
+                     .HasField("_Timestamp")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property)
+                     .IsRowVersion();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Person>()
+                     .HasMany(x => x.Sources)
+                     .WithOne()
+                     .HasForeignKey("MetadataProviderId_Sources_Id")
+                     .IsRequired();
+
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.PersonRole>()
+                     .ToTable("PersonRole")
+                     .HasKey(t => t.Id);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.PersonRole>()
+                     .Property(t => t.Id)
+                     .IsRequired()
+                     .HasField("_Id")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property)
+                     .ValueGeneratedOnAdd();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.PersonRole>()
+                     .Property(t => t.Role)
+                     .HasMaxLength(1024)
+                     .HasField("_Role")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.PersonRole>()
+                     .Property(t => t.Type)
+                     .IsRequired()
+                     .HasField("_Type")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.PersonRole>()
+                     .Property(t => t.Timestamp)
+                     .IsRequired()
+                     .HasField("_Timestamp")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property)
+                     .IsRowVersion();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.PersonRole>()
+                     .HasOne(x => x.Person)
+                     .WithOne()
+                     .HasForeignKey<global::Jellyfin.Data.Entities.PersonRole>("Person_Id")
+                     .IsRequired()
+                     .OnDelete(DeleteBehavior.Cascade);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.PersonRole>()
+                     .HasOne(x => x.Artwork)
+                     .WithOne()
+                     .HasForeignKey<global::Jellyfin.Data.Entities.PersonRole>("Artwork_Artwork_Id")
+                     .IsRequired();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.PersonRole>()
+                     .HasMany(x => x.Sources)
+                     .WithOne()
+                     .HasForeignKey("MetadataProviderId_Sources_Id")
+                     .IsRequired();
+
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Photo>()
+                     .HasMany(x => x.PhotoMetadata)
+                     .WithOne()
+                     .HasForeignKey("PhotoMetadata_PhotoMetadata_Id")
+                     .IsRequired();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Photo>()
+                     .HasMany(x => x.Releases)
+                     .WithOne()
+                     .HasForeignKey("Release_Releases_Id")
+                     .IsRequired();
+
+
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Preference>()
+                     .ToTable("Preferences")
+                     .HasKey(t => t.Id);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Preference>()
+                     .Property(t => t.Id)
+                     .IsRequired()
+                     .ValueGeneratedOnAdd();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Preference>()
+                     .Property(t => t.Kind)
+                     .IsRequired();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Preference>()
+                     .Property(t => t.Value)
+                     .HasMaxLength(65535)
+                     .IsRequired();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Preference>().Property<byte[]>("Timestamp").IsConcurrencyToken();
+
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.ProviderMapping>()
+                     .ToTable("ProviderMappings")
+                     .HasKey(t => t.Id);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.ProviderMapping>()
+                     .Property(t => t.Id)
+                     .IsRequired()
+                     .ValueGeneratedOnAdd();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.ProviderMapping>()
+                     .Property(t => t.ProviderName)
+                     .HasMaxLength(255)
+                     .IsRequired();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.ProviderMapping>()
+                     .Property(t => t.ProviderSecrets)
+                     .HasMaxLength(65535)
+                     .IsRequired();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.ProviderMapping>()
+                     .Property(t => t.ProviderData)
+                     .HasMaxLength(65535)
+                     .IsRequired();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.ProviderMapping>().Property<byte[]>("Timestamp").IsConcurrencyToken();
+
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Rating>()
+                     .ToTable("Rating")
+                     .HasKey(t => t.Id);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Rating>()
+                     .Property(t => t.Id)
+                     .IsRequired()
+                     .HasField("_Id")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property)
+                     .ValueGeneratedOnAdd();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Rating>()
+                     .Property(t => t.Value)
+                     .IsRequired()
+                     .HasField("_Value")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Rating>()
+                     .Property(t => t.Votes)
+                     .HasField("_Votes")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Rating>()
+                     .Property(t => t.Timestamp)
+                     .IsRequired()
+                     .HasField("_Timestamp")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property)
+                     .IsRowVersion();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Rating>()
+                     .HasOne(x => x.RatingType)
+                     .WithOne()
+                     .HasForeignKey<global::Jellyfin.Data.Entities.Rating>("RatingSource_RatingType_Id")
+                     .IsRequired();
+
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.RatingSource>()
+                     .ToTable("RatingType")
+                     .HasKey(t => t.Id);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.RatingSource>()
+                     .Property(t => t.Id)
+                     .IsRequired()
+                     .HasField("_Id")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property)
+                     .ValueGeneratedOnAdd();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.RatingSource>()
+                     .Property(t => t.Name)
+                     .HasMaxLength(1024)
+                     .HasField("_Name")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.RatingSource>()
+                     .Property(t => t.MaximumValue)
+                     .IsRequired()
+                     .HasField("_MaximumValue")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.RatingSource>()
+                     .Property(t => t.MinimumValue)
+                     .IsRequired()
+                     .HasField("_MinimumValue")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.RatingSource>()
+                     .Property(t => t.Timestamp)
+                     .IsRequired()
+                     .HasField("_Timestamp")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property)
+                     .IsRowVersion();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.RatingSource>()
+                     .HasOne(x => x.Source)
+                     .WithOne()
+                     .HasForeignKey<global::Jellyfin.Data.Entities.RatingSource>("MetadataProviderId_Source_Id")
+                     .IsRequired();
+
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Release>()
+                     .ToTable("Release")
+                     .HasKey(t => t.Id);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Release>()
+                     .Property(t => t.Id)
+                     .IsRequired()
+                     .HasField("_Id")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property)
+                     .ValueGeneratedOnAdd();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Release>()
+                     .Property(t => t.Name)
+                     .HasMaxLength(1024)
+                     .IsRequired()
+                     .HasField("_Name")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Release>()
+                     .Property(t => t.Timestamp)
+                     .IsRequired()
+                     .HasField("_Timestamp")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property)
+                     .IsRowVersion();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Release>()
+                     .HasMany(x => x.MediaFiles)
+                     .WithOne()
+                     .HasForeignKey("MediaFile_MediaFiles_Id")
+                     .IsRequired();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Release>()
+                     .HasMany(x => x.Chapters)
+                     .WithOne()
+                     .HasForeignKey("Chapter_Chapters_Id")
+                     .IsRequired();
+
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Season>()
+                     .Property(t => t.SeasonNumber)
+                     .HasField("_SeasonNumber")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Season>()
+                     .HasMany(x => x.SeasonMetadata)
+                     .WithOne()
+                     .HasForeignKey("SeasonMetadata_SeasonMetadata_Id")
+                     .IsRequired();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Season>()
+                     .HasMany(x => x.Episodes)
+                     .WithOne()
+                     .HasForeignKey("Episode_Episodes_Id")
+                     .IsRequired();
+
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.SeasonMetadata>()
+                     .Property(t => t.Outline)
+                     .HasMaxLength(1024)
+                     .HasField("_Outline")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Series>()
+                     .Property(t => t.AirsDayOfWeek)
+                     .HasField("_AirsDayOfWeek")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Series>()
+                     .Property(t => t.AirsTime)
+                     .HasField("_AirsTime")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Series>()
+                     .Property(t => t.FirstAired)
+                     .HasField("_FirstAired")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Series>()
+                     .HasMany(x => x.SeriesMetadata)
+                     .WithOne()
+                     .HasForeignKey("SeriesMetadata_SeriesMetadata_Id")
+                     .IsRequired();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Series>()
+                     .HasMany(x => x.Seasons)
+                     .WithOne()
+                     .HasForeignKey("Season_Seasons_Id")
+                     .IsRequired();
+
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.SeriesMetadata>()
+                     .Property(t => t.Outline)
+                     .HasMaxLength(1024)
+                     .HasField("_Outline")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.SeriesMetadata>()
+                     .Property(t => t.Plot)
+                     .HasMaxLength(65535)
+                     .HasField("_Plot")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.SeriesMetadata>()
+                     .Property(t => t.Tagline)
+                     .HasMaxLength(1024)
+                     .HasField("_Tagline")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.SeriesMetadata>()
+                     .Property(t => t.Country)
+                     .HasMaxLength(2)
+                     .HasField("_Country")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.SeriesMetadata>()
+                     .HasMany(x => x.Networks)
+                     .WithOne()
+                     .HasForeignKey("Company_Networks_Id")
+                     .IsRequired();
+
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Track>()
+                     .Property(t => t.TrackNumber)
+                     .HasField("_TrackNumber")
+                     .UsePropertyAccessMode(PropertyAccessMode.Property);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Track>()
+                     .HasMany(x => x.Releases)
+                     .WithOne()
+                     .HasForeignKey("Release_Releases_Id")
+                     .IsRequired();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.Track>()
+                     .HasMany(x => x.TrackMetadata)
+                     .WithOne()
+                     .HasForeignKey("TrackMetadata_TrackMetadata_Id")
+                     .IsRequired();
+
+
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.User>()
+                     .ToTable("Users")
+                     .HasKey(t => t.Id);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.User>()
+                     .Property(t => t.Id)
+                     .IsRequired()
+                     .ValueGeneratedOnAdd();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.User>()
+                     .Property(t => t.LastLoginTimestamp)
+                     .IsRequired()
+                     .IsRowVersion();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.User>()
+                     .Property(t => t.Username)
+                     .HasMaxLength(255)
+                     .IsRequired();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.User>()
+                     .Property(t => t.Password)
+                     .HasMaxLength(65535);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.User>()
+                     .Property(t => t.MustUpdatePassword)
+                     .IsRequired();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.User>()
+                     .Property(t => t.AudioLanguagePreference)
+                     .HasMaxLength(255)
+                     .IsRequired();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.User>()
+                     .Property(t => t.AuthenticationProviderId)
+                     .HasMaxLength(255)
+                     .IsRequired();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.User>()
+                     .Property(t => t.GroupedFolders)
+                     .HasMaxLength(65535);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.User>()
+                     .Property(t => t.InvalidLoginAttemptCount)
+                     .IsRequired();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.User>()
+                     .Property(t => t.LatestItemExcludes)
+                     .HasMaxLength(65535);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.User>()
+                     .Property(t => t.MyMediaExcludes)
+                     .HasMaxLength(65535);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.User>()
+                     .Property(t => t.OrderedViews)
+                     .HasMaxLength(65535);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.User>()
+                     .Property(t => t.SubtitleMode)
+                     .HasMaxLength(255)
+                     .IsRequired();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.User>()
+                     .Property(t => t.PlayDefaultAudioTrack)
+                     .IsRequired();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.User>()
+                     .Property(t => t.SubtitleLanguagePrefernce)
+                     .HasMaxLength(255);
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.User>()
+                     .HasMany(x => x.Groups)
+                     .WithOne()
+                     .HasForeignKey("Group_Groups_Id")
+                     .IsRequired();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.User>()
+                     .HasMany(x => x.Permissions)
+                     .WithOne()
+                     .HasForeignKey("Permission_Permissions_Id")
+                     .IsRequired();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.User>()
+                     .HasMany(x => x.ProviderMappings)
+                     .WithOne()
+                     .HasForeignKey("ProviderMapping_ProviderMappings_Id")
+                     .IsRequired();
+         modelBuilder.Entity<global::Jellyfin.Data.Entities.User>()
+                     .HasMany(x => x.Preferences)
+                     .WithOne()
+                     .HasForeignKey("Preference_Preferences_Id")
+                     .IsRequired();
+
+         OnModelCreatedImpl(modelBuilder);
+      }
+   }
+}

+ 208 - 0
Jellyfin.Data/Entities/Artwork.cs

@@ -0,0 +1,208 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated from a template.
+//
+//     Manual changes to this file may cause unexpected behavior in your application.
+//     Manual changes to this file will be overwritten if the code is regenerated.
+//
+//     Produced by Entity Framework Visual Editor
+//     https://github.com/msawczyn/EFDesigner
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Linq;
+using System.Runtime.CompilerServices;
+
+namespace Jellyfin.Data.Entities
+{
+   public partial class Artwork
+   {
+      partial void Init();
+
+      /// <summary>
+      /// Default constructor. Protected due to required properties, but present because EF needs it.
+      /// </summary>
+      protected Artwork()
+      {
+         Init();
+      }
+
+      /// <summary>
+      /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving.
+      /// </summary>
+      public static Artwork CreateArtworkUnsafe()
+      {
+         return new Artwork();
+      }
+
+      /// <summary>
+      /// Public constructor with required data
+      /// </summary>
+      /// <param name="path"></param>
+      /// <param name="kind"></param>
+      /// <param name="_metadata0"></param>
+      /// <param name="_personrole1"></param>
+      public Artwork(string path, global::Jellyfin.Data.Enums.ArtKind kind, global::Jellyfin.Data.Entities.Metadata _metadata0, global::Jellyfin.Data.Entities.PersonRole _personrole1)
+      {
+         if (string.IsNullOrEmpty(path)) throw new ArgumentNullException(nameof(path));
+         this.Path = path;
+
+         this.Kind = kind;
+
+         if (_metadata0 == null) throw new ArgumentNullException(nameof(_metadata0));
+         _metadata0.Artwork.Add(this);
+
+         if (_personrole1 == null) throw new ArgumentNullException(nameof(_personrole1));
+         _personrole1.Artwork = this;
+
+
+         Init();
+      }
+
+      /// <summary>
+      /// Static create function (for use in LINQ queries, etc.)
+      /// </summary>
+      /// <param name="path"></param>
+      /// <param name="kind"></param>
+      /// <param name="_metadata0"></param>
+      /// <param name="_personrole1"></param>
+      public static Artwork Create(string path, global::Jellyfin.Data.Enums.ArtKind kind, global::Jellyfin.Data.Entities.Metadata _metadata0, global::Jellyfin.Data.Entities.PersonRole _personrole1)
+      {
+         return new Artwork(path, kind, _metadata0, _personrole1);
+      }
+
+      /*************************************************************************
+       * Properties
+       *************************************************************************/
+
+      /// <summary>
+      /// Backing field for Id
+      /// </summary>
+      internal int _Id;
+      /// <summary>
+      /// When provided in a partial class, allows value of Id to be changed before setting.
+      /// </summary>
+      partial void SetId(int oldValue, ref int newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Id to be changed before returning.
+      /// </summary>
+      partial void GetId(ref int result);
+
+      /// <summary>
+      /// Identity, Indexed, Required
+      /// </summary>
+      [Key]
+      [Required]
+      public int Id
+      {
+         get
+         {
+            int value = _Id;
+            GetId(ref value);
+            return (_Id = value);
+         }
+         protected set
+         {
+            int oldValue = _Id;
+            SetId(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Id = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Backing field for Path
+      /// </summary>
+      protected string _Path;
+      /// <summary>
+      /// When provided in a partial class, allows value of Path to be changed before setting.
+      /// </summary>
+      partial void SetPath(string oldValue, ref string newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Path to be changed before returning.
+      /// </summary>
+      partial void GetPath(ref string result);
+
+      /// <summary>
+      /// Required, Max length = 65535
+      /// </summary>
+      [Required]
+      [MaxLength(65535)]
+      [StringLength(65535)]
+      public string Path
+      {
+         get
+         {
+            string value = _Path;
+            GetPath(ref value);
+            return (_Path = value);
+         }
+         set
+         {
+            string oldValue = _Path;
+            SetPath(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Path = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Backing field for Kind
+      /// </summary>
+      internal global::Jellyfin.Data.Enums.ArtKind _Kind;
+      /// <summary>
+      /// When provided in a partial class, allows value of Kind to be changed before setting.
+      /// </summary>
+      partial void SetKind(global::Jellyfin.Data.Enums.ArtKind oldValue, ref global::Jellyfin.Data.Enums.ArtKind newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Kind to be changed before returning.
+      /// </summary>
+      partial void GetKind(ref global::Jellyfin.Data.Enums.ArtKind result);
+
+      /// <summary>
+      /// Indexed, Required
+      /// </summary>
+      [Required]
+      public global::Jellyfin.Data.Enums.ArtKind Kind
+      {
+         get
+         {
+            global::Jellyfin.Data.Enums.ArtKind value = _Kind;
+            GetKind(ref value);
+            return (_Kind = value);
+         }
+         set
+         {
+            global::Jellyfin.Data.Enums.ArtKind oldValue = _Kind;
+            SetKind(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Kind = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Required
+      /// </summary>
+      [ConcurrencyCheck]
+      [Required]
+      public byte[] Timestamp { get; set; }
+
+      /*************************************************************************
+       * Navigation properties
+       *************************************************************************/
+
+   }
+}
+

+ 84 - 0
Jellyfin.Data/Entities/Book.cs

@@ -0,0 +1,84 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated from a template.
+//
+//     Manual changes to this file may cause unexpected behavior in your application.
+//     Manual changes to this file will be overwritten if the code is regenerated.
+//
+//     Produced by Entity Framework Visual Editor
+//     https://github.com/msawczyn/EFDesigner
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Linq;
+using System.Runtime.CompilerServices;
+
+namespace Jellyfin.Data.Entities
+{
+   public partial class Book: global::Jellyfin.Data.Entities.LibraryItem
+   {
+      partial void Init();
+
+      /// <summary>
+      /// Default constructor. Protected due to required properties, but present because EF needs it.
+      /// </summary>
+      protected Book(): base()
+      {
+         BookMetadata = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.BookMetadata>();
+         Releases = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.Release>();
+
+         Init();
+      }
+
+      /// <summary>
+      /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving.
+      /// </summary>
+      public static Book CreateBookUnsafe()
+      {
+         return new Book();
+      }
+
+      /// <summary>
+      /// Public constructor with required data
+      /// </summary>
+      /// <param name="urlid">This is whats gets displayed in the Urls and API requests. This could also be a string.</param>
+      public Book(Guid urlid, DateTime dateadded)
+      {
+         this.UrlId = urlid;
+
+         this.BookMetadata = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.BookMetadata>();
+         this.Releases = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.Release>();
+
+         Init();
+      }
+
+      /// <summary>
+      /// Static create function (for use in LINQ queries, etc.)
+      /// </summary>
+      /// <param name="urlid">This is whats gets displayed in the Urls and API requests. This could also be a string.</param>
+      public static Book Create(Guid urlid, DateTime dateadded)
+      {
+         return new Book(urlid, dateadded);
+      }
+
+      /*************************************************************************
+       * Properties
+       *************************************************************************/
+
+      /*************************************************************************
+       * Navigation properties
+       *************************************************************************/
+
+      public virtual ICollection<global::Jellyfin.Data.Entities.BookMetadata> BookMetadata { get; protected set; }
+
+      public virtual ICollection<global::Jellyfin.Data.Entities.Release> Releases { get; protected set; }
+
+   }
+}
+

+ 123 - 0
Jellyfin.Data/Entities/BookMetadata.cs

@@ -0,0 +1,123 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated from a template.
+//
+//     Manual changes to this file may cause unexpected behavior in your application.
+//     Manual changes to this file will be overwritten if the code is regenerated.
+//
+//     Produced by Entity Framework Visual Editor
+//     https://github.com/msawczyn/EFDesigner
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Linq;
+using System.Runtime.CompilerServices;
+
+namespace Jellyfin.Data.Entities
+{
+   public partial class BookMetadata: global::Jellyfin.Data.Entities.Metadata
+   {
+      partial void Init();
+
+      /// <summary>
+      /// Default constructor. Protected due to required properties, but present because EF needs it.
+      /// </summary>
+      protected BookMetadata(): base()
+      {
+         Publishers = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.Company>();
+
+         Init();
+      }
+
+      /// <summary>
+      /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving.
+      /// </summary>
+      public static BookMetadata CreateBookMetadataUnsafe()
+      {
+         return new BookMetadata();
+      }
+
+      /// <summary>
+      /// Public constructor with required data
+      /// </summary>
+      /// <param name="title">The title or name of the object</param>
+      /// <param name="language">ISO-639-3 3-character language codes</param>
+      /// <param name="_book0"></param>
+      public BookMetadata(string title, string language, DateTime dateadded, DateTime datemodified, global::Jellyfin.Data.Entities.Book _book0)
+      {
+         if (string.IsNullOrEmpty(title)) throw new ArgumentNullException(nameof(title));
+         this.Title = title;
+
+         if (string.IsNullOrEmpty(language)) throw new ArgumentNullException(nameof(language));
+         this.Language = language;
+
+         if (_book0 == null) throw new ArgumentNullException(nameof(_book0));
+         _book0.BookMetadata.Add(this);
+
+         this.Publishers = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.Company>();
+
+         Init();
+      }
+
+      /// <summary>
+      /// Static create function (for use in LINQ queries, etc.)
+      /// </summary>
+      /// <param name="title">The title or name of the object</param>
+      /// <param name="language">ISO-639-3 3-character language codes</param>
+      /// <param name="_book0"></param>
+      public static BookMetadata Create(string title, string language, DateTime dateadded, DateTime datemodified, global::Jellyfin.Data.Entities.Book _book0)
+      {
+         return new BookMetadata(title, language, dateadded, datemodified, _book0);
+      }
+
+      /*************************************************************************
+       * Properties
+       *************************************************************************/
+
+      /// <summary>
+      /// Backing field for ISBN
+      /// </summary>
+      protected long? _ISBN;
+      /// <summary>
+      /// When provided in a partial class, allows value of ISBN to be changed before setting.
+      /// </summary>
+      partial void SetISBN(long? oldValue, ref long? newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of ISBN to be changed before returning.
+      /// </summary>
+      partial void GetISBN(ref long? result);
+
+      public long? ISBN
+      {
+         get
+         {
+            long? value = _ISBN;
+            GetISBN(ref value);
+            return (_ISBN = value);
+         }
+         set
+         {
+            long? oldValue = _ISBN;
+            SetISBN(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _ISBN = value;
+            }
+         }
+      }
+
+      /*************************************************************************
+       * Navigation properties
+       *************************************************************************/
+
+      public virtual ICollection<global::Jellyfin.Data.Entities.Company> Publishers { get; protected set; }
+
+   }
+}
+

+ 274 - 0
Jellyfin.Data/Entities/Chapter.cs

@@ -0,0 +1,274 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated from a template.
+//
+//     Manual changes to this file may cause unexpected behavior in your application.
+//     Manual changes to this file will be overwritten if the code is regenerated.
+//
+//     Produced by Entity Framework Visual Editor
+//     https://github.com/msawczyn/EFDesigner
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Linq;
+using System.Runtime.CompilerServices;
+
+namespace Jellyfin.Data.Entities
+{
+   public partial class Chapter
+   {
+      partial void Init();
+
+      /// <summary>
+      /// Default constructor. Protected due to required properties, but present because EF needs it.
+      /// </summary>
+      protected Chapter()
+      {
+         Init();
+      }
+
+      /// <summary>
+      /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving.
+      /// </summary>
+      public static Chapter CreateChapterUnsafe()
+      {
+         return new Chapter();
+      }
+
+      /// <summary>
+      /// Public constructor with required data
+      /// </summary>
+      /// <param name="language">ISO-639-3 3-character language codes</param>
+      /// <param name="timestart"></param>
+      /// <param name="_release0"></param>
+      public Chapter(string language, long timestart, global::Jellyfin.Data.Entities.Release _release0)
+      {
+         if (string.IsNullOrEmpty(language)) throw new ArgumentNullException(nameof(language));
+         this.Language = language;
+
+         this.TimeStart = timestart;
+
+         if (_release0 == null) throw new ArgumentNullException(nameof(_release0));
+         _release0.Chapters.Add(this);
+
+
+         Init();
+      }
+
+      /// <summary>
+      /// Static create function (for use in LINQ queries, etc.)
+      /// </summary>
+      /// <param name="language">ISO-639-3 3-character language codes</param>
+      /// <param name="timestart"></param>
+      /// <param name="_release0"></param>
+      public static Chapter Create(string language, long timestart, global::Jellyfin.Data.Entities.Release _release0)
+      {
+         return new Chapter(language, timestart, _release0);
+      }
+
+      /*************************************************************************
+       * Properties
+       *************************************************************************/
+
+      /// <summary>
+      /// Backing field for Id
+      /// </summary>
+      internal int _Id;
+      /// <summary>
+      /// When provided in a partial class, allows value of Id to be changed before setting.
+      /// </summary>
+      partial void SetId(int oldValue, ref int newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Id to be changed before returning.
+      /// </summary>
+      partial void GetId(ref int result);
+
+      /// <summary>
+      /// Identity, Indexed, Required
+      /// </summary>
+      [Key]
+      [Required]
+      public int Id
+      {
+         get
+         {
+            int value = _Id;
+            GetId(ref value);
+            return (_Id = value);
+         }
+         protected set
+         {
+            int oldValue = _Id;
+            SetId(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Id = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Backing field for Name
+      /// </summary>
+      protected string _Name;
+      /// <summary>
+      /// When provided in a partial class, allows value of Name to be changed before setting.
+      /// </summary>
+      partial void SetName(string oldValue, ref string newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Name to be changed before returning.
+      /// </summary>
+      partial void GetName(ref string result);
+
+      /// <summary>
+      /// Max length = 1024
+      /// </summary>
+      [MaxLength(1024)]
+      [StringLength(1024)]
+      public string Name
+      {
+         get
+         {
+            string value = _Name;
+            GetName(ref value);
+            return (_Name = value);
+         }
+         set
+         {
+            string oldValue = _Name;
+            SetName(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Name = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Backing field for Language
+      /// </summary>
+      protected string _Language;
+      /// <summary>
+      /// When provided in a partial class, allows value of Language to be changed before setting.
+      /// </summary>
+      partial void SetLanguage(string oldValue, ref string newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Language to be changed before returning.
+      /// </summary>
+      partial void GetLanguage(ref string result);
+
+      /// <summary>
+      /// Required, Min length = 3, Max length = 3
+      /// ISO-639-3 3-character language codes
+      /// </summary>
+      [Required]
+      [MinLength(3)]
+      [MaxLength(3)]
+      [StringLength(3)]
+      public string Language
+      {
+         get
+         {
+            string value = _Language;
+            GetLanguage(ref value);
+            return (_Language = value);
+         }
+         set
+         {
+            string oldValue = _Language;
+            SetLanguage(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Language = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Backing field for TimeStart
+      /// </summary>
+      protected long _TimeStart;
+      /// <summary>
+      /// When provided in a partial class, allows value of TimeStart to be changed before setting.
+      /// </summary>
+      partial void SetTimeStart(long oldValue, ref long newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of TimeStart to be changed before returning.
+      /// </summary>
+      partial void GetTimeStart(ref long result);
+
+      /// <summary>
+      /// Required
+      /// </summary>
+      [Required]
+      public long TimeStart
+      {
+         get
+         {
+            long value = _TimeStart;
+            GetTimeStart(ref value);
+            return (_TimeStart = value);
+         }
+         set
+         {
+            long oldValue = _TimeStart;
+            SetTimeStart(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _TimeStart = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Backing field for TimeEnd
+      /// </summary>
+      protected long? _TimeEnd;
+      /// <summary>
+      /// When provided in a partial class, allows value of TimeEnd to be changed before setting.
+      /// </summary>
+      partial void SetTimeEnd(long? oldValue, ref long? newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of TimeEnd to be changed before returning.
+      /// </summary>
+      partial void GetTimeEnd(ref long? result);
+
+      public long? TimeEnd
+      {
+         get
+         {
+            long? value = _TimeEnd;
+            GetTimeEnd(ref value);
+            return (_TimeEnd = value);
+         }
+         set
+         {
+            long? oldValue = _TimeEnd;
+            SetTimeEnd(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _TimeEnd = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Required
+      /// </summary>
+      [ConcurrencyCheck]
+      [Required]
+      public byte[] Timestamp { get; set; }
+
+      /*************************************************************************
+       * Navigation properties
+       *************************************************************************/
+
+   }
+}
+

+ 131 - 0
Jellyfin.Data/Entities/Collection.cs

@@ -0,0 +1,131 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated from a template.
+//
+//     Manual changes to this file may cause unexpected behavior in your application.
+//     Manual changes to this file will be overwritten if the code is regenerated.
+//
+//     Produced by Entity Framework Visual Editor
+//     https://github.com/msawczyn/EFDesigner
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Linq;
+using System.Runtime.CompilerServices;
+
+namespace Jellyfin.Data.Entities
+{
+   public partial class Collection
+   {
+      partial void Init();
+
+      /// <summary>
+      /// Default constructor
+      /// </summary>
+      public Collection()
+      {
+         CollectionItem = new System.Collections.Generic.LinkedList<global::Jellyfin.Data.Entities.CollectionItem>();
+
+         Init();
+      }
+
+      /*************************************************************************
+       * Properties
+       *************************************************************************/
+
+      /// <summary>
+      /// Backing field for Id
+      /// </summary>
+      internal int _Id;
+      /// <summary>
+      /// When provided in a partial class, allows value of Id to be changed before setting.
+      /// </summary>
+      partial void SetId(int oldValue, ref int newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Id to be changed before returning.
+      /// </summary>
+      partial void GetId(ref int result);
+
+      /// <summary>
+      /// Identity, Indexed, Required
+      /// </summary>
+      [Key]
+      [Required]
+      public int Id
+      {
+         get
+         {
+            int value = _Id;
+            GetId(ref value);
+            return (_Id = value);
+         }
+         protected set
+         {
+            int oldValue = _Id;
+            SetId(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Id = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Backing field for Name
+      /// </summary>
+      protected string _Name;
+      /// <summary>
+      /// When provided in a partial class, allows value of Name to be changed before setting.
+      /// </summary>
+      partial void SetName(string oldValue, ref string newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Name to be changed before returning.
+      /// </summary>
+      partial void GetName(ref string result);
+
+      /// <summary>
+      /// Max length = 1024
+      /// </summary>
+      [MaxLength(1024)]
+      [StringLength(1024)]
+      public string Name
+      {
+         get
+         {
+            string value = _Name;
+            GetName(ref value);
+            return (_Name = value);
+         }
+         set
+         {
+            string oldValue = _Name;
+            SetName(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Name = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Required
+      /// </summary>
+      [ConcurrencyCheck]
+      [Required]
+      public byte[] Timestamp { get; set; }
+
+      /*************************************************************************
+       * Navigation properties
+       *************************************************************************/
+
+      public virtual ICollection<global::Jellyfin.Data.Entities.CollectionItem> CollectionItem { get; protected set; }
+
+   }
+}
+

+ 151 - 0
Jellyfin.Data/Entities/CollectionItem.cs

@@ -0,0 +1,151 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated from a template.
+//
+//     Manual changes to this file may cause unexpected behavior in your application.
+//     Manual changes to this file will be overwritten if the code is regenerated.
+//
+//     Produced by Entity Framework Visual Editor
+//     https://github.com/msawczyn/EFDesigner
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Linq;
+using System.Runtime.CompilerServices;
+
+namespace Jellyfin.Data.Entities
+{
+   public partial class CollectionItem
+   {
+      partial void Init();
+
+      /// <summary>
+      /// Default constructor. Protected due to required properties, but present because EF needs it.
+      /// </summary>
+      protected CollectionItem()
+      {
+         // NOTE: This class has one-to-one associations with CollectionItem.
+         // One-to-one associations are not validated in constructors since this causes a scenario where each one must be constructed before the other.
+
+         Init();
+      }
+
+      /// <summary>
+      /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving.
+      /// </summary>
+      public static CollectionItem CreateCollectionItemUnsafe()
+      {
+         return new CollectionItem();
+      }
+
+      /// <summary>
+      /// Public constructor with required data
+      /// </summary>
+      /// <param name="_collection0"></param>
+      /// <param name="_collectionitem1"></param>
+      /// <param name="_collectionitem2"></param>
+      public CollectionItem(global::Jellyfin.Data.Entities.Collection _collection0, global::Jellyfin.Data.Entities.CollectionItem _collectionitem1, global::Jellyfin.Data.Entities.CollectionItem _collectionitem2)
+      {
+         // NOTE: This class has one-to-one associations with CollectionItem.
+         // One-to-one associations are not validated in constructors since this causes a scenario where each one must be constructed before the other.
+
+         if (_collection0 == null) throw new ArgumentNullException(nameof(_collection0));
+         _collection0.CollectionItem.Add(this);
+
+         if (_collectionitem1 == null) throw new ArgumentNullException(nameof(_collectionitem1));
+         _collectionitem1.Next = this;
+
+         if (_collectionitem2 == null) throw new ArgumentNullException(nameof(_collectionitem2));
+         _collectionitem2.Previous = this;
+
+
+         Init();
+      }
+
+      /// <summary>
+      /// Static create function (for use in LINQ queries, etc.)
+      /// </summary>
+      /// <param name="_collection0"></param>
+      /// <param name="_collectionitem1"></param>
+      /// <param name="_collectionitem2"></param>
+      public static CollectionItem Create(global::Jellyfin.Data.Entities.Collection _collection0, global::Jellyfin.Data.Entities.CollectionItem _collectionitem1, global::Jellyfin.Data.Entities.CollectionItem _collectionitem2)
+      {
+         return new CollectionItem(_collection0, _collectionitem1, _collectionitem2);
+      }
+
+      /*************************************************************************
+       * Properties
+       *************************************************************************/
+
+      /// <summary>
+      /// Backing field for Id
+      /// </summary>
+      internal int _Id;
+      /// <summary>
+      /// When provided in a partial class, allows value of Id to be changed before setting.
+      /// </summary>
+      partial void SetId(int oldValue, ref int newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Id to be changed before returning.
+      /// </summary>
+      partial void GetId(ref int result);
+
+      /// <summary>
+      /// Identity, Indexed, Required
+      /// </summary>
+      [Key]
+      [Required]
+      public int Id
+      {
+         get
+         {
+            int value = _Id;
+            GetId(ref value);
+            return (_Id = value);
+         }
+         protected set
+         {
+            int oldValue = _Id;
+            SetId(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Id = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Required
+      /// </summary>
+      [ConcurrencyCheck]
+      [Required]
+      public byte[] Timestamp { get; set; }
+
+      /*************************************************************************
+       * Navigation properties
+       *************************************************************************/
+
+      /// <summary>
+      /// Required
+      /// </summary>
+      public virtual global::Jellyfin.Data.Entities.LibraryItem LibraryItem { get; set; }
+
+      /// <remarks>
+      /// TODO check if this properly updated dependant and has the proper principal relationship
+      /// </remarks>
+      public virtual global::Jellyfin.Data.Entities.CollectionItem Next { get; set; }
+
+      /// <remarks>
+      /// TODO check if this properly updated dependant and has the proper principal relationship
+      /// </remarks>
+      public virtual global::Jellyfin.Data.Entities.CollectionItem Previous { get; set; }
+
+   }
+}
+

+ 147 - 0
Jellyfin.Data/Entities/Company.cs

@@ -0,0 +1,147 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated from a template.
+//
+//     Manual changes to this file may cause unexpected behavior in your application.
+//     Manual changes to this file will be overwritten if the code is regenerated.
+//
+//     Produced by Entity Framework Visual Editor
+//     https://github.com/msawczyn/EFDesigner
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Linq;
+using System.Runtime.CompilerServices;
+
+namespace Jellyfin.Data.Entities
+{
+   public partial class Company
+   {
+      partial void Init();
+
+      /// <summary>
+      /// Default constructor. Protected due to required properties, but present because EF needs it.
+      /// </summary>
+      protected Company()
+      {
+         CompanyMetadata = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.CompanyMetadata>();
+
+         Init();
+      }
+
+      /// <summary>
+      /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving.
+      /// </summary>
+      public static Company CreateCompanyUnsafe()
+      {
+         return new Company();
+      }
+
+      /// <summary>
+      /// Public constructor with required data
+      /// </summary>
+      /// <param name="_moviemetadata0"></param>
+      /// <param name="_seriesmetadata1"></param>
+      /// <param name="_musicalbummetadata2"></param>
+      /// <param name="_bookmetadata3"></param>
+      /// <param name="_company4"></param>
+      public Company(global::Jellyfin.Data.Entities.MovieMetadata _moviemetadata0, global::Jellyfin.Data.Entities.SeriesMetadata _seriesmetadata1, global::Jellyfin.Data.Entities.MusicAlbumMetadata _musicalbummetadata2, global::Jellyfin.Data.Entities.BookMetadata _bookmetadata3, global::Jellyfin.Data.Entities.Company _company4)
+      {
+         if (_moviemetadata0 == null) throw new ArgumentNullException(nameof(_moviemetadata0));
+         _moviemetadata0.Studios.Add(this);
+
+         if (_seriesmetadata1 == null) throw new ArgumentNullException(nameof(_seriesmetadata1));
+         _seriesmetadata1.Networks.Add(this);
+
+         if (_musicalbummetadata2 == null) throw new ArgumentNullException(nameof(_musicalbummetadata2));
+         _musicalbummetadata2.Labels.Add(this);
+
+         if (_bookmetadata3 == null) throw new ArgumentNullException(nameof(_bookmetadata3));
+         _bookmetadata3.Publishers.Add(this);
+
+         if (_company4 == null) throw new ArgumentNullException(nameof(_company4));
+         _company4.Parent = this;
+
+         this.CompanyMetadata = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.CompanyMetadata>();
+
+         Init();
+      }
+
+      /// <summary>
+      /// Static create function (for use in LINQ queries, etc.)
+      /// </summary>
+      /// <param name="_moviemetadata0"></param>
+      /// <param name="_seriesmetadata1"></param>
+      /// <param name="_musicalbummetadata2"></param>
+      /// <param name="_bookmetadata3"></param>
+      /// <param name="_company4"></param>
+      public static Company Create(global::Jellyfin.Data.Entities.MovieMetadata _moviemetadata0, global::Jellyfin.Data.Entities.SeriesMetadata _seriesmetadata1, global::Jellyfin.Data.Entities.MusicAlbumMetadata _musicalbummetadata2, global::Jellyfin.Data.Entities.BookMetadata _bookmetadata3, global::Jellyfin.Data.Entities.Company _company4)
+      {
+         return new Company(_moviemetadata0, _seriesmetadata1, _musicalbummetadata2, _bookmetadata3, _company4);
+      }
+
+      /*************************************************************************
+       * Properties
+       *************************************************************************/
+
+      /// <summary>
+      /// Backing field for Id
+      /// </summary>
+      internal int _Id;
+      /// <summary>
+      /// When provided in a partial class, allows value of Id to be changed before setting.
+      /// </summary>
+      partial void SetId(int oldValue, ref int newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Id to be changed before returning.
+      /// </summary>
+      partial void GetId(ref int result);
+
+      /// <summary>
+      /// Identity, Indexed, Required
+      /// </summary>
+      [Key]
+      [Required]
+      public int Id
+      {
+         get
+         {
+            int value = _Id;
+            GetId(ref value);
+            return (_Id = value);
+         }
+         protected set
+         {
+            int oldValue = _Id;
+            SetId(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Id = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Required
+      /// </summary>
+      [ConcurrencyCheck]
+      [Required]
+      public byte[] Timestamp { get; set; }
+
+      /*************************************************************************
+       * Navigation properties
+       *************************************************************************/
+
+      public virtual ICollection<global::Jellyfin.Data.Entities.CompanyMetadata> CompanyMetadata { get; protected set; }
+
+      public virtual global::Jellyfin.Data.Entities.Company Parent { get; set; }
+
+   }
+}
+

+ 234 - 0
Jellyfin.Data/Entities/CompanyMetadata.cs

@@ -0,0 +1,234 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated from a template.
+//
+//     Manual changes to this file may cause unexpected behavior in your application.
+//     Manual changes to this file will be overwritten if the code is regenerated.
+//
+//     Produced by Entity Framework Visual Editor
+//     https://github.com/msawczyn/EFDesigner
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Linq;
+using System.Runtime.CompilerServices;
+
+namespace Jellyfin.Data.Entities
+{
+   public partial class CompanyMetadata: global::Jellyfin.Data.Entities.Metadata
+   {
+      partial void Init();
+
+      /// <summary>
+      /// Default constructor. Protected due to required properties, but present because EF needs it.
+      /// </summary>
+      protected CompanyMetadata(): base()
+      {
+         Init();
+      }
+
+      /// <summary>
+      /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving.
+      /// </summary>
+      public static CompanyMetadata CreateCompanyMetadataUnsafe()
+      {
+         return new CompanyMetadata();
+      }
+
+      /// <summary>
+      /// Public constructor with required data
+      /// </summary>
+      /// <param name="title">The title or name of the object</param>
+      /// <param name="language">ISO-639-3 3-character language codes</param>
+      /// <param name="_company0"></param>
+      public CompanyMetadata(string title, string language, DateTime dateadded, DateTime datemodified, global::Jellyfin.Data.Entities.Company _company0)
+      {
+         if (string.IsNullOrEmpty(title)) throw new ArgumentNullException(nameof(title));
+         this.Title = title;
+
+         if (string.IsNullOrEmpty(language)) throw new ArgumentNullException(nameof(language));
+         this.Language = language;
+
+         if (_company0 == null) throw new ArgumentNullException(nameof(_company0));
+         _company0.CompanyMetadata.Add(this);
+
+
+         Init();
+      }
+
+      /// <summary>
+      /// Static create function (for use in LINQ queries, etc.)
+      /// </summary>
+      /// <param name="title">The title or name of the object</param>
+      /// <param name="language">ISO-639-3 3-character language codes</param>
+      /// <param name="_company0"></param>
+      public static CompanyMetadata Create(string title, string language, DateTime dateadded, DateTime datemodified, global::Jellyfin.Data.Entities.Company _company0)
+      {
+         return new CompanyMetadata(title, language, dateadded, datemodified, _company0);
+      }
+
+      /*************************************************************************
+       * Properties
+       *************************************************************************/
+
+      /// <summary>
+      /// Backing field for Description
+      /// </summary>
+      protected string _Description;
+      /// <summary>
+      /// When provided in a partial class, allows value of Description to be changed before setting.
+      /// </summary>
+      partial void SetDescription(string oldValue, ref string newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Description to be changed before returning.
+      /// </summary>
+      partial void GetDescription(ref string result);
+
+      /// <summary>
+      /// Max length = 65535
+      /// </summary>
+      [MaxLength(65535)]
+      [StringLength(65535)]
+      public string Description
+      {
+         get
+         {
+            string value = _Description;
+            GetDescription(ref value);
+            return (_Description = value);
+         }
+         set
+         {
+            string oldValue = _Description;
+            SetDescription(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Description = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Backing field for Headquarters
+      /// </summary>
+      protected string _Headquarters;
+      /// <summary>
+      /// When provided in a partial class, allows value of Headquarters to be changed before setting.
+      /// </summary>
+      partial void SetHeadquarters(string oldValue, ref string newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Headquarters to be changed before returning.
+      /// </summary>
+      partial void GetHeadquarters(ref string result);
+
+      /// <summary>
+      /// Max length = 255
+      /// </summary>
+      [MaxLength(255)]
+      [StringLength(255)]
+      public string Headquarters
+      {
+         get
+         {
+            string value = _Headquarters;
+            GetHeadquarters(ref value);
+            return (_Headquarters = value);
+         }
+         set
+         {
+            string oldValue = _Headquarters;
+            SetHeadquarters(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Headquarters = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Backing field for Country
+      /// </summary>
+      protected string _Country;
+      /// <summary>
+      /// When provided in a partial class, allows value of Country to be changed before setting.
+      /// </summary>
+      partial void SetCountry(string oldValue, ref string newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Country to be changed before returning.
+      /// </summary>
+      partial void GetCountry(ref string result);
+
+      /// <summary>
+      /// Max length = 2
+      /// </summary>
+      [MaxLength(2)]
+      [StringLength(2)]
+      public string Country
+      {
+         get
+         {
+            string value = _Country;
+            GetCountry(ref value);
+            return (_Country = value);
+         }
+         set
+         {
+            string oldValue = _Country;
+            SetCountry(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Country = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Backing field for Homepage
+      /// </summary>
+      protected string _Homepage;
+      /// <summary>
+      /// When provided in a partial class, allows value of Homepage to be changed before setting.
+      /// </summary>
+      partial void SetHomepage(string oldValue, ref string newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Homepage to be changed before returning.
+      /// </summary>
+      partial void GetHomepage(ref string result);
+
+      /// <summary>
+      /// Max length = 1024
+      /// </summary>
+      [MaxLength(1024)]
+      [StringLength(1024)]
+      public string Homepage
+      {
+         get
+         {
+            string value = _Homepage;
+            GetHomepage(ref value);
+            return (_Homepage = value);
+         }
+         set
+         {
+            string oldValue = _Homepage;
+            SetHomepage(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Homepage = value;
+            }
+         }
+      }
+
+      /*************************************************************************
+       * Navigation properties
+       *************************************************************************/
+
+   }
+}
+

+ 84 - 0
Jellyfin.Data/Entities/CustomItem.cs

@@ -0,0 +1,84 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated from a template.
+//
+//     Manual changes to this file may cause unexpected behavior in your application.
+//     Manual changes to this file will be overwritten if the code is regenerated.
+//
+//     Produced by Entity Framework Visual Editor
+//     https://github.com/msawczyn/EFDesigner
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Linq;
+using System.Runtime.CompilerServices;
+
+namespace Jellyfin.Data.Entities
+{
+   public partial class CustomItem: global::Jellyfin.Data.Entities.LibraryItem
+   {
+      partial void Init();
+
+      /// <summary>
+      /// Default constructor. Protected due to required properties, but present because EF needs it.
+      /// </summary>
+      protected CustomItem(): base()
+      {
+         CustomItemMetadata = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.CustomItemMetadata>();
+         Releases = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.Release>();
+
+         Init();
+      }
+
+      /// <summary>
+      /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving.
+      /// </summary>
+      public static CustomItem CreateCustomItemUnsafe()
+      {
+         return new CustomItem();
+      }
+
+      /// <summary>
+      /// Public constructor with required data
+      /// </summary>
+      /// <param name="urlid">This is whats gets displayed in the Urls and API requests. This could also be a string.</param>
+      public CustomItem(Guid urlid, DateTime dateadded)
+      {
+         this.UrlId = urlid;
+
+         this.CustomItemMetadata = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.CustomItemMetadata>();
+         this.Releases = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.Release>();
+
+         Init();
+      }
+
+      /// <summary>
+      /// Static create function (for use in LINQ queries, etc.)
+      /// </summary>
+      /// <param name="urlid">This is whats gets displayed in the Urls and API requests. This could also be a string.</param>
+      public static CustomItem Create(Guid urlid, DateTime dateadded)
+      {
+         return new CustomItem(urlid, dateadded);
+      }
+
+      /*************************************************************************
+       * Properties
+       *************************************************************************/
+
+      /*************************************************************************
+       * Navigation properties
+       *************************************************************************/
+
+      public virtual ICollection<global::Jellyfin.Data.Entities.CustomItemMetadata> CustomItemMetadata { get; protected set; }
+
+      public virtual ICollection<global::Jellyfin.Data.Entities.Release> Releases { get; protected set; }
+
+   }
+}
+

+ 86 - 0
Jellyfin.Data/Entities/CustomItemMetadata.cs

@@ -0,0 +1,86 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated from a template.
+//
+//     Manual changes to this file may cause unexpected behavior in your application.
+//     Manual changes to this file will be overwritten if the code is regenerated.
+//
+//     Produced by Entity Framework Visual Editor
+//     https://github.com/msawczyn/EFDesigner
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Linq;
+using System.Runtime.CompilerServices;
+
+namespace Jellyfin.Data.Entities
+{
+   public partial class CustomItemMetadata: global::Jellyfin.Data.Entities.Metadata
+   {
+      partial void Init();
+
+      /// <summary>
+      /// Default constructor. Protected due to required properties, but present because EF needs it.
+      /// </summary>
+      protected CustomItemMetadata(): base()
+      {
+         Init();
+      }
+
+      /// <summary>
+      /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving.
+      /// </summary>
+      public static CustomItemMetadata CreateCustomItemMetadataUnsafe()
+      {
+         return new CustomItemMetadata();
+      }
+
+      /// <summary>
+      /// Public constructor with required data
+      /// </summary>
+      /// <param name="title">The title or name of the object</param>
+      /// <param name="language">ISO-639-3 3-character language codes</param>
+      /// <param name="_customitem0"></param>
+      public CustomItemMetadata(string title, string language, DateTime dateadded, DateTime datemodified, global::Jellyfin.Data.Entities.CustomItem _customitem0)
+      {
+         if (string.IsNullOrEmpty(title)) throw new ArgumentNullException(nameof(title));
+         this.Title = title;
+
+         if (string.IsNullOrEmpty(language)) throw new ArgumentNullException(nameof(language));
+         this.Language = language;
+
+         if (_customitem0 == null) throw new ArgumentNullException(nameof(_customitem0));
+         _customitem0.CustomItemMetadata.Add(this);
+
+
+         Init();
+      }
+
+      /// <summary>
+      /// Static create function (for use in LINQ queries, etc.)
+      /// </summary>
+      /// <param name="title">The title or name of the object</param>
+      /// <param name="language">ISO-639-3 3-character language codes</param>
+      /// <param name="_customitem0"></param>
+      public static CustomItemMetadata Create(string title, string language, DateTime dateadded, DateTime datemodified, global::Jellyfin.Data.Entities.CustomItem _customitem0)
+      {
+         return new CustomItemMetadata(title, language, dateadded, datemodified, _customitem0);
+      }
+
+      /*************************************************************************
+       * Properties
+       *************************************************************************/
+
+      /*************************************************************************
+       * Navigation properties
+       *************************************************************************/
+
+   }
+}
+

+ 127 - 0
Jellyfin.Data/Entities/Episode.cs

@@ -0,0 +1,127 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated from a template.
+//
+//     Manual changes to this file may cause unexpected behavior in your application.
+//     Manual changes to this file will be overwritten if the code is regenerated.
+//
+//     Produced by Entity Framework Visual Editor
+//     https://github.com/msawczyn/EFDesigner
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Linq;
+using System.Runtime.CompilerServices;
+
+namespace Jellyfin.Data.Entities
+{
+   public partial class Episode: global::Jellyfin.Data.Entities.LibraryItem
+   {
+      partial void Init();
+
+      /// <summary>
+      /// Default constructor. Protected due to required properties, but present because EF needs it.
+      /// </summary>
+      protected Episode(): base()
+      {
+         // NOTE: This class has one-to-one associations with LibraryRoot, LibraryItem and CollectionItem.
+         // One-to-one associations are not validated in constructors since this causes a scenario where each one must be constructed before the other.
+
+         Releases = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.Release>();
+         EpisodeMetadata = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.EpisodeMetadata>();
+
+         Init();
+      }
+
+      /// <summary>
+      /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving.
+      /// </summary>
+      public static Episode CreateEpisodeUnsafe()
+      {
+         return new Episode();
+      }
+
+      /// <summary>
+      /// Public constructor with required data
+      /// </summary>
+      /// <param name="urlid">This is whats gets displayed in the Urls and API requests. This could also be a string.</param>
+      /// <param name="_season0"></param>
+      public Episode(Guid urlid, DateTime dateadded, global::Jellyfin.Data.Entities.Season _season0)
+      {
+         // NOTE: This class has one-to-one associations with LibraryRoot, LibraryItem and CollectionItem.
+         // One-to-one associations are not validated in constructors since this causes a scenario where each one must be constructed before the other.
+
+         this.UrlId = urlid;
+
+         if (_season0 == null) throw new ArgumentNullException(nameof(_season0));
+         _season0.Episodes.Add(this);
+
+         this.Releases = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.Release>();
+         this.EpisodeMetadata = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.EpisodeMetadata>();
+
+         Init();
+      }
+
+      /// <summary>
+      /// Static create function (for use in LINQ queries, etc.)
+      /// </summary>
+      /// <param name="urlid">This is whats gets displayed in the Urls and API requests. This could also be a string.</param>
+      /// <param name="_season0"></param>
+      public static Episode Create(Guid urlid, DateTime dateadded, global::Jellyfin.Data.Entities.Season _season0)
+      {
+         return new Episode(urlid, dateadded, _season0);
+      }
+
+      /*************************************************************************
+       * Properties
+       *************************************************************************/
+
+      /// <summary>
+      /// Backing field for EpisodeNumber
+      /// </summary>
+      protected int? _EpisodeNumber;
+      /// <summary>
+      /// When provided in a partial class, allows value of EpisodeNumber to be changed before setting.
+      /// </summary>
+      partial void SetEpisodeNumber(int? oldValue, ref int? newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of EpisodeNumber to be changed before returning.
+      /// </summary>
+      partial void GetEpisodeNumber(ref int? result);
+
+      public int? EpisodeNumber
+      {
+         get
+         {
+            int? value = _EpisodeNumber;
+            GetEpisodeNumber(ref value);
+            return (_EpisodeNumber = value);
+         }
+         set
+         {
+            int? oldValue = _EpisodeNumber;
+            SetEpisodeNumber(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _EpisodeNumber = value;
+            }
+         }
+      }
+
+      /*************************************************************************
+       * Navigation properties
+       *************************************************************************/
+
+      public virtual ICollection<global::Jellyfin.Data.Entities.Release> Releases { get; protected set; }
+
+      public virtual ICollection<global::Jellyfin.Data.Entities.EpisodeMetadata> EpisodeMetadata { get; protected set; }
+
+   }
+}
+

+ 197 - 0
Jellyfin.Data/Entities/EpisodeMetadata.cs

@@ -0,0 +1,197 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated from a template.
+//
+//     Manual changes to this file may cause unexpected behavior in your application.
+//     Manual changes to this file will be overwritten if the code is regenerated.
+//
+//     Produced by Entity Framework Visual Editor
+//     https://github.com/msawczyn/EFDesigner
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Linq;
+using System.Runtime.CompilerServices;
+
+namespace Jellyfin.Data.Entities
+{
+   public partial class EpisodeMetadata: global::Jellyfin.Data.Entities.Metadata
+   {
+      partial void Init();
+
+      /// <summary>
+      /// Default constructor. Protected due to required properties, but present because EF needs it.
+      /// </summary>
+      protected EpisodeMetadata(): base()
+      {
+         Init();
+      }
+
+      /// <summary>
+      /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving.
+      /// </summary>
+      public static EpisodeMetadata CreateEpisodeMetadataUnsafe()
+      {
+         return new EpisodeMetadata();
+      }
+
+      /// <summary>
+      /// Public constructor with required data
+      /// </summary>
+      /// <param name="title">The title or name of the object</param>
+      /// <param name="language">ISO-639-3 3-character language codes</param>
+      /// <param name="_episode0"></param>
+      public EpisodeMetadata(string title, string language, DateTime dateadded, DateTime datemodified, global::Jellyfin.Data.Entities.Episode _episode0)
+      {
+         if (string.IsNullOrEmpty(title)) throw new ArgumentNullException(nameof(title));
+         this.Title = title;
+
+         if (string.IsNullOrEmpty(language)) throw new ArgumentNullException(nameof(language));
+         this.Language = language;
+
+         if (_episode0 == null) throw new ArgumentNullException(nameof(_episode0));
+         _episode0.EpisodeMetadata.Add(this);
+
+
+         Init();
+      }
+
+      /// <summary>
+      /// Static create function (for use in LINQ queries, etc.)
+      /// </summary>
+      /// <param name="title">The title or name of the object</param>
+      /// <param name="language">ISO-639-3 3-character language codes</param>
+      /// <param name="_episode0"></param>
+      public static EpisodeMetadata Create(string title, string language, DateTime dateadded, DateTime datemodified, global::Jellyfin.Data.Entities.Episode _episode0)
+      {
+         return new EpisodeMetadata(title, language, dateadded, datemodified, _episode0);
+      }
+
+      /*************************************************************************
+       * Properties
+       *************************************************************************/
+
+      /// <summary>
+      /// Backing field for Outline
+      /// </summary>
+      protected string _Outline;
+      /// <summary>
+      /// When provided in a partial class, allows value of Outline to be changed before setting.
+      /// </summary>
+      partial void SetOutline(string oldValue, ref string newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Outline to be changed before returning.
+      /// </summary>
+      partial void GetOutline(ref string result);
+
+      /// <summary>
+      /// Max length = 1024
+      /// </summary>
+      [MaxLength(1024)]
+      [StringLength(1024)]
+      public string Outline
+      {
+         get
+         {
+            string value = _Outline;
+            GetOutline(ref value);
+            return (_Outline = value);
+         }
+         set
+         {
+            string oldValue = _Outline;
+            SetOutline(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Outline = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Backing field for Plot
+      /// </summary>
+      protected string _Plot;
+      /// <summary>
+      /// When provided in a partial class, allows value of Plot to be changed before setting.
+      /// </summary>
+      partial void SetPlot(string oldValue, ref string newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Plot to be changed before returning.
+      /// </summary>
+      partial void GetPlot(ref string result);
+
+      /// <summary>
+      /// Max length = 65535
+      /// </summary>
+      [MaxLength(65535)]
+      [StringLength(65535)]
+      public string Plot
+      {
+         get
+         {
+            string value = _Plot;
+            GetPlot(ref value);
+            return (_Plot = value);
+         }
+         set
+         {
+            string oldValue = _Plot;
+            SetPlot(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Plot = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Backing field for Tagline
+      /// </summary>
+      protected string _Tagline;
+      /// <summary>
+      /// When provided in a partial class, allows value of Tagline to be changed before setting.
+      /// </summary>
+      partial void SetTagline(string oldValue, ref string newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Tagline to be changed before returning.
+      /// </summary>
+      partial void GetTagline(ref string result);
+
+      /// <summary>
+      /// Max length = 1024
+      /// </summary>
+      [MaxLength(1024)]
+      [StringLength(1024)]
+      public string Tagline
+      {
+         get
+         {
+            string value = _Tagline;
+            GetTagline(ref value);
+            return (_Tagline = value);
+         }
+         set
+         {
+            string oldValue = _Tagline;
+            SetTagline(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Tagline = value;
+            }
+         }
+      }
+
+      /*************************************************************************
+       * Navigation properties
+       *************************************************************************/
+
+   }
+}
+

+ 163 - 0
Jellyfin.Data/Entities/Genre.cs

@@ -0,0 +1,163 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated from a template.
+//
+//     Manual changes to this file may cause unexpected behavior in your application.
+//     Manual changes to this file will be overwritten if the code is regenerated.
+//
+//     Produced by Entity Framework Visual Editor
+//     https://github.com/msawczyn/EFDesigner
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Linq;
+using System.Runtime.CompilerServices;
+
+namespace Jellyfin.Data.Entities
+{
+   public partial class Genre
+   {
+      partial void Init();
+
+      /// <summary>
+      /// Default constructor. Protected due to required properties, but present because EF needs it.
+      /// </summary>
+      protected Genre()
+      {
+         Init();
+      }
+
+      /// <summary>
+      /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving.
+      /// </summary>
+      public static Genre CreateGenreUnsafe()
+      {
+         return new Genre();
+      }
+
+      /// <summary>
+      /// Public constructor with required data
+      /// </summary>
+      /// <param name="name"></param>
+      /// <param name="_metadata0"></param>
+      public Genre(string name, global::Jellyfin.Data.Entities.Metadata _metadata0)
+      {
+         if (string.IsNullOrEmpty(name)) throw new ArgumentNullException(nameof(name));
+         this.Name = name;
+
+         if (_metadata0 == null) throw new ArgumentNullException(nameof(_metadata0));
+         _metadata0.Genres.Add(this);
+
+
+         Init();
+      }
+
+      /// <summary>
+      /// Static create function (for use in LINQ queries, etc.)
+      /// </summary>
+      /// <param name="name"></param>
+      /// <param name="_metadata0"></param>
+      public static Genre Create(string name, global::Jellyfin.Data.Entities.Metadata _metadata0)
+      {
+         return new Genre(name, _metadata0);
+      }
+
+      /*************************************************************************
+       * Properties
+       *************************************************************************/
+
+      /// <summary>
+      /// Backing field for Id
+      /// </summary>
+      internal int _Id;
+      /// <summary>
+      /// When provided in a partial class, allows value of Id to be changed before setting.
+      /// </summary>
+      partial void SetId(int oldValue, ref int newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Id to be changed before returning.
+      /// </summary>
+      partial void GetId(ref int result);
+
+      /// <summary>
+      /// Identity, Indexed, Required
+      /// </summary>
+      [Key]
+      [Required]
+      public int Id
+      {
+         get
+         {
+            int value = _Id;
+            GetId(ref value);
+            return (_Id = value);
+         }
+         protected set
+         {
+            int oldValue = _Id;
+            SetId(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Id = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Backing field for Name
+      /// </summary>
+      internal string _Name;
+      /// <summary>
+      /// When provided in a partial class, allows value of Name to be changed before setting.
+      /// </summary>
+      partial void SetName(string oldValue, ref string newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Name to be changed before returning.
+      /// </summary>
+      partial void GetName(ref string result);
+
+      /// <summary>
+      /// Indexed, Required, Max length = 255
+      /// </summary>
+      [Required]
+      [MaxLength(255)]
+      [StringLength(255)]
+      public string Name
+      {
+         get
+         {
+            string value = _Name;
+            GetName(ref value);
+            return (_Name = value);
+         }
+         set
+         {
+            string oldValue = _Name;
+            SetName(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Name = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Required
+      /// </summary>
+      [ConcurrencyCheck]
+      [Required]
+      public byte[] Timestamp { get; set; }
+
+      /*************************************************************************
+       * Navigation properties
+       *************************************************************************/
+
+   }
+}
+

+ 115 - 0
Jellyfin.Data/Entities/Group.cs

@@ -0,0 +1,115 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated from a template.
+//
+//     Manual changes to this file may cause unexpected behavior in your application.
+//     Manual changes to this file will be overwritten if the code is regenerated.
+//
+//     Produced by Entity Framework Visual Editor
+//     https://github.com/msawczyn/EFDesigner
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Linq;
+using System.Runtime.CompilerServices;
+
+namespace Jellyfin.Data.Entities
+{
+   public partial class Group
+   {
+      partial void Init();
+
+      /// <summary>
+      /// Default constructor. Protected due to required properties, but present because EF needs it.
+      /// </summary>
+      protected Group()
+      {
+         GroupPermissions = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.Permission>();
+         ProviderMappings = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.ProviderMapping>();
+         Preferences = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.Preference>();
+
+         Init();
+      }
+
+      /// <summary>
+      /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving.
+      /// </summary>
+      public static Group CreateGroupUnsafe()
+      {
+         return new Group();
+      }
+
+      /// <summary>
+      /// Public constructor with required data
+      /// </summary>
+      /// <param name="name"></param>
+      /// <param name="_user0"></param>
+      public Group(string name, global::Jellyfin.Data.Entities.User _user0)
+      {
+         if (string.IsNullOrEmpty(name)) throw new ArgumentNullException(nameof(name));
+         this.Name = name;
+
+         if (_user0 == null) throw new ArgumentNullException(nameof(_user0));
+         _user0.Groups.Add(this);
+
+         this.GroupPermissions = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.Permission>();
+         this.ProviderMappings = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.ProviderMapping>();
+         this.Preferences = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.Preference>();
+
+         Init();
+      }
+
+      /// <summary>
+      /// Static create function (for use in LINQ queries, etc.)
+      /// </summary>
+      /// <param name="name"></param>
+      /// <param name="_user0"></param>
+      public static Group Create(string name, global::Jellyfin.Data.Entities.User _user0)
+      {
+         return new Group(name, _user0);
+      }
+
+      /*************************************************************************
+       * Properties
+       *************************************************************************/
+
+      /// <summary>
+      /// Identity, Indexed, Required
+      /// </summary>
+      [Key]
+      [Required]
+      public int Id { get; protected set; }
+
+      /// <summary>
+      /// Required, Max length = 255
+      /// </summary>
+      [Required]
+      [MaxLength(255)]
+      [StringLength(255)]
+      public string Name { get; set; }
+
+      /// <summary>
+      /// Concurrency token
+      /// </summary>
+      [Timestamp]
+      public Byte[] Timestamp { get; set; }
+
+      /*************************************************************************
+       * Navigation properties
+       *************************************************************************/
+
+      public virtual ICollection<global::Jellyfin.Data.Entities.Permission> GroupPermissions { get; protected set; }
+
+      public virtual ICollection<global::Jellyfin.Data.Entities.ProviderMapping> ProviderMappings { get; protected set; }
+
+      public virtual ICollection<global::Jellyfin.Data.Entities.Preference> Preferences { get; protected set; }
+
+   }
+}
+

+ 158 - 0
Jellyfin.Data/Entities/Library.cs

@@ -0,0 +1,158 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated from a template.
+//
+//     Manual changes to this file may cause unexpected behavior in your application.
+//     Manual changes to this file will be overwritten if the code is regenerated.
+//
+//     Produced by Entity Framework Visual Editor
+//     https://github.com/msawczyn/EFDesigner
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Linq;
+using System.Runtime.CompilerServices;
+
+namespace Jellyfin.Data.Entities
+{
+   public partial class Library
+   {
+      partial void Init();
+
+      /// <summary>
+      /// Default constructor. Protected due to required properties, but present because EF needs it.
+      /// </summary>
+      protected Library()
+      {
+         Init();
+      }
+
+      /// <summary>
+      /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving.
+      /// </summary>
+      public static Library CreateLibraryUnsafe()
+      {
+         return new Library();
+      }
+
+      /// <summary>
+      /// Public constructor with required data
+      /// </summary>
+      /// <param name="name"></param>
+      public Library(string name)
+      {
+         if (string.IsNullOrEmpty(name)) throw new ArgumentNullException(nameof(name));
+         this.Name = name;
+
+
+         Init();
+      }
+
+      /// <summary>
+      /// Static create function (for use in LINQ queries, etc.)
+      /// </summary>
+      /// <param name="name"></param>
+      public static Library Create(string name)
+      {
+         return new Library(name);
+      }
+
+      /*************************************************************************
+       * Properties
+       *************************************************************************/
+
+      /// <summary>
+      /// Backing field for Id
+      /// </summary>
+      internal int _Id;
+      /// <summary>
+      /// When provided in a partial class, allows value of Id to be changed before setting.
+      /// </summary>
+      partial void SetId(int oldValue, ref int newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Id to be changed before returning.
+      /// </summary>
+      partial void GetId(ref int result);
+
+      /// <summary>
+      /// Identity, Indexed, Required
+      /// </summary>
+      [Key]
+      [Required]
+      public int Id
+      {
+         get
+         {
+            int value = _Id;
+            GetId(ref value);
+            return (_Id = value);
+         }
+         protected set
+         {
+            int oldValue = _Id;
+            SetId(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Id = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Backing field for Name
+      /// </summary>
+      protected string _Name;
+      /// <summary>
+      /// When provided in a partial class, allows value of Name to be changed before setting.
+      /// </summary>
+      partial void SetName(string oldValue, ref string newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Name to be changed before returning.
+      /// </summary>
+      partial void GetName(ref string result);
+
+      /// <summary>
+      /// Required, Max length = 1024
+      /// </summary>
+      [Required]
+      [MaxLength(1024)]
+      [StringLength(1024)]
+      public string Name
+      {
+         get
+         {
+            string value = _Name;
+            GetName(ref value);
+            return (_Name = value);
+         }
+         set
+         {
+            string oldValue = _Name;
+            SetName(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Name = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Required
+      /// </summary>
+      [ConcurrencyCheck]
+      [Required]
+      public byte[] Timestamp { get; set; }
+
+      /*************************************************************************
+       * Navigation properties
+       *************************************************************************/
+
+   }
+}
+

+ 180 - 0
Jellyfin.Data/Entities/LibraryItem.cs

@@ -0,0 +1,180 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated from a template.
+//
+//     Manual changes to this file may cause unexpected behavior in your application.
+//     Manual changes to this file will be overwritten if the code is regenerated.
+//
+//     Produced by Entity Framework Visual Editor
+//     https://github.com/msawczyn/EFDesigner
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Linq;
+using System.Runtime.CompilerServices;
+
+namespace Jellyfin.Data.Entities
+{
+   public abstract partial class LibraryItem
+   {
+      partial void Init();
+
+      /// <summary>
+      /// Default constructor. Protected due to being abstract.
+      /// </summary>
+      protected LibraryItem()
+      {
+         Init();
+      }
+
+      /// <summary>
+      /// Public constructor with required data
+      /// </summary>
+      /// <param name="urlid">This is whats gets displayed in the Urls and API requests. This could also be a string.</param>
+      protected LibraryItem(Guid urlid, DateTime dateadded)
+      {
+         this.UrlId = urlid;
+
+
+         Init();
+      }
+
+      /*************************************************************************
+       * Properties
+       *************************************************************************/
+
+      /// <summary>
+      /// Backing field for Id
+      /// </summary>
+      internal int _Id;
+      /// <summary>
+      /// When provided in a partial class, allows value of Id to be changed before setting.
+      /// </summary>
+      partial void SetId(int oldValue, ref int newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Id to be changed before returning.
+      /// </summary>
+      partial void GetId(ref int result);
+
+      /// <summary>
+      /// Identity, Indexed, Required
+      /// </summary>
+      [Key]
+      [Required]
+      public int Id
+      {
+         get
+         {
+            int value = _Id;
+            GetId(ref value);
+            return (_Id = value);
+         }
+         protected set
+         {
+            int oldValue = _Id;
+            SetId(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Id = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Backing field for UrlId
+      /// </summary>
+      internal Guid _UrlId;
+      /// <summary>
+      /// When provided in a partial class, allows value of UrlId to be changed before setting.
+      /// </summary>
+      partial void SetUrlId(Guid oldValue, ref Guid newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of UrlId to be changed before returning.
+      /// </summary>
+      partial void GetUrlId(ref Guid result);
+
+      /// <summary>
+      /// Indexed, Required
+      /// This is whats gets displayed in the Urls and API requests. This could also be a string.
+      /// </summary>
+      [Required]
+      public Guid UrlId
+      {
+         get
+         {
+            Guid value = _UrlId;
+            GetUrlId(ref value);
+            return (_UrlId = value);
+         }
+         set
+         {
+            Guid oldValue = _UrlId;
+            SetUrlId(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _UrlId = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Backing field for DateAdded
+      /// </summary>
+      protected DateTime _DateAdded;
+      /// <summary>
+      /// When provided in a partial class, allows value of DateAdded to be changed before setting.
+      /// </summary>
+      partial void SetDateAdded(DateTime oldValue, ref DateTime newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of DateAdded to be changed before returning.
+      /// </summary>
+      partial void GetDateAdded(ref DateTime result);
+
+      /// <summary>
+      /// Required
+      /// </summary>
+      [Required]
+      public DateTime DateAdded
+      {
+         get
+         {
+            DateTime value = _DateAdded;
+            GetDateAdded(ref value);
+            return (_DateAdded = value);
+         }
+         internal set
+         {
+            DateTime oldValue = _DateAdded;
+            SetDateAdded(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _DateAdded = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Required
+      /// </summary>
+      [ConcurrencyCheck]
+      [Required]
+      public byte[] Timestamp { get; set; }
+
+      /*************************************************************************
+       * Navigation properties
+       *************************************************************************/
+
+      /// <summary>
+      /// Required
+      /// </summary>
+      public virtual global::Jellyfin.Data.Entities.LibraryRoot LibraryRoot { get; set; }
+
+   }
+}
+

+ 202 - 0
Jellyfin.Data/Entities/LibraryRoot.cs

@@ -0,0 +1,202 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated from a template.
+//
+//     Manual changes to this file may cause unexpected behavior in your application.
+//     Manual changes to this file will be overwritten if the code is regenerated.
+//
+//     Produced by Entity Framework Visual Editor
+//     https://github.com/msawczyn/EFDesigner
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Linq;
+using System.Runtime.CompilerServices;
+
+namespace Jellyfin.Data.Entities
+{
+   public partial class LibraryRoot
+   {
+      partial void Init();
+
+      /// <summary>
+      /// Default constructor. Protected due to required properties, but present because EF needs it.
+      /// </summary>
+      protected LibraryRoot()
+      {
+         Init();
+      }
+
+      /// <summary>
+      /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving.
+      /// </summary>
+      public static LibraryRoot CreateLibraryRootUnsafe()
+      {
+         return new LibraryRoot();
+      }
+
+      /// <summary>
+      /// Public constructor with required data
+      /// </summary>
+      /// <param name="path">Absolute Path</param>
+      public LibraryRoot(string path)
+      {
+         if (string.IsNullOrEmpty(path)) throw new ArgumentNullException(nameof(path));
+         this.Path = path;
+
+
+         Init();
+      }
+
+      /// <summary>
+      /// Static create function (for use in LINQ queries, etc.)
+      /// </summary>
+      /// <param name="path">Absolute Path</param>
+      public static LibraryRoot Create(string path)
+      {
+         return new LibraryRoot(path);
+      }
+
+      /*************************************************************************
+       * Properties
+       *************************************************************************/
+
+      /// <summary>
+      /// Backing field for Id
+      /// </summary>
+      internal int _Id;
+      /// <summary>
+      /// When provided in a partial class, allows value of Id to be changed before setting.
+      /// </summary>
+      partial void SetId(int oldValue, ref int newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Id to be changed before returning.
+      /// </summary>
+      partial void GetId(ref int result);
+
+      /// <summary>
+      /// Identity, Indexed, Required
+      /// </summary>
+      [Key]
+      [Required]
+      public int Id
+      {
+         get
+         {
+            int value = _Id;
+            GetId(ref value);
+            return (_Id = value);
+         }
+         protected set
+         {
+            int oldValue = _Id;
+            SetId(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Id = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Backing field for Path
+      /// </summary>
+      protected string _Path;
+      /// <summary>
+      /// When provided in a partial class, allows value of Path to be changed before setting.
+      /// </summary>
+      partial void SetPath(string oldValue, ref string newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Path to be changed before returning.
+      /// </summary>
+      partial void GetPath(ref string result);
+
+      /// <summary>
+      /// Required, Max length = 65535
+      /// Absolute Path
+      /// </summary>
+      [Required]
+      [MaxLength(65535)]
+      [StringLength(65535)]
+      public string Path
+      {
+         get
+         {
+            string value = _Path;
+            GetPath(ref value);
+            return (_Path = value);
+         }
+         set
+         {
+            string oldValue = _Path;
+            SetPath(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Path = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Backing field for NetworkPath
+      /// </summary>
+      protected string _NetworkPath;
+      /// <summary>
+      /// When provided in a partial class, allows value of NetworkPath to be changed before setting.
+      /// </summary>
+      partial void SetNetworkPath(string oldValue, ref string newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of NetworkPath to be changed before returning.
+      /// </summary>
+      partial void GetNetworkPath(ref string result);
+
+      /// <summary>
+      /// Max length = 65535
+      /// Absolute network path, for example for transcoding sattelites.
+      /// </summary>
+      [MaxLength(65535)]
+      [StringLength(65535)]
+      public string NetworkPath
+      {
+         get
+         {
+            string value = _NetworkPath;
+            GetNetworkPath(ref value);
+            return (_NetworkPath = value);
+         }
+         set
+         {
+            string oldValue = _NetworkPath;
+            SetNetworkPath(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _NetworkPath = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Required
+      /// </summary>
+      [ConcurrencyCheck]
+      [Required]
+      public byte[] Timestamp { get; set; }
+
+      /*************************************************************************
+       * Navigation properties
+       *************************************************************************/
+
+      /// <summary>
+      /// Required
+      /// </summary>
+      public virtual global::Jellyfin.Data.Entities.Library Library { get; set; }
+
+   }
+}
+

+ 209 - 0
Jellyfin.Data/Entities/MediaFile.cs

@@ -0,0 +1,209 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated from a template.
+//
+//     Manual changes to this file may cause unexpected behavior in your application.
+//     Manual changes to this file will be overwritten if the code is regenerated.
+//
+//     Produced by Entity Framework Visual Editor
+//     https://github.com/msawczyn/EFDesigner
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Linq;
+using System.Runtime.CompilerServices;
+
+namespace Jellyfin.Data.Entities
+{
+   public partial class MediaFile
+   {
+      partial void Init();
+
+      /// <summary>
+      /// Default constructor. Protected due to required properties, but present because EF needs it.
+      /// </summary>
+      protected MediaFile()
+      {
+         MediaFileStreams = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.MediaFileStream>();
+
+         Init();
+      }
+
+      /// <summary>
+      /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving.
+      /// </summary>
+      public static MediaFile CreateMediaFileUnsafe()
+      {
+         return new MediaFile();
+      }
+
+      /// <summary>
+      /// Public constructor with required data
+      /// </summary>
+      /// <param name="path">Relative to the LibraryRoot</param>
+      /// <param name="kind"></param>
+      /// <param name="_release0"></param>
+      public MediaFile(string path, global::Jellyfin.Data.Enums.MediaFileKind kind, global::Jellyfin.Data.Entities.Release _release0)
+      {
+         if (string.IsNullOrEmpty(path)) throw new ArgumentNullException(nameof(path));
+         this.Path = path;
+
+         this.Kind = kind;
+
+         if (_release0 == null) throw new ArgumentNullException(nameof(_release0));
+         _release0.MediaFiles.Add(this);
+
+         this.MediaFileStreams = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.MediaFileStream>();
+
+         Init();
+      }
+
+      /// <summary>
+      /// Static create function (for use in LINQ queries, etc.)
+      /// </summary>
+      /// <param name="path">Relative to the LibraryRoot</param>
+      /// <param name="kind"></param>
+      /// <param name="_release0"></param>
+      public static MediaFile Create(string path, global::Jellyfin.Data.Enums.MediaFileKind kind, global::Jellyfin.Data.Entities.Release _release0)
+      {
+         return new MediaFile(path, kind, _release0);
+      }
+
+      /*************************************************************************
+       * Properties
+       *************************************************************************/
+
+      /// <summary>
+      /// Backing field for Id
+      /// </summary>
+      internal int _Id;
+      /// <summary>
+      /// When provided in a partial class, allows value of Id to be changed before setting.
+      /// </summary>
+      partial void SetId(int oldValue, ref int newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Id to be changed before returning.
+      /// </summary>
+      partial void GetId(ref int result);
+
+      /// <summary>
+      /// Identity, Indexed, Required
+      /// </summary>
+      [Key]
+      [Required]
+      public int Id
+      {
+         get
+         {
+            int value = _Id;
+            GetId(ref value);
+            return (_Id = value);
+         }
+         protected set
+         {
+            int oldValue = _Id;
+            SetId(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Id = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Backing field for Path
+      /// </summary>
+      protected string _Path;
+      /// <summary>
+      /// When provided in a partial class, allows value of Path to be changed before setting.
+      /// </summary>
+      partial void SetPath(string oldValue, ref string newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Path to be changed before returning.
+      /// </summary>
+      partial void GetPath(ref string result);
+
+      /// <summary>
+      /// Required, Max length = 65535
+      /// Relative to the LibraryRoot
+      /// </summary>
+      [Required]
+      [MaxLength(65535)]
+      [StringLength(65535)]
+      public string Path
+      {
+         get
+         {
+            string value = _Path;
+            GetPath(ref value);
+            return (_Path = value);
+         }
+         set
+         {
+            string oldValue = _Path;
+            SetPath(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Path = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Backing field for Kind
+      /// </summary>
+      protected global::Jellyfin.Data.Enums.MediaFileKind _Kind;
+      /// <summary>
+      /// When provided in a partial class, allows value of Kind to be changed before setting.
+      /// </summary>
+      partial void SetKind(global::Jellyfin.Data.Enums.MediaFileKind oldValue, ref global::Jellyfin.Data.Enums.MediaFileKind newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Kind to be changed before returning.
+      /// </summary>
+      partial void GetKind(ref global::Jellyfin.Data.Enums.MediaFileKind result);
+
+      /// <summary>
+      /// Required
+      /// </summary>
+      [Required]
+      public global::Jellyfin.Data.Enums.MediaFileKind Kind
+      {
+         get
+         {
+            global::Jellyfin.Data.Enums.MediaFileKind value = _Kind;
+            GetKind(ref value);
+            return (_Kind = value);
+         }
+         set
+         {
+            global::Jellyfin.Data.Enums.MediaFileKind oldValue = _Kind;
+            SetKind(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Kind = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Required
+      /// </summary>
+      [ConcurrencyCheck]
+      [Required]
+      public byte[] Timestamp { get; set; }
+
+      /*************************************************************************
+       * Navigation properties
+       *************************************************************************/
+
+      public virtual ICollection<global::Jellyfin.Data.Entities.MediaFileStream> MediaFileStreams { get; protected set; }
+
+   }
+}
+

+ 160 - 0
Jellyfin.Data/Entities/MediaFileStream.cs

@@ -0,0 +1,160 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated from a template.
+//
+//     Manual changes to this file may cause unexpected behavior in your application.
+//     Manual changes to this file will be overwritten if the code is regenerated.
+//
+//     Produced by Entity Framework Visual Editor
+//     https://github.com/msawczyn/EFDesigner
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Linq;
+using System.Runtime.CompilerServices;
+
+namespace Jellyfin.Data.Entities
+{
+   public partial class MediaFileStream
+   {
+      partial void Init();
+
+      /// <summary>
+      /// Default constructor. Protected due to required properties, but present because EF needs it.
+      /// </summary>
+      protected MediaFileStream()
+      {
+         Init();
+      }
+
+      /// <summary>
+      /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving.
+      /// </summary>
+      public static MediaFileStream CreateMediaFileStreamUnsafe()
+      {
+         return new MediaFileStream();
+      }
+
+      /// <summary>
+      /// Public constructor with required data
+      /// </summary>
+      /// <param name="streamnumber"></param>
+      /// <param name="_mediafile0"></param>
+      public MediaFileStream(int streamnumber, global::Jellyfin.Data.Entities.MediaFile _mediafile0)
+      {
+         this.StreamNumber = streamnumber;
+
+         if (_mediafile0 == null) throw new ArgumentNullException(nameof(_mediafile0));
+         _mediafile0.MediaFileStreams.Add(this);
+
+
+         Init();
+      }
+
+      /// <summary>
+      /// Static create function (for use in LINQ queries, etc.)
+      /// </summary>
+      /// <param name="streamnumber"></param>
+      /// <param name="_mediafile0"></param>
+      public static MediaFileStream Create(int streamnumber, global::Jellyfin.Data.Entities.MediaFile _mediafile0)
+      {
+         return new MediaFileStream(streamnumber, _mediafile0);
+      }
+
+      /*************************************************************************
+       * Properties
+       *************************************************************************/
+
+      /// <summary>
+      /// Backing field for Id
+      /// </summary>
+      internal int _Id;
+      /// <summary>
+      /// When provided in a partial class, allows value of Id to be changed before setting.
+      /// </summary>
+      partial void SetId(int oldValue, ref int newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Id to be changed before returning.
+      /// </summary>
+      partial void GetId(ref int result);
+
+      /// <summary>
+      /// Identity, Indexed, Required
+      /// </summary>
+      [Key]
+      [Required]
+      public int Id
+      {
+         get
+         {
+            int value = _Id;
+            GetId(ref value);
+            return (_Id = value);
+         }
+         protected set
+         {
+            int oldValue = _Id;
+            SetId(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Id = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Backing field for StreamNumber
+      /// </summary>
+      protected int _StreamNumber;
+      /// <summary>
+      /// When provided in a partial class, allows value of StreamNumber to be changed before setting.
+      /// </summary>
+      partial void SetStreamNumber(int oldValue, ref int newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of StreamNumber to be changed before returning.
+      /// </summary>
+      partial void GetStreamNumber(ref int result);
+
+      /// <summary>
+      /// Required
+      /// </summary>
+      [Required]
+      public int StreamNumber
+      {
+         get
+         {
+            int value = _StreamNumber;
+            GetStreamNumber(ref value);
+            return (_StreamNumber = value);
+         }
+         set
+         {
+            int oldValue = _StreamNumber;
+            SetStreamNumber(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _StreamNumber = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Required
+      /// </summary>
+      [ConcurrencyCheck]
+      [Required]
+      public byte[] Timestamp { get; set; }
+
+      /*************************************************************************
+       * Navigation properties
+       *************************************************************************/
+
+   }
+}
+

+ 385 - 0
Jellyfin.Data/Entities/Metadata.cs

@@ -0,0 +1,385 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated from a template.
+//
+//     Manual changes to this file may cause unexpected behavior in your application.
+//     Manual changes to this file will be overwritten if the code is regenerated.
+//
+//     Produced by Entity Framework Visual Editor
+//     https://github.com/msawczyn/EFDesigner
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Linq;
+using System.Runtime.CompilerServices;
+
+namespace Jellyfin.Data.Entities
+{
+   public abstract partial class Metadata
+   {
+      partial void Init();
+
+      /// <summary>
+      /// Default constructor. Protected due to being abstract.
+      /// </summary>
+      protected Metadata()
+      {
+         PersonRoles = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.PersonRole>();
+         Genres = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.Genre>();
+         Artwork = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.Artwork>();
+         Ratings = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.Rating>();
+         Sources = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.MetadataProviderId>();
+
+         Init();
+      }
+
+      /// <summary>
+      /// Public constructor with required data
+      /// </summary>
+      /// <param name="title">The title or name of the object</param>
+      /// <param name="language">ISO-639-3 3-character language codes</param>
+      protected Metadata(string title, string language, DateTime dateadded, DateTime datemodified)
+      {
+         if (string.IsNullOrEmpty(title)) throw new ArgumentNullException(nameof(title));
+         this.Title = title;
+
+         if (string.IsNullOrEmpty(language)) throw new ArgumentNullException(nameof(language));
+         this.Language = language;
+
+         this.PersonRoles = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.PersonRole>();
+         this.Genres = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.Genre>();
+         this.Artwork = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.Artwork>();
+         this.Ratings = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.Rating>();
+         this.Sources = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.MetadataProviderId>();
+
+         Init();
+      }
+
+      /*************************************************************************
+       * Properties
+       *************************************************************************/
+
+      /// <summary>
+      /// Backing field for Id
+      /// </summary>
+      internal int _Id;
+      /// <summary>
+      /// When provided in a partial class, allows value of Id to be changed before setting.
+      /// </summary>
+      partial void SetId(int oldValue, ref int newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Id to be changed before returning.
+      /// </summary>
+      partial void GetId(ref int result);
+
+      /// <summary>
+      /// Identity, Indexed, Required
+      /// </summary>
+      [Key]
+      [Required]
+      public int Id
+      {
+         get
+         {
+            int value = _Id;
+            GetId(ref value);
+            return (_Id = value);
+         }
+         protected set
+         {
+            int oldValue = _Id;
+            SetId(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Id = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Backing field for Title
+      /// </summary>
+      protected string _Title;
+      /// <summary>
+      /// When provided in a partial class, allows value of Title to be changed before setting.
+      /// </summary>
+      partial void SetTitle(string oldValue, ref string newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Title to be changed before returning.
+      /// </summary>
+      partial void GetTitle(ref string result);
+
+      /// <summary>
+      /// Required, Max length = 1024
+      /// The title or name of the object
+      /// </summary>
+      [Required]
+      [MaxLength(1024)]
+      [StringLength(1024)]
+      public string Title
+      {
+         get
+         {
+            string value = _Title;
+            GetTitle(ref value);
+            return (_Title = value);
+         }
+         set
+         {
+            string oldValue = _Title;
+            SetTitle(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Title = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Backing field for OriginalTitle
+      /// </summary>
+      protected string _OriginalTitle;
+      /// <summary>
+      /// When provided in a partial class, allows value of OriginalTitle to be changed before setting.
+      /// </summary>
+      partial void SetOriginalTitle(string oldValue, ref string newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of OriginalTitle to be changed before returning.
+      /// </summary>
+      partial void GetOriginalTitle(ref string result);
+
+      /// <summary>
+      /// Max length = 1024
+      /// </summary>
+      [MaxLength(1024)]
+      [StringLength(1024)]
+      public string OriginalTitle
+      {
+         get
+         {
+            string value = _OriginalTitle;
+            GetOriginalTitle(ref value);
+            return (_OriginalTitle = value);
+         }
+         set
+         {
+            string oldValue = _OriginalTitle;
+            SetOriginalTitle(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _OriginalTitle = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Backing field for SortTitle
+      /// </summary>
+      protected string _SortTitle;
+      /// <summary>
+      /// When provided in a partial class, allows value of SortTitle to be changed before setting.
+      /// </summary>
+      partial void SetSortTitle(string oldValue, ref string newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of SortTitle to be changed before returning.
+      /// </summary>
+      partial void GetSortTitle(ref string result);
+
+      /// <summary>
+      /// Max length = 1024
+      /// </summary>
+      [MaxLength(1024)]
+      [StringLength(1024)]
+      public string SortTitle
+      {
+         get
+         {
+            string value = _SortTitle;
+            GetSortTitle(ref value);
+            return (_SortTitle = value);
+         }
+         set
+         {
+            string oldValue = _SortTitle;
+            SetSortTitle(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _SortTitle = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Backing field for Language
+      /// </summary>
+      protected string _Language;
+      /// <summary>
+      /// When provided in a partial class, allows value of Language to be changed before setting.
+      /// </summary>
+      partial void SetLanguage(string oldValue, ref string newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Language to be changed before returning.
+      /// </summary>
+      partial void GetLanguage(ref string result);
+
+      /// <summary>
+      /// Required, Min length = 3, Max length = 3
+      /// ISO-639-3 3-character language codes
+      /// </summary>
+      [Required]
+      [MinLength(3)]
+      [MaxLength(3)]
+      [StringLength(3)]
+      public string Language
+      {
+         get
+         {
+            string value = _Language;
+            GetLanguage(ref value);
+            return (_Language = value);
+         }
+         set
+         {
+            string oldValue = _Language;
+            SetLanguage(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Language = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Backing field for ReleaseDate
+      /// </summary>
+      protected DateTimeOffset? _ReleaseDate;
+      /// <summary>
+      /// When provided in a partial class, allows value of ReleaseDate to be changed before setting.
+      /// </summary>
+      partial void SetReleaseDate(DateTimeOffset? oldValue, ref DateTimeOffset? newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of ReleaseDate to be changed before returning.
+      /// </summary>
+      partial void GetReleaseDate(ref DateTimeOffset? result);
+
+      public DateTimeOffset? ReleaseDate
+      {
+         get
+         {
+            DateTimeOffset? value = _ReleaseDate;
+            GetReleaseDate(ref value);
+            return (_ReleaseDate = value);
+         }
+         set
+         {
+            DateTimeOffset? oldValue = _ReleaseDate;
+            SetReleaseDate(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _ReleaseDate = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Backing field for DateAdded
+      /// </summary>
+      protected DateTime _DateAdded;
+      /// <summary>
+      /// When provided in a partial class, allows value of DateAdded to be changed before setting.
+      /// </summary>
+      partial void SetDateAdded(DateTime oldValue, ref DateTime newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of DateAdded to be changed before returning.
+      /// </summary>
+      partial void GetDateAdded(ref DateTime result);
+
+      /// <summary>
+      /// Required
+      /// </summary>
+      [Required]
+      public DateTime DateAdded
+      {
+         get
+         {
+            DateTime value = _DateAdded;
+            GetDateAdded(ref value);
+            return (_DateAdded = value);
+         }
+         internal set
+         {
+            DateTime oldValue = _DateAdded;
+            SetDateAdded(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _DateAdded = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Backing field for DateModified
+      /// </summary>
+      protected DateTime _DateModified;
+      /// <summary>
+      /// When provided in a partial class, allows value of DateModified to be changed before setting.
+      /// </summary>
+      partial void SetDateModified(DateTime oldValue, ref DateTime newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of DateModified to be changed before returning.
+      /// </summary>
+      partial void GetDateModified(ref DateTime result);
+
+      /// <summary>
+      /// Required
+      /// </summary>
+      [Required]
+      public DateTime DateModified
+      {
+         get
+         {
+            DateTime value = _DateModified;
+            GetDateModified(ref value);
+            return (_DateModified = value);
+         }
+         internal set
+         {
+            DateTime oldValue = _DateModified;
+            SetDateModified(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _DateModified = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Required
+      /// </summary>
+      [ConcurrencyCheck]
+      [Required]
+      public byte[] Timestamp { get; set; }
+
+      /*************************************************************************
+       * Navigation properties
+       *************************************************************************/
+
+      public virtual ICollection<global::Jellyfin.Data.Entities.PersonRole> PersonRoles { get; protected set; }
+
+      public virtual ICollection<global::Jellyfin.Data.Entities.Genre> Genres { get; protected set; }
+
+      public virtual ICollection<global::Jellyfin.Data.Entities.Artwork> Artwork { get; protected set; }
+
+      public virtual ICollection<global::Jellyfin.Data.Entities.Rating> Ratings { get; protected set; }
+
+      public virtual ICollection<global::Jellyfin.Data.Entities.MetadataProviderId> Sources { get; protected set; }
+
+   }
+}
+

+ 158 - 0
Jellyfin.Data/Entities/MetadataProvider.cs

@@ -0,0 +1,158 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated from a template.
+//
+//     Manual changes to this file may cause unexpected behavior in your application.
+//     Manual changes to this file will be overwritten if the code is regenerated.
+//
+//     Produced by Entity Framework Visual Editor
+//     https://github.com/msawczyn/EFDesigner
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Linq;
+using System.Runtime.CompilerServices;
+
+namespace Jellyfin.Data.Entities
+{
+   public partial class MetadataProvider
+   {
+      partial void Init();
+
+      /// <summary>
+      /// Default constructor. Protected due to required properties, but present because EF needs it.
+      /// </summary>
+      protected MetadataProvider()
+      {
+         Init();
+      }
+
+      /// <summary>
+      /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving.
+      /// </summary>
+      public static MetadataProvider CreateMetadataProviderUnsafe()
+      {
+         return new MetadataProvider();
+      }
+
+      /// <summary>
+      /// Public constructor with required data
+      /// </summary>
+      /// <param name="name"></param>
+      public MetadataProvider(string name)
+      {
+         if (string.IsNullOrEmpty(name)) throw new ArgumentNullException(nameof(name));
+         this.Name = name;
+
+
+         Init();
+      }
+
+      /// <summary>
+      /// Static create function (for use in LINQ queries, etc.)
+      /// </summary>
+      /// <param name="name"></param>
+      public static MetadataProvider Create(string name)
+      {
+         return new MetadataProvider(name);
+      }
+
+      /*************************************************************************
+       * Properties
+       *************************************************************************/
+
+      /// <summary>
+      /// Backing field for Id
+      /// </summary>
+      internal int _Id;
+      /// <summary>
+      /// When provided in a partial class, allows value of Id to be changed before setting.
+      /// </summary>
+      partial void SetId(int oldValue, ref int newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Id to be changed before returning.
+      /// </summary>
+      partial void GetId(ref int result);
+
+      /// <summary>
+      /// Identity, Indexed, Required
+      /// </summary>
+      [Key]
+      [Required]
+      public int Id
+      {
+         get
+         {
+            int value = _Id;
+            GetId(ref value);
+            return (_Id = value);
+         }
+         protected set
+         {
+            int oldValue = _Id;
+            SetId(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Id = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Backing field for Name
+      /// </summary>
+      protected string _Name;
+      /// <summary>
+      /// When provided in a partial class, allows value of Name to be changed before setting.
+      /// </summary>
+      partial void SetName(string oldValue, ref string newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Name to be changed before returning.
+      /// </summary>
+      partial void GetName(ref string result);
+
+      /// <summary>
+      /// Required, Max length = 1024
+      /// </summary>
+      [Required]
+      [MaxLength(1024)]
+      [StringLength(1024)]
+      public string Name
+      {
+         get
+         {
+            string value = _Name;
+            GetName(ref value);
+            return (_Name = value);
+         }
+         set
+         {
+            string oldValue = _Name;
+            SetName(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Name = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Required
+      /// </summary>
+      [ConcurrencyCheck]
+      [Required]
+      public byte[] Timestamp { get; set; }
+
+      /*************************************************************************
+       * Navigation properties
+       *************************************************************************/
+
+   }
+}
+

+ 189 - 0
Jellyfin.Data/Entities/MetadataProviderId.cs

@@ -0,0 +1,189 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated from a template.
+//
+//     Manual changes to this file may cause unexpected behavior in your application.
+//     Manual changes to this file will be overwritten if the code is regenerated.
+//
+//     Produced by Entity Framework Visual Editor
+//     https://github.com/msawczyn/EFDesigner
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Linq;
+using System.Runtime.CompilerServices;
+
+namespace Jellyfin.Data.Entities
+{
+   public partial class MetadataProviderId
+   {
+      partial void Init();
+
+      /// <summary>
+      /// Default constructor. Protected due to required properties, but present because EF needs it.
+      /// </summary>
+      protected MetadataProviderId()
+      {
+         // NOTE: This class has one-to-one associations with MetadataProviderId.
+         // One-to-one associations are not validated in constructors since this causes a scenario where each one must be constructed before the other.
+
+         Init();
+      }
+
+      /// <summary>
+      /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving.
+      /// </summary>
+      public static MetadataProviderId CreateMetadataProviderIdUnsafe()
+      {
+         return new MetadataProviderId();
+      }
+
+      /// <summary>
+      /// Public constructor with required data
+      /// </summary>
+      /// <param name="providerid"></param>
+      /// <param name="_metadata0"></param>
+      /// <param name="_person1"></param>
+      /// <param name="_personrole2"></param>
+      /// <param name="_ratingsource3"></param>
+      public MetadataProviderId(string providerid, global::Jellyfin.Data.Entities.Metadata _metadata0, global::Jellyfin.Data.Entities.Person _person1, global::Jellyfin.Data.Entities.PersonRole _personrole2, global::Jellyfin.Data.Entities.RatingSource _ratingsource3)
+      {
+         // NOTE: This class has one-to-one associations with MetadataProviderId.
+         // One-to-one associations are not validated in constructors since this causes a scenario where each one must be constructed before the other.
+
+         if (string.IsNullOrEmpty(providerid)) throw new ArgumentNullException(nameof(providerid));
+         this.ProviderId = providerid;
+
+         if (_metadata0 == null) throw new ArgumentNullException(nameof(_metadata0));
+         _metadata0.Sources.Add(this);
+
+         if (_person1 == null) throw new ArgumentNullException(nameof(_person1));
+         _person1.Sources.Add(this);
+
+         if (_personrole2 == null) throw new ArgumentNullException(nameof(_personrole2));
+         _personrole2.Sources.Add(this);
+
+         if (_ratingsource3 == null) throw new ArgumentNullException(nameof(_ratingsource3));
+         _ratingsource3.Source = this;
+
+
+         Init();
+      }
+
+      /// <summary>
+      /// Static create function (for use in LINQ queries, etc.)
+      /// </summary>
+      /// <param name="providerid"></param>
+      /// <param name="_metadata0"></param>
+      /// <param name="_person1"></param>
+      /// <param name="_personrole2"></param>
+      /// <param name="_ratingsource3"></param>
+      public static MetadataProviderId Create(string providerid, global::Jellyfin.Data.Entities.Metadata _metadata0, global::Jellyfin.Data.Entities.Person _person1, global::Jellyfin.Data.Entities.PersonRole _personrole2, global::Jellyfin.Data.Entities.RatingSource _ratingsource3)
+      {
+         return new MetadataProviderId(providerid, _metadata0, _person1, _personrole2, _ratingsource3);
+      }
+
+      /*************************************************************************
+       * Properties
+       *************************************************************************/
+
+      /// <summary>
+      /// Backing field for Id
+      /// </summary>
+      internal int _Id;
+      /// <summary>
+      /// When provided in a partial class, allows value of Id to be changed before setting.
+      /// </summary>
+      partial void SetId(int oldValue, ref int newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Id to be changed before returning.
+      /// </summary>
+      partial void GetId(ref int result);
+
+      /// <summary>
+      /// Identity, Indexed, Required
+      /// </summary>
+      [Key]
+      [Required]
+      public int Id
+      {
+         get
+         {
+            int value = _Id;
+            GetId(ref value);
+            return (_Id = value);
+         }
+         protected set
+         {
+            int oldValue = _Id;
+            SetId(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Id = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Backing field for ProviderId
+      /// </summary>
+      protected string _ProviderId;
+      /// <summary>
+      /// When provided in a partial class, allows value of ProviderId to be changed before setting.
+      /// </summary>
+      partial void SetProviderId(string oldValue, ref string newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of ProviderId to be changed before returning.
+      /// </summary>
+      partial void GetProviderId(ref string result);
+
+      /// <summary>
+      /// Required, Max length = 255
+      /// </summary>
+      [Required]
+      [MaxLength(255)]
+      [StringLength(255)]
+      public string ProviderId
+      {
+         get
+         {
+            string value = _ProviderId;
+            GetProviderId(ref value);
+            return (_ProviderId = value);
+         }
+         set
+         {
+            string oldValue = _ProviderId;
+            SetProviderId(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _ProviderId = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Required
+      /// </summary>
+      [ConcurrencyCheck]
+      [Required]
+      public byte[] Timestamp { get; set; }
+
+      /*************************************************************************
+       * Navigation properties
+       *************************************************************************/
+
+      /// <summary>
+      /// Required
+      /// </summary>
+      public virtual global::Jellyfin.Data.Entities.MetadataProvider MetadataProvider { get; set; }
+
+   }
+}
+

+ 84 - 0
Jellyfin.Data/Entities/Movie.cs

@@ -0,0 +1,84 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated from a template.
+//
+//     Manual changes to this file may cause unexpected behavior in your application.
+//     Manual changes to this file will be overwritten if the code is regenerated.
+//
+//     Produced by Entity Framework Visual Editor
+//     https://github.com/msawczyn/EFDesigner
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Linq;
+using System.Runtime.CompilerServices;
+
+namespace Jellyfin.Data.Entities
+{
+   public partial class Movie: global::Jellyfin.Data.Entities.LibraryItem
+   {
+      partial void Init();
+
+      /// <summary>
+      /// Default constructor. Protected due to required properties, but present because EF needs it.
+      /// </summary>
+      protected Movie(): base()
+      {
+         Releases = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.Release>();
+         MovieMetadata = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.MovieMetadata>();
+
+         Init();
+      }
+
+      /// <summary>
+      /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving.
+      /// </summary>
+      public static Movie CreateMovieUnsafe()
+      {
+         return new Movie();
+      }
+
+      /// <summary>
+      /// Public constructor with required data
+      /// </summary>
+      /// <param name="urlid">This is whats gets displayed in the Urls and API requests. This could also be a string.</param>
+      public Movie(Guid urlid, DateTime dateadded)
+      {
+         this.UrlId = urlid;
+
+         this.Releases = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.Release>();
+         this.MovieMetadata = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.MovieMetadata>();
+
+         Init();
+      }
+
+      /// <summary>
+      /// Static create function (for use in LINQ queries, etc.)
+      /// </summary>
+      /// <param name="urlid">This is whats gets displayed in the Urls and API requests. This could also be a string.</param>
+      public static Movie Create(Guid urlid, DateTime dateadded)
+      {
+         return new Movie(urlid, dateadded);
+      }
+
+      /*************************************************************************
+       * Properties
+       *************************************************************************/
+
+      /*************************************************************************
+       * Navigation properties
+       *************************************************************************/
+
+      public virtual ICollection<global::Jellyfin.Data.Entities.Release> Releases { get; protected set; }
+
+      public virtual ICollection<global::Jellyfin.Data.Entities.MovieMetadata> MovieMetadata { get; protected set; }
+
+   }
+}
+

+ 239 - 0
Jellyfin.Data/Entities/MovieMetadata.cs

@@ -0,0 +1,239 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated from a template.
+//
+//     Manual changes to this file may cause unexpected behavior in your application.
+//     Manual changes to this file will be overwritten if the code is regenerated.
+//
+//     Produced by Entity Framework Visual Editor
+//     https://github.com/msawczyn/EFDesigner
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Linq;
+using System.Runtime.CompilerServices;
+
+namespace Jellyfin.Data.Entities
+{
+   public partial class MovieMetadata: global::Jellyfin.Data.Entities.Metadata
+   {
+      partial void Init();
+
+      /// <summary>
+      /// Default constructor. Protected due to required properties, but present because EF needs it.
+      /// </summary>
+      protected MovieMetadata(): base()
+      {
+         Studios = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.Company>();
+
+         Init();
+      }
+
+      /// <summary>
+      /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving.
+      /// </summary>
+      public static MovieMetadata CreateMovieMetadataUnsafe()
+      {
+         return new MovieMetadata();
+      }
+
+      /// <summary>
+      /// Public constructor with required data
+      /// </summary>
+      /// <param name="title">The title or name of the object</param>
+      /// <param name="language">ISO-639-3 3-character language codes</param>
+      /// <param name="_movie0"></param>
+      public MovieMetadata(string title, string language, DateTime dateadded, DateTime datemodified, global::Jellyfin.Data.Entities.Movie _movie0)
+      {
+         if (string.IsNullOrEmpty(title)) throw new ArgumentNullException(nameof(title));
+         this.Title = title;
+
+         if (string.IsNullOrEmpty(language)) throw new ArgumentNullException(nameof(language));
+         this.Language = language;
+
+         if (_movie0 == null) throw new ArgumentNullException(nameof(_movie0));
+         _movie0.MovieMetadata.Add(this);
+
+         this.Studios = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.Company>();
+
+         Init();
+      }
+
+      /// <summary>
+      /// Static create function (for use in LINQ queries, etc.)
+      /// </summary>
+      /// <param name="title">The title or name of the object</param>
+      /// <param name="language">ISO-639-3 3-character language codes</param>
+      /// <param name="_movie0"></param>
+      public static MovieMetadata Create(string title, string language, DateTime dateadded, DateTime datemodified, global::Jellyfin.Data.Entities.Movie _movie0)
+      {
+         return new MovieMetadata(title, language, dateadded, datemodified, _movie0);
+      }
+
+      /*************************************************************************
+       * Properties
+       *************************************************************************/
+
+      /// <summary>
+      /// Backing field for Outline
+      /// </summary>
+      protected string _Outline;
+      /// <summary>
+      /// When provided in a partial class, allows value of Outline to be changed before setting.
+      /// </summary>
+      partial void SetOutline(string oldValue, ref string newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Outline to be changed before returning.
+      /// </summary>
+      partial void GetOutline(ref string result);
+
+      /// <summary>
+      /// Max length = 1024
+      /// </summary>
+      [MaxLength(1024)]
+      [StringLength(1024)]
+      public string Outline
+      {
+         get
+         {
+            string value = _Outline;
+            GetOutline(ref value);
+            return (_Outline = value);
+         }
+         set
+         {
+            string oldValue = _Outline;
+            SetOutline(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Outline = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Backing field for Plot
+      /// </summary>
+      protected string _Plot;
+      /// <summary>
+      /// When provided in a partial class, allows value of Plot to be changed before setting.
+      /// </summary>
+      partial void SetPlot(string oldValue, ref string newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Plot to be changed before returning.
+      /// </summary>
+      partial void GetPlot(ref string result);
+
+      /// <summary>
+      /// Max length = 65535
+      /// </summary>
+      [MaxLength(65535)]
+      [StringLength(65535)]
+      public string Plot
+      {
+         get
+         {
+            string value = _Plot;
+            GetPlot(ref value);
+            return (_Plot = value);
+         }
+         set
+         {
+            string oldValue = _Plot;
+            SetPlot(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Plot = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Backing field for Tagline
+      /// </summary>
+      protected string _Tagline;
+      /// <summary>
+      /// When provided in a partial class, allows value of Tagline to be changed before setting.
+      /// </summary>
+      partial void SetTagline(string oldValue, ref string newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Tagline to be changed before returning.
+      /// </summary>
+      partial void GetTagline(ref string result);
+
+      /// <summary>
+      /// Max length = 1024
+      /// </summary>
+      [MaxLength(1024)]
+      [StringLength(1024)]
+      public string Tagline
+      {
+         get
+         {
+            string value = _Tagline;
+            GetTagline(ref value);
+            return (_Tagline = value);
+         }
+         set
+         {
+            string oldValue = _Tagline;
+            SetTagline(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Tagline = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Backing field for Country
+      /// </summary>
+      protected string _Country;
+      /// <summary>
+      /// When provided in a partial class, allows value of Country to be changed before setting.
+      /// </summary>
+      partial void SetCountry(string oldValue, ref string newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Country to be changed before returning.
+      /// </summary>
+      partial void GetCountry(ref string result);
+
+      /// <summary>
+      /// Max length = 2
+      /// </summary>
+      [MaxLength(2)]
+      [StringLength(2)]
+      public string Country
+      {
+         get
+         {
+            string value = _Country;
+            GetCountry(ref value);
+            return (_Country = value);
+         }
+         set
+         {
+            string oldValue = _Country;
+            SetCountry(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Country = value;
+            }
+         }
+      }
+
+      /*************************************************************************
+       * Navigation properties
+       *************************************************************************/
+
+      public virtual ICollection<global::Jellyfin.Data.Entities.Company> Studios { get; protected set; }
+
+   }
+}
+

+ 84 - 0
Jellyfin.Data/Entities/MusicAlbum.cs

@@ -0,0 +1,84 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated from a template.
+//
+//     Manual changes to this file may cause unexpected behavior in your application.
+//     Manual changes to this file will be overwritten if the code is regenerated.
+//
+//     Produced by Entity Framework Visual Editor
+//     https://github.com/msawczyn/EFDesigner
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Linq;
+using System.Runtime.CompilerServices;
+
+namespace Jellyfin.Data.Entities
+{
+   public partial class MusicAlbum: global::Jellyfin.Data.Entities.LibraryItem
+   {
+      partial void Init();
+
+      /// <summary>
+      /// Default constructor. Protected due to required properties, but present because EF needs it.
+      /// </summary>
+      protected MusicAlbum(): base()
+      {
+         MusicAlbumMetadata = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.MusicAlbumMetadata>();
+         Tracks = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.Track>();
+
+         Init();
+      }
+
+      /// <summary>
+      /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving.
+      /// </summary>
+      public static MusicAlbum CreateMusicAlbumUnsafe()
+      {
+         return new MusicAlbum();
+      }
+
+      /// <summary>
+      /// Public constructor with required data
+      /// </summary>
+      /// <param name="urlid">This is whats gets displayed in the Urls and API requests. This could also be a string.</param>
+      public MusicAlbum(Guid urlid, DateTime dateadded)
+      {
+         this.UrlId = urlid;
+
+         this.MusicAlbumMetadata = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.MusicAlbumMetadata>();
+         this.Tracks = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.Track>();
+
+         Init();
+      }
+
+      /// <summary>
+      /// Static create function (for use in LINQ queries, etc.)
+      /// </summary>
+      /// <param name="urlid">This is whats gets displayed in the Urls and API requests. This could also be a string.</param>
+      public static MusicAlbum Create(Guid urlid, DateTime dateadded)
+      {
+         return new MusicAlbum(urlid, dateadded);
+      }
+
+      /*************************************************************************
+       * Properties
+       *************************************************************************/
+
+      /*************************************************************************
+       * Navigation properties
+       *************************************************************************/
+
+      public virtual ICollection<global::Jellyfin.Data.Entities.MusicAlbumMetadata> MusicAlbumMetadata { get; protected set; }
+
+      public virtual ICollection<global::Jellyfin.Data.Entities.Track> Tracks { get; protected set; }
+
+   }
+}
+

+ 202 - 0
Jellyfin.Data/Entities/MusicAlbumMetadata.cs

@@ -0,0 +1,202 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated from a template.
+//
+//     Manual changes to this file may cause unexpected behavior in your application.
+//     Manual changes to this file will be overwritten if the code is regenerated.
+//
+//     Produced by Entity Framework Visual Editor
+//     https://github.com/msawczyn/EFDesigner
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Linq;
+using System.Runtime.CompilerServices;
+
+namespace Jellyfin.Data.Entities
+{
+   public partial class MusicAlbumMetadata: global::Jellyfin.Data.Entities.Metadata
+   {
+      partial void Init();
+
+      /// <summary>
+      /// Default constructor. Protected due to required properties, but present because EF needs it.
+      /// </summary>
+      protected MusicAlbumMetadata(): base()
+      {
+         Labels = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.Company>();
+
+         Init();
+      }
+
+      /// <summary>
+      /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving.
+      /// </summary>
+      public static MusicAlbumMetadata CreateMusicAlbumMetadataUnsafe()
+      {
+         return new MusicAlbumMetadata();
+      }
+
+      /// <summary>
+      /// Public constructor with required data
+      /// </summary>
+      /// <param name="title">The title or name of the object</param>
+      /// <param name="language">ISO-639-3 3-character language codes</param>
+      /// <param name="_musicalbum0"></param>
+      public MusicAlbumMetadata(string title, string language, DateTime dateadded, DateTime datemodified, global::Jellyfin.Data.Entities.MusicAlbum _musicalbum0)
+      {
+         if (string.IsNullOrEmpty(title)) throw new ArgumentNullException(nameof(title));
+         this.Title = title;
+
+         if (string.IsNullOrEmpty(language)) throw new ArgumentNullException(nameof(language));
+         this.Language = language;
+
+         if (_musicalbum0 == null) throw new ArgumentNullException(nameof(_musicalbum0));
+         _musicalbum0.MusicAlbumMetadata.Add(this);
+
+         this.Labels = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.Company>();
+
+         Init();
+      }
+
+      /// <summary>
+      /// Static create function (for use in LINQ queries, etc.)
+      /// </summary>
+      /// <param name="title">The title or name of the object</param>
+      /// <param name="language">ISO-639-3 3-character language codes</param>
+      /// <param name="_musicalbum0"></param>
+      public static MusicAlbumMetadata Create(string title, string language, DateTime dateadded, DateTime datemodified, global::Jellyfin.Data.Entities.MusicAlbum _musicalbum0)
+      {
+         return new MusicAlbumMetadata(title, language, dateadded, datemodified, _musicalbum0);
+      }
+
+      /*************************************************************************
+       * Properties
+       *************************************************************************/
+
+      /// <summary>
+      /// Backing field for Barcode
+      /// </summary>
+      protected string _Barcode;
+      /// <summary>
+      /// When provided in a partial class, allows value of Barcode to be changed before setting.
+      /// </summary>
+      partial void SetBarcode(string oldValue, ref string newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Barcode to be changed before returning.
+      /// </summary>
+      partial void GetBarcode(ref string result);
+
+      /// <summary>
+      /// Max length = 255
+      /// </summary>
+      [MaxLength(255)]
+      [StringLength(255)]
+      public string Barcode
+      {
+         get
+         {
+            string value = _Barcode;
+            GetBarcode(ref value);
+            return (_Barcode = value);
+         }
+         set
+         {
+            string oldValue = _Barcode;
+            SetBarcode(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Barcode = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Backing field for LabelNumber
+      /// </summary>
+      protected string _LabelNumber;
+      /// <summary>
+      /// When provided in a partial class, allows value of LabelNumber to be changed before setting.
+      /// </summary>
+      partial void SetLabelNumber(string oldValue, ref string newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of LabelNumber to be changed before returning.
+      /// </summary>
+      partial void GetLabelNumber(ref string result);
+
+      /// <summary>
+      /// Max length = 255
+      /// </summary>
+      [MaxLength(255)]
+      [StringLength(255)]
+      public string LabelNumber
+      {
+         get
+         {
+            string value = _LabelNumber;
+            GetLabelNumber(ref value);
+            return (_LabelNumber = value);
+         }
+         set
+         {
+            string oldValue = _LabelNumber;
+            SetLabelNumber(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _LabelNumber = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Backing field for Country
+      /// </summary>
+      protected string _Country;
+      /// <summary>
+      /// When provided in a partial class, allows value of Country to be changed before setting.
+      /// </summary>
+      partial void SetCountry(string oldValue, ref string newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Country to be changed before returning.
+      /// </summary>
+      partial void GetCountry(ref string result);
+
+      /// <summary>
+      /// Max length = 2
+      /// </summary>
+      [MaxLength(2)]
+      [StringLength(2)]
+      public string Country
+      {
+         get
+         {
+            string value = _Country;
+            GetCountry(ref value);
+            return (_Country = value);
+         }
+         set
+         {
+            string oldValue = _Country;
+            SetCountry(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Country = value;
+            }
+         }
+      }
+
+      /*************************************************************************
+       * Navigation properties
+       *************************************************************************/
+
+      public virtual ICollection<global::Jellyfin.Data.Entities.Company> Labels { get; protected set; }
+
+   }
+}
+

+ 152 - 0
Jellyfin.Data/Entities/Permission.cs

@@ -0,0 +1,152 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated from a template.
+//
+//     Manual changes to this file may cause unexpected behavior in your application.
+//     Manual changes to this file will be overwritten if the code is regenerated.
+//
+//     Produced by Entity Framework Visual Editor
+//     https://github.com/msawczyn/EFDesigner
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Linq;
+using System.Runtime.CompilerServices;
+
+namespace Jellyfin.Data.Entities
+{
+   public partial class Permission
+   {
+      partial void Init();
+
+      /// <summary>
+      /// Default constructor. Protected due to required properties, but present because EF needs it.
+      /// </summary>
+      protected Permission()
+      {
+         Init();
+      }
+
+      /// <summary>
+      /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving.
+      /// </summary>
+      public static Permission CreatePermissionUnsafe()
+      {
+         return new Permission();
+      }
+
+      /// <summary>
+      /// Public constructor with required data
+      /// </summary>
+      /// <param name="kind"></param>
+      /// <param name="value"></param>
+      /// <param name="_user0"></param>
+      /// <param name="_group1"></param>
+      public Permission(global::Jellyfin.Data.Enums.PermissionKind kind, bool value, global::Jellyfin.Data.Entities.User _user0, global::Jellyfin.Data.Entities.Group _group1)
+      {
+         this.Kind = kind;
+
+         this.Value = value;
+
+         if (_user0 == null) throw new ArgumentNullException(nameof(_user0));
+         _user0.Permissions.Add(this);
+
+         if (_group1 == null) throw new ArgumentNullException(nameof(_group1));
+         _group1.GroupPermissions.Add(this);
+
+
+         Init();
+      }
+
+      /// <summary>
+      /// Static create function (for use in LINQ queries, etc.)
+      /// </summary>
+      /// <param name="kind"></param>
+      /// <param name="value"></param>
+      /// <param name="_user0"></param>
+      /// <param name="_group1"></param>
+      public static Permission Create(global::Jellyfin.Data.Enums.PermissionKind kind, bool value, global::Jellyfin.Data.Entities.User _user0, global::Jellyfin.Data.Entities.Group _group1)
+      {
+         return new Permission(kind, value, _user0, _group1);
+      }
+
+      /*************************************************************************
+       * Properties
+       *************************************************************************/
+
+      /// <summary>
+      /// Identity, Indexed, Required
+      /// </summary>
+      [Key]
+      [Required]
+      public int Id { get; protected set; }
+
+      /// <summary>
+      /// Backing field for Kind
+      /// </summary>
+      protected global::Jellyfin.Data.Enums.PermissionKind _Kind;
+      /// <summary>
+      /// When provided in a partial class, allows value of Kind to be changed before setting.
+      /// </summary>
+      partial void SetKind(global::Jellyfin.Data.Enums.PermissionKind oldValue, ref global::Jellyfin.Data.Enums.PermissionKind newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Kind to be changed before returning.
+      /// </summary>
+      partial void GetKind(ref global::Jellyfin.Data.Enums.PermissionKind result);
+
+      /// <summary>
+      /// Required
+      /// </summary>
+      [Required]
+      public global::Jellyfin.Data.Enums.PermissionKind Kind
+      {
+         get
+         {
+            global::Jellyfin.Data.Enums.PermissionKind value = _Kind;
+            GetKind(ref value);
+            return (_Kind = value);
+         }
+         set
+         {
+            global::Jellyfin.Data.Enums.PermissionKind oldValue = _Kind;
+            SetKind(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Kind = value;
+               OnPropertyChanged();
+            }
+         }
+      }
+
+      /// <summary>
+      /// Required
+      /// </summary>
+      [Required]
+      public bool Value { get; set; }
+
+      /// <summary>
+      /// Concurrency token
+      /// </summary>
+      [Timestamp]
+      public Byte[] Timestamp { get; set; }
+
+      /*************************************************************************
+       * Navigation properties
+       *************************************************************************/
+
+      public virtual event PropertyChangedEventHandler PropertyChanged;
+
+      protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
+      {
+         PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
+      }
+
+   }
+}
+

+ 40 - 0
Jellyfin.Data/Entities/PermissionKind.cs

@@ -0,0 +1,40 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated from a template.
+//
+//     Manual changes to this file may cause unexpected behavior in your application.
+//     Manual changes to this file will be overwritten if the code is regenerated.
+//
+//     Produced by Entity Framework Visual Editor
+//     https://github.com/msawczyn/EFDesigner
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+using System;
+
+namespace Jellyfin.Data.Enums
+{
+   public enum PermissionKind : Int32
+   {
+      IsAdministrator,
+      IsHidden,
+      IsDisabled,
+      BlockUnrateditems,
+      EnbleSharedDeviceControl,
+      EnableRemoteAccess,
+      EnableLiveTvManagement,
+      EnableLiveTvAccess,
+      EnableMediaPlayback,
+      EnableAudioPlaybackTranscoding,
+      EnableVideoPlaybackTranscoding,
+      EnableContentDeletion,
+      EnableContentDownloading,
+      EnableSyncTranscoding,
+      EnableMediaConversion,
+      EnableAllDevices,
+      EnableAllChannels,
+      EnableAllFolders,
+      EnablePublicSharing,
+      AccessSchedules
+   }
+}

+ 312 - 0
Jellyfin.Data/Entities/Person.cs

@@ -0,0 +1,312 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated from a template.
+//
+//     Manual changes to this file may cause unexpected behavior in your application.
+//     Manual changes to this file will be overwritten if the code is regenerated.
+//
+//     Produced by Entity Framework Visual Editor
+//     https://github.com/msawczyn/EFDesigner
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Linq;
+using System.Runtime.CompilerServices;
+
+namespace Jellyfin.Data.Entities
+{
+   public partial class Person
+   {
+      partial void Init();
+
+      /// <summary>
+      /// Default constructor. Protected due to required properties, but present because EF needs it.
+      /// </summary>
+      protected Person()
+      {
+         Sources = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.MetadataProviderId>();
+
+         Init();
+      }
+
+      /// <summary>
+      /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving.
+      /// </summary>
+      public static Person CreatePersonUnsafe()
+      {
+         return new Person();
+      }
+
+      /// <summary>
+      /// Public constructor with required data
+      /// </summary>
+      /// <param name="urlid"></param>
+      /// <param name="name"></param>
+      public Person(Guid urlid, string name, DateTime dateadded, DateTime datemodified)
+      {
+         this.UrlId = urlid;
+
+         if (string.IsNullOrEmpty(name)) throw new ArgumentNullException(nameof(name));
+         this.Name = name;
+
+         this.Sources = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.MetadataProviderId>();
+
+         Init();
+      }
+
+      /// <summary>
+      /// Static create function (for use in LINQ queries, etc.)
+      /// </summary>
+      /// <param name="urlid"></param>
+      /// <param name="name"></param>
+      public static Person Create(Guid urlid, string name, DateTime dateadded, DateTime datemodified)
+      {
+         return new Person(urlid, name, dateadded, datemodified);
+      }
+
+      /*************************************************************************
+       * Properties
+       *************************************************************************/
+
+      /// <summary>
+      /// Backing field for Id
+      /// </summary>
+      internal int _Id;
+      /// <summary>
+      /// When provided in a partial class, allows value of Id to be changed before setting.
+      /// </summary>
+      partial void SetId(int oldValue, ref int newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Id to be changed before returning.
+      /// </summary>
+      partial void GetId(ref int result);
+
+      /// <summary>
+      /// Identity, Indexed, Required
+      /// </summary>
+      [Key]
+      [Required]
+      public int Id
+      {
+         get
+         {
+            int value = _Id;
+            GetId(ref value);
+            return (_Id = value);
+         }
+         protected set
+         {
+            int oldValue = _Id;
+            SetId(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Id = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Backing field for UrlId
+      /// </summary>
+      protected Guid _UrlId;
+      /// <summary>
+      /// When provided in a partial class, allows value of UrlId to be changed before setting.
+      /// </summary>
+      partial void SetUrlId(Guid oldValue, ref Guid newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of UrlId to be changed before returning.
+      /// </summary>
+      partial void GetUrlId(ref Guid result);
+
+      /// <summary>
+      /// Required
+      /// </summary>
+      [Required]
+      public Guid UrlId
+      {
+         get
+         {
+            Guid value = _UrlId;
+            GetUrlId(ref value);
+            return (_UrlId = value);
+         }
+         set
+         {
+            Guid oldValue = _UrlId;
+            SetUrlId(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _UrlId = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Backing field for Name
+      /// </summary>
+      protected string _Name;
+      /// <summary>
+      /// When provided in a partial class, allows value of Name to be changed before setting.
+      /// </summary>
+      partial void SetName(string oldValue, ref string newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Name to be changed before returning.
+      /// </summary>
+      partial void GetName(ref string result);
+
+      /// <summary>
+      /// Required, Max length = 1024
+      /// </summary>
+      [Required]
+      [MaxLength(1024)]
+      [StringLength(1024)]
+      public string Name
+      {
+         get
+         {
+            string value = _Name;
+            GetName(ref value);
+            return (_Name = value);
+         }
+         set
+         {
+            string oldValue = _Name;
+            SetName(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Name = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Backing field for SourceId
+      /// </summary>
+      protected string _SourceId;
+      /// <summary>
+      /// When provided in a partial class, allows value of SourceId to be changed before setting.
+      /// </summary>
+      partial void SetSourceId(string oldValue, ref string newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of SourceId to be changed before returning.
+      /// </summary>
+      partial void GetSourceId(ref string result);
+
+      /// <summary>
+      /// Max length = 255
+      /// </summary>
+      [MaxLength(255)]
+      [StringLength(255)]
+      public string SourceId
+      {
+         get
+         {
+            string value = _SourceId;
+            GetSourceId(ref value);
+            return (_SourceId = value);
+         }
+         set
+         {
+            string oldValue = _SourceId;
+            SetSourceId(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _SourceId = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Backing field for DateAdded
+      /// </summary>
+      protected DateTime _DateAdded;
+      /// <summary>
+      /// When provided in a partial class, allows value of DateAdded to be changed before setting.
+      /// </summary>
+      partial void SetDateAdded(DateTime oldValue, ref DateTime newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of DateAdded to be changed before returning.
+      /// </summary>
+      partial void GetDateAdded(ref DateTime result);
+
+      /// <summary>
+      /// Required
+      /// </summary>
+      [Required]
+      public DateTime DateAdded
+      {
+         get
+         {
+            DateTime value = _DateAdded;
+            GetDateAdded(ref value);
+            return (_DateAdded = value);
+         }
+         internal set
+         {
+            DateTime oldValue = _DateAdded;
+            SetDateAdded(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _DateAdded = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Backing field for DateModified
+      /// </summary>
+      protected DateTime _DateModified;
+      /// <summary>
+      /// When provided in a partial class, allows value of DateModified to be changed before setting.
+      /// </summary>
+      partial void SetDateModified(DateTime oldValue, ref DateTime newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of DateModified to be changed before returning.
+      /// </summary>
+      partial void GetDateModified(ref DateTime result);
+
+      /// <summary>
+      /// Required
+      /// </summary>
+      [Required]
+      public DateTime DateModified
+      {
+         get
+         {
+            DateTime value = _DateModified;
+            GetDateModified(ref value);
+            return (_DateModified = value);
+         }
+         internal set
+         {
+            DateTime oldValue = _DateModified;
+            SetDateModified(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _DateModified = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Required
+      /// </summary>
+      [ConcurrencyCheck]
+      [Required]
+      public byte[] Timestamp { get; set; }
+
+      /*************************************************************************
+       * Navigation properties
+       *************************************************************************/
+
+      public virtual ICollection<global::Jellyfin.Data.Entities.MetadataProviderId> Sources { get; protected set; }
+
+   }
+}
+

+ 215 - 0
Jellyfin.Data/Entities/PersonRole.cs

@@ -0,0 +1,215 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated from a template.
+//
+//     Manual changes to this file may cause unexpected behavior in your application.
+//     Manual changes to this file will be overwritten if the code is regenerated.
+//
+//     Produced by Entity Framework Visual Editor
+//     https://github.com/msawczyn/EFDesigner
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Linq;
+using System.Runtime.CompilerServices;
+
+namespace Jellyfin.Data.Entities
+{
+   public partial class PersonRole
+   {
+      partial void Init();
+
+      /// <summary>
+      /// Default constructor. Protected due to required properties, but present because EF needs it.
+      /// </summary>
+      protected PersonRole()
+      {
+         // NOTE: This class has one-to-one associations with PersonRole.
+         // One-to-one associations are not validated in constructors since this causes a scenario where each one must be constructed before the other.
+
+         Sources = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.MetadataProviderId>();
+
+         Init();
+      }
+
+      /// <summary>
+      /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving.
+      /// </summary>
+      public static PersonRole CreatePersonRoleUnsafe()
+      {
+         return new PersonRole();
+      }
+
+      /// <summary>
+      /// Public constructor with required data
+      /// </summary>
+      /// <param name="type"></param>
+      /// <param name="_metadata0"></param>
+      public PersonRole(global::Jellyfin.Data.Enums.PersonRoleType type, global::Jellyfin.Data.Entities.Metadata _metadata0)
+      {
+         // NOTE: This class has one-to-one associations with PersonRole.
+         // One-to-one associations are not validated in constructors since this causes a scenario where each one must be constructed before the other.
+
+         this.Type = type;
+
+         if (_metadata0 == null) throw new ArgumentNullException(nameof(_metadata0));
+         _metadata0.PersonRoles.Add(this);
+
+         this.Sources = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.MetadataProviderId>();
+
+         Init();
+      }
+
+      /// <summary>
+      /// Static create function (for use in LINQ queries, etc.)
+      /// </summary>
+      /// <param name="type"></param>
+      /// <param name="_metadata0"></param>
+      public static PersonRole Create(global::Jellyfin.Data.Enums.PersonRoleType type, global::Jellyfin.Data.Entities.Metadata _metadata0)
+      {
+         return new PersonRole(type, _metadata0);
+      }
+
+      /*************************************************************************
+       * Properties
+       *************************************************************************/
+
+      /// <summary>
+      /// Backing field for Id
+      /// </summary>
+      internal int _Id;
+      /// <summary>
+      /// When provided in a partial class, allows value of Id to be changed before setting.
+      /// </summary>
+      partial void SetId(int oldValue, ref int newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Id to be changed before returning.
+      /// </summary>
+      partial void GetId(ref int result);
+
+      /// <summary>
+      /// Identity, Indexed, Required
+      /// </summary>
+      [Key]
+      [Required]
+      public int Id
+      {
+         get
+         {
+            int value = _Id;
+            GetId(ref value);
+            return (_Id = value);
+         }
+         protected set
+         {
+            int oldValue = _Id;
+            SetId(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Id = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Backing field for Role
+      /// </summary>
+      protected string _Role;
+      /// <summary>
+      /// When provided in a partial class, allows value of Role to be changed before setting.
+      /// </summary>
+      partial void SetRole(string oldValue, ref string newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Role to be changed before returning.
+      /// </summary>
+      partial void GetRole(ref string result);
+
+      /// <summary>
+      /// Max length = 1024
+      /// </summary>
+      [MaxLength(1024)]
+      [StringLength(1024)]
+      public string Role
+      {
+         get
+         {
+            string value = _Role;
+            GetRole(ref value);
+            return (_Role = value);
+         }
+         set
+         {
+            string oldValue = _Role;
+            SetRole(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Role = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Backing field for Type
+      /// </summary>
+      protected global::Jellyfin.Data.Enums.PersonRoleType _Type;
+      /// <summary>
+      /// When provided in a partial class, allows value of Type to be changed before setting.
+      /// </summary>
+      partial void SetType(global::Jellyfin.Data.Enums.PersonRoleType oldValue, ref global::Jellyfin.Data.Enums.PersonRoleType newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Type to be changed before returning.
+      /// </summary>
+      partial void GetType(ref global::Jellyfin.Data.Enums.PersonRoleType result);
+
+      /// <summary>
+      /// Required
+      /// </summary>
+      [Required]
+      public global::Jellyfin.Data.Enums.PersonRoleType Type
+      {
+         get
+         {
+            global::Jellyfin.Data.Enums.PersonRoleType value = _Type;
+            GetType(ref value);
+            return (_Type = value);
+         }
+         set
+         {
+            global::Jellyfin.Data.Enums.PersonRoleType oldValue = _Type;
+            SetType(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Type = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Required
+      /// </summary>
+      [ConcurrencyCheck]
+      [Required]
+      public byte[] Timestamp { get; set; }
+
+      /*************************************************************************
+       * Navigation properties
+       *************************************************************************/
+
+      /// <summary>
+      /// Required
+      /// </summary>
+      public virtual global::Jellyfin.Data.Entities.Person Person { get; set; }
+
+      public virtual global::Jellyfin.Data.Entities.Artwork Artwork { get; set; }
+
+      public virtual ICollection<global::Jellyfin.Data.Entities.MetadataProviderId> Sources { get; protected set; }
+
+   }
+}
+

+ 84 - 0
Jellyfin.Data/Entities/Photo.cs

@@ -0,0 +1,84 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated from a template.
+//
+//     Manual changes to this file may cause unexpected behavior in your application.
+//     Manual changes to this file will be overwritten if the code is regenerated.
+//
+//     Produced by Entity Framework Visual Editor
+//     https://github.com/msawczyn/EFDesigner
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Linq;
+using System.Runtime.CompilerServices;
+
+namespace Jellyfin.Data.Entities
+{
+   public partial class Photo: global::Jellyfin.Data.Entities.LibraryItem
+   {
+      partial void Init();
+
+      /// <summary>
+      /// Default constructor. Protected due to required properties, but present because EF needs it.
+      /// </summary>
+      protected Photo(): base()
+      {
+         PhotoMetadata = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.PhotoMetadata>();
+         Releases = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.Release>();
+
+         Init();
+      }
+
+      /// <summary>
+      /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving.
+      /// </summary>
+      public static Photo CreatePhotoUnsafe()
+      {
+         return new Photo();
+      }
+
+      /// <summary>
+      /// Public constructor with required data
+      /// </summary>
+      /// <param name="urlid">This is whats gets displayed in the Urls and API requests. This could also be a string.</param>
+      public Photo(Guid urlid, DateTime dateadded)
+      {
+         this.UrlId = urlid;
+
+         this.PhotoMetadata = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.PhotoMetadata>();
+         this.Releases = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.Release>();
+
+         Init();
+      }
+
+      /// <summary>
+      /// Static create function (for use in LINQ queries, etc.)
+      /// </summary>
+      /// <param name="urlid">This is whats gets displayed in the Urls and API requests. This could also be a string.</param>
+      public static Photo Create(Guid urlid, DateTime dateadded)
+      {
+         return new Photo(urlid, dateadded);
+      }
+
+      /*************************************************************************
+       * Properties
+       *************************************************************************/
+
+      /*************************************************************************
+       * Navigation properties
+       *************************************************************************/
+
+      public virtual ICollection<global::Jellyfin.Data.Entities.PhotoMetadata> PhotoMetadata { get; protected set; }
+
+      public virtual ICollection<global::Jellyfin.Data.Entities.Release> Releases { get; protected set; }
+
+   }
+}
+

+ 86 - 0
Jellyfin.Data/Entities/PhotoMetadata.cs

@@ -0,0 +1,86 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated from a template.
+//
+//     Manual changes to this file may cause unexpected behavior in your application.
+//     Manual changes to this file will be overwritten if the code is regenerated.
+//
+//     Produced by Entity Framework Visual Editor
+//     https://github.com/msawczyn/EFDesigner
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Linq;
+using System.Runtime.CompilerServices;
+
+namespace Jellyfin.Data.Entities
+{
+   public partial class PhotoMetadata: global::Jellyfin.Data.Entities.Metadata
+   {
+      partial void Init();
+
+      /// <summary>
+      /// Default constructor. Protected due to required properties, but present because EF needs it.
+      /// </summary>
+      protected PhotoMetadata(): base()
+      {
+         Init();
+      }
+
+      /// <summary>
+      /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving.
+      /// </summary>
+      public static PhotoMetadata CreatePhotoMetadataUnsafe()
+      {
+         return new PhotoMetadata();
+      }
+
+      /// <summary>
+      /// Public constructor with required data
+      /// </summary>
+      /// <param name="title">The title or name of the object</param>
+      /// <param name="language">ISO-639-3 3-character language codes</param>
+      /// <param name="_photo0"></param>
+      public PhotoMetadata(string title, string language, DateTime dateadded, DateTime datemodified, global::Jellyfin.Data.Entities.Photo _photo0)
+      {
+         if (string.IsNullOrEmpty(title)) throw new ArgumentNullException(nameof(title));
+         this.Title = title;
+
+         if (string.IsNullOrEmpty(language)) throw new ArgumentNullException(nameof(language));
+         this.Language = language;
+
+         if (_photo0 == null) throw new ArgumentNullException(nameof(_photo0));
+         _photo0.PhotoMetadata.Add(this);
+
+
+         Init();
+      }
+
+      /// <summary>
+      /// Static create function (for use in LINQ queries, etc.)
+      /// </summary>
+      /// <param name="title">The title or name of the object</param>
+      /// <param name="language">ISO-639-3 3-character language codes</param>
+      /// <param name="_photo0"></param>
+      public static PhotoMetadata Create(string title, string language, DateTime dateadded, DateTime datemodified, global::Jellyfin.Data.Entities.Photo _photo0)
+      {
+         return new PhotoMetadata(title, language, dateadded, datemodified, _photo0);
+      }
+
+      /*************************************************************************
+       * Properties
+       *************************************************************************/
+
+      /*************************************************************************
+       * Navigation properties
+       *************************************************************************/
+
+   }
+}
+

+ 117 - 0
Jellyfin.Data/Entities/Preference.cs

@@ -0,0 +1,117 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated from a template.
+//
+//     Manual changes to this file may cause unexpected behavior in your application.
+//     Manual changes to this file will be overwritten if the code is regenerated.
+//
+//     Produced by Entity Framework Visual Editor
+//     https://github.com/msawczyn/EFDesigner
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Linq;
+using System.Runtime.CompilerServices;
+
+namespace Jellyfin.Data.Entities
+{
+   public partial class Preference
+   {
+      partial void Init();
+
+      /// <summary>
+      /// Default constructor. Protected due to required properties, but present because EF needs it.
+      /// </summary>
+      protected Preference()
+      {
+         Init();
+      }
+
+      /// <summary>
+      /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving.
+      /// </summary>
+      public static Preference CreatePreferenceUnsafe()
+      {
+         return new Preference();
+      }
+
+      /// <summary>
+      /// Public constructor with required data
+      /// </summary>
+      /// <param name="kind"></param>
+      /// <param name="value"></param>
+      /// <param name="_user0"></param>
+      /// <param name="_group1"></param>
+      public Preference(global::Jellyfin.Data.Enums.PreferenceKind kind, string value, global::Jellyfin.Data.Entities.User _user0, global::Jellyfin.Data.Entities.Group _group1)
+      {
+         this.Kind = kind;
+
+         if (string.IsNullOrEmpty(value)) throw new ArgumentNullException(nameof(value));
+         this.Value = value;
+
+         if (_user0 == null) throw new ArgumentNullException(nameof(_user0));
+         _user0.Preferences.Add(this);
+
+         if (_group1 == null) throw new ArgumentNullException(nameof(_group1));
+         _group1.Preferences.Add(this);
+
+
+         Init();
+      }
+
+      /// <summary>
+      /// Static create function (for use in LINQ queries, etc.)
+      /// </summary>
+      /// <param name="kind"></param>
+      /// <param name="value"></param>
+      /// <param name="_user0"></param>
+      /// <param name="_group1"></param>
+      public static Preference Create(global::Jellyfin.Data.Enums.PreferenceKind kind, string value, global::Jellyfin.Data.Entities.User _user0, global::Jellyfin.Data.Entities.Group _group1)
+      {
+         return new Preference(kind, value, _user0, _group1);
+      }
+
+      /*************************************************************************
+       * Properties
+       *************************************************************************/
+
+      /// <summary>
+      /// Identity, Indexed, Required
+      /// </summary>
+      [Key]
+      [Required]
+      public int Id { get; protected set; }
+
+      /// <summary>
+      /// Required
+      /// </summary>
+      [Required]
+      public global::Jellyfin.Data.Enums.PreferenceKind Kind { get; set; }
+
+      /// <summary>
+      /// Required, Max length = 65535
+      /// </summary>
+      [Required]
+      [MaxLength(65535)]
+      [StringLength(65535)]
+      public string Value { get; set; }
+
+      /// <summary>
+      /// Concurrency token
+      /// </summary>
+      [Timestamp]
+      public Byte[] Timestamp { get; set; }
+
+      /*************************************************************************
+       * Navigation properties
+       *************************************************************************/
+
+   }
+}
+

+ 27 - 0
Jellyfin.Data/Entities/PreferenceKind.cs

@@ -0,0 +1,27 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated from a template.
+//
+//     Manual changes to this file may cause unexpected behavior in your application.
+//     Manual changes to this file will be overwritten if the code is regenerated.
+//
+//     Produced by Entity Framework Visual Editor
+//     https://github.com/msawczyn/EFDesigner
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+using System;
+
+namespace Jellyfin.Data.Enums
+{
+   public enum PreferenceKind : Int32
+   {
+      MaxParentalRating,
+      BlockedTags,
+      RemoteClientBitrateLimit,
+      EnabledDevices,
+      EnabledChannels,
+      EnabledFolders,
+      EnableContentDeletionFromFolders
+   }
+}

+ 133 - 0
Jellyfin.Data/Entities/ProviderMapping.cs

@@ -0,0 +1,133 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated from a template.
+//
+//     Manual changes to this file may cause unexpected behavior in your application.
+//     Manual changes to this file will be overwritten if the code is regenerated.
+//
+//     Produced by Entity Framework Visual Editor
+//     https://github.com/msawczyn/EFDesigner
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Linq;
+using System.Runtime.CompilerServices;
+
+namespace Jellyfin.Data.Entities
+{
+   public partial class ProviderMapping
+   {
+      partial void Init();
+
+      /// <summary>
+      /// Default constructor. Protected due to required properties, but present because EF needs it.
+      /// </summary>
+      protected ProviderMapping()
+      {
+         Init();
+      }
+
+      /// <summary>
+      /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving.
+      /// </summary>
+      public static ProviderMapping CreateProviderMappingUnsafe()
+      {
+         return new ProviderMapping();
+      }
+
+      /// <summary>
+      /// Public constructor with required data
+      /// </summary>
+      /// <param name="providername"></param>
+      /// <param name="providersecrets"></param>
+      /// <param name="providerdata"></param>
+      /// <param name="_user0"></param>
+      /// <param name="_group1"></param>
+      public ProviderMapping(string providername, string providersecrets, string providerdata, global::Jellyfin.Data.Entities.User _user0, global::Jellyfin.Data.Entities.Group _group1)
+      {
+         if (string.IsNullOrEmpty(providername)) throw new ArgumentNullException(nameof(providername));
+         this.ProviderName = providername;
+
+         if (string.IsNullOrEmpty(providersecrets)) throw new ArgumentNullException(nameof(providersecrets));
+         this.ProviderSecrets = providersecrets;
+
+         if (string.IsNullOrEmpty(providerdata)) throw new ArgumentNullException(nameof(providerdata));
+         this.ProviderData = providerdata;
+
+         if (_user0 == null) throw new ArgumentNullException(nameof(_user0));
+         _user0.ProviderMappings.Add(this);
+
+         if (_group1 == null) throw new ArgumentNullException(nameof(_group1));
+         _group1.ProviderMappings.Add(this);
+
+
+         Init();
+      }
+
+      /// <summary>
+      /// Static create function (for use in LINQ queries, etc.)
+      /// </summary>
+      /// <param name="providername"></param>
+      /// <param name="providersecrets"></param>
+      /// <param name="providerdata"></param>
+      /// <param name="_user0"></param>
+      /// <param name="_group1"></param>
+      public static ProviderMapping Create(string providername, string providersecrets, string providerdata, global::Jellyfin.Data.Entities.User _user0, global::Jellyfin.Data.Entities.Group _group1)
+      {
+         return new ProviderMapping(providername, providersecrets, providerdata, _user0, _group1);
+      }
+
+      /*************************************************************************
+       * Properties
+       *************************************************************************/
+
+      /// <summary>
+      /// Identity, Indexed, Required
+      /// </summary>
+      [Key]
+      [Required]
+      public int Id { get; protected set; }
+
+      /// <summary>
+      /// Required, Max length = 255
+      /// </summary>
+      [Required]
+      [MaxLength(255)]
+      [StringLength(255)]
+      public string ProviderName { get; set; }
+
+      /// <summary>
+      /// Required, Max length = 65535
+      /// </summary>
+      [Required]
+      [MaxLength(65535)]
+      [StringLength(65535)]
+      public string ProviderSecrets { get; set; }
+
+      /// <summary>
+      /// Required, Max length = 65535
+      /// </summary>
+      [Required]
+      [MaxLength(65535)]
+      [StringLength(65535)]
+      public string ProviderData { get; set; }
+
+      /// <summary>
+      /// Concurrency token
+      /// </summary>
+      [Timestamp]
+      public Byte[] Timestamp { get; set; }
+
+      /*************************************************************************
+       * Navigation properties
+       *************************************************************************/
+
+   }
+}
+

+ 197 - 0
Jellyfin.Data/Entities/Rating.cs

@@ -0,0 +1,197 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated from a template.
+//
+//     Manual changes to this file may cause unexpected behavior in your application.
+//     Manual changes to this file will be overwritten if the code is regenerated.
+//
+//     Produced by Entity Framework Visual Editor
+//     https://github.com/msawczyn/EFDesigner
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Linq;
+using System.Runtime.CompilerServices;
+
+namespace Jellyfin.Data.Entities
+{
+   public partial class Rating
+   {
+      partial void Init();
+
+      /// <summary>
+      /// Default constructor. Protected due to required properties, but present because EF needs it.
+      /// </summary>
+      protected Rating()
+      {
+         Init();
+      }
+
+      /// <summary>
+      /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving.
+      /// </summary>
+      public static Rating CreateRatingUnsafe()
+      {
+         return new Rating();
+      }
+
+      /// <summary>
+      /// Public constructor with required data
+      /// </summary>
+      /// <param name="value"></param>
+      /// <param name="_metadata0"></param>
+      public Rating(double value, global::Jellyfin.Data.Entities.Metadata _metadata0)
+      {
+         this.Value = value;
+
+         if (_metadata0 == null) throw new ArgumentNullException(nameof(_metadata0));
+         _metadata0.Ratings.Add(this);
+
+
+         Init();
+      }
+
+      /// <summary>
+      /// Static create function (for use in LINQ queries, etc.)
+      /// </summary>
+      /// <param name="value"></param>
+      /// <param name="_metadata0"></param>
+      public static Rating Create(double value, global::Jellyfin.Data.Entities.Metadata _metadata0)
+      {
+         return new Rating(value, _metadata0);
+      }
+
+      /*************************************************************************
+       * Properties
+       *************************************************************************/
+
+      /// <summary>
+      /// Backing field for Id
+      /// </summary>
+      internal int _Id;
+      /// <summary>
+      /// When provided in a partial class, allows value of Id to be changed before setting.
+      /// </summary>
+      partial void SetId(int oldValue, ref int newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Id to be changed before returning.
+      /// </summary>
+      partial void GetId(ref int result);
+
+      /// <summary>
+      /// Identity, Indexed, Required
+      /// </summary>
+      [Key]
+      [Required]
+      public int Id
+      {
+         get
+         {
+            int value = _Id;
+            GetId(ref value);
+            return (_Id = value);
+         }
+         protected set
+         {
+            int oldValue = _Id;
+            SetId(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Id = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Backing field for Value
+      /// </summary>
+      protected double _Value;
+      /// <summary>
+      /// When provided in a partial class, allows value of Value to be changed before setting.
+      /// </summary>
+      partial void SetValue(double oldValue, ref double newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Value to be changed before returning.
+      /// </summary>
+      partial void GetValue(ref double result);
+
+      /// <summary>
+      /// Required
+      /// </summary>
+      [Required]
+      public double Value
+      {
+         get
+         {
+            double value = _Value;
+            GetValue(ref value);
+            return (_Value = value);
+         }
+         set
+         {
+            double oldValue = _Value;
+            SetValue(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Value = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Backing field for Votes
+      /// </summary>
+      protected int? _Votes;
+      /// <summary>
+      /// When provided in a partial class, allows value of Votes to be changed before setting.
+      /// </summary>
+      partial void SetVotes(int? oldValue, ref int? newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Votes to be changed before returning.
+      /// </summary>
+      partial void GetVotes(ref int? result);
+
+      public int? Votes
+      {
+         get
+         {
+            int? value = _Votes;
+            GetVotes(ref value);
+            return (_Votes = value);
+         }
+         set
+         {
+            int? oldValue = _Votes;
+            SetVotes(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Votes = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Required
+      /// </summary>
+      [ConcurrencyCheck]
+      [Required]
+      public byte[] Timestamp { get; set; }
+
+      /*************************************************************************
+       * Navigation properties
+       *************************************************************************/
+
+      /// <summary>
+      /// If this is NULL it&apos;s the internal user rating.
+      /// </summary>
+      public virtual global::Jellyfin.Data.Entities.RatingSource RatingType { get; set; }
+
+   }
+}
+

+ 242 - 0
Jellyfin.Data/Entities/RatingSource.cs

@@ -0,0 +1,242 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated from a template.
+//
+//     Manual changes to this file may cause unexpected behavior in your application.
+//     Manual changes to this file will be overwritten if the code is regenerated.
+//
+//     Produced by Entity Framework Visual Editor
+//     https://github.com/msawczyn/EFDesigner
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Linq;
+using System.Runtime.CompilerServices;
+
+namespace Jellyfin.Data.Entities
+{
+   /// <summary>
+   /// This is the entity to store review ratings, not age ratings
+   /// </summary>
+   public partial class RatingSource
+   {
+      partial void Init();
+
+      /// <summary>
+      /// Default constructor. Protected due to required properties, but present because EF needs it.
+      /// </summary>
+      protected RatingSource()
+      {
+         Init();
+      }
+
+      /// <summary>
+      /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving.
+      /// </summary>
+      public static RatingSource CreateRatingSourceUnsafe()
+      {
+         return new RatingSource();
+      }
+
+      /// <summary>
+      /// Public constructor with required data
+      /// </summary>
+      /// <param name="maximumvalue"></param>
+      /// <param name="minimumvalue"></param>
+      /// <param name="_rating0"></param>
+      public RatingSource(double maximumvalue, double minimumvalue, global::Jellyfin.Data.Entities.Rating _rating0)
+      {
+         this.MaximumValue = maximumvalue;
+
+         this.MinimumValue = minimumvalue;
+
+         if (_rating0 == null) throw new ArgumentNullException(nameof(_rating0));
+         _rating0.RatingType = this;
+
+
+         Init();
+      }
+
+      /// <summary>
+      /// Static create function (for use in LINQ queries, etc.)
+      /// </summary>
+      /// <param name="maximumvalue"></param>
+      /// <param name="minimumvalue"></param>
+      /// <param name="_rating0"></param>
+      public static RatingSource Create(double maximumvalue, double minimumvalue, global::Jellyfin.Data.Entities.Rating _rating0)
+      {
+         return new RatingSource(maximumvalue, minimumvalue, _rating0);
+      }
+
+      /*************************************************************************
+       * Properties
+       *************************************************************************/
+
+      /// <summary>
+      /// Backing field for Id
+      /// </summary>
+      internal int _Id;
+      /// <summary>
+      /// When provided in a partial class, allows value of Id to be changed before setting.
+      /// </summary>
+      partial void SetId(int oldValue, ref int newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Id to be changed before returning.
+      /// </summary>
+      partial void GetId(ref int result);
+
+      /// <summary>
+      /// Identity, Indexed, Required
+      /// </summary>
+      [Key]
+      [Required]
+      public int Id
+      {
+         get
+         {
+            int value = _Id;
+            GetId(ref value);
+            return (_Id = value);
+         }
+         protected set
+         {
+            int oldValue = _Id;
+            SetId(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Id = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Backing field for Name
+      /// </summary>
+      protected string _Name;
+      /// <summary>
+      /// When provided in a partial class, allows value of Name to be changed before setting.
+      /// </summary>
+      partial void SetName(string oldValue, ref string newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Name to be changed before returning.
+      /// </summary>
+      partial void GetName(ref string result);
+
+      /// <summary>
+      /// Max length = 1024
+      /// </summary>
+      [MaxLength(1024)]
+      [StringLength(1024)]
+      public string Name
+      {
+         get
+         {
+            string value = _Name;
+            GetName(ref value);
+            return (_Name = value);
+         }
+         set
+         {
+            string oldValue = _Name;
+            SetName(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Name = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Backing field for MaximumValue
+      /// </summary>
+      protected double _MaximumValue;
+      /// <summary>
+      /// When provided in a partial class, allows value of MaximumValue to be changed before setting.
+      /// </summary>
+      partial void SetMaximumValue(double oldValue, ref double newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of MaximumValue to be changed before returning.
+      /// </summary>
+      partial void GetMaximumValue(ref double result);
+
+      /// <summary>
+      /// Required
+      /// </summary>
+      [Required]
+      public double MaximumValue
+      {
+         get
+         {
+            double value = _MaximumValue;
+            GetMaximumValue(ref value);
+            return (_MaximumValue = value);
+         }
+         set
+         {
+            double oldValue = _MaximumValue;
+            SetMaximumValue(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _MaximumValue = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Backing field for MinimumValue
+      /// </summary>
+      protected double _MinimumValue;
+      /// <summary>
+      /// When provided in a partial class, allows value of MinimumValue to be changed before setting.
+      /// </summary>
+      partial void SetMinimumValue(double oldValue, ref double newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of MinimumValue to be changed before returning.
+      /// </summary>
+      partial void GetMinimumValue(ref double result);
+
+      /// <summary>
+      /// Required
+      /// </summary>
+      [Required]
+      public double MinimumValue
+      {
+         get
+         {
+            double value = _MinimumValue;
+            GetMinimumValue(ref value);
+            return (_MinimumValue = value);
+         }
+         set
+         {
+            double oldValue = _MinimumValue;
+            SetMinimumValue(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _MinimumValue = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Required
+      /// </summary>
+      [ConcurrencyCheck]
+      [Required]
+      public byte[] Timestamp { get; set; }
+
+      /*************************************************************************
+       * Navigation properties
+       *************************************************************************/
+
+      public virtual global::Jellyfin.Data.Entities.MetadataProviderId Source { get; set; }
+
+   }
+}
+

+ 197 - 0
Jellyfin.Data/Entities/Release.cs

@@ -0,0 +1,197 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated from a template.
+//
+//     Manual changes to this file may cause unexpected behavior in your application.
+//     Manual changes to this file will be overwritten if the code is regenerated.
+//
+//     Produced by Entity Framework Visual Editor
+//     https://github.com/msawczyn/EFDesigner
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Linq;
+using System.Runtime.CompilerServices;
+
+namespace Jellyfin.Data.Entities
+{
+   public partial class Release
+   {
+      partial void Init();
+
+      /// <summary>
+      /// Default constructor. Protected due to required properties, but present because EF needs it.
+      /// </summary>
+      protected Release()
+      {
+         MediaFiles = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.MediaFile>();
+         Chapters = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.Chapter>();
+
+         Init();
+      }
+
+      /// <summary>
+      /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving.
+      /// </summary>
+      public static Release CreateReleaseUnsafe()
+      {
+         return new Release();
+      }
+
+      /// <summary>
+      /// Public constructor with required data
+      /// </summary>
+      /// <param name="name"></param>
+      /// <param name="_movie0"></param>
+      /// <param name="_episode1"></param>
+      /// <param name="_track2"></param>
+      /// <param name="_customitem3"></param>
+      /// <param name="_book4"></param>
+      /// <param name="_photo5"></param>
+      public Release(string name, global::Jellyfin.Data.Entities.Movie _movie0, global::Jellyfin.Data.Entities.Episode _episode1, global::Jellyfin.Data.Entities.Track _track2, global::Jellyfin.Data.Entities.CustomItem _customitem3, global::Jellyfin.Data.Entities.Book _book4, global::Jellyfin.Data.Entities.Photo _photo5)
+      {
+         if (string.IsNullOrEmpty(name)) throw new ArgumentNullException(nameof(name));
+         this.Name = name;
+
+         if (_movie0 == null) throw new ArgumentNullException(nameof(_movie0));
+         _movie0.Releases.Add(this);
+
+         if (_episode1 == null) throw new ArgumentNullException(nameof(_episode1));
+         _episode1.Releases.Add(this);
+
+         if (_track2 == null) throw new ArgumentNullException(nameof(_track2));
+         _track2.Releases.Add(this);
+
+         if (_customitem3 == null) throw new ArgumentNullException(nameof(_customitem3));
+         _customitem3.Releases.Add(this);
+
+         if (_book4 == null) throw new ArgumentNullException(nameof(_book4));
+         _book4.Releases.Add(this);
+
+         if (_photo5 == null) throw new ArgumentNullException(nameof(_photo5));
+         _photo5.Releases.Add(this);
+
+         this.MediaFiles = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.MediaFile>();
+         this.Chapters = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.Chapter>();
+
+         Init();
+      }
+
+      /// <summary>
+      /// Static create function (for use in LINQ queries, etc.)
+      /// </summary>
+      /// <param name="name"></param>
+      /// <param name="_movie0"></param>
+      /// <param name="_episode1"></param>
+      /// <param name="_track2"></param>
+      /// <param name="_customitem3"></param>
+      /// <param name="_book4"></param>
+      /// <param name="_photo5"></param>
+      public static Release Create(string name, global::Jellyfin.Data.Entities.Movie _movie0, global::Jellyfin.Data.Entities.Episode _episode1, global::Jellyfin.Data.Entities.Track _track2, global::Jellyfin.Data.Entities.CustomItem _customitem3, global::Jellyfin.Data.Entities.Book _book4, global::Jellyfin.Data.Entities.Photo _photo5)
+      {
+         return new Release(name, _movie0, _episode1, _track2, _customitem3, _book4, _photo5);
+      }
+
+      /*************************************************************************
+       * Properties
+       *************************************************************************/
+
+      /// <summary>
+      /// Backing field for Id
+      /// </summary>
+      internal int _Id;
+      /// <summary>
+      /// When provided in a partial class, allows value of Id to be changed before setting.
+      /// </summary>
+      partial void SetId(int oldValue, ref int newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Id to be changed before returning.
+      /// </summary>
+      partial void GetId(ref int result);
+
+      /// <summary>
+      /// Identity, Indexed, Required
+      /// </summary>
+      [Key]
+      [Required]
+      public int Id
+      {
+         get
+         {
+            int value = _Id;
+            GetId(ref value);
+            return (_Id = value);
+         }
+         protected set
+         {
+            int oldValue = _Id;
+            SetId(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Id = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Backing field for Name
+      /// </summary>
+      protected string _Name;
+      /// <summary>
+      /// When provided in a partial class, allows value of Name to be changed before setting.
+      /// </summary>
+      partial void SetName(string oldValue, ref string newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Name to be changed before returning.
+      /// </summary>
+      partial void GetName(ref string result);
+
+      /// <summary>
+      /// Required, Max length = 1024
+      /// </summary>
+      [Required]
+      [MaxLength(1024)]
+      [StringLength(1024)]
+      public string Name
+      {
+         get
+         {
+            string value = _Name;
+            GetName(ref value);
+            return (_Name = value);
+         }
+         set
+         {
+            string oldValue = _Name;
+            SetName(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Name = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Required
+      /// </summary>
+      [ConcurrencyCheck]
+      [Required]
+      public byte[] Timestamp { get; set; }
+
+      /*************************************************************************
+       * Navigation properties
+       *************************************************************************/
+
+      public virtual ICollection<global::Jellyfin.Data.Entities.MediaFile> MediaFiles { get; protected set; }
+
+      public virtual ICollection<global::Jellyfin.Data.Entities.Chapter> Chapters { get; protected set; }
+
+   }
+}
+

+ 127 - 0
Jellyfin.Data/Entities/Season.cs

@@ -0,0 +1,127 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated from a template.
+//
+//     Manual changes to this file may cause unexpected behavior in your application.
+//     Manual changes to this file will be overwritten if the code is regenerated.
+//
+//     Produced by Entity Framework Visual Editor
+//     https://github.com/msawczyn/EFDesigner
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Linq;
+using System.Runtime.CompilerServices;
+
+namespace Jellyfin.Data.Entities
+{
+   public partial class Season: global::Jellyfin.Data.Entities.LibraryItem
+   {
+      partial void Init();
+
+      /// <summary>
+      /// Default constructor. Protected due to required properties, but present because EF needs it.
+      /// </summary>
+      protected Season(): base()
+      {
+         // NOTE: This class has one-to-one associations with LibraryRoot, LibraryItem and CollectionItem.
+         // One-to-one associations are not validated in constructors since this causes a scenario where each one must be constructed before the other.
+
+         SeasonMetadata = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.SeasonMetadata>();
+         Episodes = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.Episode>();
+
+         Init();
+      }
+
+      /// <summary>
+      /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving.
+      /// </summary>
+      public static Season CreateSeasonUnsafe()
+      {
+         return new Season();
+      }
+
+      /// <summary>
+      /// Public constructor with required data
+      /// </summary>
+      /// <param name="urlid">This is whats gets displayed in the Urls and API requests. This could also be a string.</param>
+      /// <param name="_series0"></param>
+      public Season(Guid urlid, DateTime dateadded, global::Jellyfin.Data.Entities.Series _series0)
+      {
+         // NOTE: This class has one-to-one associations with LibraryRoot, LibraryItem and CollectionItem.
+         // One-to-one associations are not validated in constructors since this causes a scenario where each one must be constructed before the other.
+
+         this.UrlId = urlid;
+
+         if (_series0 == null) throw new ArgumentNullException(nameof(_series0));
+         _series0.Seasons.Add(this);
+
+         this.SeasonMetadata = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.SeasonMetadata>();
+         this.Episodes = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.Episode>();
+
+         Init();
+      }
+
+      /// <summary>
+      /// Static create function (for use in LINQ queries, etc.)
+      /// </summary>
+      /// <param name="urlid">This is whats gets displayed in the Urls and API requests. This could also be a string.</param>
+      /// <param name="_series0"></param>
+      public static Season Create(Guid urlid, DateTime dateadded, global::Jellyfin.Data.Entities.Series _series0)
+      {
+         return new Season(urlid, dateadded, _series0);
+      }
+
+      /*************************************************************************
+       * Properties
+       *************************************************************************/
+
+      /// <summary>
+      /// Backing field for SeasonNumber
+      /// </summary>
+      protected int? _SeasonNumber;
+      /// <summary>
+      /// When provided in a partial class, allows value of SeasonNumber to be changed before setting.
+      /// </summary>
+      partial void SetSeasonNumber(int? oldValue, ref int? newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of SeasonNumber to be changed before returning.
+      /// </summary>
+      partial void GetSeasonNumber(ref int? result);
+
+      public int? SeasonNumber
+      {
+         get
+         {
+            int? value = _SeasonNumber;
+            GetSeasonNumber(ref value);
+            return (_SeasonNumber = value);
+         }
+         set
+         {
+            int? oldValue = _SeasonNumber;
+            SetSeasonNumber(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _SeasonNumber = value;
+            }
+         }
+      }
+
+      /*************************************************************************
+       * Navigation properties
+       *************************************************************************/
+
+      public virtual ICollection<global::Jellyfin.Data.Entities.SeasonMetadata> SeasonMetadata { get; protected set; }
+
+      public virtual ICollection<global::Jellyfin.Data.Entities.Episode> Episodes { get; protected set; }
+
+   }
+}
+

+ 123 - 0
Jellyfin.Data/Entities/SeasonMetadata.cs

@@ -0,0 +1,123 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated from a template.
+//
+//     Manual changes to this file may cause unexpected behavior in your application.
+//     Manual changes to this file will be overwritten if the code is regenerated.
+//
+//     Produced by Entity Framework Visual Editor
+//     https://github.com/msawczyn/EFDesigner
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Linq;
+using System.Runtime.CompilerServices;
+
+namespace Jellyfin.Data.Entities
+{
+   public partial class SeasonMetadata: global::Jellyfin.Data.Entities.Metadata
+   {
+      partial void Init();
+
+      /// <summary>
+      /// Default constructor. Protected due to required properties, but present because EF needs it.
+      /// </summary>
+      protected SeasonMetadata(): base()
+      {
+         Init();
+      }
+
+      /// <summary>
+      /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving.
+      /// </summary>
+      public static SeasonMetadata CreateSeasonMetadataUnsafe()
+      {
+         return new SeasonMetadata();
+      }
+
+      /// <summary>
+      /// Public constructor with required data
+      /// </summary>
+      /// <param name="title">The title or name of the object</param>
+      /// <param name="language">ISO-639-3 3-character language codes</param>
+      /// <param name="_season0"></param>
+      public SeasonMetadata(string title, string language, DateTime dateadded, DateTime datemodified, global::Jellyfin.Data.Entities.Season _season0)
+      {
+         if (string.IsNullOrEmpty(title)) throw new ArgumentNullException(nameof(title));
+         this.Title = title;
+
+         if (string.IsNullOrEmpty(language)) throw new ArgumentNullException(nameof(language));
+         this.Language = language;
+
+         if (_season0 == null) throw new ArgumentNullException(nameof(_season0));
+         _season0.SeasonMetadata.Add(this);
+
+
+         Init();
+      }
+
+      /// <summary>
+      /// Static create function (for use in LINQ queries, etc.)
+      /// </summary>
+      /// <param name="title">The title or name of the object</param>
+      /// <param name="language">ISO-639-3 3-character language codes</param>
+      /// <param name="_season0"></param>
+      public static SeasonMetadata Create(string title, string language, DateTime dateadded, DateTime datemodified, global::Jellyfin.Data.Entities.Season _season0)
+      {
+         return new SeasonMetadata(title, language, dateadded, datemodified, _season0);
+      }
+
+      /*************************************************************************
+       * Properties
+       *************************************************************************/
+
+      /// <summary>
+      /// Backing field for Outline
+      /// </summary>
+      protected string _Outline;
+      /// <summary>
+      /// When provided in a partial class, allows value of Outline to be changed before setting.
+      /// </summary>
+      partial void SetOutline(string oldValue, ref string newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Outline to be changed before returning.
+      /// </summary>
+      partial void GetOutline(ref string result);
+
+      /// <summary>
+      /// Max length = 1024
+      /// </summary>
+      [MaxLength(1024)]
+      [StringLength(1024)]
+      public string Outline
+      {
+         get
+         {
+            string value = _Outline;
+            GetOutline(ref value);
+            return (_Outline = value);
+         }
+         set
+         {
+            string oldValue = _Outline;
+            SetOutline(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Outline = value;
+            }
+         }
+      }
+
+      /*************************************************************************
+       * Navigation properties
+       *************************************************************************/
+
+   }
+}
+

+ 183 - 0
Jellyfin.Data/Entities/Series.cs

@@ -0,0 +1,183 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated from a template.
+//
+//     Manual changes to this file may cause unexpected behavior in your application.
+//     Manual changes to this file will be overwritten if the code is regenerated.
+//
+//     Produced by Entity Framework Visual Editor
+//     https://github.com/msawczyn/EFDesigner
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Linq;
+using System.Runtime.CompilerServices;
+
+namespace Jellyfin.Data.Entities
+{
+   public partial class Series: global::Jellyfin.Data.Entities.LibraryItem
+   {
+      partial void Init();
+
+      /// <summary>
+      /// Default constructor. Protected due to required properties, but present because EF needs it.
+      /// </summary>
+      protected Series(): base()
+      {
+         SeriesMetadata = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.SeriesMetadata>();
+         Seasons = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.Season>();
+
+         Init();
+      }
+
+      /// <summary>
+      /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving.
+      /// </summary>
+      public static Series CreateSeriesUnsafe()
+      {
+         return new Series();
+      }
+
+      /// <summary>
+      /// Public constructor with required data
+      /// </summary>
+      /// <param name="urlid">This is whats gets displayed in the Urls and API requests. This could also be a string.</param>
+      public Series(Guid urlid, DateTime dateadded)
+      {
+         this.UrlId = urlid;
+
+         this.SeriesMetadata = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.SeriesMetadata>();
+         this.Seasons = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.Season>();
+
+         Init();
+      }
+
+      /// <summary>
+      /// Static create function (for use in LINQ queries, etc.)
+      /// </summary>
+      /// <param name="urlid">This is whats gets displayed in the Urls and API requests. This could also be a string.</param>
+      public static Series Create(Guid urlid, DateTime dateadded)
+      {
+         return new Series(urlid, dateadded);
+      }
+
+      /*************************************************************************
+       * Properties
+       *************************************************************************/
+
+      /// <summary>
+      /// Backing field for AirsDayOfWeek
+      /// </summary>
+      protected global::Jellyfin.Data.Enums.Weekday? _AirsDayOfWeek;
+      /// <summary>
+      /// When provided in a partial class, allows value of AirsDayOfWeek to be changed before setting.
+      /// </summary>
+      partial void SetAirsDayOfWeek(global::Jellyfin.Data.Enums.Weekday? oldValue, ref global::Jellyfin.Data.Enums.Weekday? newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of AirsDayOfWeek to be changed before returning.
+      /// </summary>
+      partial void GetAirsDayOfWeek(ref global::Jellyfin.Data.Enums.Weekday? result);
+
+      public global::Jellyfin.Data.Enums.Weekday? AirsDayOfWeek
+      {
+         get
+         {
+            global::Jellyfin.Data.Enums.Weekday? value = _AirsDayOfWeek;
+            GetAirsDayOfWeek(ref value);
+            return (_AirsDayOfWeek = value);
+         }
+         set
+         {
+            global::Jellyfin.Data.Enums.Weekday? oldValue = _AirsDayOfWeek;
+            SetAirsDayOfWeek(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _AirsDayOfWeek = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Backing field for AirsTime
+      /// </summary>
+      protected DateTimeOffset? _AirsTime;
+      /// <summary>
+      /// When provided in a partial class, allows value of AirsTime to be changed before setting.
+      /// </summary>
+      partial void SetAirsTime(DateTimeOffset? oldValue, ref DateTimeOffset? newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of AirsTime to be changed before returning.
+      /// </summary>
+      partial void GetAirsTime(ref DateTimeOffset? result);
+
+      /// <summary>
+      /// The time the show airs, ignore the date portion
+      /// </summary>
+      public DateTimeOffset? AirsTime
+      {
+         get
+         {
+            DateTimeOffset? value = _AirsTime;
+            GetAirsTime(ref value);
+            return (_AirsTime = value);
+         }
+         set
+         {
+            DateTimeOffset? oldValue = _AirsTime;
+            SetAirsTime(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _AirsTime = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Backing field for FirstAired
+      /// </summary>
+      protected DateTimeOffset? _FirstAired;
+      /// <summary>
+      /// When provided in a partial class, allows value of FirstAired to be changed before setting.
+      /// </summary>
+      partial void SetFirstAired(DateTimeOffset? oldValue, ref DateTimeOffset? newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of FirstAired to be changed before returning.
+      /// </summary>
+      partial void GetFirstAired(ref DateTimeOffset? result);
+
+      public DateTimeOffset? FirstAired
+      {
+         get
+         {
+            DateTimeOffset? value = _FirstAired;
+            GetFirstAired(ref value);
+            return (_FirstAired = value);
+         }
+         set
+         {
+            DateTimeOffset? oldValue = _FirstAired;
+            SetFirstAired(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _FirstAired = value;
+            }
+         }
+      }
+
+      /*************************************************************************
+       * Navigation properties
+       *************************************************************************/
+
+      public virtual ICollection<global::Jellyfin.Data.Entities.SeriesMetadata> SeriesMetadata { get; protected set; }
+
+      public virtual ICollection<global::Jellyfin.Data.Entities.Season> Seasons { get; protected set; }
+
+   }
+}
+

+ 239 - 0
Jellyfin.Data/Entities/SeriesMetadata.cs

@@ -0,0 +1,239 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated from a template.
+//
+//     Manual changes to this file may cause unexpected behavior in your application.
+//     Manual changes to this file will be overwritten if the code is regenerated.
+//
+//     Produced by Entity Framework Visual Editor
+//     https://github.com/msawczyn/EFDesigner
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Linq;
+using System.Runtime.CompilerServices;
+
+namespace Jellyfin.Data.Entities
+{
+   public partial class SeriesMetadata: global::Jellyfin.Data.Entities.Metadata
+   {
+      partial void Init();
+
+      /// <summary>
+      /// Default constructor. Protected due to required properties, but present because EF needs it.
+      /// </summary>
+      protected SeriesMetadata(): base()
+      {
+         Networks = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.Company>();
+
+         Init();
+      }
+
+      /// <summary>
+      /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving.
+      /// </summary>
+      public static SeriesMetadata CreateSeriesMetadataUnsafe()
+      {
+         return new SeriesMetadata();
+      }
+
+      /// <summary>
+      /// Public constructor with required data
+      /// </summary>
+      /// <param name="title">The title or name of the object</param>
+      /// <param name="language">ISO-639-3 3-character language codes</param>
+      /// <param name="_series0"></param>
+      public SeriesMetadata(string title, string language, DateTime dateadded, DateTime datemodified, global::Jellyfin.Data.Entities.Series _series0)
+      {
+         if (string.IsNullOrEmpty(title)) throw new ArgumentNullException(nameof(title));
+         this.Title = title;
+
+         if (string.IsNullOrEmpty(language)) throw new ArgumentNullException(nameof(language));
+         this.Language = language;
+
+         if (_series0 == null) throw new ArgumentNullException(nameof(_series0));
+         _series0.SeriesMetadata.Add(this);
+
+         this.Networks = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.Company>();
+
+         Init();
+      }
+
+      /// <summary>
+      /// Static create function (for use in LINQ queries, etc.)
+      /// </summary>
+      /// <param name="title">The title or name of the object</param>
+      /// <param name="language">ISO-639-3 3-character language codes</param>
+      /// <param name="_series0"></param>
+      public static SeriesMetadata Create(string title, string language, DateTime dateadded, DateTime datemodified, global::Jellyfin.Data.Entities.Series _series0)
+      {
+         return new SeriesMetadata(title, language, dateadded, datemodified, _series0);
+      }
+
+      /*************************************************************************
+       * Properties
+       *************************************************************************/
+
+      /// <summary>
+      /// Backing field for Outline
+      /// </summary>
+      protected string _Outline;
+      /// <summary>
+      /// When provided in a partial class, allows value of Outline to be changed before setting.
+      /// </summary>
+      partial void SetOutline(string oldValue, ref string newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Outline to be changed before returning.
+      /// </summary>
+      partial void GetOutline(ref string result);
+
+      /// <summary>
+      /// Max length = 1024
+      /// </summary>
+      [MaxLength(1024)]
+      [StringLength(1024)]
+      public string Outline
+      {
+         get
+         {
+            string value = _Outline;
+            GetOutline(ref value);
+            return (_Outline = value);
+         }
+         set
+         {
+            string oldValue = _Outline;
+            SetOutline(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Outline = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Backing field for Plot
+      /// </summary>
+      protected string _Plot;
+      /// <summary>
+      /// When provided in a partial class, allows value of Plot to be changed before setting.
+      /// </summary>
+      partial void SetPlot(string oldValue, ref string newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Plot to be changed before returning.
+      /// </summary>
+      partial void GetPlot(ref string result);
+
+      /// <summary>
+      /// Max length = 65535
+      /// </summary>
+      [MaxLength(65535)]
+      [StringLength(65535)]
+      public string Plot
+      {
+         get
+         {
+            string value = _Plot;
+            GetPlot(ref value);
+            return (_Plot = value);
+         }
+         set
+         {
+            string oldValue = _Plot;
+            SetPlot(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Plot = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Backing field for Tagline
+      /// </summary>
+      protected string _Tagline;
+      /// <summary>
+      /// When provided in a partial class, allows value of Tagline to be changed before setting.
+      /// </summary>
+      partial void SetTagline(string oldValue, ref string newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Tagline to be changed before returning.
+      /// </summary>
+      partial void GetTagline(ref string result);
+
+      /// <summary>
+      /// Max length = 1024
+      /// </summary>
+      [MaxLength(1024)]
+      [StringLength(1024)]
+      public string Tagline
+      {
+         get
+         {
+            string value = _Tagline;
+            GetTagline(ref value);
+            return (_Tagline = value);
+         }
+         set
+         {
+            string oldValue = _Tagline;
+            SetTagline(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Tagline = value;
+            }
+         }
+      }
+
+      /// <summary>
+      /// Backing field for Country
+      /// </summary>
+      protected string _Country;
+      /// <summary>
+      /// When provided in a partial class, allows value of Country to be changed before setting.
+      /// </summary>
+      partial void SetCountry(string oldValue, ref string newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of Country to be changed before returning.
+      /// </summary>
+      partial void GetCountry(ref string result);
+
+      /// <summary>
+      /// Max length = 2
+      /// </summary>
+      [MaxLength(2)]
+      [StringLength(2)]
+      public string Country
+      {
+         get
+         {
+            string value = _Country;
+            GetCountry(ref value);
+            return (_Country = value);
+         }
+         set
+         {
+            string oldValue = _Country;
+            SetCountry(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _Country = value;
+            }
+         }
+      }
+
+      /*************************************************************************
+       * Navigation properties
+       *************************************************************************/
+
+      public virtual ICollection<global::Jellyfin.Data.Entities.Company> Networks { get; protected set; }
+
+   }
+}
+

+ 127 - 0
Jellyfin.Data/Entities/Track.cs

@@ -0,0 +1,127 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated from a template.
+//
+//     Manual changes to this file may cause unexpected behavior in your application.
+//     Manual changes to this file will be overwritten if the code is regenerated.
+//
+//     Produced by Entity Framework Visual Editor
+//     https://github.com/msawczyn/EFDesigner
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Linq;
+using System.Runtime.CompilerServices;
+
+namespace Jellyfin.Data.Entities
+{
+   public partial class Track: global::Jellyfin.Data.Entities.LibraryItem
+   {
+      partial void Init();
+
+      /// <summary>
+      /// Default constructor. Protected due to required properties, but present because EF needs it.
+      /// </summary>
+      protected Track(): base()
+      {
+         // NOTE: This class has one-to-one associations with LibraryRoot, LibraryItem and CollectionItem.
+         // One-to-one associations are not validated in constructors since this causes a scenario where each one must be constructed before the other.
+
+         Releases = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.Release>();
+         TrackMetadata = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.TrackMetadata>();
+
+         Init();
+      }
+
+      /// <summary>
+      /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving.
+      /// </summary>
+      public static Track CreateTrackUnsafe()
+      {
+         return new Track();
+      }
+
+      /// <summary>
+      /// Public constructor with required data
+      /// </summary>
+      /// <param name="urlid">This is whats gets displayed in the Urls and API requests. This could also be a string.</param>
+      /// <param name="_musicalbum0"></param>
+      public Track(Guid urlid, DateTime dateadded, global::Jellyfin.Data.Entities.MusicAlbum _musicalbum0)
+      {
+         // NOTE: This class has one-to-one associations with LibraryRoot, LibraryItem and CollectionItem.
+         // One-to-one associations are not validated in constructors since this causes a scenario where each one must be constructed before the other.
+
+         this.UrlId = urlid;
+
+         if (_musicalbum0 == null) throw new ArgumentNullException(nameof(_musicalbum0));
+         _musicalbum0.Tracks.Add(this);
+
+         this.Releases = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.Release>();
+         this.TrackMetadata = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.TrackMetadata>();
+
+         Init();
+      }
+
+      /// <summary>
+      /// Static create function (for use in LINQ queries, etc.)
+      /// </summary>
+      /// <param name="urlid">This is whats gets displayed in the Urls and API requests. This could also be a string.</param>
+      /// <param name="_musicalbum0"></param>
+      public static Track Create(Guid urlid, DateTime dateadded, global::Jellyfin.Data.Entities.MusicAlbum _musicalbum0)
+      {
+         return new Track(urlid, dateadded, _musicalbum0);
+      }
+
+      /*************************************************************************
+       * Properties
+       *************************************************************************/
+
+      /// <summary>
+      /// Backing field for TrackNumber
+      /// </summary>
+      protected int? _TrackNumber;
+      /// <summary>
+      /// When provided in a partial class, allows value of TrackNumber to be changed before setting.
+      /// </summary>
+      partial void SetTrackNumber(int? oldValue, ref int? newValue);
+      /// <summary>
+      /// When provided in a partial class, allows value of TrackNumber to be changed before returning.
+      /// </summary>
+      partial void GetTrackNumber(ref int? result);
+
+      public int? TrackNumber
+      {
+         get
+         {
+            int? value = _TrackNumber;
+            GetTrackNumber(ref value);
+            return (_TrackNumber = value);
+         }
+         set
+         {
+            int? oldValue = _TrackNumber;
+            SetTrackNumber(oldValue, ref value);
+            if (oldValue != value)
+            {
+               _TrackNumber = value;
+            }
+         }
+      }
+
+      /*************************************************************************
+       * Navigation properties
+       *************************************************************************/
+
+      public virtual ICollection<global::Jellyfin.Data.Entities.Release> Releases { get; protected set; }
+
+      public virtual ICollection<global::Jellyfin.Data.Entities.TrackMetadata> TrackMetadata { get; protected set; }
+
+   }
+}
+

+ 86 - 0
Jellyfin.Data/Entities/TrackMetadata.cs

@@ -0,0 +1,86 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated from a template.
+//
+//     Manual changes to this file may cause unexpected behavior in your application.
+//     Manual changes to this file will be overwritten if the code is regenerated.
+//
+//     Produced by Entity Framework Visual Editor
+//     https://github.com/msawczyn/EFDesigner
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Linq;
+using System.Runtime.CompilerServices;
+
+namespace Jellyfin.Data.Entities
+{
+   public partial class TrackMetadata: global::Jellyfin.Data.Entities.Metadata
+   {
+      partial void Init();
+
+      /// <summary>
+      /// Default constructor. Protected due to required properties, but present because EF needs it.
+      /// </summary>
+      protected TrackMetadata(): base()
+      {
+         Init();
+      }
+
+      /// <summary>
+      /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving.
+      /// </summary>
+      public static TrackMetadata CreateTrackMetadataUnsafe()
+      {
+         return new TrackMetadata();
+      }
+
+      /// <summary>
+      /// Public constructor with required data
+      /// </summary>
+      /// <param name="title">The title or name of the object</param>
+      /// <param name="language">ISO-639-3 3-character language codes</param>
+      /// <param name="_track0"></param>
+      public TrackMetadata(string title, string language, DateTime dateadded, DateTime datemodified, global::Jellyfin.Data.Entities.Track _track0)
+      {
+         if (string.IsNullOrEmpty(title)) throw new ArgumentNullException(nameof(title));
+         this.Title = title;
+
+         if (string.IsNullOrEmpty(language)) throw new ArgumentNullException(nameof(language));
+         this.Language = language;
+
+         if (_track0 == null) throw new ArgumentNullException(nameof(_track0));
+         _track0.TrackMetadata.Add(this);
+
+
+         Init();
+      }
+
+      /// <summary>
+      /// Static create function (for use in LINQ queries, etc.)
+      /// </summary>
+      /// <param name="title">The title or name of the object</param>
+      /// <param name="language">ISO-639-3 3-character language codes</param>
+      /// <param name="_track0"></param>
+      public static TrackMetadata Create(string title, string language, DateTime dateadded, DateTime datemodified, global::Jellyfin.Data.Entities.Track _track0)
+      {
+         return new TrackMetadata(title, language, dateadded, datemodified, _track0);
+      }
+
+      /*************************************************************************
+       * Properties
+       *************************************************************************/
+
+      /*************************************************************************
+       * Navigation properties
+       *************************************************************************/
+
+   }
+}
+

+ 242 - 0
Jellyfin.Data/Entities/User.cs

@@ -0,0 +1,242 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated from a template.
+//
+//     Manual changes to this file may cause unexpected behavior in your application.
+//     Manual changes to this file will be overwritten if the code is regenerated.
+//
+//     Produced by Entity Framework Visual Editor
+//     https://github.com/msawczyn/EFDesigner
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Linq;
+using System.Runtime.CompilerServices;
+
+namespace Jellyfin.Data.Entities
+{
+   public partial class User
+   {
+      partial void Init();
+
+      /// <summary>
+      /// Default constructor. Protected due to required properties, but present because EF needs it.
+      /// </summary>
+      protected User()
+      {
+         Groups = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.Group>();
+         Permissions = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.Permission>();
+         ProviderMappings = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.ProviderMapping>();
+         Preferences = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.Preference>();
+
+         Init();
+      }
+
+      /// <summary>
+      /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving.
+      /// </summary>
+      public static User CreateUserUnsafe()
+      {
+         return new User();
+      }
+
+      /// <summary>
+      /// Public constructor with required data
+      /// </summary>
+      /// <param name="username"></param>
+      /// <param name="mustupdatepassword"></param>
+      /// <param name="audiolanguagepreference"></param>
+      /// <param name="authenticationproviderid"></param>
+      /// <param name="invalidloginattemptcount"></param>
+      /// <param name="subtitlemode"></param>
+      /// <param name="playdefaultaudiotrack"></param>
+      public User(string username, bool mustupdatepassword, string audiolanguagepreference, string authenticationproviderid, int invalidloginattemptcount, string subtitlemode, bool playdefaultaudiotrack)
+      {
+         if (string.IsNullOrEmpty(username)) throw new ArgumentNullException(nameof(username));
+         this.Username = username;
+
+         this.MustUpdatePassword = mustupdatepassword;
+
+         if (string.IsNullOrEmpty(audiolanguagepreference)) throw new ArgumentNullException(nameof(audiolanguagepreference));
+         this.AudioLanguagePreference = audiolanguagepreference;
+
+         if (string.IsNullOrEmpty(authenticationproviderid)) throw new ArgumentNullException(nameof(authenticationproviderid));
+         this.AuthenticationProviderId = authenticationproviderid;
+
+         this.InvalidLoginAttemptCount = invalidloginattemptcount;
+
+         if (string.IsNullOrEmpty(subtitlemode)) throw new ArgumentNullException(nameof(subtitlemode));
+         this.SubtitleMode = subtitlemode;
+
+         this.PlayDefaultAudioTrack = playdefaultaudiotrack;
+
+         this.Groups = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.Group>();
+         this.Permissions = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.Permission>();
+         this.ProviderMappings = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.ProviderMapping>();
+         this.Preferences = new System.Collections.Generic.HashSet<global::Jellyfin.Data.Entities.Preference>();
+
+         Init();
+      }
+
+      /// <summary>
+      /// Static create function (for use in LINQ queries, etc.)
+      /// </summary>
+      /// <param name="username"></param>
+      /// <param name="mustupdatepassword"></param>
+      /// <param name="audiolanguagepreference"></param>
+      /// <param name="authenticationproviderid"></param>
+      /// <param name="invalidloginattemptcount"></param>
+      /// <param name="subtitlemode"></param>
+      /// <param name="playdefaultaudiotrack"></param>
+      public static User Create(string username, bool mustupdatepassword, string audiolanguagepreference, string authenticationproviderid, int invalidloginattemptcount, string subtitlemode, bool playdefaultaudiotrack)
+      {
+         return new User(username, mustupdatepassword, audiolanguagepreference, authenticationproviderid, invalidloginattemptcount, subtitlemode, playdefaultaudiotrack);
+      }
+
+      /*************************************************************************
+       * Properties
+       *************************************************************************/
+
+      /// <summary>
+      /// Identity, Indexed, Required
+      /// </summary>
+      [Key]
+      [Required]
+      public Guid Id { get; protected set; }
+
+      /// <summary>
+      /// Required
+      /// </summary>
+      [ConcurrencyCheck]
+      [Required]
+      public byte[] LastLoginTimestamp { get; set; }
+
+      /// <summary>
+      /// Required, Max length = 255
+      /// </summary>
+      [Required]
+      [MaxLength(255)]
+      [StringLength(255)]
+      public string Username { get; set; }
+
+      /// <summary>
+      /// Max length = 65535
+      /// </summary>
+      [MaxLength(65535)]
+      [StringLength(65535)]
+      public string Password { get; set; }
+
+      /// <summary>
+      /// Required
+      /// </summary>
+      [Required]
+      public bool MustUpdatePassword { get; set; }
+
+      /// <summary>
+      /// Required, Max length = 255
+      /// </summary>
+      [Required]
+      [MaxLength(255)]
+      [StringLength(255)]
+      public string AudioLanguagePreference { get; set; }
+
+      /// <summary>
+      /// Required, Max length = 255
+      /// </summary>
+      [Required]
+      [MaxLength(255)]
+      [StringLength(255)]
+      public string AuthenticationProviderId { get; set; }
+
+      /// <summary>
+      /// Max length = 65535
+      /// </summary>
+      [MaxLength(65535)]
+      [StringLength(65535)]
+      public string GroupedFolders { get; set; }
+
+      /// <summary>
+      /// Required
+      /// </summary>
+      [Required]
+      public int InvalidLoginAttemptCount { get; set; }
+
+      /// <summary>
+      /// Max length = 65535
+      /// </summary>
+      [MaxLength(65535)]
+      [StringLength(65535)]
+      public string LatestItemExcludes { get; set; }
+
+      public int? LoginAttemptsBeforeLockout { get; set; }
+
+      /// <summary>
+      /// Max length = 65535
+      /// </summary>
+      [MaxLength(65535)]
+      [StringLength(65535)]
+      public string MyMediaExcludes { get; set; }
+
+      /// <summary>
+      /// Max length = 65535
+      /// </summary>
+      [MaxLength(65535)]
+      [StringLength(65535)]
+      public string OrderedViews { get; set; }
+
+      /// <summary>
+      /// Required, Max length = 255
+      /// </summary>
+      [Required]
+      [MaxLength(255)]
+      [StringLength(255)]
+      public string SubtitleMode { get; set; }
+
+      /// <summary>
+      /// Required
+      /// </summary>
+      [Required]
+      public bool PlayDefaultAudioTrack { get; set; }
+
+      /// <summary>
+      /// Max length = 255
+      /// </summary>
+      [MaxLength(255)]
+      [StringLength(255)]
+      public string SubtitleLanguagePrefernce { get; set; }
+
+      public bool? DisplayMissingEpisodes { get; set; }
+
+      public bool? DisplayCollectionsView { get; set; }
+
+      public bool? HidePlayedInLatest { get; set; }
+
+      public bool? RememberAudioSelections { get; set; }
+
+      public bool? RememberSubtitleSelections { get; set; }
+
+      public bool? EnableNextEpisodeAutoPlay { get; set; }
+
+      public bool? EnableUserPreferenceAccess { get; set; }
+
+      /*************************************************************************
+       * Navigation properties
+       *************************************************************************/
+
+      public virtual ICollection<global::Jellyfin.Data.Entities.Group> Groups { get; protected set; }
+
+      public virtual ICollection<global::Jellyfin.Data.Entities.Permission> Permissions { get; protected set; }
+
+      public virtual ICollection<global::Jellyfin.Data.Entities.ProviderMapping> ProviderMappings { get; protected set; }
+
+      public virtual ICollection<global::Jellyfin.Data.Entities.Preference> Preferences { get; protected set; }
+
+   }
+}
+

+ 25 - 0
Jellyfin.Data/Enums/ArtKind.cs

@@ -0,0 +1,25 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated from a template.
+//
+//     Manual changes to this file may cause unexpected behavior in your application.
+//     Manual changes to this file will be overwritten if the code is regenerated.
+//
+//     Produced by Entity Framework Visual Editor
+//     https://github.com/msawczyn/EFDesigner
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+using System;
+
+namespace Jellyfin.Data.Enums
+{
+   public enum ArtKind : Int32
+   {
+      Other,
+      Poster,
+      Banner,
+      Thumbnail,
+      Logo
+   }
+}

+ 25 - 0
Jellyfin.Data/Enums/MediaFileKind.cs

@@ -0,0 +1,25 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated from a template.
+//
+//     Manual changes to this file may cause unexpected behavior in your application.
+//     Manual changes to this file will be overwritten if the code is regenerated.
+//
+//     Produced by Entity Framework Visual Editor
+//     https://github.com/msawczyn/EFDesigner
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+using System;
+
+namespace Jellyfin.Data.Enums
+{
+   public enum MediaFileKind : Int32
+   {
+      Main,
+      Sidecar,
+      AdditionalPart,
+      AlternativeFormat,
+      AdditionalStream
+   }
+}

Some files were not shown because too many files changed in this diff