diff --git a/Kyoo.Common/Controllers/ILibraryManager.cs b/Kyoo.Common/Controllers/ILibraryManager.cs index 1d23460a..ee141bde 100644 --- a/Kyoo.Common/Controllers/ILibraryManager.cs +++ b/Kyoo.Common/Controllers/ILibraryManager.cs @@ -55,6 +55,7 @@ namespace Kyoo.Controllers bool IsEpisodeRegistered(string episodePath, out long episodeID); //Register values + long RegisterLibrary(Library library); long RegisterCollection(Collection collection); long RegisterShow(Show show); long EditShow(Show show); diff --git a/Kyoo.Common/Models/ProviderLink.cs b/Kyoo.Common/Models/ProviderLink.cs index 5abfc260..6bf0eacf 100644 --- a/Kyoo.Common/Models/ProviderLink.cs +++ b/Kyoo.Common/Models/ProviderLink.cs @@ -10,9 +10,30 @@ namespace Kyoo.Models [JsonIgnore] public long? LibraryID { get; set; } [JsonIgnore] public virtual Library Library { get; set; } - public string Name => Provider.Name; - public string Logo => Provider.Logo; - + public string Name + { + get => Provider?.Name; + set + { + if (Provider != null) + Provider.Name = value; + else + Provider = new ProviderID {Name = value}; + } + } + + public string Logo + { + get => Provider?.Logo; + set + { + if (Provider != null) + Provider.Logo = value; + else + Provider = new ProviderID {Logo = value}; + } + } + public ProviderLink() { } } } \ No newline at end of file diff --git a/Kyoo/Controllers/LibraryManager.cs b/Kyoo/Controllers/LibraryManager.cs index 10457943..457e84ff 100644 --- a/Kyoo/Controllers/LibraryManager.cs +++ b/Kyoo/Controllers/LibraryManager.cs @@ -354,11 +354,28 @@ namespace Kyoo.Controllers return collection.ID; } + public long RegisterLibrary(Library library) + { + if (library == null) + return 0; + library.Providers = library.Providers.Select(x => + { + x.Provider = _database.Providers.FirstOrDefault(y => y.Name == x.Name); + if (x.Provider != null) + x.ProviderID = x.Provider.ID; + return x; + }).Where(x => x.Provider != null).ToList(); + if (_database.Entry(library).State == EntityState.Detached) + _database.Libraries.Add(library); + _database.SaveChanges(); + return library.ID; + } + public long RegisterShow(Show show) { if (show == null) return 0; - if (!_database.Entry(show).IsKeySet) + if (_database.Entry(show).State == EntityState.Detached) _database.Shows.Add(show); _database.SaveChanges(); return show.ID; diff --git a/Kyoo/Models/DatabaseContext.cs b/Kyoo/Models/DatabaseContext.cs index 3d4b9b13..991f358a 100644 --- a/Kyoo/Models/DatabaseContext.cs +++ b/Kyoo/Models/DatabaseContext.cs @@ -124,6 +124,11 @@ namespace Kyoo .Ignore(x => x.Name); modelBuilder.Entity() .Ignore(x => x.ExternalIDs); + + modelBuilder.Entity() + .Ignore(x => x.Name); + modelBuilder.Entity() + .Ignore(x => x.Logo); modelBuilder.Entity() diff --git a/Kyoo/Models/DatabaseMigrations/Internal/20200426223831_Initial.Designer.cs b/Kyoo/Models/DatabaseMigrations/Internal/20200426223831_Initial.Designer.cs new file mode 100644 index 00000000..36ce01db --- /dev/null +++ b/Kyoo/Models/DatabaseMigrations/Internal/20200426223831_Initial.Designer.cs @@ -0,0 +1,624 @@ +// +using System; +using Kyoo; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +namespace Kyoo.Models.DatabaseMigrations.Internal +{ + [DbContext(typeof(DatabaseContext))] + [Migration("20200426223831_Initial")] + partial class Initial + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.3"); + + modelBuilder.Entity("Kyoo.Models.Collection", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ImgPrimary") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Overview") + .HasColumnType("TEXT"); + + b.Property("Poster") + .HasColumnType("TEXT"); + + b.Property("Slug") + .HasColumnType("TEXT"); + + b.HasKey("ID"); + + b.HasIndex("Slug") + .IsUnique(); + + b.ToTable("Collections"); + }); + + modelBuilder.Entity("Kyoo.Models.CollectionLink", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CollectionID") + .HasColumnType("INTEGER"); + + b.Property("ShowID") + .HasColumnType("INTEGER"); + + b.HasKey("ID"); + + b.HasIndex("CollectionID"); + + b.HasIndex("ShowID"); + + b.ToTable("CollectionLinks"); + }); + + modelBuilder.Entity("Kyoo.Models.Episode", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AbsoluteNumber") + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("ImgPrimary") + .HasColumnType("TEXT"); + + b.Property("Overview") + .HasColumnType("TEXT"); + + b.Property("Path") + .HasColumnType("TEXT"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("Runtime") + .HasColumnType("INTEGER"); + + b.Property("SeasonID") + .HasColumnType("INTEGER"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("ShowID") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("ID"); + + b.HasIndex("SeasonID"); + + b.HasIndex("ShowID"); + + b.ToTable("Episodes"); + }); + + modelBuilder.Entity("Kyoo.Models.Genre", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Slug") + .HasColumnType("TEXT"); + + b.HasKey("ID"); + + b.HasIndex("Slug") + .IsUnique(); + + b.ToTable("Genres"); + }); + + modelBuilder.Entity("Kyoo.Models.GenreLink", b => + { + b.Property("ShowID") + .HasColumnType("INTEGER"); + + b.Property("GenreID") + .HasColumnType("INTEGER"); + + b.HasKey("ShowID", "GenreID"); + + b.HasIndex("GenreID"); + + b.ToTable("GenreLinks"); + }); + + modelBuilder.Entity("Kyoo.Models.Library", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Paths") + .HasColumnType("TEXT"); + + b.Property("Slug") + .HasColumnType("TEXT"); + + b.HasKey("ID"); + + b.HasIndex("Slug") + .IsUnique(); + + b.ToTable("Libraries"); + }); + + modelBuilder.Entity("Kyoo.Models.LibraryLink", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CollectionID") + .HasColumnType("INTEGER"); + + b.Property("LibraryID") + .HasColumnType("INTEGER"); + + b.Property("ShowID") + .HasColumnType("INTEGER"); + + b.HasKey("ID"); + + b.HasIndex("CollectionID"); + + b.HasIndex("LibraryID"); + + b.HasIndex("ShowID"); + + b.ToTable("LibraryLinks"); + }); + + modelBuilder.Entity("Kyoo.Models.MetadataID", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DataID") + .HasColumnType("TEXT"); + + b.Property("EpisodeID") + .HasColumnType("INTEGER"); + + b.Property("Link") + .HasColumnType("TEXT"); + + b.Property("PeopleID") + .HasColumnType("INTEGER"); + + b.Property("ProviderID") + .HasColumnType("INTEGER"); + + b.Property("SeasonID") + .HasColumnType("INTEGER"); + + b.Property("ShowID") + .HasColumnType("INTEGER"); + + b.HasKey("ID"); + + b.HasIndex("EpisodeID"); + + b.HasIndex("PeopleID"); + + b.HasIndex("ProviderID"); + + b.HasIndex("SeasonID"); + + b.HasIndex("ShowID"); + + b.ToTable("MetadataIds"); + }); + + modelBuilder.Entity("Kyoo.Models.People", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ImgPrimary") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Slug") + .HasColumnType("TEXT"); + + b.HasKey("ID"); + + b.HasIndex("Slug") + .IsUnique(); + + b.ToTable("Peoples"); + }); + + modelBuilder.Entity("Kyoo.Models.PeopleLink", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("PeopleID") + .HasColumnType("TEXT"); + + b.Property("PeopleID1") + .HasColumnType("INTEGER"); + + b.Property("Role") + .HasColumnType("TEXT"); + + b.Property("ShowID") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("TEXT"); + + b.HasKey("ID"); + + b.HasIndex("PeopleID1"); + + b.HasIndex("ShowID"); + + b.ToTable("PeopleLinks"); + }); + + modelBuilder.Entity("Kyoo.Models.ProviderID", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Logo") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.HasKey("ID"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("Providers"); + }); + + modelBuilder.Entity("Kyoo.Models.ProviderLink", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("LibraryID") + .HasColumnType("INTEGER"); + + b.Property("ProviderID") + .HasColumnType("INTEGER"); + + b.HasKey("ID"); + + b.HasIndex("LibraryID"); + + b.HasIndex("ProviderID"); + + b.ToTable("ProviderLinks"); + }); + + modelBuilder.Entity("Kyoo.Models.Season", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ImgPrimary") + .HasColumnType("TEXT"); + + b.Property("Overview") + .HasColumnType("TEXT"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("ShowID") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("Year") + .HasColumnType("INTEGER"); + + b.HasKey("ID"); + + b.HasIndex("ShowID"); + + b.ToTable("Seasons"); + }); + + modelBuilder.Entity("Kyoo.Models.Show", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Aliases") + .HasColumnType("TEXT"); + + b.Property("Backdrop") + .HasColumnType("TEXT"); + + b.Property("EndYear") + .HasColumnType("INTEGER"); + + b.Property("IsMovie") + .HasColumnType("INTEGER"); + + b.Property("Logo") + .HasColumnType("TEXT"); + + b.Property("Overview") + .HasColumnType("TEXT"); + + b.Property("Path") + .HasColumnType("TEXT"); + + b.Property("Poster") + .HasColumnType("TEXT"); + + b.Property("Slug") + .HasColumnType("TEXT"); + + b.Property("StartYear") + .HasColumnType("INTEGER"); + + b.Property("Status") + .HasColumnType("INTEGER"); + + b.Property("StudioID") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TrailerUrl") + .HasColumnType("TEXT"); + + b.HasKey("ID"); + + b.HasIndex("Slug") + .IsUnique(); + + b.HasIndex("StudioID"); + + b.ToTable("Shows"); + }); + + modelBuilder.Entity("Kyoo.Models.Studio", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Slug") + .HasColumnType("TEXT"); + + b.HasKey("ID"); + + b.HasIndex("Slug") + .IsUnique(); + + b.ToTable("Studios"); + }); + + modelBuilder.Entity("Kyoo.Models.Track", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Codec") + .HasColumnType("TEXT"); + + b.Property("EpisodeID") + .HasColumnType("INTEGER"); + + b.Property("IsDefault") + .HasColumnType("INTEGER"); + + b.Property("IsExternal") + .HasColumnType("INTEGER"); + + b.Property("IsForced") + .HasColumnType("INTEGER"); + + b.Property("Language") + .HasColumnType("TEXT"); + + b.Property("Path") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("ID"); + + b.HasIndex("EpisodeID"); + + b.ToTable("Tracks"); + }); + + modelBuilder.Entity("Kyoo.Models.CollectionLink", b => + { + b.HasOne("Kyoo.Models.Collection", "Collection") + .WithMany() + .HasForeignKey("CollectionID"); + + b.HasOne("Kyoo.Models.Show", "Show") + .WithMany() + .HasForeignKey("ShowID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Kyoo.Models.Episode", b => + { + b.HasOne("Kyoo.Models.Season", "Season") + .WithMany("Episodes") + .HasForeignKey("SeasonID"); + + b.HasOne("Kyoo.Models.Show", "Show") + .WithMany("Episodes") + .HasForeignKey("ShowID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Kyoo.Models.GenreLink", b => + { + b.HasOne("Kyoo.Models.Genre", "Genre") + .WithMany() + .HasForeignKey("GenreID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Kyoo.Models.Show", "Show") + .WithMany("GenreLinks") + .HasForeignKey("ShowID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Kyoo.Models.LibraryLink", b => + { + b.HasOne("Kyoo.Models.Collection", "Collection") + .WithMany() + .HasForeignKey("CollectionID"); + + b.HasOne("Kyoo.Models.Library", "Library") + .WithMany() + .HasForeignKey("LibraryID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Kyoo.Models.Show", "Show") + .WithMany() + .HasForeignKey("ShowID"); + }); + + modelBuilder.Entity("Kyoo.Models.MetadataID", b => + { + b.HasOne("Kyoo.Models.Episode", "Episode") + .WithMany("ExternalIDs") + .HasForeignKey("EpisodeID"); + + b.HasOne("Kyoo.Models.People", "People") + .WithMany("ExternalIDs") + .HasForeignKey("PeopleID"); + + b.HasOne("Kyoo.Models.ProviderID", "Provider") + .WithMany() + .HasForeignKey("ProviderID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Kyoo.Models.Season", "Season") + .WithMany("ExternalIDs") + .HasForeignKey("SeasonID"); + + b.HasOne("Kyoo.Models.Show", "Show") + .WithMany("ExternalIDs") + .HasForeignKey("ShowID"); + }); + + modelBuilder.Entity("Kyoo.Models.PeopleLink", b => + { + b.HasOne("Kyoo.Models.People", "People") + .WithMany("Roles") + .HasForeignKey("PeopleID1"); + + b.HasOne("Kyoo.Models.Show", "Show") + .WithMany("People") + .HasForeignKey("ShowID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Kyoo.Models.ProviderLink", b => + { + b.HasOne("Kyoo.Models.Library", "Library") + .WithMany("Providers") + .HasForeignKey("LibraryID"); + + b.HasOne("Kyoo.Models.ProviderID", "Provider") + .WithMany() + .HasForeignKey("ProviderID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Kyoo.Models.Season", b => + { + b.HasOne("Kyoo.Models.Show", "Show") + .WithMany("Seasons") + .HasForeignKey("ShowID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Kyoo.Models.Show", b => + { + b.HasOne("Kyoo.Models.Studio", "Studio") + .WithMany() + .HasForeignKey("StudioID"); + }); + + modelBuilder.Entity("Kyoo.Models.Track", b => + { + b.HasOne("Kyoo.Models.Episode", "Episode") + .WithMany("Tracks") + .HasForeignKey("EpisodeID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Kyoo/Models/DatabaseMigrations/Internal/20200426223831_Initial.cs b/Kyoo/Models/DatabaseMigrations/Internal/20200426223831_Initial.cs new file mode 100644 index 00000000..3ae1e6b9 --- /dev/null +++ b/Kyoo/Models/DatabaseMigrations/Internal/20200426223831_Initial.cs @@ -0,0 +1,598 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Kyoo.Models.DatabaseMigrations.Internal +{ + public partial class Initial : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Collections", + columns: table => new + { + ID = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Slug = table.Column(nullable: true), + Name = table.Column(nullable: true), + Poster = table.Column(nullable: true), + Overview = table.Column(nullable: true), + ImgPrimary = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Collections", x => x.ID); + }); + + migrationBuilder.CreateTable( + name: "Genres", + columns: table => new + { + ID = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Slug = table.Column(nullable: true), + Name = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Genres", x => x.ID); + }); + + migrationBuilder.CreateTable( + name: "Libraries", + columns: table => new + { + ID = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Slug = table.Column(nullable: true), + Name = table.Column(nullable: true), + Paths = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Libraries", x => x.ID); + }); + + migrationBuilder.CreateTable( + name: "Peoples", + columns: table => new + { + ID = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Slug = table.Column(nullable: true), + Name = table.Column(nullable: true), + ImgPrimary = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Peoples", x => x.ID); + }); + + migrationBuilder.CreateTable( + name: "Providers", + columns: table => new + { + ID = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Name = table.Column(nullable: true), + Logo = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Providers", x => x.ID); + }); + + migrationBuilder.CreateTable( + name: "Studios", + columns: table => new + { + ID = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Slug = table.Column(nullable: true), + Name = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Studios", x => x.ID); + }); + + migrationBuilder.CreateTable( + name: "ProviderLinks", + columns: table => new + { + ID = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + ProviderID = table.Column(nullable: false), + LibraryID = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_ProviderLinks", x => x.ID); + table.ForeignKey( + name: "FK_ProviderLinks_Libraries_LibraryID", + column: x => x.LibraryID, + principalTable: "Libraries", + principalColumn: "ID", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_ProviderLinks_Providers_ProviderID", + column: x => x.ProviderID, + principalTable: "Providers", + principalColumn: "ID", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Shows", + columns: table => new + { + ID = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Slug = table.Column(nullable: true), + Title = table.Column(nullable: true), + Aliases = table.Column(nullable: true), + Path = table.Column(nullable: true), + Overview = table.Column(nullable: true), + Status = table.Column(nullable: true), + TrailerUrl = table.Column(nullable: true), + StartYear = table.Column(nullable: true), + EndYear = table.Column(nullable: true), + Poster = table.Column(nullable: true), + Logo = table.Column(nullable: true), + Backdrop = table.Column(nullable: true), + IsMovie = table.Column(nullable: false), + StudioID = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Shows", x => x.ID); + table.ForeignKey( + name: "FK_Shows_Studios_StudioID", + column: x => x.StudioID, + principalTable: "Studios", + principalColumn: "ID", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "CollectionLinks", + columns: table => new + { + ID = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + CollectionID = table.Column(nullable: true), + ShowID = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_CollectionLinks", x => x.ID); + table.ForeignKey( + name: "FK_CollectionLinks_Collections_CollectionID", + column: x => x.CollectionID, + principalTable: "Collections", + principalColumn: "ID", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_CollectionLinks_Shows_ShowID", + column: x => x.ShowID, + principalTable: "Shows", + principalColumn: "ID", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "GenreLinks", + columns: table => new + { + ShowID = table.Column(nullable: false), + GenreID = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_GenreLinks", x => new { x.ShowID, x.GenreID }); + table.ForeignKey( + name: "FK_GenreLinks_Genres_GenreID", + column: x => x.GenreID, + principalTable: "Genres", + principalColumn: "ID", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_GenreLinks_Shows_ShowID", + column: x => x.ShowID, + principalTable: "Shows", + principalColumn: "ID", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "LibraryLinks", + columns: table => new + { + ID = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + LibraryID = table.Column(nullable: false), + ShowID = table.Column(nullable: true), + CollectionID = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_LibraryLinks", x => x.ID); + table.ForeignKey( + name: "FK_LibraryLinks_Collections_CollectionID", + column: x => x.CollectionID, + principalTable: "Collections", + principalColumn: "ID", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_LibraryLinks_Libraries_LibraryID", + column: x => x.LibraryID, + principalTable: "Libraries", + principalColumn: "ID", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_LibraryLinks_Shows_ShowID", + column: x => x.ShowID, + principalTable: "Shows", + principalColumn: "ID", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "PeopleLinks", + columns: table => new + { + ID = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + PeopleID = table.Column(nullable: true), + PeopleID1 = table.Column(nullable: true), + ShowID = table.Column(nullable: false), + Role = table.Column(nullable: true), + Type = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_PeopleLinks", x => x.ID); + table.ForeignKey( + name: "FK_PeopleLinks_Peoples_PeopleID1", + column: x => x.PeopleID1, + principalTable: "Peoples", + principalColumn: "ID", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_PeopleLinks_Shows_ShowID", + column: x => x.ShowID, + principalTable: "Shows", + principalColumn: "ID", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Seasons", + columns: table => new + { + ID = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + ShowID = table.Column(nullable: false), + SeasonNumber = table.Column(nullable: false), + Title = table.Column(nullable: true), + Overview = table.Column(nullable: true), + Year = table.Column(nullable: true), + ImgPrimary = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Seasons", x => x.ID); + table.ForeignKey( + name: "FK_Seasons_Shows_ShowID", + column: x => x.ShowID, + principalTable: "Shows", + principalColumn: "ID", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Episodes", + columns: table => new + { + ID = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + ShowID = table.Column(nullable: false), + SeasonID = table.Column(nullable: true), + SeasonNumber = table.Column(nullable: false), + EpisodeNumber = table.Column(nullable: false), + AbsoluteNumber = table.Column(nullable: false), + Path = table.Column(nullable: true), + Title = table.Column(nullable: true), + Overview = table.Column(nullable: true), + ReleaseDate = table.Column(nullable: true), + Runtime = table.Column(nullable: false), + ImgPrimary = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Episodes", x => x.ID); + table.ForeignKey( + name: "FK_Episodes_Seasons_SeasonID", + column: x => x.SeasonID, + principalTable: "Seasons", + principalColumn: "ID", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_Episodes_Shows_ShowID", + column: x => x.ShowID, + principalTable: "Shows", + principalColumn: "ID", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "MetadataIds", + columns: table => new + { + ID = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + ProviderID = table.Column(nullable: false), + ShowID = table.Column(nullable: true), + EpisodeID = table.Column(nullable: true), + SeasonID = table.Column(nullable: true), + PeopleID = table.Column(nullable: true), + DataID = table.Column(nullable: true), + Link = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_MetadataIds", x => x.ID); + table.ForeignKey( + name: "FK_MetadataIds_Episodes_EpisodeID", + column: x => x.EpisodeID, + principalTable: "Episodes", + principalColumn: "ID", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_MetadataIds_Peoples_PeopleID", + column: x => x.PeopleID, + principalTable: "Peoples", + principalColumn: "ID", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_MetadataIds_Providers_ProviderID", + column: x => x.ProviderID, + principalTable: "Providers", + principalColumn: "ID", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_MetadataIds_Seasons_SeasonID", + column: x => x.SeasonID, + principalTable: "Seasons", + principalColumn: "ID", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_MetadataIds_Shows_ShowID", + column: x => x.ShowID, + principalTable: "Shows", + principalColumn: "ID", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "Tracks", + columns: table => new + { + ID = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Title = table.Column(nullable: true), + Language = table.Column(nullable: true), + Codec = table.Column(nullable: true), + Path = table.Column(nullable: true), + Type = table.Column(nullable: false), + EpisodeID = table.Column(nullable: false), + IsDefault = table.Column(nullable: false), + IsForced = table.Column(nullable: false), + IsExternal = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Tracks", x => x.ID); + table.ForeignKey( + name: "FK_Tracks_Episodes_EpisodeID", + column: x => x.EpisodeID, + principalTable: "Episodes", + principalColumn: "ID", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_CollectionLinks_CollectionID", + table: "CollectionLinks", + column: "CollectionID"); + + migrationBuilder.CreateIndex( + name: "IX_CollectionLinks_ShowID", + table: "CollectionLinks", + column: "ShowID"); + + migrationBuilder.CreateIndex( + name: "IX_Collections_Slug", + table: "Collections", + column: "Slug", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_Episodes_SeasonID", + table: "Episodes", + column: "SeasonID"); + + migrationBuilder.CreateIndex( + name: "IX_Episodes_ShowID", + table: "Episodes", + column: "ShowID"); + + migrationBuilder.CreateIndex( + name: "IX_GenreLinks_GenreID", + table: "GenreLinks", + column: "GenreID"); + + migrationBuilder.CreateIndex( + name: "IX_Genres_Slug", + table: "Genres", + column: "Slug", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_Libraries_Slug", + table: "Libraries", + column: "Slug", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_LibraryLinks_CollectionID", + table: "LibraryLinks", + column: "CollectionID"); + + migrationBuilder.CreateIndex( + name: "IX_LibraryLinks_LibraryID", + table: "LibraryLinks", + column: "LibraryID"); + + migrationBuilder.CreateIndex( + name: "IX_LibraryLinks_ShowID", + table: "LibraryLinks", + column: "ShowID"); + + migrationBuilder.CreateIndex( + name: "IX_MetadataIds_EpisodeID", + table: "MetadataIds", + column: "EpisodeID"); + + migrationBuilder.CreateIndex( + name: "IX_MetadataIds_PeopleID", + table: "MetadataIds", + column: "PeopleID"); + + migrationBuilder.CreateIndex( + name: "IX_MetadataIds_ProviderID", + table: "MetadataIds", + column: "ProviderID"); + + migrationBuilder.CreateIndex( + name: "IX_MetadataIds_SeasonID", + table: "MetadataIds", + column: "SeasonID"); + + migrationBuilder.CreateIndex( + name: "IX_MetadataIds_ShowID", + table: "MetadataIds", + column: "ShowID"); + + migrationBuilder.CreateIndex( + name: "IX_PeopleLinks_PeopleID1", + table: "PeopleLinks", + column: "PeopleID1"); + + migrationBuilder.CreateIndex( + name: "IX_PeopleLinks_ShowID", + table: "PeopleLinks", + column: "ShowID"); + + migrationBuilder.CreateIndex( + name: "IX_Peoples_Slug", + table: "Peoples", + column: "Slug", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_ProviderLinks_LibraryID", + table: "ProviderLinks", + column: "LibraryID"); + + migrationBuilder.CreateIndex( + name: "IX_ProviderLinks_ProviderID", + table: "ProviderLinks", + column: "ProviderID"); + + migrationBuilder.CreateIndex( + name: "IX_Providers_Name", + table: "Providers", + column: "Name", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_Seasons_ShowID", + table: "Seasons", + column: "ShowID"); + + migrationBuilder.CreateIndex( + name: "IX_Shows_Slug", + table: "Shows", + column: "Slug", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_Shows_StudioID", + table: "Shows", + column: "StudioID"); + + migrationBuilder.CreateIndex( + name: "IX_Studios_Slug", + table: "Studios", + column: "Slug", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_Tracks_EpisodeID", + table: "Tracks", + column: "EpisodeID"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "CollectionLinks"); + + migrationBuilder.DropTable( + name: "GenreLinks"); + + migrationBuilder.DropTable( + name: "LibraryLinks"); + + migrationBuilder.DropTable( + name: "MetadataIds"); + + migrationBuilder.DropTable( + name: "PeopleLinks"); + + migrationBuilder.DropTable( + name: "ProviderLinks"); + + migrationBuilder.DropTable( + name: "Tracks"); + + migrationBuilder.DropTable( + name: "Genres"); + + migrationBuilder.DropTable( + name: "Collections"); + + migrationBuilder.DropTable( + name: "Peoples"); + + migrationBuilder.DropTable( + name: "Libraries"); + + migrationBuilder.DropTable( + name: "Providers"); + + migrationBuilder.DropTable( + name: "Episodes"); + + migrationBuilder.DropTable( + name: "Seasons"); + + migrationBuilder.DropTable( + name: "Shows"); + + migrationBuilder.DropTable( + name: "Studios"); + } + } +} diff --git a/Kyoo/Models/DatabaseMigrations/Internal/DatabaseContextModelSnapshot.cs b/Kyoo/Models/DatabaseMigrations/Internal/DatabaseContextModelSnapshot.cs index 32465a57..75c41270 100644 --- a/Kyoo/Models/DatabaseMigrations/Internal/DatabaseContextModelSnapshot.cs +++ b/Kyoo/Models/DatabaseMigrations/Internal/DatabaseContextModelSnapshot.cs @@ -310,7 +310,7 @@ namespace Kyoo.Models.DatabaseMigrations.Internal b.HasIndex("Name") .IsUnique(); - b.ToTable("ProviderIds"); + b.ToTable("Providers"); }); modelBuilder.Entity("Kyoo.Models.ProviderLink", b => diff --git a/Kyoo/Views/API/LibrariesAPI.cs b/Kyoo/Views/API/LibrariesAPI.cs index 75233fc1..6c972af8 100644 --- a/Kyoo/Views/API/LibrariesAPI.cs +++ b/Kyoo/Views/API/LibrariesAPI.cs @@ -8,12 +8,13 @@ using Microsoft.AspNetCore.Authorization; namespace Kyoo.Api { [Route("api/libraries")] + [Route("api/library")] [ApiController] - public class LibrariesController : ControllerBase + public class LibrariesAPI : ControllerBase { private readonly ILibraryManager _libraryManager; - public LibrariesController(ILibraryManager libraryManager) + public LibrariesAPI(ILibraryManager libraryManager) { _libraryManager = libraryManager; } @@ -23,6 +24,25 @@ namespace Kyoo.Api { return _libraryManager.GetLibraries(); } + + [Route("/api/library/create")] + [HttpPost] + [Authorize(Policy="Admin")] + public IActionResult CreateLibrary([FromBody] Library library) + { + if (!ModelState.IsValid) + return BadRequest(library); + if (string.IsNullOrEmpty(library.Slug)) + return BadRequest(new {error = "The library's slug must be set and not empty"}); + if (string.IsNullOrEmpty(library.Name)) + return BadRequest(new {error = "The library's name must be set and not empty"}); + if (library.Paths == null || library.Paths.Length == 0) + return BadRequest(new {error = "The library should have a least one path."}); + if (_libraryManager.GetLibrary(library.Slug) != null) + return BadRequest(new {error = "Duplicated library slug"}); + _libraryManager.RegisterLibrary(library); + return Ok(); + } [HttpGet("{librarySlug}")] [Authorize(Policy="Read")]