|
@@ -4,11 +4,10 @@ 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.Devices;
|
|
|
-using MediaBrowser.Controller.Entities;
|
|
|
using MediaBrowser.Controller.Library;
|
|
|
using MediaBrowser.Controller.Plugins;
|
|
|
using MediaBrowser.Controller.Session;
|
|
@@ -30,7 +29,7 @@ namespace Emby.Server.Implementations.Activity
|
|
|
/// </summary>
|
|
|
public sealed class ActivityLogEntryPoint : IServerEntryPoint
|
|
|
{
|
|
|
- private readonly ILogger _logger;
|
|
|
+ private readonly ILogger<ActivityLogEntryPoint> _logger;
|
|
|
private readonly IInstallationManager _installationManager;
|
|
|
private readonly ISessionManager _sessionManager;
|
|
|
private readonly ITaskManager _taskManager;
|
|
@@ -38,14 +37,12 @@ namespace Emby.Server.Implementations.Activity
|
|
|
private readonly ILocalizationManager _localization;
|
|
|
private readonly ISubtitleManager _subManager;
|
|
|
private readonly IUserManager _userManager;
|
|
|
- private readonly IDeviceManager _deviceManager;
|
|
|
|
|
|
/// <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="deviceManager">The device manager.</param>
|
|
|
/// <param name="taskManager">The task manager.</param>
|
|
|
/// <param name="activityManager">The activity manager.</param>
|
|
|
/// <param name="localization">The localization manager.</param>
|
|
@@ -55,7 +52,6 @@ namespace Emby.Server.Implementations.Activity
|
|
|
public ActivityLogEntryPoint(
|
|
|
ILogger<ActivityLogEntryPoint> logger,
|
|
|
ISessionManager sessionManager,
|
|
|
- IDeviceManager deviceManager,
|
|
|
ITaskManager taskManager,
|
|
|
IActivityManager activityManager,
|
|
|
ILocalizationManager localization,
|
|
@@ -65,7 +61,6 @@ namespace Emby.Server.Implementations.Activity
|
|
|
{
|
|
|
_logger = logger;
|
|
|
_sessionManager = sessionManager;
|
|
|
- _deviceManager = deviceManager;
|
|
|
_taskManager = taskManager;
|
|
|
_activityManager = activityManager;
|
|
|
_localization = localization;
|
|
@@ -99,52 +94,38 @@ namespace Emby.Server.Implementations.Activity
|
|
|
_userManager.UserPolicyUpdated += OnUserPolicyUpdated;
|
|
|
_userManager.UserLockedOut += OnUserLockedOut;
|
|
|
|
|
|
- _deviceManager.CameraImageUploaded += OnCameraImageUploaded;
|
|
|
-
|
|
|
return Task.CompletedTask;
|
|
|
}
|
|
|
|
|
|
- private void OnCameraImageUploaded(object sender, GenericEventArgs<CameraImageUploadInfo> e)
|
|
|
+ private async void OnUserLockedOut(object sender, GenericEventArgs<MediaBrowser.Controller.Entities.User> e)
|
|
|
{
|
|
|
- CreateLogEntry(new ActivityLogEntry
|
|
|
- {
|
|
|
- Name = string.Format(
|
|
|
- CultureInfo.InvariantCulture,
|
|
|
- _localization.GetLocalizedString("CameraImageUploadedFrom"),
|
|
|
- e.Argument.Device.Name),
|
|
|
- Type = NotificationType.CameraImageUploaded.ToString()
|
|
|
- });
|
|
|
- }
|
|
|
-
|
|
|
- private void OnUserLockedOut(object sender, GenericEventArgs<User> e)
|
|
|
- {
|
|
|
- CreateLogEntry(new ActivityLogEntry
|
|
|
- {
|
|
|
- Name = string.Format(
|
|
|
- CultureInfo.InvariantCulture,
|
|
|
- _localization.GetLocalizedString("UserLockedOutWithName"),
|
|
|
- e.Argument.Name),
|
|
|
- Type = NotificationType.UserLockedOut.ToString(),
|
|
|
- UserId = e.Argument.Id
|
|
|
- });
|
|
|
+ await CreateLogEntry(new ActivityLog(
|
|
|
+ string.Format(
|
|
|
+ CultureInfo.InvariantCulture,
|
|
|
+ _localization.GetLocalizedString("UserLockedOutWithName"),
|
|
|
+ e.Argument.Name),
|
|
|
+ NotificationType.UserLockedOut.ToString(),
|
|
|
+ e.Argument.Id))
|
|
|
+ .ConfigureAwait(false);
|
|
|
}
|
|
|
|
|
|
- private void OnSubtitleDownloadFailure(object sender, SubtitleDownloadFailureEventArgs e)
|
|
|
+ private async void OnSubtitleDownloadFailure(object sender, SubtitleDownloadFailureEventArgs e)
|
|
|
{
|
|
|
- CreateLogEntry(new ActivityLogEntry
|
|
|
- {
|
|
|
- Name = string.Format(
|
|
|
+ await CreateLogEntry(new ActivityLog(
|
|
|
+ string.Format(
|
|
|
CultureInfo.InvariantCulture,
|
|
|
_localization.GetLocalizedString("SubtitleDownloadFailureFromForItem"),
|
|
|
e.Provider,
|
|
|
Notifications.NotificationEntryPoint.GetItemName(e.Item)),
|
|
|
- Type = "SubtitleDownloadFailure",
|
|
|
+ "SubtitleDownloadFailure",
|
|
|
+ Guid.Empty)
|
|
|
+ {
|
|
|
ItemId = e.Item.Id.ToString("N", CultureInfo.InvariantCulture),
|
|
|
ShortOverview = e.Exception.Message
|
|
|
- });
|
|
|
+ }).ConfigureAwait(false);
|
|
|
}
|
|
|
|
|
|
- private void OnPlaybackStopped(object sender, PlaybackStopEventArgs e)
|
|
|
+ private async void OnPlaybackStopped(object sender, PlaybackStopEventArgs e)
|
|
|
{
|
|
|
var item = e.MediaInfo;
|
|
|
|
|
@@ -167,20 +148,19 @@ namespace Emby.Server.Implementations.Activity
|
|
|
|
|
|
var user = e.Users[0];
|
|
|
|
|
|
- CreateLogEntry(new ActivityLogEntry
|
|
|
- {
|
|
|
- Name = string.Format(
|
|
|
+ await CreateLogEntry(new ActivityLog(
|
|
|
+ string.Format(
|
|
|
CultureInfo.InvariantCulture,
|
|
|
_localization.GetLocalizedString("UserStoppedPlayingItemWithValues"),
|
|
|
user.Name,
|
|
|
GetItemName(item),
|
|
|
e.DeviceName),
|
|
|
- Type = GetPlaybackStoppedNotificationType(item.MediaType),
|
|
|
- UserId = user.Id
|
|
|
- });
|
|
|
+ GetPlaybackStoppedNotificationType(item.MediaType),
|
|
|
+ user.Id))
|
|
|
+ .ConfigureAwait(false);
|
|
|
}
|
|
|
|
|
|
- private void OnPlaybackStart(object sender, PlaybackProgressEventArgs e)
|
|
|
+ private async void OnPlaybackStart(object sender, PlaybackProgressEventArgs e)
|
|
|
{
|
|
|
var item = e.MediaInfo;
|
|
|
|
|
@@ -203,17 +183,16 @@ namespace Emby.Server.Implementations.Activity
|
|
|
|
|
|
var user = e.Users.First();
|
|
|
|
|
|
- CreateLogEntry(new ActivityLogEntry
|
|
|
- {
|
|
|
- Name = string.Format(
|
|
|
+ await CreateLogEntry(new ActivityLog(
|
|
|
+ string.Format(
|
|
|
CultureInfo.InvariantCulture,
|
|
|
_localization.GetLocalizedString("UserStartedPlayingItemWithValues"),
|
|
|
user.Name,
|
|
|
GetItemName(item),
|
|
|
e.DeviceName),
|
|
|
- Type = GetPlaybackNotificationType(item.MediaType),
|
|
|
- UserId = user.Id
|
|
|
- });
|
|
|
+ GetPlaybackNotificationType(item.MediaType),
|
|
|
+ user.Id))
|
|
|
+ .ConfigureAwait(false);
|
|
|
}
|
|
|
|
|
|
private static string GetItemName(BaseItemDto item)
|
|
@@ -263,7 +242,7 @@ namespace Emby.Server.Implementations.Activity
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
- private void OnSessionEnded(object sender, SessionEventArgs e)
|
|
|
+ private async void OnSessionEnded(object sender, SessionEventArgs e)
|
|
|
{
|
|
|
var session = e.SessionInfo;
|
|
|
|
|
@@ -272,110 +251,108 @@ namespace Emby.Server.Implementations.Activity
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- CreateLogEntry(new ActivityLogEntry
|
|
|
- {
|
|
|
- Name = string.Format(
|
|
|
+ await CreateLogEntry(new ActivityLog(
|
|
|
+ string.Format(
|
|
|
CultureInfo.InvariantCulture,
|
|
|
_localization.GetLocalizedString("UserOfflineFromDevice"),
|
|
|
session.UserName,
|
|
|
session.DeviceName),
|
|
|
- Type = "SessionEnded",
|
|
|
+ "SessionEnded",
|
|
|
+ session.UserId)
|
|
|
+ {
|
|
|
ShortOverview = string.Format(
|
|
|
CultureInfo.InvariantCulture,
|
|
|
_localization.GetLocalizedString("LabelIpAddressValue"),
|
|
|
session.RemoteEndPoint),
|
|
|
- UserId = session.UserId
|
|
|
- });
|
|
|
+ }).ConfigureAwait(false);
|
|
|
}
|
|
|
|
|
|
- private void OnAuthenticationSucceeded(object sender, GenericEventArgs<AuthenticationResult> e)
|
|
|
+ private async void OnAuthenticationSucceeded(object sender, GenericEventArgs<AuthenticationResult> e)
|
|
|
{
|
|
|
var user = e.Argument.User;
|
|
|
|
|
|
- CreateLogEntry(new ActivityLogEntry
|
|
|
- {
|
|
|
- Name = string.Format(
|
|
|
+ await CreateLogEntry(new ActivityLog(
|
|
|
+ string.Format(
|
|
|
CultureInfo.InvariantCulture,
|
|
|
_localization.GetLocalizedString("AuthenticationSucceededWithUserName"),
|
|
|
user.Name),
|
|
|
- Type = "AuthenticationSucceeded",
|
|
|
+ "AuthenticationSucceeded",
|
|
|
+ user.Id)
|
|
|
+ {
|
|
|
ShortOverview = string.Format(
|
|
|
CultureInfo.InvariantCulture,
|
|
|
_localization.GetLocalizedString("LabelIpAddressValue"),
|
|
|
e.Argument.SessionInfo.RemoteEndPoint),
|
|
|
- UserId = user.Id
|
|
|
- });
|
|
|
+ }).ConfigureAwait(false);
|
|
|
}
|
|
|
|
|
|
- private void OnAuthenticationFailed(object sender, GenericEventArgs<AuthenticationRequest> e)
|
|
|
+ private async void OnAuthenticationFailed(object sender, GenericEventArgs<AuthenticationRequest> e)
|
|
|
{
|
|
|
- CreateLogEntry(new ActivityLogEntry
|
|
|
- {
|
|
|
- Name = string.Format(
|
|
|
+ await CreateLogEntry(new ActivityLog(
|
|
|
+ string.Format(
|
|
|
CultureInfo.InvariantCulture,
|
|
|
_localization.GetLocalizedString("FailedLoginAttemptWithUserName"),
|
|
|
e.Argument.Username),
|
|
|
- Type = "AuthenticationFailed",
|
|
|
+ "AuthenticationFailed",
|
|
|
+ Guid.Empty)
|
|
|
+ {
|
|
|
+ LogSeverity = LogLevel.Error,
|
|
|
ShortOverview = string.Format(
|
|
|
CultureInfo.InvariantCulture,
|
|
|
_localization.GetLocalizedString("LabelIpAddressValue"),
|
|
|
e.Argument.RemoteEndPoint),
|
|
|
- Severity = LogLevel.Error
|
|
|
- });
|
|
|
+ }).ConfigureAwait(false);
|
|
|
}
|
|
|
|
|
|
- private void OnUserPolicyUpdated(object sender, GenericEventArgs<User> e)
|
|
|
+ private async void OnUserPolicyUpdated(object sender, GenericEventArgs<MediaBrowser.Controller.Entities.User> e)
|
|
|
{
|
|
|
- CreateLogEntry(new ActivityLogEntry
|
|
|
- {
|
|
|
- Name = string.Format(
|
|
|
+ await CreateLogEntry(new ActivityLog(
|
|
|
+ string.Format(
|
|
|
CultureInfo.InvariantCulture,
|
|
|
_localization.GetLocalizedString("UserPolicyUpdatedWithName"),
|
|
|
e.Argument.Name),
|
|
|
- Type = "UserPolicyUpdated",
|
|
|
- UserId = e.Argument.Id
|
|
|
- });
|
|
|
+ "UserPolicyUpdated",
|
|
|
+ e.Argument.Id))
|
|
|
+ .ConfigureAwait(false);
|
|
|
}
|
|
|
|
|
|
- private void OnUserDeleted(object sender, GenericEventArgs<User> e)
|
|
|
+ private async void OnUserDeleted(object sender, GenericEventArgs<MediaBrowser.Controller.Entities.User> e)
|
|
|
{
|
|
|
- CreateLogEntry(new ActivityLogEntry
|
|
|
- {
|
|
|
- Name = string.Format(
|
|
|
+ await CreateLogEntry(new ActivityLog(
|
|
|
+ string.Format(
|
|
|
CultureInfo.InvariantCulture,
|
|
|
_localization.GetLocalizedString("UserDeletedWithName"),
|
|
|
e.Argument.Name),
|
|
|
- Type = "UserDeleted"
|
|
|
- });
|
|
|
+ "UserDeleted",
|
|
|
+ Guid.Empty))
|
|
|
+ .ConfigureAwait(false);
|
|
|
}
|
|
|
|
|
|
- private void OnUserPasswordChanged(object sender, GenericEventArgs<User> e)
|
|
|
+ private async void OnUserPasswordChanged(object sender, GenericEventArgs<MediaBrowser.Controller.Entities.User> e)
|
|
|
{
|
|
|
- CreateLogEntry(new ActivityLogEntry
|
|
|
- {
|
|
|
- Name = string.Format(
|
|
|
+ await CreateLogEntry(new ActivityLog(
|
|
|
+ string.Format(
|
|
|
CultureInfo.InvariantCulture,
|
|
|
_localization.GetLocalizedString("UserPasswordChangedWithName"),
|
|
|
e.Argument.Name),
|
|
|
- Type = "UserPasswordChanged",
|
|
|
- UserId = e.Argument.Id
|
|
|
- });
|
|
|
+ "UserPasswordChanged",
|
|
|
+ e.Argument.Id))
|
|
|
+ .ConfigureAwait(false);
|
|
|
}
|
|
|
|
|
|
- private void OnUserCreated(object sender, GenericEventArgs<User> e)
|
|
|
+ private async void OnUserCreated(object sender, GenericEventArgs<MediaBrowser.Controller.Entities.User> e)
|
|
|
{
|
|
|
- CreateLogEntry(new ActivityLogEntry
|
|
|
- {
|
|
|
- Name = string.Format(
|
|
|
+ await CreateLogEntry(new ActivityLog(
|
|
|
+ string.Format(
|
|
|
CultureInfo.InvariantCulture,
|
|
|
_localization.GetLocalizedString("UserCreatedWithName"),
|
|
|
e.Argument.Name),
|
|
|
- Type = "UserCreated",
|
|
|
- UserId = e.Argument.Id
|
|
|
- });
|
|
|
+ "UserCreated",
|
|
|
+ e.Argument.Id))
|
|
|
+ .ConfigureAwait(false);
|
|
|
}
|
|
|
|
|
|
- private void OnSessionStarted(object sender, SessionEventArgs e)
|
|
|
+ private async void OnSessionStarted(object sender, SessionEventArgs e)
|
|
|
{
|
|
|
var session = e.SessionInfo;
|
|
|
|
|
@@ -384,87 +361,90 @@ namespace Emby.Server.Implementations.Activity
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- CreateLogEntry(new ActivityLogEntry
|
|
|
- {
|
|
|
- Name = string.Format(
|
|
|
+ await CreateLogEntry(new ActivityLog(
|
|
|
+ string.Format(
|
|
|
CultureInfo.InvariantCulture,
|
|
|
_localization.GetLocalizedString("UserOnlineFromDevice"),
|
|
|
session.UserName,
|
|
|
session.DeviceName),
|
|
|
- Type = "SessionStarted",
|
|
|
+ "SessionStarted",
|
|
|
+ session.UserId)
|
|
|
+ {
|
|
|
ShortOverview = string.Format(
|
|
|
CultureInfo.InvariantCulture,
|
|
|
_localization.GetLocalizedString("LabelIpAddressValue"),
|
|
|
- session.RemoteEndPoint),
|
|
|
- UserId = session.UserId
|
|
|
- });
|
|
|
+ session.RemoteEndPoint)
|
|
|
+ }).ConfigureAwait(false);
|
|
|
}
|
|
|
|
|
|
- private void OnPluginUpdated(object sender, GenericEventArgs<(IPlugin, VersionInfo)> e)
|
|
|
+ private async void OnPluginUpdated(object sender, GenericEventArgs<(IPlugin, VersionInfo)> e)
|
|
|
{
|
|
|
- CreateLogEntry(new ActivityLogEntry
|
|
|
- {
|
|
|
- Name = string.Format(
|
|
|
+ await CreateLogEntry(new ActivityLog(
|
|
|
+ string.Format(
|
|
|
CultureInfo.InvariantCulture,
|
|
|
_localization.GetLocalizedString("PluginUpdatedWithName"),
|
|
|
e.Argument.Item1.Name),
|
|
|
- Type = NotificationType.PluginUpdateInstalled.ToString(),
|
|
|
+ NotificationType.PluginUpdateInstalled.ToString(),
|
|
|
+ Guid.Empty)
|
|
|
+ {
|
|
|
ShortOverview = string.Format(
|
|
|
CultureInfo.InvariantCulture,
|
|
|
_localization.GetLocalizedString("VersionNumber"),
|
|
|
e.Argument.Item2.version),
|
|
|
Overview = e.Argument.Item2.changelog
|
|
|
- });
|
|
|
+ }).ConfigureAwait(false);
|
|
|
}
|
|
|
|
|
|
- private void OnPluginUninstalled(object sender, GenericEventArgs<IPlugin> e)
|
|
|
+ private async void OnPluginUninstalled(object sender, GenericEventArgs<IPlugin> e)
|
|
|
{
|
|
|
- CreateLogEntry(new ActivityLogEntry
|
|
|
- {
|
|
|
- Name = string.Format(
|
|
|
+ await CreateLogEntry(new ActivityLog(
|
|
|
+ string.Format(
|
|
|
CultureInfo.InvariantCulture,
|
|
|
_localization.GetLocalizedString("PluginUninstalledWithName"),
|
|
|
e.Argument.Name),
|
|
|
- Type = NotificationType.PluginUninstalled.ToString()
|
|
|
- });
|
|
|
+ NotificationType.PluginUninstalled.ToString(),
|
|
|
+ Guid.Empty))
|
|
|
+ .ConfigureAwait(false);
|
|
|
}
|
|
|
|
|
|
- private void OnPluginInstalled(object sender, GenericEventArgs<VersionInfo> e)
|
|
|
+ private async void OnPluginInstalled(object sender, GenericEventArgs<VersionInfo> e)
|
|
|
{
|
|
|
- CreateLogEntry(new ActivityLogEntry
|
|
|
- {
|
|
|
- Name = string.Format(
|
|
|
+ await CreateLogEntry(new ActivityLog(
|
|
|
+ string.Format(
|
|
|
CultureInfo.InvariantCulture,
|
|
|
_localization.GetLocalizedString("PluginInstalledWithName"),
|
|
|
e.Argument.name),
|
|
|
- Type = NotificationType.PluginInstalled.ToString(),
|
|
|
+ NotificationType.PluginInstalled.ToString(),
|
|
|
+ Guid.Empty)
|
|
|
+ {
|
|
|
ShortOverview = string.Format(
|
|
|
CultureInfo.InvariantCulture,
|
|
|
_localization.GetLocalizedString("VersionNumber"),
|
|
|
e.Argument.version)
|
|
|
- });
|
|
|
+ }).ConfigureAwait(false);
|
|
|
}
|
|
|
|
|
|
- private void OnPackageInstallationFailed(object sender, InstallationFailedEventArgs e)
|
|
|
+ private async void OnPackageInstallationFailed(object sender, InstallationFailedEventArgs e)
|
|
|
{
|
|
|
var installationInfo = e.InstallationInfo;
|
|
|
|
|
|
- CreateLogEntry(new ActivityLogEntry
|
|
|
- {
|
|
|
- Name = string.Format(
|
|
|
+ await CreateLogEntry(new ActivityLog(
|
|
|
+ string.Format(
|
|
|
CultureInfo.InvariantCulture,
|
|
|
_localization.GetLocalizedString("NameInstallFailed"),
|
|
|
installationInfo.Name),
|
|
|
- Type = NotificationType.InstallationFailed.ToString(),
|
|
|
+ NotificationType.InstallationFailed.ToString(),
|
|
|
+ Guid.Empty)
|
|
|
+ {
|
|
|
ShortOverview = string.Format(
|
|
|
CultureInfo.InvariantCulture,
|
|
|
_localization.GetLocalizedString("VersionNumber"),
|
|
|
installationInfo.Version),
|
|
|
Overview = e.Exception.Message
|
|
|
- });
|
|
|
+ }).ConfigureAwait(false);
|
|
|
}
|
|
|
|
|
|
- private void OnTaskCompleted(object sender, TaskCompletionEventArgs e)
|
|
|
+ private async void OnTaskCompleted(object sender, TaskCompletionEventArgs e)
|
|
|
{
|
|
|
var result = e.Result;
|
|
|
var task = e.Task;
|
|
@@ -495,22 +475,20 @@ namespace Emby.Server.Implementations.Activity
|
|
|
vals.Add(e.Result.LongErrorMessage);
|
|
|
}
|
|
|
|
|
|
- CreateLogEntry(new ActivityLogEntry
|
|
|
+ await CreateLogEntry(new ActivityLog(
|
|
|
+ string.Format(CultureInfo.InvariantCulture, _localization.GetLocalizedString("ScheduledTaskFailedWithName"), task.Name),
|
|
|
+ NotificationType.TaskFailed.ToString(),
|
|
|
+ Guid.Empty)
|
|
|
{
|
|
|
- Name = string.Format(
|
|
|
- CultureInfo.InvariantCulture,
|
|
|
- _localization.GetLocalizedString("ScheduledTaskFailedWithName"),
|
|
|
- task.Name),
|
|
|
- Type = NotificationType.TaskFailed.ToString(),
|
|
|
+ LogSeverity = LogLevel.Error,
|
|
|
Overview = string.Join(Environment.NewLine, vals),
|
|
|
- ShortOverview = runningTime,
|
|
|
- Severity = LogLevel.Error
|
|
|
- });
|
|
|
+ ShortOverview = runningTime
|
|
|
+ }).ConfigureAwait(false);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private void CreateLogEntry(ActivityLogEntry entry)
|
|
|
- => _activityManager.Create(entry);
|
|
|
+ private async Task CreateLogEntry(ActivityLog entry)
|
|
|
+ => await _activityManager.CreateAsync(entry).ConfigureAwait(false);
|
|
|
|
|
|
/// <inheritdoc />
|
|
|
public void Dispose()
|
|
@@ -537,8 +515,6 @@ namespace Emby.Server.Implementations.Activity
|
|
|
_userManager.UserDeleted -= OnUserDeleted;
|
|
|
_userManager.UserPolicyUpdated -= OnUserPolicyUpdated;
|
|
|
_userManager.UserLockedOut -= OnUserLockedOut;
|
|
|
-
|
|
|
- _deviceManager.CameraImageUploaded -= OnCameraImageUploaded;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
@@ -566,7 +542,7 @@ namespace Emby.Server.Implementations.Activity
|
|
|
{
|
|
|
int months = days / DaysInMonth;
|
|
|
values.Add(CreateValueString(months, "month"));
|
|
|
- days %= DaysInMonth;
|
|
|
+ days = days % DaysInMonth;
|
|
|
}
|
|
|
|
|
|
// Number of days
|