Skip to content

Commit

Permalink
Merge pull request #70 from jellyfin/user-item-data
Browse files Browse the repository at this point in the history
Add UserDataSaved event handler
  • Loading branch information
crobibero authored Sep 27, 2021
2 parents 05fae11 + eaba165 commit ab87251
Show file tree
Hide file tree
Showing 6 changed files with 146 additions and 5 deletions.
3 changes: 2 additions & 1 deletion Jellyfin.Plugin.Webhook/Configuration/Web/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@
"UserDeleted": "User Deleted",
"UserLockedOut": "User Locked Out",
"UserPasswordChanged": "User Password Changed",
"UserUpdated": "User Updated"
"UserUpdated": "User Updated",
"UserDataSaved": "User Data Saved"
},
create: function (container, selected = []) {
const notificationTypeKeys = Object.keys(Webhook.notificationType.values).sort();
Expand Down
2 changes: 1 addition & 1 deletion Jellyfin.Plugin.Webhook/Destinations/IWebhookClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@ public interface IWebhookClient<in TDestinationOptions>
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
Task SendAsync(TDestinationOptions options, Dictionary<string, object> data);
}
}
}
9 changes: 7 additions & 2 deletions Jellyfin.Plugin.Webhook/Destinations/NotificationType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,11 @@ public enum NotificationType
/// <summary>
/// User updated.
/// </summary>
UserUpdated = 22
UserUpdated = 22,

/// <summary>
/// User data saved.
/// </summary>
UserDataSaved = 23
}
}
}
25 changes: 25 additions & 0 deletions Jellyfin.Plugin.Webhook/Helpers/DataObjectHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,31 @@ public static Dictionary<string, object> AddExceptionInfo(this Dictionary<string
return dataObject;
}

/// <summary>
/// Add user item data.
/// </summary>
/// <param name="dataObject">The data object.</param>
/// <param name="userItemData">The user item data.</param>
/// <returns>The modified data object.</returns>
public static Dictionary<string, object> AddUserItemData(this Dictionary<string, object> dataObject, UserItemData userItemData)
{
dataObject["Likes"] = userItemData.Likes ?? false;
dataObject["Rating"] = userItemData.Rating ?? 0;
dataObject["PlaybackPositionTicks"] = userItemData.PlaybackPositionTicks;
dataObject["PlaybackPosition"] = TimeSpan.FromTicks(userItemData.PlaybackPositionTicks).ToString(@"hh\:mm\:ss", CultureInfo.InvariantCulture);
dataObject["PlayCount"] = userItemData.PlayCount;
dataObject["Favorite"] = userItemData.IsFavorite;
dataObject["Played"] = userItemData.Played;
dataObject["AudioStreamIndex"] = userItemData.AudioStreamIndex ?? -1;
dataObject["SubtitleStreamIndex"] = userItemData.SubtitleStreamIndex ?? -1;
if (userItemData.LastPlayedDate.HasValue)
{
dataObject["LastPlayedDate"] = userItemData.LastPlayedDate;
}

return dataObject;
}

/// <summary>
/// Escape quotes for proper json.
/// </summary>
Expand Down
2 changes: 1 addition & 1 deletion Jellyfin.Plugin.Webhook/IWebhookSender.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@ public interface IWebhookSender
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
Task SendNotification(NotificationType notificationType, Dictionary<string, object> itemData, Type? itemType = null);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
using System;
using System.Threading.Tasks;
using Jellyfin.Plugin.Webhook.Destinations;
using Jellyfin.Plugin.Webhook.Helpers;
using MediaBrowser.Common;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Plugins;
using Microsoft.Extensions.Logging;

namespace Jellyfin.Plugin.Webhook.Notifiers.UserDataSavedNotifier
{
/// <summary>
/// User data saved notifier.
/// </summary>
public class UserDataSavedNotifierEntryPoint : IServerEntryPoint
{
private readonly IWebhookSender _webhookSender;
private readonly IApplicationHost _applicationHost;
private readonly IUserDataManager _userDataManager;
private readonly IUserManager _userManager;
private readonly ILogger<UserDataSavedNotifierEntryPoint> _logger;

/// <summary>
/// Initializes a new instance of the <see cref="UserDataSavedNotifierEntryPoint"/> class.
/// </summary>
/// <param name="webhookSender">Instance of the <see cref="IWebhookSender"/> interface.</param>
/// <param name="userDataManager">Instance of the <see cref="IUserDataManager"/> interface.</param>
/// <param name="applicationHost">Instance of the <see cref="IApplicationHost"/> interface.</param>
/// <param name="logger">Instance of the <see cref="ILogger{UserDataChangedNotifierEntryPoint}"/> interface.</param>
/// <param name="userManager">Instance of the <see cref="IUserManager"/> interface.</param>
public UserDataSavedNotifierEntryPoint(
IWebhookSender webhookSender,
IApplicationHost applicationHost,
IUserDataManager userDataManager,
ILogger<UserDataSavedNotifierEntryPoint> logger,
IUserManager userManager)
{
_userDataManager = userDataManager;
_logger = logger;
_userManager = userManager;
_applicationHost = applicationHost;
_webhookSender = webhookSender;
}

/// <inheritdoc />
public Task RunAsync()
{
_userDataManager.UserDataSaved += UserDataSavedHandler;
return Task.CompletedTask;
}

/// <inheritdoc />
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}

/// <summary>
/// Dispose.
/// </summary>
/// <param name="disposing">Dispose all assets.</param>
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
_userDataManager.UserDataSaved -= UserDataSavedHandler;
}
}

private async void UserDataSavedHandler(object? sender, UserDataSaveEventArgs eventArgs)
{
try
{
if (eventArgs.Item is null)
{
return;
}

if (eventArgs.Item.IsThemeMedia)
{
// Don't report theme song or local trailer playback.
return;
}

var user = _userManager.GetUserById(eventArgs.UserId);
if (user is null)
{
return;
}

var dataObject = DataObjectHelpers
.GetBaseDataObject(_applicationHost, NotificationType.UserDataSaved)
.AddBaseItemData(eventArgs.Item)
.AddUserItemData(eventArgs.UserData);

dataObject["SaveReason"] = eventArgs.SaveReason.ToString();
dataObject["NotificationUsername"] = user.Username;
dataObject["UserId"] = user.Id;

await _webhookSender.SendNotification(NotificationType.UserDataSaved, dataObject, eventArgs.Item.GetType())
.ConfigureAwait(false);
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Unable to send notification");
}
}
}
}

0 comments on commit ab87251

Please sign in to comment.