2023-12-08 02:42:46 +01:00

105 lines
3.4 KiB
C#

// Kyoo - A portable and vast media library solution.
// Copyright (c) Kyoo.
//
// See AUTHORS.md and LICENSE file in the project root for full license information.
//
// Kyoo is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// Kyoo is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using Kyoo.Abstractions.Controllers;
using Kyoo.Abstractions.Models;
using Kyoo.Utils;
using Microsoft.AspNetCore.Mvc;
namespace Kyoo.Core.Api
{
/// <summary>
/// A common API containing custom methods to help inheritors.
/// </summary>
public abstract class BaseApi : ControllerBase
{
/// <summary>
/// Construct and return a page from an api.
/// </summary>
/// <param name="resources">The list of resources that should be included in the current page.</param>
/// <param name="limit">
/// The max number of items that should be present per page. This should be the same as in the request,
/// it is used to calculate if this is the last page and so on.
/// </param>
/// <typeparam name="TResult">The type of items on the page.</typeparam>
/// <returns>A Page representing the response.</returns>
protected Page<TResult> Page<TResult>(ICollection<TResult> resources, int limit)
where TResult : IResource
{
Dictionary<string, string> query = Request
.Query
.ToDictionary(
x => x.Key,
x => x.Value.ToString(),
StringComparer.InvariantCultureIgnoreCase
);
// If the query was sorted randomly, add the seed to the url to get reproducible links (next,prev,first...)
if (query.ContainsKey("sortBy"))
{
object seed = HttpContext.Items["seed"]!;
query["sortBy"] = Regex.Replace(query["sortBy"], "random(?!:)", $"random:{seed}");
}
return new Page<TResult>(resources, Request.Path, query, limit);
}
protected SearchPage<TResult> SearchPage<TResult>(SearchPage<TResult>.SearchResult result)
where TResult : IResource
{
Dictionary<string, string> query = Request
.Query
.ToDictionary(
x => x.Key,
x => x.Value.ToString(),
StringComparer.InvariantCultureIgnoreCase
);
string self = Request.Path + query.ToQueryString();
string? previous = null;
string? next = null;
string first;
int limit = query.TryGetValue("limit", out string? limitStr)
? int.Parse(limitStr)
: new SearchPagination().Limit;
int? skip = query.TryGetValue("skip", out string? skipStr) ? int.Parse(skipStr) : null;
if (skip != null)
{
query["skip"] = Math.Max(0, skip.Value - limit).ToString();
previous = Request.Path + query.ToQueryString();
}
if (result.Items.Count == limit && limit > 0)
{
int newSkip = skip.HasValue ? skip.Value + limit : limit;
query["skip"] = newSkip.ToString();
next = Request.Path + query.ToQueryString();
}
query.Remove("skip");
first = Request.Path + query.ToQueryString();
return new SearchPage<TResult>(result, self, previous, next, first);
}
}
}