Looks like we finally have a solution.
Change logging to just log a message, instead of the exception. Moved logic to Syncer involvement. When posting the data, if a 500 is returned, then it is up to the Syncer to re-submit it.
This commit is contained in:
parent
73955353cb
commit
004c490dd8
23 changed files with 529 additions and 177 deletions
|
|
@ -66,6 +66,17 @@ public class DataContext : DbContext
|
|||
.FirstOrDefaultAsync(ct);
|
||||
}
|
||||
|
||||
public async Task CleanupChangeLogAsync(CancellationToken ct = default)
|
||||
{
|
||||
var logs = await ChangeLogs.ToListAsync(ct);
|
||||
if (logs.Count < 50) return;
|
||||
for (var i = 0; i < (logs.Count - 50); i++)
|
||||
{
|
||||
ChangeLogs.Remove(logs[i]);
|
||||
}
|
||||
await base.SaveChangesAsync(ct);
|
||||
}
|
||||
|
||||
public DbSet<History> Histories { get; set; }
|
||||
public DbSet<Playlist> Playlists { get; set; }
|
||||
public DbSet<Profile> Profiles { get; set; }
|
||||
|
|
|
|||
|
|
@ -1,40 +0,0 @@
|
|||
using System.Collections;
|
||||
|
||||
namespace FreeTubeSync.Database;
|
||||
|
||||
public static class MapData
|
||||
{
|
||||
public static void MapFrom(this object obj2, object obj1)
|
||||
{
|
||||
var props = new Dictionary<string, object?>();
|
||||
var t1Type = obj1.GetType();
|
||||
var t2Type = obj2.GetType();
|
||||
|
||||
var properties = t1Type.GetProperties();
|
||||
foreach (var property in properties)
|
||||
{
|
||||
props[property.Name] = property.GetValue(obj1);
|
||||
}
|
||||
properties = t2Type.GetProperties();
|
||||
foreach (var property in properties)
|
||||
{
|
||||
if (props.ContainsKey(property.Name))
|
||||
{
|
||||
var value = props[property.Name];
|
||||
if (value is string || value is not IEnumerable)
|
||||
property.SetValue(obj2, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void MapTo<T1, T2>(this IEnumerable<T1> obj1, IList<T2> obj2)
|
||||
where T1 : class where T2 : class, new()
|
||||
{
|
||||
foreach (var obj in obj1)
|
||||
{
|
||||
var newObj = new T2();
|
||||
newObj.MapFrom(obj);
|
||||
obj2.Add(newObj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -32,25 +32,22 @@ public static class HistoryEndpoint
|
|||
{
|
||||
try
|
||||
{
|
||||
logger.LogInformation("History {id} does not exist, adding it to the database Thread: {thread}",
|
||||
history._id, Thread.CurrentThread.ManagedThreadId);
|
||||
await repository.AddAsync(history, ct);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.LogError(ex, "Failed to create history {json}", history._id);
|
||||
logger.LogError("Failed to create history {json}", history._id);
|
||||
return Results.StatusCode(500);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
await repository.UpdateAsync(history, ct);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.LogError(ex, "Failed to update history {json}", history._id);
|
||||
return Results.StatusCode(500);
|
||||
}
|
||||
logger.LogInformation("History {id} exists, updating the database. Thread: {thread}", history._id,
|
||||
Thread.CurrentThread.ManagedThreadId);
|
||||
results.UpdateFrom(history);
|
||||
await repository.UpdateAsync(results, ct);
|
||||
}
|
||||
return Results.Ok();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,10 +7,10 @@ public static class PingEndpoint
|
|||
public static void MapPingEndpoints(this WebApplication app)
|
||||
{
|
||||
var group = app.MapGroup("ping");
|
||||
group.MapGet("/", async (CancellationToken token) =>
|
||||
group.MapGet("/", async (DataContext dbContext, CancellationToken token) =>
|
||||
{
|
||||
await Task.Delay(10);
|
||||
var dict = new { AppVersion = "0.1.4" };
|
||||
await dbContext.CleanupChangeLogAsync(token);
|
||||
var dict = new { AppVersion = "0.1.5" };
|
||||
return Results.Ok(dict);
|
||||
});
|
||||
|
||||
|
|
@ -22,6 +22,7 @@ public static class PingEndpoint
|
|||
return Results.NotFound();
|
||||
|
||||
var dict = new { LastUpdated = log.ChangeTime };
|
||||
await dbContext.CleanupChangeLogAsync(token);
|
||||
return Results.Ok(dict);
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,24 +34,21 @@ public static class PlaylistEndpoint
|
|||
{
|
||||
try
|
||||
{
|
||||
logger.LogInformation("Playlist {id} does not exist, adding it to the database", playlist._id);
|
||||
await repository.AddAsync(playlist, ct);
|
||||
}
|
||||
catch (Exception ex)
|
||||
catch (Exception)
|
||||
{
|
||||
logger.LogError(ex, "Failed to create Playlist {playlist}", playlist._id);
|
||||
logger.LogError("Failed to create Playlist {playlist}", playlist._id);
|
||||
return Results.StatusCode(500);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Add Update Code here
|
||||
logger.LogInformation("Playlist {id} exists, updating the databsae.", playlist._id);
|
||||
results.UpdateFrom(playlist);
|
||||
var toRemove = results.videos.Where(vid => !playlist.videos.Any(x => x.playlistItemId == vid.playlistItemId)).ToList();
|
||||
|
||||
results.lastUpdatedAt = playlist.lastUpdatedAt;
|
||||
results.@protected = playlist.@protected;
|
||||
results.playlistName = playlist.playlistName;
|
||||
results.createdAt = playlist.createdAt;
|
||||
|
||||
foreach (var vid in toRemove)
|
||||
results.videos.Remove(vid);
|
||||
|
||||
|
|
|
|||
|
|
@ -33,22 +33,21 @@ public static class ProfileEndpoint
|
|||
{
|
||||
try
|
||||
{
|
||||
logger.LogInformation("Profile {id} does not exist, adding it to the database", profile._id);
|
||||
await repository.AddAsync(profile, ct);
|
||||
}
|
||||
catch (Exception ex)
|
||||
catch (Exception)
|
||||
{
|
||||
logger.LogError(ex, "Failed to create profile {json}", profile._id);
|
||||
logger.LogError("Failed to create profile {json}", profile._id);
|
||||
return Results.StatusCode(500);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.LogInformation("Profile {id} exists, updating the database.", profile._id);
|
||||
res.UpdateFrom(profile);
|
||||
var toRemove = res.subscriptions.Where(sub => !profile.subscriptions.Any(x => x.id == sub.id)).ToList();
|
||||
|
||||
res.name = profile.name;
|
||||
res.textColor = profile.textColor;
|
||||
res.bgColor = profile.bgColor;
|
||||
|
||||
foreach (var sub in toRemove)
|
||||
res.subscriptions.Remove(sub);
|
||||
|
||||
|
|
|
|||
|
|
@ -34,25 +34,20 @@ public static class SearchHistoryEndpoint
|
|||
{
|
||||
try
|
||||
{
|
||||
logger.LogInformation("SearchHistory {id} does not exist, adding it to the database", history._id);
|
||||
await repository.AddAsync(history, ct);
|
||||
}
|
||||
catch (Exception e)
|
||||
catch (Exception)
|
||||
{
|
||||
logger.LogError(e, "Failed to update history {json}", history._id);
|
||||
logger.LogError("Failed to update history {json}", history._id);
|
||||
return Results.StatusCode(500);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
await repository.UpdateAsync(history, ct);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.LogError(e, "Failed to update history {json}", history._id);
|
||||
return Results.StatusCode(500);
|
||||
}
|
||||
logger.LogInformation("SearchHistory {id} exists, updating the database.", history._id);
|
||||
result.UpdateFrom(history);
|
||||
await repository.UpdateAsync(result, ct);
|
||||
}
|
||||
|
||||
return Results.Ok();
|
||||
|
|
|
|||
|
|
@ -33,25 +33,20 @@ public static class SettingEndpoint
|
|||
{
|
||||
try
|
||||
{
|
||||
logger.LogInformation("Setting {id} does not exist, adding it to the database", setting._id);
|
||||
await repository.AddAsync(setting, ct);
|
||||
}
|
||||
catch (Exception ex)
|
||||
catch (Exception)
|
||||
{
|
||||
logger.LogError(ex, "Failed to add setting {setting}", setting._id);
|
||||
logger.LogError("Failed to add setting {setting}", setting._id);
|
||||
return Results.StatusCode(500);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
await repository.UpdateAsync(setting, ct);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.LogError(ex, "Failed to update setting {setting}", setting._id);
|
||||
return Results.StatusCode(500);
|
||||
}
|
||||
logger.LogInformation("Setting {id} exists, updating the database.", setting._id);
|
||||
res.UpdateFrom(setting);
|
||||
await repository.UpdateAsync(res, ct);
|
||||
}
|
||||
return Results.Ok();
|
||||
}
|
||||
|
|
|
|||
257
FreeTubeSync/Migrations/20250808221748_UpdateNewLayout.Designer.cs
generated
Normal file
257
FreeTubeSync/Migrations/20250808221748_UpdateNewLayout.Designer.cs
generated
Normal file
|
|
@ -0,0 +1,257 @@
|
|||
// <auto-generated />
|
||||
using System;
|
||||
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("20250808221748_UpdateNewLayout")]
|
||||
partial class UpdateNewLayout
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder.HasAnnotation("ProductVersion", "9.0.7");
|
||||
|
||||
modelBuilder.Entity("FreeTubeSync.Model.ChangeLog", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("ChangeTime")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ChangeType")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("TableName")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("ChangeLogs");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FreeTubeSync.Model.History", b =>
|
||||
{
|
||||
b.Property<string>("_id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("author")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("authorId")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("description")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("isLive")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("lastViewedPlaylistItemId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("lastViewedPlaylistType")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<long>("lengthSeconds")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<long>("published")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<long>("timeWatched")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("title")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("type")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("videoId")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<long>("viewCount")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<float>("watchProgress")
|
||||
.HasColumnType("REAL");
|
||||
|
||||
b.HasKey("_id");
|
||||
|
||||
b.ToTable("Histories");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FreeTubeSync.Model.Playlist", b =>
|
||||
{
|
||||
b.Property<string>("_id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<long>("createdAt")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<long>("lastUpdatedAt")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("playlistName")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("protected")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("_id");
|
||||
|
||||
b.ToTable("Playlists");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FreeTubeSync.Model.Profile", b =>
|
||||
{
|
||||
b.Property<string>("_id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("bgColor")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("name")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("textColor")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("_id");
|
||||
|
||||
b.ToTable("Profiles");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FreeTubeSync.Model.SearchHistory", b =>
|
||||
{
|
||||
b.Property<string>("_id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<long>("lastUpdatedAt")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("_id");
|
||||
|
||||
b.ToTable("SearchHistories");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FreeTubeSync.Model.Setting", b =>
|
||||
{
|
||||
b.Property<string>("_id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("value")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("_id");
|
||||
|
||||
b.ToTable("Settings");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FreeTubeSync.Model.Playlist", b =>
|
||||
{
|
||||
b.OwnsMany("FreeTubeSync.Model.Video", "videos", b1 =>
|
||||
{
|
||||
b1.Property<string>("Playlist_id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b1.Property<string>("videoId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b1.Property<string>("author")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b1.Property<string>("authorId")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b1.Property<string>("lengthSeconds")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b1.Property<string>("playlistItemId")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b1.Property<long>("published")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b1.Property<long>("timeAdded")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b1.Property<string>("title")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b1.Property<string>("type")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b1.HasKey("Playlist_id", "videoId");
|
||||
|
||||
b1.ToTable("Video");
|
||||
|
||||
b1.WithOwner()
|
||||
.HasForeignKey("Playlist_id");
|
||||
});
|
||||
|
||||
b.Navigation("videos");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FreeTubeSync.Model.Profile", b =>
|
||||
{
|
||||
b.OwnsMany("FreeTubeSync.Model.Subscription", "subscriptions", b1 =>
|
||||
{
|
||||
b1.Property<string>("Profile_id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b1.Property<string>("id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b1.Property<string>("name")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b1.Property<string>("thumbnail")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b1.HasKey("Profile_id", "id");
|
||||
|
||||
b1.ToTable("Subscription");
|
||||
|
||||
b1.WithOwner()
|
||||
.HasForeignKey("Profile_id");
|
||||
});
|
||||
|
||||
b.Navigation("subscriptions");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
130
FreeTubeSync/Migrations/20250808221748_UpdateNewLayout.cs
Normal file
130
FreeTubeSync/Migrations/20250808221748_UpdateNewLayout.cs
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace FreeTubeSync.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class UpdateNewLayout : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "Subscriptions");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Videos");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Subscription",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<string>(type: "TEXT", nullable: false),
|
||||
Profile_id = table.Column<string>(type: "TEXT", nullable: false),
|
||||
name = table.Column<string>(type: "TEXT", nullable: false),
|
||||
thumbnail = table.Column<string>(type: "TEXT", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Subscription", x => new { x.Profile_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "FK_Subscription_Profiles_Profile_id",
|
||||
column: x => x.Profile_id,
|
||||
principalTable: "Profiles",
|
||||
principalColumn: "_id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Video",
|
||||
columns: table => new
|
||||
{
|
||||
videoId = table.Column<string>(type: "TEXT", nullable: false),
|
||||
Playlist_id = table.Column<string>(type: "TEXT", nullable: false),
|
||||
title = table.Column<string>(type: "TEXT", nullable: false),
|
||||
author = table.Column<string>(type: "TEXT", nullable: false),
|
||||
authorId = table.Column<string>(type: "TEXT", nullable: false),
|
||||
lengthSeconds = table.Column<string>(type: "TEXT", nullable: false),
|
||||
published = table.Column<long>(type: "INTEGER", nullable: false),
|
||||
timeAdded = table.Column<long>(type: "INTEGER", nullable: false),
|
||||
playlistItemId = table.Column<string>(type: "TEXT", nullable: false),
|
||||
type = table.Column<string>(type: "TEXT", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Video", x => new { x.Playlist_id, x.videoId });
|
||||
table.ForeignKey(
|
||||
name: "FK_Video_Playlists_Playlist_id",
|
||||
column: x => x.Playlist_id,
|
||||
principalTable: "Playlists",
|
||||
principalColumn: "_id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "Subscription");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Video");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Subscriptions",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<string>(type: "TEXT", nullable: false),
|
||||
Profile_id = table.Column<string>(type: "TEXT", nullable: true),
|
||||
name = table.Column<string>(type: "TEXT", nullable: false),
|
||||
thumbnail = table.Column<string>(type: "TEXT", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Subscriptions", x => x.id);
|
||||
table.ForeignKey(
|
||||
name: "FK_Subscriptions_Profiles_Profile_id",
|
||||
column: x => x.Profile_id,
|
||||
principalTable: "Profiles",
|
||||
principalColumn: "_id");
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Videos",
|
||||
columns: table => new
|
||||
{
|
||||
playlistItemId = table.Column<string>(type: "TEXT", nullable: false),
|
||||
Playlist_id = table.Column<string>(type: "TEXT", nullable: true),
|
||||
author = table.Column<string>(type: "TEXT", nullable: false),
|
||||
authorId = table.Column<string>(type: "TEXT", nullable: false),
|
||||
lengthSeconds = table.Column<string>(type: "TEXT", nullable: false),
|
||||
pubished = table.Column<long>(type: "INTEGER", nullable: false),
|
||||
timeAdded = table.Column<long>(type: "INTEGER", nullable: false),
|
||||
title = table.Column<string>(type: "TEXT", nullable: false),
|
||||
type = table.Column<string>(type: "TEXT", nullable: false),
|
||||
videoId = table.Column<string>(type: "TEXT", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Videos", x => x.playlistItemId);
|
||||
table.ForeignKey(
|
||||
name: "FK_Videos_Playlists_Playlist_id",
|
||||
column: x => x.Playlist_id,
|
||||
principalTable: "Playlists",
|
||||
principalColumn: "_id");
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Subscriptions_Profile_id",
|
||||
table: "Subscriptions",
|
||||
column: "Profile_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Videos_Playlist_id",
|
||||
table: "Videos",
|
||||
column: "Playlist_id");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -17,7 +17,7 @@ namespace FreeTubeSync.Migrations
|
|||
#pragma warning disable 612, 618
|
||||
modelBuilder.HasAnnotation("ProductVersion", "9.0.7");
|
||||
|
||||
modelBuilder.Entity("FreeTubeSync.Model.Database.ChangeLog", b =>
|
||||
modelBuilder.Entity("FreeTubeSync.Model.ChangeLog", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
|
|
@ -39,7 +39,7 @@ namespace FreeTubeSync.Migrations
|
|||
b.ToTable("ChangeLogs");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FreeTubeSync.Model.Database.History", b =>
|
||||
modelBuilder.Entity("FreeTubeSync.Model.History", b =>
|
||||
{
|
||||
b.Property<string>("_id")
|
||||
.HasColumnType("TEXT");
|
||||
|
|
@ -98,7 +98,7 @@ namespace FreeTubeSync.Migrations
|
|||
b.ToTable("Histories");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FreeTubeSync.Model.Database.Playlist", b =>
|
||||
modelBuilder.Entity("FreeTubeSync.Model.Playlist", b =>
|
||||
{
|
||||
b.Property<string>("_id")
|
||||
.HasColumnType("TEXT");
|
||||
|
|
@ -121,7 +121,7 @@ namespace FreeTubeSync.Migrations
|
|||
b.ToTable("Playlists");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FreeTubeSync.Model.Database.Profile", b =>
|
||||
modelBuilder.Entity("FreeTubeSync.Model.Profile", b =>
|
||||
{
|
||||
b.Property<string>("_id")
|
||||
.HasColumnType("TEXT");
|
||||
|
|
@ -143,7 +143,7 @@ namespace FreeTubeSync.Migrations
|
|||
b.ToTable("Profiles");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FreeTubeSync.Model.Database.SearchHistory", b =>
|
||||
modelBuilder.Entity("FreeTubeSync.Model.SearchHistory", b =>
|
||||
{
|
||||
b.Property<string>("_id")
|
||||
.HasColumnType("TEXT");
|
||||
|
|
@ -156,7 +156,7 @@ namespace FreeTubeSync.Migrations
|
|||
b.ToTable("SearchHistories");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FreeTubeSync.Model.Database.Setting", b =>
|
||||
modelBuilder.Entity("FreeTubeSync.Model.Setting", b =>
|
||||
{
|
||||
b.Property<string>("_id")
|
||||
.HasColumnType("TEXT");
|
||||
|
|
@ -170,94 +170,82 @@ namespace FreeTubeSync.Migrations
|
|||
b.ToTable("Settings");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FreeTubeSync.Model.Database.Subscription", b =>
|
||||
modelBuilder.Entity("FreeTubeSync.Model.Playlist", b =>
|
||||
{
|
||||
b.Property<string>("id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Profile_id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("name")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("thumbnail")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("id");
|
||||
|
||||
b.HasIndex("Profile_id");
|
||||
|
||||
b.ToTable("Subscriptions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FreeTubeSync.Model.Database.Video", b =>
|
||||
b.OwnsMany("FreeTubeSync.Model.Video", "videos", b1 =>
|
||||
{
|
||||
b.Property<string>("playlistItemId")
|
||||
b1.Property<string>("Playlist_id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Playlist_id")
|
||||
b1.Property<string>("videoId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("author")
|
||||
b1.Property<string>("author")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("authorId")
|
||||
b1.Property<string>("authorId")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("lengthSeconds")
|
||||
b1.Property<string>("lengthSeconds")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<long>("pubished")
|
||||
b1.Property<string>("playlistItemId")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b1.Property<long>("published")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<long>("timeAdded")
|
||||
b1.Property<long>("timeAdded")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("title")
|
||||
b1.Property<string>("title")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("type")
|
||||
b1.Property<string>("type")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("videoId")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
b1.HasKey("Playlist_id", "videoId");
|
||||
|
||||
b.HasKey("playlistItemId");
|
||||
b1.ToTable("Video");
|
||||
|
||||
b.HasIndex("Playlist_id");
|
||||
|
||||
b.ToTable("Videos");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FreeTubeSync.Model.Database.Subscription", b =>
|
||||
{
|
||||
b.HasOne("FreeTubeSync.Model.Database.Profile", null)
|
||||
.WithMany("subscriptions")
|
||||
.HasForeignKey("Profile_id");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FreeTubeSync.Model.Database.Video", b =>
|
||||
{
|
||||
b.HasOne("FreeTubeSync.Model.Database.Playlist", null)
|
||||
.WithMany("videos")
|
||||
b1.WithOwner()
|
||||
.HasForeignKey("Playlist_id");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FreeTubeSync.Model.Database.Playlist", b =>
|
||||
{
|
||||
b.Navigation("videos");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FreeTubeSync.Model.Database.Profile", b =>
|
||||
modelBuilder.Entity("FreeTubeSync.Model.Profile", b =>
|
||||
{
|
||||
b.OwnsMany("FreeTubeSync.Model.Subscription", "subscriptions", b1 =>
|
||||
{
|
||||
b1.Property<string>("Profile_id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b1.Property<string>("id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b1.Property<string>("name")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b1.Property<string>("thumbnail")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b1.HasKey("Profile_id", "id");
|
||||
|
||||
b1.ToTable("Subscription");
|
||||
|
||||
b1.WithOwner()
|
||||
.HasForeignKey("Profile_id");
|
||||
});
|
||||
|
||||
b.Navigation("subscriptions");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
|
|
|
|||
17
FreeTubeSync/Model/BaseModel.cs
Normal file
17
FreeTubeSync/Model/BaseModel.cs
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
using System.Collections;
|
||||
|
||||
namespace FreeTubeSync.Model;
|
||||
|
||||
public class BaseModel
|
||||
{
|
||||
public void UpdateFrom(object other)
|
||||
{
|
||||
foreach (var prop in other.GetType().GetProperties())
|
||||
{
|
||||
if (prop.Name == "_id" || prop.Name == "id" || prop.Name == "Id" || prop.Name == "subscriptions" || prop.Name == "videos")
|
||||
continue;
|
||||
var val = prop.GetValue(other);
|
||||
prop.SetValue(this, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
namespace FreeTubeSync.Model;
|
||||
|
||||
public class ChangeLog
|
||||
public class ChangeLog : BaseModel
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string TableName { get; set; } = string.Empty;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ using System.ComponentModel.DataAnnotations;
|
|||
|
||||
namespace FreeTubeSync.Model;
|
||||
|
||||
public class History
|
||||
public class History : BaseModel
|
||||
{
|
||||
[Key]
|
||||
public string _id { get; set; } = string.Empty;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ using System.ComponentModel.DataAnnotations;
|
|||
|
||||
namespace FreeTubeSync.Model;
|
||||
|
||||
public class Playlist
|
||||
public class Playlist : BaseModel
|
||||
{
|
||||
[Key]
|
||||
public string _id { get; set; } = string.Empty;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ using System.ComponentModel.DataAnnotations;
|
|||
|
||||
namespace FreeTubeSync.Model;
|
||||
|
||||
public class Profile
|
||||
public class Profile : BaseModel
|
||||
{
|
||||
[Key]
|
||||
public string _id { get; set; } = string.Empty;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ using System.ComponentModel.DataAnnotations;
|
|||
|
||||
namespace FreeTubeSync.Model;
|
||||
|
||||
public class SearchHistory
|
||||
public class SearchHistory : BaseModel
|
||||
{
|
||||
[Key]
|
||||
public string _id { get; set; } = string.Empty;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ using System.ComponentModel.DataAnnotations;
|
|||
|
||||
namespace FreeTubeSync.Model;
|
||||
|
||||
public class Setting
|
||||
public class Setting : BaseModel
|
||||
{
|
||||
[Key]
|
||||
public string _id { get; set; }
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ using Microsoft.EntityFrameworkCore;
|
|||
namespace FreeTubeSync.Model;
|
||||
|
||||
[Owned]
|
||||
public class Subscription
|
||||
public class Subscription : BaseModel
|
||||
{
|
||||
public string id { get; set; } = string.Empty;
|
||||
public string name { get; set; } = string.Empty;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ using Microsoft.EntityFrameworkCore;
|
|||
namespace FreeTubeSync.Model;
|
||||
|
||||
[Owned]
|
||||
public class Video
|
||||
public class Video : BaseModel
|
||||
{
|
||||
public string videoId { get; set; } = string.Empty;
|
||||
public string title { get; set; } = string.Empty;
|
||||
|
|
|
|||
|
|
@ -22,9 +22,12 @@ public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
|
|||
}
|
||||
|
||||
public async Task UpdateAsync(TEntity entity, CancellationToken ct, bool sync = true)
|
||||
{
|
||||
if (!_dbSet.Local.Contains(entity))
|
||||
{
|
||||
_dbSet.Attach(entity);
|
||||
_context.Entry(entity).State = EntityState.Modified;
|
||||
}
|
||||
if (sync)
|
||||
await _context.SaveChangesAsync(ct);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,8 @@
|
|||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
"Microsoft.AspNetCore": "Warning",
|
||||
"Microsoft.EntityFrameworkCore": "Warning"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,8 @@
|
|||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
"Microsoft.AspNetCore": "Warning",
|
||||
"Microsoft.EntityFrameworkCore": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue