Merge pull request #3910 from barronpm/event-rewrite-1
Event Rewrite (Part 1)
This commit is contained in:
commit
cf6ef9958d
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,19 +1,13 @@
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace MediaBrowser.Model.Events
|
namespace Jellyfin.Data.Events
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Provides a generic EventArgs subclass that can hold any kind of object.
|
/// Provides a generic EventArgs subclass that can hold any kind of object.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T"></typeparam>
|
/// <typeparam name="T">The type of this event.</typeparam>
|
||||||
public class GenericEventArgs<T> : EventArgs
|
public class GenericEventArgs<T> : EventArgs
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the argument.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The argument.</value>
|
|
||||||
public T Argument { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="GenericEventArgs{T}"/> class.
|
/// Initializes a new instance of the <see cref="GenericEventArgs{T}"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -22,5 +16,11 @@ namespace MediaBrowser.Model.Events
|
||||||
{
|
{
|
||||||
Argument = arg;
|
Argument = arg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the argument.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The argument.</value>
|
||||||
|
public T Argument { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
11
Jellyfin.Data/Events/System/PendingRestartEventArgs.cs
Normal file
11
Jellyfin.Data/Events/System/PendingRestartEventArgs.cs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Jellyfin.Data.Events.System
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An event that occurs when there is a pending restart.
|
||||||
|
/// </summary>
|
||||||
|
public class PendingRestartEventArgs : EventArgs
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
18
Jellyfin.Data/Events/Users/UserCreatedEventArgs.cs
Normal file
18
Jellyfin.Data/Events/Users/UserCreatedEventArgs.cs
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
using Jellyfin.Data.Entities;
|
||||||
|
|
||||||
|
namespace Jellyfin.Data.Events.Users
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An event that occurs when a user is created.
|
||||||
|
/// </summary>
|
||||||
|
public class UserCreatedEventArgs : GenericEventArgs<User>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="UserCreatedEventArgs"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="arg">The user.</param>
|
||||||
|
public UserCreatedEventArgs(User arg) : base(arg)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
18
Jellyfin.Data/Events/Users/UserDeletedEventArgs.cs
Normal file
18
Jellyfin.Data/Events/Users/UserDeletedEventArgs.cs
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
using Jellyfin.Data.Entities;
|
||||||
|
|
||||||
|
namespace Jellyfin.Data.Events.Users
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An event that occurs when a user is deleted.
|
||||||
|
/// </summary>
|
||||||
|
public class UserDeletedEventArgs : GenericEventArgs<User>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="UserDeletedEventArgs"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="arg">The user.</param>
|
||||||
|
public UserDeletedEventArgs(User arg) : base(arg)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
18
Jellyfin.Data/Events/Users/UserLockedOutEventArgs.cs
Normal file
18
Jellyfin.Data/Events/Users/UserLockedOutEventArgs.cs
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
using Jellyfin.Data.Entities;
|
||||||
|
|
||||||
|
namespace Jellyfin.Data.Events.Users
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An event that occurs when a user is locked out.
|
||||||
|
/// </summary>
|
||||||
|
public class UserLockedOutEventArgs : GenericEventArgs<User>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="UserLockedOutEventArgs"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="arg">The user.</param>
|
||||||
|
public UserLockedOutEventArgs(User arg) : base(arg)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
18
Jellyfin.Data/Events/Users/UserPasswordChangedEventArgs.cs
Normal file
18
Jellyfin.Data/Events/Users/UserPasswordChangedEventArgs.cs
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
using Jellyfin.Data.Entities;
|
||||||
|
|
||||||
|
namespace Jellyfin.Data.Events.Users
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An event that occurs when a user's password has changed.
|
||||||
|
/// </summary>
|
||||||
|
public class UserPasswordChangedEventArgs : GenericEventArgs<User>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="UserPasswordChangedEventArgs"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="arg">The user.</param>
|
||||||
|
public UserPasswordChangedEventArgs(User arg) : base(arg)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
18
Jellyfin.Data/Events/Users/UserUpdatedEventArgs.cs
Normal file
18
Jellyfin.Data/Events/Users/UserUpdatedEventArgs.cs
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
using Jellyfin.Data.Entities;
|
||||||
|
|
||||||
|
namespace Jellyfin.Data.Events.Users
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An event that occurs when a user is updated.
|
||||||
|
/// </summary>
|
||||||
|
public class UserUpdatedEventArgs : GenericEventArgs<User>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="UserUpdatedEventArgs"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="arg">The user.</param>
|
||||||
|
public UserUpdatedEventArgs(User arg) : base(arg)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,8 +2,8 @@ using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Jellyfin.Data.Entities;
|
using Jellyfin.Data.Entities;
|
||||||
|
using Jellyfin.Data.Events;
|
||||||
using MediaBrowser.Model.Activity;
|
using MediaBrowser.Model.Activity;
|
||||||
using MediaBrowser.Model.Events;
|
|
||||||
using MediaBrowser.Model.Querying;
|
using MediaBrowser.Model.Querying;
|
||||||
|
|
||||||
namespace Jellyfin.Server.Implementations.Activity
|
namespace Jellyfin.Server.Implementations.Activity
|
||||||
|
|
|
@ -0,0 +1,102 @@
|
||||||
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Jellyfin.Data.Entities;
|
||||||
|
using MediaBrowser.Controller.Entities;
|
||||||
|
using MediaBrowser.Controller.Entities.Audio;
|
||||||
|
using MediaBrowser.Controller.Events;
|
||||||
|
using MediaBrowser.Controller.Subtitles;
|
||||||
|
using MediaBrowser.Model.Activity;
|
||||||
|
using MediaBrowser.Model.Globalization;
|
||||||
|
using Episode = MediaBrowser.Controller.Entities.TV.Episode;
|
||||||
|
|
||||||
|
namespace Jellyfin.Server.Implementations.Events.Consumers.Library
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Creates an entry in the activity log whenever a subtitle download fails.
|
||||||
|
/// </summary>
|
||||||
|
public class SubtitleDownloadFailureLogger : IEventConsumer<SubtitleDownloadFailureEventArgs>
|
||||||
|
{
|
||||||
|
private readonly ILocalizationManager _localizationManager;
|
||||||
|
private readonly IActivityManager _activityManager;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="SubtitleDownloadFailureLogger"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="localizationManager">The localization manager.</param>
|
||||||
|
/// <param name="activityManager">The activity manager.</param>
|
||||||
|
public SubtitleDownloadFailureLogger(ILocalizationManager localizationManager, IActivityManager activityManager)
|
||||||
|
{
|
||||||
|
_localizationManager = localizationManager;
|
||||||
|
_activityManager = activityManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public async Task OnEvent(SubtitleDownloadFailureEventArgs eventArgs)
|
||||||
|
{
|
||||||
|
await _activityManager.CreateAsync(new ActivityLog(
|
||||||
|
string.Format(
|
||||||
|
CultureInfo.InvariantCulture,
|
||||||
|
_localizationManager.GetLocalizedString("SubtitleDownloadFailureFromForItem"),
|
||||||
|
eventArgs.Provider,
|
||||||
|
GetItemName(eventArgs.Item)),
|
||||||
|
"SubtitleDownloadFailure",
|
||||||
|
Guid.Empty)
|
||||||
|
{
|
||||||
|
ItemId = eventArgs.Item.Id.ToString("N", CultureInfo.InvariantCulture),
|
||||||
|
ShortOverview = eventArgs.Exception.Message
|
||||||
|
}).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetItemName(BaseItem item)
|
||||||
|
{
|
||||||
|
var name = item.Name;
|
||||||
|
if (item is Episode episode)
|
||||||
|
{
|
||||||
|
if (episode.IndexNumber.HasValue)
|
||||||
|
{
|
||||||
|
name = string.Format(
|
||||||
|
CultureInfo.InvariantCulture,
|
||||||
|
"Ep{0} - {1}",
|
||||||
|
episode.IndexNumber.Value,
|
||||||
|
name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (episode.ParentIndexNumber.HasValue)
|
||||||
|
{
|
||||||
|
name = string.Format(
|
||||||
|
CultureInfo.InvariantCulture,
|
||||||
|
"S{0}, {1}",
|
||||||
|
episode.ParentIndexNumber.Value,
|
||||||
|
name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item is IHasSeries hasSeries)
|
||||||
|
{
|
||||||
|
name = hasSeries.SeriesName + " - " + name;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item is IHasAlbumArtist hasAlbumArtist)
|
||||||
|
{
|
||||||
|
var artists = hasAlbumArtist.AlbumArtists;
|
||||||
|
|
||||||
|
if (artists.Count > 0)
|
||||||
|
{
|
||||||
|
name = artists[0] + " - " + name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (item is IHasArtist hasArtist)
|
||||||
|
{
|
||||||
|
var artists = hasArtist.Artists;
|
||||||
|
|
||||||
|
if (artists.Count > 0)
|
||||||
|
{
|
||||||
|
name = artists[0] + " - " + name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Jellyfin.Data.Entities;
|
||||||
|
using Jellyfin.Data.Events;
|
||||||
|
using MediaBrowser.Controller.Events;
|
||||||
|
using MediaBrowser.Controller.Session;
|
||||||
|
using MediaBrowser.Model.Activity;
|
||||||
|
using MediaBrowser.Model.Globalization;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace Jellyfin.Server.Implementations.Events.Consumers.Security
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Creates an entry in the activity log when there is a failed login attempt.
|
||||||
|
/// </summary>
|
||||||
|
public class AuthenticationFailedLogger : IEventConsumer<GenericEventArgs<AuthenticationRequest>>
|
||||||
|
{
|
||||||
|
private readonly ILocalizationManager _localizationManager;
|
||||||
|
private readonly IActivityManager _activityManager;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="AuthenticationFailedLogger"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="localizationManager">The localization manager.</param>
|
||||||
|
/// <param name="activityManager">The activity manager.</param>
|
||||||
|
public AuthenticationFailedLogger(ILocalizationManager localizationManager, IActivityManager activityManager)
|
||||||
|
{
|
||||||
|
_localizationManager = localizationManager;
|
||||||
|
_activityManager = activityManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public async Task OnEvent(GenericEventArgs<AuthenticationRequest> eventArgs)
|
||||||
|
{
|
||||||
|
await _activityManager.CreateAsync(new ActivityLog(
|
||||||
|
string.Format(
|
||||||
|
CultureInfo.InvariantCulture,
|
||||||
|
_localizationManager.GetLocalizedString("FailedLoginAttemptWithUserName"),
|
||||||
|
eventArgs.Argument.Username),
|
||||||
|
"AuthenticationFailed",
|
||||||
|
Guid.Empty)
|
||||||
|
{
|
||||||
|
LogSeverity = LogLevel.Error,
|
||||||
|
ShortOverview = string.Format(
|
||||||
|
CultureInfo.InvariantCulture,
|
||||||
|
_localizationManager.GetLocalizedString("LabelIpAddressValue"),
|
||||||
|
eventArgs.Argument.RemoteEndPoint),
|
||||||
|
}).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Jellyfin.Data.Entities;
|
||||||
|
using Jellyfin.Data.Events;
|
||||||
|
using MediaBrowser.Controller.Authentication;
|
||||||
|
using MediaBrowser.Controller.Events;
|
||||||
|
using MediaBrowser.Model.Activity;
|
||||||
|
using MediaBrowser.Model.Globalization;
|
||||||
|
|
||||||
|
namespace Jellyfin.Server.Implementations.Events.Consumers.Security
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Creates an entry in the activity log when there is a successful login attempt.
|
||||||
|
/// </summary>
|
||||||
|
public class AuthenticationSucceededLogger : IEventConsumer<GenericEventArgs<AuthenticationResult>>
|
||||||
|
{
|
||||||
|
private readonly ILocalizationManager _localizationManager;
|
||||||
|
private readonly IActivityManager _activityManager;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="AuthenticationSucceededLogger"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="localizationManager">The localization manager.</param>
|
||||||
|
/// <param name="activityManager">The activity manager.</param>
|
||||||
|
public AuthenticationSucceededLogger(ILocalizationManager localizationManager, IActivityManager activityManager)
|
||||||
|
{
|
||||||
|
_localizationManager = localizationManager;
|
||||||
|
_activityManager = activityManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public async Task OnEvent(GenericEventArgs<AuthenticationResult> e)
|
||||||
|
{
|
||||||
|
await _activityManager.CreateAsync(new ActivityLog(
|
||||||
|
string.Format(
|
||||||
|
CultureInfo.InvariantCulture,
|
||||||
|
_localizationManager.GetLocalizedString("AuthenticationSucceededWithUserName"),
|
||||||
|
e.Argument.User.Name),
|
||||||
|
"AuthenticationSucceeded",
|
||||||
|
e.Argument.User.Id)
|
||||||
|
{
|
||||||
|
ShortOverview = string.Format(
|
||||||
|
CultureInfo.InvariantCulture,
|
||||||
|
_localizationManager.GetLocalizedString("LabelIpAddressValue"),
|
||||||
|
e.Argument.SessionInfo.RemoteEndPoint),
|
||||||
|
}).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,104 @@
|
||||||
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Jellyfin.Data.Entities;
|
||||||
|
using MediaBrowser.Controller.Events;
|
||||||
|
using MediaBrowser.Controller.Library;
|
||||||
|
using MediaBrowser.Model.Activity;
|
||||||
|
using MediaBrowser.Model.Dto;
|
||||||
|
using MediaBrowser.Model.Entities;
|
||||||
|
using MediaBrowser.Model.Globalization;
|
||||||
|
using MediaBrowser.Model.Notifications;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace Jellyfin.Server.Implementations.Events.Consumers.Session
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Creates an entry in the activity log whenever a user starts playback.
|
||||||
|
/// </summary>
|
||||||
|
public class PlaybackStartLogger : IEventConsumer<PlaybackStartEventArgs>
|
||||||
|
{
|
||||||
|
private readonly ILogger<PlaybackStartLogger> _logger;
|
||||||
|
private readonly ILocalizationManager _localizationManager;
|
||||||
|
private readonly IActivityManager _activityManager;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="PlaybackStartLogger"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="logger">The logger.</param>
|
||||||
|
/// <param name="localizationManager">The localization manager.</param>
|
||||||
|
/// <param name="activityManager">The activity manager.</param>
|
||||||
|
public PlaybackStartLogger(ILogger<PlaybackStartLogger> logger, ILocalizationManager localizationManager, IActivityManager activityManager)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_localizationManager = localizationManager;
|
||||||
|
_activityManager = activityManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public async Task OnEvent(PlaybackStartEventArgs eventArgs)
|
||||||
|
{
|
||||||
|
if (eventArgs.MediaInfo == null)
|
||||||
|
{
|
||||||
|
_logger.LogWarning("PlaybackStart reported with null media info.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (eventArgs.Item != null && eventArgs.Item.IsThemeMedia)
|
||||||
|
{
|
||||||
|
// Don't report theme song or local trailer playback
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (eventArgs.Users.Count == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var user = eventArgs.Users[0];
|
||||||
|
|
||||||
|
await _activityManager.CreateAsync(new ActivityLog(
|
||||||
|
string.Format(
|
||||||
|
CultureInfo.InvariantCulture,
|
||||||
|
_localizationManager.GetLocalizedString("UserStartedPlayingItemWithValues"),
|
||||||
|
user.Username,
|
||||||
|
GetItemName(eventArgs.MediaInfo),
|
||||||
|
eventArgs.DeviceName),
|
||||||
|
GetPlaybackNotificationType(eventArgs.MediaInfo.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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,106 @@
|
||||||
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Jellyfin.Data.Entities;
|
||||||
|
using MediaBrowser.Controller.Events;
|
||||||
|
using MediaBrowser.Controller.Library;
|
||||||
|
using MediaBrowser.Model.Activity;
|
||||||
|
using MediaBrowser.Model.Dto;
|
||||||
|
using MediaBrowser.Model.Entities;
|
||||||
|
using MediaBrowser.Model.Globalization;
|
||||||
|
using MediaBrowser.Model.Notifications;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace Jellyfin.Server.Implementations.Events.Consumers.Session
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Creates an activity log entry whenever a user stops playback.
|
||||||
|
/// </summary>
|
||||||
|
public class PlaybackStopLogger : IEventConsumer<PlaybackStopEventArgs>
|
||||||
|
{
|
||||||
|
private readonly ILogger<PlaybackStopLogger> _logger;
|
||||||
|
private readonly ILocalizationManager _localizationManager;
|
||||||
|
private readonly IActivityManager _activityManager;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="PlaybackStopLogger"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="logger">The logger.</param>
|
||||||
|
/// <param name="localizationManager">The localization manager.</param>
|
||||||
|
/// <param name="activityManager">The activity manager.</param>
|
||||||
|
public PlaybackStopLogger(ILogger<PlaybackStopLogger> logger, ILocalizationManager localizationManager, IActivityManager activityManager)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_localizationManager = localizationManager;
|
||||||
|
_activityManager = activityManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public async Task OnEvent(PlaybackStopEventArgs eventArgs)
|
||||||
|
{
|
||||||
|
var item = eventArgs.MediaInfo;
|
||||||
|
|
||||||
|
if (item == null)
|
||||||
|
{
|
||||||
|
_logger.LogWarning("PlaybackStopped reported with null media info.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (eventArgs.Item != null && eventArgs.Item.IsThemeMedia)
|
||||||
|
{
|
||||||
|
// Don't report theme song or local trailer playback
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (eventArgs.Users.Count == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var user = eventArgs.Users[0];
|
||||||
|
|
||||||
|
await _activityManager.CreateAsync(new ActivityLog(
|
||||||
|
string.Format(
|
||||||
|
CultureInfo.InvariantCulture,
|
||||||
|
_localizationManager.GetLocalizedString("UserStoppedPlayingItemWithValues"),
|
||||||
|
user.Username,
|
||||||
|
GetItemName(item),
|
||||||
|
eventArgs.DeviceName),
|
||||||
|
GetPlaybackStoppedNotificationType(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 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Jellyfin.Data.Entities;
|
||||||
|
using MediaBrowser.Controller.Events;
|
||||||
|
using MediaBrowser.Controller.Events.Session;
|
||||||
|
using MediaBrowser.Model.Activity;
|
||||||
|
using MediaBrowser.Model.Globalization;
|
||||||
|
|
||||||
|
namespace Jellyfin.Server.Implementations.Events.Consumers.Session
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Creates an entry in the activity log whenever a session ends.
|
||||||
|
/// </summary>
|
||||||
|
public class SessionEndedLogger : IEventConsumer<SessionEndedEventArgs>
|
||||||
|
{
|
||||||
|
private readonly ILocalizationManager _localizationManager;
|
||||||
|
private readonly IActivityManager _activityManager;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="SessionEndedLogger"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="localizationManager">The localization manager.</param>
|
||||||
|
/// <param name="activityManager">The activity manager.</param>
|
||||||
|
public SessionEndedLogger(ILocalizationManager localizationManager, IActivityManager activityManager)
|
||||||
|
{
|
||||||
|
_localizationManager = localizationManager;
|
||||||
|
_activityManager = activityManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public async Task OnEvent(SessionEndedEventArgs eventArgs)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(eventArgs.Argument.UserName))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await _activityManager.CreateAsync(new ActivityLog(
|
||||||
|
string.Format(
|
||||||
|
CultureInfo.InvariantCulture,
|
||||||
|
_localizationManager.GetLocalizedString("UserOfflineFromDevice"),
|
||||||
|
eventArgs.Argument.UserName,
|
||||||
|
eventArgs.Argument.DeviceName),
|
||||||
|
"SessionEnded",
|
||||||
|
eventArgs.Argument.UserId)
|
||||||
|
{
|
||||||
|
ShortOverview = string.Format(
|
||||||
|
CultureInfo.InvariantCulture,
|
||||||
|
_localizationManager.GetLocalizedString("LabelIpAddressValue"),
|
||||||
|
eventArgs.Argument.RemoteEndPoint),
|
||||||
|
}).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Jellyfin.Data.Entities;
|
||||||
|
using MediaBrowser.Controller.Events;
|
||||||
|
using MediaBrowser.Controller.Events.Session;
|
||||||
|
using MediaBrowser.Model.Activity;
|
||||||
|
using MediaBrowser.Model.Globalization;
|
||||||
|
|
||||||
|
namespace Jellyfin.Server.Implementations.Events.Consumers.Session
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Creates an entry in the activity log when a session is started.
|
||||||
|
/// </summary>
|
||||||
|
public class SessionStartedLogger : IEventConsumer<SessionStartedEventArgs>
|
||||||
|
{
|
||||||
|
private readonly ILocalizationManager _localizationManager;
|
||||||
|
private readonly IActivityManager _activityManager;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="SessionStartedLogger"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="localizationManager">The localization manager.</param>
|
||||||
|
/// <param name="activityManager">The activity manager.</param>
|
||||||
|
public SessionStartedLogger(ILocalizationManager localizationManager, IActivityManager activityManager)
|
||||||
|
{
|
||||||
|
_localizationManager = localizationManager;
|
||||||
|
_activityManager = activityManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public async Task OnEvent(SessionStartedEventArgs eventArgs)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(eventArgs.Argument.UserName))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await _activityManager.CreateAsync(new ActivityLog(
|
||||||
|
string.Format(
|
||||||
|
CultureInfo.InvariantCulture,
|
||||||
|
_localizationManager.GetLocalizedString("UserOnlineFromDevice"),
|
||||||
|
eventArgs.Argument.UserName,
|
||||||
|
eventArgs.Argument.DeviceName),
|
||||||
|
"SessionStarted",
|
||||||
|
eventArgs.Argument.UserId)
|
||||||
|
{
|
||||||
|
ShortOverview = string.Format(
|
||||||
|
CultureInfo.InvariantCulture,
|
||||||
|
_localizationManager.GetLocalizedString("LabelIpAddressValue"),
|
||||||
|
eventArgs.Argument.RemoteEndPoint)
|
||||||
|
}).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Jellyfin.Data.Events.System;
|
||||||
|
using MediaBrowser.Controller.Events;
|
||||||
|
using MediaBrowser.Controller.Session;
|
||||||
|
|
||||||
|
namespace Jellyfin.Server.Implementations.Events.Consumers.System
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Notifies users when there is a pending restart.
|
||||||
|
/// </summary>
|
||||||
|
public class PendingRestartNotifier : IEventConsumer<PendingRestartEventArgs>
|
||||||
|
{
|
||||||
|
private readonly ISessionManager _sessionManager;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="PendingRestartNotifier"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sessionManager">The session manager.</param>
|
||||||
|
public PendingRestartNotifier(ISessionManager sessionManager)
|
||||||
|
{
|
||||||
|
_sessionManager = sessionManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public async Task OnEvent(PendingRestartEventArgs eventArgs)
|
||||||
|
{
|
||||||
|
await _sessionManager.SendRestartRequiredNotification(CancellationToken.None).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,158 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Jellyfin.Data.Entities;
|
||||||
|
using MediaBrowser.Controller.Events;
|
||||||
|
using MediaBrowser.Model.Activity;
|
||||||
|
using MediaBrowser.Model.Globalization;
|
||||||
|
using MediaBrowser.Model.Notifications;
|
||||||
|
using MediaBrowser.Model.Tasks;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace Jellyfin.Server.Implementations.Events.Consumers.System
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Creates an activity log entry whenever a task is completed.
|
||||||
|
/// </summary>
|
||||||
|
public class TaskCompletedLogger : IEventConsumer<TaskCompletionEventArgs>
|
||||||
|
{
|
||||||
|
private readonly ILocalizationManager _localizationManager;
|
||||||
|
private readonly IActivityManager _activityManager;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="TaskCompletedLogger"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="localizationManager">The localization manager.</param>
|
||||||
|
/// <param name="activityManager">The activity manager.</param>
|
||||||
|
public TaskCompletedLogger(ILocalizationManager localizationManager, IActivityManager activityManager)
|
||||||
|
{
|
||||||
|
_localizationManager = localizationManager;
|
||||||
|
_activityManager = activityManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public async Task OnEvent(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,
|
||||||
|
_localizationManager.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 _activityManager.CreateAsync(new ActivityLog(
|
||||||
|
string.Format(CultureInfo.InvariantCulture, _localizationManager.GetLocalizedString("ScheduledTaskFailedWithName"), task.Name),
|
||||||
|
NotificationType.TaskFailed.ToString(),
|
||||||
|
Guid.Empty)
|
||||||
|
{
|
||||||
|
LogSeverity = LogLevel.Error,
|
||||||
|
Overview = string.Join(Environment.NewLine, vals),
|
||||||
|
ShortOverview = runningTime
|
||||||
|
}).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Controller.Events;
|
||||||
|
using MediaBrowser.Controller.Session;
|
||||||
|
using MediaBrowser.Model.Tasks;
|
||||||
|
|
||||||
|
namespace Jellyfin.Server.Implementations.Events.Consumers.System
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Notifies admin users when a task is completed.
|
||||||
|
/// </summary>
|
||||||
|
public class TaskCompletedNotifier : IEventConsumer<TaskCompletionEventArgs>
|
||||||
|
{
|
||||||
|
private readonly ISessionManager _sessionManager;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="TaskCompletedNotifier"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sessionManager">The session manager.</param>
|
||||||
|
public TaskCompletedNotifier(ISessionManager sessionManager)
|
||||||
|
{
|
||||||
|
_sessionManager = sessionManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public async Task OnEvent(TaskCompletionEventArgs eventArgs)
|
||||||
|
{
|
||||||
|
await _sessionManager.SendMessageToAdminSessions("ScheduledTaskEnded", eventArgs.Result, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Controller.Events;
|
||||||
|
using MediaBrowser.Controller.Events.Updates;
|
||||||
|
using MediaBrowser.Controller.Session;
|
||||||
|
|
||||||
|
namespace Jellyfin.Server.Implementations.Events.Consumers.Updates
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Notifies admin users when a plugin installation is cancelled.
|
||||||
|
/// </summary>
|
||||||
|
public class PluginInstallationCancelledNotifier : IEventConsumer<PluginInstallationCancelledEventArgs>
|
||||||
|
{
|
||||||
|
private readonly ISessionManager _sessionManager;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="PluginInstallationCancelledNotifier"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sessionManager">The session manager.</param>
|
||||||
|
public PluginInstallationCancelledNotifier(ISessionManager sessionManager)
|
||||||
|
{
|
||||||
|
_sessionManager = sessionManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public async Task OnEvent(PluginInstallationCancelledEventArgs eventArgs)
|
||||||
|
{
|
||||||
|
await _sessionManager.SendMessageToAdminSessions("PackageInstallationCancelled", eventArgs.Argument, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Jellyfin.Data.Entities;
|
||||||
|
using MediaBrowser.Common.Updates;
|
||||||
|
using MediaBrowser.Controller.Events;
|
||||||
|
using MediaBrowser.Model.Activity;
|
||||||
|
using MediaBrowser.Model.Globalization;
|
||||||
|
using MediaBrowser.Model.Notifications;
|
||||||
|
|
||||||
|
namespace Jellyfin.Server.Implementations.Events.Consumers.Updates
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Creates an entry in the activity log when a package installation fails.
|
||||||
|
/// </summary>
|
||||||
|
public class PluginInstallationFailedLogger : IEventConsumer<InstallationFailedEventArgs>
|
||||||
|
{
|
||||||
|
private readonly ILocalizationManager _localizationManager;
|
||||||
|
private readonly IActivityManager _activityManager;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="PluginInstallationFailedLogger"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="localizationManager">The localization manager.</param>
|
||||||
|
/// <param name="activityManager">The activity manager.</param>
|
||||||
|
public PluginInstallationFailedLogger(ILocalizationManager localizationManager, IActivityManager activityManager)
|
||||||
|
{
|
||||||
|
_localizationManager = localizationManager;
|
||||||
|
_activityManager = activityManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public async Task OnEvent(InstallationFailedEventArgs eventArgs)
|
||||||
|
{
|
||||||
|
await _activityManager.CreateAsync(new ActivityLog(
|
||||||
|
string.Format(
|
||||||
|
CultureInfo.InvariantCulture,
|
||||||
|
_localizationManager.GetLocalizedString("NameInstallFailed"),
|
||||||
|
eventArgs.InstallationInfo.Name),
|
||||||
|
NotificationType.InstallationFailed.ToString(),
|
||||||
|
Guid.Empty)
|
||||||
|
{
|
||||||
|
ShortOverview = string.Format(
|
||||||
|
CultureInfo.InvariantCulture,
|
||||||
|
_localizationManager.GetLocalizedString("VersionNumber"),
|
||||||
|
eventArgs.InstallationInfo.Version),
|
||||||
|
Overview = eventArgs.Exception.Message
|
||||||
|
}).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Common.Updates;
|
||||||
|
using MediaBrowser.Controller.Events;
|
||||||
|
using MediaBrowser.Controller.Session;
|
||||||
|
|
||||||
|
namespace Jellyfin.Server.Implementations.Events.Consumers.Updates
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Notifies admin users when a plugin installation fails.
|
||||||
|
/// </summary>
|
||||||
|
public class PluginInstallationFailedNotifier : IEventConsumer<InstallationFailedEventArgs>
|
||||||
|
{
|
||||||
|
private readonly ISessionManager _sessionManager;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="PluginInstallationFailedNotifier"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sessionManager">The session manager.</param>
|
||||||
|
public PluginInstallationFailedNotifier(ISessionManager sessionManager)
|
||||||
|
{
|
||||||
|
_sessionManager = sessionManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public async Task OnEvent(InstallationFailedEventArgs eventArgs)
|
||||||
|
{
|
||||||
|
await _sessionManager.SendMessageToAdminSessions("PackageInstallationFailed", eventArgs.InstallationInfo, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Jellyfin.Data.Entities;
|
||||||
|
using MediaBrowser.Controller.Events;
|
||||||
|
using MediaBrowser.Controller.Events.Updates;
|
||||||
|
using MediaBrowser.Model.Activity;
|
||||||
|
using MediaBrowser.Model.Globalization;
|
||||||
|
using MediaBrowser.Model.Notifications;
|
||||||
|
|
||||||
|
namespace Jellyfin.Server.Implementations.Events.Consumers.Updates
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Creates an entry in the activity log when a plugin is installed.
|
||||||
|
/// </summary>
|
||||||
|
public class PluginInstalledLogger : IEventConsumer<PluginInstalledEventArgs>
|
||||||
|
{
|
||||||
|
private readonly ILocalizationManager _localizationManager;
|
||||||
|
private readonly IActivityManager _activityManager;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="PluginInstalledLogger"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="localizationManager">The localization manager.</param>
|
||||||
|
/// <param name="activityManager">The activity manager.</param>
|
||||||
|
public PluginInstalledLogger(ILocalizationManager localizationManager, IActivityManager activityManager)
|
||||||
|
{
|
||||||
|
_localizationManager = localizationManager;
|
||||||
|
_activityManager = activityManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public async Task OnEvent(PluginInstalledEventArgs eventArgs)
|
||||||
|
{
|
||||||
|
await _activityManager.CreateAsync(new ActivityLog(
|
||||||
|
string.Format(
|
||||||
|
CultureInfo.InvariantCulture,
|
||||||
|
_localizationManager.GetLocalizedString("PluginInstalledWithName"),
|
||||||
|
eventArgs.Argument.Name),
|
||||||
|
NotificationType.PluginInstalled.ToString(),
|
||||||
|
Guid.Empty)
|
||||||
|
{
|
||||||
|
ShortOverview = string.Format(
|
||||||
|
CultureInfo.InvariantCulture,
|
||||||
|
_localizationManager.GetLocalizedString("VersionNumber"),
|
||||||
|
eventArgs.Argument.Version)
|
||||||
|
}).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Controller.Events;
|
||||||
|
using MediaBrowser.Controller.Events.Updates;
|
||||||
|
using MediaBrowser.Controller.Session;
|
||||||
|
|
||||||
|
namespace Jellyfin.Server.Implementations.Events.Consumers.Updates
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Notifies admin users when a plugin is installed.
|
||||||
|
/// </summary>
|
||||||
|
public class PluginInstalledNotifier : IEventConsumer<PluginInstalledEventArgs>
|
||||||
|
{
|
||||||
|
private readonly ISessionManager _sessionManager;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="PluginInstalledNotifier"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sessionManager">The session manager.</param>
|
||||||
|
public PluginInstalledNotifier(ISessionManager sessionManager)
|
||||||
|
{
|
||||||
|
_sessionManager = sessionManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public async Task OnEvent(PluginInstalledEventArgs eventArgs)
|
||||||
|
{
|
||||||
|
await _sessionManager.SendMessageToAdminSessions("PackageInstallationCompleted", eventArgs.Argument, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Controller.Events;
|
||||||
|
using MediaBrowser.Controller.Events.Updates;
|
||||||
|
using MediaBrowser.Controller.Session;
|
||||||
|
|
||||||
|
namespace Jellyfin.Server.Implementations.Events.Consumers.Updates
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Notifies admin users when a plugin is being installed.
|
||||||
|
/// </summary>
|
||||||
|
public class PluginInstallingNotifier : IEventConsumer<PluginInstallingEventArgs>
|
||||||
|
{
|
||||||
|
private readonly ISessionManager _sessionManager;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="PluginInstallingNotifier"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sessionManager">The session manager.</param>
|
||||||
|
public PluginInstallingNotifier(ISessionManager sessionManager)
|
||||||
|
{
|
||||||
|
_sessionManager = sessionManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public async Task OnEvent(PluginInstallingEventArgs eventArgs)
|
||||||
|
{
|
||||||
|
await _sessionManager.SendMessageToAdminSessions("PackageInstalling", eventArgs.Argument, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Jellyfin.Data.Entities;
|
||||||
|
using MediaBrowser.Controller.Events;
|
||||||
|
using MediaBrowser.Controller.Events.Updates;
|
||||||
|
using MediaBrowser.Model.Activity;
|
||||||
|
using MediaBrowser.Model.Globalization;
|
||||||
|
using MediaBrowser.Model.Notifications;
|
||||||
|
|
||||||
|
namespace Jellyfin.Server.Implementations.Events.Consumers.Updates
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Creates an entry in the activity log when a plugin is uninstalled.
|
||||||
|
/// </summary>
|
||||||
|
public class PluginUninstalledLogger : IEventConsumer<PluginUninstalledEventArgs>
|
||||||
|
{
|
||||||
|
private readonly ILocalizationManager _localizationManager;
|
||||||
|
private readonly IActivityManager _activityManager;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="PluginUninstalledLogger"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="localizationManager">The localization manager.</param>
|
||||||
|
/// <param name="activityManager">The activity manager.</param>
|
||||||
|
public PluginUninstalledLogger(ILocalizationManager localizationManager, IActivityManager activityManager)
|
||||||
|
{
|
||||||
|
_localizationManager = localizationManager;
|
||||||
|
_activityManager = activityManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public async Task OnEvent(PluginUninstalledEventArgs e)
|
||||||
|
{
|
||||||
|
await _activityManager.CreateAsync(new ActivityLog(
|
||||||
|
string.Format(
|
||||||
|
CultureInfo.InvariantCulture,
|
||||||
|
_localizationManager.GetLocalizedString("PluginUninstalledWithName"),
|
||||||
|
e.Argument.Name),
|
||||||
|
NotificationType.PluginUninstalled.ToString(),
|
||||||
|
Guid.Empty))
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Controller.Events;
|
||||||
|
using MediaBrowser.Controller.Events.Updates;
|
||||||
|
using MediaBrowser.Controller.Session;
|
||||||
|
|
||||||
|
namespace Jellyfin.Server.Implementations.Events.Consumers.Updates
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Notifies admin users when a plugin is uninstalled.
|
||||||
|
/// </summary>
|
||||||
|
public class PluginUninstalledNotifier : IEventConsumer<PluginUninstalledEventArgs>
|
||||||
|
{
|
||||||
|
private readonly ISessionManager _sessionManager;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="PluginUninstalledNotifier"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sessionManager">The session manager.</param>
|
||||||
|
public PluginUninstalledNotifier(ISessionManager sessionManager)
|
||||||
|
{
|
||||||
|
_sessionManager = sessionManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public async Task OnEvent(PluginUninstalledEventArgs eventArgs)
|
||||||
|
{
|
||||||
|
await _sessionManager.SendMessageToAdminSessions("PluginUninstalled", eventArgs.Argument, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Jellyfin.Data.Entities;
|
||||||
|
using MediaBrowser.Controller.Events;
|
||||||
|
using MediaBrowser.Controller.Events.Updates;
|
||||||
|
using MediaBrowser.Model.Activity;
|
||||||
|
using MediaBrowser.Model.Globalization;
|
||||||
|
using MediaBrowser.Model.Notifications;
|
||||||
|
|
||||||
|
namespace Jellyfin.Server.Implementations.Events.Consumers.Updates
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Creates an entry in the activity log when a plugin is updated.
|
||||||
|
/// </summary>
|
||||||
|
public class PluginUpdatedLogger : IEventConsumer<PluginUpdatedEventArgs>
|
||||||
|
{
|
||||||
|
private readonly ILocalizationManager _localizationManager;
|
||||||
|
private readonly IActivityManager _activityManager;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="PluginUpdatedLogger"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="localizationManager">The localization manager.</param>
|
||||||
|
/// <param name="activityManager">The activity manager.</param>
|
||||||
|
public PluginUpdatedLogger(ILocalizationManager localizationManager, IActivityManager activityManager)
|
||||||
|
{
|
||||||
|
_localizationManager = localizationManager;
|
||||||
|
_activityManager = activityManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public async Task OnEvent(PluginUpdatedEventArgs eventArgs)
|
||||||
|
{
|
||||||
|
await _activityManager.CreateAsync(new ActivityLog(
|
||||||
|
string.Format(
|
||||||
|
CultureInfo.InvariantCulture,
|
||||||
|
_localizationManager.GetLocalizedString("PluginUpdatedWithName"),
|
||||||
|
eventArgs.Argument.Name),
|
||||||
|
NotificationType.PluginUpdateInstalled.ToString(),
|
||||||
|
Guid.Empty)
|
||||||
|
{
|
||||||
|
ShortOverview = string.Format(
|
||||||
|
CultureInfo.InvariantCulture,
|
||||||
|
_localizationManager.GetLocalizedString("VersionNumber"),
|
||||||
|
eventArgs.Argument.Version),
|
||||||
|
Overview = eventArgs.Argument.Changelog
|
||||||
|
}).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Jellyfin.Data.Entities;
|
||||||
|
using Jellyfin.Data.Events.Users;
|
||||||
|
using MediaBrowser.Controller.Events;
|
||||||
|
using MediaBrowser.Model.Activity;
|
||||||
|
using MediaBrowser.Model.Globalization;
|
||||||
|
|
||||||
|
namespace Jellyfin.Server.Implementations.Events.Consumers.Users
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Creates an entry in the activity log when a user is created.
|
||||||
|
/// </summary>
|
||||||
|
public class UserCreatedLogger : IEventConsumer<UserCreatedEventArgs>
|
||||||
|
{
|
||||||
|
private readonly ILocalizationManager _localizationManager;
|
||||||
|
private readonly IActivityManager _activityManager;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="UserCreatedLogger"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="localizationManager">The localization manager.</param>
|
||||||
|
/// <param name="activityManager">The activity manager.</param>
|
||||||
|
public UserCreatedLogger(ILocalizationManager localizationManager, IActivityManager activityManager)
|
||||||
|
{
|
||||||
|
_localizationManager = localizationManager;
|
||||||
|
_activityManager = activityManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public async Task OnEvent(UserCreatedEventArgs eventArgs)
|
||||||
|
{
|
||||||
|
await _activityManager.CreateAsync(new ActivityLog(
|
||||||
|
string.Format(
|
||||||
|
CultureInfo.InvariantCulture,
|
||||||
|
_localizationManager.GetLocalizedString("UserCreatedWithName"),
|
||||||
|
eventArgs.Argument.Username),
|
||||||
|
"UserCreated",
|
||||||
|
eventArgs.Argument.Id))
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Jellyfin.Data.Entities;
|
||||||
|
using Jellyfin.Data.Events.Users;
|
||||||
|
using MediaBrowser.Controller.Events;
|
||||||
|
using MediaBrowser.Model.Activity;
|
||||||
|
using MediaBrowser.Model.Globalization;
|
||||||
|
|
||||||
|
namespace Jellyfin.Server.Implementations.Events.Consumers.Users
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Adds an entry to the activity log when a user is deleted.
|
||||||
|
/// </summary>
|
||||||
|
public class UserDeletedLogger : IEventConsumer<UserDeletedEventArgs>
|
||||||
|
{
|
||||||
|
private readonly ILocalizationManager _localizationManager;
|
||||||
|
private readonly IActivityManager _activityManager;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="UserDeletedLogger"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="localizationManager">The localization manager.</param>
|
||||||
|
/// <param name="activityManager">The activity manager.</param>
|
||||||
|
public UserDeletedLogger(ILocalizationManager localizationManager, IActivityManager activityManager)
|
||||||
|
{
|
||||||
|
_localizationManager = localizationManager;
|
||||||
|
_activityManager = activityManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public async Task OnEvent(UserDeletedEventArgs eventArgs)
|
||||||
|
{
|
||||||
|
await _activityManager.CreateAsync(new ActivityLog(
|
||||||
|
string.Format(
|
||||||
|
CultureInfo.InvariantCulture,
|
||||||
|
_localizationManager.GetLocalizedString("UserDeletedWithName"),
|
||||||
|
eventArgs.Argument.Username),
|
||||||
|
"UserDeleted",
|
||||||
|
Guid.Empty))
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Jellyfin.Data.Events.Users;
|
||||||
|
using MediaBrowser.Controller.Events;
|
||||||
|
using MediaBrowser.Controller.Session;
|
||||||
|
|
||||||
|
namespace Jellyfin.Server.Implementations.Events.Consumers.Users
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Notifies the user's sessions when a user is deleted.
|
||||||
|
/// </summary>
|
||||||
|
public class UserDeletedNotifier : IEventConsumer<UserDeletedEventArgs>
|
||||||
|
{
|
||||||
|
private readonly ISessionManager _sessionManager;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="UserDeletedNotifier"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sessionManager">The session manager.</param>
|
||||||
|
public UserDeletedNotifier(ISessionManager sessionManager)
|
||||||
|
{
|
||||||
|
_sessionManager = sessionManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public async Task OnEvent(UserDeletedEventArgs eventArgs)
|
||||||
|
{
|
||||||
|
await _sessionManager.SendMessageToUserSessions(
|
||||||
|
new List<Guid> { eventArgs.Argument.Id },
|
||||||
|
"UserDeleted",
|
||||||
|
eventArgs.Argument.Id.ToString("N", CultureInfo.InvariantCulture),
|
||||||
|
CancellationToken.None).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Jellyfin.Data.Entities;
|
||||||
|
using Jellyfin.Data.Events.Users;
|
||||||
|
using MediaBrowser.Controller.Events;
|
||||||
|
using MediaBrowser.Model.Activity;
|
||||||
|
using MediaBrowser.Model.Globalization;
|
||||||
|
using MediaBrowser.Model.Notifications;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace Jellyfin.Server.Implementations.Events.Consumers.Users
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Creates an entry in the activity log when a user is locked out.
|
||||||
|
/// </summary>
|
||||||
|
public class UserLockedOutLogger : IEventConsumer<UserLockedOutEventArgs>
|
||||||
|
{
|
||||||
|
private readonly ILocalizationManager _localizationManager;
|
||||||
|
private readonly IActivityManager _activityManager;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="UserLockedOutLogger"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="localizationManager">The localization manager.</param>
|
||||||
|
/// <param name="activityManager">The activity manager.</param>
|
||||||
|
public UserLockedOutLogger(ILocalizationManager localizationManager, IActivityManager activityManager)
|
||||||
|
{
|
||||||
|
_localizationManager = localizationManager;
|
||||||
|
_activityManager = activityManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public async Task OnEvent(UserLockedOutEventArgs eventArgs)
|
||||||
|
{
|
||||||
|
await _activityManager.CreateAsync(new ActivityLog(
|
||||||
|
string.Format(
|
||||||
|
CultureInfo.InvariantCulture,
|
||||||
|
_localizationManager.GetLocalizedString("UserLockedOutWithName"),
|
||||||
|
eventArgs.Argument.Username),
|
||||||
|
NotificationType.UserLockedOut.ToString(),
|
||||||
|
eventArgs.Argument.Id)
|
||||||
|
{
|
||||||
|
LogSeverity = LogLevel.Error
|
||||||
|
}).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Jellyfin.Data.Entities;
|
||||||
|
using Jellyfin.Data.Events.Users;
|
||||||
|
using MediaBrowser.Controller.Events;
|
||||||
|
using MediaBrowser.Model.Activity;
|
||||||
|
using MediaBrowser.Model.Globalization;
|
||||||
|
|
||||||
|
namespace Jellyfin.Server.Implementations.Events.Consumers.Users
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Creates an entry in the activity log when a user's password is changed.
|
||||||
|
/// </summary>
|
||||||
|
public class UserPasswordChangedLogger : IEventConsumer<UserPasswordChangedEventArgs>
|
||||||
|
{
|
||||||
|
private readonly ILocalizationManager _localizationManager;
|
||||||
|
private readonly IActivityManager _activityManager;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="UserPasswordChangedLogger"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="localizationManager">The localization manager.</param>
|
||||||
|
/// <param name="activityManager">The activity manager.</param>
|
||||||
|
public UserPasswordChangedLogger(ILocalizationManager localizationManager, IActivityManager activityManager)
|
||||||
|
{
|
||||||
|
_localizationManager = localizationManager;
|
||||||
|
_activityManager = activityManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public async Task OnEvent(UserPasswordChangedEventArgs eventArgs)
|
||||||
|
{
|
||||||
|
await _activityManager.CreateAsync(new ActivityLog(
|
||||||
|
string.Format(
|
||||||
|
CultureInfo.InvariantCulture,
|
||||||
|
_localizationManager.GetLocalizedString("UserPasswordChangedWithName"),
|
||||||
|
eventArgs.Argument.Username),
|
||||||
|
"UserPasswordChanged",
|
||||||
|
eventArgs.Argument.Id))
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Jellyfin.Data.Events.Users;
|
||||||
|
using MediaBrowser.Controller.Events;
|
||||||
|
using MediaBrowser.Controller.Library;
|
||||||
|
using MediaBrowser.Controller.Session;
|
||||||
|
|
||||||
|
namespace Jellyfin.Server.Implementations.Events.Consumers.Users
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Notifies a user when their account has been updated.
|
||||||
|
/// </summary>
|
||||||
|
public class UserUpdatedNotifier : IEventConsumer<UserUpdatedEventArgs>
|
||||||
|
{
|
||||||
|
private readonly IUserManager _userManager;
|
||||||
|
private readonly ISessionManager _sessionManager;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="UserUpdatedNotifier"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="userManager">The user manager.</param>
|
||||||
|
/// <param name="sessionManager">The session manager.</param>
|
||||||
|
public UserUpdatedNotifier(IUserManager userManager, ISessionManager sessionManager)
|
||||||
|
{
|
||||||
|
_userManager = userManager;
|
||||||
|
_sessionManager = sessionManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public async Task OnEvent(UserUpdatedEventArgs e)
|
||||||
|
{
|
||||||
|
await _sessionManager.SendMessageToUserSessions(
|
||||||
|
new List<Guid> { e.Argument.Id },
|
||||||
|
"UserUpdated",
|
||||||
|
_userManager.GetUserDto(e.Argument),
|
||||||
|
CancellationToken.None).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
60
Jellyfin.Server.Implementations/Events/EventManager.cs
Normal file
60
Jellyfin.Server.Implementations/Events/EventManager.cs
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Controller;
|
||||||
|
using MediaBrowser.Controller.Events;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace Jellyfin.Server.Implementations.Events
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Handles the firing of events.
|
||||||
|
/// </summary>
|
||||||
|
public class EventManager : IEventManager
|
||||||
|
{
|
||||||
|
private readonly ILogger<EventManager> _logger;
|
||||||
|
private readonly IServerApplicationHost _appHost;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="EventManager"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="logger">The logger.</param>
|
||||||
|
/// <param name="appHost">The application host.</param>
|
||||||
|
public EventManager(ILogger<EventManager> logger, IServerApplicationHost appHost)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_appHost = appHost;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void Publish<T>(T eventArgs)
|
||||||
|
where T : EventArgs
|
||||||
|
{
|
||||||
|
Task.WaitAll(PublishInternal(eventArgs));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public async Task PublishAsync<T>(T eventArgs)
|
||||||
|
where T : EventArgs
|
||||||
|
{
|
||||||
|
await PublishInternal(eventArgs).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task PublishInternal<T>(T eventArgs)
|
||||||
|
where T : EventArgs
|
||||||
|
{
|
||||||
|
using var scope = _appHost.ServiceProvider.CreateScope();
|
||||||
|
foreach (var service in scope.ServiceProvider.GetServices<IEventConsumer<T>>())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await service.OnEvent(eventArgs).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_logger.LogError(e, "Uncaught exception in EventConsumer {type}: ", service.GetType());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,72 @@
|
||||||
|
using Jellyfin.Data.Events;
|
||||||
|
using Jellyfin.Data.Events.System;
|
||||||
|
using Jellyfin.Data.Events.Users;
|
||||||
|
using Jellyfin.Server.Implementations.Events.Consumers.Library;
|
||||||
|
using Jellyfin.Server.Implementations.Events.Consumers.Security;
|
||||||
|
using Jellyfin.Server.Implementations.Events.Consumers.Session;
|
||||||
|
using Jellyfin.Server.Implementations.Events.Consumers.System;
|
||||||
|
using Jellyfin.Server.Implementations.Events.Consumers.Updates;
|
||||||
|
using Jellyfin.Server.Implementations.Events.Consumers.Users;
|
||||||
|
using MediaBrowser.Common.Updates;
|
||||||
|
using MediaBrowser.Controller.Authentication;
|
||||||
|
using MediaBrowser.Controller.Events;
|
||||||
|
using MediaBrowser.Controller.Events.Session;
|
||||||
|
using MediaBrowser.Controller.Events.Updates;
|
||||||
|
using MediaBrowser.Controller.Library;
|
||||||
|
using MediaBrowser.Controller.Session;
|
||||||
|
using MediaBrowser.Controller.Subtitles;
|
||||||
|
using MediaBrowser.Model.Tasks;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
|
namespace Jellyfin.Server.Implementations.Events
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A class containing extensions to <see cref="IServiceCollection"/> for eventing.
|
||||||
|
/// </summary>
|
||||||
|
public static class EventingServiceCollectionExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Adds the event services to the service collection.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="collection">The service collection.</param>
|
||||||
|
public static void AddEventServices(this IServiceCollection collection)
|
||||||
|
{
|
||||||
|
// Library consumers
|
||||||
|
collection.AddScoped<IEventConsumer<SubtitleDownloadFailureEventArgs>, SubtitleDownloadFailureLogger>();
|
||||||
|
|
||||||
|
// Security consumers
|
||||||
|
collection.AddScoped<IEventConsumer<GenericEventArgs<AuthenticationRequest>>, AuthenticationFailedLogger>();
|
||||||
|
collection.AddScoped<IEventConsumer<GenericEventArgs<AuthenticationResult>>, AuthenticationSucceededLogger>();
|
||||||
|
|
||||||
|
// Session consumers
|
||||||
|
collection.AddScoped<IEventConsumer<PlaybackStartEventArgs>, PlaybackStartLogger>();
|
||||||
|
collection.AddScoped<IEventConsumer<PlaybackStopEventArgs>, PlaybackStopLogger>();
|
||||||
|
collection.AddScoped<IEventConsumer<SessionEndedEventArgs>, SessionEndedLogger>();
|
||||||
|
collection.AddScoped<IEventConsumer<SessionStartedEventArgs>, SessionStartedLogger>();
|
||||||
|
|
||||||
|
// System consumers
|
||||||
|
collection.AddScoped<IEventConsumer<PendingRestartEventArgs>, PendingRestartNotifier>();
|
||||||
|
collection.AddScoped<IEventConsumer<TaskCompletionEventArgs>, TaskCompletedLogger>();
|
||||||
|
collection.AddScoped<IEventConsumer<TaskCompletionEventArgs>, TaskCompletedNotifier>();
|
||||||
|
|
||||||
|
// Update consumers
|
||||||
|
collection.AddScoped<IEventConsumer<PluginInstallationCancelledEventArgs>, PluginInstallationCancelledNotifier>();
|
||||||
|
collection.AddScoped<IEventConsumer<InstallationFailedEventArgs>, PluginInstallationFailedLogger>();
|
||||||
|
collection.AddScoped<IEventConsumer<InstallationFailedEventArgs>, PluginInstallationFailedNotifier>();
|
||||||
|
collection.AddScoped<IEventConsumer<PluginInstalledEventArgs>, PluginInstalledLogger>();
|
||||||
|
collection.AddScoped<IEventConsumer<PluginInstalledEventArgs>, PluginInstalledNotifier>();
|
||||||
|
collection.AddScoped<IEventConsumer<PluginInstallingEventArgs>, PluginInstallingNotifier>();
|
||||||
|
collection.AddScoped<IEventConsumer<PluginUninstalledEventArgs>, PluginUninstalledLogger>();
|
||||||
|
collection.AddScoped<IEventConsumer<PluginUninstalledEventArgs>, PluginUninstalledNotifier>();
|
||||||
|
collection.AddScoped<IEventConsumer<PluginUpdatedEventArgs>, PluginUpdatedLogger>();
|
||||||
|
|
||||||
|
// User consumers
|
||||||
|
collection.AddScoped<IEventConsumer<UserCreatedEventArgs>, UserCreatedLogger>();
|
||||||
|
collection.AddScoped<IEventConsumer<UserDeletedEventArgs>, UserDeletedLogger>();
|
||||||
|
collection.AddScoped<IEventConsumer<UserDeletedEventArgs>, UserDeletedNotifier>();
|
||||||
|
collection.AddScoped<IEventConsumer<UserLockedOutEventArgs>, UserLockedOutLogger>();
|
||||||
|
collection.AddScoped<IEventConsumer<UserPasswordChangedEventArgs>, UserPasswordChangedLogger>();
|
||||||
|
collection.AddScoped<IEventConsumer<UserUpdatedEventArgs>, UserUpdatedNotifier>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,12 +4,12 @@
|
||||||
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.Controller.Devices;
|
using MediaBrowser.Controller.Devices;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
using MediaBrowser.Controller.Plugins;
|
using MediaBrowser.Controller.Plugins;
|
||||||
using MediaBrowser.Controller.Security;
|
using MediaBrowser.Controller.Security;
|
||||||
using MediaBrowser.Controller.Session;
|
using MediaBrowser.Controller.Session;
|
||||||
using MediaBrowser.Model.Events;
|
|
||||||
|
|
||||||
namespace Jellyfin.Server.Implementations.Users
|
namespace Jellyfin.Server.Implementations.Users
|
||||||
{
|
{
|
||||||
|
|
|
@ -10,18 +10,20 @@ using System.Text.RegularExpressions;
|
||||||
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 Jellyfin.Data.Events.Users;
|
||||||
using MediaBrowser.Common;
|
using MediaBrowser.Common;
|
||||||
using MediaBrowser.Common.Cryptography;
|
using MediaBrowser.Common.Cryptography;
|
||||||
using MediaBrowser.Common.Extensions;
|
using MediaBrowser.Common.Extensions;
|
||||||
using MediaBrowser.Common.Net;
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Controller.Authentication;
|
using MediaBrowser.Controller.Authentication;
|
||||||
using MediaBrowser.Controller.Drawing;
|
using MediaBrowser.Controller.Drawing;
|
||||||
|
using MediaBrowser.Controller.Events;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
using MediaBrowser.Controller.Net;
|
using MediaBrowser.Controller.Net;
|
||||||
using MediaBrowser.Model.Configuration;
|
using MediaBrowser.Model.Configuration;
|
||||||
using MediaBrowser.Model.Cryptography;
|
using MediaBrowser.Model.Cryptography;
|
||||||
using MediaBrowser.Model.Dto;
|
using MediaBrowser.Model.Dto;
|
||||||
using MediaBrowser.Model.Events;
|
|
||||||
using MediaBrowser.Model.Users;
|
using MediaBrowser.Model.Users;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
@ -34,6 +36,7 @@ namespace Jellyfin.Server.Implementations.Users
|
||||||
public class UserManager : IUserManager
|
public class UserManager : IUserManager
|
||||||
{
|
{
|
||||||
private readonly JellyfinDbProvider _dbProvider;
|
private readonly JellyfinDbProvider _dbProvider;
|
||||||
|
private readonly IEventManager _eventManager;
|
||||||
private readonly ICryptoProvider _cryptoProvider;
|
private readonly ICryptoProvider _cryptoProvider;
|
||||||
private readonly INetworkManager _networkManager;
|
private readonly INetworkManager _networkManager;
|
||||||
private readonly IApplicationHost _appHost;
|
private readonly IApplicationHost _appHost;
|
||||||
|
@ -49,6 +52,7 @@ namespace Jellyfin.Server.Implementations.Users
|
||||||
/// Initializes a new instance of the <see cref="UserManager"/> class.
|
/// Initializes a new instance of the <see cref="UserManager"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="dbProvider">The database provider.</param>
|
/// <param name="dbProvider">The database provider.</param>
|
||||||
|
/// <param name="eventManager">The event manager.</param>
|
||||||
/// <param name="cryptoProvider">The cryptography provider.</param>
|
/// <param name="cryptoProvider">The cryptography provider.</param>
|
||||||
/// <param name="networkManager">The network manager.</param>
|
/// <param name="networkManager">The network manager.</param>
|
||||||
/// <param name="appHost">The application host.</param>
|
/// <param name="appHost">The application host.</param>
|
||||||
|
@ -56,6 +60,7 @@ namespace Jellyfin.Server.Implementations.Users
|
||||||
/// <param name="logger">The logger.</param>
|
/// <param name="logger">The logger.</param>
|
||||||
public UserManager(
|
public UserManager(
|
||||||
JellyfinDbProvider dbProvider,
|
JellyfinDbProvider dbProvider,
|
||||||
|
IEventManager eventManager,
|
||||||
ICryptoProvider cryptoProvider,
|
ICryptoProvider cryptoProvider,
|
||||||
INetworkManager networkManager,
|
INetworkManager networkManager,
|
||||||
IApplicationHost appHost,
|
IApplicationHost appHost,
|
||||||
|
@ -63,6 +68,7 @@ namespace Jellyfin.Server.Implementations.Users
|
||||||
ILogger<UserManager> logger)
|
ILogger<UserManager> logger)
|
||||||
{
|
{
|
||||||
_dbProvider = dbProvider;
|
_dbProvider = dbProvider;
|
||||||
|
_eventManager = eventManager;
|
||||||
_cryptoProvider = cryptoProvider;
|
_cryptoProvider = cryptoProvider;
|
||||||
_networkManager = networkManager;
|
_networkManager = networkManager;
|
||||||
_appHost = appHost;
|
_appHost = appHost;
|
||||||
|
@ -77,21 +83,9 @@ namespace Jellyfin.Server.Implementations.Users
|
||||||
_defaultPasswordResetProvider = _passwordResetProviders.OfType<DefaultPasswordResetProvider>().First();
|
_defaultPasswordResetProvider = _passwordResetProviders.OfType<DefaultPasswordResetProvider>().First();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public event EventHandler<GenericEventArgs<User>>? OnUserPasswordChanged;
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public event EventHandler<GenericEventArgs<User>>? OnUserUpdated;
|
public event EventHandler<GenericEventArgs<User>>? OnUserUpdated;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public event EventHandler<GenericEventArgs<User>>? OnUserCreated;
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public event EventHandler<GenericEventArgs<User>>? OnUserDeleted;
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public event EventHandler<GenericEventArgs<User>>? OnUserLockedOut;
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public IEnumerable<User> Users
|
public IEnumerable<User> Users
|
||||||
{
|
{
|
||||||
|
@ -234,7 +228,7 @@ namespace Jellyfin.Server.Implementations.Users
|
||||||
dbContext.Users.Add(newUser);
|
dbContext.Users.Add(newUser);
|
||||||
await dbContext.SaveChangesAsync().ConfigureAwait(false);
|
await dbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
OnUserCreated?.Invoke(this, new GenericEventArgs<User>(newUser));
|
await _eventManager.PublishAsync(new UserCreatedEventArgs(newUser)).ConfigureAwait(false);
|
||||||
|
|
||||||
return newUser;
|
return newUser;
|
||||||
}
|
}
|
||||||
|
@ -293,7 +287,8 @@ namespace Jellyfin.Server.Implementations.Users
|
||||||
dbContext.RemoveRange(user.AccessSchedules);
|
dbContext.RemoveRange(user.AccessSchedules);
|
||||||
dbContext.Users.Remove(user);
|
dbContext.Users.Remove(user);
|
||||||
dbContext.SaveChanges();
|
dbContext.SaveChanges();
|
||||||
OnUserDeleted?.Invoke(this, new GenericEventArgs<User>(user));
|
|
||||||
|
_eventManager.Publish(new UserDeletedEventArgs(user));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
|
@ -319,7 +314,7 @@ namespace Jellyfin.Server.Implementations.Users
|
||||||
await GetAuthenticationProvider(user).ChangePassword(user, newPassword).ConfigureAwait(false);
|
await GetAuthenticationProvider(user).ChangePassword(user, newPassword).ConfigureAwait(false);
|
||||||
await UpdateUserAsync(user).ConfigureAwait(false);
|
await UpdateUserAsync(user).ConfigureAwait(false);
|
||||||
|
|
||||||
OnUserPasswordChanged?.Invoke(this, new GenericEventArgs<User>(user));
|
await _eventManager.PublishAsync(new UserPasswordChangedEventArgs(user)).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
|
@ -338,7 +333,7 @@ namespace Jellyfin.Server.Implementations.Users
|
||||||
user.EasyPassword = newPasswordSha1;
|
user.EasyPassword = newPasswordSha1;
|
||||||
UpdateUser(user);
|
UpdateUser(user);
|
||||||
|
|
||||||
OnUserPasswordChanged?.Invoke(this, new GenericEventArgs<User>(user));
|
_eventManager.Publish(new UserPasswordChangedEventArgs(user));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
|
@ -901,7 +896,7 @@ namespace Jellyfin.Server.Implementations.Users
|
||||||
if (maxInvalidLogins.HasValue && user.InvalidLoginAttemptCount >= maxInvalidLogins)
|
if (maxInvalidLogins.HasValue && user.InvalidLoginAttemptCount >= maxInvalidLogins)
|
||||||
{
|
{
|
||||||
user.SetPermission(PermissionKind.IsDisabled, true);
|
user.SetPermission(PermissionKind.IsDisabled, true);
|
||||||
OnUserLockedOut?.Invoke(this, new GenericEventArgs<User>(user));
|
await _eventManager.PublishAsync(new UserLockedOutEventArgs(user)).ConfigureAwait(false);
|
||||||
_logger.LogWarning(
|
_logger.LogWarning(
|
||||||
"Disabling user {Username} due to {Attempts} unsuccessful login attempts.",
|
"Disabling user {Username} due to {Attempts} unsuccessful login attempts.",
|
||||||
user.Username,
|
user.Username,
|
||||||
|
|
|
@ -1,20 +1,20 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Emby.Drawing;
|
using Emby.Drawing;
|
||||||
using Emby.Server.Implementations;
|
using Emby.Server.Implementations;
|
||||||
using Jellyfin.Drawing.Skia;
|
using Jellyfin.Drawing.Skia;
|
||||||
using Jellyfin.Server.Implementations;
|
using Jellyfin.Server.Implementations;
|
||||||
using Jellyfin.Server.Implementations.Activity;
|
using Jellyfin.Server.Implementations.Activity;
|
||||||
|
using Jellyfin.Server.Implementations.Events;
|
||||||
using Jellyfin.Server.Implementations.Users;
|
using Jellyfin.Server.Implementations.Users;
|
||||||
using MediaBrowser.Common.Net;
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Controller;
|
using MediaBrowser.Controller;
|
||||||
using MediaBrowser.Controller.Drawing;
|
using MediaBrowser.Controller.Drawing;
|
||||||
|
using MediaBrowser.Controller.Events;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
using MediaBrowser.Model.Activity;
|
using MediaBrowser.Model.Activity;
|
||||||
using MediaBrowser.Model.IO;
|
using MediaBrowser.Model.IO;
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
@ -33,30 +33,33 @@ namespace Jellyfin.Server
|
||||||
/// <param name="options">The <see cref="StartupOptions" /> to be used by the <see cref="CoreAppHost" />.</param>
|
/// <param name="options">The <see cref="StartupOptions" /> to be used by the <see cref="CoreAppHost" />.</param>
|
||||||
/// <param name="fileSystem">The <see cref="IFileSystem" /> to be used by the <see cref="CoreAppHost" />.</param>
|
/// <param name="fileSystem">The <see cref="IFileSystem" /> to be used by the <see cref="CoreAppHost" />.</param>
|
||||||
/// <param name="networkManager">The <see cref="INetworkManager" /> to be used by the <see cref="CoreAppHost" />.</param>
|
/// <param name="networkManager">The <see cref="INetworkManager" /> to be used by the <see cref="CoreAppHost" />.</param>
|
||||||
|
/// <param name="collection">The <see cref="IServiceCollection"/> to be used by the <see cref="CoreAppHost"/>.</param>
|
||||||
public CoreAppHost(
|
public CoreAppHost(
|
||||||
IServerApplicationPaths applicationPaths,
|
IServerApplicationPaths applicationPaths,
|
||||||
ILoggerFactory loggerFactory,
|
ILoggerFactory loggerFactory,
|
||||||
IStartupOptions options,
|
IStartupOptions options,
|
||||||
IFileSystem fileSystem,
|
IFileSystem fileSystem,
|
||||||
INetworkManager networkManager)
|
INetworkManager networkManager,
|
||||||
|
IServiceCollection collection)
|
||||||
: base(
|
: base(
|
||||||
applicationPaths,
|
applicationPaths,
|
||||||
loggerFactory,
|
loggerFactory,
|
||||||
options,
|
options,
|
||||||
fileSystem,
|
fileSystem,
|
||||||
networkManager)
|
networkManager,
|
||||||
|
collection)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
protected override void RegisterServices(IServiceCollection serviceCollection)
|
protected override void RegisterServices()
|
||||||
{
|
{
|
||||||
// Register an image encoder
|
// Register an image encoder
|
||||||
bool useSkiaEncoder = SkiaEncoder.IsNativeLibAvailable();
|
bool useSkiaEncoder = SkiaEncoder.IsNativeLibAvailable();
|
||||||
Type imageEncoderType = useSkiaEncoder
|
Type imageEncoderType = useSkiaEncoder
|
||||||
? typeof(SkiaEncoder)
|
? typeof(SkiaEncoder)
|
||||||
: typeof(NullImageEncoder);
|
: typeof(NullImageEncoder);
|
||||||
serviceCollection.AddSingleton(typeof(IImageEncoder), imageEncoderType);
|
ServiceCollection.AddSingleton(typeof(IImageEncoder), imageEncoderType);
|
||||||
|
|
||||||
// Log a warning if the Skia encoder could not be used
|
// Log a warning if the Skia encoder could not be used
|
||||||
if (!useSkiaEncoder)
|
if (!useSkiaEncoder)
|
||||||
|
@ -71,13 +74,15 @@ namespace Jellyfin.Server
|
||||||
// .UseSqlite($"Filename={Path.Combine(ApplicationPaths.DataPath, "jellyfin.db")}"),
|
// .UseSqlite($"Filename={Path.Combine(ApplicationPaths.DataPath, "jellyfin.db")}"),
|
||||||
// ServiceLifetime.Transient);
|
// ServiceLifetime.Transient);
|
||||||
|
|
||||||
serviceCollection.AddSingleton<JellyfinDbProvider>();
|
ServiceCollection.AddEventServices();
|
||||||
|
ServiceCollection.AddSingleton<IEventManager, EventManager>();
|
||||||
|
ServiceCollection.AddSingleton<JellyfinDbProvider>();
|
||||||
|
|
||||||
serviceCollection.AddSingleton<IActivityManager, ActivityManager>();
|
ServiceCollection.AddSingleton<IActivityManager, ActivityManager>();
|
||||||
serviceCollection.AddSingleton<IUserManager, UserManager>();
|
ServiceCollection.AddSingleton<IUserManager, UserManager>();
|
||||||
serviceCollection.AddSingleton<IDisplayPreferencesManager, DisplayPreferencesManager>();
|
ServiceCollection.AddSingleton<IDisplayPreferencesManager, DisplayPreferencesManager>();
|
||||||
|
|
||||||
base.RegisterServices(serviceCollection);
|
base.RegisterServices();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|
|
@ -154,13 +154,15 @@ namespace Jellyfin.Server
|
||||||
ApplicationHost.LogEnvironmentInfo(_logger, appPaths);
|
ApplicationHost.LogEnvironmentInfo(_logger, appPaths);
|
||||||
|
|
||||||
PerformStaticInitialization();
|
PerformStaticInitialization();
|
||||||
|
var serviceCollection = new ServiceCollection();
|
||||||
|
|
||||||
var appHost = new CoreAppHost(
|
var appHost = new CoreAppHost(
|
||||||
appPaths,
|
appPaths,
|
||||||
_loggerFactory,
|
_loggerFactory,
|
||||||
options,
|
options,
|
||||||
new ManagedFileSystem(_loggerFactory.CreateLogger<ManagedFileSystem>(), appPaths),
|
new ManagedFileSystem(_loggerFactory.CreateLogger<ManagedFileSystem>(), appPaths),
|
||||||
new NetworkManager(_loggerFactory.CreateLogger<NetworkManager>()));
|
new NetworkManager(_loggerFactory.CreateLogger<NetworkManager>()),
|
||||||
|
serviceCollection);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -178,8 +180,7 @@ namespace Jellyfin.Server
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ServiceCollection serviceCollection = new ServiceCollection();
|
appHost.Init();
|
||||||
appHost.Init(serviceCollection);
|
|
||||||
|
|
||||||
var webHost = new WebHostBuilder().ConfigureWebHostBuilder(appHost, serviceCollection, options, startupConfig, appPaths).Build();
|
var webHost = new WebHostBuilder().ConfigureWebHostBuilder(appHost, serviceCollection, options, startupConfig, appPaths).Build();
|
||||||
|
|
||||||
|
|
|
@ -116,8 +116,7 @@ namespace MediaBrowser.Common
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes this instance.
|
/// Initializes this instance.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="serviceCollection">The service collection.</param>
|
void Init();
|
||||||
void Init(IServiceCollection serviceCollection);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates the instance.
|
/// Creates the instance.
|
||||||
|
|
|
@ -6,6 +6,7 @@ using System.Reflection;
|
||||||
using MediaBrowser.Common.Configuration;
|
using MediaBrowser.Common.Configuration;
|
||||||
using MediaBrowser.Model.Plugins;
|
using MediaBrowser.Model.Plugins;
|
||||||
using MediaBrowser.Model.Serialization;
|
using MediaBrowser.Model.Serialization;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
namespace MediaBrowser.Common.Plugins
|
namespace MediaBrowser.Common.Plugins
|
||||||
{
|
{
|
||||||
|
@ -81,6 +82,16 @@ namespace MediaBrowser.Common.Plugins
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public virtual void RegisterServices(IServiceCollection serviceCollection)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public virtual void UnregisterServices(IServiceCollection serviceCollection)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void SetAttributes(string assemblyFilePath, string dataFolderPath, Version assemblyVersion)
|
public void SetAttributes(string assemblyFilePath, string dataFolderPath, Version assemblyVersion)
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using MediaBrowser.Model.Plugins;
|
using MediaBrowser.Model.Plugins;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
namespace MediaBrowser.Common.Plugins
|
namespace MediaBrowser.Common.Plugins
|
||||||
{
|
{
|
||||||
|
@ -61,6 +62,18 @@ namespace MediaBrowser.Common.Plugins
|
||||||
/// Called when just before the plugin is uninstalled from the server.
|
/// Called when just before the plugin is uninstalled from the server.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void OnUninstalling();
|
void OnUninstalling();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Registers the plugin's services to the service collection.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="serviceCollection">The service collection.</param>
|
||||||
|
void RegisterServices(IServiceCollection serviceCollection);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unregisters the plugin's services from the service collection.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="serviceCollection">The service collection.</param>
|
||||||
|
void UnregisterServices(IServiceCollection serviceCollection);
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IHasPluginConfiguration
|
public interface IHasPluginConfiguration
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
|
using System;
|
||||||
using MediaBrowser.Model.Updates;
|
using MediaBrowser.Model.Updates;
|
||||||
|
|
||||||
namespace MediaBrowser.Common.Updates
|
namespace MediaBrowser.Common.Updates
|
||||||
{
|
{
|
||||||
public class InstallationEventArgs
|
public class InstallationEventArgs : EventArgs
|
||||||
{
|
{
|
||||||
public InstallationInfo InstallationInfo { get; set; }
|
public InstallationInfo InstallationInfo { get; set; }
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using Jellyfin.Data.Entities;
|
using Jellyfin.Data.Entities;
|
||||||
|
using Jellyfin.Data.Events;
|
||||||
using MediaBrowser.Model.Devices;
|
using MediaBrowser.Model.Devices;
|
||||||
using MediaBrowser.Model.Events;
|
|
||||||
using MediaBrowser.Model.Querying;
|
using MediaBrowser.Model.Querying;
|
||||||
using MediaBrowser.Model.Session;
|
using MediaBrowser.Model.Session;
|
||||||
|
|
||||||
|
|
20
MediaBrowser.Controller/Events/IEventConsumer.cs
Normal file
20
MediaBrowser.Controller/Events/IEventConsumer.cs
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Controller.Events
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An interface representing a type that consumes events of type <c>T</c>.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">The type of events this consumes.</typeparam>
|
||||||
|
public interface IEventConsumer<in T>
|
||||||
|
where T : EventArgs
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A method that is called when an event of type <c>T</c> is fired.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="eventArgs">The event.</param>
|
||||||
|
/// <returns>A task representing the consumption of the event.</returns>
|
||||||
|
Task OnEvent(T eventArgs);
|
||||||
|
}
|
||||||
|
}
|
28
MediaBrowser.Controller/Events/IEventManager.cs
Normal file
28
MediaBrowser.Controller/Events/IEventManager.cs
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Controller.Events
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An interface that handles eventing.
|
||||||
|
/// </summary>
|
||||||
|
public interface IEventManager
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Publishes an event.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="eventArgs">the event arguments.</param>
|
||||||
|
/// <typeparam name="T">The type of event.</typeparam>
|
||||||
|
void Publish<T>(T eventArgs)
|
||||||
|
where T : EventArgs;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Publishes an event asynchronously.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="eventArgs">The event arguments.</param>
|
||||||
|
/// <typeparam name="T">The type of event.</typeparam>
|
||||||
|
/// <returns>A task representing the publishing of the event.</returns>
|
||||||
|
Task PublishAsync<T>(T eventArgs)
|
||||||
|
where T : EventArgs;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
using Jellyfin.Data.Events;
|
||||||
|
using MediaBrowser.Controller.Session;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Controller.Events.Session
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An event that fires when a session is ended.
|
||||||
|
/// </summary>
|
||||||
|
public class SessionEndedEventArgs : GenericEventArgs<SessionInfo>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="SessionEndedEventArgs"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="arg">The session info.</param>
|
||||||
|
public SessionEndedEventArgs(SessionInfo arg) : base(arg)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
using Jellyfin.Data.Events;
|
||||||
|
using MediaBrowser.Controller.Session;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Controller.Events.Session
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An event that fires when a session is started.
|
||||||
|
/// </summary>
|
||||||
|
public class SessionStartedEventArgs : GenericEventArgs<SessionInfo>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="SessionStartedEventArgs"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="arg">The session info.</param>
|
||||||
|
public SessionStartedEventArgs(SessionInfo arg) : base(arg)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
using Jellyfin.Data.Events;
|
||||||
|
using MediaBrowser.Model.Updates;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Controller.Events.Updates
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An event that occurs when a plugin installation is cancelled.
|
||||||
|
/// </summary>
|
||||||
|
public class PluginInstallationCancelledEventArgs : GenericEventArgs<InstallationInfo>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="PluginInstallationCancelledEventArgs"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="arg">The installation info.</param>
|
||||||
|
public PluginInstallationCancelledEventArgs(InstallationInfo arg) : base(arg)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
using Jellyfin.Data.Events;
|
||||||
|
using MediaBrowser.Model.Updates;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Controller.Events.Updates
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An event that occurs when a plugin is installed.
|
||||||
|
/// </summary>
|
||||||
|
public class PluginInstalledEventArgs : GenericEventArgs<InstallationInfo>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="PluginInstalledEventArgs"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="arg">The installation info.</param>
|
||||||
|
public PluginInstalledEventArgs(InstallationInfo arg) : base(arg)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
using Jellyfin.Data.Events;
|
||||||
|
using MediaBrowser.Model.Updates;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Controller.Events.Updates
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An event that occurs when a plugin is installing.
|
||||||
|
/// </summary>
|
||||||
|
public class PluginInstallingEventArgs : GenericEventArgs<InstallationInfo>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="PluginInstallingEventArgs"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="arg">The installation info.</param>
|
||||||
|
public PluginInstallingEventArgs(InstallationInfo arg) : base(arg)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
using Jellyfin.Data.Events;
|
||||||
|
using MediaBrowser.Common.Plugins;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Controller.Events.Updates
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An event that occurs when a plugin is uninstalled.
|
||||||
|
/// </summary>
|
||||||
|
public class PluginUninstalledEventArgs : GenericEventArgs<IPlugin>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="PluginUninstalledEventArgs"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="arg">The plugin.</param>
|
||||||
|
public PluginUninstalledEventArgs(IPlugin arg) : base(arg)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
using Jellyfin.Data.Events;
|
||||||
|
using MediaBrowser.Model.Updates;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Controller.Events.Updates
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An event that occurs when a plugin is updated.
|
||||||
|
/// </summary>
|
||||||
|
public class PluginUpdatedEventArgs : GenericEventArgs<InstallationInfo>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="PluginUpdatedEventArgs"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="arg">The installation info.</param>
|
||||||
|
public PluginUpdatedEventArgs(InstallationInfo arg) : base(arg)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,13 +18,7 @@ namespace MediaBrowser.Controller
|
||||||
{
|
{
|
||||||
event EventHandler HasUpdateAvailableChanged;
|
event EventHandler HasUpdateAvailableChanged;
|
||||||
|
|
||||||
/// <summary>
|
IServiceProvider ServiceProvider { get; }
|
||||||
/// Gets the system info.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>SystemInfo.</returns>
|
|
||||||
Task<SystemInfo> GetSystemInfo(CancellationToken cancellationToken);
|
|
||||||
|
|
||||||
Task<PublicSystemInfo> GetPublicSystemInfo(CancellationToken cancellationToken);
|
|
||||||
|
|
||||||
bool CanLaunchWebBrowser { get; }
|
bool CanLaunchWebBrowser { get; }
|
||||||
|
|
||||||
|
@ -57,6 +51,14 @@ namespace MediaBrowser.Controller
|
||||||
/// <value>The name of the friendly.</value>
|
/// <value>The name of the friendly.</value>
|
||||||
string FriendlyName { get; }
|
string FriendlyName { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the system info.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>SystemInfo.</returns>
|
||||||
|
Task<SystemInfo> GetSystemInfo(CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
Task<PublicSystemInfo> GetPublicSystemInfo(CancellationToken cancellationToken);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets all the local IP addresses of this API instance. Each address is validated by sending a 'ping' request
|
/// Gets all the local IP addresses of this API instance. Each address is validated by sending a 'ping' request
|
||||||
/// to the API that should exist at the address.
|
/// to the API that should exist at the address.
|
||||||
|
|
|
@ -4,9 +4,9 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Jellyfin.Data.Entities;
|
using Jellyfin.Data.Entities;
|
||||||
|
using Jellyfin.Data.Events;
|
||||||
using MediaBrowser.Model.Configuration;
|
using MediaBrowser.Model.Configuration;
|
||||||
using MediaBrowser.Model.Dto;
|
using MediaBrowser.Model.Dto;
|
||||||
using MediaBrowser.Model.Events;
|
|
||||||
using MediaBrowser.Model.Users;
|
using MediaBrowser.Model.Users;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Library
|
namespace MediaBrowser.Controller.Library
|
||||||
|
@ -21,26 +21,6 @@ namespace MediaBrowser.Controller.Library
|
||||||
/// </summary>
|
/// </summary>
|
||||||
event EventHandler<GenericEventArgs<User>> OnUserUpdated;
|
event EventHandler<GenericEventArgs<User>> OnUserUpdated;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Occurs when a user is created.
|
|
||||||
/// </summary>
|
|
||||||
event EventHandler<GenericEventArgs<User>> OnUserCreated;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Occurs when a user is deleted.
|
|
||||||
/// </summary>
|
|
||||||
event EventHandler<GenericEventArgs<User>> OnUserDeleted;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Occurs when a user's password is changed.
|
|
||||||
/// </summary>
|
|
||||||
event EventHandler<GenericEventArgs<User>> OnUserPasswordChanged;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Occurs when a user is locked out.
|
|
||||||
/// </summary>
|
|
||||||
event EventHandler<GenericEventArgs<User>> OnUserLockedOut;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the users.
|
/// Gets the users.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
namespace MediaBrowser.Controller.Library
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An event that occurs when playback is started.
|
||||||
|
/// </summary>
|
||||||
|
public class PlaybackStartEventArgs : PlaybackProgressEventArgs
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,11 +5,11 @@ using System.Collections.Generic;
|
||||||
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.Dto;
|
using MediaBrowser.Controller.Dto;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
using MediaBrowser.Model.Dto;
|
using MediaBrowser.Model.Dto;
|
||||||
using MediaBrowser.Model.Events;
|
|
||||||
using MediaBrowser.Model.LiveTv;
|
using MediaBrowser.Model.LiveTv;
|
||||||
using MediaBrowser.Model.Querying;
|
using MediaBrowser.Model.Querying;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Model.Events;
|
using Jellyfin.Data.Events;
|
||||||
using MediaBrowser.Model.Services;
|
using MediaBrowser.Model.Services;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
|
|
||||||
|
|
|
@ -7,12 +7,12 @@ using System.Net.Http;
|
||||||
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.Common.Net;
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
using MediaBrowser.Model.Configuration;
|
using MediaBrowser.Model.Configuration;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
using MediaBrowser.Model.Events;
|
|
||||||
using MediaBrowser.Model.Providers;
|
using MediaBrowser.Model.Providers;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Providers
|
namespace MediaBrowser.Controller.Providers
|
||||||
|
|
|
@ -4,11 +4,11 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Jellyfin.Data.Events;
|
||||||
using MediaBrowser.Controller.Authentication;
|
using MediaBrowser.Controller.Authentication;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
using MediaBrowser.Controller.Security;
|
using MediaBrowser.Controller.Security;
|
||||||
using MediaBrowser.Model.Dto;
|
using MediaBrowser.Model.Dto;
|
||||||
using MediaBrowser.Model.Events;
|
|
||||||
using MediaBrowser.Model.Session;
|
using MediaBrowser.Model.Session;
|
||||||
using MediaBrowser.Model.SyncPlay;
|
using MediaBrowser.Model.SyncPlay;
|
||||||
|
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
#pragma warning disable CS1591
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using MediaBrowser.Controller.Entities;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Subtitles
|
|
||||||
{
|
|
||||||
public class SubtitleDownloadEventArgs
|
|
||||||
{
|
|
||||||
public BaseItem Item { get; set; }
|
|
||||||
|
|
||||||
public string Format { get; set; }
|
|
||||||
|
|
||||||
public string Language { get; set; }
|
|
||||||
|
|
||||||
public bool IsForced { get; set; }
|
|
||||||
|
|
||||||
public string Provider { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class SubtitleDownloadFailureEventArgs
|
|
||||||
{
|
|
||||||
public BaseItem Item { get; set; }
|
|
||||||
|
|
||||||
public string Provider { get; set; }
|
|
||||||
|
|
||||||
public Exception Exception { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
using System;
|
||||||
|
using MediaBrowser.Controller.Entities;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Controller.Subtitles
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An event that occurs when subtitle downloading fails.
|
||||||
|
/// </summary>
|
||||||
|
public class SubtitleDownloadFailureEventArgs : EventArgs
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the item.
|
||||||
|
/// </summary>
|
||||||
|
public BaseItem Item { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the provider.
|
||||||
|
/// </summary>
|
||||||
|
public string Provider { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the exception.
|
||||||
|
/// </summary>
|
||||||
|
public Exception Exception { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,7 +4,7 @@ using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Jellyfin.Data.Entities;
|
using Jellyfin.Data.Entities;
|
||||||
using MediaBrowser.Model.Events;
|
using Jellyfin.Data.Events;
|
||||||
using MediaBrowser.Model.Querying;
|
using MediaBrowser.Model.Querying;
|
||||||
|
|
||||||
namespace MediaBrowser.Model.Activity
|
namespace MediaBrowser.Model.Activity
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using MediaBrowser.Model.Events;
|
using Jellyfin.Data.Events;
|
||||||
|
|
||||||
namespace MediaBrowser.Model.Dlna
|
namespace MediaBrowser.Model.Dlna
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#nullable disable
|
#nullable disable
|
||||||
using System;
|
using System;
|
||||||
using MediaBrowser.Model.Events;
|
using Jellyfin.Data.Events;
|
||||||
|
|
||||||
namespace MediaBrowser.Model.Tasks
|
namespace MediaBrowser.Model.Tasks
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Model.Events;
|
using Jellyfin.Data.Events;
|
||||||
|
|
||||||
namespace MediaBrowser.Model.Tasks
|
namespace MediaBrowser.Model.Tasks
|
||||||
{
|
{
|
||||||
|
|
|
@ -10,6 +10,7 @@ using System.Net.Mime;
|
||||||
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.Common.Net;
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Common.Progress;
|
using MediaBrowser.Common.Progress;
|
||||||
using MediaBrowser.Controller;
|
using MediaBrowser.Controller;
|
||||||
|
@ -23,7 +24,6 @@ using MediaBrowser.Controller.Providers;
|
||||||
using MediaBrowser.Controller.Subtitles;
|
using MediaBrowser.Controller.Subtitles;
|
||||||
using MediaBrowser.Model.Configuration;
|
using MediaBrowser.Model.Configuration;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
using MediaBrowser.Model.Events;
|
|
||||||
using MediaBrowser.Model.IO;
|
using MediaBrowser.Model.IO;
|
||||||
using MediaBrowser.Model.Net;
|
using MediaBrowser.Model.Net;
|
||||||
using MediaBrowser.Model.Providers;
|
using MediaBrowser.Model.Providers;
|
||||||
|
|
|
@ -72,6 +72,7 @@ namespace MediaBrowser.Api.Tests
|
||||||
var startupConfig = Program.CreateAppConfiguration(commandLineOpts, appPaths);
|
var startupConfig = Program.CreateAppConfiguration(commandLineOpts, appPaths);
|
||||||
|
|
||||||
ILoggerFactory loggerFactory = new SerilogLoggerFactory();
|
ILoggerFactory loggerFactory = new SerilogLoggerFactory();
|
||||||
|
var serviceCollection = new ServiceCollection();
|
||||||
_disposableComponents.Add(loggerFactory);
|
_disposableComponents.Add(loggerFactory);
|
||||||
|
|
||||||
// Create the app host and initialize it
|
// Create the app host and initialize it
|
||||||
|
@ -80,10 +81,10 @@ namespace MediaBrowser.Api.Tests
|
||||||
loggerFactory,
|
loggerFactory,
|
||||||
commandLineOpts,
|
commandLineOpts,
|
||||||
new ManagedFileSystem(loggerFactory.CreateLogger<ManagedFileSystem>(), appPaths),
|
new ManagedFileSystem(loggerFactory.CreateLogger<ManagedFileSystem>(), appPaths),
|
||||||
new NetworkManager(loggerFactory.CreateLogger<NetworkManager>()));
|
new NetworkManager(loggerFactory.CreateLogger<NetworkManager>()),
|
||||||
|
serviceCollection);
|
||||||
_disposableComponents.Add(appHost);
|
_disposableComponents.Add(appHost);
|
||||||
var serviceCollection = new ServiceCollection();
|
appHost.Init();
|
||||||
appHost.Init(serviceCollection);
|
|
||||||
|
|
||||||
// Configure the web host builder
|
// Configure the web host builder
|
||||||
Program.ConfigureWebHostBuilder(builder, appHost, serviceCollection, commandLineOpts, startupConfig, appPaths);
|
Program.ConfigureWebHostBuilder(builder, appHost, serviceCollection, commandLineOpts, startupConfig, appPaths);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user