mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-06-23 07:20:33 -04:00
Serializer: Reworking images serialization
This commit is contained in:
parent
1cd88a8bfe
commit
96494ecf28
@ -1,51 +0,0 @@
|
||||
// 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;
|
||||
|
||||
namespace Kyoo.Abstractions.Models.Attributes
|
||||
{
|
||||
/// <summary>
|
||||
/// Change the way the field is serialized. It allow one to use a string format like formatting instead of the default value.
|
||||
/// This can be disabled for a request by setting the "internal" query string parameter to true.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
|
||||
public class SerializeAsAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// The format string to use.
|
||||
/// </summary>
|
||||
public string Format { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="SerializeAsAttribute"/> with the selected format.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The format string can contains any property within {}. It will be replaced by the actual value of the property.
|
||||
/// You can also use the special value {HOST} that will put the webhost address.
|
||||
/// </remarks>
|
||||
/// <example>
|
||||
/// The show's poster serialized uses this format string: <code>{HOST}/api/shows/{Slug}/poster</code>
|
||||
/// </example>
|
||||
/// <param name="format">The format to use</param>
|
||||
public SerializeAsAttribute(string format)
|
||||
{
|
||||
Format = format;
|
||||
}
|
||||
}
|
||||
}
|
@ -19,7 +19,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
using Kyoo.Abstractions.Models.Attributes;
|
||||
|
||||
namespace Kyoo.Abstractions.Models
|
||||
{
|
||||
@ -86,14 +85,6 @@ namespace Kyoo.Abstractions.Models
|
||||
/// <inheritdoc />
|
||||
public Dictionary<int, string> Images { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The path of this item's poster.
|
||||
/// By default, the http path for this poster is returned from the public API.
|
||||
/// This can be disabled using the internal query flag.
|
||||
/// </summary>
|
||||
[SerializeAs("{HOST}/api/{Type:l}/{Slug}/poster")]
|
||||
public string Poster => Images?.GetValueOrDefault(Models.Images.Poster);
|
||||
|
||||
/// <summary>
|
||||
/// The type of this item (ether a collection, a show or a movie).
|
||||
/// </summary>
|
||||
|
@ -16,7 +16,6 @@
|
||||
// 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 Kyoo.Abstractions.Models.Attributes;
|
||||
|
||||
@ -42,15 +41,6 @@ namespace Kyoo.Abstractions.Models
|
||||
/// <inheritdoc />
|
||||
public Dictionary<int, string> Images { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The path of this poster.
|
||||
/// By default, the http path for this poster is returned from the public API.
|
||||
/// This can be disabled using the internal query flag.
|
||||
/// </summary>
|
||||
[SerializeAs("{HOST}/api/collection/{Slug}/poster")]
|
||||
[Obsolete("Use Images instead of this, this is only kept for the API response.")]
|
||||
public string Poster => Images?.GetValueOrDefault(Models.Images.Poster);
|
||||
|
||||
/// <summary>
|
||||
/// The description of this collection.
|
||||
/// </summary>
|
||||
|
@ -127,15 +127,6 @@ namespace Kyoo.Abstractions.Models
|
||||
/// <inheritdoc />
|
||||
public Dictionary<int, string> Images { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The path of this episode's thumbnail.
|
||||
/// By default, the http path for the thumbnail is returned from the public API.
|
||||
/// This can be disabled using the internal query flag.
|
||||
/// </summary>
|
||||
[SerializeAs("{HOST}/api/episodes/{Slug}/thumbnail")]
|
||||
[Obsolete("Use Images instead of this, this is only kept for the API response.")]
|
||||
public string Thumb => Images?.GetValueOrDefault(Models.Images.Thumbnail);
|
||||
|
||||
/// <summary>
|
||||
/// The title of this episode.
|
||||
/// </summary>
|
||||
|
@ -34,8 +34,6 @@ namespace Kyoo.Abstractions.Models
|
||||
/// An arbitrary index should not be used, instead use indexes from <see cref="Models.Images"/>
|
||||
/// </remarks>
|
||||
public Dictionary<int, string> Images { get; set; }
|
||||
|
||||
// TODO remove Posters properties add them via the json serializer for every IThumbnails
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -63,5 +61,17 @@ namespace Kyoo.Abstractions.Models
|
||||
/// A video of a few minutes that tease the content.
|
||||
/// </summary>
|
||||
public const int Trailer = 3;
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the name of an image using it's ID. It is also used by the serializer to retrieve all named images.
|
||||
/// If a plugin adds a new image type, it should add it's value and name here to allow the serializer to add it.
|
||||
/// </summary>
|
||||
public static Dictionary<int, string> ImageName { get; } = new()
|
||||
{
|
||||
[Poster] = nameof(Poster),
|
||||
[Thumbnail] = nameof(Thumbnail),
|
||||
[Logo] = nameof(Logo),
|
||||
[Trailer] = nameof(Trailer)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,6 @@
|
||||
// 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 Kyoo.Abstractions.Models.Attributes;
|
||||
|
||||
@ -41,15 +40,6 @@ namespace Kyoo.Abstractions.Models
|
||||
/// <inheritdoc />
|
||||
public Dictionary<int, string> Images { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The path of this poster.
|
||||
/// By default, the http path for this poster is returned from the public API.
|
||||
/// This can be disabled using the internal query flag.
|
||||
/// </summary>
|
||||
[SerializeAs("{HOST}/api/people/{Slug}/poster")]
|
||||
[Obsolete("Use Images instead of this, this is only kept for the API response.")]
|
||||
public string Poster => Images?.GetValueOrDefault(Models.Images.Poster);
|
||||
|
||||
/// <inheritdoc />
|
||||
[EditableRelation] [LoadableRelation] public ICollection<MetadataID> ExternalIDs { get; set; }
|
||||
|
||||
|
@ -16,7 +16,6 @@
|
||||
// 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 Kyoo.Abstractions.Controllers;
|
||||
using Kyoo.Abstractions.Models.Attributes;
|
||||
@ -44,15 +43,6 @@ namespace Kyoo.Abstractions.Models
|
||||
/// <inheritdoc />
|
||||
public Dictionary<int, string> Images { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The path of this provider's logo.
|
||||
/// By default, the http path for this logo is returned from the public API.
|
||||
/// This can be disabled using the internal query flag.
|
||||
/// </summary>
|
||||
[SerializeAs("{HOST}/api/providers/{Slug}/logo")]
|
||||
[Obsolete("Use Images instead of this, this is only kept for the API response.")]
|
||||
public string Logo => Images?.GetValueOrDefault(Models.Images.Logo);
|
||||
|
||||
/// <summary>
|
||||
/// The list of libraries that uses this provider.
|
||||
/// </summary>
|
||||
|
@ -98,15 +98,6 @@ namespace Kyoo.Abstractions.Models
|
||||
/// <inheritdoc />
|
||||
public Dictionary<int, string> Images { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The path of this poster.
|
||||
/// By default, the http path for this poster is returned from the public API.
|
||||
/// This can be disabled using the internal query flag.
|
||||
/// </summary>
|
||||
[SerializeAs("{HOST}/api/seasons/{Slug}/thumb")]
|
||||
[Obsolete("Use Images instead of this, this is only kept for the API response.")]
|
||||
public string Poster => Images?.GetValueOrDefault(Models.Images.Poster);
|
||||
|
||||
/// <inheritdoc />
|
||||
[EditableRelation] [LoadableRelation] public ICollection<MetadataID> ExternalIDs { get; set; }
|
||||
|
||||
|
@ -82,33 +82,6 @@ namespace Kyoo.Abstractions.Models
|
||||
/// <inheritdoc />
|
||||
public Dictionary<int, string> Images { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The path of this show's poster.
|
||||
/// By default, the http path for this poster is returned from the public API.
|
||||
/// This can be disabled using the internal query flag.
|
||||
/// </summary>
|
||||
[SerializeAs("{HOST}/api/shows/{Slug}/poster")]
|
||||
[Obsolete("Use Images instead of this, this is only kept for the API response.")]
|
||||
public string Poster => Images?.GetValueOrDefault(Models.Images.Poster);
|
||||
|
||||
/// <summary>
|
||||
/// The path of this show's logo.
|
||||
/// By default, the http path for this logo is returned from the public API.
|
||||
/// This can be disabled using the internal query flag.
|
||||
/// </summary>
|
||||
[SerializeAs("{HOST}/api/shows/{Slug}/logo")]
|
||||
[Obsolete("Use Images instead of this, this is only kept for the API response.")]
|
||||
public string Logo => Images?.GetValueOrDefault(Models.Images.Logo);
|
||||
|
||||
/// <summary>
|
||||
/// The path of this show's backdrop.
|
||||
/// By default, the http path for this backdrop is returned from the public API.
|
||||
/// This can be disabled using the internal query flag.
|
||||
/// </summary>
|
||||
[SerializeAs("{HOST}/api/shows/{Slug}/backdrop")]
|
||||
[Obsolete("Use Images instead of this, this is only kept for the API response.")]
|
||||
public string Backdrop => Images?.GetValueOrDefault(Models.Images.Thumbnail);
|
||||
|
||||
/// <summary>
|
||||
/// True if this show represent a movie, false otherwise.
|
||||
/// </summary>
|
||||
|
@ -101,27 +101,6 @@ namespace Kyoo.Abstractions.Models
|
||||
/// </summary>
|
||||
public bool IsMovie { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The path of this item's poster.
|
||||
/// By default, the http path for the poster is returned from the public API.
|
||||
/// This can be disabled using the internal query flag.
|
||||
/// </summary>
|
||||
[SerializeAs("{HOST}/api/show/{ShowSlug}/poster")] public string Poster { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The path of this item's logo.
|
||||
/// By default, the http path for the logo is returned from the public API.
|
||||
/// This can be disabled using the internal query flag.
|
||||
/// </summary>
|
||||
[SerializeAs("{HOST}/api/show/{ShowSlug}/logo")] public string Logo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The path of this item's backdrop.
|
||||
/// By default, the http path for the backdrop is returned from the public API.
|
||||
/// This can be disabled using the internal query flag.
|
||||
/// </summary>
|
||||
[SerializeAs("{HOST}/api/show/{ShowSlug}/backdrop")] public string Backdrop { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The container of the video file of this episode.
|
||||
/// Common containers are mp4, mkv, avi and so on.
|
||||
|
@ -36,7 +36,7 @@ namespace Kyoo.Core.Api
|
||||
/// Make an expression (like
|
||||
/// <see cref="Expression.LessThan(System.Linq.Expressions.Expression,System.Linq.Expressions.Expression)"/>
|
||||
/// compatible with strings). If the expressions are not strings, the given <paramref name="operand"/> is
|
||||
/// constructed but if the expressions are strings, this method make the <param name="operand"/> compatible with
|
||||
/// constructed but if the expressions are strings, this method make the <paramref name="operand"/> compatible with
|
||||
/// strings.
|
||||
/// </summary>
|
||||
/// <param name="operand">
|
||||
|
@ -16,6 +16,7 @@
|
||||
// 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.Reflection;
|
||||
using Kyoo.Abstractions.Models;
|
||||
@ -70,13 +71,74 @@ namespace Kyoo.Core.Api
|
||||
property.ShouldSerialize = _ => false;
|
||||
if (member.GetCustomAttribute<DeserializeIgnoreAttribute>() != null)
|
||||
property.ShouldDeserialize = _ => false;
|
||||
|
||||
// TODO use http context to disable serialize as.
|
||||
// TODO check https://stackoverflow.com/questions/53288633/net-core-api-custom-json-resolver-based-on-request-values
|
||||
// SerializeAsAttribute serializeAs = member.GetCustomAttribute<SerializeAsAttribute>();
|
||||
// if (serializeAs != null)
|
||||
// property.ValueProvider = new SerializeAsProvider(serializeAs.Format, _host);
|
||||
return property;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
|
||||
{
|
||||
IList<JsonProperty> properties = base.CreateProperties(type, memberSerialization);
|
||||
if (!type.IsAssignableTo(typeof(IThumbnails)))
|
||||
return properties;
|
||||
foreach ((int id, string image) in Images.ImageName)
|
||||
{
|
||||
properties.Add(new JsonProperty
|
||||
{
|
||||
DeclaringType = type,
|
||||
PropertyName = image.ToLower(),
|
||||
UnderlyingName = image,
|
||||
PropertyType = typeof(string),
|
||||
Readable = true,
|
||||
Writable = false,
|
||||
ItemIsReference = false,
|
||||
TypeNameHandling = TypeNameHandling.None,
|
||||
ShouldSerialize = x =>
|
||||
{
|
||||
IThumbnails thumb = (IThumbnails)x;
|
||||
return thumb.Images?.ContainsKey(id) == true;
|
||||
},
|
||||
ValueProvider = new ThumbnailProvider(id)
|
||||
});
|
||||
}
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A custom <see cref="IValueProvider"/> that uses the
|
||||
/// <see cref="IThumbnails"/>.<see cref="IThumbnails.Images"/> as a value.
|
||||
/// </summary>
|
||||
private class ThumbnailProvider : IValueProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// The index/ID of the image to retrieve/set.
|
||||
/// </summary>
|
||||
private readonly int _imageIndex;
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="ThumbnailProvider"/>.
|
||||
/// </summary>
|
||||
/// <param name="imageIndex">The index/ID of the image to retrieve/set.</param>
|
||||
public ThumbnailProvider(int imageIndex)
|
||||
{
|
||||
_imageIndex = imageIndex;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void SetValue(object target, object value)
|
||||
{
|
||||
if (target is not IThumbnails thumb)
|
||||
throw new ArgumentException($"The given object is not an Thumbnail.");
|
||||
thumb.Images[_imageIndex] = value as string;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public object GetValue(object target)
|
||||
{
|
||||
if (target is IThumbnails thumb)
|
||||
return thumb.Images?.GetValueOrDefault(_imageIndex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,77 +0,0 @@
|
||||
// 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.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text.RegularExpressions;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
|
||||
namespace Kyoo.Core.Api
|
||||
{
|
||||
public class SerializeAsProvider : IValueProvider
|
||||
{
|
||||
private readonly string _format;
|
||||
private readonly Uri _host;
|
||||
|
||||
public SerializeAsProvider(string format, Uri host)
|
||||
{
|
||||
_format = format;
|
||||
_host = host;
|
||||
}
|
||||
|
||||
public object GetValue(object target)
|
||||
{
|
||||
return Regex.Replace(_format, @"(?<!{){(\w+)(:(\w+))?}", x =>
|
||||
{
|
||||
string value = x.Groups[1].Value;
|
||||
string modifier = x.Groups[3].Value;
|
||||
|
||||
if (value == "HOST")
|
||||
return _host.ToString().TrimEnd('/');
|
||||
|
||||
PropertyInfo properties = target.GetType()
|
||||
.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
|
||||
.FirstOrDefault(y => y.Name == value);
|
||||
if (properties == null)
|
||||
return null;
|
||||
object objValue = properties.GetValue(target);
|
||||
if (objValue is not string ret)
|
||||
ret = objValue?.ToString();
|
||||
if (ret == null)
|
||||
throw new ArgumentException($"Invalid serializer replacement {value}");
|
||||
|
||||
foreach (char modification in modifier)
|
||||
{
|
||||
ret = modification switch
|
||||
{
|
||||
'l' => ret.ToLowerInvariant(),
|
||||
'u' => ret.ToUpperInvariant(),
|
||||
_ => throw new ArgumentException($"Invalid serializer modificator {modification}.")
|
||||
};
|
||||
}
|
||||
return ret;
|
||||
});
|
||||
}
|
||||
|
||||
public void SetValue(object target, object value)
|
||||
{
|
||||
// Values are ignored and should not be editable, except if the internal value is set.
|
||||
}
|
||||
}
|
||||
}
|
@ -15,7 +15,8 @@ namespace Kyoo.Postgresql.Migrations
|
||||
[Migration("20210801171613_Initial")]
|
||||
partial class Initial
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
|
@ -15,6 +15,7 @@ namespace Kyoo.Postgresql.Migrations
|
||||
[Migration("20210801171641_Triggers")]
|
||||
partial class Triggers
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
|
@ -12,6 +12,7 @@ namespace Kyoo.SqLite.Migrations
|
||||
[Migration("20210801171534_Initial")]
|
||||
partial class Initial
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
|
@ -12,6 +12,7 @@ namespace Kyoo.SqLite.Migrations
|
||||
[Migration("20210801171544_Triggers")]
|
||||
partial class Triggers
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
|
Loading…
x
Reference in New Issue
Block a user