Automatically download/extract info on API creation (dirtyfix) (#161

* Download thumbnails automatically

* Automatically extract tracks
This commit is contained in:
Zoe Roux 2023-04-03 20:02:12 +09:00
parent d0db4815f1
commit 592c92785f
15 changed files with 73 additions and 24 deletions

View File

@ -20,7 +20,7 @@ COPY src/Kyoo.Swagger/Kyoo.Swagger.csproj src/Kyoo.Swagger/Kyoo.Swagger.csproj
COPY tests/Kyoo.Tests/Kyoo.Tests.csproj tests/Kyoo.Tests/Kyoo.Tests.csproj
RUN dotnet restore
COPY --from=transcoder /transcoder/libtranscoder.so /app
COPY --from=transcoder /transcoder/libtranscoder.so /app/out/bin/Kyoo.Host/Debug/net6.0/libtranscoder.so
WORKDIR /kyoo
EXPOSE 5000

View File

@ -69,6 +69,7 @@ namespace Kyoo.Core.Controllers
try
{
_logger.LogInformation("Downloading image {What}", what);
AsyncRef<string> mime = new();
await using Stream reader = await _files.GetReader(url, mime);
string extension = new FileExtensionContentTypeProvider()

View File

@ -138,7 +138,7 @@ namespace Kyoo.Core.Api
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(RequestError))]
[ProducesResponseType(StatusCodes.Status409Conflict, Type = typeof(ActionResult<>))]
public async Task<ActionResult<T>> Create([FromBody] T resource)
public virtual async Task<ActionResult<T>> Create([FromBody] T resource)
{
return await Repository.Create(resource);
}

View File

@ -153,5 +153,14 @@ namespace Kyoo.Core.Api
{
return GetImage(identifier, Images.Thumbnail);
}
/// <inheritdoc/>
public override async Task<ActionResult<T>> Create([FromBody] T resource)
{
// TODO: Remove this method and use a websocket API to do that.
ActionResult<T> ret = await base.Create(resource);
await _thumbs.DownloadImages(ret.Value);
return ret;
}
}
}

View File

@ -24,6 +24,7 @@ using Kyoo.Abstractions.Models;
using Kyoo.Abstractions.Models.Attributes;
using Kyoo.Abstractions.Models.Permissions;
using Kyoo.Abstractions.Models.Utils;
using Kyoo.Utils;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using static Kyoo.Abstractions.Models.Utils.Constants;
@ -76,6 +77,15 @@ namespace Kyoo.Core.Api
_files = files;
}
/// <inheritdoc/>
public override async Task<ActionResult<Episode>> Create([FromBody] Episode resource)
{
// TODO: Remove this method and use a websocket API to do that.
resource.Tracks = await _transcoder.ExtractInfos(resource, false);
ActionResult<Episode> ret = await base.Create(resource);
return ret;
}
/// <summary>
/// Get episode's show
/// </summary>

View File

@ -48,6 +48,7 @@ namespace Kyoo.Core.Api
/// The library manager used to modify or retrieve information in the data store.
/// </summary>
private readonly ILibraryManager _libraryManager;
private readonly ITranscoder _transcoder;
/// <summary>
/// Create a new <see cref="ShowApi"/>.
@ -57,12 +58,34 @@ namespace Kyoo.Core.Api
/// </param>
/// <param name="files">The file manager used to send images and fonts.</param>
/// <param name="thumbs">The thumbnail manager used to retrieve images paths.</param>
/// <param name="transcoder">TODO: Remove this.</param>
public ShowApi(ILibraryManager libraryManager,
IFileSystem files,
IThumbnailsManager thumbs)
IThumbnailsManager thumbs,
ITranscoder transcoder)
: base(libraryManager.ShowRepository, files, thumbs)
{
_libraryManager = libraryManager;
_transcoder = transcoder;
}
/// <inheritdoc/>
public override async Task<ActionResult<Show>> Create([FromBody] Show resource)
{
ActionResult<Show> ret = await base.Create(resource);
if (ret.Value.IsMovie)
{
Episode episode = new()
{
Show = ret.Value,
Title = ret.Value.Title,
Path = ret.Value.Path
};
episode.Tracks = await _transcoder.ExtractInfos(episode, false);
await _libraryManager.Create(episode);
}
return ret;
}
/// <summary>

View File

@ -24,7 +24,6 @@ using System.Threading.Tasks;
using Autofac;
using Autofac.Extensions.DependencyInjection;
using Kyoo.Postgresql;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
@ -176,6 +175,7 @@ namespace Kyoo.Host
.MinimumLevel.Warning()
.MinimumLevel.Override("Kyoo", LogEventLevel.Verbose)
.MinimumLevel.Override("Microsoft.Hosting.Lifetime", LogEventLevel.Verbose)
.MinimumLevel.Override("Microsoft.EntityFrameworkCore", LogEventLevel.Fatal)
.WriteTo.Console(new ExpressionTemplate(template, theme: TemplateTheme.Code))
.Enrich.WithThreadId()
.Enrich.FromLogContext();

View File

@ -342,8 +342,8 @@ class TheMovieDatabase(Provider):
release_date=datetime.strptime(episode["air_date"], "%Y-%m-%d").date()
if episode["air_date"]
else None,
thumbnail=f"https://image.tmdb.org/t/p/original{episode['poster_path']}"
if "poster_path" in episode
thumbnail=f"https://image.tmdb.org/t/p/original{episode['still_path']}"
if "still_path" in episode and episode["still_path"] is not None
else None,
external_ids={
self.name: MetadataID(

View File

@ -41,6 +41,9 @@ class Episode:
**asdict(self),
**asdict(self.translations[default_language]),
"title": self.translations[default_language].name,
"images": {
"1": self.thumbnail,
},
# TODO: The back has bad external id support, we disable it for now
"external_ids": None,
"show": None,

View File

@ -22,4 +22,4 @@ class Genre(str, Enum):
WESTERN = "Western"
def to_kyoo(self):
return {"name": f"{self}"}
return {"name": self.value}

View File

@ -50,12 +50,12 @@ class Movie:
return {
**asdict(self),
**asdict(self.translations[default_language]),
"poster": next(iter(self.translations[default_language].posters), None),
"thumbnail": next(
iter(self.translations[default_language].thumbnails), None
),
"logo": next(iter(self.translations[default_language].logos), None),
"trailer": next(iter(self.translations[default_language].trailers), None),
"images": {
"0": next(iter(self.translations[default_language].posters), None),
"1": next(iter(self.translations[default_language].thumbnails), None),
"2": next(iter(self.translations[default_language].logos), None),
"3": next(iter(self.translations[default_language].trailers), None),
},
"studio": next((x.to_kyoo() for x in self.studios), None),
"release_date": None,
"startAir": format_date(self.release_date),

View File

@ -30,10 +30,10 @@ class Season:
return {
**asdict(self),
**asdict(self.translations[default_language]),
"poster": next(iter(self.translations[default_language].posters), None),
"thumbnail": next(
iter(self.translations[default_language].thumbnails), None
),
"images": {
"0": next(iter(self.translations[default_language].posters), None),
"1": next(iter(self.translations[default_language].thumbnails), None),
},
"title": self.translations[default_language].name,
# TODO: The back has bad external id support, we disable it for now
"external_ids": None,

View File

@ -52,12 +52,12 @@ class Show:
return {
**asdict(self),
**asdict(self.translations[default_language]),
"poster": next(iter(self.translations[default_language].posters), None),
"thumbnail": next(
iter(self.translations[default_language].thumbnails), None
),
"logo": next(iter(self.translations[default_language].logos), None),
"trailer": next(iter(self.translations[default_language].trailers), None),
"images": {
"0": next(iter(self.translations[default_language].posters), None),
"1": next(iter(self.translations[default_language].thumbnails), None),
"2": next(iter(self.translations[default_language].logos), None),
"3": next(iter(self.translations[default_language].trailers), None),
},
"studio": next((x.to_kyoo() for x in self.studios), None),
"title": self.translations[default_language].name,
"genres": [x.to_kyoo() for x in self.genres],

View File

@ -12,6 +12,9 @@ class Studio:
def to_kyoo(self):
return {
**asdict(self),
"images": {
"2": next(iter(self.logos), None),
},
# TODO: The back has bad external id support, we disable it for now
"external_ids": None,
}

View File

@ -38,7 +38,7 @@ def provider_cache(*args):
if "event" in ic:
await ic["event"].wait()
if not ic["ret"]:
if "ret" not in ic:
raise ProviderError("Cache miss. Another error should exist")
return ic["ret"]
ic["event"] = asyncio.Event()