Merge branch 'master' into library-pictures
This commit is contained in:
commit
b7c07f6821
|
@ -147,19 +147,42 @@ jobs:
|
||||||
displayName: 'Publish NuGet packages'
|
displayName: 'Publish NuGet packages'
|
||||||
dependsOn:
|
dependsOn:
|
||||||
- BuildPackage
|
- BuildPackage
|
||||||
condition: and(succeeded('BuildPackage'), startsWith(variables['Build.SourceBranch'], 'refs/tags'))
|
condition: succeeded('BuildPackage')
|
||||||
|
|
||||||
pool:
|
pool:
|
||||||
vmImage: 'ubuntu-latest'
|
vmImage: 'ubuntu-latest'
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- task: NuGetCommand@2
|
- task: DotNetCoreCLI@2
|
||||||
|
displayName: 'Build Stable Nuget packages'
|
||||||
|
condition: startsWith(variables['Build.SourceBranch'], 'refs/tags')
|
||||||
inputs:
|
inputs:
|
||||||
command: 'pack'
|
command: 'pack'
|
||||||
packagesToPack: Jellyfin.Data/Jellyfin.Data.csproj;MediaBrowser.Common/MediaBrowser.Common.csproj;MediaBrowser.Controller/MediaBrowser.Controller.csproj;MediaBrowser.Model/MediaBrowser.Model.csproj;Emby.Naming/Emby.Naming.csproj
|
packagesToPack: 'Jellyfin.Data/Jellyfin.Data.csproj;MediaBrowser.Common/MediaBrowser.Common.csproj;MediaBrowser.Controller/MediaBrowser.Controller.csproj;MediaBrowser.Model/MediaBrowser.Model.csproj;Emby.Naming/Emby.Naming.csproj'
|
||||||
packDestination: '$(Build.ArtifactStagingDirectory)'
|
versioningScheme: 'off'
|
||||||
|
|
||||||
|
- task: DotNetCoreCLI@2
|
||||||
|
displayName: 'Build Unstable Nuget packages'
|
||||||
|
inputs:
|
||||||
|
command: 'custom'
|
||||||
|
projects: |
|
||||||
|
Jellyfin.Data/Jellyfin.Data.csproj
|
||||||
|
MediaBrowser.Common/MediaBrowser.Common.csproj
|
||||||
|
MediaBrowser.Controller/MediaBrowser.Controller.csproj
|
||||||
|
MediaBrowser.Model/MediaBrowser.Model.csproj
|
||||||
|
Emby.Naming/Emby.Naming.csproj
|
||||||
|
custom: 'pack'
|
||||||
|
arguments: '--version-suffix $(Build.BuildNumber) -o $(Build.ArtifactStagingDirectory)'
|
||||||
|
|
||||||
|
- task: PublishBuildArtifacts@1
|
||||||
|
displayName: 'Publish Nuget packages'
|
||||||
|
inputs:
|
||||||
|
pathToPublish: $(Build.ArtifactStagingDirectory)
|
||||||
|
artifactName: Jellyfin Nuget Packages
|
||||||
|
|
||||||
- task: NuGetCommand@2
|
- task: NuGetCommand@2
|
||||||
|
displayName: 'Push Nuget packages to feed'
|
||||||
|
condition: startsWith(variables['Build.SourceBranch'], 'refs/tags')
|
||||||
inputs:
|
inputs:
|
||||||
command: 'push'
|
command: 'push'
|
||||||
packagesToPush: '$(Build.ArtifactStagingDirectory)/**/*.nupkg'
|
packagesToPush: '$(Build.ArtifactStagingDirectory)/**/*.nupkg'
|
||||||
|
|
|
@ -14,7 +14,7 @@ using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace Emby.Dlna.Eventing
|
namespace Emby.Dlna.Eventing
|
||||||
{
|
{
|
||||||
public class EventManager : IEventManager
|
public class DlnaEventManager : IDlnaEventManager
|
||||||
{
|
{
|
||||||
private readonly ConcurrentDictionary<string, EventSubscription> _subscriptions =
|
private readonly ConcurrentDictionary<string, EventSubscription> _subscriptions =
|
||||||
new ConcurrentDictionary<string, EventSubscription>(StringComparer.OrdinalIgnoreCase);
|
new ConcurrentDictionary<string, EventSubscription>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
@ -24,7 +24,7 @@ namespace Emby.Dlna.Eventing
|
||||||
|
|
||||||
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
|
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
|
||||||
|
|
||||||
public EventManager(ILogger logger, IHttpClient httpClient)
|
public DlnaEventManager(ILogger logger, IHttpClient httpClient)
|
||||||
{
|
{
|
||||||
_httpClient = httpClient;
|
_httpClient = httpClient;
|
||||||
_logger = logger;
|
_logger = logger;
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
namespace Emby.Dlna
|
namespace Emby.Dlna
|
||||||
{
|
{
|
||||||
public interface IConnectionManager : IEventManager, IUpnpService
|
public interface IConnectionManager : IDlnaEventManager, IUpnpService
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
namespace Emby.Dlna
|
namespace Emby.Dlna
|
||||||
{
|
{
|
||||||
public interface IContentDirectory : IEventManager, IUpnpService
|
public interface IContentDirectory : IDlnaEventManager, IUpnpService
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
namespace Emby.Dlna
|
namespace Emby.Dlna
|
||||||
{
|
{
|
||||||
public interface IEventManager
|
public interface IDlnaEventManager
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Cancels the event subscription.
|
/// Cancels the event subscription.
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
namespace Emby.Dlna
|
namespace Emby.Dlna
|
||||||
{
|
{
|
||||||
public interface IMediaReceiverRegistrar : IEventManager, IUpnpService
|
public interface IMediaReceiverRegistrar : IDlnaEventManager, IUpnpService
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Emby.Dlna.Didl;
|
using Emby.Dlna.Didl;
|
||||||
using Jellyfin.Data.Entities;
|
using Jellyfin.Data.Entities;
|
||||||
|
using Jellyfin.Data.Events;
|
||||||
using MediaBrowser.Common.Configuration;
|
using MediaBrowser.Common.Configuration;
|
||||||
using MediaBrowser.Controller.Dlna;
|
using MediaBrowser.Controller.Dlna;
|
||||||
using MediaBrowser.Controller.Drawing;
|
using MediaBrowser.Controller.Drawing;
|
||||||
|
@ -18,7 +19,6 @@ using MediaBrowser.Controller.Session;
|
||||||
using MediaBrowser.Model.Dlna;
|
using MediaBrowser.Model.Dlna;
|
||||||
using MediaBrowser.Model.Dto;
|
using MediaBrowser.Model.Dto;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
using MediaBrowser.Model.Events;
|
|
||||||
using MediaBrowser.Model.Globalization;
|
using MediaBrowser.Model.Globalization;
|
||||||
using MediaBrowser.Model.Session;
|
using MediaBrowser.Model.Session;
|
||||||
using Microsoft.AspNetCore.WebUtilities;
|
using Microsoft.AspNetCore.WebUtilities;
|
||||||
|
|
|
@ -6,6 +6,7 @@ using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Jellyfin.Data.Events;
|
||||||
using MediaBrowser.Common.Extensions;
|
using MediaBrowser.Common.Extensions;
|
||||||
using MediaBrowser.Common.Net;
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Controller;
|
using MediaBrowser.Controller;
|
||||||
|
@ -16,7 +17,6 @@ using MediaBrowser.Controller.Library;
|
||||||
using MediaBrowser.Controller.MediaEncoding;
|
using MediaBrowser.Controller.MediaEncoding;
|
||||||
using MediaBrowser.Controller.Session;
|
using MediaBrowser.Controller.Session;
|
||||||
using MediaBrowser.Model.Dlna;
|
using MediaBrowser.Model.Dlna;
|
||||||
using MediaBrowser.Model.Events;
|
|
||||||
using MediaBrowser.Model.Globalization;
|
using MediaBrowser.Model.Globalization;
|
||||||
using MediaBrowser.Model.Session;
|
using MediaBrowser.Model.Session;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
|
@ -6,17 +6,17 @@ using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace Emby.Dlna.Service
|
namespace Emby.Dlna.Service
|
||||||
{
|
{
|
||||||
public class BaseService : IEventManager
|
public class BaseService : IDlnaEventManager
|
||||||
{
|
{
|
||||||
protected BaseService(ILogger<BaseService> logger, IHttpClient httpClient)
|
protected BaseService(ILogger<BaseService> logger, IHttpClient httpClient)
|
||||||
{
|
{
|
||||||
Logger = logger;
|
Logger = logger;
|
||||||
HttpClient = httpClient;
|
HttpClient = httpClient;
|
||||||
|
|
||||||
EventManager = new EventManager(logger, HttpClient);
|
EventManager = new DlnaEventManager(logger, HttpClient);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected IEventManager EventManager { get; }
|
protected IDlnaEventManager EventManager { get; }
|
||||||
|
|
||||||
protected IHttpClient HttpClient { get; }
|
protected IHttpClient HttpClient { get; }
|
||||||
|
|
||||||
|
|
|
@ -3,9 +3,9 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Jellyfin.Data.Events;
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
using MediaBrowser.Model.Dlna;
|
using MediaBrowser.Model.Dlna;
|
||||||
using MediaBrowser.Model.Events;
|
|
||||||
using Rssdp;
|
using Rssdp;
|
||||||
using Rssdp.Infrastructure;
|
using Rssdp.Infrastructure;
|
||||||
|
|
||||||
|
|
|
@ -23,8 +23,9 @@
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Authors>Jellyfin Contributors</Authors>
|
<Authors>Jellyfin Contributors</Authors>
|
||||||
<PackageId>Jellyfin.Naming</PackageId>
|
<PackageId>Jellyfin.Naming</PackageId>
|
||||||
<PackageLicenseUrl>https://www.gnu.org/licenses/old-licenses/gpl-2.0.txt</PackageLicenseUrl>
|
<VersionPrefix>10.7.0</VersionPrefix>
|
||||||
<RepositoryUrl>https://github.com/jellyfin/jellyfin</RepositoryUrl>
|
<RepositoryUrl>https://github.com/jellyfin/jellyfin</RepositoryUrl>
|
||||||
|
<PackageLicenseExpression>GPL-3.0-only</PackageLicenseExpression>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<!-- Code Analyzers-->
|
<!-- Code Analyzers-->
|
||||||
|
|
|
@ -4,6 +4,7 @@ using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Jellyfin.Data.Events;
|
||||||
using MediaBrowser.Common.Configuration;
|
using MediaBrowser.Common.Configuration;
|
||||||
using MediaBrowser.Controller;
|
using MediaBrowser.Controller;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
|
@ -13,7 +14,6 @@ using MediaBrowser.Controller.Library;
|
||||||
using MediaBrowser.Controller.Notifications;
|
using MediaBrowser.Controller.Notifications;
|
||||||
using MediaBrowser.Controller.Plugins;
|
using MediaBrowser.Controller.Plugins;
|
||||||
using MediaBrowser.Model.Activity;
|
using MediaBrowser.Model.Activity;
|
||||||
using MediaBrowser.Model.Events;
|
|
||||||
using MediaBrowser.Model.Globalization;
|
using MediaBrowser.Model.Globalization;
|
||||||
using MediaBrowser.Model.Notifications;
|
using MediaBrowser.Model.Notifications;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
|
@ -1,590 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Globalization;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Jellyfin.Data.Entities;
|
|
||||||
using MediaBrowser.Common.Plugins;
|
|
||||||
using MediaBrowser.Common.Updates;
|
|
||||||
using MediaBrowser.Controller.Authentication;
|
|
||||||
using MediaBrowser.Controller.Library;
|
|
||||||
using MediaBrowser.Controller.Plugins;
|
|
||||||
using MediaBrowser.Controller.Session;
|
|
||||||
using MediaBrowser.Controller.Subtitles;
|
|
||||||
using MediaBrowser.Model.Activity;
|
|
||||||
using MediaBrowser.Model.Dto;
|
|
||||||
using MediaBrowser.Model.Entities;
|
|
||||||
using MediaBrowser.Model.Events;
|
|
||||||
using MediaBrowser.Model.Globalization;
|
|
||||||
using MediaBrowser.Model.Notifications;
|
|
||||||
using MediaBrowser.Model.Tasks;
|
|
||||||
using MediaBrowser.Model.Updates;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
|
|
||||||
namespace Emby.Server.Implementations.Activity
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Entry point for the activity logger.
|
|
||||||
/// </summary>
|
|
||||||
public sealed class ActivityLogEntryPoint : IServerEntryPoint
|
|
||||||
{
|
|
||||||
private readonly ILogger<ActivityLogEntryPoint> _logger;
|
|
||||||
private readonly IInstallationManager _installationManager;
|
|
||||||
private readonly ISessionManager _sessionManager;
|
|
||||||
private readonly ITaskManager _taskManager;
|
|
||||||
private readonly IActivityManager _activityManager;
|
|
||||||
private readonly ILocalizationManager _localization;
|
|
||||||
private readonly ISubtitleManager _subManager;
|
|
||||||
private readonly IUserManager _userManager;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="ActivityLogEntryPoint"/> class.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="logger">The logger.</param>
|
|
||||||
/// <param name="sessionManager">The session manager.</param>
|
|
||||||
/// <param name="taskManager">The task manager.</param>
|
|
||||||
/// <param name="activityManager">The activity manager.</param>
|
|
||||||
/// <param name="localization">The localization manager.</param>
|
|
||||||
/// <param name="installationManager">The installation manager.</param>
|
|
||||||
/// <param name="subManager">The subtitle manager.</param>
|
|
||||||
/// <param name="userManager">The user manager.</param>
|
|
||||||
public ActivityLogEntryPoint(
|
|
||||||
ILogger<ActivityLogEntryPoint> logger,
|
|
||||||
ISessionManager sessionManager,
|
|
||||||
ITaskManager taskManager,
|
|
||||||
IActivityManager activityManager,
|
|
||||||
ILocalizationManager localization,
|
|
||||||
IInstallationManager installationManager,
|
|
||||||
ISubtitleManager subManager,
|
|
||||||
IUserManager userManager)
|
|
||||||
{
|
|
||||||
_logger = logger;
|
|
||||||
_sessionManager = sessionManager;
|
|
||||||
_taskManager = taskManager;
|
|
||||||
_activityManager = activityManager;
|
|
||||||
_localization = localization;
|
|
||||||
_installationManager = installationManager;
|
|
||||||
_subManager = subManager;
|
|
||||||
_userManager = userManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public Task RunAsync()
|
|
||||||
{
|
|
||||||
_taskManager.TaskCompleted += OnTaskCompleted;
|
|
||||||
|
|
||||||
_installationManager.PluginInstalled += OnPluginInstalled;
|
|
||||||
_installationManager.PluginUninstalled += OnPluginUninstalled;
|
|
||||||
_installationManager.PluginUpdated += OnPluginUpdated;
|
|
||||||
_installationManager.PackageInstallationFailed += OnPackageInstallationFailed;
|
|
||||||
|
|
||||||
_sessionManager.SessionStarted += OnSessionStarted;
|
|
||||||
_sessionManager.AuthenticationFailed += OnAuthenticationFailed;
|
|
||||||
_sessionManager.AuthenticationSucceeded += OnAuthenticationSucceeded;
|
|
||||||
_sessionManager.SessionEnded += OnSessionEnded;
|
|
||||||
_sessionManager.PlaybackStart += OnPlaybackStart;
|
|
||||||
_sessionManager.PlaybackStopped += OnPlaybackStopped;
|
|
||||||
|
|
||||||
_subManager.SubtitleDownloadFailure += OnSubtitleDownloadFailure;
|
|
||||||
|
|
||||||
_userManager.OnUserCreated += OnUserCreated;
|
|
||||||
_userManager.OnUserPasswordChanged += OnUserPasswordChanged;
|
|
||||||
_userManager.OnUserDeleted += OnUserDeleted;
|
|
||||||
_userManager.OnUserLockedOut += OnUserLockedOut;
|
|
||||||
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void OnUserLockedOut(object sender, GenericEventArgs<User> e)
|
|
||||||
{
|
|
||||||
await CreateLogEntry(new ActivityLog(
|
|
||||||
string.Format(
|
|
||||||
CultureInfo.InvariantCulture,
|
|
||||||
_localization.GetLocalizedString("UserLockedOutWithName"),
|
|
||||||
e.Argument.Username),
|
|
||||||
NotificationType.UserLockedOut.ToString(),
|
|
||||||
e.Argument.Id)
|
|
||||||
{
|
|
||||||
LogSeverity = LogLevel.Error
|
|
||||||
}).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void OnSubtitleDownloadFailure(object sender, SubtitleDownloadFailureEventArgs e)
|
|
||||||
{
|
|
||||||
await CreateLogEntry(new ActivityLog(
|
|
||||||
string.Format(
|
|
||||||
CultureInfo.InvariantCulture,
|
|
||||||
_localization.GetLocalizedString("SubtitleDownloadFailureFromForItem"),
|
|
||||||
e.Provider,
|
|
||||||
Notifications.NotificationEntryPoint.GetItemName(e.Item)),
|
|
||||||
"SubtitleDownloadFailure",
|
|
||||||
Guid.Empty)
|
|
||||||
{
|
|
||||||
ItemId = e.Item.Id.ToString("N", CultureInfo.InvariantCulture),
|
|
||||||
ShortOverview = e.Exception.Message
|
|
||||||
}).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void OnPlaybackStopped(object sender, PlaybackStopEventArgs e)
|
|
||||||
{
|
|
||||||
var item = e.MediaInfo;
|
|
||||||
|
|
||||||
if (item == null)
|
|
||||||
{
|
|
||||||
_logger.LogWarning("PlaybackStopped reported with null media info.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e.Item != null && e.Item.IsThemeMedia)
|
|
||||||
{
|
|
||||||
// Don't report theme song or local trailer playback
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e.Users.Count == 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var user = e.Users[0];
|
|
||||||
|
|
||||||
await CreateLogEntry(new ActivityLog(
|
|
||||||
string.Format(
|
|
||||||
CultureInfo.InvariantCulture,
|
|
||||||
_localization.GetLocalizedString("UserStoppedPlayingItemWithValues"),
|
|
||||||
user.Username,
|
|
||||||
GetItemName(item),
|
|
||||||
e.DeviceName),
|
|
||||||
GetPlaybackStoppedNotificationType(item.MediaType),
|
|
||||||
user.Id))
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void OnPlaybackStart(object sender, PlaybackProgressEventArgs e)
|
|
||||||
{
|
|
||||||
var item = e.MediaInfo;
|
|
||||||
|
|
||||||
if (item == null)
|
|
||||||
{
|
|
||||||
_logger.LogWarning("PlaybackStart reported with null media info.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e.Item != null && e.Item.IsThemeMedia)
|
|
||||||
{
|
|
||||||
// Don't report theme song or local trailer playback
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e.Users.Count == 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var user = e.Users.First();
|
|
||||||
|
|
||||||
await CreateLogEntry(new ActivityLog(
|
|
||||||
string.Format(
|
|
||||||
CultureInfo.InvariantCulture,
|
|
||||||
_localization.GetLocalizedString("UserStartedPlayingItemWithValues"),
|
|
||||||
user.Username,
|
|
||||||
GetItemName(item),
|
|
||||||
e.DeviceName),
|
|
||||||
GetPlaybackNotificationType(item.MediaType),
|
|
||||||
user.Id))
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string GetItemName(BaseItemDto item)
|
|
||||||
{
|
|
||||||
var name = item.Name;
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(item.SeriesName))
|
|
||||||
{
|
|
||||||
name = item.SeriesName + " - " + name;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item.Artists != null && item.Artists.Count > 0)
|
|
||||||
{
|
|
||||||
name = item.Artists[0] + " - " + name;
|
|
||||||
}
|
|
||||||
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string GetPlaybackNotificationType(string mediaType)
|
|
||||||
{
|
|
||||||
if (string.Equals(mediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
return NotificationType.AudioPlayback.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string.Equals(mediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
return NotificationType.VideoPlayback.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string GetPlaybackStoppedNotificationType(string mediaType)
|
|
||||||
{
|
|
||||||
if (string.Equals(mediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
return NotificationType.AudioPlaybackStopped.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string.Equals(mediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
return NotificationType.VideoPlaybackStopped.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void OnSessionEnded(object sender, SessionEventArgs e)
|
|
||||||
{
|
|
||||||
var session = e.SessionInfo;
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(session.UserName))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await CreateLogEntry(new ActivityLog(
|
|
||||||
string.Format(
|
|
||||||
CultureInfo.InvariantCulture,
|
|
||||||
_localization.GetLocalizedString("UserOfflineFromDevice"),
|
|
||||||
session.UserName,
|
|
||||||
session.DeviceName),
|
|
||||||
"SessionEnded",
|
|
||||||
session.UserId)
|
|
||||||
{
|
|
||||||
ShortOverview = string.Format(
|
|
||||||
CultureInfo.InvariantCulture,
|
|
||||||
_localization.GetLocalizedString("LabelIpAddressValue"),
|
|
||||||
session.RemoteEndPoint),
|
|
||||||
}).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void OnAuthenticationSucceeded(object sender, GenericEventArgs<AuthenticationResult> e)
|
|
||||||
{
|
|
||||||
var user = e.Argument.User;
|
|
||||||
|
|
||||||
await CreateLogEntry(new ActivityLog(
|
|
||||||
string.Format(
|
|
||||||
CultureInfo.InvariantCulture,
|
|
||||||
_localization.GetLocalizedString("AuthenticationSucceededWithUserName"),
|
|
||||||
user.Name),
|
|
||||||
"AuthenticationSucceeded",
|
|
||||||
user.Id)
|
|
||||||
{
|
|
||||||
ShortOverview = string.Format(
|
|
||||||
CultureInfo.InvariantCulture,
|
|
||||||
_localization.GetLocalizedString("LabelIpAddressValue"),
|
|
||||||
e.Argument.SessionInfo.RemoteEndPoint),
|
|
||||||
}).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void OnAuthenticationFailed(object sender, GenericEventArgs<AuthenticationRequest> e)
|
|
||||||
{
|
|
||||||
await CreateLogEntry(new ActivityLog(
|
|
||||||
string.Format(
|
|
||||||
CultureInfo.InvariantCulture,
|
|
||||||
_localization.GetLocalizedString("FailedLoginAttemptWithUserName"),
|
|
||||||
e.Argument.Username),
|
|
||||||
"AuthenticationFailed",
|
|
||||||
Guid.Empty)
|
|
||||||
{
|
|
||||||
LogSeverity = LogLevel.Error,
|
|
||||||
ShortOverview = string.Format(
|
|
||||||
CultureInfo.InvariantCulture,
|
|
||||||
_localization.GetLocalizedString("LabelIpAddressValue"),
|
|
||||||
e.Argument.RemoteEndPoint),
|
|
||||||
}).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void OnUserDeleted(object sender, GenericEventArgs<User> e)
|
|
||||||
{
|
|
||||||
await CreateLogEntry(new ActivityLog(
|
|
||||||
string.Format(
|
|
||||||
CultureInfo.InvariantCulture,
|
|
||||||
_localization.GetLocalizedString("UserDeletedWithName"),
|
|
||||||
e.Argument.Username),
|
|
||||||
"UserDeleted",
|
|
||||||
Guid.Empty))
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void OnUserPasswordChanged(object sender, GenericEventArgs<User> e)
|
|
||||||
{
|
|
||||||
await CreateLogEntry(new ActivityLog(
|
|
||||||
string.Format(
|
|
||||||
CultureInfo.InvariantCulture,
|
|
||||||
_localization.GetLocalizedString("UserPasswordChangedWithName"),
|
|
||||||
e.Argument.Username),
|
|
||||||
"UserPasswordChanged",
|
|
||||||
e.Argument.Id))
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void OnUserCreated(object sender, GenericEventArgs<User> e)
|
|
||||||
{
|
|
||||||
await CreateLogEntry(new ActivityLog(
|
|
||||||
string.Format(
|
|
||||||
CultureInfo.InvariantCulture,
|
|
||||||
_localization.GetLocalizedString("UserCreatedWithName"),
|
|
||||||
e.Argument.Username),
|
|
||||||
"UserCreated",
|
|
||||||
e.Argument.Id))
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void OnSessionStarted(object sender, SessionEventArgs e)
|
|
||||||
{
|
|
||||||
var session = e.SessionInfo;
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(session.UserName))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await CreateLogEntry(new ActivityLog(
|
|
||||||
string.Format(
|
|
||||||
CultureInfo.InvariantCulture,
|
|
||||||
_localization.GetLocalizedString("UserOnlineFromDevice"),
|
|
||||||
session.UserName,
|
|
||||||
session.DeviceName),
|
|
||||||
"SessionStarted",
|
|
||||||
session.UserId)
|
|
||||||
{
|
|
||||||
ShortOverview = string.Format(
|
|
||||||
CultureInfo.InvariantCulture,
|
|
||||||
_localization.GetLocalizedString("LabelIpAddressValue"),
|
|
||||||
session.RemoteEndPoint)
|
|
||||||
}).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void OnPluginUpdated(object sender, InstallationInfo e)
|
|
||||||
{
|
|
||||||
await CreateLogEntry(new ActivityLog(
|
|
||||||
string.Format(
|
|
||||||
CultureInfo.InvariantCulture,
|
|
||||||
_localization.GetLocalizedString("PluginUpdatedWithName"),
|
|
||||||
e.Name),
|
|
||||||
NotificationType.PluginUpdateInstalled.ToString(),
|
|
||||||
Guid.Empty)
|
|
||||||
{
|
|
||||||
ShortOverview = string.Format(
|
|
||||||
CultureInfo.InvariantCulture,
|
|
||||||
_localization.GetLocalizedString("VersionNumber"),
|
|
||||||
e.Version),
|
|
||||||
Overview = e.Changelog
|
|
||||||
}).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void OnPluginUninstalled(object sender, IPlugin e)
|
|
||||||
{
|
|
||||||
await CreateLogEntry(new ActivityLog(
|
|
||||||
string.Format(
|
|
||||||
CultureInfo.InvariantCulture,
|
|
||||||
_localization.GetLocalizedString("PluginUninstalledWithName"),
|
|
||||||
e.Name),
|
|
||||||
NotificationType.PluginUninstalled.ToString(),
|
|
||||||
Guid.Empty))
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void OnPluginInstalled(object sender, InstallationInfo e)
|
|
||||||
{
|
|
||||||
await CreateLogEntry(new ActivityLog(
|
|
||||||
string.Format(
|
|
||||||
CultureInfo.InvariantCulture,
|
|
||||||
_localization.GetLocalizedString("PluginInstalledWithName"),
|
|
||||||
e.Name),
|
|
||||||
NotificationType.PluginInstalled.ToString(),
|
|
||||||
Guid.Empty)
|
|
||||||
{
|
|
||||||
ShortOverview = string.Format(
|
|
||||||
CultureInfo.InvariantCulture,
|
|
||||||
_localization.GetLocalizedString("VersionNumber"),
|
|
||||||
e.Version)
|
|
||||||
}).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void OnPackageInstallationFailed(object sender, InstallationFailedEventArgs e)
|
|
||||||
{
|
|
||||||
var installationInfo = e.InstallationInfo;
|
|
||||||
|
|
||||||
await CreateLogEntry(new ActivityLog(
|
|
||||||
string.Format(
|
|
||||||
CultureInfo.InvariantCulture,
|
|
||||||
_localization.GetLocalizedString("NameInstallFailed"),
|
|
||||||
installationInfo.Name),
|
|
||||||
NotificationType.InstallationFailed.ToString(),
|
|
||||||
Guid.Empty)
|
|
||||||
{
|
|
||||||
ShortOverview = string.Format(
|
|
||||||
CultureInfo.InvariantCulture,
|
|
||||||
_localization.GetLocalizedString("VersionNumber"),
|
|
||||||
installationInfo.Version),
|
|
||||||
Overview = e.Exception.Message
|
|
||||||
}).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void OnTaskCompleted(object sender, TaskCompletionEventArgs e)
|
|
||||||
{
|
|
||||||
var result = e.Result;
|
|
||||||
var task = e.Task;
|
|
||||||
|
|
||||||
if (task.ScheduledTask is IConfigurableScheduledTask activityTask
|
|
||||||
&& !activityTask.IsLogged)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var time = result.EndTimeUtc - result.StartTimeUtc;
|
|
||||||
var runningTime = string.Format(
|
|
||||||
CultureInfo.InvariantCulture,
|
|
||||||
_localization.GetLocalizedString("LabelRunningTimeValue"),
|
|
||||||
ToUserFriendlyString(time));
|
|
||||||
|
|
||||||
if (result.Status == TaskCompletionStatus.Failed)
|
|
||||||
{
|
|
||||||
var vals = new List<string>();
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(e.Result.ErrorMessage))
|
|
||||||
{
|
|
||||||
vals.Add(e.Result.ErrorMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(e.Result.LongErrorMessage))
|
|
||||||
{
|
|
||||||
vals.Add(e.Result.LongErrorMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
await CreateLogEntry(new ActivityLog(
|
|
||||||
string.Format(CultureInfo.InvariantCulture, _localization.GetLocalizedString("ScheduledTaskFailedWithName"), task.Name),
|
|
||||||
NotificationType.TaskFailed.ToString(),
|
|
||||||
Guid.Empty)
|
|
||||||
{
|
|
||||||
LogSeverity = LogLevel.Error,
|
|
||||||
Overview = string.Join(Environment.NewLine, vals),
|
|
||||||
ShortOverview = runningTime
|
|
||||||
}).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task CreateLogEntry(ActivityLog entry)
|
|
||||||
=> await _activityManager.CreateAsync(entry).ConfigureAwait(false);
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
_taskManager.TaskCompleted -= OnTaskCompleted;
|
|
||||||
|
|
||||||
_installationManager.PluginInstalled -= OnPluginInstalled;
|
|
||||||
_installationManager.PluginUninstalled -= OnPluginUninstalled;
|
|
||||||
_installationManager.PluginUpdated -= OnPluginUpdated;
|
|
||||||
_installationManager.PackageInstallationFailed -= OnPackageInstallationFailed;
|
|
||||||
|
|
||||||
_sessionManager.SessionStarted -= OnSessionStarted;
|
|
||||||
_sessionManager.AuthenticationFailed -= OnAuthenticationFailed;
|
|
||||||
_sessionManager.AuthenticationSucceeded -= OnAuthenticationSucceeded;
|
|
||||||
_sessionManager.SessionEnded -= OnSessionEnded;
|
|
||||||
|
|
||||||
_sessionManager.PlaybackStart -= OnPlaybackStart;
|
|
||||||
_sessionManager.PlaybackStopped -= OnPlaybackStopped;
|
|
||||||
|
|
||||||
_subManager.SubtitleDownloadFailure -= OnSubtitleDownloadFailure;
|
|
||||||
|
|
||||||
_userManager.OnUserCreated -= OnUserCreated;
|
|
||||||
_userManager.OnUserPasswordChanged -= OnUserPasswordChanged;
|
|
||||||
_userManager.OnUserDeleted -= OnUserDeleted;
|
|
||||||
_userManager.OnUserLockedOut -= OnUserLockedOut;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Constructs a user-friendly string for this TimeSpan instance.
|
|
||||||
/// </summary>
|
|
||||||
private static string ToUserFriendlyString(TimeSpan span)
|
|
||||||
{
|
|
||||||
const int DaysInYear = 365;
|
|
||||||
const int DaysInMonth = 30;
|
|
||||||
|
|
||||||
// Get each non-zero value from TimeSpan component
|
|
||||||
var values = new List<string>();
|
|
||||||
|
|
||||||
// Number of years
|
|
||||||
int days = span.Days;
|
|
||||||
if (days >= DaysInYear)
|
|
||||||
{
|
|
||||||
int years = days / DaysInYear;
|
|
||||||
values.Add(CreateValueString(years, "year"));
|
|
||||||
days %= DaysInYear;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Number of months
|
|
||||||
if (days >= DaysInMonth)
|
|
||||||
{
|
|
||||||
int months = days / DaysInMonth;
|
|
||||||
values.Add(CreateValueString(months, "month"));
|
|
||||||
days = days % DaysInMonth;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Number of days
|
|
||||||
if (days >= 1)
|
|
||||||
{
|
|
||||||
values.Add(CreateValueString(days, "day"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Number of hours
|
|
||||||
if (span.Hours >= 1)
|
|
||||||
{
|
|
||||||
values.Add(CreateValueString(span.Hours, "hour"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Number of minutes
|
|
||||||
if (span.Minutes >= 1)
|
|
||||||
{
|
|
||||||
values.Add(CreateValueString(span.Minutes, "minute"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Number of seconds (include when 0 if no other components included)
|
|
||||||
if (span.Seconds >= 1 || values.Count == 0)
|
|
||||||
{
|
|
||||||
values.Add(CreateValueString(span.Seconds, "second"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Combine values into string
|
|
||||||
var builder = new StringBuilder();
|
|
||||||
for (int i = 0; i < values.Count; i++)
|
|
||||||
{
|
|
||||||
if (builder.Length > 0)
|
|
||||||
{
|
|
||||||
builder.Append(i == values.Count - 1 ? " and " : ", ");
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.Append(values[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return result
|
|
||||||
return builder.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Constructs a string description of a time-span value.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="value">The value of this item.</param>
|
|
||||||
/// <param name="description">The name of this item (singular form).</param>
|
|
||||||
private static string CreateValueString(int value, string description)
|
|
||||||
{
|
|
||||||
return string.Format(
|
|
||||||
CultureInfo.InvariantCulture,
|
|
||||||
"{0:#,##0} {1}",
|
|
||||||
value,
|
|
||||||
value == 1 ? description : string.Format(CultureInfo.InvariantCulture, "{0}s", description));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -53,7 +53,6 @@ using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Common.Plugins;
|
using MediaBrowser.Common.Plugins;
|
||||||
using MediaBrowser.Common.Updates;
|
using MediaBrowser.Common.Updates;
|
||||||
using MediaBrowser.Controller;
|
using MediaBrowser.Controller;
|
||||||
using MediaBrowser.Controller.Authentication;
|
|
||||||
using MediaBrowser.Controller.Channels;
|
using MediaBrowser.Controller.Channels;
|
||||||
using MediaBrowser.Controller.Chapters;
|
using MediaBrowser.Controller.Chapters;
|
||||||
using MediaBrowser.Controller.Collections;
|
using MediaBrowser.Controller.Collections;
|
||||||
|
@ -173,6 +172,8 @@ namespace Emby.Server.Implementations
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected ILogger<ApplicationHost> Logger { get; }
|
protected ILogger<ApplicationHost> Logger { get; }
|
||||||
|
|
||||||
|
protected IServiceCollection ServiceCollection { get; }
|
||||||
|
|
||||||
private IPlugin[] _plugins;
|
private IPlugin[] _plugins;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -238,9 +239,11 @@ namespace Emby.Server.Implementations
|
||||||
ILoggerFactory loggerFactory,
|
ILoggerFactory loggerFactory,
|
||||||
IStartupOptions options,
|
IStartupOptions options,
|
||||||
IFileSystem fileSystem,
|
IFileSystem fileSystem,
|
||||||
INetworkManager networkManager)
|
INetworkManager networkManager,
|
||||||
|
IServiceCollection serviceCollection)
|
||||||
{
|
{
|
||||||
_xmlSerializer = new MyXmlSerializer();
|
_xmlSerializer = new MyXmlSerializer();
|
||||||
|
ServiceCollection = serviceCollection;
|
||||||
|
|
||||||
_networkManager = networkManager;
|
_networkManager = networkManager;
|
||||||
networkManager.LocalSubnetsFn = GetConfiguredLocalSubnets;
|
networkManager.LocalSubnetsFn = GetConfiguredLocalSubnets;
|
||||||
|
@ -464,7 +467,7 @@ namespace Emby.Server.Implementations
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void Init(IServiceCollection serviceCollection)
|
public void Init()
|
||||||
{
|
{
|
||||||
HttpPort = ServerConfigurationManager.Configuration.HttpServerPortNumber;
|
HttpPort = ServerConfigurationManager.Configuration.HttpServerPortNumber;
|
||||||
HttpsPort = ServerConfigurationManager.Configuration.HttpsPortNumber;
|
HttpsPort = ServerConfigurationManager.Configuration.HttpsPortNumber;
|
||||||
|
@ -493,7 +496,7 @@ namespace Emby.Server.Implementations
|
||||||
|
|
||||||
DiscoverTypes();
|
DiscoverTypes();
|
||||||
|
|
||||||
RegisterServices(serviceCollection);
|
RegisterServices();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task ExecuteHttpHandlerAsync(HttpContext context, Func<Task> next)
|
public Task ExecuteHttpHandlerAsync(HttpContext context, Func<Task> next)
|
||||||
|
@ -502,139 +505,139 @@ namespace Emby.Server.Implementations
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Registers services/resources with the service collection that will be available via DI.
|
/// Registers services/resources with the service collection that will be available via DI.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected virtual void RegisterServices(IServiceCollection serviceCollection)
|
protected virtual void RegisterServices()
|
||||||
{
|
{
|
||||||
serviceCollection.AddSingleton(_startupOptions);
|
ServiceCollection.AddSingleton(_startupOptions);
|
||||||
|
|
||||||
serviceCollection.AddMemoryCache();
|
ServiceCollection.AddMemoryCache();
|
||||||
|
|
||||||
serviceCollection.AddSingleton(ConfigurationManager);
|
ServiceCollection.AddSingleton(ConfigurationManager);
|
||||||
serviceCollection.AddSingleton<IApplicationHost>(this);
|
ServiceCollection.AddSingleton<IApplicationHost>(this);
|
||||||
|
|
||||||
serviceCollection.AddSingleton<IApplicationPaths>(ApplicationPaths);
|
ServiceCollection.AddSingleton<IApplicationPaths>(ApplicationPaths);
|
||||||
|
|
||||||
serviceCollection.AddSingleton<IJsonSerializer, JsonSerializer>();
|
ServiceCollection.AddSingleton<IJsonSerializer, JsonSerializer>();
|
||||||
|
|
||||||
serviceCollection.AddSingleton(_fileSystemManager);
|
ServiceCollection.AddSingleton(_fileSystemManager);
|
||||||
serviceCollection.AddSingleton<TvdbClientManager>();
|
ServiceCollection.AddSingleton<TvdbClientManager>();
|
||||||
|
|
||||||
serviceCollection.AddSingleton<IHttpClient, HttpClientManager.HttpClientManager>();
|
ServiceCollection.AddSingleton<IHttpClient, HttpClientManager.HttpClientManager>();
|
||||||
|
|
||||||
serviceCollection.AddSingleton(_networkManager);
|
ServiceCollection.AddSingleton(_networkManager);
|
||||||
|
|
||||||
serviceCollection.AddSingleton<IIsoManager, IsoManager>();
|
ServiceCollection.AddSingleton<IIsoManager, IsoManager>();
|
||||||
|
|
||||||
serviceCollection.AddSingleton<ITaskManager, TaskManager>();
|
ServiceCollection.AddSingleton<ITaskManager, TaskManager>();
|
||||||
|
|
||||||
serviceCollection.AddSingleton(_xmlSerializer);
|
ServiceCollection.AddSingleton(_xmlSerializer);
|
||||||
|
|
||||||
serviceCollection.AddSingleton<IStreamHelper, StreamHelper>();
|
ServiceCollection.AddSingleton<IStreamHelper, StreamHelper>();
|
||||||
|
|
||||||
serviceCollection.AddSingleton<ICryptoProvider, CryptographyProvider>();
|
ServiceCollection.AddSingleton<ICryptoProvider, CryptographyProvider>();
|
||||||
|
|
||||||
serviceCollection.AddSingleton<ISocketFactory, SocketFactory>();
|
ServiceCollection.AddSingleton<ISocketFactory, SocketFactory>();
|
||||||
|
|
||||||
serviceCollection.AddSingleton<IInstallationManager, InstallationManager>();
|
ServiceCollection.AddSingleton<IInstallationManager, InstallationManager>();
|
||||||
|
|
||||||
serviceCollection.AddSingleton<IZipClient, ZipClient>();
|
ServiceCollection.AddSingleton<IZipClient, ZipClient>();
|
||||||
|
|
||||||
serviceCollection.AddSingleton<IHttpResultFactory, HttpResultFactory>();
|
ServiceCollection.AddSingleton<IHttpResultFactory, HttpResultFactory>();
|
||||||
|
|
||||||
serviceCollection.AddSingleton<IServerApplicationHost>(this);
|
ServiceCollection.AddSingleton<IServerApplicationHost>(this);
|
||||||
serviceCollection.AddSingleton<IServerApplicationPaths>(ApplicationPaths);
|
ServiceCollection.AddSingleton<IServerApplicationPaths>(ApplicationPaths);
|
||||||
|
|
||||||
serviceCollection.AddSingleton(ServerConfigurationManager);
|
ServiceCollection.AddSingleton(ServerConfigurationManager);
|
||||||
|
|
||||||
serviceCollection.AddSingleton<ILocalizationManager, LocalizationManager>();
|
ServiceCollection.AddSingleton<ILocalizationManager, LocalizationManager>();
|
||||||
|
|
||||||
serviceCollection.AddSingleton<IBlurayExaminer, BdInfoExaminer>();
|
ServiceCollection.AddSingleton<IBlurayExaminer, BdInfoExaminer>();
|
||||||
|
|
||||||
serviceCollection.AddSingleton<IUserDataRepository, SqliteUserDataRepository>();
|
ServiceCollection.AddSingleton<IUserDataRepository, SqliteUserDataRepository>();
|
||||||
serviceCollection.AddSingleton<IUserDataManager, UserDataManager>();
|
ServiceCollection.AddSingleton<IUserDataManager, UserDataManager>();
|
||||||
|
|
||||||
serviceCollection.AddSingleton<IItemRepository, SqliteItemRepository>();
|
ServiceCollection.AddSingleton<IItemRepository, SqliteItemRepository>();
|
||||||
|
|
||||||
serviceCollection.AddSingleton<IAuthenticationRepository, AuthenticationRepository>();
|
ServiceCollection.AddSingleton<IAuthenticationRepository, AuthenticationRepository>();
|
||||||
|
|
||||||
// TODO: Refactor to eliminate the circular dependency here so that Lazy<T> isn't required
|
// TODO: Refactor to eliminate the circular dependency here so that Lazy<T> isn't required
|
||||||
serviceCollection.AddTransient(provider => new Lazy<IDtoService>(provider.GetRequiredService<IDtoService>));
|
ServiceCollection.AddTransient(provider => new Lazy<IDtoService>(provider.GetRequiredService<IDtoService>));
|
||||||
|
|
||||||
// TODO: Refactor to eliminate the circular dependency here so that Lazy<T> isn't required
|
// TODO: Refactor to eliminate the circular dependency here so that Lazy<T> isn't required
|
||||||
serviceCollection.AddTransient(provider => new Lazy<EncodingHelper>(provider.GetRequiredService<EncodingHelper>));
|
ServiceCollection.AddTransient(provider => new Lazy<EncodingHelper>(provider.GetRequiredService<EncodingHelper>));
|
||||||
serviceCollection.AddSingleton<IMediaEncoder, MediaBrowser.MediaEncoding.Encoder.MediaEncoder>();
|
ServiceCollection.AddSingleton<IMediaEncoder, MediaBrowser.MediaEncoding.Encoder.MediaEncoder>();
|
||||||
|
|
||||||
// TODO: Refactor to eliminate the circular dependencies here so that Lazy<T> isn't required
|
// TODO: Refactor to eliminate the circular dependencies here so that Lazy<T> isn't required
|
||||||
serviceCollection.AddTransient(provider => new Lazy<ILibraryMonitor>(provider.GetRequiredService<ILibraryMonitor>));
|
ServiceCollection.AddTransient(provider => new Lazy<ILibraryMonitor>(provider.GetRequiredService<ILibraryMonitor>));
|
||||||
serviceCollection.AddTransient(provider => new Lazy<IProviderManager>(provider.GetRequiredService<IProviderManager>));
|
ServiceCollection.AddTransient(provider => new Lazy<IProviderManager>(provider.GetRequiredService<IProviderManager>));
|
||||||
serviceCollection.AddTransient(provider => new Lazy<IUserViewManager>(provider.GetRequiredService<IUserViewManager>));
|
ServiceCollection.AddTransient(provider => new Lazy<IUserViewManager>(provider.GetRequiredService<IUserViewManager>));
|
||||||
serviceCollection.AddSingleton<ILibraryManager, LibraryManager>();
|
ServiceCollection.AddSingleton<ILibraryManager, LibraryManager>();
|
||||||
|
|
||||||
serviceCollection.AddSingleton<IMusicManager, MusicManager>();
|
ServiceCollection.AddSingleton<IMusicManager, MusicManager>();
|
||||||
|
|
||||||
serviceCollection.AddSingleton<ILibraryMonitor, LibraryMonitor>();
|
ServiceCollection.AddSingleton<ILibraryMonitor, LibraryMonitor>();
|
||||||
|
|
||||||
serviceCollection.AddSingleton<ISearchEngine, SearchEngine>();
|
ServiceCollection.AddSingleton<ISearchEngine, SearchEngine>();
|
||||||
|
|
||||||
serviceCollection.AddSingleton<ServiceController>();
|
ServiceCollection.AddSingleton<ServiceController>();
|
||||||
serviceCollection.AddSingleton<IHttpServer, HttpListenerHost>();
|
ServiceCollection.AddSingleton<IHttpServer, HttpListenerHost>();
|
||||||
|
|
||||||
serviceCollection.AddSingleton<IImageProcessor, ImageProcessor>();
|
ServiceCollection.AddSingleton<IImageProcessor, ImageProcessor>();
|
||||||
|
|
||||||
serviceCollection.AddSingleton<ITVSeriesManager, TVSeriesManager>();
|
ServiceCollection.AddSingleton<ITVSeriesManager, TVSeriesManager>();
|
||||||
|
|
||||||
serviceCollection.AddSingleton<IDeviceManager, DeviceManager>();
|
ServiceCollection.AddSingleton<IDeviceManager, DeviceManager>();
|
||||||
|
|
||||||
serviceCollection.AddSingleton<IMediaSourceManager, MediaSourceManager>();
|
ServiceCollection.AddSingleton<IMediaSourceManager, MediaSourceManager>();
|
||||||
|
|
||||||
serviceCollection.AddSingleton<ISubtitleManager, SubtitleManager>();
|
ServiceCollection.AddSingleton<ISubtitleManager, SubtitleManager>();
|
||||||
|
|
||||||
serviceCollection.AddSingleton<IProviderManager, ProviderManager>();
|
ServiceCollection.AddSingleton<IProviderManager, ProviderManager>();
|
||||||
|
|
||||||
// TODO: Refactor to eliminate the circular dependency here so that Lazy<T> isn't required
|
// TODO: Refactor to eliminate the circular dependency here so that Lazy<T> isn't required
|
||||||
serviceCollection.AddTransient(provider => new Lazy<ILiveTvManager>(provider.GetRequiredService<ILiveTvManager>));
|
ServiceCollection.AddTransient(provider => new Lazy<ILiveTvManager>(provider.GetRequiredService<ILiveTvManager>));
|
||||||
serviceCollection.AddSingleton<IDtoService, DtoService>();
|
ServiceCollection.AddSingleton<IDtoService, DtoService>();
|
||||||
|
|
||||||
serviceCollection.AddSingleton<IChannelManager, ChannelManager>();
|
ServiceCollection.AddSingleton<IChannelManager, ChannelManager>();
|
||||||
|
|
||||||
serviceCollection.AddSingleton<ISessionManager, SessionManager>();
|
ServiceCollection.AddSingleton<ISessionManager, SessionManager>();
|
||||||
|
|
||||||
serviceCollection.AddSingleton<IDlnaManager, DlnaManager>();
|
ServiceCollection.AddSingleton<IDlnaManager, DlnaManager>();
|
||||||
|
|
||||||
serviceCollection.AddSingleton<ICollectionManager, CollectionManager>();
|
ServiceCollection.AddSingleton<ICollectionManager, CollectionManager>();
|
||||||
|
|
||||||
serviceCollection.AddSingleton<IPlaylistManager, PlaylistManager>();
|
ServiceCollection.AddSingleton<IPlaylistManager, PlaylistManager>();
|
||||||
|
|
||||||
serviceCollection.AddSingleton<ISyncPlayManager, SyncPlayManager>();
|
ServiceCollection.AddSingleton<ISyncPlayManager, SyncPlayManager>();
|
||||||
|
|
||||||
serviceCollection.AddSingleton<LiveTvDtoService>();
|
ServiceCollection.AddSingleton<LiveTvDtoService>();
|
||||||
serviceCollection.AddSingleton<ILiveTvManager, LiveTvManager>();
|
ServiceCollection.AddSingleton<ILiveTvManager, LiveTvManager>();
|
||||||
|
|
||||||
serviceCollection.AddSingleton<IUserViewManager, UserViewManager>();
|
ServiceCollection.AddSingleton<IUserViewManager, UserViewManager>();
|
||||||
|
|
||||||
serviceCollection.AddSingleton<INotificationManager, NotificationManager>();
|
ServiceCollection.AddSingleton<INotificationManager, NotificationManager>();
|
||||||
|
|
||||||
serviceCollection.AddSingleton<IDeviceDiscovery, DeviceDiscovery>();
|
ServiceCollection.AddSingleton<IDeviceDiscovery, DeviceDiscovery>();
|
||||||
|
|
||||||
serviceCollection.AddSingleton<IChapterManager, ChapterManager>();
|
ServiceCollection.AddSingleton<IChapterManager, ChapterManager>();
|
||||||
|
|
||||||
serviceCollection.AddSingleton<IEncodingManager, MediaEncoder.EncodingManager>();
|
ServiceCollection.AddSingleton<IEncodingManager, MediaEncoder.EncodingManager>();
|
||||||
|
|
||||||
serviceCollection.AddSingleton<IAuthorizationContext, AuthorizationContext>();
|
ServiceCollection.AddSingleton<IAuthorizationContext, AuthorizationContext>();
|
||||||
serviceCollection.AddSingleton<ISessionContext, SessionContext>();
|
ServiceCollection.AddSingleton<ISessionContext, SessionContext>();
|
||||||
|
|
||||||
serviceCollection.AddSingleton<IAuthService, AuthService>();
|
ServiceCollection.AddSingleton<IAuthService, AuthService>();
|
||||||
|
|
||||||
serviceCollection.AddSingleton<ISubtitleEncoder, MediaBrowser.MediaEncoding.Subtitles.SubtitleEncoder>();
|
ServiceCollection.AddSingleton<ISubtitleEncoder, MediaBrowser.MediaEncoding.Subtitles.SubtitleEncoder>();
|
||||||
|
|
||||||
serviceCollection.AddSingleton<IResourceFileManager, ResourceFileManager>();
|
ServiceCollection.AddSingleton<IResourceFileManager, ResourceFileManager>();
|
||||||
serviceCollection.AddSingleton<EncodingHelper>();
|
ServiceCollection.AddSingleton<EncodingHelper>();
|
||||||
|
|
||||||
serviceCollection.AddSingleton<IAttachmentExtractor, MediaBrowser.MediaEncoding.Attachments.AttachmentExtractor>();
|
ServiceCollection.AddSingleton<IAttachmentExtractor, MediaBrowser.MediaEncoding.Attachments.AttachmentExtractor>();
|
||||||
|
|
||||||
serviceCollection.AddSingleton<TranscodingJobHelper>();
|
ServiceCollection.AddSingleton<TranscodingJobHelper>();
|
||||||
serviceCollection.AddScoped<MediaInfoHelper>();
|
ServiceCollection.AddScoped<MediaInfoHelper>();
|
||||||
serviceCollection.AddScoped<AudioHelper>();
|
ServiceCollection.AddScoped<AudioHelper>();
|
||||||
serviceCollection.AddScoped<DynamicHlsHelper>();
|
ServiceCollection.AddScoped<DynamicHlsHelper>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -834,6 +837,8 @@ namespace Emby.Server.Implementations
|
||||||
{
|
{
|
||||||
hasPluginConfiguration.SetStartupInfo(s => Directory.CreateDirectory(s));
|
hasPluginConfiguration.SetStartupInfo(s => Directory.CreateDirectory(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
plugin.RegisterServices(ServiceCollection);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|
|
@ -746,12 +746,21 @@ namespace Emby.Server.Implementations.Channels
|
||||||
// null if came from cache
|
// null if came from cache
|
||||||
if (itemsResult != null)
|
if (itemsResult != null)
|
||||||
{
|
{
|
||||||
var internalItems = itemsResult.Items
|
var items = itemsResult.Items;
|
||||||
.Select(i => GetChannelItemEntity(i, channelProvider, channel.Id, parentItem, cancellationToken))
|
var itemsLen = items.Count;
|
||||||
.ToArray();
|
var internalItems = new Guid[itemsLen];
|
||||||
|
for (int i = 0; i < itemsLen; i++)
|
||||||
|
{
|
||||||
|
internalItems[i] = (await GetChannelItemEntityAsync(
|
||||||
|
items[i],
|
||||||
|
channelProvider,
|
||||||
|
channel.Id,
|
||||||
|
parentItem,
|
||||||
|
cancellationToken).ConfigureAwait(false)).Id;
|
||||||
|
}
|
||||||
|
|
||||||
var existingIds = _libraryManager.GetItemIds(query);
|
var existingIds = _libraryManager.GetItemIds(query);
|
||||||
var deadIds = existingIds.Except(internalItems.Select(i => i.Id))
|
var deadIds = existingIds.Except(internalItems)
|
||||||
.ToArray();
|
.ToArray();
|
||||||
|
|
||||||
foreach (var deadId in deadIds)
|
foreach (var deadId in deadIds)
|
||||||
|
@ -963,7 +972,7 @@ namespace Emby.Server.Implementations.Channels
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
private BaseItem GetChannelItemEntity(ChannelItemInfo info, IChannel channelProvider, Guid internalChannelId, BaseItem parentFolder, CancellationToken cancellationToken)
|
private async Task<BaseItem> GetChannelItemEntityAsync(ChannelItemInfo info, IChannel channelProvider, Guid internalChannelId, BaseItem parentFolder, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var parentFolderId = parentFolder.Id;
|
var parentFolderId = parentFolder.Id;
|
||||||
|
|
||||||
|
@ -1165,7 +1174,7 @@ namespace Emby.Server.Implementations.Channels
|
||||||
}
|
}
|
||||||
else if (forceUpdate)
|
else if (forceUpdate)
|
||||||
{
|
{
|
||||||
item.UpdateToRepository(ItemUpdateType.None, cancellationToken);
|
await item.UpdateToRepositoryAsync(ItemUpdateType.None, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((isNew || forceUpdate) && info.Type == ChannelItemType.Media)
|
if ((isNew || forceUpdate) && info.Type == ChannelItemType.Media)
|
||||||
|
|
|
@ -132,7 +132,7 @@ namespace Emby.Server.Implementations.Collections
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public BoxSet CreateCollection(CollectionCreationOptions options)
|
public async Task<BoxSet> CreateCollectionAsync(CollectionCreationOptions options)
|
||||||
{
|
{
|
||||||
var name = options.Name;
|
var name = options.Name;
|
||||||
|
|
||||||
|
@ -141,7 +141,7 @@ namespace Emby.Server.Implementations.Collections
|
||||||
// This could cause it to get re-resolved as a plain folder
|
// This could cause it to get re-resolved as a plain folder
|
||||||
var folderName = _fileSystem.GetValidFilename(name) + " [boxset]";
|
var folderName = _fileSystem.GetValidFilename(name) + " [boxset]";
|
||||||
|
|
||||||
var parentFolder = GetCollectionsFolder(true).GetAwaiter().GetResult();
|
var parentFolder = await GetCollectionsFolder(true).ConfigureAwait(false);
|
||||||
|
|
||||||
if (parentFolder == null)
|
if (parentFolder == null)
|
||||||
{
|
{
|
||||||
|
@ -169,12 +169,16 @@ namespace Emby.Server.Implementations.Collections
|
||||||
|
|
||||||
if (options.ItemIdList.Length > 0)
|
if (options.ItemIdList.Length > 0)
|
||||||
{
|
{
|
||||||
AddToCollection(collection.Id, options.ItemIdList, false, new MetadataRefreshOptions(new DirectoryService(_fileSystem))
|
await AddToCollectionAsync(
|
||||||
{
|
collection.Id,
|
||||||
// The initial adding of items is going to create a local metadata file
|
options.ItemIdList.Select(x => new Guid(x)),
|
||||||
// This will cause internet metadata to be skipped as a result
|
false,
|
||||||
MetadataRefreshMode = MetadataRefreshMode.FullRefresh
|
new MetadataRefreshOptions(new DirectoryService(_fileSystem))
|
||||||
});
|
{
|
||||||
|
// The initial adding of items is going to create a local metadata file
|
||||||
|
// This will cause internet metadata to be skipped as a result
|
||||||
|
MetadataRefreshMode = MetadataRefreshMode.FullRefresh
|
||||||
|
}).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -197,18 +201,10 @@ namespace Emby.Server.Implementations.Collections
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void AddToCollection(Guid collectionId, IEnumerable<string> ids)
|
public Task AddToCollectionAsync(Guid collectionId, IEnumerable<Guid> ids)
|
||||||
{
|
=> AddToCollectionAsync(collectionId, ids, true, new MetadataRefreshOptions(new DirectoryService(_fileSystem)));
|
||||||
AddToCollection(collectionId, ids, true, new MetadataRefreshOptions(new DirectoryService(_fileSystem)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
private async Task AddToCollectionAsync(Guid collectionId, IEnumerable<Guid> ids, bool fireEvent, MetadataRefreshOptions refreshOptions)
|
||||||
public void AddToCollection(Guid collectionId, IEnumerable<Guid> ids)
|
|
||||||
{
|
|
||||||
AddToCollection(collectionId, ids.Select(i => i.ToString("N", CultureInfo.InvariantCulture)), true, new MetadataRefreshOptions(new DirectoryService(_fileSystem)));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AddToCollection(Guid collectionId, IEnumerable<string> ids, bool fireEvent, MetadataRefreshOptions refreshOptions)
|
|
||||||
{
|
{
|
||||||
var collection = _libraryManager.GetItemById(collectionId) as BoxSet;
|
var collection = _libraryManager.GetItemById(collectionId) as BoxSet;
|
||||||
if (collection == null)
|
if (collection == null)
|
||||||
|
@ -224,15 +220,14 @@ namespace Emby.Server.Implementations.Collections
|
||||||
|
|
||||||
foreach (var id in ids)
|
foreach (var id in ids)
|
||||||
{
|
{
|
||||||
var guidId = new Guid(id);
|
var item = _libraryManager.GetItemById(id);
|
||||||
var item = _libraryManager.GetItemById(guidId);
|
|
||||||
|
|
||||||
if (item == null)
|
if (item == null)
|
||||||
{
|
{
|
||||||
throw new ArgumentException("No item exists with the supplied Id");
|
throw new ArgumentException("No item exists with the supplied Id");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!currentLinkedChildrenIds.Contains(guidId))
|
if (!currentLinkedChildrenIds.Contains(id))
|
||||||
{
|
{
|
||||||
itemList.Add(item);
|
itemList.Add(item);
|
||||||
|
|
||||||
|
@ -249,7 +244,7 @@ namespace Emby.Server.Implementations.Collections
|
||||||
|
|
||||||
collection.UpdateRatingToItems(linkedChildrenList);
|
collection.UpdateRatingToItems(linkedChildrenList);
|
||||||
|
|
||||||
collection.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None);
|
await collection.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
refreshOptions.ForceSave = true;
|
refreshOptions.ForceSave = true;
|
||||||
_providerManager.QueueRefresh(collection.Id, refreshOptions, RefreshPriority.High);
|
_providerManager.QueueRefresh(collection.Id, refreshOptions, RefreshPriority.High);
|
||||||
|
@ -266,13 +261,7 @@ namespace Emby.Server.Implementations.Collections
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void RemoveFromCollection(Guid collectionId, IEnumerable<string> itemIds)
|
public async Task RemoveFromCollectionAsync(Guid collectionId, IEnumerable<Guid> itemIds)
|
||||||
{
|
|
||||||
RemoveFromCollection(collectionId, itemIds.Select(i => new Guid(i)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public void RemoveFromCollection(Guid collectionId, IEnumerable<Guid> itemIds)
|
|
||||||
{
|
{
|
||||||
var collection = _libraryManager.GetItemById(collectionId) as BoxSet;
|
var collection = _libraryManager.GetItemById(collectionId) as BoxSet;
|
||||||
|
|
||||||
|
@ -309,7 +298,7 @@ namespace Emby.Server.Implementations.Collections
|
||||||
collection.LinkedChildren = collection.LinkedChildren.Except(list).ToArray();
|
collection.LinkedChildren = collection.LinkedChildren.Except(list).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
collection.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None);
|
await collection.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
|
||||||
_providerManager.QueueRefresh(
|
_providerManager.QueueRefresh(
|
||||||
collection.Id,
|
collection.Id,
|
||||||
new MetadataRefreshOptions(new DirectoryService(_fileSystem))
|
new MetadataRefreshOptions(new DirectoryService(_fileSystem))
|
||||||
|
|
|
@ -2,11 +2,11 @@ using System;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using Emby.Server.Implementations.AppBase;
|
using Emby.Server.Implementations.AppBase;
|
||||||
|
using Jellyfin.Data.Events;
|
||||||
using MediaBrowser.Common.Configuration;
|
using MediaBrowser.Common.Configuration;
|
||||||
using MediaBrowser.Controller;
|
using MediaBrowser.Controller;
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
using MediaBrowser.Model.Configuration;
|
using MediaBrowser.Model.Configuration;
|
||||||
using MediaBrowser.Model.Events;
|
|
||||||
using MediaBrowser.Model.IO;
|
using MediaBrowser.Model.IO;
|
||||||
using MediaBrowser.Model.Serialization;
|
using MediaBrowser.Model.Serialization;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
|
@ -7,13 +7,13 @@ using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Jellyfin.Data.Entities;
|
using Jellyfin.Data.Entities;
|
||||||
using Jellyfin.Data.Enums;
|
using Jellyfin.Data.Enums;
|
||||||
|
using Jellyfin.Data.Events;
|
||||||
using MediaBrowser.Common.Extensions;
|
using MediaBrowser.Common.Extensions;
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
using MediaBrowser.Controller.Devices;
|
using MediaBrowser.Controller.Devices;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
using MediaBrowser.Controller.Security;
|
using MediaBrowser.Controller.Security;
|
||||||
using MediaBrowser.Model.Devices;
|
using MediaBrowser.Model.Devices;
|
||||||
using MediaBrowser.Model.Events;
|
|
||||||
using MediaBrowser.Model.Querying;
|
using MediaBrowser.Model.Querying;
|
||||||
using MediaBrowser.Model.Serialization;
|
using MediaBrowser.Model.Serialization;
|
||||||
using MediaBrowser.Model.Session;
|
using MediaBrowser.Model.Session;
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="IPNetwork2" Version="2.5.211" />
|
<PackageReference Include="IPNetwork2" Version="2.5.224" />
|
||||||
<PackageReference Include="Jellyfin.XmlTv" Version="10.6.2" />
|
<PackageReference Include="Jellyfin.XmlTv" Version="10.6.2" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="2.2.7" />
|
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="2.2.7" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="2.2.0" />
|
<PackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="2.2.0" />
|
||||||
|
@ -37,11 +37,11 @@
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.1.6" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.1.6" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="3.1.6" />
|
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="3.1.6" />
|
||||||
<PackageReference Include="Mono.Nat" Version="2.0.2" />
|
<PackageReference Include="Mono.Nat" Version="2.0.2" />
|
||||||
<PackageReference Include="prometheus-net.DotNetRuntime" Version="3.3.1" />
|
<PackageReference Include="prometheus-net.DotNetRuntime" Version="3.4.0" />
|
||||||
<PackageReference Include="ServiceStack.Text.Core" Version="5.9.2" />
|
<PackageReference Include="ServiceStack.Text.Core" Version="5.9.2" />
|
||||||
<PackageReference Include="sharpcompress" Version="0.26.0" />
|
<PackageReference Include="sharpcompress" Version="0.26.0" />
|
||||||
<PackageReference Include="SQLitePCL.pretty.netstandard" Version="2.1.0" />
|
<PackageReference Include="SQLitePCL.pretty.netstandard" Version="2.1.0" />
|
||||||
<PackageReference Include="DotNet.Glob" Version="3.0.9" />
|
<PackageReference Include="DotNet.Glob" Version="3.1.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -7,11 +7,11 @@ using System.Net;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Jellyfin.Data.Events;
|
||||||
using MediaBrowser.Controller;
|
using MediaBrowser.Controller;
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
using MediaBrowser.Controller.Plugins;
|
using MediaBrowser.Controller.Plugins;
|
||||||
using MediaBrowser.Model.Dlna;
|
using MediaBrowser.Model.Dlna;
|
||||||
using MediaBrowser.Model.Events;
|
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Mono.Nat;
|
using Mono.Nat;
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Jellyfin.Data.Entities;
|
using Jellyfin.Data.Entities;
|
||||||
|
using Jellyfin.Data.Events;
|
||||||
using MediaBrowser.Controller.Channels;
|
using MediaBrowser.Controller.Channels;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Entities.Audio;
|
using MediaBrowser.Controller.Entities.Audio;
|
||||||
|
@ -15,7 +16,6 @@ using MediaBrowser.Controller.Plugins;
|
||||||
using MediaBrowser.Controller.Providers;
|
using MediaBrowser.Controller.Providers;
|
||||||
using MediaBrowser.Controller.Session;
|
using MediaBrowser.Controller.Session;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
using MediaBrowser.Model.Events;
|
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace Emby.Server.Implementations.EntryPoints
|
namespace Emby.Server.Implementations.EntryPoints
|
||||||
|
|
|
@ -5,6 +5,7 @@ using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Jellyfin.Data.Enums;
|
using Jellyfin.Data.Enums;
|
||||||
|
using Jellyfin.Data.Events;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
using MediaBrowser.Controller.LiveTv;
|
using MediaBrowser.Controller.LiveTv;
|
||||||
using MediaBrowser.Controller.Plugins;
|
using MediaBrowser.Controller.Plugins;
|
||||||
|
@ -43,22 +44,22 @@ namespace Emby.Server.Implementations.EntryPoints
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void OnLiveTvManagerSeriesTimerCreated(object sender, MediaBrowser.Model.Events.GenericEventArgs<TimerEventInfo> e)
|
private async void OnLiveTvManagerSeriesTimerCreated(object sender, GenericEventArgs<TimerEventInfo> e)
|
||||||
{
|
{
|
||||||
await SendMessage("SeriesTimerCreated", e.Argument).ConfigureAwait(false);
|
await SendMessage("SeriesTimerCreated", e.Argument).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void OnLiveTvManagerTimerCreated(object sender, MediaBrowser.Model.Events.GenericEventArgs<TimerEventInfo> e)
|
private async void OnLiveTvManagerTimerCreated(object sender, GenericEventArgs<TimerEventInfo> e)
|
||||||
{
|
{
|
||||||
await SendMessage("TimerCreated", e.Argument).ConfigureAwait(false);
|
await SendMessage("TimerCreated", e.Argument).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void OnLiveTvManagerSeriesTimerCancelled(object sender, MediaBrowser.Model.Events.GenericEventArgs<TimerEventInfo> e)
|
private async void OnLiveTvManagerSeriesTimerCancelled(object sender, GenericEventArgs<TimerEventInfo> e)
|
||||||
{
|
{
|
||||||
await SendMessage("SeriesTimerCancelled", e.Argument).ConfigureAwait(false);
|
await SendMessage("SeriesTimerCancelled", e.Argument).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void OnLiveTvManagerTimerCancelled(object sender, MediaBrowser.Model.Events.GenericEventArgs<TimerEventInfo> e)
|
private async void OnLiveTvManagerTimerCancelled(object sender, GenericEventArgs<TimerEventInfo> e)
|
||||||
{
|
{
|
||||||
await SendMessage("TimerCancelled", e.Argument).ConfigureAwait(false);
|
await SendMessage("TimerCancelled", e.Argument).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,210 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Globalization;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Jellyfin.Data.Entities;
|
|
||||||
using MediaBrowser.Common.Plugins;
|
|
||||||
using MediaBrowser.Common.Updates;
|
|
||||||
using MediaBrowser.Controller;
|
|
||||||
using MediaBrowser.Controller.Library;
|
|
||||||
using MediaBrowser.Controller.Plugins;
|
|
||||||
using MediaBrowser.Controller.Session;
|
|
||||||
using MediaBrowser.Model.Events;
|
|
||||||
using MediaBrowser.Model.Tasks;
|
|
||||||
using MediaBrowser.Model.Updates;
|
|
||||||
|
|
||||||
namespace Emby.Server.Implementations.EntryPoints
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Class WebSocketEvents.
|
|
||||||
/// </summary>
|
|
||||||
public class ServerEventNotifier : IServerEntryPoint
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The user manager.
|
|
||||||
/// </summary>
|
|
||||||
private readonly IUserManager _userManager;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The installation manager.
|
|
||||||
/// </summary>
|
|
||||||
private readonly IInstallationManager _installationManager;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The kernel.
|
|
||||||
/// </summary>
|
|
||||||
private readonly IServerApplicationHost _appHost;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The task manager.
|
|
||||||
/// </summary>
|
|
||||||
private readonly ITaskManager _taskManager;
|
|
||||||
|
|
||||||
private readonly ISessionManager _sessionManager;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="ServerEventNotifier"/> class.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="appHost">The application host.</param>
|
|
||||||
/// <param name="userManager">The user manager.</param>
|
|
||||||
/// <param name="installationManager">The installation manager.</param>
|
|
||||||
/// <param name="taskManager">The task manager.</param>
|
|
||||||
/// <param name="sessionManager">The session manager.</param>
|
|
||||||
public ServerEventNotifier(
|
|
||||||
IServerApplicationHost appHost,
|
|
||||||
IUserManager userManager,
|
|
||||||
IInstallationManager installationManager,
|
|
||||||
ITaskManager taskManager,
|
|
||||||
ISessionManager sessionManager)
|
|
||||||
{
|
|
||||||
_userManager = userManager;
|
|
||||||
_installationManager = installationManager;
|
|
||||||
_appHost = appHost;
|
|
||||||
_taskManager = taskManager;
|
|
||||||
_sessionManager = sessionManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public Task RunAsync()
|
|
||||||
{
|
|
||||||
_userManager.OnUserDeleted += OnUserDeleted;
|
|
||||||
_userManager.OnUserUpdated += OnUserUpdated;
|
|
||||||
|
|
||||||
_appHost.HasPendingRestartChanged += OnHasPendingRestartChanged;
|
|
||||||
|
|
||||||
_installationManager.PluginUninstalled += OnPluginUninstalled;
|
|
||||||
_installationManager.PackageInstalling += OnPackageInstalling;
|
|
||||||
_installationManager.PackageInstallationCancelled += OnPackageInstallationCancelled;
|
|
||||||
_installationManager.PackageInstallationCompleted += OnPackageInstallationCompleted;
|
|
||||||
_installationManager.PackageInstallationFailed += OnPackageInstallationFailed;
|
|
||||||
|
|
||||||
_taskManager.TaskCompleted += OnTaskCompleted;
|
|
||||||
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void OnPackageInstalling(object sender, InstallationInfo e)
|
|
||||||
{
|
|
||||||
await SendMessageToAdminSessions("PackageInstalling", e).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void OnPackageInstallationCancelled(object sender, InstallationInfo e)
|
|
||||||
{
|
|
||||||
await SendMessageToAdminSessions("PackageInstallationCancelled", e).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void OnPackageInstallationCompleted(object sender, InstallationInfo e)
|
|
||||||
{
|
|
||||||
await SendMessageToAdminSessions("PackageInstallationCompleted", e).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void OnPackageInstallationFailed(object sender, InstallationFailedEventArgs e)
|
|
||||||
{
|
|
||||||
await SendMessageToAdminSessions("PackageInstallationFailed", e.InstallationInfo).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void OnTaskCompleted(object sender, TaskCompletionEventArgs e)
|
|
||||||
{
|
|
||||||
await SendMessageToAdminSessions("ScheduledTaskEnded", e.Result).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Installations the manager_ plugin uninstalled.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="sender">The sender.</param>
|
|
||||||
/// <param name="e">The e.</param>
|
|
||||||
private async void OnPluginUninstalled(object sender, IPlugin e)
|
|
||||||
{
|
|
||||||
await SendMessageToAdminSessions("PluginUninstalled", e).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Handles the HasPendingRestartChanged event of the kernel control.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="sender">The source of the event.</param>
|
|
||||||
/// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
|
|
||||||
private async void OnHasPendingRestartChanged(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
await _sessionManager.SendRestartRequiredNotification(CancellationToken.None).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Users the manager_ user updated.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="sender">The sender.</param>
|
|
||||||
/// <param name="e">The e.</param>
|
|
||||||
private async void OnUserUpdated(object sender, GenericEventArgs<User> e)
|
|
||||||
{
|
|
||||||
var dto = _userManager.GetUserDto(e.Argument);
|
|
||||||
|
|
||||||
await SendMessageToUserSession(e.Argument, "UserUpdated", dto).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Users the manager_ user deleted.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="sender">The sender.</param>
|
|
||||||
/// <param name="e">The e.</param>
|
|
||||||
private async void OnUserDeleted(object sender, GenericEventArgs<User> e)
|
|
||||||
{
|
|
||||||
await SendMessageToUserSession(e.Argument, "UserDeleted", e.Argument.Id.ToString("N", CultureInfo.InvariantCulture)).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task SendMessageToAdminSessions<T>(string name, T data)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await _sessionManager.SendMessageToAdminSessions(name, data, CancellationToken.None).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task SendMessageToUserSession<T>(User user, string name, T data)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await _sessionManager.SendMessageToUserSessions(
|
|
||||||
new List<Guid> { user.Id },
|
|
||||||
name,
|
|
||||||
data,
|
|
||||||
CancellationToken.None).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
Dispose(true);
|
|
||||||
GC.SuppressFinalize(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Releases unmanaged and - optionally - managed resources.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
|
|
||||||
protected virtual void Dispose(bool dispose)
|
|
||||||
{
|
|
||||||
if (dispose)
|
|
||||||
{
|
|
||||||
_userManager.OnUserDeleted -= OnUserDeleted;
|
|
||||||
_userManager.OnUserUpdated -= OnUserUpdated;
|
|
||||||
|
|
||||||
_installationManager.PluginUninstalled -= OnPluginUninstalled;
|
|
||||||
_installationManager.PackageInstalling -= OnPackageInstalling;
|
|
||||||
_installationManager.PackageInstallationCancelled -= OnPackageInstallationCancelled;
|
|
||||||
_installationManager.PackageInstallationCompleted -= OnPackageInstallationCompleted;
|
|
||||||
_installationManager.PackageInstallationFailed -= OnPackageInstallationFailed;
|
|
||||||
|
|
||||||
_appHost.HasPendingRestartChanged -= OnHasPendingRestartChanged;
|
|
||||||
|
|
||||||
_taskManager.TaskCompleted -= OnTaskCompleted;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -12,13 +12,13 @@ using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Emby.Server.Implementations.Services;
|
using Emby.Server.Implementations.Services;
|
||||||
using Emby.Server.Implementations.SocketSharp;
|
using Emby.Server.Implementations.SocketSharp;
|
||||||
|
using Jellyfin.Data.Events;
|
||||||
using MediaBrowser.Common.Extensions;
|
using MediaBrowser.Common.Extensions;
|
||||||
using MediaBrowser.Common.Net;
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Controller;
|
using MediaBrowser.Controller;
|
||||||
using MediaBrowser.Controller.Authentication;
|
using MediaBrowser.Controller.Authentication;
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
using MediaBrowser.Controller.Net;
|
using MediaBrowser.Controller.Net;
|
||||||
using MediaBrowser.Model.Events;
|
|
||||||
using MediaBrowser.Model.Globalization;
|
using MediaBrowser.Model.Globalization;
|
||||||
using MediaBrowser.Model.Serialization;
|
using MediaBrowser.Model.Serialization;
|
||||||
using MediaBrowser.Model.Services;
|
using MediaBrowser.Model.Services;
|
||||||
|
|
|
@ -179,7 +179,7 @@ namespace Emby.Server.Implementations.HttpServer
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
WebSocketMessage<object> stub;
|
WebSocketMessage<object>? stub;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -209,6 +209,12 @@ namespace Emby.Server.Implementations.HttpServer
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (stub == null)
|
||||||
|
{
|
||||||
|
_logger.LogError("Error processing web socket message");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Tell the PipeReader how much of the buffer we have consumed
|
// Tell the PipeReader how much of the buffer we have consumed
|
||||||
reader.AdvanceTo(buffer.End);
|
reader.AdvanceTo(buffer.End);
|
||||||
|
|
||||||
|
|
|
@ -771,7 +771,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
if (folder.ParentId != rootFolder.Id)
|
if (folder.ParentId != rootFolder.Id)
|
||||||
{
|
{
|
||||||
folder.ParentId = rootFolder.Id;
|
folder.ParentId = rootFolder.Id;
|
||||||
folder.UpdateToRepository(ItemUpdateType.MetadataImport, CancellationToken.None);
|
folder.UpdateToRepositoryAsync(ItemUpdateType.MetadataImport, CancellationToken.None).GetAwaiter().GetResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
rootFolder.AddVirtualChild(folder);
|
rootFolder.AddVirtualChild(folder);
|
||||||
|
@ -1868,7 +1868,8 @@ namespace Emby.Server.Implementations.Library
|
||||||
return image.Path != null && !image.IsLocalFile;
|
return image.Path != null && !image.IsLocalFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateImages(BaseItem item, bool forceUpdate = false)
|
/// <inheritdoc />
|
||||||
|
public async Task UpdateImagesAsync(BaseItem item, bool forceUpdate = false)
|
||||||
{
|
{
|
||||||
if (item == null)
|
if (item == null)
|
||||||
{
|
{
|
||||||
|
@ -1891,7 +1892,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var index = item.GetImageIndex(img);
|
var index = item.GetImageIndex(img);
|
||||||
image = ConvertImageToLocal(item, img, index).ConfigureAwait(false).GetAwaiter().GetResult();
|
image = await ConvertImageToLocal(item, img, index).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (ArgumentException)
|
catch (ArgumentException)
|
||||||
{
|
{
|
||||||
|
@ -1913,7 +1914,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogError(ex, "Cannnot get image dimensions for {0}", image.Path);
|
_logger.LogError(ex, "Cannot get image dimensions for {0}", image.Path);
|
||||||
image.Width = 0;
|
image.Width = 0;
|
||||||
image.Height = 0;
|
image.Height = 0;
|
||||||
continue;
|
continue;
|
||||||
|
@ -1943,10 +1944,8 @@ namespace Emby.Server.Implementations.Library
|
||||||
RegisterItem(item);
|
RegisterItem(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <inheritdoc />
|
||||||
/// Updates the item.
|
public async Task UpdateItemsAsync(IReadOnlyList<BaseItem> items, BaseItem parent, ItemUpdateType updateReason, CancellationToken cancellationToken)
|
||||||
/// </summary>
|
|
||||||
public void UpdateItems(IReadOnlyList<BaseItem> items, BaseItem parent, ItemUpdateType updateReason, CancellationToken cancellationToken)
|
|
||||||
{
|
{
|
||||||
foreach (var item in items)
|
foreach (var item in items)
|
||||||
{
|
{
|
||||||
|
@ -1957,7 +1956,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
|
|
||||||
item.DateLastSaved = DateTime.UtcNow;
|
item.DateLastSaved = DateTime.UtcNow;
|
||||||
|
|
||||||
UpdateImages(item, updateReason >= ItemUpdateType.ImageUpdate);
|
await UpdateImagesAsync(item, updateReason >= ItemUpdateType.ImageUpdate).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
_itemRepository.SaveItems(items, cancellationToken);
|
_itemRepository.SaveItems(items, cancellationToken);
|
||||||
|
@ -1991,17 +1990,9 @@ namespace Emby.Server.Implementations.Library
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <inheritdoc />
|
||||||
/// Updates the item.
|
public Task UpdateItemAsync(BaseItem item, BaseItem parent, ItemUpdateType updateReason, CancellationToken cancellationToken)
|
||||||
/// </summary>
|
=> UpdateItemsAsync(new[] { item }, parent, updateReason, cancellationToken);
|
||||||
/// <param name="item">The item.</param>
|
|
||||||
/// <param name="parent">The parent item.</param>
|
|
||||||
/// <param name="updateReason">The update reason.</param>
|
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
|
||||||
public void UpdateItem(BaseItem item, BaseItem parent, ItemUpdateType updateReason, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
UpdateItems(new[] { item }, parent, updateReason, cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Reports the item removed.
|
/// Reports the item removed.
|
||||||
|
@ -2233,7 +2224,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
|
|
||||||
if (refresh)
|
if (refresh)
|
||||||
{
|
{
|
||||||
item.UpdateToRepository(ItemUpdateType.MetadataImport, CancellationToken.None);
|
item.UpdateToRepositoryAsync(ItemUpdateType.MetadataImport, CancellationToken.None).GetAwaiter().GetResult();
|
||||||
ProviderManager.QueueRefresh(item.Id, new MetadataRefreshOptions(new DirectoryService(_fileSystem)), RefreshPriority.Normal);
|
ProviderManager.QueueRefresh(item.Id, new MetadataRefreshOptions(new DirectoryService(_fileSystem)), RefreshPriority.Normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2420,7 +2411,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
if (!string.Equals(viewType, item.ViewType, StringComparison.OrdinalIgnoreCase))
|
if (!string.Equals(viewType, item.ViewType, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
item.ViewType = viewType;
|
item.ViewType = viewType;
|
||||||
item.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None);
|
item.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).GetAwaiter().GetResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
var refresh = isNew || DateTime.UtcNow - item.DateLastRefreshed >= _viewRefreshInterval;
|
var refresh = isNew || DateTime.UtcNow - item.DateLastRefreshed >= _viewRefreshInterval;
|
||||||
|
@ -2902,7 +2893,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
|
|
||||||
await ProviderManager.SaveImage(item, url, image.Type, imageIndex, CancellationToken.None).ConfigureAwait(false);
|
await ProviderManager.SaveImage(item, url, image.Type, imageIndex, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
item.UpdateToRepository(ItemUpdateType.ImageUpdate, CancellationToken.None);
|
await item.UpdateToRepositoryAsync(ItemUpdateType.ImageUpdate, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
return item.GetImageInfo(image.Type, imageIndex);
|
return item.GetImageInfo(image.Type, imageIndex);
|
||||||
}
|
}
|
||||||
|
@ -2920,7 +2911,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
|
|
||||||
// Remove this image to prevent it from retrying over and over
|
// Remove this image to prevent it from retrying over and over
|
||||||
item.RemoveImage(image);
|
item.RemoveImage(image);
|
||||||
item.UpdateToRepository(ItemUpdateType.ImageUpdate, CancellationToken.None);
|
await item.UpdateToRepositoryAsync(ItemUpdateType.ImageUpdate, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
throw new InvalidOperationException();
|
throw new InvalidOperationException();
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ using System.Threading.Tasks;
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
using Emby.Server.Implementations.Library;
|
using Emby.Server.Implementations.Library;
|
||||||
using Jellyfin.Data.Enums;
|
using Jellyfin.Data.Enums;
|
||||||
|
using Jellyfin.Data.Events;
|
||||||
using MediaBrowser.Common.Configuration;
|
using MediaBrowser.Common.Configuration;
|
||||||
using MediaBrowser.Common.Extensions;
|
using MediaBrowser.Common.Extensions;
|
||||||
using MediaBrowser.Common.Net;
|
using MediaBrowser.Common.Net;
|
||||||
|
@ -29,7 +30,6 @@ using MediaBrowser.Controller.Providers;
|
||||||
using MediaBrowser.Model.Configuration;
|
using MediaBrowser.Model.Configuration;
|
||||||
using MediaBrowser.Model.Dto;
|
using MediaBrowser.Model.Dto;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
using MediaBrowser.Model.Events;
|
|
||||||
using MediaBrowser.Model.IO;
|
using MediaBrowser.Model.IO;
|
||||||
using MediaBrowser.Model.LiveTv;
|
using MediaBrowser.Model.LiveTv;
|
||||||
using MediaBrowser.Model.MediaInfo;
|
using MediaBrowser.Model.MediaInfo;
|
||||||
|
|
|
@ -5,8 +5,8 @@ using System.Collections.Concurrent;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using Jellyfin.Data.Events;
|
||||||
using MediaBrowser.Controller.LiveTv;
|
using MediaBrowser.Controller.LiveTv;
|
||||||
using MediaBrowser.Model.Events;
|
|
||||||
using MediaBrowser.Model.LiveTv;
|
using MediaBrowser.Model.LiveTv;
|
||||||
using MediaBrowser.Model.Serialization;
|
using MediaBrowser.Model.Serialization;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
|
@ -10,6 +10,7 @@ using System.Threading.Tasks;
|
||||||
using Emby.Server.Implementations.Library;
|
using Emby.Server.Implementations.Library;
|
||||||
using Jellyfin.Data.Entities;
|
using Jellyfin.Data.Entities;
|
||||||
using Jellyfin.Data.Enums;
|
using Jellyfin.Data.Enums;
|
||||||
|
using Jellyfin.Data.Events;
|
||||||
using MediaBrowser.Common.Configuration;
|
using MediaBrowser.Common.Configuration;
|
||||||
using MediaBrowser.Common.Extensions;
|
using MediaBrowser.Common.Extensions;
|
||||||
using MediaBrowser.Common.Progress;
|
using MediaBrowser.Common.Progress;
|
||||||
|
@ -24,7 +25,6 @@ using MediaBrowser.Controller.Providers;
|
||||||
using MediaBrowser.Controller.Sorting;
|
using MediaBrowser.Controller.Sorting;
|
||||||
using MediaBrowser.Model.Dto;
|
using MediaBrowser.Model.Dto;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
using MediaBrowser.Model.Events;
|
|
||||||
using MediaBrowser.Model.Globalization;
|
using MediaBrowser.Model.Globalization;
|
||||||
using MediaBrowser.Model.IO;
|
using MediaBrowser.Model.IO;
|
||||||
using MediaBrowser.Model.LiveTv;
|
using MediaBrowser.Model.LiveTv;
|
||||||
|
@ -422,7 +422,7 @@ namespace Emby.Server.Implementations.LiveTv
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private LiveTvChannel GetChannel(ChannelInfo channelInfo, string serviceName, BaseItem parentFolder, CancellationToken cancellationToken)
|
private async Task<LiveTvChannel> GetChannelAsync(ChannelInfo channelInfo, string serviceName, BaseItem parentFolder, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var parentFolderId = parentFolder.Id;
|
var parentFolderId = parentFolder.Id;
|
||||||
var isNew = false;
|
var isNew = false;
|
||||||
|
@ -512,7 +512,7 @@ namespace Emby.Server.Implementations.LiveTv
|
||||||
}
|
}
|
||||||
else if (forceUpdate)
|
else if (forceUpdate)
|
||||||
{
|
{
|
||||||
_libraryManager.UpdateItem(item, parentFolder, ItemUpdateType.MetadataImport, cancellationToken);
|
await _libraryManager.UpdateItemAsync(item, parentFolder, ItemUpdateType.MetadataImport, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
|
@ -1129,7 +1129,7 @@ namespace Emby.Server.Implementations.LiveTv
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var item = GetChannel(channelInfo.Item2, channelInfo.Item1, parentFolder, cancellationToken);
|
var item = await GetChannelAsync(channelInfo.Item2, channelInfo.Item1, parentFolder, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
list.Add(item);
|
list.Add(item);
|
||||||
}
|
}
|
||||||
|
@ -1146,7 +1146,7 @@ namespace Emby.Server.Implementations.LiveTv
|
||||||
double percent = numComplete;
|
double percent = numComplete;
|
||||||
percent /= allChannelsList.Count;
|
percent /= allChannelsList.Count;
|
||||||
|
|
||||||
progress.Report(5 * percent + 10);
|
progress.Report((5 * percent) + 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
progress.Report(15);
|
progress.Report(15);
|
||||||
|
@ -1221,7 +1221,11 @@ namespace Emby.Server.Implementations.LiveTv
|
||||||
|
|
||||||
if (updatedPrograms.Count > 0)
|
if (updatedPrograms.Count > 0)
|
||||||
{
|
{
|
||||||
_libraryManager.UpdateItems(updatedPrograms, currentChannel, ItemUpdateType.MetadataImport, cancellationToken);
|
await _libraryManager.UpdateItemsAsync(
|
||||||
|
updatedPrograms,
|
||||||
|
currentChannel,
|
||||||
|
ItemUpdateType.MetadataImport,
|
||||||
|
cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
currentChannel.IsMovie = isMovie;
|
currentChannel.IsMovie = isMovie;
|
||||||
|
@ -1234,7 +1238,7 @@ namespace Emby.Server.Implementations.LiveTv
|
||||||
currentChannel.AddTag("Kids");
|
currentChannel.AddTag("Kids");
|
||||||
}
|
}
|
||||||
|
|
||||||
currentChannel.UpdateToRepository(ItemUpdateType.MetadataImport, cancellationToken);
|
await currentChannel.UpdateToRepositoryAsync(ItemUpdateType.MetadataImport, cancellationToken).ConfigureAwait(false);
|
||||||
await currentChannel.RefreshMetadata(
|
await currentChannel.RefreshMetadata(
|
||||||
new MetadataRefreshOptions(new DirectoryService(_fileSystem))
|
new MetadataRefreshOptions(new DirectoryService(_fileSystem))
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"Albums": "Album",
|
"Albums": "Album",
|
||||||
"AuthenticationSucceededWithUserName": "{0} berhasil diautentikasi",
|
"AuthenticationSucceededWithUserName": "{0} berhasil diautentikasi",
|
||||||
"AppDeviceValues": "Aplikasi: {0}, Alat: {1}",
|
"AppDeviceValues": "Aplikasi : {0}, Alat : {1}",
|
||||||
"LabelRunningTimeValue": "Waktu berjalan: {0}",
|
"LabelRunningTimeValue": "Waktu berjalan: {0}",
|
||||||
"MessageApplicationUpdatedTo": "Jellyfin Server sudah diperbarui ke {0}",
|
"MessageApplicationUpdatedTo": "Jellyfin Server sudah diperbarui ke {0}",
|
||||||
"MessageApplicationUpdated": "Jellyfin Server sudah diperbarui",
|
"MessageApplicationUpdated": "Jellyfin Server sudah diperbarui",
|
||||||
|
@ -22,7 +22,7 @@
|
||||||
"HeaderContinueWatching": "Lanjutkan Menonton",
|
"HeaderContinueWatching": "Lanjutkan Menonton",
|
||||||
"HeaderCameraUploads": "Unggahan Kamera",
|
"HeaderCameraUploads": "Unggahan Kamera",
|
||||||
"HeaderAlbumArtists": "Album Artis",
|
"HeaderAlbumArtists": "Album Artis",
|
||||||
"Genres": "Genre",
|
"Genres": "Aliran",
|
||||||
"Folders": "Folder",
|
"Folders": "Folder",
|
||||||
"Favorites": "Favorit",
|
"Favorites": "Favorit",
|
||||||
"Collections": "Koleksi",
|
"Collections": "Koleksi",
|
||||||
|
|
|
@ -69,5 +69,8 @@
|
||||||
"AppDeviceValues": "App: {0}, อุปกรณ์: {1}",
|
"AppDeviceValues": "App: {0}, อุปกรณ์: {1}",
|
||||||
"Albums": "อัลบั้ม",
|
"Albums": "อัลบั้ม",
|
||||||
"ScheduledTaskStartedWithName": "{0} เริ่มต้น",
|
"ScheduledTaskStartedWithName": "{0} เริ่มต้น",
|
||||||
"ScheduledTaskFailedWithName": "{0} ล้มเหลว"
|
"ScheduledTaskFailedWithName": "{0} ล้มเหลว",
|
||||||
|
"Songs": "เพลง",
|
||||||
|
"Shows": "แสดง",
|
||||||
|
"ServerNameNeedsToBeRestarted": "{0} ต้องการรีสตาร์ท"
|
||||||
}
|
}
|
||||||
|
|
|
@ -152,10 +152,10 @@ namespace Emby.Server.Implementations.Playlists
|
||||||
|
|
||||||
if (options.ItemIdList.Length > 0)
|
if (options.ItemIdList.Length > 0)
|
||||||
{
|
{
|
||||||
AddToPlaylistInternal(playlist.Id.ToString("N", CultureInfo.InvariantCulture), options.ItemIdList, user, new DtoOptions(false)
|
await AddToPlaylistInternal(playlist.Id, options.ItemIdList, user, new DtoOptions(false)
|
||||||
{
|
{
|
||||||
EnableImages = true
|
EnableImages = true
|
||||||
});
|
}).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new PlaylistCreationResult(playlist.Id.ToString("N", CultureInfo.InvariantCulture));
|
return new PlaylistCreationResult(playlist.Id.ToString("N", CultureInfo.InvariantCulture));
|
||||||
|
@ -184,17 +184,17 @@ namespace Emby.Server.Implementations.Playlists
|
||||||
return Playlist.GetPlaylistItems(playlistMediaType, items, user, options);
|
return Playlist.GetPlaylistItems(playlistMediaType, items, user, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddToPlaylist(string playlistId, ICollection<Guid> itemIds, Guid userId)
|
public Task AddToPlaylistAsync(Guid playlistId, ICollection<Guid> itemIds, Guid userId)
|
||||||
{
|
{
|
||||||
var user = userId.Equals(Guid.Empty) ? null : _userManager.GetUserById(userId);
|
var user = userId.Equals(Guid.Empty) ? null : _userManager.GetUserById(userId);
|
||||||
|
|
||||||
AddToPlaylistInternal(playlistId, itemIds, user, new DtoOptions(false)
|
return AddToPlaylistInternal(playlistId, itemIds, user, new DtoOptions(false)
|
||||||
{
|
{
|
||||||
EnableImages = true
|
EnableImages = true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddToPlaylistInternal(string playlistId, ICollection<Guid> newItemIds, User user, DtoOptions options)
|
private async Task AddToPlaylistInternal(Guid playlistId, ICollection<Guid> newItemIds, User user, DtoOptions options)
|
||||||
{
|
{
|
||||||
// Retrieve the existing playlist
|
// Retrieve the existing playlist
|
||||||
var playlist = _libraryManager.GetItemById(playlistId) as Playlist
|
var playlist = _libraryManager.GetItemById(playlistId) as Playlist
|
||||||
|
@ -238,7 +238,7 @@ namespace Emby.Server.Implementations.Playlists
|
||||||
|
|
||||||
// Update the playlist in the repository
|
// Update the playlist in the repository
|
||||||
playlist.LinkedChildren = newLinkedChildren;
|
playlist.LinkedChildren = newLinkedChildren;
|
||||||
playlist.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None);
|
await playlist.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
// Update the playlist on disk
|
// Update the playlist on disk
|
||||||
if (playlist.IsFile)
|
if (playlist.IsFile)
|
||||||
|
@ -256,7 +256,7 @@ namespace Emby.Server.Implementations.Playlists
|
||||||
RefreshPriority.High);
|
RefreshPriority.High);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveFromPlaylist(string playlistId, IEnumerable<string> entryIds)
|
public async Task RemoveFromPlaylistAsync(string playlistId, IEnumerable<string> entryIds)
|
||||||
{
|
{
|
||||||
if (!(_libraryManager.GetItemById(playlistId) is Playlist playlist))
|
if (!(_libraryManager.GetItemById(playlistId) is Playlist playlist))
|
||||||
{
|
{
|
||||||
|
@ -273,7 +273,7 @@ namespace Emby.Server.Implementations.Playlists
|
||||||
.Select(i => i.Item1)
|
.Select(i => i.Item1)
|
||||||
.ToArray();
|
.ToArray();
|
||||||
|
|
||||||
playlist.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None);
|
await playlist.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
if (playlist.IsFile)
|
if (playlist.IsFile)
|
||||||
{
|
{
|
||||||
|
@ -289,7 +289,7 @@ namespace Emby.Server.Implementations.Playlists
|
||||||
RefreshPriority.High);
|
RefreshPriority.High);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void MoveItem(string playlistId, string entryId, int newIndex)
|
public async Task MoveItemAsync(string playlistId, string entryId, int newIndex)
|
||||||
{
|
{
|
||||||
if (!(_libraryManager.GetItemById(playlistId) is Playlist playlist))
|
if (!(_libraryManager.GetItemById(playlistId) is Playlist playlist))
|
||||||
{
|
{
|
||||||
|
@ -322,7 +322,7 @@ namespace Emby.Server.Implementations.Playlists
|
||||||
|
|
||||||
playlist.LinkedChildren = newList.ToArray();
|
playlist.LinkedChildren = newList.ToArray();
|
||||||
|
|
||||||
playlist.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None);
|
await playlist.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
if (playlist.IsFile)
|
if (playlist.IsFile)
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,10 +6,10 @@ using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Jellyfin.Data.Events;
|
||||||
using MediaBrowser.Common.Configuration;
|
using MediaBrowser.Common.Configuration;
|
||||||
using MediaBrowser.Common.Extensions;
|
using MediaBrowser.Common.Extensions;
|
||||||
using MediaBrowser.Common.Progress;
|
using MediaBrowser.Common.Progress;
|
||||||
using MediaBrowser.Model.Events;
|
|
||||||
using MediaBrowser.Model.Serialization;
|
using MediaBrowser.Model.Serialization;
|
||||||
using MediaBrowser.Model.Tasks;
|
using MediaBrowser.Model.Tasks;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
|
@ -5,8 +5,8 @@ using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Jellyfin.Data.Events;
|
||||||
using MediaBrowser.Common.Configuration;
|
using MediaBrowser.Common.Configuration;
|
||||||
using MediaBrowser.Model.Events;
|
|
||||||
using MediaBrowser.Model.Serialization;
|
using MediaBrowser.Model.Serialization;
|
||||||
using MediaBrowser.Model.Tasks;
|
using MediaBrowser.Model.Tasks;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
|
@ -9,6 +9,7 @@ using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Jellyfin.Data.Entities;
|
using Jellyfin.Data.Entities;
|
||||||
using Jellyfin.Data.Enums;
|
using Jellyfin.Data.Enums;
|
||||||
|
using Jellyfin.Data.Events;
|
||||||
using MediaBrowser.Common.Events;
|
using MediaBrowser.Common.Events;
|
||||||
using MediaBrowser.Common.Extensions;
|
using MediaBrowser.Common.Extensions;
|
||||||
using MediaBrowser.Controller;
|
using MediaBrowser.Controller;
|
||||||
|
@ -17,6 +18,8 @@ using MediaBrowser.Controller.Devices;
|
||||||
using MediaBrowser.Controller.Drawing;
|
using MediaBrowser.Controller.Drawing;
|
||||||
using MediaBrowser.Controller.Dto;
|
using MediaBrowser.Controller.Dto;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
|
using MediaBrowser.Controller.Events;
|
||||||
|
using MediaBrowser.Controller.Events.Session;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
using MediaBrowser.Controller.Net;
|
using MediaBrowser.Controller.Net;
|
||||||
using MediaBrowser.Controller.Security;
|
using MediaBrowser.Controller.Security;
|
||||||
|
@ -24,7 +27,6 @@ using MediaBrowser.Controller.Session;
|
||||||
using MediaBrowser.Model.Devices;
|
using MediaBrowser.Model.Devices;
|
||||||
using MediaBrowser.Model.Dto;
|
using MediaBrowser.Model.Dto;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
using MediaBrowser.Model.Events;
|
|
||||||
using MediaBrowser.Model.Library;
|
using MediaBrowser.Model.Library;
|
||||||
using MediaBrowser.Model.Querying;
|
using MediaBrowser.Model.Querying;
|
||||||
using MediaBrowser.Model.Session;
|
using MediaBrowser.Model.Session;
|
||||||
|
@ -40,25 +42,16 @@ namespace Emby.Server.Implementations.Session
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class SessionManager : ISessionManager, IDisposable
|
public class SessionManager : ISessionManager, IDisposable
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// The user data repository.
|
|
||||||
/// </summary>
|
|
||||||
private readonly IUserDataManager _userDataManager;
|
private readonly IUserDataManager _userDataManager;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The logger.
|
|
||||||
/// </summary>
|
|
||||||
private readonly ILogger<SessionManager> _logger;
|
private readonly ILogger<SessionManager> _logger;
|
||||||
|
private readonly IEventManager _eventManager;
|
||||||
private readonly ILibraryManager _libraryManager;
|
private readonly ILibraryManager _libraryManager;
|
||||||
private readonly IUserManager _userManager;
|
private readonly IUserManager _userManager;
|
||||||
private readonly IMusicManager _musicManager;
|
private readonly IMusicManager _musicManager;
|
||||||
private readonly IDtoService _dtoService;
|
private readonly IDtoService _dtoService;
|
||||||
private readonly IImageProcessor _imageProcessor;
|
private readonly IImageProcessor _imageProcessor;
|
||||||
private readonly IMediaSourceManager _mediaSourceManager;
|
private readonly IMediaSourceManager _mediaSourceManager;
|
||||||
|
|
||||||
private readonly IServerApplicationHost _appHost;
|
private readonly IServerApplicationHost _appHost;
|
||||||
|
|
||||||
private readonly IAuthenticationRepository _authRepo;
|
private readonly IAuthenticationRepository _authRepo;
|
||||||
private readonly IDeviceManager _deviceManager;
|
private readonly IDeviceManager _deviceManager;
|
||||||
|
|
||||||
|
@ -75,6 +68,7 @@ namespace Emby.Server.Implementations.Session
|
||||||
|
|
||||||
public SessionManager(
|
public SessionManager(
|
||||||
ILogger<SessionManager> logger,
|
ILogger<SessionManager> logger,
|
||||||
|
IEventManager eventManager,
|
||||||
IUserDataManager userDataManager,
|
IUserDataManager userDataManager,
|
||||||
ILibraryManager libraryManager,
|
ILibraryManager libraryManager,
|
||||||
IUserManager userManager,
|
IUserManager userManager,
|
||||||
|
@ -87,6 +81,7 @@ namespace Emby.Server.Implementations.Session
|
||||||
IMediaSourceManager mediaSourceManager)
|
IMediaSourceManager mediaSourceManager)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
_eventManager = eventManager;
|
||||||
_userDataManager = userDataManager;
|
_userDataManager = userDataManager;
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
_userManager = userManager;
|
_userManager = userManager;
|
||||||
|
@ -209,6 +204,8 @@ namespace Emby.Server.Implementations.Session
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_eventManager.Publish(new SessionStartedEventArgs(info));
|
||||||
|
|
||||||
EventHelper.QueueEventIfNotNull(
|
EventHelper.QueueEventIfNotNull(
|
||||||
SessionStarted,
|
SessionStarted,
|
||||||
this,
|
this,
|
||||||
|
@ -230,6 +227,8 @@ namespace Emby.Server.Implementations.Session
|
||||||
},
|
},
|
||||||
_logger);
|
_logger);
|
||||||
|
|
||||||
|
_eventManager.Publish(new SessionEndedEventArgs(info));
|
||||||
|
|
||||||
info.Dispose();
|
info.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -667,22 +666,26 @@ namespace Emby.Server.Implementations.Session
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var eventArgs = new PlaybackProgressEventArgs
|
||||||
|
{
|
||||||
|
Item = libraryItem,
|
||||||
|
Users = users,
|
||||||
|
MediaSourceId = info.MediaSourceId,
|
||||||
|
MediaInfo = info.Item,
|
||||||
|
DeviceName = session.DeviceName,
|
||||||
|
ClientName = session.Client,
|
||||||
|
DeviceId = session.DeviceId,
|
||||||
|
Session = session
|
||||||
|
};
|
||||||
|
|
||||||
|
await _eventManager.PublishAsync(eventArgs).ConfigureAwait(false);
|
||||||
|
|
||||||
// Nothing to save here
|
// Nothing to save here
|
||||||
// Fire events to inform plugins
|
// Fire events to inform plugins
|
||||||
EventHelper.QueueEventIfNotNull(
|
EventHelper.QueueEventIfNotNull(
|
||||||
PlaybackStart,
|
PlaybackStart,
|
||||||
this,
|
this,
|
||||||
new PlaybackProgressEventArgs
|
eventArgs,
|
||||||
{
|
|
||||||
Item = libraryItem,
|
|
||||||
Users = users,
|
|
||||||
MediaSourceId = info.MediaSourceId,
|
|
||||||
MediaInfo = info.Item,
|
|
||||||
DeviceName = session.DeviceName,
|
|
||||||
ClientName = session.Client,
|
|
||||||
DeviceId = session.DeviceId,
|
|
||||||
Session = session
|
|
||||||
},
|
|
||||||
_logger);
|
_logger);
|
||||||
|
|
||||||
StartIdleCheckTimer();
|
StartIdleCheckTimer();
|
||||||
|
@ -750,23 +753,25 @@ namespace Emby.Server.Implementations.Session
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PlaybackProgress?.Invoke(
|
var eventArgs = new PlaybackProgressEventArgs
|
||||||
this,
|
{
|
||||||
new PlaybackProgressEventArgs
|
Item = libraryItem,
|
||||||
{
|
Users = users,
|
||||||
Item = libraryItem,
|
PlaybackPositionTicks = session.PlayState.PositionTicks,
|
||||||
Users = users,
|
MediaSourceId = session.PlayState.MediaSourceId,
|
||||||
PlaybackPositionTicks = session.PlayState.PositionTicks,
|
MediaInfo = info.Item,
|
||||||
MediaSourceId = session.PlayState.MediaSourceId,
|
DeviceName = session.DeviceName,
|
||||||
MediaInfo = info.Item,
|
ClientName = session.Client,
|
||||||
DeviceName = session.DeviceName,
|
DeviceId = session.DeviceId,
|
||||||
ClientName = session.Client,
|
IsPaused = info.IsPaused,
|
||||||
DeviceId = session.DeviceId,
|
PlaySessionId = info.PlaySessionId,
|
||||||
IsPaused = info.IsPaused,
|
IsAutomated = isAutomated,
|
||||||
PlaySessionId = info.PlaySessionId,
|
Session = session
|
||||||
IsAutomated = isAutomated,
|
};
|
||||||
Session = session
|
|
||||||
});
|
await _eventManager.PublishAsync(eventArgs).ConfigureAwait(false);
|
||||||
|
|
||||||
|
PlaybackProgress?.Invoke(this, eventArgs);
|
||||||
|
|
||||||
if (!isAutomated)
|
if (!isAutomated)
|
||||||
{
|
{
|
||||||
|
@ -943,23 +948,23 @@ namespace Emby.Server.Implementations.Session
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EventHelper.QueueEventIfNotNull(
|
var eventArgs = new PlaybackStopEventArgs
|
||||||
PlaybackStopped,
|
{
|
||||||
this,
|
Item = libraryItem,
|
||||||
new PlaybackStopEventArgs
|
Users = users,
|
||||||
{
|
PlaybackPositionTicks = info.PositionTicks,
|
||||||
Item = libraryItem,
|
PlayedToCompletion = playedToCompletion,
|
||||||
Users = users,
|
MediaSourceId = info.MediaSourceId,
|
||||||
PlaybackPositionTicks = info.PositionTicks,
|
MediaInfo = info.Item,
|
||||||
PlayedToCompletion = playedToCompletion,
|
DeviceName = session.DeviceName,
|
||||||
MediaSourceId = info.MediaSourceId,
|
ClientName = session.Client,
|
||||||
MediaInfo = info.Item,
|
DeviceId = session.DeviceId,
|
||||||
DeviceName = session.DeviceName,
|
Session = session
|
||||||
ClientName = session.Client,
|
};
|
||||||
DeviceId = session.DeviceId,
|
|
||||||
Session = session
|
await _eventManager.PublishAsync(eventArgs).ConfigureAwait(false);
|
||||||
},
|
|
||||||
_logger);
|
EventHelper.QueueEventIfNotNull(PlaybackStopped, this, eventArgs, _logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool OnPlaybackStopped(User user, BaseItem item, long? positionTicks, bool playbackFailed)
|
private bool OnPlaybackStopped(User user, BaseItem item, long? positionTicks, bool playbackFailed)
|
||||||
|
|
|
@ -4,9 +4,9 @@ using System.Linq;
|
||||||
using System.Net.WebSockets;
|
using System.Net.WebSockets;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Jellyfin.Data.Events;
|
||||||
using MediaBrowser.Controller.Net;
|
using MediaBrowser.Controller.Net;
|
||||||
using MediaBrowser.Controller.Session;
|
using MediaBrowser.Controller.Session;
|
||||||
using MediaBrowser.Model.Events;
|
|
||||||
using MediaBrowser.Model.Net;
|
using MediaBrowser.Model.Net;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Jellyfin.Api.Constants;
|
using Jellyfin.Api.Constants;
|
||||||
using Jellyfin.Api.Extensions;
|
using Jellyfin.Api.Extensions;
|
||||||
using Jellyfin.Api.Helpers;
|
using Jellyfin.Api.Helpers;
|
||||||
|
@ -51,7 +52,7 @@ namespace Jellyfin.Api.Controllers
|
||||||
/// <returns>A <see cref="CollectionCreationOptions"/> with information about the new collection.</returns>
|
/// <returns>A <see cref="CollectionCreationOptions"/> with information about the new collection.</returns>
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||||
public ActionResult<CollectionCreationResult> CreateCollection(
|
public async Task<ActionResult<CollectionCreationResult>> CreateCollection(
|
||||||
[FromQuery] string? name,
|
[FromQuery] string? name,
|
||||||
[FromQuery] string? ids,
|
[FromQuery] string? ids,
|
||||||
[FromQuery] Guid? parentId,
|
[FromQuery] Guid? parentId,
|
||||||
|
@ -59,14 +60,14 @@ namespace Jellyfin.Api.Controllers
|
||||||
{
|
{
|
||||||
var userId = _authContext.GetAuthorizationInfo(Request).UserId;
|
var userId = _authContext.GetAuthorizationInfo(Request).UserId;
|
||||||
|
|
||||||
var item = _collectionManager.CreateCollection(new CollectionCreationOptions
|
var item = await _collectionManager.CreateCollectionAsync(new CollectionCreationOptions
|
||||||
{
|
{
|
||||||
IsLocked = isLocked,
|
IsLocked = isLocked,
|
||||||
Name = name,
|
Name = name,
|
||||||
ParentId = parentId,
|
ParentId = parentId,
|
||||||
ItemIdList = RequestHelpers.Split(ids, ',', true),
|
ItemIdList = RequestHelpers.Split(ids, ',', true),
|
||||||
UserIds = new[] { userId }
|
UserIds = new[] { userId }
|
||||||
});
|
}).ConfigureAwait(false);
|
||||||
|
|
||||||
var dtoOptions = new DtoOptions().AddClientFields(Request);
|
var dtoOptions = new DtoOptions().AddClientFields(Request);
|
||||||
|
|
||||||
|
@ -87,9 +88,9 @@ namespace Jellyfin.Api.Controllers
|
||||||
/// <returns>A <see cref="NoContentResult"/> indicating success.</returns>
|
/// <returns>A <see cref="NoContentResult"/> indicating success.</returns>
|
||||||
[HttpPost("{collectionId}/Items")]
|
[HttpPost("{collectionId}/Items")]
|
||||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||||
public ActionResult AddToCollection([FromRoute] Guid collectionId, [FromQuery, Required] string? itemIds)
|
public async Task<ActionResult> AddToCollection([FromRoute] Guid collectionId, [FromQuery, Required] string? itemIds)
|
||||||
{
|
{
|
||||||
_collectionManager.AddToCollection(collectionId, RequestHelpers.Split(itemIds, ',', true));
|
await _collectionManager.AddToCollectionAsync(collectionId, RequestHelpers.GetGuids(itemIds)).ConfigureAwait(true);
|
||||||
return NoContent();
|
return NoContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,9 +103,9 @@ namespace Jellyfin.Api.Controllers
|
||||||
/// <returns>A <see cref="NoContentResult"/> indicating success.</returns>
|
/// <returns>A <see cref="NoContentResult"/> indicating success.</returns>
|
||||||
[HttpDelete("{collectionId}/Items")]
|
[HttpDelete("{collectionId}/Items")]
|
||||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||||
public ActionResult RemoveFromCollection([FromRoute] Guid collectionId, [FromQuery, Required] string? itemIds)
|
public async Task<ActionResult> RemoveFromCollection([FromRoute] Guid collectionId, [FromQuery, Required] string? itemIds)
|
||||||
{
|
{
|
||||||
_collectionManager.RemoveFromCollection(collectionId, RequestHelpers.Split(itemIds, ',', true));
|
await _collectionManager.RemoveFromCollectionAsync(collectionId, RequestHelpers.GetGuids(itemIds)).ConfigureAwait(false);
|
||||||
return NoContent();
|
return NoContent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,7 +117,7 @@ namespace Jellyfin.Api.Controllers
|
||||||
[HttpPost("MediaEncoder/Path")]
|
[HttpPost("MediaEncoder/Path")]
|
||||||
[Authorize(Policy = Policies.FirstTimeSetupOrElevated)]
|
[Authorize(Policy = Policies.FirstTimeSetupOrElevated)]
|
||||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||||
public ActionResult UpdateMediaEncoderPath([FromForm, Required] MediaEncoderPathDto mediaEncoderPath)
|
public ActionResult UpdateMediaEncoderPath([FromBody, Required] MediaEncoderPathDto mediaEncoderPath)
|
||||||
{
|
{
|
||||||
_mediaEncoder.UpdateEncoderPath(mediaEncoderPath.Path, mediaEncoderPath.PathType);
|
_mediaEncoder.UpdateEncoderPath(mediaEncoderPath.Path, mediaEncoderPath.PathType);
|
||||||
return NoContent();
|
return NoContent();
|
||||||
|
|
|
@ -229,7 +229,7 @@ namespace Jellyfin.Api.Controllers
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private EventSubscriptionResponse ProcessEventRequest(IEventManager eventManager)
|
private EventSubscriptionResponse ProcessEventRequest(IDlnaEventManager dlnaEventManager)
|
||||||
{
|
{
|
||||||
var subscriptionId = Request.Headers["SID"];
|
var subscriptionId = Request.Headers["SID"];
|
||||||
if (string.Equals(Request.Method, "subscribe", StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(Request.Method, "subscribe", StringComparison.OrdinalIgnoreCase))
|
||||||
|
@ -240,17 +240,17 @@ namespace Jellyfin.Api.Controllers
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(notificationType))
|
if (string.IsNullOrEmpty(notificationType))
|
||||||
{
|
{
|
||||||
return eventManager.RenewEventSubscription(
|
return dlnaEventManager.RenewEventSubscription(
|
||||||
subscriptionId,
|
subscriptionId,
|
||||||
notificationType,
|
notificationType,
|
||||||
timeoutString,
|
timeoutString,
|
||||||
callback);
|
callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
return eventManager.CreateEventSubscription(notificationType, timeoutString, callback);
|
return dlnaEventManager.CreateEventSubscription(notificationType, timeoutString, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
return eventManager.CancelEventSubscription(subscriptionId);
|
return dlnaEventManager.CancelEventSubscription(subscriptionId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1356,7 +1356,7 @@ namespace Jellyfin.Api.Controllers
|
||||||
|
|
||||||
return string.Format(
|
return string.Format(
|
||||||
CultureInfo.InvariantCulture,
|
CultureInfo.InvariantCulture,
|
||||||
"{0} {1} -map_metadata -1 -map_chapters -1 -threads {2} {3} {4} {5} -copyts -avoid_negative_ts disabled -f hls -max_delay 5000000 -hls_time {6} -individual_header_trailer 0 -hls_segment_type {7} -start_number {8} -hls_segment_filename \"{9}\" -hls_playlist_type vod -hls_list_size 0 -y \"{10}\"",
|
"{0} {1} -map_metadata -1 -map_chapters -1 -threads {2} {3} {4} {5} -copyts -avoid_negative_ts disabled -max_muxing_queue_size 2048 -f hls -max_delay 5000000 -hls_time {6} -individual_header_trailer 0 -hls_segment_type {7} -start_number {8} -hls_segment_filename \"{9}\" -hls_playlist_type vod -hls_list_size 0 -y \"{10}\"",
|
||||||
inputModifier,
|
inputModifier,
|
||||||
_encodingHelper.GetInputArgument(state, encodingOptions),
|
_encodingHelper.GetInputArgument(state, encodingOptions),
|
||||||
threads,
|
threads,
|
||||||
|
|
|
@ -174,7 +174,7 @@ namespace Jellyfin.Api.Controllers
|
||||||
[Authorize(Policy = Policies.RequiresElevation)]
|
[Authorize(Policy = Policies.RequiresElevation)]
|
||||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
public ActionResult DeleteItemImage(
|
public async Task<ActionResult> DeleteItemImage(
|
||||||
[FromRoute] Guid itemId,
|
[FromRoute] Guid itemId,
|
||||||
[FromRoute] ImageType imageType,
|
[FromRoute] ImageType imageType,
|
||||||
[FromRoute] int? imageIndex = null)
|
[FromRoute] int? imageIndex = null)
|
||||||
|
@ -185,7 +185,7 @@ namespace Jellyfin.Api.Controllers
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
item.DeleteImage(imageType, imageIndex ?? 0);
|
await item.DeleteImageAsync(imageType, imageIndex ?? 0).ConfigureAwait(false);
|
||||||
return NoContent();
|
return NoContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,7 +218,7 @@ namespace Jellyfin.Api.Controllers
|
||||||
// Handle image/png; charset=utf-8
|
// Handle image/png; charset=utf-8
|
||||||
var mimeType = Request.ContentType.Split(';').FirstOrDefault();
|
var mimeType = Request.ContentType.Split(';').FirstOrDefault();
|
||||||
await _providerManager.SaveImage(item, Request.Body, mimeType, imageType, null, CancellationToken.None).ConfigureAwait(false);
|
await _providerManager.SaveImage(item, Request.Body, mimeType, imageType, null, CancellationToken.None).ConfigureAwait(false);
|
||||||
item.UpdateToRepository(ItemUpdateType.ImageUpdate, CancellationToken.None);
|
await item.UpdateToRepositoryAsync(ItemUpdateType.ImageUpdate, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
return NoContent();
|
return NoContent();
|
||||||
}
|
}
|
||||||
|
@ -237,7 +237,7 @@ namespace Jellyfin.Api.Controllers
|
||||||
[Authorize(Policy = Policies.RequiresElevation)]
|
[Authorize(Policy = Policies.RequiresElevation)]
|
||||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
public ActionResult UpdateItemImageIndex(
|
public async Task<ActionResult> UpdateItemImageIndex(
|
||||||
[FromRoute] Guid itemId,
|
[FromRoute] Guid itemId,
|
||||||
[FromRoute] ImageType imageType,
|
[FromRoute] ImageType imageType,
|
||||||
[FromRoute] int imageIndex,
|
[FromRoute] int imageIndex,
|
||||||
|
@ -249,7 +249,7 @@ namespace Jellyfin.Api.Controllers
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
item.SwapImages(imageType, imageIndex, newIndex);
|
await item.SwapImagesAsync(imageType, imageIndex, newIndex).ConfigureAwait(false);
|
||||||
return NoContent();
|
return NoContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,7 +264,7 @@ namespace Jellyfin.Api.Controllers
|
||||||
[Authorize(Policy = Policies.DefaultAuthorization)]
|
[Authorize(Policy = Policies.DefaultAuthorization)]
|
||||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
public ActionResult<IEnumerable<ImageInfo>> GetItemImageInfos([FromRoute] Guid itemId)
|
public async Task<ActionResult<IEnumerable<ImageInfo>>> GetItemImageInfos([FromRoute] Guid itemId)
|
||||||
{
|
{
|
||||||
var item = _libraryManager.GetItemById(itemId);
|
var item = _libraryManager.GetItemById(itemId);
|
||||||
if (item == null)
|
if (item == null)
|
||||||
|
@ -281,7 +281,7 @@ namespace Jellyfin.Api.Controllers
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
_libraryManager.UpdateImages(item); // this makes sure dimensions and hashes are correct
|
await _libraryManager.UpdateImagesAsync(item).ConfigureAwait(false); // this makes sure dimensions and hashes are correct
|
||||||
|
|
||||||
foreach (var image in itemImages)
|
foreach (var image in itemImages)
|
||||||
{
|
{
|
||||||
|
@ -1281,9 +1281,9 @@ namespace Jellyfin.Api.Controllers
|
||||||
Response.Headers.Add(HeaderNames.LastModified, dateImageModified.ToUniversalTime().ToString("ddd, dd MMM yyyy HH:mm:ss \"GMT\"", new CultureInfo("en-US", false)));
|
Response.Headers.Add(HeaderNames.LastModified, dateImageModified.ToUniversalTime().ToString("ddd, dd MMM yyyy HH:mm:ss \"GMT\"", new CultureInfo("en-US", false)));
|
||||||
|
|
||||||
// if the image was not modified since "ifModifiedSinceHeader"-header, return a HTTP status code 304 not modified
|
// if the image was not modified since "ifModifiedSinceHeader"-header, return a HTTP status code 304 not modified
|
||||||
if (!(dateImageModified > ifModifiedSinceHeader))
|
if (!(dateImageModified > ifModifiedSinceHeader) && cacheDuration.HasValue)
|
||||||
{
|
{
|
||||||
if (ifModifiedSinceHeader.Add(cacheDuration!.Value) < DateTime.UtcNow)
|
if (ifModifiedSinceHeader.Add(cacheDuration.Value) < DateTime.UtcNow)
|
||||||
{
|
{
|
||||||
Response.StatusCode = StatusCodes.Status304NotModified;
|
Response.StatusCode = StatusCodes.Status304NotModified;
|
||||||
return new ContentResult();
|
return new ContentResult();
|
||||||
|
|
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Jellyfin.Api.Constants;
|
using Jellyfin.Api.Constants;
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
|
@ -67,7 +68,7 @@ namespace Jellyfin.Api.Controllers
|
||||||
[HttpPost("Items/{itemId}")]
|
[HttpPost("Items/{itemId}")]
|
||||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
public ActionResult UpdateItem([FromRoute] Guid itemId, [FromBody, Required] BaseItemDto request)
|
public async Task<ActionResult> UpdateItem([FromRoute] Guid itemId, [FromBody, Required] BaseItemDto request)
|
||||||
{
|
{
|
||||||
var item = _libraryManager.GetItemById(itemId);
|
var item = _libraryManager.GetItemById(itemId);
|
||||||
if (item == null)
|
if (item == null)
|
||||||
|
@ -101,7 +102,7 @@ namespace Jellyfin.Api.Controllers
|
||||||
|
|
||||||
item.OnMetadataChanged();
|
item.OnMetadataChanged();
|
||||||
|
|
||||||
item.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None);
|
await item.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
if (isLockedChanged && item.IsFolder)
|
if (isLockedChanged && item.IsFolder)
|
||||||
{
|
{
|
||||||
|
@ -110,7 +111,7 @@ namespace Jellyfin.Api.Controllers
|
||||||
foreach (var child in folder.GetRecursiveChildren())
|
foreach (var child in folder.GetRecursiveChildren())
|
||||||
{
|
{
|
||||||
child.IsLocked = newLockData;
|
child.IsLocked = newLockData;
|
||||||
child.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None);
|
await child.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,10 +4,10 @@ using System.Linq;
|
||||||
using Jellyfin.Api.Constants;
|
using Jellyfin.Api.Constants;
|
||||||
using Jellyfin.Api.Extensions;
|
using Jellyfin.Api.Extensions;
|
||||||
using Jellyfin.Api.Helpers;
|
using Jellyfin.Api.Helpers;
|
||||||
using Jellyfin.Data.Entities;
|
|
||||||
using Jellyfin.Data.Enums;
|
using Jellyfin.Data.Enums;
|
||||||
using MediaBrowser.Controller.Dto;
|
using MediaBrowser.Controller.Dto;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
|
using MediaBrowser.Controller.Entities.Audio;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
using MediaBrowser.Model.Dto;
|
using MediaBrowser.Model.Dto;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
|
@ -266,7 +266,9 @@ namespace Jellyfin.Api.Controllers
|
||||||
|
|
||||||
bool isInEnabledFolder = user!.GetPreference(PreferenceKind.EnabledFolders).Any(i => new Guid(i) == item.Id)
|
bool isInEnabledFolder = user!.GetPreference(PreferenceKind.EnabledFolders).Any(i => new Guid(i) == item.Id)
|
||||||
// Assume all folders inside an EnabledChannel are enabled
|
// Assume all folders inside an EnabledChannel are enabled
|
||||||
|| user.GetPreference(PreferenceKind.EnabledChannels).Any(i => new Guid(i) == item.Id);
|
|| user.GetPreference(PreferenceKind.EnabledChannels).Any(i => new Guid(i) == item.Id)
|
||||||
|
// Assume all items inside an EnabledChannel are enabled
|
||||||
|
|| user.GetPreference(PreferenceKind.EnabledChannels).Any(i => new Guid(i) == item.ChannelId);
|
||||||
|
|
||||||
var collectionFolders = _libraryManager.GetCollectionFolders(item);
|
var collectionFolders = _libraryManager.GetCollectionFolders(item);
|
||||||
foreach (var collectionFolder in collectionFolders)
|
foreach (var collectionFolder in collectionFolders)
|
||||||
|
|
|
@ -19,6 +19,7 @@ using MediaBrowser.Controller.Dto;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Entities.Audio;
|
using MediaBrowser.Controller.Entities.Audio;
|
||||||
using MediaBrowser.Controller.Entities.Movies;
|
using MediaBrowser.Controller.Entities.Movies;
|
||||||
|
using MediaBrowser.Controller.Entities.TV;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
using MediaBrowser.Controller.LiveTv;
|
using MediaBrowser.Controller.LiveTv;
|
||||||
using MediaBrowser.Controller.Net;
|
using MediaBrowser.Controller.Net;
|
||||||
|
@ -35,8 +36,6 @@ using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Book = MediaBrowser.Controller.Entities.Book;
|
using Book = MediaBrowser.Controller.Entities.Book;
|
||||||
using Movie = Jellyfin.Data.Entities.Movie;
|
|
||||||
using MusicAlbum = Jellyfin.Data.Entities.MusicAlbum;
|
|
||||||
|
|
||||||
namespace Jellyfin.Api.Controllers
|
namespace Jellyfin.Api.Controllers
|
||||||
{
|
{
|
||||||
|
@ -619,7 +618,7 @@ namespace Jellyfin.Api.Controllers
|
||||||
[Authorize(Policy = Policies.Download)]
|
[Authorize(Policy = Policies.Download)]
|
||||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
public ActionResult GetDownload([FromRoute] Guid itemId)
|
public async Task<ActionResult> GetDownload([FromRoute] Guid itemId)
|
||||||
{
|
{
|
||||||
var item = _libraryManager.GetItemById(itemId);
|
var item = _libraryManager.GetItemById(itemId);
|
||||||
if (item == null)
|
if (item == null)
|
||||||
|
@ -648,7 +647,7 @@ namespace Jellyfin.Api.Controllers
|
||||||
|
|
||||||
if (user != null)
|
if (user != null)
|
||||||
{
|
{
|
||||||
LogDownload(item, user, auth);
|
await LogDownloadAsync(item, user, auth).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
var path = item.Path;
|
var path = item.Path;
|
||||||
|
@ -861,17 +860,17 @@ namespace Jellyfin.Api.Controllers
|
||||||
: item;
|
: item;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LogDownload(BaseItem item, User user, AuthorizationInfo auth)
|
private async Task LogDownloadAsync(BaseItem item, User user, AuthorizationInfo auth)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_activityManager.Create(new ActivityLog(
|
await _activityManager.CreateAsync(new ActivityLog(
|
||||||
string.Format(CultureInfo.InvariantCulture, _localization.GetLocalizedString("UserDownloadingItemWithValues"), user.Username, item.Name),
|
string.Format(CultureInfo.InvariantCulture, _localization.GetLocalizedString("UserDownloadingItemWithValues"), user.Username, item.Name),
|
||||||
"UserDownloadingContent",
|
"UserDownloadingContent",
|
||||||
auth.UserId)
|
auth.UserId)
|
||||||
{
|
{
|
||||||
ShortOverview = string.Format(CultureInfo.InvariantCulture, _localization.GetLocalizedString("AppDeviceValues"), auth.Client, auth.Device),
|
ShortOverview = string.Format(CultureInfo.InvariantCulture, _localization.GetLocalizedString("AppDeviceValues"), auth.Client, auth.Device),
|
||||||
});
|
}).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
|
|
|
@ -76,7 +76,7 @@ namespace Jellyfin.Api.Controllers
|
||||||
[FromQuery] string? name,
|
[FromQuery] string? name,
|
||||||
[FromQuery] string? collectionType,
|
[FromQuery] string? collectionType,
|
||||||
[FromQuery] string[] paths,
|
[FromQuery] string[] paths,
|
||||||
[FromBody] LibraryOptionsDto? libraryOptionsDto,
|
[FromBody] AddVirtualFolderDto? libraryOptionsDto,
|
||||||
[FromQuery] bool refreshLibrary = false)
|
[FromQuery] bool refreshLibrary = false)
|
||||||
{
|
{
|
||||||
var libraryOptions = libraryOptionsDto?.LibraryOptions ?? new LibraryOptions();
|
var libraryOptions = libraryOptionsDto?.LibraryOptions ?? new LibraryOptions();
|
||||||
|
@ -312,19 +312,17 @@ namespace Jellyfin.Api.Controllers
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Update library options.
|
/// Update library options.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="id">The library name.</param>
|
/// <param name="request">The library name and options.</param>
|
||||||
/// <param name="libraryOptions">The library options.</param>
|
|
||||||
/// <response code="204">Library updated.</response>
|
/// <response code="204">Library updated.</response>
|
||||||
/// <returns>A <see cref="NoContentResult"/>.</returns>
|
/// <returns>A <see cref="NoContentResult"/>.</returns>
|
||||||
[HttpPost("LibraryOptions")]
|
[HttpPost("LibraryOptions")]
|
||||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||||
public ActionResult UpdateLibraryOptions(
|
public ActionResult UpdateLibraryOptions(
|
||||||
[FromQuery] string? id,
|
[FromBody] UpdateLibraryOptionsDto request)
|
||||||
[FromBody] LibraryOptions? libraryOptions)
|
|
||||||
{
|
{
|
||||||
var collectionFolder = (CollectionFolder)_libraryManager.GetItemById(id);
|
var collectionFolder = (CollectionFolder)_libraryManager.GetItemById(request.Id);
|
||||||
|
|
||||||
collectionFolder.UpdateLibraryOptions(libraryOptions);
|
collectionFolder.UpdateLibraryOptions(request.LibraryOptions);
|
||||||
return NoContent();
|
return NoContent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -269,9 +269,9 @@ namespace Jellyfin.Api.Controllers
|
||||||
/// <returns>A <see cref="NoContentResult"/> indicating success.</returns>
|
/// <returns>A <see cref="NoContentResult"/> indicating success.</returns>
|
||||||
[HttpPost("LiveStreams/Close")]
|
[HttpPost("LiveStreams/Close")]
|
||||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||||
public ActionResult CloseLiveStream([FromQuery, Required] string? liveStreamId)
|
public async Task<ActionResult> CloseLiveStream([FromQuery, Required] string? liveStreamId)
|
||||||
{
|
{
|
||||||
_mediaSourceManager.CloseLiveStream(liveStreamId).GetAwaiter().GetResult();
|
await _mediaSourceManager.CloseLiveStream(liveStreamId).ConfigureAwait(false);
|
||||||
return NoContent();
|
return NoContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ using MediaBrowser.Common.Extensions;
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
using MediaBrowser.Controller.Dto;
|
using MediaBrowser.Controller.Dto;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
|
using MediaBrowser.Controller.Entities.Movies;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
using MediaBrowser.Controller.LiveTv;
|
using MediaBrowser.Controller.LiveTv;
|
||||||
using MediaBrowser.Model.Dto;
|
using MediaBrowser.Model.Dto;
|
||||||
|
@ -181,7 +182,7 @@ namespace Jellyfin.Api.Controllers
|
||||||
DtoOptions dtoOptions,
|
DtoOptions dtoOptions,
|
||||||
RecommendationType type)
|
RecommendationType type)
|
||||||
{
|
{
|
||||||
var itemTypes = new List<string> { nameof(MediaBrowser.Controller.Entities.Movies.Movie) };
|
var itemTypes = new List<string> { nameof(Movie) };
|
||||||
if (_serverConfigurationManager.Configuration.EnableExternalContentInSuggestions)
|
if (_serverConfigurationManager.Configuration.EnableExternalContentInSuggestions)
|
||||||
{
|
{
|
||||||
itemTypes.Add(nameof(Trailer));
|
itemTypes.Add(nameof(Trailer));
|
||||||
|
|
|
@ -83,12 +83,12 @@ namespace Jellyfin.Api.Controllers
|
||||||
/// <returns>An <see cref="NoContentResult"/> on success.</returns>
|
/// <returns>An <see cref="NoContentResult"/> on success.</returns>
|
||||||
[HttpPost("{playlistId}/Items")]
|
[HttpPost("{playlistId}/Items")]
|
||||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||||
public ActionResult AddToPlaylist(
|
public async Task<ActionResult> AddToPlaylist(
|
||||||
[FromRoute] string? playlistId,
|
[FromRoute] Guid playlistId,
|
||||||
[FromQuery] string? ids,
|
[FromQuery] string? ids,
|
||||||
[FromQuery] Guid? userId)
|
[FromQuery] Guid? userId)
|
||||||
{
|
{
|
||||||
_playlistManager.AddToPlaylist(playlistId, RequestHelpers.GetGuids(ids), userId ?? Guid.Empty);
|
await _playlistManager.AddToPlaylistAsync(playlistId, RequestHelpers.GetGuids(ids), userId ?? Guid.Empty).ConfigureAwait(false);
|
||||||
return NoContent();
|
return NoContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,12 +102,12 @@ namespace Jellyfin.Api.Controllers
|
||||||
/// <returns>An <see cref="NoContentResult"/> on success.</returns>
|
/// <returns>An <see cref="NoContentResult"/> on success.</returns>
|
||||||
[HttpPost("{playlistId}/Items/{itemId}/Move/{newIndex}")]
|
[HttpPost("{playlistId}/Items/{itemId}/Move/{newIndex}")]
|
||||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||||
public ActionResult MoveItem(
|
public async Task<ActionResult> MoveItem(
|
||||||
[FromRoute] string? playlistId,
|
[FromRoute] string? playlistId,
|
||||||
[FromRoute] string? itemId,
|
[FromRoute] string? itemId,
|
||||||
[FromRoute] int newIndex)
|
[FromRoute] int newIndex)
|
||||||
{
|
{
|
||||||
_playlistManager.MoveItem(playlistId, itemId, newIndex);
|
await _playlistManager.MoveItemAsync(playlistId, itemId, newIndex).ConfigureAwait(false);
|
||||||
return NoContent();
|
return NoContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,9 +120,9 @@ namespace Jellyfin.Api.Controllers
|
||||||
/// <returns>An <see cref="NoContentResult"/> on success.</returns>
|
/// <returns>An <see cref="NoContentResult"/> on success.</returns>
|
||||||
[HttpDelete("{playlistId}/Items")]
|
[HttpDelete("{playlistId}/Items")]
|
||||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||||
public ActionResult RemoveFromPlaylist([FromRoute] string? playlistId, [FromQuery] string? entryIds)
|
public async Task<ActionResult> RemoveFromPlaylist([FromRoute] string? playlistId, [FromQuery] string? entryIds)
|
||||||
{
|
{
|
||||||
_playlistManager.RemoveFromPlaylist(playlistId, RequestHelpers.Split(entryIds, ',', true));
|
await _playlistManager.RemoveFromPlaylistAsync(playlistId, RequestHelpers.Split(entryIds, ',', true)).ConfigureAwait(false);
|
||||||
return NoContent();
|
return NoContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -120,10 +120,14 @@ namespace Jellyfin.Api.Controllers
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
var configuration = (BasePluginConfiguration)await JsonSerializer.DeserializeAsync(Request.Body, plugin.ConfigurationType, _serializerOptions)
|
var configuration = (BasePluginConfiguration?)await JsonSerializer.DeserializeAsync(Request.Body, plugin.ConfigurationType, _serializerOptions)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
plugin.UpdateConfiguration(configuration);
|
if (configuration != null)
|
||||||
|
{
|
||||||
|
plugin.UpdateConfiguration(configuration);
|
||||||
|
}
|
||||||
|
|
||||||
return NoContent();
|
return NoContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -221,7 +221,7 @@ namespace Jellyfin.Api.Controllers
|
||||||
await _providerManager.SaveImage(item, imageUrl, type, null, CancellationToken.None)
|
await _providerManager.SaveImage(item, imageUrl, type, null, CancellationToken.None)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
item.UpdateToRepository(ItemUpdateType.ImageUpdate, CancellationToken.None);
|
await item.UpdateToRepositoryAsync(ItemUpdateType.ImageUpdate, CancellationToken.None).ConfigureAwait(false);
|
||||||
return NoContent();
|
return NoContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -153,7 +153,6 @@ namespace Jellyfin.Api.Controllers
|
||||||
/// <param name="itemIds">The ids of the items to play, comma delimited.</param>
|
/// <param name="itemIds">The ids of the items to play, comma delimited.</param>
|
||||||
/// <param name="startPositionTicks">The starting position of the first item.</param>
|
/// <param name="startPositionTicks">The starting position of the first item.</param>
|
||||||
/// <param name="playCommand">The type of play command to issue (PlayNow, PlayNext, PlayLast). Clients who have not yet implemented play next and play last may play now.</param>
|
/// <param name="playCommand">The type of play command to issue (PlayNow, PlayNext, PlayLast). Clients who have not yet implemented play next and play last may play now.</param>
|
||||||
/// <param name="playRequest">The <see cref="PlayRequest"/>.</param>
|
|
||||||
/// <response code="204">Instruction sent to session.</response>
|
/// <response code="204">Instruction sent to session.</response>
|
||||||
/// <returns>A <see cref="NoContentResult"/>.</returns>
|
/// <returns>A <see cref="NoContentResult"/>.</returns>
|
||||||
[HttpPost("Sessions/{sessionId}/Playing")]
|
[HttpPost("Sessions/{sessionId}/Playing")]
|
||||||
|
@ -163,17 +162,14 @@ namespace Jellyfin.Api.Controllers
|
||||||
[FromRoute, Required] string? sessionId,
|
[FromRoute, Required] string? sessionId,
|
||||||
[FromQuery] Guid[] itemIds,
|
[FromQuery] Guid[] itemIds,
|
||||||
[FromQuery] long? startPositionTicks,
|
[FromQuery] long? startPositionTicks,
|
||||||
[FromQuery] PlayCommand playCommand,
|
[FromQuery] PlayCommand playCommand)
|
||||||
[FromBody, Required] PlayRequest playRequest)
|
|
||||||
{
|
{
|
||||||
if (playRequest == null)
|
var playRequest = new PlayRequest
|
||||||
{
|
{
|
||||||
throw new ArgumentException("Request Body may not be null");
|
ItemIds = itemIds,
|
||||||
}
|
StartPositionTicks = startPositionTicks,
|
||||||
|
PlayCommand = playCommand
|
||||||
playRequest.ItemIds = itemIds;
|
};
|
||||||
playRequest.StartPositionTicks = startPositionTicks;
|
|
||||||
playRequest.PlayCommand = playCommand;
|
|
||||||
|
|
||||||
_sessionManager.SendPlayCommand(
|
_sessionManager.SendPlayCommand(
|
||||||
RequestHelpers.GetSession(_sessionManager, _authContext, Request).Id,
|
RequestHelpers.GetSession(_sessionManager, _authContext, Request).Id,
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Jellyfin.Api.Constants;
|
using Jellyfin.Api.Constants;
|
||||||
|
@ -64,21 +65,16 @@ namespace Jellyfin.Api.Controllers
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets the initial startup wizard configuration.
|
/// Sets the initial startup wizard configuration.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="uiCulture">The UI language culture.</param>
|
/// <param name="startupConfiguration">The updated startup configuration.</param>
|
||||||
/// <param name="metadataCountryCode">The metadata country code.</param>
|
|
||||||
/// <param name="preferredMetadataLanguage">The preferred language for metadata.</param>
|
|
||||||
/// <response code="204">Configuration saved.</response>
|
/// <response code="204">Configuration saved.</response>
|
||||||
/// <returns>A <see cref="NoContentResult"/> indicating success.</returns>
|
/// <returns>A <see cref="NoContentResult"/> indicating success.</returns>
|
||||||
[HttpPost("Configuration")]
|
[HttpPost("Configuration")]
|
||||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||||
public ActionResult UpdateInitialConfiguration(
|
public ActionResult UpdateInitialConfiguration([FromBody, Required] StartupConfigurationDto startupConfiguration)
|
||||||
[FromForm] string? uiCulture,
|
|
||||||
[FromForm] string? metadataCountryCode,
|
|
||||||
[FromForm] string? preferredMetadataLanguage)
|
|
||||||
{
|
{
|
||||||
_config.Configuration.UICulture = uiCulture;
|
_config.Configuration.UICulture = startupConfiguration.UICulture;
|
||||||
_config.Configuration.MetadataCountryCode = metadataCountryCode;
|
_config.Configuration.MetadataCountryCode = startupConfiguration.MetadataCountryCode;
|
||||||
_config.Configuration.PreferredMetadataLanguage = preferredMetadataLanguage;
|
_config.Configuration.PreferredMetadataLanguage = startupConfiguration.PreferredMetadataLanguage;
|
||||||
_config.SaveConfiguration();
|
_config.SaveConfiguration();
|
||||||
return NoContent();
|
return NoContent();
|
||||||
}
|
}
|
||||||
|
@ -86,16 +82,15 @@ namespace Jellyfin.Api.Controllers
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets remote access and UPnP.
|
/// Sets remote access and UPnP.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="enableRemoteAccess">Enable remote access.</param>
|
/// <param name="startupRemoteAccessDto">The startup remote access dto.</param>
|
||||||
/// <param name="enableAutomaticPortMapping">Enable UPnP.</param>
|
|
||||||
/// <response code="204">Configuration saved.</response>
|
/// <response code="204">Configuration saved.</response>
|
||||||
/// <returns>A <see cref="NoContentResult"/> indicating success.</returns>
|
/// <returns>A <see cref="NoContentResult"/> indicating success.</returns>
|
||||||
[HttpPost("RemoteAccess")]
|
[HttpPost("RemoteAccess")]
|
||||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||||
public ActionResult SetRemoteAccess([FromForm] bool enableRemoteAccess, [FromForm] bool enableAutomaticPortMapping)
|
public ActionResult SetRemoteAccess([FromBody, Required] StartupRemoteAccessDto startupRemoteAccessDto)
|
||||||
{
|
{
|
||||||
_config.Configuration.EnableRemoteAccess = enableRemoteAccess;
|
_config.Configuration.EnableRemoteAccess = startupRemoteAccessDto.EnableRemoteAccess;
|
||||||
_config.Configuration.EnableUPnP = enableAutomaticPortMapping;
|
_config.Configuration.EnableUPnP = startupRemoteAccessDto.EnableAutomaticPortMapping;
|
||||||
_config.SaveConfiguration();
|
_config.SaveConfiguration();
|
||||||
return NoContent();
|
return NoContent();
|
||||||
}
|
}
|
||||||
|
@ -131,7 +126,7 @@ namespace Jellyfin.Api.Controllers
|
||||||
/// </returns>
|
/// </returns>
|
||||||
[HttpPost("User")]
|
[HttpPost("User")]
|
||||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||||
public async Task<ActionResult> UpdateStartupUser([FromForm] StartupUserDto startupUserDto)
|
public async Task<ActionResult> UpdateStartupUser([FromBody] StartupUserDto startupUserDto)
|
||||||
{
|
{
|
||||||
var user = _userManager.Users.First();
|
var user = _userManager.Users.First();
|
||||||
|
|
||||||
|
|
|
@ -161,7 +161,7 @@ namespace Jellyfin.Api.Controllers
|
||||||
[Authorize(Policy = Policies.RequiresElevation)]
|
[Authorize(Policy = Policies.RequiresElevation)]
|
||||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
public ActionResult DeleteAlternateSources([FromRoute] Guid itemId)
|
public async Task<ActionResult> DeleteAlternateSources([FromRoute] Guid itemId)
|
||||||
{
|
{
|
||||||
var video = (Video)_libraryManager.GetItemById(itemId);
|
var video = (Video)_libraryManager.GetItemById(itemId);
|
||||||
|
|
||||||
|
@ -180,12 +180,12 @@ namespace Jellyfin.Api.Controllers
|
||||||
link.SetPrimaryVersionId(null);
|
link.SetPrimaryVersionId(null);
|
||||||
link.LinkedAlternateVersions = Array.Empty<LinkedChild>();
|
link.LinkedAlternateVersions = Array.Empty<LinkedChild>();
|
||||||
|
|
||||||
link.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None);
|
await link.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
video.LinkedAlternateVersions = Array.Empty<LinkedChild>();
|
video.LinkedAlternateVersions = Array.Empty<LinkedChild>();
|
||||||
video.SetPrimaryVersionId(null);
|
video.SetPrimaryVersionId(null);
|
||||||
video.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None);
|
await video.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
return NoContent();
|
return NoContent();
|
||||||
}
|
}
|
||||||
|
@ -201,7 +201,7 @@ namespace Jellyfin.Api.Controllers
|
||||||
[Authorize(Policy = Policies.RequiresElevation)]
|
[Authorize(Policy = Policies.RequiresElevation)]
|
||||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||||
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
||||||
public ActionResult MergeVersions([FromQuery, Required] string? itemIds)
|
public async Task<ActionResult> MergeVersions([FromQuery, Required] string? itemIds)
|
||||||
{
|
{
|
||||||
var items = RequestHelpers.Split(itemIds, ',', true)
|
var items = RequestHelpers.Split(itemIds, ',', true)
|
||||||
.Select(i => _libraryManager.GetItemById(i))
|
.Select(i => _libraryManager.GetItemById(i))
|
||||||
|
@ -239,7 +239,7 @@ namespace Jellyfin.Api.Controllers
|
||||||
{
|
{
|
||||||
item.SetPrimaryVersionId(primaryVersion.Id.ToString("N", CultureInfo.InvariantCulture));
|
item.SetPrimaryVersionId(primaryVersion.Id.ToString("N", CultureInfo.InvariantCulture));
|
||||||
|
|
||||||
item.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None);
|
await item.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
list.Add(new LinkedChild
|
list.Add(new LinkedChild
|
||||||
{
|
{
|
||||||
|
@ -258,12 +258,12 @@ namespace Jellyfin.Api.Controllers
|
||||||
if (item.LinkedAlternateVersions.Length > 0)
|
if (item.LinkedAlternateVersions.Length > 0)
|
||||||
{
|
{
|
||||||
item.LinkedAlternateVersions = Array.Empty<LinkedChild>();
|
item.LinkedAlternateVersions = Array.Empty<LinkedChild>();
|
||||||
item.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None);
|
await item.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
primaryVersion.LinkedAlternateVersions = list.ToArray();
|
primaryVersion.LinkedAlternateVersions = list.ToArray();
|
||||||
primaryVersion.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None);
|
await primaryVersion.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
|
||||||
return NoContent();
|
return NoContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -127,7 +127,11 @@ namespace Jellyfin.Api.Helpers
|
||||||
{
|
{
|
||||||
// Since we're going to be setting properties on MediaSourceInfos that come out of _mediaSourceManager, we should clone it
|
// Since we're going to be setting properties on MediaSourceInfos that come out of _mediaSourceManager, we should clone it
|
||||||
// Should we move this directly into MediaSourceManager?
|
// Should we move this directly into MediaSourceManager?
|
||||||
result.MediaSources = JsonSerializer.Deserialize<MediaSourceInfo[]>(JsonSerializer.SerializeToUtf8Bytes(mediaSources));
|
var mediaSourcesClone = JsonSerializer.Deserialize<MediaSourceInfo[]>(JsonSerializer.SerializeToUtf8Bytes(mediaSources));
|
||||||
|
if (mediaSourcesClone != null)
|
||||||
|
{
|
||||||
|
result.MediaSources = mediaSourcesClone;
|
||||||
|
}
|
||||||
|
|
||||||
result.PlaySessionId = Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture);
|
result.PlaySessionId = Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,9 +3,9 @@
|
||||||
namespace Jellyfin.Api.Models.LibraryStructureDto
|
namespace Jellyfin.Api.Models.LibraryStructureDto
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Library options dto.
|
/// Add virtual folder dto.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class LibraryOptionsDto
|
public class AddVirtualFolderDto
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets library options.
|
/// Gets or sets library options.
|
|
@ -0,0 +1,21 @@
|
||||||
|
using System;
|
||||||
|
using MediaBrowser.Model.Configuration;
|
||||||
|
|
||||||
|
namespace Jellyfin.Api.Models.LibraryStructureDto
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Update library options dto.
|
||||||
|
/// </summary>
|
||||||
|
public class UpdateLibraryOptionsDto
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the library item id.
|
||||||
|
/// </summary>
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets library options.
|
||||||
|
/// </summary>
|
||||||
|
public LibraryOptions? LibraryOptions { get; set; }
|
||||||
|
}
|
||||||
|
}
|
22
Jellyfin.Api/Models/StartupDtos/StartupRemoteAccessDto.cs
Normal file
22
Jellyfin.Api/Models/StartupDtos/StartupRemoteAccessDto.cs
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace Jellyfin.Api.Models.StartupDtos
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Startup remote access dto.
|
||||||
|
/// </summary>
|
||||||
|
public class StartupRemoteAccessDto
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether enable remote access.
|
||||||
|
/// </summary>
|
||||||
|
[Required]
|
||||||
|
public bool EnableRemoteAccess { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether enable automatic port mapping.
|
||||||
|
/// </summary>
|
||||||
|
[Required]
|
||||||
|
public bool EnableAutomaticPortMapping { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,8 +1,8 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Jellyfin.Data.Events;
|
||||||
using MediaBrowser.Controller.Net;
|
using MediaBrowser.Controller.Net;
|
||||||
using MediaBrowser.Model.Activity;
|
using MediaBrowser.Model.Activity;
|
||||||
using MediaBrowser.Model.Events;
|
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace Jellyfin.Api.WebSocketListeners
|
namespace Jellyfin.Api.WebSocketListeners
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Jellyfin.Data.Events;
|
||||||
using MediaBrowser.Controller.Net;
|
using MediaBrowser.Controller.Net;
|
||||||
using MediaBrowser.Model.Events;
|
|
||||||
using MediaBrowser.Model.Tasks;
|
using MediaBrowser.Model.Tasks;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Jellyfin.Data.Enums;
|
using Jellyfin.Data.Enums;
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using Jellyfin.Data.Interfaces;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace Jellyfin.Data.Entities
|
namespace Jellyfin.Data.Entities
|
||||||
|
@ -8,7 +11,7 @@ namespace Jellyfin.Data.Entities
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// An entity referencing an activity log entry.
|
/// An entity referencing an activity log entry.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public partial class ActivityLog : ISavingChanges
|
public partial class ActivityLog : IHasConcurrencyToken
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="ActivityLog"/> class.
|
/// Initializes a new instance of the <see cref="ActivityLog"/> class.
|
||||||
|
|
|
@ -1,208 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
|
|
||||||
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, Enums.ArtKind kind, Metadata _metadata0, 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, Enums.ArtKind kind, Metadata _metadata0, 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 Enums.ArtKind _Kind;
|
|
||||||
/// <summary>
|
|
||||||
/// When provided in a partial class, allows value of Kind to be changed before setting.
|
|
||||||
/// </summary>
|
|
||||||
partial void SetKind(Enums.ArtKind oldValue, ref Enums.ArtKind newValue);
|
|
||||||
/// <summary>
|
|
||||||
/// When provided in a partial class, allows value of Kind to be changed before returning.
|
|
||||||
/// </summary>
|
|
||||||
partial void GetKind(ref Enums.ArtKind result);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Indexed, Required.
|
|
||||||
/// </summary>
|
|
||||||
[Required]
|
|
||||||
public Enums.ArtKind Kind
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
Enums.ArtKind value = _Kind;
|
|
||||||
GetKind(ref value);
|
|
||||||
return _Kind = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
set
|
|
||||||
{
|
|
||||||
Enums.ArtKind oldValue = _Kind;
|
|
||||||
SetKind(oldValue, ref value);
|
|
||||||
if (oldValue != value)
|
|
||||||
{
|
|
||||||
_Kind = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Required, ConcurrenyToken.
|
|
||||||
/// </summary>
|
|
||||||
[ConcurrencyCheck]
|
|
||||||
[Required]
|
|
||||||
public uint RowVersion { get; set; }
|
|
||||||
|
|
||||||
public void OnSavingChanges()
|
|
||||||
{
|
|
||||||
RowVersion++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* Navigation properties
|
|
||||||
*************************************************************************/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,68 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
|
||||||
|
|
||||||
namespace Jellyfin.Data.Entities
|
|
||||||
{
|
|
||||||
public partial class Book : LibraryItem
|
|
||||||
{
|
|
||||||
partial void Init();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Default constructor. Protected due to required properties, but present because EF needs it.
|
|
||||||
/// </summary>
|
|
||||||
protected Book()
|
|
||||||
{
|
|
||||||
BookMetadata = new HashSet<BookMetadata>();
|
|
||||||
Releases = new HashSet<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 HashSet<BookMetadata>();
|
|
||||||
this.Releases = new HashSet<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
|
|
||||||
*************************************************************************/
|
|
||||||
|
|
||||||
[ForeignKey("BookMetadata_BookMetadata_Id")]
|
|
||||||
public virtual ICollection<BookMetadata> BookMetadata { get; protected set; }
|
|
||||||
|
|
||||||
[ForeignKey("Release_Releases_Id")]
|
|
||||||
public virtual ICollection<Release> Releases { get; protected set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,119 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
|
||||||
|
|
||||||
namespace Jellyfin.Data.Entities
|
|
||||||
{
|
|
||||||
public partial class BookMetadata : Metadata
|
|
||||||
{
|
|
||||||
partial void Init();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Default constructor. Protected due to required properties, but present because EF needs it.
|
|
||||||
/// </summary>
|
|
||||||
protected BookMetadata()
|
|
||||||
{
|
|
||||||
Publishers = new HashSet<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, 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 HashSet<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, 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
|
|
||||||
*************************************************************************/
|
|
||||||
|
|
||||||
[ForeignKey("Company_Publishers_Id")]
|
|
||||||
public virtual ICollection<Company> Publishers { get; protected set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,275 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
|
||||||
|
|
||||||
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, 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, 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]
|
|
||||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
|
||||||
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, ConcurrenyToken.
|
|
||||||
/// </summary>
|
|
||||||
[ConcurrencyCheck]
|
|
||||||
[Required]
|
|
||||||
public uint RowVersion { get; set; }
|
|
||||||
|
|
||||||
public void OnSavingChanges()
|
|
||||||
{
|
|
||||||
RowVersion++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* Navigation properties
|
|
||||||
*************************************************************************/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,121 +0,0 @@
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
|
||||||
|
|
||||||
namespace Jellyfin.Data.Entities
|
|
||||||
{
|
|
||||||
public partial class Collection
|
|
||||||
{
|
|
||||||
partial void Init();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Default constructor.
|
|
||||||
/// </summary>
|
|
||||||
public Collection()
|
|
||||||
{
|
|
||||||
CollectionItem = new LinkedList<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]
|
|
||||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
|
||||||
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, ConcurrenyToken.
|
|
||||||
/// </summary>
|
|
||||||
[ConcurrencyCheck]
|
|
||||||
[Required]
|
|
||||||
public uint RowVersion { get; set; }
|
|
||||||
|
|
||||||
public void OnSavingChanges()
|
|
||||||
{
|
|
||||||
RowVersion++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* Navigation properties
|
|
||||||
*************************************************************************/
|
|
||||||
[ForeignKey("CollectionItem_CollectionItem_Id")]
|
|
||||||
public virtual ICollection<CollectionItem> CollectionItem { get; protected set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,154 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
|
||||||
|
|
||||||
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(Collection _collection0, CollectionItem _collectionitem1, 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(Collection _collection0, CollectionItem _collectionitem1, 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]
|
|
||||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
|
||||||
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, ConcurrenyToken.
|
|
||||||
/// </summary>
|
|
||||||
[ConcurrencyCheck]
|
|
||||||
[Required]
|
|
||||||
public uint RowVersion { get; set; }
|
|
||||||
|
|
||||||
public void OnSavingChanges()
|
|
||||||
{
|
|
||||||
RowVersion++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* Navigation properties
|
|
||||||
*************************************************************************/
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Required.
|
|
||||||
/// </summary>
|
|
||||||
[ForeignKey("LibraryItem_Id")]
|
|
||||||
public virtual LibraryItem LibraryItem { get; set; }
|
|
||||||
|
|
||||||
/// <remarks>
|
|
||||||
/// TODO check if this properly updated dependant and has the proper principal relationship
|
|
||||||
/// </remarks>
|
|
||||||
[ForeignKey("CollectionItem_Next_Id")]
|
|
||||||
public virtual CollectionItem Next { get; set; }
|
|
||||||
|
|
||||||
/// <remarks>
|
|
||||||
/// TODO check if this properly updated dependant and has the proper principal relationship
|
|
||||||
/// </remarks>
|
|
||||||
[ForeignKey("CollectionItem_Previous_Id")]
|
|
||||||
public virtual CollectionItem Previous { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,157 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
|
||||||
|
|
||||||
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 HashSet<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(MovieMetadata _moviemetadata0, SeriesMetadata _seriesmetadata1, MusicAlbumMetadata _musicalbummetadata2, BookMetadata _bookmetadata3, 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 HashSet<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(MovieMetadata _moviemetadata0, SeriesMetadata _seriesmetadata1, MusicAlbumMetadata _musicalbummetadata2, BookMetadata _bookmetadata3, 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]
|
|
||||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
|
||||||
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, ConcurrenyToken.
|
|
||||||
/// </summary>
|
|
||||||
[ConcurrencyCheck]
|
|
||||||
[Required]
|
|
||||||
public uint RowVersion { get; set; }
|
|
||||||
|
|
||||||
public void OnSavingChanges()
|
|
||||||
{
|
|
||||||
RowVersion++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* Navigation properties
|
|
||||||
*************************************************************************/
|
|
||||||
[ForeignKey("CompanyMetadata_CompanyMetadata_Id")]
|
|
||||||
public virtual ICollection<CompanyMetadata> CompanyMetadata { get; protected set; }
|
|
||||||
[ForeignKey("Company_Parent_Id")]
|
|
||||||
public virtual Company Parent { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,230 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
|
|
||||||
namespace Jellyfin.Data.Entities
|
|
||||||
{
|
|
||||||
public partial class CompanyMetadata : Metadata
|
|
||||||
{
|
|
||||||
partial void Init();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Default constructor. Protected due to required properties, but present because EF needs it.
|
|
||||||
/// </summary>
|
|
||||||
protected CompanyMetadata()
|
|
||||||
{
|
|
||||||
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, 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, 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
|
|
||||||
*************************************************************************/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,67 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
|
||||||
|
|
||||||
namespace Jellyfin.Data.Entities
|
|
||||||
{
|
|
||||||
public partial class CustomItem : LibraryItem
|
|
||||||
{
|
|
||||||
partial void Init();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Default constructor. Protected due to required properties, but present because EF needs it.
|
|
||||||
/// </summary>
|
|
||||||
protected CustomItem()
|
|
||||||
{
|
|
||||||
CustomItemMetadata = new HashSet<CustomItemMetadata>();
|
|
||||||
Releases = new HashSet<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 HashSet<CustomItemMetadata>();
|
|
||||||
this.Releases = new HashSet<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
|
|
||||||
*************************************************************************/
|
|
||||||
[ForeignKey("CustomItemMetadata_CustomItemMetadata_Id")]
|
|
||||||
public virtual ICollection<CustomItemMetadata> CustomItemMetadata { get; protected set; }
|
|
||||||
|
|
||||||
[ForeignKey("Release_Releases_Id")]
|
|
||||||
public virtual ICollection<Release> Releases { get; protected set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,77 +0,0 @@
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace Jellyfin.Data.Entities
|
|
||||||
{
|
|
||||||
public partial class CustomItemMetadata : Metadata
|
|
||||||
{
|
|
||||||
partial void Init();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Default constructor. Protected due to required properties, but present because EF needs it.
|
|
||||||
/// </summary>
|
|
||||||
protected CustomItemMetadata()
|
|
||||||
{
|
|
||||||
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, 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, CustomItem _customitem0)
|
|
||||||
{
|
|
||||||
return new CustomItemMetadata(title, language, dateadded, datemodified, _customitem0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* Properties
|
|
||||||
*************************************************************************/
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* Navigation properties
|
|
||||||
*************************************************************************/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,114 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
|
||||||
|
|
||||||
namespace Jellyfin.Data.Entities
|
|
||||||
{
|
|
||||||
public partial class Episode : LibraryItem
|
|
||||||
{
|
|
||||||
partial void Init();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Default constructor. Protected due to required properties, but present because EF needs it.
|
|
||||||
/// </summary>
|
|
||||||
protected Episode()
|
|
||||||
{
|
|
||||||
// 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 HashSet<Release>();
|
|
||||||
EpisodeMetadata = new HashSet<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, 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 HashSet<Release>();
|
|
||||||
this.EpisodeMetadata = new HashSet<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, 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
|
|
||||||
*************************************************************************/
|
|
||||||
[ForeignKey("Release_Releases_Id")]
|
|
||||||
public virtual ICollection<Release> Releases { get; protected set; }
|
|
||||||
[ForeignKey("EpisodeMetadata_EpisodeMetadata_Id")]
|
|
||||||
public virtual ICollection<EpisodeMetadata> EpisodeMetadata { get; protected set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,192 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
|
|
||||||
namespace Jellyfin.Data.Entities
|
|
||||||
{
|
|
||||||
public partial class EpisodeMetadata : Metadata
|
|
||||||
{
|
|
||||||
partial void Init();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Default constructor. Protected due to required properties, but present because EF needs it.
|
|
||||||
/// </summary>
|
|
||||||
protected EpisodeMetadata()
|
|
||||||
{
|
|
||||||
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, 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, 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
|
|
||||||
*************************************************************************/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,160 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
|
||||||
|
|
||||||
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, 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, 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]
|
|
||||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
|
||||||
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, ConcurrenyToken.
|
|
||||||
/// </summary>
|
|
||||||
[ConcurrencyCheck]
|
|
||||||
[Required]
|
|
||||||
public uint RowVersion { get; set; }
|
|
||||||
|
|
||||||
public void OnSavingChanges()
|
|
||||||
{
|
|
||||||
RowVersion++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* Navigation properties
|
|
||||||
*************************************************************************/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,16 +1,19 @@
|
||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Jellyfin.Data.Enums;
|
using Jellyfin.Data.Enums;
|
||||||
|
using Jellyfin.Data.Interfaces;
|
||||||
|
|
||||||
namespace Jellyfin.Data.Entities
|
namespace Jellyfin.Data.Entities
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// An entity representing a group.
|
/// An entity representing a group.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public partial class Group : IHasPermissions, ISavingChanges
|
public partial class Group : IHasPermissions, IHasConcurrencyToken
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="Group"/> class.
|
/// Initializes a new instance of the <see cref="Group"/> class.
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
using System;
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
using System;
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
using Jellyfin.Data.Enums;
|
using Jellyfin.Data.Enums;
|
||||||
|
|
81
Jellyfin.Data/Entities/Libraries/Artwork.cs
Normal file
81
Jellyfin.Data/Entities/Libraries/Artwork.cs
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
using System;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using Jellyfin.Data.Enums;
|
||||||
|
using Jellyfin.Data.Interfaces;
|
||||||
|
|
||||||
|
namespace Jellyfin.Data.Entities.Libraries
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An entity representing artwork.
|
||||||
|
/// </summary>
|
||||||
|
public class Artwork : IHasConcurrencyToken
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="Artwork"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path">The path.</param>
|
||||||
|
/// <param name="kind">The kind of art.</param>
|
||||||
|
/// <param name="owner">The owner.</param>
|
||||||
|
public Artwork(string path, ArtKind kind, IHasArtwork owner)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(path))
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
Path = path;
|
||||||
|
Kind = kind;
|
||||||
|
|
||||||
|
owner?.Artwork.Add(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="Artwork"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Default constructor. Protected due to required properties, but present because EF needs it.
|
||||||
|
/// </remarks>
|
||||||
|
protected Artwork()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the id.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Identity, Indexed, Required.
|
||||||
|
/// </remarks>
|
||||||
|
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||||
|
public int Id { get; protected set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the path.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Required, Max length = 65535.
|
||||||
|
/// </remarks>
|
||||||
|
[Required]
|
||||||
|
[MaxLength(65535)]
|
||||||
|
[StringLength(65535)]
|
||||||
|
public string Path { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the kind of artwork.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Required.
|
||||||
|
/// </remarks>
|
||||||
|
public ArtKind Kind { get; set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
[ConcurrencyCheck]
|
||||||
|
public uint RowVersion { get; set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void OnSavingChanges()
|
||||||
|
{
|
||||||
|
RowVersion++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
28
Jellyfin.Data/Entities/Libraries/Book.cs
Normal file
28
Jellyfin.Data/Entities/Libraries/Book.cs
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Jellyfin.Data.Interfaces;
|
||||||
|
|
||||||
|
namespace Jellyfin.Data.Entities.Libraries
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An entity representing a book.
|
||||||
|
/// </summary>
|
||||||
|
public class Book : LibraryItem, IHasReleases
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="Book"/> class.
|
||||||
|
/// </summary>
|
||||||
|
public Book()
|
||||||
|
{
|
||||||
|
BookMetadata = new HashSet<BookMetadata>();
|
||||||
|
Releases = new HashSet<Release>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a collection containing the metadata for this book.
|
||||||
|
/// </summary>
|
||||||
|
public virtual ICollection<BookMetadata> BookMetadata { get; protected set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public virtual ICollection<Release> Releases { get; protected set; }
|
||||||
|
}
|
||||||
|
}
|
55
Jellyfin.Data/Entities/Libraries/BookMetadata.cs
Normal file
55
Jellyfin.Data/Entities/Libraries/BookMetadata.cs
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using Jellyfin.Data.Interfaces;
|
||||||
|
|
||||||
|
namespace Jellyfin.Data.Entities.Libraries
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An entity containing metadata for a book.
|
||||||
|
/// </summary>
|
||||||
|
public class BookMetadata : Metadata, IHasCompanies
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="BookMetadata"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="title">The title or name of the object.</param>
|
||||||
|
/// <param name="language">ISO-639-3 3-character language codes.</param>
|
||||||
|
/// <param name="book">The book.</param>
|
||||||
|
public BookMetadata(string title, string language, Book book) : base(title, language)
|
||||||
|
{
|
||||||
|
if (book == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(book));
|
||||||
|
}
|
||||||
|
|
||||||
|
book.BookMetadata.Add(this);
|
||||||
|
|
||||||
|
Publishers = new HashSet<Company>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="BookMetadata"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Default constructor. Protected due to required properties, but present because EF needs it.
|
||||||
|
/// </remarks>
|
||||||
|
protected BookMetadata()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the ISBN.
|
||||||
|
/// </summary>
|
||||||
|
public long? Isbn { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a collection of the publishers for this book.
|
||||||
|
/// </summary>
|
||||||
|
public virtual ICollection<Company> Publishers { get; protected set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
[NotMapped]
|
||||||
|
public ICollection<Company> Companies => Publishers;
|
||||||
|
}
|
||||||
|
}
|
102
Jellyfin.Data/Entities/Libraries/Chapter.cs
Normal file
102
Jellyfin.Data/Entities/Libraries/Chapter.cs
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
using System;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using Jellyfin.Data.Interfaces;
|
||||||
|
|
||||||
|
namespace Jellyfin.Data.Entities.Libraries
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An entity representing a chapter.
|
||||||
|
/// </summary>
|
||||||
|
public class Chapter : IHasConcurrencyToken
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="Chapter"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="language">ISO-639-3 3-character language codes.</param>
|
||||||
|
/// <param name="startTime">The start time for this chapter.</param>
|
||||||
|
/// <param name="release">The release.</param>
|
||||||
|
public Chapter(string language, long startTime, Release release)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(language))
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(language));
|
||||||
|
}
|
||||||
|
|
||||||
|
Language = language;
|
||||||
|
StartTime = startTime;
|
||||||
|
|
||||||
|
if (release == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(release));
|
||||||
|
}
|
||||||
|
|
||||||
|
release.Chapters.Add(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="Chapter"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Default constructor. Protected due to required properties, but present because EF needs it.
|
||||||
|
/// </remarks>
|
||||||
|
protected Chapter()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the id.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Identity, Indexed, Required.
|
||||||
|
/// </remarks>
|
||||||
|
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||||
|
public int Id { get; protected set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the name.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Max length = 1024.
|
||||||
|
/// </remarks>
|
||||||
|
[MaxLength(1024)]
|
||||||
|
[StringLength(1024)]
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the language.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Required, Min length = 3, Max length = 3
|
||||||
|
/// ISO-639-3 3-character language codes.
|
||||||
|
/// </remarks>
|
||||||
|
[Required]
|
||||||
|
[MinLength(3)]
|
||||||
|
[MaxLength(3)]
|
||||||
|
[StringLength(3)]
|
||||||
|
public string Language { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the start time.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Required.
|
||||||
|
/// </remarks>
|
||||||
|
public long StartTime { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the end time.
|
||||||
|
/// </summary>
|
||||||
|
public long? EndTime { get; set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
[ConcurrencyCheck]
|
||||||
|
public uint RowVersion { get; protected set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void OnSavingChanges()
|
||||||
|
{
|
||||||
|
RowVersion++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
55
Jellyfin.Data/Entities/Libraries/Collection.cs
Normal file
55
Jellyfin.Data/Entities/Libraries/Collection.cs
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using Jellyfin.Data.Interfaces;
|
||||||
|
|
||||||
|
namespace Jellyfin.Data.Entities.Libraries
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An entity representing a collection.
|
||||||
|
/// </summary>
|
||||||
|
public class Collection : IHasConcurrencyToken
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="Collection"/> class.
|
||||||
|
/// </summary>
|
||||||
|
public Collection()
|
||||||
|
{
|
||||||
|
Items = new HashSet<CollectionItem>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the id.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Identity, Indexed, Required.
|
||||||
|
/// </remarks>
|
||||||
|
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||||
|
public int Id { get; protected set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the name.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Max length = 1024.
|
||||||
|
/// </remarks>
|
||||||
|
[MaxLength(1024)]
|
||||||
|
[StringLength(1024)]
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
[ConcurrencyCheck]
|
||||||
|
public uint RowVersion { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a collection containing this collection's items.
|
||||||
|
/// </summary>
|
||||||
|
public virtual ICollection<CollectionItem> Items { get; protected set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void OnSavingChanges()
|
||||||
|
{
|
||||||
|
RowVersion++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
94
Jellyfin.Data/Entities/Libraries/CollectionItem.cs
Normal file
94
Jellyfin.Data/Entities/Libraries/CollectionItem.cs
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
using System;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using Jellyfin.Data.Interfaces;
|
||||||
|
|
||||||
|
namespace Jellyfin.Data.Entities.Libraries
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An entity representing a collection item.
|
||||||
|
/// </summary>
|
||||||
|
public class CollectionItem : IHasConcurrencyToken
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="CollectionItem"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="collection">The collection.</param>
|
||||||
|
/// <param name="previous">The previous item.</param>
|
||||||
|
/// <param name="next">The next item.</param>
|
||||||
|
public CollectionItem(Collection collection, CollectionItem previous, CollectionItem next)
|
||||||
|
{
|
||||||
|
if (collection == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(collection));
|
||||||
|
}
|
||||||
|
|
||||||
|
collection.Items.Add(this);
|
||||||
|
|
||||||
|
if (next != null)
|
||||||
|
{
|
||||||
|
Next = next;
|
||||||
|
next.Previous = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (previous != null)
|
||||||
|
{
|
||||||
|
Previous = previous;
|
||||||
|
previous.Next = this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="CollectionItem"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Default constructor. Protected due to required properties, but present because EF needs it.
|
||||||
|
/// </remarks>
|
||||||
|
protected CollectionItem()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the id.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Identity, Indexed, Required.
|
||||||
|
/// </remarks>
|
||||||
|
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
[ConcurrencyCheck]
|
||||||
|
public uint RowVersion { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the library item.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Required.
|
||||||
|
/// </remarks>
|
||||||
|
public virtual LibraryItem LibraryItem { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the next item in the collection.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// TODO check if this properly updated dependant and has the proper principal relationship
|
||||||
|
/// </remarks>
|
||||||
|
public virtual CollectionItem Next { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the previous item in the collection.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// TODO check if this properly updated dependant and has the proper principal relationship
|
||||||
|
/// </remarks>
|
||||||
|
public virtual CollectionItem Previous { get; set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void OnSavingChanges()
|
||||||
|
{
|
||||||
|
RowVersion++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
67
Jellyfin.Data/Entities/Libraries/Company.cs
Normal file
67
Jellyfin.Data/Entities/Libraries/Company.cs
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using Jellyfin.Data.Interfaces;
|
||||||
|
|
||||||
|
namespace Jellyfin.Data.Entities.Libraries
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An entity representing a company.
|
||||||
|
/// </summary>
|
||||||
|
public class Company : IHasCompanies, IHasConcurrencyToken
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="Company"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="owner">The owner of this company.</param>
|
||||||
|
public Company(IHasCompanies owner)
|
||||||
|
{
|
||||||
|
owner?.Companies.Add(this);
|
||||||
|
|
||||||
|
CompanyMetadata = new HashSet<CompanyMetadata>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="Company"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Default constructor. Protected due to required properties, but present because EF needs it.
|
||||||
|
/// </remarks>
|
||||||
|
protected Company()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the id.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Identity, Indexed, Required.
|
||||||
|
/// </remarks>
|
||||||
|
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||||
|
public int Id { get; protected set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
[ConcurrencyCheck]
|
||||||
|
public uint RowVersion { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a collection containing the metadata.
|
||||||
|
/// </summary>
|
||||||
|
public virtual ICollection<CompanyMetadata> CompanyMetadata { get; protected set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a collection containing this company's child companies.
|
||||||
|
/// </summary>
|
||||||
|
public virtual ICollection<Company> ChildCompanies { get; protected set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
[NotMapped]
|
||||||
|
public ICollection<Company> Companies => ChildCompanies;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void OnSavingChanges()
|
||||||
|
{
|
||||||
|
RowVersion++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
74
Jellyfin.Data/Entities/Libraries/CompanyMetadata.cs
Normal file
74
Jellyfin.Data/Entities/Libraries/CompanyMetadata.cs
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
using System;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace Jellyfin.Data.Entities.Libraries
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An entity holding metadata for a <see cref="Company"/>.
|
||||||
|
/// </summary>
|
||||||
|
public class CompanyMetadata : Metadata
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="CompanyMetadata"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="title">The title or name of the object.</param>
|
||||||
|
/// <param name="language">ISO-639-3 3-character language codes.</param>
|
||||||
|
/// <param name="company">The company.</param>
|
||||||
|
public CompanyMetadata(string title, string language, Company company) : base(title, language)
|
||||||
|
{
|
||||||
|
if (company == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(company));
|
||||||
|
}
|
||||||
|
|
||||||
|
company.CompanyMetadata.Add(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="CompanyMetadata"/> class.
|
||||||
|
/// </summary>
|
||||||
|
protected CompanyMetadata()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the description.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Max length = 65535.
|
||||||
|
/// </remarks>
|
||||||
|
[MaxLength(65535)]
|
||||||
|
[StringLength(65535)]
|
||||||
|
public string Description { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the headquarters.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Max length = 255.
|
||||||
|
/// </remarks>
|
||||||
|
[MaxLength(255)]
|
||||||
|
[StringLength(255)]
|
||||||
|
public string Headquarters { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the country code.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Max length = 2.
|
||||||
|
/// </remarks>
|
||||||
|
[MaxLength(2)]
|
||||||
|
[StringLength(2)]
|
||||||
|
public string Country { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the homepage.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Max length = 1024.
|
||||||
|
/// </remarks>
|
||||||
|
[MaxLength(1024)]
|
||||||
|
[StringLength(1024)]
|
||||||
|
public string Homepage { get; set; }
|
||||||
|
}
|
||||||
|
}
|
28
Jellyfin.Data/Entities/Libraries/CustomItem.cs
Normal file
28
Jellyfin.Data/Entities/Libraries/CustomItem.cs
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Jellyfin.Data.Interfaces;
|
||||||
|
|
||||||
|
namespace Jellyfin.Data.Entities.Libraries
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An entity representing a custom item.
|
||||||
|
/// </summary>
|
||||||
|
public class CustomItem : LibraryItem, IHasReleases
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="CustomItem"/> class.
|
||||||
|
/// </summary>
|
||||||
|
public CustomItem()
|
||||||
|
{
|
||||||
|
CustomItemMetadata = new HashSet<CustomItemMetadata>();
|
||||||
|
Releases = new HashSet<Release>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a collection containing the metadata for this item.
|
||||||
|
/// </summary>
|
||||||
|
public virtual ICollection<CustomItemMetadata> CustomItemMetadata { get; protected set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public virtual ICollection<Release> Releases { get; protected set; }
|
||||||
|
}
|
||||||
|
}
|
36
Jellyfin.Data/Entities/Libraries/CustomItemMetadata.cs
Normal file
36
Jellyfin.Data/Entities/Libraries/CustomItemMetadata.cs
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Jellyfin.Data.Entities.Libraries
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An entity containing metadata for a custom item.
|
||||||
|
/// </summary>
|
||||||
|
public class CustomItemMetadata : Metadata
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="CustomItemMetadata"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="title">The title or name of the object.</param>
|
||||||
|
/// <param name="language">ISO-639-3 3-character language codes.</param>
|
||||||
|
/// <param name="item">The item.</param>
|
||||||
|
public CustomItemMetadata(string title, string language, CustomItem item) : base(title, language)
|
||||||
|
{
|
||||||
|
if (item == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(item));
|
||||||
|
}
|
||||||
|
|
||||||
|
item.CustomItemMetadata.Add(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="CustomItemMetadata"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Default constructor. Protected due to required properties, but present because EF needs it.
|
||||||
|
/// </remarks>
|
||||||
|
protected CustomItemMetadata()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
52
Jellyfin.Data/Entities/Libraries/Episode.cs
Normal file
52
Jellyfin.Data/Entities/Libraries/Episode.cs
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Jellyfin.Data.Interfaces;
|
||||||
|
|
||||||
|
namespace Jellyfin.Data.Entities.Libraries
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An entity representing an episode.
|
||||||
|
/// </summary>
|
||||||
|
public class Episode : LibraryItem, IHasReleases
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="Episode"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="season">The season.</param>
|
||||||
|
public Episode(Season season)
|
||||||
|
{
|
||||||
|
if (season == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(season));
|
||||||
|
}
|
||||||
|
|
||||||
|
season.Episodes.Add(this);
|
||||||
|
|
||||||
|
Releases = new HashSet<Release>();
|
||||||
|
EpisodeMetadata = new HashSet<EpisodeMetadata>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="Episode"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Default constructor. Protected due to required properties, but present because EF needs it.
|
||||||
|
/// </remarks>
|
||||||
|
protected Episode()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the episode number.
|
||||||
|
/// </summary>
|
||||||
|
public int? EpisodeNumber { get; set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public virtual ICollection<Release> Releases { get; protected set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a collection containing the metadata for this episode.
|
||||||
|
/// </summary>
|
||||||
|
public virtual ICollection<EpisodeMetadata> EpisodeMetadata { get; protected set; }
|
||||||
|
}
|
||||||
|
}
|
67
Jellyfin.Data/Entities/Libraries/EpisodeMetadata.cs
Normal file
67
Jellyfin.Data/Entities/Libraries/EpisodeMetadata.cs
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
using System;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace Jellyfin.Data.Entities.Libraries
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An entity containing metadata for an <see cref="Episode"/>.
|
||||||
|
/// </summary>
|
||||||
|
public class EpisodeMetadata : Metadata
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="EpisodeMetadata"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="title">The title or name of the object.</param>
|
||||||
|
/// <param name="language">ISO-639-3 3-character language codes.</param>
|
||||||
|
/// <param name="episode">The episode.</param>
|
||||||
|
public EpisodeMetadata(string title, string language, Episode episode) : base(title, language)
|
||||||
|
{
|
||||||
|
if (episode == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(episode));
|
||||||
|
}
|
||||||
|
|
||||||
|
episode.EpisodeMetadata.Add(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="EpisodeMetadata"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Default constructor. Protected due to required properties, but present because EF needs it.
|
||||||
|
/// </remarks>
|
||||||
|
protected EpisodeMetadata()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the outline.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Max length = 1024.
|
||||||
|
/// </remarks>
|
||||||
|
[MaxLength(1024)]
|
||||||
|
[StringLength(1024)]
|
||||||
|
public string Outline { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the plot.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Max length = 65535.
|
||||||
|
/// </remarks>
|
||||||
|
[MaxLength(65535)]
|
||||||
|
[StringLength(65535)]
|
||||||
|
public string Plot { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the tagline.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Max length = 1024.
|
||||||
|
/// </remarks>
|
||||||
|
[MaxLength(1024)]
|
||||||
|
[StringLength(1024)]
|
||||||
|
public string Tagline { get; set; }
|
||||||
|
}
|
||||||
|
}
|
75
Jellyfin.Data/Entities/Libraries/Genre.cs
Normal file
75
Jellyfin.Data/Entities/Libraries/Genre.cs
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
using System;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using Jellyfin.Data.Interfaces;
|
||||||
|
|
||||||
|
namespace Jellyfin.Data.Entities.Libraries
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An entity representing a genre.
|
||||||
|
/// </summary>
|
||||||
|
public class Genre : IHasConcurrencyToken
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="Genre"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name">The name.</param>
|
||||||
|
/// <param name="metadata">The metadata.</param>
|
||||||
|
public Genre(string name, Metadata metadata)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(name))
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
Name = name;
|
||||||
|
|
||||||
|
if (metadata == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(metadata));
|
||||||
|
}
|
||||||
|
|
||||||
|
metadata.Genres.Add(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="Genre"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Default constructor. Protected due to required properties, but present because EF needs it.
|
||||||
|
/// </remarks>
|
||||||
|
protected Genre()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the id.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Identity, Indexed, Required.
|
||||||
|
/// </remarks>
|
||||||
|
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||||
|
public int Id { get; protected set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the name.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Indexed, Required, Max length = 255.
|
||||||
|
/// </remarks>
|
||||||
|
[Required]
|
||||||
|
[MaxLength(255)]
|
||||||
|
[StringLength(255)]
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
[ConcurrencyCheck]
|
||||||
|
public uint RowVersion { get; protected set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void OnSavingChanges()
|
||||||
|
{
|
||||||
|
RowVersion++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
76
Jellyfin.Data/Entities/Libraries/Library.cs
Normal file
76
Jellyfin.Data/Entities/Libraries/Library.cs
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
using System;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using Jellyfin.Data.Interfaces;
|
||||||
|
|
||||||
|
namespace Jellyfin.Data.Entities.Libraries
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An entity representing a library.
|
||||||
|
/// </summary>
|
||||||
|
public class Library : IHasConcurrencyToken
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="Library"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name">The name of the library.</param>
|
||||||
|
public Library(string name)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(name))
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
Name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="Library"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Default constructor. Protected due to required properties, but present because EF needs it.
|
||||||
|
/// </remarks>
|
||||||
|
protected Library()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the id.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Identity, Indexed, Required.
|
||||||
|
/// </remarks>
|
||||||
|
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||||
|
public int Id { get; protected set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the name.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Required, Max length = 128.
|
||||||
|
/// </remarks>
|
||||||
|
[Required]
|
||||||
|
[MaxLength(128)]
|
||||||
|
[StringLength(128)]
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the root path of the library.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Required.
|
||||||
|
/// </remarks>
|
||||||
|
[Required]
|
||||||
|
public string Path { get; set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
[ConcurrencyCheck]
|
||||||
|
public uint RowVersion { get; set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void OnSavingChanges()
|
||||||
|
{
|
||||||
|
RowVersion++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
63
Jellyfin.Data/Entities/Libraries/LibraryItem.cs
Normal file
63
Jellyfin.Data/Entities/Libraries/LibraryItem.cs
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
using System;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using Jellyfin.Data.Interfaces;
|
||||||
|
|
||||||
|
namespace Jellyfin.Data.Entities.Libraries
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An entity representing a library item.
|
||||||
|
/// </summary>
|
||||||
|
public abstract class LibraryItem : IHasConcurrencyToken
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="LibraryItem"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="library">The library of this item.</param>
|
||||||
|
protected LibraryItem(Library library)
|
||||||
|
{
|
||||||
|
DateAdded = DateTime.UtcNow;
|
||||||
|
Library = library;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="LibraryItem"/> class.
|
||||||
|
/// </summary>
|
||||||
|
protected LibraryItem()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the id.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Identity, Indexed, Required.
|
||||||
|
/// </remarks>
|
||||||
|
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||||
|
public int Id { get; protected set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the date this library item was added.
|
||||||
|
/// </summary>
|
||||||
|
public DateTime DateAdded { get; protected set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
[ConcurrencyCheck]
|
||||||
|
public uint RowVersion { get; protected set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the library of this item.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Required.
|
||||||
|
/// </remarks>
|
||||||
|
[Required]
|
||||||
|
public virtual Library Library { get; set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void OnSavingChanges()
|
||||||
|
{
|
||||||
|
RowVersion++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
94
Jellyfin.Data/Entities/Libraries/MediaFile.cs
Normal file
94
Jellyfin.Data/Entities/Libraries/MediaFile.cs
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using Jellyfin.Data.Enums;
|
||||||
|
using Jellyfin.Data.Interfaces;
|
||||||
|
|
||||||
|
namespace Jellyfin.Data.Entities.Libraries
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An entity representing a file on disk.
|
||||||
|
/// </summary>
|
||||||
|
public class MediaFile : IHasConcurrencyToken
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MediaFile"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path">The path relative to the LibraryRoot.</param>
|
||||||
|
/// <param name="kind">The file kind.</param>
|
||||||
|
/// <param name="release">The release.</param>
|
||||||
|
public MediaFile(string path, MediaFileKind kind, Release release)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(path))
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
Path = path;
|
||||||
|
Kind = kind;
|
||||||
|
|
||||||
|
if (release == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(release));
|
||||||
|
}
|
||||||
|
|
||||||
|
release.MediaFiles.Add(this);
|
||||||
|
|
||||||
|
MediaFileStreams = new HashSet<MediaFileStream>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MediaFile"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Default constructor. Protected due to required properties, but present because EF needs it.
|
||||||
|
/// </remarks>
|
||||||
|
protected MediaFile()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the id.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Identity, Indexed, Required.
|
||||||
|
/// </remarks>
|
||||||
|
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||||
|
public int Id { get; protected set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the path relative to the library root.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Required, Max length = 65535.
|
||||||
|
/// </remarks>
|
||||||
|
[Required]
|
||||||
|
[MaxLength(65535)]
|
||||||
|
[StringLength(65535)]
|
||||||
|
public string Path { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the kind of media file.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Required.
|
||||||
|
/// </remarks>
|
||||||
|
public MediaFileKind Kind { get; set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
[ConcurrencyCheck]
|
||||||
|
public uint RowVersion { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a collection containing the streams in this file.
|
||||||
|
/// </summary>
|
||||||
|
public virtual ICollection<MediaFileStream> MediaFileStreams { get; protected set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void OnSavingChanges()
|
||||||
|
{
|
||||||
|
RowVersion++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
67
Jellyfin.Data/Entities/Libraries/MediaFileStream.cs
Normal file
67
Jellyfin.Data/Entities/Libraries/MediaFileStream.cs
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
using System;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using Jellyfin.Data.Interfaces;
|
||||||
|
|
||||||
|
namespace Jellyfin.Data.Entities.Libraries
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An entity representing a stream in a media file.
|
||||||
|
/// </summary>
|
||||||
|
public class MediaFileStream : IHasConcurrencyToken
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MediaFileStream"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="streamNumber">The number of this stream.</param>
|
||||||
|
/// <param name="mediaFile">The media file.</param>
|
||||||
|
public MediaFileStream(int streamNumber, MediaFile mediaFile)
|
||||||
|
{
|
||||||
|
StreamNumber = streamNumber;
|
||||||
|
|
||||||
|
if (mediaFile == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(mediaFile));
|
||||||
|
}
|
||||||
|
|
||||||
|
mediaFile.MediaFileStreams.Add(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MediaFileStream"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Default constructor. Protected due to required properties, but present because EF needs it.
|
||||||
|
/// </remarks>
|
||||||
|
protected MediaFileStream()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the id.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Identity, Indexed, Required.
|
||||||
|
/// </remarks>
|
||||||
|
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||||
|
public int Id { get; protected set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the stream number.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Required.
|
||||||
|
/// </remarks>
|
||||||
|
public int StreamNumber { get; set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
[ConcurrencyCheck]
|
||||||
|
public uint RowVersion { get; set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void OnSavingChanges()
|
||||||
|
{
|
||||||
|
RowVersion++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
165
Jellyfin.Data/Entities/Libraries/Metadata.cs
Normal file
165
Jellyfin.Data/Entities/Libraries/Metadata.cs
Normal file
|
@ -0,0 +1,165 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using Jellyfin.Data.Interfaces;
|
||||||
|
|
||||||
|
namespace Jellyfin.Data.Entities.Libraries
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An abstract class that holds metadata.
|
||||||
|
/// </summary>
|
||||||
|
public abstract class Metadata : IHasArtwork, IHasConcurrencyToken
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="Metadata"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="title">The title or name of the object.</param>
|
||||||
|
/// <param name="language">ISO-639-3 3-character language codes.</param>
|
||||||
|
protected Metadata(string title, string language)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(title))
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(title));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(language))
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(language));
|
||||||
|
}
|
||||||
|
|
||||||
|
Title = title;
|
||||||
|
Language = language;
|
||||||
|
DateAdded = DateTime.UtcNow;
|
||||||
|
DateModified = DateAdded;
|
||||||
|
|
||||||
|
PersonRoles = new HashSet<PersonRole>();
|
||||||
|
Genres = new HashSet<Genre>();
|
||||||
|
Artwork = new HashSet<Artwork>();
|
||||||
|
Ratings = new HashSet<Rating>();
|
||||||
|
Sources = new HashSet<MetadataProviderId>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="Metadata"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Default constructor. Protected due to being abstract.
|
||||||
|
/// </remarks>
|
||||||
|
protected Metadata()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the id.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Identity, Indexed, Required.
|
||||||
|
/// </remarks>
|
||||||
|
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||||
|
public int Id { get; protected set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the title.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Required, Max length = 1024.
|
||||||
|
/// </remarks>
|
||||||
|
[Required]
|
||||||
|
[MaxLength(1024)]
|
||||||
|
[StringLength(1024)]
|
||||||
|
public string Title { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the original title.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Max length = 1024.
|
||||||
|
/// </remarks>
|
||||||
|
[MaxLength(1024)]
|
||||||
|
[StringLength(1024)]
|
||||||
|
public string OriginalTitle { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the sort title.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Max length = 1024.
|
||||||
|
/// </remarks>
|
||||||
|
[MaxLength(1024)]
|
||||||
|
[StringLength(1024)]
|
||||||
|
public string SortTitle { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the language.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Required, Min length = 3, Max length = 3.
|
||||||
|
/// ISO-639-3 3-character language codes.
|
||||||
|
/// </remarks>
|
||||||
|
[Required]
|
||||||
|
[MinLength(3)]
|
||||||
|
[MaxLength(3)]
|
||||||
|
[StringLength(3)]
|
||||||
|
public string Language { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the release date.
|
||||||
|
/// </summary>
|
||||||
|
public DateTimeOffset? ReleaseDate { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the date added.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Required.
|
||||||
|
/// </remarks>
|
||||||
|
public DateTime DateAdded { get; protected set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the date modified.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Required.
|
||||||
|
/// </remarks>
|
||||||
|
public DateTime DateModified { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the row version.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Required, ConcurrencyToken.
|
||||||
|
/// </remarks>
|
||||||
|
[ConcurrencyCheck]
|
||||||
|
public uint RowVersion { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a collection containing the person roles for this item.
|
||||||
|
/// </summary>
|
||||||
|
public virtual ICollection<PersonRole> PersonRoles { get; protected set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a collection containing the generes for this item.
|
||||||
|
/// </summary>
|
||||||
|
public virtual ICollection<Genre> Genres { get; protected set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public virtual ICollection<Artwork> Artwork { get; protected set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a collection containing the ratings for this item.
|
||||||
|
/// </summary>
|
||||||
|
public virtual ICollection<Rating> Ratings { get; protected set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a collection containing the metadata sources for this item.
|
||||||
|
/// </summary>
|
||||||
|
public virtual ICollection<MetadataProviderId> Sources { get; protected set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void OnSavingChanges()
|
||||||
|
{
|
||||||
|
RowVersion++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
67
Jellyfin.Data/Entities/Libraries/MetadataProvider.cs
Normal file
67
Jellyfin.Data/Entities/Libraries/MetadataProvider.cs
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
using System;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using Jellyfin.Data.Interfaces;
|
||||||
|
|
||||||
|
namespace Jellyfin.Data.Entities.Libraries
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An entity representing a metadata provider.
|
||||||
|
/// </summary>
|
||||||
|
public class MetadataProvider : IHasConcurrencyToken
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MetadataProvider"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name">The name of the metadata provider.</param>
|
||||||
|
public MetadataProvider(string name)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(name))
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
Name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MetadataProvider"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Default constructor. Protected due to required properties, but present because EF needs it.
|
||||||
|
/// </remarks>
|
||||||
|
protected MetadataProvider()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the id.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Identity, Indexed, Required.
|
||||||
|
/// </remarks>
|
||||||
|
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||||
|
public int Id { get; protected set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the name.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Required, Max length = 1024.
|
||||||
|
/// </remarks>
|
||||||
|
[Required]
|
||||||
|
[MaxLength(1024)]
|
||||||
|
[StringLength(1024)]
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
[ConcurrencyCheck]
|
||||||
|
public uint RowVersion { get; set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void OnSavingChanges()
|
||||||
|
{
|
||||||
|
RowVersion++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
83
Jellyfin.Data/Entities/Libraries/MetadataProviderId.cs
Normal file
83
Jellyfin.Data/Entities/Libraries/MetadataProviderId.cs
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
using System;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using Jellyfin.Data.Interfaces;
|
||||||
|
|
||||||
|
namespace Jellyfin.Data.Entities.Libraries
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An entity representing a unique identifier for a metadata provider.
|
||||||
|
/// </summary>
|
||||||
|
public class MetadataProviderId : IHasConcurrencyToken
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MetadataProviderId"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="providerId">The provider id.</param>
|
||||||
|
/// <param name="metadata">The metadata entity.</param>
|
||||||
|
public MetadataProviderId(string providerId, Metadata metadata)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(providerId))
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(providerId));
|
||||||
|
}
|
||||||
|
|
||||||
|
ProviderId = providerId;
|
||||||
|
|
||||||
|
if (metadata == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(metadata));
|
||||||
|
}
|
||||||
|
|
||||||
|
metadata.Sources.Add(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MetadataProviderId"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Default constructor. Protected due to required properties, but present because EF needs it.
|
||||||
|
/// </remarks>
|
||||||
|
protected MetadataProviderId()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the id.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Identity, Indexed, Required.
|
||||||
|
/// </remarks>
|
||||||
|
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||||
|
public int Id { get; protected set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the provider id.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Required, Max length = 255.
|
||||||
|
/// </remarks>
|
||||||
|
[Required]
|
||||||
|
[MaxLength(255)]
|
||||||
|
[StringLength(255)]
|
||||||
|
public string ProviderId { get; set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
[ConcurrencyCheck]
|
||||||
|
public uint RowVersion { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the metadata provider.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Required.
|
||||||
|
/// </remarks>
|
||||||
|
public virtual MetadataProvider MetadataProvider { get; set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void OnSavingChanges()
|
||||||
|
{
|
||||||
|
RowVersion++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
28
Jellyfin.Data/Entities/Libraries/Movie.cs
Normal file
28
Jellyfin.Data/Entities/Libraries/Movie.cs
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Jellyfin.Data.Interfaces;
|
||||||
|
|
||||||
|
namespace Jellyfin.Data.Entities.Libraries
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An entity representing a movie.
|
||||||
|
/// </summary>
|
||||||
|
public class Movie : LibraryItem, IHasReleases
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="Movie"/> class.
|
||||||
|
/// </summary>
|
||||||
|
public Movie()
|
||||||
|
{
|
||||||
|
Releases = new HashSet<Release>();
|
||||||
|
MovieMetadata = new HashSet<MovieMetadata>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public virtual ICollection<Release> Releases { get; protected set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a collection containing the metadata for this movie.
|
||||||
|
/// </summary>
|
||||||
|
public virtual ICollection<MovieMetadata> MovieMetadata { get; protected set; }
|
||||||
|
}
|
||||||
|
}
|
85
Jellyfin.Data/Entities/Libraries/MovieMetadata.cs
Normal file
85
Jellyfin.Data/Entities/Libraries/MovieMetadata.cs
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using Jellyfin.Data.Interfaces;
|
||||||
|
|
||||||
|
namespace Jellyfin.Data.Entities.Libraries
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An entity holding the metadata for a movie.
|
||||||
|
/// </summary>
|
||||||
|
public class MovieMetadata : Metadata, IHasCompanies
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MovieMetadata"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="title">The title or name of the movie.</param>
|
||||||
|
/// <param name="language">ISO-639-3 3-character language codes.</param>
|
||||||
|
/// <param name="movie">The movie.</param>
|
||||||
|
public MovieMetadata(string title, string language, Movie movie) : base(title, language)
|
||||||
|
{
|
||||||
|
Studios = new HashSet<Company>();
|
||||||
|
|
||||||
|
movie.MovieMetadata.Add(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MovieMetadata"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Default constructor. Protected due to required properties, but present because EF needs it.
|
||||||
|
/// </remarks>
|
||||||
|
protected MovieMetadata()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the outline.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Max length = 1024.
|
||||||
|
/// </remarks>
|
||||||
|
[MaxLength(1024)]
|
||||||
|
[StringLength(1024)]
|
||||||
|
public string Outline { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the tagline.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Max length = 1024.
|
||||||
|
/// </remarks>
|
||||||
|
[MaxLength(1024)]
|
||||||
|
[StringLength(1024)]
|
||||||
|
public string Tagline { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the plot.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Max length = 65535.
|
||||||
|
/// </remarks>
|
||||||
|
[MaxLength(65535)]
|
||||||
|
[StringLength(65535)]
|
||||||
|
public string Plot { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the country code.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Max length = 2.
|
||||||
|
/// </remarks>
|
||||||
|
[MaxLength(2)]
|
||||||
|
[StringLength(2)]
|
||||||
|
public string Country { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the studios that produced this movie.
|
||||||
|
/// </summary>
|
||||||
|
public virtual ICollection<Company> Studios { get; protected set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
[NotMapped]
|
||||||
|
public ICollection<Company> Companies => Studios;
|
||||||
|
}
|
||||||
|
}
|
29
Jellyfin.Data/Entities/Libraries/MusicAlbum.cs
Normal file
29
Jellyfin.Data/Entities/Libraries/MusicAlbum.cs
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Jellyfin.Data.Entities.Libraries
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An entity representing a music album.
|
||||||
|
/// </summary>
|
||||||
|
public class MusicAlbum : LibraryItem
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MusicAlbum"/> class.
|
||||||
|
/// </summary>
|
||||||
|
public MusicAlbum()
|
||||||
|
{
|
||||||
|
MusicAlbumMetadata = new HashSet<MusicAlbumMetadata>();
|
||||||
|
Tracks = new HashSet<Track>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a collection containing the album metadata.
|
||||||
|
/// </summary>
|
||||||
|
public virtual ICollection<MusicAlbumMetadata> MusicAlbumMetadata { get; protected set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a collection containing the tracks.
|
||||||
|
/// </summary>
|
||||||
|
public virtual ICollection<Track> Tracks { get; protected set; }
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user