浏览代码

Merge pull request #2929 from crobibero/api-scheduled-tasks

Scheduled Tasks to Jellyfin.Api
Patrick Barron 5 年之前
父节点
当前提交
fe02c6e863

+ 161 - 0
Jellyfin.Api/Controllers/ScheduledTasksController.cs

@@ -0,0 +1,161 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Jellyfin.Api.Constants;
+using MediaBrowser.Model.Tasks;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.ModelBinding;
+
+namespace Jellyfin.Api.Controllers
+{
+    /// <summary>
+    /// Scheduled Tasks Controller.
+    /// </summary>
+    [Authorize(Policy = Policies.RequiresElevation)]
+    public class ScheduledTasksController : BaseJellyfinApiController
+    {
+        private readonly ITaskManager _taskManager;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ScheduledTasksController"/> class.
+        /// </summary>
+        /// <param name="taskManager">Instance of the <see cref="ITaskManager"/> interface.</param>
+        public ScheduledTasksController(ITaskManager taskManager)
+        {
+            _taskManager = taskManager;
+        }
+
+        /// <summary>
+        /// Get tasks.
+        /// </summary>
+        /// <param name="isHidden">Optional filter tasks that are hidden, or not.</param>
+        /// <param name="isEnabled">Optional filter tasks that are enabled, or not.</param>
+        /// <response code="200">Scheduled tasks retrieved.</response>
+        /// <returns>The list of scheduled tasks.</returns>
+        [HttpGet]
+        [ProducesResponseType(StatusCodes.Status200OK)]
+        public IEnumerable<IScheduledTaskWorker> GetTasks(
+            [FromQuery] bool? isHidden,
+            [FromQuery] bool? isEnabled)
+        {
+            IEnumerable<IScheduledTaskWorker> tasks = _taskManager.ScheduledTasks.OrderBy(o => o.Name);
+
+            foreach (var task in tasks)
+            {
+                if (task.ScheduledTask is IConfigurableScheduledTask scheduledTask)
+                {
+                    if (isHidden.HasValue && isHidden.Value != scheduledTask.IsHidden)
+                    {
+                        continue;
+                    }
+
+                    if (isEnabled.HasValue && isEnabled.Value != scheduledTask.IsEnabled)
+                    {
+                        continue;
+                    }
+                }
+
+                yield return task;
+            }
+        }
+
+        /// <summary>
+        /// Get task by id.
+        /// </summary>
+        /// <param name="taskId">Task Id.</param>
+        /// <response code="200">Task retrieved.</response>
+        /// <response code="404">Task not found.</response>
+        /// <returns>An <see cref="OkResult"/> containing the task on success, or a <see cref="NotFoundResult"/> if the task could not be found.</returns>
+        [HttpGet("{taskId}")]
+        [ProducesResponseType(StatusCodes.Status200OK)]
+        [ProducesResponseType(StatusCodes.Status404NotFound)]
+        public ActionResult<TaskInfo> GetTask([FromRoute] string taskId)
+        {
+            var task = _taskManager.ScheduledTasks.FirstOrDefault(i =>
+                string.Equals(i.Id, taskId, StringComparison.OrdinalIgnoreCase));
+
+            if (task == null)
+            {
+                return NotFound();
+            }
+
+            return ScheduledTaskHelpers.GetTaskInfo(task);
+        }
+
+        /// <summary>
+        /// Start specified task.
+        /// </summary>
+        /// <param name="taskId">Task Id.</param>
+        /// <response code="204">Task started.</response>
+        /// <response code="404">Task not found.</response>
+        /// <returns>An <see cref="NoContentResult"/> on success, or a <see cref="NotFoundResult"/> if the file could not be found.</returns>
+        [HttpPost("Running/{taskId}")]
+        [ProducesResponseType(StatusCodes.Status204NoContent)]
+        [ProducesResponseType(StatusCodes.Status404NotFound)]
+        public ActionResult StartTask([FromRoute] string taskId)
+        {
+            var task = _taskManager.ScheduledTasks.FirstOrDefault(o =>
+                o.Id.Equals(taskId, StringComparison.OrdinalIgnoreCase));
+
+            if (task == null)
+            {
+                return NotFound();
+            }
+
+            _taskManager.Execute(task, new TaskOptions());
+            return NoContent();
+        }
+
+        /// <summary>
+        /// Stop specified task.
+        /// </summary>
+        /// <param name="taskId">Task Id.</param>
+        /// <response code="204">Task stopped.</response>
+        /// <response code="404">Task not found.</response>
+        /// <returns>An <see cref="OkResult"/> on success, or a <see cref="NotFoundResult"/> if the file could not be found.</returns>
+        [HttpDelete("Running/{taskId}")]
+        [ProducesResponseType(StatusCodes.Status204NoContent)]
+        [ProducesResponseType(StatusCodes.Status404NotFound)]
+        public ActionResult StopTask([FromRoute] string taskId)
+        {
+            var task = _taskManager.ScheduledTasks.FirstOrDefault(o =>
+                o.Id.Equals(taskId, StringComparison.OrdinalIgnoreCase));
+
+            if (task == null)
+            {
+                return NotFound();
+            }
+
+            _taskManager.Cancel(task);
+            return NoContent();
+        }
+
+        /// <summary>
+        /// Update specified task triggers.
+        /// </summary>
+        /// <param name="taskId">Task Id.</param>
+        /// <param name="triggerInfos">Triggers.</param>
+        /// <response code="204">Task triggers updated.</response>
+        /// <response code="404">Task not found.</response>
+        /// <returns>An <see cref="OkResult"/> on success, or a <see cref="NotFoundResult"/> if the file could not be found.</returns>
+        [HttpPost("{taskId}/Triggers")]
+        [ProducesResponseType(StatusCodes.Status204NoContent)]
+        [ProducesResponseType(StatusCodes.Status404NotFound)]
+        public ActionResult UpdateTask(
+            [FromRoute] string taskId,
+            [FromBody, BindRequired] TaskTriggerInfo[] triggerInfos)
+        {
+            var task = _taskManager.ScheduledTasks.FirstOrDefault(o =>
+                o.Id.Equals(taskId, StringComparison.OrdinalIgnoreCase));
+            if (task == null)
+            {
+                return NotFound();
+            }
+
+            task.Triggers = triggerInfos;
+            return NoContent();
+        }
+    }
+}

+ 0 - 234
MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs

@@ -1,234 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using MediaBrowser.Common.Extensions;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Model.Services;
-using MediaBrowser.Model.Tasks;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Api.ScheduledTasks
-{
-    /// <summary>
-    /// Class GetScheduledTask
-    /// </summary>
-    [Route("/ScheduledTasks/{Id}", "GET", Summary = "Gets a scheduled task, by Id")]
-    public class GetScheduledTask : IReturn<TaskInfo>
-    {
-        /// <summary>
-        /// Gets or sets the id.
-        /// </summary>
-        /// <value>The id.</value>
-        [ApiMember(Name = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string Id { get; set; }
-    }
-
-    /// <summary>
-    /// Class GetScheduledTasks
-    /// </summary>
-    [Route("/ScheduledTasks", "GET", Summary = "Gets scheduled tasks")]
-    public class GetScheduledTasks : IReturn<TaskInfo[]>
-    {
-        [ApiMember(Name = "IsHidden", Description = "Optional filter tasks that are hidden, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
-        public bool? IsHidden { get; set; }
-
-        [ApiMember(Name = "IsEnabled", Description = "Optional filter tasks that are enabled, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
-        public bool? IsEnabled { get; set; }
-    }
-
-    /// <summary>
-    /// Class StartScheduledTask
-    /// </summary>
-    [Route("/ScheduledTasks/Running/{Id}", "POST", Summary = "Starts a scheduled task")]
-    public class StartScheduledTask : IReturnVoid
-    {
-        /// <summary>
-        /// Gets or sets the id.
-        /// </summary>
-        /// <value>The id.</value>
-        [ApiMember(Name = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
-        public string Id { get; set; }
-    }
-
-    /// <summary>
-    /// Class StopScheduledTask
-    /// </summary>
-    [Route("/ScheduledTasks/Running/{Id}", "DELETE", Summary = "Stops a scheduled task")]
-    public class StopScheduledTask : IReturnVoid
-    {
-        /// <summary>
-        /// Gets or sets the id.
-        /// </summary>
-        /// <value>The id.</value>
-        [ApiMember(Name = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
-        public string Id { get; set; }
-    }
-
-    /// <summary>
-    /// Class UpdateScheduledTaskTriggers
-    /// </summary>
-    [Route("/ScheduledTasks/{Id}/Triggers", "POST", Summary = "Updates the triggers for a scheduled task")]
-    public class UpdateScheduledTaskTriggers : List<TaskTriggerInfo>, IReturnVoid
-    {
-        /// <summary>
-        /// Gets or sets the task id.
-        /// </summary>
-        /// <value>The task id.</value>
-        [ApiMember(Name = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
-        public string Id { get; set; }
-    }
-
-    /// <summary>
-    /// Class ScheduledTasksService
-    /// </summary>
-    [Authenticated(Roles = "Admin")]
-    public class ScheduledTaskService : BaseApiService
-    {
-        /// <summary>
-        /// The task manager.
-        /// </summary>
-        private readonly ITaskManager _taskManager;
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ScheduledTaskService" /> class.
-        /// </summary>
-        /// <param name="taskManager">The task manager.</param>
-        /// <exception cref="ArgumentNullException">taskManager</exception>
-        public ScheduledTaskService(
-            ILogger<ScheduledTaskService> logger,
-            IServerConfigurationManager serverConfigurationManager,
-            IHttpResultFactory httpResultFactory,
-            ITaskManager taskManager)
-            : base(logger, serverConfigurationManager, httpResultFactory)
-        {
-            _taskManager = taskManager;
-        }
-
-        /// <summary>
-        /// Gets the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>IEnumerable{TaskInfo}.</returns>
-        public object Get(GetScheduledTasks request)
-        {
-            IEnumerable<IScheduledTaskWorker> result = _taskManager.ScheduledTasks
-                .OrderBy(i => i.Name);
-
-            if (request.IsHidden.HasValue)
-            {
-                var val = request.IsHidden.Value;
-
-                result = result.Where(i =>
-                {
-                    var isHidden = false;
-
-                    if (i.ScheduledTask is IConfigurableScheduledTask configurableTask)
-                    {
-                        isHidden = configurableTask.IsHidden;
-                    }
-
-                    return isHidden == val;
-                });
-            }
-
-            if (request.IsEnabled.HasValue)
-            {
-                var val = request.IsEnabled.Value;
-
-                result = result.Where(i =>
-                {
-                    var isEnabled = true;
-
-                    if (i.ScheduledTask is IConfigurableScheduledTask configurableTask)
-                    {
-                        isEnabled = configurableTask.IsEnabled;
-                    }
-
-                    return isEnabled == val;
-                });
-            }
-
-            var infos = result
-                .Select(ScheduledTaskHelpers.GetTaskInfo)
-                .ToArray();
-
-            return ToOptimizedResult(infos);
-        }
-
-        /// <summary>
-        /// Gets the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>IEnumerable{TaskInfo}.</returns>
-        /// <exception cref="ResourceNotFoundException">Task not found</exception>
-        public object Get(GetScheduledTask request)
-        {
-            var task = _taskManager.ScheduledTasks.FirstOrDefault(i => string.Equals(i.Id, request.Id));
-
-            if (task == null)
-            {
-                throw new ResourceNotFoundException("Task not found");
-            }
-
-            var result = ScheduledTaskHelpers.GetTaskInfo(task);
-
-            return ToOptimizedResult(result);
-        }
-
-        /// <summary>
-        /// Posts the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <exception cref="ResourceNotFoundException">Task not found</exception>
-        public void Post(StartScheduledTask request)
-        {
-            var task = _taskManager.ScheduledTasks.FirstOrDefault(i => string.Equals(i.Id, request.Id));
-
-            if (task == null)
-            {
-                throw new ResourceNotFoundException("Task not found");
-            }
-
-            _taskManager.Execute(task, new TaskOptions());
-        }
-
-        /// <summary>
-        /// Posts the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <exception cref="ResourceNotFoundException">Task not found</exception>
-        public void Delete(StopScheduledTask request)
-        {
-            var task = _taskManager.ScheduledTasks.FirstOrDefault(i => string.Equals(i.Id, request.Id));
-
-            if (task == null)
-            {
-                throw new ResourceNotFoundException("Task not found");
-            }
-
-            _taskManager.Cancel(task);
-        }
-
-        /// <summary>
-        /// Posts the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <exception cref="ResourceNotFoundException">Task not found</exception>
-        public void Post(UpdateScheduledTaskTriggers request)
-        {
-            // We need to parse this manually because we told service stack not to with IRequiresRequestStream
-            // https://code.google.com/p/servicestack/source/browse/trunk/Common/ServiceStack.Text/ServiceStack.Text/Controller/PathInfo.cs
-            var id = GetPathValue(1).ToString();
-
-            var task = _taskManager.ScheduledTasks.FirstOrDefault(i => string.Equals(i.Id, id, StringComparison.Ordinal));
-
-            if (task == null)
-            {
-                throw new ResourceNotFoundException("Task not found");
-            }
-
-            task.Triggers = request.ToArray();
-        }
-    }
-}

+ 56 - 0
MediaBrowser.Common/Json/Converters/JsonInt64Converter.cs

@@ -0,0 +1,56 @@
+using System;
+using System.Buffers;
+using System.Buffers.Text;
+using System.Globalization;
+using System.Text.Json;
+using System.Text.Json.Serialization;
+
+namespace MediaBrowser.Common.Json.Converters
+{
+    /// <summary>
+    /// Long to String JSON converter.
+    /// Javascript does not support 64-bit integers.
+    /// </summary>
+    public class JsonInt64Converter : JsonConverter<long>
+    {
+        /// <summary>
+        /// Read JSON string as int64.
+        /// </summary>
+        /// <param name="reader"><see cref="Utf8JsonReader"/>.</param>
+        /// <param name="type">Type.</param>
+        /// <param name="options">Options.</param>
+        /// <returns>Parsed value.</returns>
+        public override long Read(ref Utf8JsonReader reader, Type type, JsonSerializerOptions options)
+        {
+            if (reader.TokenType == JsonTokenType.String)
+            {
+                // try to parse number directly from bytes
+                var span = reader.HasValueSequence ? reader.ValueSequence.ToArray() : reader.ValueSpan;
+                if (Utf8Parser.TryParse(span, out long number, out var bytesConsumed) && span.Length == bytesConsumed)
+                {
+                    return number;
+                }
+
+                // try to parse from a string if the above failed, this covers cases with other escaped/UTF characters
+                if (long.TryParse(reader.GetString(), out number))
+                {
+                    return number;
+                }
+            }
+
+            // fallback to default handling
+            return reader.GetInt64();
+        }
+
+        /// <summary>
+        /// Write long to JSON string.
+        /// </summary>
+        /// <param name="writer"><see cref="Utf8JsonWriter"/>.</param>
+        /// <param name="value">Value to write.</param>
+        /// <param name="options">Options.</param>
+        public override void Write(Utf8JsonWriter writer, long value, JsonSerializerOptions options)
+        {
+            writer.WriteStringValue(value.ToString(NumberFormatInfo.InvariantInfo));
+        }
+    }
+}

+ 1 - 0
MediaBrowser.Common/Json/JsonDefaults.cs

@@ -31,6 +31,7 @@ namespace MediaBrowser.Common.Json
             options.Converters.Add(new JsonInt32Converter());
             options.Converters.Add(new JsonStringEnumConverter());
             options.Converters.Add(new JsonNonStringKeyDictionaryConverterFactory());
+            options.Converters.Add(new JsonInt64Converter());
 
             return options;
         }