mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-06-03 21:54:49 -04:00
Serializing images paths
This commit is contained in:
parent
356b8a5472
commit
779702f969
@ -7,4 +7,15 @@ namespace Kyoo.Models.Attributes
|
||||
|
||||
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
|
||||
public class DeserializeIgnoreAttribute : Attribute {}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
|
||||
public class SerializeAsAttribute : Attribute
|
||||
{
|
||||
public string Format { get; }
|
||||
|
||||
public SerializeAsAttribute(string format)
|
||||
{
|
||||
Format = format;
|
||||
}
|
||||
}
|
||||
}
|
@ -8,7 +8,7 @@ namespace Kyoo.Models
|
||||
public int ID { get; set; }
|
||||
public string Slug { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Poster { get; set; }
|
||||
[SerializeAs("{HOST}/api/library/{Slug}/poster")] public string Poster { get; set; }
|
||||
public string Overview { get; set; }
|
||||
[LoadableRelation] public virtual ICollection<Show> Shows { get; set; }
|
||||
[LoadableRelation] public virtual ICollection<Library> Libraries { get; set; }
|
||||
|
@ -19,14 +19,14 @@ namespace Kyoo.Models
|
||||
public int EpisodeNumber { get; set; } = -1;
|
||||
public int AbsoluteNumber { get; set; } = -1;
|
||||
[SerializeIgnore] public string Path { get; set; }
|
||||
public string Thumb => $"/api/episodes/{Slug}/thumb";
|
||||
|
||||
[SerializeAs("{HOST}/api/episodes/{Slug}/thumb")] public string Thumb { get; set; }
|
||||
public string Title { get; set; }
|
||||
public string Overview { get; set; }
|
||||
public DateTime? ReleaseDate { get; set; }
|
||||
|
||||
public int Runtime { get; set; } //This runtime variable should be in minutes
|
||||
|
||||
[SerializeIgnore] public string Poster { get; set; }
|
||||
[LoadableRelation] public virtual ICollection<MetadataID> ExternalIDs { get; set; }
|
||||
|
||||
[LoadableRelation] public virtual ICollection<Track> Tracks { get; set; }
|
||||
@ -41,7 +41,7 @@ namespace Kyoo.Models
|
||||
string overview,
|
||||
DateTime? releaseDate,
|
||||
int runtime,
|
||||
string poster,
|
||||
string thumb,
|
||||
IEnumerable<MetadataID> externalIDs)
|
||||
{
|
||||
SeasonNumber = seasonNumber;
|
||||
@ -51,7 +51,7 @@ namespace Kyoo.Models
|
||||
Overview = overview;
|
||||
ReleaseDate = releaseDate;
|
||||
Runtime = runtime;
|
||||
Poster = poster;
|
||||
Thumb = thumb;
|
||||
ExternalIDs = externalIDs?.ToArray();
|
||||
}
|
||||
|
||||
|
@ -18,8 +18,7 @@ namespace Kyoo.Models
|
||||
public string Overview { get; set; }
|
||||
public int? Year { get; set; }
|
||||
|
||||
[SerializeIgnore] public string Poster { get; set; }
|
||||
public string Thumb => $"/api/seasons/{Slug}/thumb";
|
||||
[SerializeAs("{HOST}/api/seasons/{Slug}/thumb")] public string Poster { get; set; }
|
||||
[EditableRelation] [LoadableRelation] public virtual ICollection<MetadataID> ExternalIDs { get; set; }
|
||||
|
||||
[LoadableRelation] public virtual ICollection<Episode> Episodes { get; set; }
|
||||
|
@ -18,9 +18,9 @@ namespace Kyoo.Models
|
||||
public int? StartYear { get; set; }
|
||||
public int? EndYear { get; set; }
|
||||
|
||||
public string Poster { get; set; }
|
||||
public string Logo { get; set; }
|
||||
public string Backdrop { get; set; }
|
||||
[SerializeAs("{HOST}/api/shows/{Slug}/poster")] public string Poster { get; set; }
|
||||
[SerializeAs("{HOST}/api/shows/{Slug}/logo")] public string Logo { get; set; }
|
||||
[SerializeAs("{HOST}/api/shows/{Slug}/backdrop")] public string Backdrop { get; set; }
|
||||
|
||||
public bool IsMovie { get; set; }
|
||||
|
||||
|
@ -1,7 +1,9 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text.RegularExpressions;
|
||||
using Kyoo.Models;
|
||||
using Kyoo.Models.Attributes;
|
||||
using Newtonsoft.Json;
|
||||
@ -13,7 +15,13 @@ namespace Kyoo.Controllers
|
||||
public class JsonPropertyIgnorer : CamelCasePropertyNamesContractResolver
|
||||
{
|
||||
private int _depth = -1;
|
||||
|
||||
private string _host;
|
||||
|
||||
public JsonPropertyIgnorer(string host)
|
||||
{
|
||||
_host = host;
|
||||
}
|
||||
|
||||
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
|
||||
{
|
||||
JsonProperty property = base.CreateProperty(member, memberSerialization);
|
||||
@ -38,6 +46,10 @@ namespace Kyoo.Controllers
|
||||
property.ShouldSerialize = _ => false;
|
||||
if (member?.GetCustomAttribute<DeserializeIgnoreAttribute>() != null)
|
||||
property.ShouldDeserialize = _ => false;
|
||||
|
||||
SerializeAsAttribute serializeAs = member?.GetCustomAttribute<SerializeAsAttribute>();
|
||||
if (serializeAs != null)
|
||||
property.ValueProvider = new SerializeAsProvider(serializeAs.Format, _host);
|
||||
return property;
|
||||
}
|
||||
|
||||
@ -86,4 +98,40 @@ namespace Kyoo.Controllers
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public class SerializeAsProvider : IValueProvider
|
||||
{
|
||||
private string _format;
|
||||
private string _host;
|
||||
|
||||
public SerializeAsProvider(string format, string host)
|
||||
{
|
||||
_format = format;
|
||||
_host = host.TrimEnd('/');
|
||||
}
|
||||
|
||||
public object GetValue(object target)
|
||||
{
|
||||
return Regex.Replace(_format, @"(?<!{){(\w+)}", x =>
|
||||
{
|
||||
string value = x.Groups[1].Value;
|
||||
|
||||
if (value == "HOST")
|
||||
return _host;
|
||||
|
||||
PropertyInfo properties = target.GetType().GetProperties()
|
||||
.FirstOrDefault(y => y.Name == value);
|
||||
if (properties == null)
|
||||
return null;
|
||||
if (properties.GetValue(target) is string ret)
|
||||
return ret;
|
||||
throw new ArgumentException($"Invalid serializer replacement {value}");
|
||||
});
|
||||
}
|
||||
|
||||
public void SetValue(object target, object value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
@ -10,6 +10,7 @@ using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Controllers;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Kyoo.CommonApi
|
||||
{
|
||||
@ -24,9 +25,15 @@ namespace Kyoo.CommonApi
|
||||
where.Remove(key);
|
||||
}
|
||||
|
||||
string[] fields = context.HttpContext.Request.Query["fields"]
|
||||
List<string> fields = context.HttpContext.Request.Query["fields"]
|
||||
.SelectMany(x => x.Split(','))
|
||||
.ToArray();
|
||||
.ToList();
|
||||
if (fields.Contains("internal"))
|
||||
{
|
||||
fields.Remove("internal");
|
||||
context.HttpContext.Items["internal"] = true;
|
||||
// TODO disable SerializeAs attributes when this is true.
|
||||
}
|
||||
if (context.ActionDescriptor is ControllerActionDescriptor descriptor)
|
||||
{
|
||||
Type type = descriptor.MethodInfo.ReturnType;
|
||||
@ -50,7 +57,7 @@ namespace Kyoo.CommonApi
|
||||
});
|
||||
return null;
|
||||
})
|
||||
.ToArray();
|
||||
.ToList();
|
||||
if (context.Result != null)
|
||||
return;
|
||||
}
|
||||
@ -71,7 +78,7 @@ namespace Kyoo.CommonApi
|
||||
return;
|
||||
|
||||
await using ILibraryManager library = context.HttpContext.RequestServices.GetService<ILibraryManager>();
|
||||
string[] fields = (string[])context.HttpContext.Items["fields"];
|
||||
ICollection<string> fields = (ICollection<string>)context.HttpContext.Items["fields"];
|
||||
Type pageType = Utility.GetGenericDefinition(result.DeclaredType, typeof(Page<>));
|
||||
|
||||
|
||||
|
@ -44,7 +44,7 @@ namespace Kyoo.Controllers
|
||||
Library library,
|
||||
string what)
|
||||
{
|
||||
List<T> ret = new List<T>();
|
||||
List<T> ret = new();
|
||||
|
||||
IEnumerable<IMetadataProvider> providers = library?.Providers
|
||||
.Select(x => _providers.FirstOrDefault(y => y.Provider.Slug == x.Slug))
|
||||
@ -121,6 +121,7 @@ namespace Kyoo.Controllers
|
||||
$"the season {seasonNumber} of {show.Title}");
|
||||
season.Show = show;
|
||||
season.ShowID = show.ID;
|
||||
season.ShowSlug = show.Slug;
|
||||
season.SeasonNumber = season.SeasonNumber == -1 ? seasonNumber : season.SeasonNumber;
|
||||
season.Title ??= $"Season {season.SeasonNumber}";
|
||||
return season;
|
||||
@ -139,6 +140,7 @@ namespace Kyoo.Controllers
|
||||
"an episode");
|
||||
episode.Show = show;
|
||||
episode.ShowID = show.ID;
|
||||
episode.ShowSlug = show.Slug;
|
||||
episode.Path = episodePath;
|
||||
episode.SeasonNumber = episode.SeasonNumber != -1 ? episode.SeasonNumber : seasonNumber;
|
||||
episode.EpisodeNumber = episode.EpisodeNumber != -1 ? episode.EpisodeNumber : episodeNumber;
|
||||
|
@ -96,11 +96,11 @@ namespace Kyoo.Controllers
|
||||
if (episode?.Path == null)
|
||||
return default;
|
||||
|
||||
if (episode.Poster != null)
|
||||
if (episode.Thumb != null)
|
||||
{
|
||||
string localPath = Path.ChangeExtension(episode.Path, "jpg");
|
||||
if (alwaysDownload || !File.Exists(localPath))
|
||||
await DownloadImage(episode.Poster, localPath, $"The thumbnail of {episode.Show.Title}");
|
||||
await DownloadImage(episode.Thumb, localPath, $"The thumbnail of {episode.Show.Title}");
|
||||
}
|
||||
return episode;
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
namespace Kyoo.Models.DatabaseMigrations.Internal
|
||||
{
|
||||
[DbContext(typeof(DatabaseContext))]
|
||||
[Migration("20210306181259_Initial")]
|
||||
[Migration("20210312234147_Initial")]
|
||||
partial class Initial
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
@ -71,9 +71,6 @@ namespace Kyoo.Models.DatabaseMigrations.Internal
|
||||
b.Property<string>("Path")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Poster")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTime?>("ReleaseDate")
|
||||
.HasColumnType("timestamp without time zone");
|
||||
|
||||
@ -89,6 +86,9 @@ namespace Kyoo.Models.DatabaseMigrations.Internal
|
||||
b.Property<int>("ShowID")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("Thumb")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.HasColumnType("text");
|
||||
|
@ -318,11 +318,11 @@ namespace Kyoo.Models.DatabaseMigrations.Internal
|
||||
EpisodeNumber = table.Column<int>(type: "integer", nullable: false),
|
||||
AbsoluteNumber = table.Column<int>(type: "integer", nullable: false),
|
||||
Path = table.Column<string>(type: "text", nullable: true),
|
||||
Thumb = table.Column<string>(type: "text", nullable: true),
|
||||
Title = table.Column<string>(type: "text", nullable: true),
|
||||
Overview = table.Column<string>(type: "text", nullable: true),
|
||||
ReleaseDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: true),
|
||||
Runtime = table.Column<int>(type: "integer", nullable: false),
|
||||
Poster = table.Column<string>(type: "text", nullable: true)
|
||||
Runtime = table.Column<int>(type: "integer", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
@ -69,9 +69,6 @@ namespace Kyoo.Models.DatabaseMigrations.Internal
|
||||
b.Property<string>("Path")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Poster")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTime?>("ReleaseDate")
|
||||
.HasColumnType("timestamp without time zone");
|
||||
|
||||
@ -87,6 +84,9 @@ namespace Kyoo.Models.DatabaseMigrations.Internal
|
||||
b.Property<int>("ShowID")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("Thumb")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.HasColumnType("text");
|
||||
|
||||
|
@ -11,6 +11,7 @@ namespace Kyoo
|
||||
{
|
||||
public static async Task Main(string[] args)
|
||||
{
|
||||
|
||||
if (args.Length > 0)
|
||||
FileSystem.CurrentDirectory = args[0];
|
||||
if (!File.Exists("./appsettings.json"))
|
||||
|
@ -37,6 +37,8 @@ namespace Kyoo
|
||||
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
string publicUrl = _configuration.GetValue<string>("public_url");
|
||||
|
||||
services.AddSpaStaticFiles(configuration =>
|
||||
{
|
||||
configuration.RootPath = Path.Join(AppDomain.CurrentDomain.BaseDirectory, "wwwroot");
|
||||
@ -45,7 +47,7 @@ namespace Kyoo
|
||||
services.AddControllers()
|
||||
.AddNewtonsoftJson(x =>
|
||||
{
|
||||
x.SerializerSettings.ContractResolver = new JsonPropertyIgnorer();
|
||||
x.SerializerSettings.ContractResolver = new JsonPropertyIgnorer(publicUrl);
|
||||
x.SerializerSettings.Converters.Add(new PeopleRoleConverter());
|
||||
});
|
||||
services.AddHttpClient();
|
||||
@ -63,7 +65,6 @@ namespace Kyoo
|
||||
});
|
||||
|
||||
string assemblyName = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;
|
||||
string publicUrl = _configuration.GetValue<string>("public_url");
|
||||
|
||||
services.AddIdentityCore<User>(o =>
|
||||
{
|
||||
|
@ -351,7 +351,8 @@ namespace Kyoo.Controllers
|
||||
Title = show.Title,
|
||||
Path = episodePath,
|
||||
Show = show,
|
||||
ShowID = show.ID
|
||||
ShowID = show.ID,
|
||||
ShowSlug = show.Slug
|
||||
};
|
||||
episode.Tracks = await GetTracks(episode);
|
||||
return episode;
|
||||
|
@ -1,94 +0,0 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Kyoo.Controllers;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
|
||||
namespace Kyoo.Api
|
||||
{
|
||||
public class ThumbnailController : ControllerBase
|
||||
{
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
private readonly string _peoplePath;
|
||||
|
||||
|
||||
public ThumbnailController(ILibraryManager libraryManager, IConfiguration config)
|
||||
{
|
||||
_libraryManager = libraryManager;
|
||||
_peoplePath = config.GetValue<string>("peoplePath");
|
||||
}
|
||||
|
||||
|
||||
[HttpGet("poster/{showSlug}")]
|
||||
[Authorize(Policy="Read")]
|
||||
public async Task<IActionResult> GetShowThumb(string showSlug)
|
||||
{
|
||||
string path = (await _libraryManager.GetShow(showSlug))?.Path;
|
||||
if (path == null)
|
||||
return NotFound();
|
||||
|
||||
string thumb = Path.Combine(path, "poster.jpg");
|
||||
|
||||
if (System.IO.File.Exists(thumb))
|
||||
return new PhysicalFileResult(Path.GetFullPath(thumb), "image/jpg");
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
[HttpGet("logo/{showSlug}")]
|
||||
[Authorize(Policy="Read")]
|
||||
public async Task<IActionResult> GetShowLogo(string showSlug)
|
||||
{
|
||||
string path = (await _libraryManager.GetShow(showSlug))?.Path;
|
||||
if (path == null)
|
||||
return NotFound();
|
||||
|
||||
string thumb = Path.Combine(path, "logo.png");
|
||||
|
||||
if (System.IO.File.Exists(thumb))
|
||||
return new PhysicalFileResult(Path.GetFullPath(thumb), "image/jpg");
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
[HttpGet("backdrop/{showSlug}")]
|
||||
[Authorize(Policy="Read")]
|
||||
public async Task<IActionResult> GetShowBackdrop(string showSlug)
|
||||
{
|
||||
string path = (await _libraryManager.GetShow(showSlug))?.Path;
|
||||
if (path == null)
|
||||
return NotFound();
|
||||
|
||||
string thumb = Path.Combine(path, "backdrop.jpg");
|
||||
|
||||
if (System.IO.File.Exists(thumb))
|
||||
return new PhysicalFileResult(Path.GetFullPath(thumb), "image/jpg");
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
[HttpGet("peopleimg/{peopleSlug}")]
|
||||
[Authorize(Policy="Read")]
|
||||
public IActionResult GetPeopleIcon(string peopleSlug)
|
||||
{
|
||||
string thumbPath = Path.Combine(_peoplePath, peopleSlug + ".jpg");
|
||||
if (!System.IO.File.Exists(thumbPath))
|
||||
return NotFound();
|
||||
|
||||
return new PhysicalFileResult(Path.GetFullPath(thumbPath), "image/jpg");
|
||||
}
|
||||
|
||||
[HttpGet("thumb/{showSlug}-s{seasonNumber}e{episodeNumber}")]
|
||||
[Authorize(Policy="Read")]
|
||||
public async Task<IActionResult> GetEpisodeThumb(string showSlug, int seasonNumber, int episodeNumber)
|
||||
{
|
||||
string path = (await _libraryManager.GetEpisode(showSlug, seasonNumber, episodeNumber))?.Path;
|
||||
if (path == null)
|
||||
return NotFound();
|
||||
|
||||
string thumb = Path.ChangeExtension(path, "jpg");
|
||||
|
||||
if (System.IO.File.Exists(thumb))
|
||||
return new PhysicalFileResult(Path.GetFullPath(thumb), "image/jpg");
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user