mirror of
				https://github.com/jellyfin/jellyfin.git
				synced 2025-10-31 10:37:22 -04:00 
			
		
		
		
	Merge pull request #2876 from ZadenRB/asp-net-notifications-service
Migrates the notifications service to use ASP.NET API framework
This commit is contained in:
		
						commit
						b1a2fb60f2
					
				| @ -1,189 +0,0 @@ | ||||
| #pragma warning disable CS1591 | ||||
| #pragma warning disable SA1402 | ||||
| #pragma warning disable SA1649 | ||||
| 
 | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Diagnostics.CodeAnalysis; | ||||
| using System.Linq; | ||||
| using System.Threading; | ||||
| using System.Threading.Tasks; | ||||
| using MediaBrowser.Controller.Library; | ||||
| using MediaBrowser.Controller.Net; | ||||
| using MediaBrowser.Controller.Notifications; | ||||
| using MediaBrowser.Model.Dto; | ||||
| using MediaBrowser.Model.Notifications; | ||||
| using MediaBrowser.Model.Services; | ||||
| 
 | ||||
| namespace Emby.Notifications.Api | ||||
| { | ||||
|     [Route("/Notifications/{UserId}", "GET", Summary = "Gets notifications")] | ||||
|     public class GetNotifications : IReturn<NotificationResult> | ||||
|     { | ||||
|         [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] | ||||
|         public string UserId { get; set; } = string.Empty; | ||||
| 
 | ||||
|         [ApiMember(Name = "IsRead", Description = "An optional filter by IsRead", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")] | ||||
|         public bool? IsRead { get; set; } | ||||
| 
 | ||||
|         [ApiMember(Name = "StartIndex", Description = "Optional. The record index to start at. All items with a lower index will be dropped from the results.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")] | ||||
|         public int? StartIndex { get; set; } | ||||
| 
 | ||||
|         [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")] | ||||
|         public int? Limit { get; set; } | ||||
|     } | ||||
| 
 | ||||
|     public class Notification | ||||
|     { | ||||
|         public string Id { get; set; } = string.Empty; | ||||
| 
 | ||||
|         public string UserId { get; set; } = string.Empty; | ||||
| 
 | ||||
|         public DateTime Date { get; set; } | ||||
| 
 | ||||
|         public bool IsRead { get; set; } | ||||
| 
 | ||||
|         public string Name { get; set; } = string.Empty; | ||||
| 
 | ||||
|         public string Description { get; set; } = string.Empty; | ||||
| 
 | ||||
|         public string Url { get; set; } = string.Empty; | ||||
| 
 | ||||
|         public NotificationLevel Level { get; set; } | ||||
|     } | ||||
| 
 | ||||
|     public class NotificationResult | ||||
|     { | ||||
|         public IReadOnlyList<Notification> Notifications { get; set; } = Array.Empty<Notification>(); | ||||
| 
 | ||||
|         public int TotalRecordCount { get; set; } | ||||
|     } | ||||
| 
 | ||||
|     public class NotificationsSummary | ||||
|     { | ||||
|         public int UnreadCount { get; set; } | ||||
| 
 | ||||
|         public NotificationLevel MaxUnreadNotificationLevel { get; set; } | ||||
|     } | ||||
| 
 | ||||
|     [Route("/Notifications/{UserId}/Summary", "GET", Summary = "Gets a notification summary for a user")] | ||||
|     public class GetNotificationsSummary : IReturn<NotificationsSummary> | ||||
|     { | ||||
|         [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] | ||||
|         public string UserId { get; set; } = string.Empty; | ||||
|     } | ||||
| 
 | ||||
|     [Route("/Notifications/Types", "GET", Summary = "Gets notification types")] | ||||
|     public class GetNotificationTypes : IReturn<List<NotificationTypeInfo>> | ||||
|     { | ||||
|     } | ||||
| 
 | ||||
|     [Route("/Notifications/Services", "GET", Summary = "Gets notification types")] | ||||
|     public class GetNotificationServices : IReturn<List<NameIdPair>> | ||||
|     { | ||||
|     } | ||||
| 
 | ||||
|     [Route("/Notifications/Admin", "POST", Summary = "Sends a notification to all admin users")] | ||||
|     public class AddAdminNotification : IReturnVoid | ||||
|     { | ||||
|         [ApiMember(Name = "Name", Description = "The notification's name", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")] | ||||
|         public string Name { get; set; } = string.Empty; | ||||
| 
 | ||||
|         [ApiMember(Name = "Description", Description = "The notification's description", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")] | ||||
|         public string Description { get; set; } = string.Empty; | ||||
| 
 | ||||
|         [ApiMember(Name = "ImageUrl", Description = "The notification's image url", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")] | ||||
|         public string? ImageUrl { get; set; } | ||||
| 
 | ||||
|         [ApiMember(Name = "Url", Description = "The notification's info url", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")] | ||||
|         public string? Url { get; set; } | ||||
| 
 | ||||
|         [ApiMember(Name = "Level", Description = "The notification level", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")] | ||||
|         public NotificationLevel Level { get; set; } | ||||
|     } | ||||
| 
 | ||||
|     [Route("/Notifications/{UserId}/Read", "POST", Summary = "Marks notifications as read")] | ||||
|     public class MarkRead : IReturnVoid | ||||
|     { | ||||
|         [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] | ||||
|         public string UserId { get; set; } = string.Empty; | ||||
| 
 | ||||
|         [ApiMember(Name = "Ids", Description = "A list of notification ids, comma delimited", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST", AllowMultiple = true)] | ||||
|         public string Ids { get; set; } = string.Empty; | ||||
|     } | ||||
| 
 | ||||
|     [Route("/Notifications/{UserId}/Unread", "POST", Summary = "Marks notifications as unread")] | ||||
|     public class MarkUnread : IReturnVoid | ||||
|     { | ||||
|         [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] | ||||
|         public string UserId { get; set; } = string.Empty; | ||||
| 
 | ||||
|         [ApiMember(Name = "Ids", Description = "A list of notification ids, comma delimited", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST", AllowMultiple = true)] | ||||
|         public string Ids { get; set; } = string.Empty; | ||||
|     } | ||||
| 
 | ||||
|     [Authenticated] | ||||
|     public class NotificationsService : IService | ||||
|     { | ||||
|         private readonly INotificationManager _notificationManager; | ||||
|         private readonly IUserManager _userManager; | ||||
| 
 | ||||
|         public NotificationsService(INotificationManager notificationManager, IUserManager userManager) | ||||
|         { | ||||
|             _notificationManager = notificationManager; | ||||
|             _userManager = userManager; | ||||
|         } | ||||
| 
 | ||||
|         [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "request", Justification = "Required for ServiceStack")] | ||||
|         public object Get(GetNotificationTypes request) | ||||
|         { | ||||
|             return _notificationManager.GetNotificationTypes(); | ||||
|         } | ||||
| 
 | ||||
|         [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "request", Justification = "Required for ServiceStack")] | ||||
|         public object Get(GetNotificationServices request) | ||||
|         { | ||||
|             return _notificationManager.GetNotificationServices().ToList(); | ||||
|         } | ||||
| 
 | ||||
|         [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "request", Justification = "Required for ServiceStack")] | ||||
|         public object Get(GetNotificationsSummary request) | ||||
|         { | ||||
|             return new NotificationsSummary | ||||
|             { | ||||
|             }; | ||||
|         } | ||||
| 
 | ||||
|         public Task Post(AddAdminNotification request) | ||||
|         { | ||||
|             // This endpoint really just exists as post of a real with sickbeard | ||||
|             var notification = new NotificationRequest | ||||
|             { | ||||
|                 Date = DateTime.UtcNow, | ||||
|                 Description = request.Description, | ||||
|                 Level = request.Level, | ||||
|                 Name = request.Name, | ||||
|                 Url = request.Url, | ||||
|                 UserIds = _userManager.Users.Where(i => i.Policy.IsAdministrator).Select(i => i.Id).ToArray() | ||||
|             }; | ||||
| 
 | ||||
|             return _notificationManager.SendNotification(notification, CancellationToken.None); | ||||
|         } | ||||
| 
 | ||||
|         [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "request", Justification = "Required for ServiceStack")] | ||||
|         public void Post(MarkRead request) | ||||
|         { | ||||
|         } | ||||
| 
 | ||||
|         [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "request", Justification = "Required for ServiceStack")] | ||||
|         public void Post(MarkUnread request) | ||||
|         { | ||||
|         } | ||||
| 
 | ||||
|         [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "request", Justification = "Required for ServiceStack")] | ||||
|         public object Get(GetNotifications request) | ||||
|         { | ||||
|             return new NotificationResult(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										159
									
								
								Jellyfin.Api/Controllers/NotificationsController.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										159
									
								
								Jellyfin.Api/Controllers/NotificationsController.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,159 @@ | ||||
| #nullable enable | ||||
| #pragma warning disable CA1801 | ||||
| 
 | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Threading; | ||||
| using Jellyfin.Api.Models.NotificationDtos; | ||||
| using MediaBrowser.Controller.Library; | ||||
| using MediaBrowser.Controller.Notifications; | ||||
| using MediaBrowser.Model.Dto; | ||||
| using MediaBrowser.Model.Notifications; | ||||
| using Microsoft.AspNetCore.Http; | ||||
| using Microsoft.AspNetCore.Mvc; | ||||
| 
 | ||||
| namespace Jellyfin.Api.Controllers | ||||
| { | ||||
|     /// <summary> | ||||
|     /// The notification controller. | ||||
|     /// </summary> | ||||
|     public class NotificationsController : BaseJellyfinApiController | ||||
|     { | ||||
|         private readonly INotificationManager _notificationManager; | ||||
|         private readonly IUserManager _userManager; | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Initializes a new instance of the <see cref="NotificationsController" /> class. | ||||
|         /// </summary> | ||||
|         /// <param name="notificationManager">The notification manager.</param> | ||||
|         /// <param name="userManager">The user manager.</param> | ||||
|         public NotificationsController(INotificationManager notificationManager, IUserManager userManager) | ||||
|         { | ||||
|             _notificationManager = notificationManager; | ||||
|             _userManager = userManager; | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Gets a user's notifications. | ||||
|         /// </summary> | ||||
|         /// <param name="userId">The user's ID.</param> | ||||
|         /// <param name="isRead">An optional filter by notification read state.</param> | ||||
|         /// <param name="startIndex">The optional index to start at. All notifications with a lower index will be omitted from the results.</param> | ||||
|         /// <param name="limit">An optional limit on the number of notifications returned.</param> | ||||
|         /// <response code="200">Notifications returned.</response> | ||||
|         /// <returns>An <see cref="OkResult"/> containing a list of notifications.</returns> | ||||
|         [HttpGet("{UserID}")] | ||||
|         [ProducesResponseType(StatusCodes.Status200OK)] | ||||
|         public ActionResult<NotificationResultDto> GetNotifications( | ||||
|             [FromRoute] string userId, | ||||
|             [FromQuery] bool? isRead, | ||||
|             [FromQuery] int? startIndex, | ||||
|             [FromQuery] int? limit) | ||||
|         { | ||||
|             return new NotificationResultDto(); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Gets a user's notification summary. | ||||
|         /// </summary> | ||||
|         /// <param name="userId">The user's ID.</param> | ||||
|         /// <response code="200">Summary of user's notifications returned.</response> | ||||
|         /// <returns>An <cref see="OkResult"/> containing a summary of the users notifications.</returns> | ||||
|         [HttpGet("{UserID}/Summary")] | ||||
|         [ProducesResponseType(StatusCodes.Status200OK)] | ||||
|         public ActionResult<NotificationsSummaryDto> GetNotificationsSummary( | ||||
|             [FromRoute] string userId) | ||||
|         { | ||||
|             return new NotificationsSummaryDto(); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Gets notification types. | ||||
|         /// </summary> | ||||
|         /// <response code="200">All notification types returned.</response> | ||||
|         /// <returns>An <cref see="OkResult"/> containing a list of all notification types.</returns> | ||||
|         [HttpGet("Types")] | ||||
|         [ProducesResponseType(StatusCodes.Status200OK)] | ||||
|         public IEnumerable<NotificationTypeInfo> GetNotificationTypes() | ||||
|         { | ||||
|             return _notificationManager.GetNotificationTypes(); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Gets notification services. | ||||
|         /// </summary> | ||||
|         /// <response>All notification services returned.</response> | ||||
|         /// <returns>An <cref see="OkResult"/> containing a list of all notification services.</returns> | ||||
|         [HttpGet("Services")] | ||||
|         [ProducesResponseType(StatusCodes.Status200OK)] | ||||
|         public IEnumerable<NameIdPair> GetNotificationServices() | ||||
|         { | ||||
|             return _notificationManager.GetNotificationServices(); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Sends a notification to all admins. | ||||
|         /// </summary> | ||||
|         /// <param name="name">The name of the notification.</param> | ||||
|         /// <param name="description">The description of the notification.</param> | ||||
|         /// <param name="url">The URL of the notification.</param> | ||||
|         /// <param name="level">The level of the notification.</param> | ||||
|         /// <response code="200">Notification sent.</response> | ||||
|         /// <returns>An <cref see="OkResult"/>.</returns> | ||||
|         [HttpPost("Admin")] | ||||
|         [ProducesResponseType(StatusCodes.Status200OK)] | ||||
|         public ActionResult CreateAdminNotification( | ||||
|             [FromQuery] string name, | ||||
|             [FromQuery] string description, | ||||
|             [FromQuery] string? url, | ||||
|             [FromQuery] NotificationLevel? level) | ||||
|         { | ||||
|             var notification = new NotificationRequest | ||||
|             { | ||||
|                 Name = name, | ||||
|                 Description = description, | ||||
|                 Url = url, | ||||
|                 Level = level ?? NotificationLevel.Normal, | ||||
|                 UserIds = _userManager.Users.Where(i => i.Policy.IsAdministrator).Select(i => i.Id).ToArray(), | ||||
|                 Date = DateTime.UtcNow, | ||||
|             }; | ||||
| 
 | ||||
|             _notificationManager.SendNotification(notification, CancellationToken.None); | ||||
| 
 | ||||
|             return Ok(); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Sets notifications as read. | ||||
|         /// </summary> | ||||
|         /// <param name="userId">The userID.</param> | ||||
|         /// <param name="ids">A comma-separated list of the IDs of notifications which should be set as read.</param> | ||||
|         /// <response code="200">Notifications set as read.</response> | ||||
|         /// <returns>An <cref see="OkResult"/>.</returns> | ||||
|         [HttpPost("{UserID}/Read")] | ||||
|         [ProducesResponseType(StatusCodes.Status200OK)] | ||||
|         public ActionResult SetRead( | ||||
|             [FromRoute] string userId, | ||||
|             [FromQuery] string ids) | ||||
|         { | ||||
|             return Ok(); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Sets notifications as unread. | ||||
|         /// </summary> | ||||
|         /// <param name="userId">The userID.</param> | ||||
|         /// <param name="ids">A comma-separated list of the IDs of notifications which should be set as unread.</param> | ||||
|         /// <response code="200">Notifications set as unread.</response> | ||||
|         /// <returns>An <cref see="OkResult"/>.</returns> | ||||
|         [HttpPost("{UserID}/Unread")] | ||||
|         [ProducesResponseType(StatusCodes.Status200OK)] | ||||
|         public ActionResult SetUnread( | ||||
|             [FromRoute] string userId, | ||||
|             [FromQuery] string ids) | ||||
|         { | ||||
|             return Ok(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										53
									
								
								Jellyfin.Api/Models/NotificationDtos/NotificationDto.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								Jellyfin.Api/Models/NotificationDtos/NotificationDto.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,53 @@ | ||||
| #nullable enable | ||||
| 
 | ||||
| using System; | ||||
| using MediaBrowser.Model.Notifications; | ||||
| 
 | ||||
| namespace Jellyfin.Api.Models.NotificationDtos | ||||
| { | ||||
|     /// <summary> | ||||
|     /// The notification DTO. | ||||
|     /// </summary> | ||||
|     public class NotificationDto | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Gets or sets the notification ID. Defaults to an empty string. | ||||
|         /// </summary> | ||||
|         public string Id { get; set; } = string.Empty; | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Gets or sets the notification's user ID. Defaults to an empty string. | ||||
|         /// </summary> | ||||
|         public string UserId { get; set; } = string.Empty; | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Gets or sets the notification date. | ||||
|         /// </summary> | ||||
|         public DateTime Date { get; set; } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Gets or sets a value indicating whether the notification has been read. Defaults to false. | ||||
|         /// </summary> | ||||
|         public bool IsRead { get; set; } = false; | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Gets or sets the notification's name. Defaults to an empty string. | ||||
|         /// </summary> | ||||
|         public string Name { get; set; } = string.Empty; | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Gets or sets the notification's description. Defaults to an empty string. | ||||
|         /// </summary> | ||||
|         public string Description { get; set; } = string.Empty; | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Gets or sets the notification's URL. Defaults to an empty string. | ||||
|         /// </summary> | ||||
|         public string Url { get; set; } = string.Empty; | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Gets or sets the notification level. | ||||
|         /// </summary> | ||||
|         public NotificationLevel Level { get; set; } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,23 @@ | ||||
| #nullable enable | ||||
| 
 | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| 
 | ||||
| namespace Jellyfin.Api.Models.NotificationDtos | ||||
| { | ||||
|     /// <summary> | ||||
|     /// A list of notifications with the total record count for pagination. | ||||
|     /// </summary> | ||||
|     public class NotificationResultDto | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Gets or sets the current page of notifications. | ||||
|         /// </summary> | ||||
|         public IReadOnlyList<NotificationDto> Notifications { get; set; } = Array.Empty<NotificationDto>(); | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Gets or sets the total number of notifications. | ||||
|         /// </summary> | ||||
|         public int TotalRecordCount { get; set; } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,22 @@ | ||||
| #nullable enable | ||||
| 
 | ||||
| using MediaBrowser.Model.Notifications; | ||||
| 
 | ||||
| namespace Jellyfin.Api.Models.NotificationDtos | ||||
| { | ||||
|     /// <summary> | ||||
|     /// The notification summary DTO. | ||||
|     /// </summary> | ||||
|     public class NotificationsSummaryDto | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Gets or sets the number of unread notifications. | ||||
|         /// </summary> | ||||
|         public int UnreadCount { get; set; } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Gets or sets the maximum unread notification level. | ||||
|         /// </summary> | ||||
|         public NotificationLevel? MaxUnreadNotificationLevel { get; set; } | ||||
|     } | ||||
| } | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user