diff --git a/back/Dockerfile.dev b/back/Dockerfile.dev index 4b37417b..71a2f5bd 100644 --- a/back/Dockerfile.dev +++ b/back/Dockerfile.dev @@ -17,6 +17,7 @@ RUN dotnet restore WORKDIR /kyoo EXPOSE 5000 ENV DOTNET_USE_POLLING_FILE_WATCHER 1 -HEALTHCHECK --interval=5s CMD curl --fail http://localhost:5000/health || exit +# HEALTHCHECK --interval=5s CMD curl --fail http://localhost:5000/health || exit +HEALTHCHECK CMD true CMD dotnet watch run --no-restore --project /app/src/Kyoo.Host diff --git a/back/src/Kyoo.Abstractions/Models/News.cs b/back/src/Kyoo.Abstractions/Models/News.cs new file mode 100644 index 00000000..feb763f4 --- /dev/null +++ b/back/src/Kyoo.Abstractions/Models/News.cs @@ -0,0 +1,147 @@ +// 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 . + +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; + +namespace Kyoo.Abstractions.Models +{ + /// + /// The type of item, ether a show, a movie or a collection. + /// + public enum NewsKind + { + /// + /// The is an . + /// + Episode, + + /// + /// The is a Movie. + /// + Movie, + } + + /// + /// A new item + /// + public class News : IResource, IMetadata, IThumbnails, IAddedDate + { + /// + public int Id { get; set; } + + /// + [MaxLength(256)] + public string Slug { get; set; } + + /// + /// The title of this show. + /// + public string? Name { get; set; } + + /// + /// A catchphrase for this movie. + /// + public string? Tagline { get; set; } + + /// + /// The list of alternative titles of this show. + /// + public string[] Aliases { get; set; } = Array.Empty(); + + /// + /// The path of the movie video file. + /// + public string Path { get; set; } + + /// + /// The summary of this show. + /// + public string? Overview { get; set; } + + /// + /// A list of tags that match this movie. + /// + public string[] Tags { get; set; } = Array.Empty(); + + /// + /// The list of genres (themes) this show has. + /// + public Genre[] Genres { get; set; } = Array.Empty(); + + /// + /// Is this show airing, not aired yet or finished? + /// + public Status? Status { get; set; } + + /// + /// The date this movie aired. + /// + public DateTime? AirDate { get; set; } + + /// + public DateTime AddedDate { get; set; } + + /// + public Image? Poster { get; set; } + + /// + public Image? Thumbnail { get; set; } + + /// + public Image? Logo { get; set; } + + /// + /// A video of a few minutes that tease the content. + /// + public string? Trailer { get; set; } + + /// + public Dictionary ExternalId { get; set; } = new(); + + /// + /// The season in witch this episode is in. + /// + public int? SeasonNumber { get; set; } + + /// + /// The number of this episode in it's season. + /// + public int? EpisodeNumber { get; set; } + + /// + /// The absolute number of this episode. It's an episode number that is not reset to 1 after a new season. + /// + public int? AbsoluteNumber { get; set; } + + /// + /// Is the item a a movie or an episode? + /// + public NewsKind Kind { get; set; } + + /// + /// Links to watch this movie. + /// + public VideoLinks Links => new() + { + Direct = $"/video/{Kind.ToString().ToLower()}/{Slug}/direct", + Hls = $"/video/{Kind.ToString().ToLower()}/{Slug}/master.m3u8", + }; + } +} diff --git a/back/src/Kyoo.Abstractions/Models/Resources/Episode.cs b/back/src/Kyoo.Abstractions/Models/Resources/Episode.cs index 24638cc9..6bb64121 100644 --- a/back/src/Kyoo.Abstractions/Models/Resources/Episode.cs +++ b/back/src/Kyoo.Abstractions/Models/Resources/Episode.cs @@ -23,7 +23,6 @@ using System.Linq; using System.Text.RegularExpressions; using EntityFrameworkCore.Projectables; using JetBrains.Annotations; -using Kyoo.Abstractions.Controllers; using Kyoo.Abstractions.Models.Attributes; namespace Kyoo.Abstractions.Models diff --git a/back/src/Kyoo.Abstractions/Models/Resources/Interfaces/IThumbnails.cs b/back/src/Kyoo.Abstractions/Models/Resources/Interfaces/IThumbnails.cs index 277bde24..a692e52b 100644 --- a/back/src/Kyoo.Abstractions/Models/Resources/Interfaces/IThumbnails.cs +++ b/back/src/Kyoo.Abstractions/Models/Resources/Interfaces/IThumbnails.cs @@ -20,7 +20,6 @@ using System; using System.ComponentModel; using System.ComponentModel.DataAnnotations; using System.Globalization; -using Kyoo.Abstractions.Models.Attributes; namespace Kyoo.Abstractions.Models { @@ -60,24 +59,6 @@ namespace Kyoo.Abstractions.Models [MaxLength(32)] public string Blurhash { get; set; } - [SerializeIgnore] - public string Path { private get; set; } - - /// - /// The url to retrieve the low quality image. - /// - public string Low => $"{Path}?quality=low"; - - /// - /// The url to retrieve the medium quality image. - /// - public string Medium => $"{Path}?quality=medium"; - - /// - /// The url to retrieve the high quality image. - /// - public string High => $"{Path}?quality=high"; - public Image(string source, string? blurhash = null) { Source = source; diff --git a/back/src/Kyoo.Core/Controllers/Repositories/NewsRepository.cs b/back/src/Kyoo.Core/Controllers/Repositories/NewsRepository.cs new file mode 100644 index 00000000..708ead3b --- /dev/null +++ b/back/src/Kyoo.Core/Controllers/Repositories/NewsRepository.cs @@ -0,0 +1,72 @@ +// 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 . + +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Kyoo.Abstractions.Controllers; +using Kyoo.Abstractions.Models; +using Kyoo.Postgresql; + +namespace Kyoo.Core.Controllers +{ + /// + /// A local repository to handle shows + /// + public class NewsRepository : LocalRepository + { + /// + protected override Sort DefaultSort => new Sort.By(x => x.AddedDate); + + public NewsRepository(DatabaseContext database, IThumbnailsManager thumbs) + : base(database, thumbs) + { } + + /// + public override Task> Search(string query) + => throw new InvalidOperationException(); + + /// + public override Task Create(News obj) + => throw new InvalidOperationException(); + + /// + public override Task CreateIfNotExists(News obj) + => throw new InvalidOperationException(); + + /// + public override Task Edit(News edited) + => throw new InvalidOperationException(); + + /// + public override Task Patch(int id, Func> patch) + => throw new InvalidOperationException(); + + /// + public override Task Delete(int id) + => throw new InvalidOperationException(); + + /// + public override Task Delete(string slug) + => throw new InvalidOperationException(); + + /// + public override Task Delete(News obj) + => throw new InvalidOperationException(); + } +} diff --git a/back/src/Kyoo.Core/CoreModule.cs b/back/src/Kyoo.Core/CoreModule.cs index fcf16594..72c05456 100644 --- a/back/src/Kyoo.Core/CoreModule.cs +++ b/back/src/Kyoo.Core/CoreModule.cs @@ -59,6 +59,7 @@ namespace Kyoo.Core builder.RegisterRepository(); builder.RegisterRepository(); builder.RegisterRepository(); + builder.RegisterType().OwnedByLifetimeScope(); } /// diff --git a/back/src/Kyoo.Core/Views/Helper/Serializers/JsonSerializerContract.cs b/back/src/Kyoo.Core/Views/Helper/Serializers/JsonSerializerContract.cs index 76aacdea..d9ca24dc 100644 --- a/back/src/Kyoo.Core/Views/Helper/Serializers/JsonSerializerContract.cs +++ b/back/src/Kyoo.Core/Views/Helper/Serializers/JsonSerializerContract.cs @@ -58,7 +58,7 @@ namespace Kyoo.Core.Api { property.ShouldSerialize = _ => { - ICollection fields = (ICollection)_httpContextAccessor.HttpContext!.Items["fields"]!; + ICollection? fields = (ICollection)_httpContextAccessor.HttpContext!.Items["fields"]!; if (fields == null) return false; return fields.Contains(member.Name); diff --git a/back/src/Kyoo.Core/Views/Resources/NewsApi.cs b/back/src/Kyoo.Core/Views/Resources/NewsApi.cs new file mode 100644 index 00000000..e82e832b --- /dev/null +++ b/back/src/Kyoo.Core/Views/Resources/NewsApi.cs @@ -0,0 +1,61 @@ +// 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 . + +using System.Collections.Generic; +using System.Threading.Tasks; +using Kyoo.Abstractions.Controllers; +using Kyoo.Abstractions.Models; +using Kyoo.Abstractions.Models.Attributes; +using Kyoo.Abstractions.Models.Permissions; +using Kyoo.Core.Controllers; +using Microsoft.AspNetCore.Mvc; +using static Kyoo.Abstractions.Models.Utils.Constants; + +namespace Kyoo.Core.Api +{ + /// + /// List new items added to kyoo. + /// + [Route("news")] + [Route("new", Order = AlternativeRoute)] + [ApiController] + [ResourceView] + [PartialPermission("LibraryItem")] + [ApiDefinition("News", Group = ResourcesGroup)] + public class NewsApi : BaseApi + { + private readonly NewsRepository _news; + + public NewsApi(NewsRepository news) + { + _news = news; + } + + public async Task>> GetAll( + [FromQuery] Dictionary where, + [FromQuery] Pagination pagination) + { + ICollection resources = await _news.GetNews( + ApiHelper.ParseWhere(where), + pagination + ); + + return Page(resources, pagination.Limit); + } + } +} diff --git a/back/src/Kyoo.Postgresql/DatabaseContext.cs b/back/src/Kyoo.Postgresql/DatabaseContext.cs index 3e7232be..557ca197 100644 --- a/back/src/Kyoo.Postgresql/DatabaseContext.cs +++ b/back/src/Kyoo.Postgresql/DatabaseContext.cs @@ -100,6 +100,14 @@ namespace Kyoo.Postgresql /// public DbSet LibraryItems { get; set; } + /// + /// The list of new items (episodes and movies). + /// + /// + /// This set is ready only, on most database this will be a view. + /// + public DbSet News { get; set; } + /// /// Add a many to many link between two resources. /// @@ -283,6 +291,7 @@ namespace Kyoo.Postgresql .UsingEntity(x => x.ToTable(LinkName())); _HasMetadata(modelBuilder); + _HasMetadata(modelBuilder); _HasMetadata(modelBuilder); _HasMetadata(modelBuilder); _HasMetadata(modelBuilder); @@ -292,6 +301,7 @@ namespace Kyoo.Postgresql _HasMetadata(modelBuilder); _HasImages(modelBuilder); + _HasImages(modelBuilder); _HasImages(modelBuilder); _HasImages(modelBuilder); _HasImages(modelBuilder); @@ -300,6 +310,7 @@ namespace Kyoo.Postgresql _HasImages(modelBuilder); _HasAddedDate(modelBuilder); + _HasAddedDate(modelBuilder); _HasAddedDate(modelBuilder); _HasAddedDate(modelBuilder); _HasAddedDate(modelBuilder); @@ -347,6 +358,8 @@ namespace Kyoo.Postgresql .Ignore(x => x.Links); modelBuilder.Entity() .Ignore(x => x.Links); + modelBuilder.Entity() + .Ignore(x => x.Links); } /// diff --git a/back/src/Kyoo.Postgresql/PostgresContext.cs b/back/src/Kyoo.Postgresql/PostgresContext.cs index a55e8773..520758e7 100644 --- a/back/src/Kyoo.Postgresql/PostgresContext.cs +++ b/back/src/Kyoo.Postgresql/PostgresContext.cs @@ -51,6 +51,7 @@ namespace Kyoo.Postgresql NpgsqlConnection.GlobalTypeMapper.MapEnum(); NpgsqlConnection.GlobalTypeMapper.MapEnum(); NpgsqlConnection.GlobalTypeMapper.MapEnum(); + NpgsqlConnection.GlobalTypeMapper.MapEnum(); } /// @@ -104,6 +105,7 @@ namespace Kyoo.Postgresql modelBuilder.HasPostgresEnum(); modelBuilder.HasPostgresEnum(); modelBuilder.HasPostgresEnum(); + modelBuilder.HasPostgresEnum(); modelBuilder.HasDbFunction(typeof(DatabaseContext).GetMethod(nameof(MD5))!) .HasTranslation(args =>