mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-05-24 02:02:36 -04:00
Fix tracks slugs
This commit is contained in:
parent
0f96f02df5
commit
066229eb0e
2
.github/workflows/tests.yml
vendored
2
.github/workflows/tests.yml
vendored
@ -38,7 +38,7 @@ jobs:
|
||||
dotnet test --no-build '-p:CollectCoverage=true;CoverletOutputFormat=opencover' --logger "trx;LogFileName=TestOutputResults.xml"
|
||||
env:
|
||||
POSTGRES_HOST: postgres
|
||||
POSTGRES_USERNAME: postgres
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: postgres
|
||||
|
||||
- name: Sanitize coverage output
|
||||
|
1
back/.gitignore
vendored
1
back/.gitignore
vendored
@ -80,7 +80,6 @@ StyleCopReport.xml
|
||||
*.ipdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
|
4
back/ef.rsp
Normal file
4
back/ef.rsp
Normal file
@ -0,0 +1,4 @@
|
||||
--project
|
||||
src/Kyoo.Postgresql/Kyoo.Postgresql.csproj
|
||||
--msbuildprojectextensionspath
|
||||
out/obj/Kyoo.Postgresql
|
@ -80,7 +80,7 @@ namespace Kyoo.Abstractions.Models
|
||||
/// <summary>
|
||||
/// The slug of the Show that contain this episode. If this is not set, this episode is ill-formed.
|
||||
/// </summary>
|
||||
[SerializeIgnore] public string ShowSlug { get; set; }
|
||||
[SerializeIgnore] public string ShowSlug { private get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The ID of the Show containing this episode.
|
||||
|
@ -68,7 +68,7 @@ namespace Kyoo.Abstractions.Models
|
||||
{
|
||||
string type = Type.ToString().ToLowerInvariant();
|
||||
string index = TrackIndex != 0 ? $"-{TrackIndex}" : string.Empty;
|
||||
string episode = _episodeSlug ?? Episode?.Slug ?? EpisodeID.ToString(CultureInfo.InvariantCulture);
|
||||
string episode = EpisodeSlug ?? Episode?.Slug ?? EpisodeID.ToString(CultureInfo.InvariantCulture);
|
||||
return $"{episode}.{Language ?? "und"}{index}{(IsForced ? ".forced" : string.Empty)}.{type}";
|
||||
}
|
||||
|
||||
@ -88,7 +88,7 @@ namespace Kyoo.Abstractions.Models
|
||||
);
|
||||
}
|
||||
|
||||
_episodeSlug = match.Groups["ep"].Value;
|
||||
EpisodeSlug = match.Groups["ep"].Value;
|
||||
Language = match.Groups["lang"].Value;
|
||||
if (Language == "und")
|
||||
Language = null;
|
||||
@ -154,7 +154,7 @@ namespace Kyoo.Abstractions.Models
|
||||
{
|
||||
_episode = value;
|
||||
if (_episode != null)
|
||||
_episodeSlug = _episode.Slug;
|
||||
EpisodeSlug = _episode.Slug;
|
||||
}
|
||||
}
|
||||
|
||||
@ -190,7 +190,7 @@ namespace Kyoo.Abstractions.Models
|
||||
/// <summary>
|
||||
/// The slug of the episode that contain this track. If this is not set, this track is ill-formed.
|
||||
/// </summary>
|
||||
[SerializeIgnore] private string _episodeSlug;
|
||||
[SerializeIgnore] public string EpisodeSlug { private get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The episode that uses this track.
|
||||
|
@ -47,7 +47,7 @@ namespace Kyoo.Core.Controllers
|
||||
/// <summary>
|
||||
/// A track repository to handle creation and deletion of tracks related to the current episode.
|
||||
/// </summary>
|
||||
private readonly ITrackRepository _tracks;
|
||||
private readonly Lazy<ITrackRepository> _tracks;
|
||||
|
||||
/// <inheritdoc />
|
||||
// Use absolute numbers by default and fallback to season/episodes if it does not exists.
|
||||
@ -67,7 +67,7 @@ namespace Kyoo.Core.Controllers
|
||||
public EpisodeRepository(DatabaseContext database,
|
||||
IShowRepository shows,
|
||||
IProviderRepository providers,
|
||||
ITrackRepository tracks)
|
||||
Lazy<ITrackRepository> tracks)
|
||||
: base(database)
|
||||
{
|
||||
_database = database;
|
||||
@ -75,15 +75,15 @@ namespace Kyoo.Core.Controllers
|
||||
_tracks = tracks;
|
||||
|
||||
// Edit episode slugs when the show's slug changes.
|
||||
shows.OnEdited += async (show) =>
|
||||
shows.OnEdited += (show) =>
|
||||
{
|
||||
foreach (Episode ep in _database.Episodes.Where(x => x.ShowID == show.ID))
|
||||
List<Episode> episodes = _database.Episodes.AsTracking().Where(x => x.ShowID == show.ID).ToList();
|
||||
foreach (Episode ep in episodes)
|
||||
{
|
||||
Console.WriteLine("BFR ID: {0}; Slug: {1}; ShowSlug: {2}", ep.ID, ep.Slug, ep.ShowSlug);
|
||||
ep.ShowSlug = show.Slug;
|
||||
Console.WriteLine("AFT ID: {0}; Slug: {1}; ShowSlug: {2}", ep.ID, ep.Slug, ep.ShowSlug);
|
||||
_database.SaveChanges();
|
||||
OnResourceEdited(ep);
|
||||
}
|
||||
await _database.SaveChangesAsync();
|
||||
};
|
||||
}
|
||||
|
||||
@ -171,7 +171,7 @@ namespace Kyoo.Core.Controllers
|
||||
|
||||
if (changed.Tracks != null || resetOld)
|
||||
{
|
||||
await _tracks.DeleteAll(x => x.EpisodeID == resource.ID);
|
||||
await _tracks.Value.DeleteAll(x => x.EpisodeID == resource.ID);
|
||||
resource.Tracks = changed.Tracks;
|
||||
await _ValidateTracks(resource);
|
||||
}
|
||||
@ -196,7 +196,7 @@ namespace Kyoo.Core.Controllers
|
||||
resource.Tracks = await resource.Tracks.SelectAsync(x =>
|
||||
{
|
||||
x.Episode = resource;
|
||||
return _tracks.Create(x);
|
||||
return _tracks.Value.Create(x);
|
||||
}).ToListAsync();
|
||||
_database.Tracks.AttachRange(resource.Tracks);
|
||||
return resource;
|
||||
@ -235,7 +235,7 @@ namespace Kyoo.Core.Controllers
|
||||
throw new ArgumentNullException(nameof(obj));
|
||||
|
||||
_database.Entry(obj).State = EntityState.Deleted;
|
||||
await obj.Tracks.ForEachAsync(x => _tracks.Delete(x));
|
||||
await obj.Tracks.ForEachAsync(x => _tracks.Value.Delete(x));
|
||||
obj.ExternalIDs.ForEach(x => _database.Entry(x).State = EntityState.Deleted);
|
||||
await _database.SaveChangesAsync();
|
||||
await base.Delete(obj);
|
||||
|
@ -353,6 +353,15 @@ namespace Kyoo.Core.Controllers
|
||||
OnCreated?.Invoke(obj);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Callback that should be called after a resource has been edited.
|
||||
/// </summary>
|
||||
/// <param name="obj">The resource newly edited.</param>
|
||||
protected void OnResourceEdited(T obj)
|
||||
{
|
||||
OnEdited?.Invoke(obj);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public virtual async Task<T> CreateIfNotExists(T obj)
|
||||
{
|
||||
|
@ -61,11 +61,15 @@ namespace Kyoo.Core.Controllers
|
||||
_providers = providers;
|
||||
|
||||
// Edit seasons slugs when the show's slug changes.
|
||||
shows.OnEdited += async (show) =>
|
||||
shows.OnEdited += (show) =>
|
||||
{
|
||||
foreach (Season season in _database.Seasons.Where(x => x.ShowID == show.ID))
|
||||
List<Season> seasons = _database.Seasons.AsTracking().Where(x => x.ShowID == show.ID).ToList();
|
||||
foreach (Season season in seasons)
|
||||
{
|
||||
season.ShowSlug = show.Slug;
|
||||
await _database.SaveChangesAsync();
|
||||
_database.SaveChanges();
|
||||
OnResourceEdited(season);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Kyoo.Abstractions.Controllers;
|
||||
using Kyoo.Abstractions.Models;
|
||||
@ -43,10 +44,23 @@ namespace Kyoo.Core.Controllers
|
||||
/// Create a new <see cref="TrackRepository"/>.
|
||||
/// </summary>
|
||||
/// <param name="database">The database handle</param>
|
||||
public TrackRepository(DatabaseContext database)
|
||||
/// <param name="episodes">The episode repository</param>
|
||||
public TrackRepository(DatabaseContext database, IEpisodeRepository episodes)
|
||||
: base(database)
|
||||
{
|
||||
_database = database;
|
||||
|
||||
// Edit tracks slugs when the episodes's slug changes.
|
||||
episodes.OnEdited += (ep) =>
|
||||
{
|
||||
List<Track> tracks = _database.Tracks.AsTracking().Where(x => x.EpisodeID == ep.ID).ToList();
|
||||
foreach (Track track in tracks)
|
||||
{
|
||||
track.EpisodeSlug = ep.Slug;
|
||||
_database.SaveChanges();
|
||||
OnResourceEdited(track);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
@ -305,6 +305,9 @@ namespace Kyoo.Postgresql
|
||||
modelBuilder.Entity<People>().Property(x => x.Slug).IsRequired();
|
||||
modelBuilder.Entity<Provider>().Property(x => x.Slug).IsRequired();
|
||||
modelBuilder.Entity<Show>().Property(x => x.Slug).IsRequired();
|
||||
modelBuilder.Entity<Season>().Property(x => x.Slug).IsRequired();
|
||||
modelBuilder.Entity<Episode>().Property(x => x.Slug).IsRequired();
|
||||
modelBuilder.Entity<Track>().Property(x => x.Slug).IsRequired();
|
||||
modelBuilder.Entity<Studio>().Property(x => x.Slug).IsRequired();
|
||||
modelBuilder.Entity<User>().Property(x => x.Slug).IsRequired();
|
||||
|
||||
@ -350,16 +353,6 @@ namespace Kyoo.Postgresql
|
||||
modelBuilder.Entity<User>()
|
||||
.HasIndex(x => x.Slug)
|
||||
.IsUnique();
|
||||
|
||||
modelBuilder.Entity<Season>()
|
||||
.Property(x => x.Slug)
|
||||
.ValueGeneratedOnAddOrUpdate();
|
||||
modelBuilder.Entity<Episode>()
|
||||
.Property(x => x.Slug)
|
||||
.ValueGeneratedOnAddOrUpdate();
|
||||
modelBuilder.Entity<Track>()
|
||||
.Property(x => x.Slug)
|
||||
.ValueGeneratedOnAddOrUpdate();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -1,4 +1,4 @@
|
||||
// <auto-generated />
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Kyoo.Abstractions.Models;
|
||||
@ -12,11 +12,10 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
namespace Kyoo.Postgresql.Migrations
|
||||
{
|
||||
[DbContext(typeof(PostgresContext))]
|
||||
[Migration("20230621074246_RemoveTrigers")]
|
||||
partial class RemoveTrigers
|
||||
[Migration("20230724144449_RemoveTriggers")]
|
||||
partial class RemoveTriggers
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
@ -107,7 +106,7 @@ namespace Kyoo.Postgresql.Migrations
|
||||
.HasColumnName("show_id");
|
||||
|
||||
b.Property<string>("Slug")
|
||||
.ValueGeneratedOnAddOrUpdate()
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("slug");
|
||||
|
||||
@ -362,7 +361,7 @@ namespace Kyoo.Postgresql.Migrations
|
||||
.HasColumnName("show_id");
|
||||
|
||||
b.Property<string>("Slug")
|
||||
.ValueGeneratedOnAddOrUpdate()
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("slug");
|
||||
|
||||
@ -518,7 +517,7 @@ namespace Kyoo.Postgresql.Migrations
|
||||
.HasColumnName("path");
|
||||
|
||||
b.Property<string>("Slug")
|
||||
.ValueGeneratedOnAddOrUpdate()
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("slug");
|
||||
|
@ -23,11 +23,41 @@ namespace Kyoo.Postgresql.Migrations
|
||||
/// <summary>
|
||||
/// Remove triggers
|
||||
/// </summary>
|
||||
public partial class RemoveTrigers : Migration
|
||||
public partial class RemoveTriggers : Migration
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "slug",
|
||||
table: "tracks",
|
||||
type: "text",
|
||||
nullable: false,
|
||||
defaultValue: string.Empty,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "text",
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "slug",
|
||||
table: "seasons",
|
||||
type: "text",
|
||||
nullable: false,
|
||||
defaultValue: string.Empty,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "text",
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "slug",
|
||||
table: "episodes",
|
||||
type: "text",
|
||||
nullable: false,
|
||||
defaultValue: string.Empty,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "text",
|
||||
oldNullable: true);
|
||||
|
||||
// language=PostgreSQL
|
||||
migrationBuilder.Sql("DROP TRIGGER show_slug_trigger ON shows;");
|
||||
// language=PostgreSQL
|
||||
@ -53,6 +83,29 @@ namespace Kyoo.Postgresql.Migrations
|
||||
/// <inheritdoc/>
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "slug",
|
||||
table: "tracks",
|
||||
type: "text",
|
||||
nullable: true,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "text");
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "slug",
|
||||
table: "seasons",
|
||||
type: "text",
|
||||
nullable: true,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "text");
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "slug",
|
||||
table: "episodes",
|
||||
type: "text",
|
||||
nullable: true,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "text");
|
||||
}
|
||||
}
|
||||
}
|
@ -104,7 +104,7 @@ namespace Kyoo.Postgresql.Migrations
|
||||
.HasColumnName("show_id");
|
||||
|
||||
b.Property<string>("Slug")
|
||||
.ValueGeneratedOnAddOrUpdate()
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("slug");
|
||||
|
||||
@ -359,7 +359,7 @@ namespace Kyoo.Postgresql.Migrations
|
||||
.HasColumnName("show_id");
|
||||
|
||||
b.Property<string>("Slug")
|
||||
.ValueGeneratedOnAddOrUpdate()
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("slug");
|
||||
|
||||
@ -515,7 +515,7 @@ namespace Kyoo.Postgresql.Migrations
|
||||
.HasColumnName("path");
|
||||
|
||||
b.Property<string>("Slug")
|
||||
.ValueGeneratedOnAddOrUpdate()
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("slug");
|
||||
|
||||
|
@ -48,8 +48,8 @@ namespace Kyoo.Tests.Database
|
||||
SeasonRepository season = new(_NewContext(), show, provider);
|
||||
LibraryItemRepository libraryItem = new(_NewContext(),
|
||||
new Lazy<ILibraryRepository>(() => LibraryManager.LibraryRepository));
|
||||
TrackRepository track = new(_NewContext());
|
||||
EpisodeRepository episode = new(_NewContext(), show, provider, track);
|
||||
EpisodeRepository episode = new(_NewContext(), show, provider, new Lazy<ITrackRepository>(() => LibraryManager.TrackRepository));
|
||||
TrackRepository track = new(_NewContext(), episode);
|
||||
UserRepository user = new(_NewContext());
|
||||
|
||||
LibraryManager = new LibraryManager(new IBaseRepository[] {
|
||||
|
@ -104,7 +104,7 @@ namespace Kyoo.Tests
|
||||
{
|
||||
string server = Environment.GetEnvironmentVariable("POSTGRES_HOST") ?? "127.0.0.1";
|
||||
string port = Environment.GetEnvironmentVariable("POSTGRES_PORT") ?? "5432";
|
||||
string username = Environment.GetEnvironmentVariable("POSTGRES_USERNAME") ?? "kyoo";
|
||||
string username = Environment.GetEnvironmentVariable("POSTGRES_USER") ?? "kyoo";
|
||||
string password = Environment.GetEnvironmentVariable("POSTGRES_PASSWORD") ?? "kyooPassword";
|
||||
return $"Server={server};Port={port};Database={database};User ID={username};Password={password};Include Error Detail=true";
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user