diff --git a/.gitignore b/.gitignore index f188de7..9bc3519 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,5 @@ obj/ riderModule.iml /_ReSharper.Caches/ FreeTubeSync.db +FreeTubeSync.db-wal +FreeTubeSync.db-shm diff --git a/FreeTubeSync/Database/DataContext.cs b/FreeTubeSync/Database/DataContext.cs index 48ca94d..61b74f9 100644 --- a/FreeTubeSync/Database/DataContext.cs +++ b/FreeTubeSync/Database/DataContext.cs @@ -25,6 +25,20 @@ public class DataContext : DbContext .Property(s => s.ValueJson) .HasColumnName("Value") .IsRequired(); + + modelBuilder.Entity() + .ToTable("Profiles") + .HasKey(s => s._id); + + modelBuilder.Entity() + .Navigation(e => e.subscriptions).AutoInclude(); + + modelBuilder.Entity() + .ToTable("Playlists") + .HasKey(s => s._id); + + modelBuilder.Entity() + .Navigation(e => e.videos).AutoInclude(); } public DbSet Histories { get; set; } diff --git a/FreeTubeSync/EndPoints/SearchHistoryEndpoint.cs b/FreeTubeSync/EndPoints/SearchHistoryEndpoint.cs index 38519ed..8908ddc 100644 --- a/FreeTubeSync/EndPoints/SearchHistoryEndpoint.cs +++ b/FreeTubeSync/EndPoints/SearchHistoryEndpoint.cs @@ -8,13 +8,13 @@ public static class SearchHistoryEndpoint { var group = app.MapGroup("searchHistory"); - group.MapGet("/", async (IRepository repository, CancellationToken ct) => + group.MapGet("/", async (IRepository repository, CancellationToken ct) => { var result = await repository.GetAllAsync(ct); return Results.Ok(result); }); - group.MapPost("/", async (IRepository repository, CancellationToken ct, History history) => + group.MapPost("/", async (IRepository repository, CancellationToken ct, SearchHistory history) => { var result = await repository.GetByIdAsync(history._id, ct); if (result != null) @@ -24,7 +24,7 @@ public static class SearchHistoryEndpoint return Results.Ok(); }); - group.MapDelete("/{id}", async (IRepository repository, CancellationToken ct, string id) => + group.MapDelete("/{id}", async (IRepository repository, CancellationToken ct, string id) => { var result = await repository.GetByIdAsync(id, ct); if (result == null) return Results.NotFound(); diff --git a/FreeTubeSync/Migrations/20250719172349_UpdateIntToLong.Designer.cs b/FreeTubeSync/Migrations/20250719172349_UpdateIntToLong.Designer.cs new file mode 100644 index 0000000..5631586 --- /dev/null +++ b/FreeTubeSync/Migrations/20250719172349_UpdateIntToLong.Designer.cs @@ -0,0 +1,247 @@ +// +using FreeTubeSync.Database; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace FreeTubeSync.Migrations +{ + [DbContext(typeof(DataContext))] + [Migration("20250719172349_UpdateIntToLong")] + partial class UpdateIntToLong + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "9.0.7"); + + modelBuilder.Entity("FreeTubeSync.Model.History", b => + { + b.Property("_id") + .HasColumnType("TEXT"); + + b.Property("author") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("authorId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("description") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("isLive") + .HasColumnType("INTEGER"); + + b.Property("lastViewedPlaylistItemId") + .HasColumnType("TEXT"); + + b.Property("lastViewedPlaylistType") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("lengthSeconds") + .HasColumnType("INTEGER"); + + b.Property("published") + .HasColumnType("INTEGER"); + + b.Property("timeWatched") + .HasColumnType("INTEGER"); + + b.Property("title") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("type") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("videoId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("viewCount") + .HasColumnType("INTEGER"); + + b.Property("watchProgress") + .HasColumnType("REAL"); + + b.HasKey("_id"); + + b.ToTable("Histories"); + }); + + modelBuilder.Entity("FreeTubeSync.Model.Playlist", b => + { + b.Property("_id") + .HasColumnType("TEXT"); + + b.Property("createdAt") + .HasColumnType("INTEGER"); + + b.Property("lastUpdatedAt") + .HasColumnType("INTEGER"); + + b.Property("playlistName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("protected") + .HasColumnType("INTEGER"); + + b.HasKey("_id"); + + b.ToTable("Playlists", (string)null); + }); + + modelBuilder.Entity("FreeTubeSync.Model.Profile", b => + { + b.Property("_id") + .HasColumnType("TEXT"); + + b.Property("bgColor") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("textColor") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("_id"); + + b.ToTable("Profiles", (string)null); + }); + + modelBuilder.Entity("FreeTubeSync.Model.SearchHistory", b => + { + b.Property("_id") + .HasColumnType("TEXT"); + + b.Property("lastUpdatedAt") + .HasColumnType("INTEGER"); + + b.HasKey("_id"); + + b.ToTable("SearchHistories"); + }); + + modelBuilder.Entity("FreeTubeSync.Model.Setting", b => + { + b.Property("_id") + .HasColumnType("TEXT"); + + b.Property("ValueJson") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("Value"); + + b.HasKey("_id"); + + b.ToTable("Settings", (string)null); + }); + + modelBuilder.Entity("FreeTubeSync.Model.Subscription", b => + { + b.Property("id") + .HasColumnType("TEXT"); + + b.Property("Profile_id") + .HasColumnType("TEXT"); + + b.Property("name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("thumbnail") + .HasColumnType("TEXT"); + + b.HasKey("id"); + + b.HasIndex("Profile_id"); + + b.ToTable("Subscriptions"); + }); + + modelBuilder.Entity("FreeTubeSync.Model.Video", b => + { + b.Property("videoId") + .HasColumnType("TEXT"); + + b.Property("Playlist_id") + .HasColumnType("TEXT"); + + b.Property("author") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("authorId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("lengthSeconds") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("playlistItemId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("pubished") + .HasColumnType("INTEGER"); + + b.Property("timeAdded") + .HasColumnType("INTEGER"); + + b.Property("title") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("type") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("videoId"); + + b.HasIndex("Playlist_id"); + + b.ToTable("Videos"); + }); + + modelBuilder.Entity("FreeTubeSync.Model.Subscription", b => + { + b.HasOne("FreeTubeSync.Model.Profile", null) + .WithMany("subscriptions") + .HasForeignKey("Profile_id"); + }); + + modelBuilder.Entity("FreeTubeSync.Model.Video", b => + { + b.HasOne("FreeTubeSync.Model.Playlist", null) + .WithMany("videos") + .HasForeignKey("Playlist_id"); + }); + + modelBuilder.Entity("FreeTubeSync.Model.Playlist", b => + { + b.Navigation("videos"); + }); + + modelBuilder.Entity("FreeTubeSync.Model.Profile", b => + { + b.Navigation("subscriptions"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/FreeTubeSync/Migrations/20250719172349_UpdateIntToLong.cs b/FreeTubeSync/Migrations/20250719172349_UpdateIntToLong.cs new file mode 100644 index 0000000..4456c89 --- /dev/null +++ b/FreeTubeSync/Migrations/20250719172349_UpdateIntToLong.cs @@ -0,0 +1,22 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace FreeTubeSync.Migrations +{ + /// + public partial class UpdateIntToLong : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + + } + } +} diff --git a/FreeTubeSync/Migrations/20250719172939_ChangePrimaryKeyToPlaylistItemId.Designer.cs b/FreeTubeSync/Migrations/20250719172939_ChangePrimaryKeyToPlaylistItemId.Designer.cs new file mode 100644 index 0000000..8a90fe8 --- /dev/null +++ b/FreeTubeSync/Migrations/20250719172939_ChangePrimaryKeyToPlaylistItemId.Designer.cs @@ -0,0 +1,247 @@ +// +using FreeTubeSync.Database; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace FreeTubeSync.Migrations +{ + [DbContext(typeof(DataContext))] + [Migration("20250719172939_ChangePrimaryKeyToPlaylistItemId")] + partial class ChangePrimaryKeyToPlaylistItemId + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "9.0.7"); + + modelBuilder.Entity("FreeTubeSync.Model.History", b => + { + b.Property("_id") + .HasColumnType("TEXT"); + + b.Property("author") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("authorId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("description") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("isLive") + .HasColumnType("INTEGER"); + + b.Property("lastViewedPlaylistItemId") + .HasColumnType("TEXT"); + + b.Property("lastViewedPlaylistType") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("lengthSeconds") + .HasColumnType("INTEGER"); + + b.Property("published") + .HasColumnType("INTEGER"); + + b.Property("timeWatched") + .HasColumnType("INTEGER"); + + b.Property("title") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("type") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("videoId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("viewCount") + .HasColumnType("INTEGER"); + + b.Property("watchProgress") + .HasColumnType("REAL"); + + b.HasKey("_id"); + + b.ToTable("Histories"); + }); + + modelBuilder.Entity("FreeTubeSync.Model.Playlist", b => + { + b.Property("_id") + .HasColumnType("TEXT"); + + b.Property("createdAt") + .HasColumnType("INTEGER"); + + b.Property("lastUpdatedAt") + .HasColumnType("INTEGER"); + + b.Property("playlistName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("protected") + .HasColumnType("INTEGER"); + + b.HasKey("_id"); + + b.ToTable("Playlists", (string)null); + }); + + modelBuilder.Entity("FreeTubeSync.Model.Profile", b => + { + b.Property("_id") + .HasColumnType("TEXT"); + + b.Property("bgColor") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("textColor") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("_id"); + + b.ToTable("Profiles", (string)null); + }); + + modelBuilder.Entity("FreeTubeSync.Model.SearchHistory", b => + { + b.Property("_id") + .HasColumnType("TEXT"); + + b.Property("lastUpdatedAt") + .HasColumnType("INTEGER"); + + b.HasKey("_id"); + + b.ToTable("SearchHistories"); + }); + + modelBuilder.Entity("FreeTubeSync.Model.Setting", b => + { + b.Property("_id") + .HasColumnType("TEXT"); + + b.Property("ValueJson") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("Value"); + + b.HasKey("_id"); + + b.ToTable("Settings", (string)null); + }); + + modelBuilder.Entity("FreeTubeSync.Model.Subscription", b => + { + b.Property("id") + .HasColumnType("TEXT"); + + b.Property("Profile_id") + .HasColumnType("TEXT"); + + b.Property("name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("thumbnail") + .HasColumnType("TEXT"); + + b.HasKey("id"); + + b.HasIndex("Profile_id"); + + b.ToTable("Subscriptions"); + }); + + modelBuilder.Entity("FreeTubeSync.Model.Video", b => + { + b.Property("playlistItemId") + .HasColumnType("TEXT"); + + b.Property("Playlist_id") + .HasColumnType("TEXT"); + + b.Property("author") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("authorId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("lengthSeconds") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("pubished") + .HasColumnType("INTEGER"); + + b.Property("timeAdded") + .HasColumnType("INTEGER"); + + b.Property("title") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("type") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("videoId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("playlistItemId"); + + b.HasIndex("Playlist_id"); + + b.ToTable("Videos"); + }); + + modelBuilder.Entity("FreeTubeSync.Model.Subscription", b => + { + b.HasOne("FreeTubeSync.Model.Profile", null) + .WithMany("subscriptions") + .HasForeignKey("Profile_id"); + }); + + modelBuilder.Entity("FreeTubeSync.Model.Video", b => + { + b.HasOne("FreeTubeSync.Model.Playlist", null) + .WithMany("videos") + .HasForeignKey("Playlist_id"); + }); + + modelBuilder.Entity("FreeTubeSync.Model.Playlist", b => + { + b.Navigation("videos"); + }); + + modelBuilder.Entity("FreeTubeSync.Model.Profile", b => + { + b.Navigation("subscriptions"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/FreeTubeSync/Migrations/20250719172939_ChangePrimaryKeyToPlaylistItemId.cs b/FreeTubeSync/Migrations/20250719172939_ChangePrimaryKeyToPlaylistItemId.cs new file mode 100644 index 0000000..82aa26e --- /dev/null +++ b/FreeTubeSync/Migrations/20250719172939_ChangePrimaryKeyToPlaylistItemId.cs @@ -0,0 +1,36 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace FreeTubeSync.Migrations +{ + /// + public partial class ChangePrimaryKeyToPlaylistItemId : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropPrimaryKey( + name: "PK_Videos", + table: "Videos"); + + migrationBuilder.AddPrimaryKey( + name: "PK_Videos", + table: "Videos", + column: "playlistItemId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropPrimaryKey( + name: "PK_Videos", + table: "Videos"); + + migrationBuilder.AddPrimaryKey( + name: "PK_Videos", + table: "Videos", + column: "videoId"); + } + } +} diff --git a/FreeTubeSync/Migrations/DataContextModelSnapshot.cs b/FreeTubeSync/Migrations/DataContextModelSnapshot.cs index ea14f77..985f8b7 100644 --- a/FreeTubeSync/Migrations/DataContextModelSnapshot.cs +++ b/FreeTubeSync/Migrations/DataContextModelSnapshot.cs @@ -1,5 +1,4 @@ // - using FreeTubeSync.Database; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; @@ -81,10 +80,10 @@ namespace FreeTubeSync.Migrations b.Property("_id") .HasColumnType("TEXT"); - b.Property("createdAt") + b.Property("createdAt") .HasColumnType("INTEGER"); - b.Property("lastUpdatedAt") + b.Property("lastUpdatedAt") .HasColumnType("INTEGER"); b.Property("playlistName") @@ -96,7 +95,7 @@ namespace FreeTubeSync.Migrations b.HasKey("_id"); - b.ToTable("Playlists"); + b.ToTable("Playlists", (string)null); }); modelBuilder.Entity("FreeTubeSync.Model.Profile", b => @@ -118,7 +117,7 @@ namespace FreeTubeSync.Migrations b.HasKey("_id"); - b.ToTable("Profiles"); + b.ToTable("Profiles", (string)null); }); modelBuilder.Entity("FreeTubeSync.Model.SearchHistory", b => @@ -126,7 +125,7 @@ namespace FreeTubeSync.Migrations b.Property("_id") .HasColumnType("TEXT"); - b.Property("lastUpdatedAt") + b.Property("lastUpdatedAt") .HasColumnType("INTEGER"); b.HasKey("_id"); @@ -173,7 +172,7 @@ namespace FreeTubeSync.Migrations modelBuilder.Entity("FreeTubeSync.Model.Video", b => { - b.Property("videoId") + b.Property("playlistItemId") .HasColumnType("TEXT"); b.Property("Playlist_id") @@ -191,14 +190,10 @@ namespace FreeTubeSync.Migrations .IsRequired() .HasColumnType("TEXT"); - b.Property("playlistItemId") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("pubished") + b.Property("pubished") .HasColumnType("INTEGER"); - b.Property("timeAdded") + b.Property("timeAdded") .HasColumnType("INTEGER"); b.Property("title") @@ -209,7 +204,11 @@ namespace FreeTubeSync.Migrations .IsRequired() .HasColumnType("TEXT"); - b.HasKey("videoId"); + b.Property("videoId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("playlistItemId"); b.HasIndex("Playlist_id"); diff --git a/FreeTubeSync/Model/Playlist.cs b/FreeTubeSync/Model/Playlist.cs index b07026d..2d1627e 100644 --- a/FreeTubeSync/Model/Playlist.cs +++ b/FreeTubeSync/Model/Playlist.cs @@ -11,8 +11,8 @@ public class Playlist public string playlistName { get; set; } = string.Empty; public bool @protected { get; set; } public List