diff --git a/Emby.Notifications/Api/NotificationsService.cs b/Emby.Notifications/Api/NotificationsService.cs deleted file mode 100644 index 788750796d..0000000000 --- a/Emby.Notifications/Api/NotificationsService.cs +++ /dev/null @@ -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 - { - [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 Notifications { get; set; } = Array.Empty(); - - 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 - { - [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> - { - } - - [Route("/Notifications/Services", "GET", Summary = "Gets notification types")] - public class GetNotificationServices : IReturn> - { - } - - [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(); - } - } -} diff --git a/Jellyfin.Api/Controllers/NotificationsController.cs b/Jellyfin.Api/Controllers/NotificationsController.cs new file mode 100644 index 0000000000..3cbb3a3a3f --- /dev/null +++ b/Jellyfin.Api/Controllers/NotificationsController.cs @@ -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 +{ + /// + /// The notification controller. + /// + public class NotificationsController : BaseJellyfinApiController + { + private readonly INotificationManager _notificationManager; + private readonly IUserManager _userManager; + + /// + /// Initializes a new instance of the class. + /// + /// The notification manager. + /// The user manager. + public NotificationsController(INotificationManager notificationManager, IUserManager userManager) + { + _notificationManager = notificationManager; + _userManager = userManager; + } + + /// + /// Gets a user's notifications. + /// + /// The user's ID. + /// An optional filter by notification read state. + /// The optional index to start at. All notifications with a lower index will be omitted from the results. + /// An optional limit on the number of notifications returned. + /// Notifications returned. + /// An containing a list of notifications. + [HttpGet("{UserID}")] + [ProducesResponseType(StatusCodes.Status200OK)] + public ActionResult GetNotifications( + [FromRoute] string userId, + [FromQuery] bool? isRead, + [FromQuery] int? startIndex, + [FromQuery] int? limit) + { + return new NotificationResultDto(); + } + + /// + /// Gets a user's notification summary. + /// + /// The user's ID. + /// Summary of user's notifications returned. + /// An containing a summary of the users notifications. + [HttpGet("{UserID}/Summary")] + [ProducesResponseType(StatusCodes.Status200OK)] + public ActionResult GetNotificationsSummary( + [FromRoute] string userId) + { + return new NotificationsSummaryDto(); + } + + /// + /// Gets notification types. + /// + /// All notification types returned. + /// An containing a list of all notification types. + [HttpGet("Types")] + [ProducesResponseType(StatusCodes.Status200OK)] + public IEnumerable GetNotificationTypes() + { + return _notificationManager.GetNotificationTypes(); + } + + /// + /// Gets notification services. + /// + /// All notification services returned. + /// An containing a list of all notification services. + [HttpGet("Services")] + [ProducesResponseType(StatusCodes.Status200OK)] + public IEnumerable GetNotificationServices() + { + return _notificationManager.GetNotificationServices(); + } + + /// + /// Sends a notification to all admins. + /// + /// The name of the notification. + /// The description of the notification. + /// The URL of the notification. + /// The level of the notification. + /// Notification sent. + /// An . + [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(); + } + + /// + /// Sets notifications as read. + /// + /// The userID. + /// A comma-separated list of the IDs of notifications which should be set as read. + /// Notifications set as read. + /// An . + [HttpPost("{UserID}/Read")] + [ProducesResponseType(StatusCodes.Status200OK)] + public ActionResult SetRead( + [FromRoute] string userId, + [FromQuery] string ids) + { + return Ok(); + } + + /// + /// Sets notifications as unread. + /// + /// The userID. + /// A comma-separated list of the IDs of notifications which should be set as unread. + /// Notifications set as unread. + /// An . + [HttpPost("{UserID}/Unread")] + [ProducesResponseType(StatusCodes.Status200OK)] + public ActionResult SetUnread( + [FromRoute] string userId, + [FromQuery] string ids) + { + return Ok(); + } + } +} diff --git a/Jellyfin.Api/Models/NotificationDtos/NotificationDto.cs b/Jellyfin.Api/Models/NotificationDtos/NotificationDto.cs new file mode 100644 index 0000000000..502b22623b --- /dev/null +++ b/Jellyfin.Api/Models/NotificationDtos/NotificationDto.cs @@ -0,0 +1,53 @@ +#nullable enable + +using System; +using MediaBrowser.Model.Notifications; + +namespace Jellyfin.Api.Models.NotificationDtos +{ + /// + /// The notification DTO. + /// + public class NotificationDto + { + /// + /// Gets or sets the notification ID. Defaults to an empty string. + /// + public string Id { get; set; } = string.Empty; + + /// + /// Gets or sets the notification's user ID. Defaults to an empty string. + /// + public string UserId { get; set; } = string.Empty; + + /// + /// Gets or sets the notification date. + /// + public DateTime Date { get; set; } + + /// + /// Gets or sets a value indicating whether the notification has been read. Defaults to false. + /// + public bool IsRead { get; set; } = false; + + /// + /// Gets or sets the notification's name. Defaults to an empty string. + /// + public string Name { get; set; } = string.Empty; + + /// + /// Gets or sets the notification's description. Defaults to an empty string. + /// + public string Description { get; set; } = string.Empty; + + /// + /// Gets or sets the notification's URL. Defaults to an empty string. + /// + public string Url { get; set; } = string.Empty; + + /// + /// Gets or sets the notification level. + /// + public NotificationLevel Level { get; set; } + } +} diff --git a/Jellyfin.Api/Models/NotificationDtos/NotificationResultDto.cs b/Jellyfin.Api/Models/NotificationDtos/NotificationResultDto.cs new file mode 100644 index 0000000000..e34e176cb9 --- /dev/null +++ b/Jellyfin.Api/Models/NotificationDtos/NotificationResultDto.cs @@ -0,0 +1,23 @@ +#nullable enable + +using System; +using System.Collections.Generic; + +namespace Jellyfin.Api.Models.NotificationDtos +{ + /// + /// A list of notifications with the total record count for pagination. + /// + public class NotificationResultDto + { + /// + /// Gets or sets the current page of notifications. + /// + public IReadOnlyList Notifications { get; set; } = Array.Empty(); + + /// + /// Gets or sets the total number of notifications. + /// + public int TotalRecordCount { get; set; } + } +} diff --git a/Jellyfin.Api/Models/NotificationDtos/NotificationsSummaryDto.cs b/Jellyfin.Api/Models/NotificationDtos/NotificationsSummaryDto.cs new file mode 100644 index 0000000000..b3746ee2da --- /dev/null +++ b/Jellyfin.Api/Models/NotificationDtos/NotificationsSummaryDto.cs @@ -0,0 +1,22 @@ +#nullable enable + +using MediaBrowser.Model.Notifications; + +namespace Jellyfin.Api.Models.NotificationDtos +{ + /// + /// The notification summary DTO. + /// + public class NotificationsSummaryDto + { + /// + /// Gets or sets the number of unread notifications. + /// + public int UnreadCount { get; set; } + + /// + /// Gets or sets the maximum unread notification level. + /// + public NotificationLevel? MaxUnreadNotificationLevel { get; set; } + } +}