Compare commits
6 commits
fab306c393
...
6f920f3f0d
| Author | SHA1 | Date | |
|---|---|---|---|
| 6f920f3f0d | |||
| 5387e1beb7 | |||
| 57b6f24e35 | |||
| 72dca6c1fe | |||
| e2d0c327eb | |||
| c3cd7b5a16 |
8 changed files with 420 additions and 1 deletions
|
|
@ -18,6 +18,53 @@ public class DataContext : DbContext
|
|||
modelBuilder.Entity<Playlist>()
|
||||
.Navigation(e => e.videos).AutoInclude();
|
||||
}
|
||||
|
||||
public override int SaveChanges()
|
||||
{
|
||||
TrackChanges();
|
||||
return base.SaveChanges();
|
||||
}
|
||||
|
||||
public override async Task<int> SaveChangesAsync(CancellationToken ct = default)
|
||||
{
|
||||
TrackChanges();
|
||||
return await base.SaveChangesAsync(ct);
|
||||
}
|
||||
|
||||
private void TrackChanges()
|
||||
{
|
||||
var changedEntries = ChangeTracker.Entries()
|
||||
.Where(e => e.State == EntityState.Added ||
|
||||
e.State == EntityState.Modified ||
|
||||
e.State == EntityState.Deleted)
|
||||
.ToList();
|
||||
|
||||
foreach (var entry in changedEntries)
|
||||
{
|
||||
var log = new ChangeLog
|
||||
{
|
||||
TableName = entry.Metadata.GetTableName() ?? entry.Entity.GetType().Name,
|
||||
ChangeType = entry.State.ToString(),
|
||||
ChangeTime = DateTime.UtcNow
|
||||
};
|
||||
|
||||
ChangeLogs.Add(log);
|
||||
}
|
||||
}
|
||||
|
||||
public ChangeLog? GetLatestChange()
|
||||
{
|
||||
return ChangeLogs
|
||||
.OrderByDescending(cl => cl.ChangeTime)
|
||||
.FirstOrDefault();
|
||||
}
|
||||
|
||||
public async Task<ChangeLog?> GetLatestChangeAsync(CancellationToken ct = default)
|
||||
{
|
||||
return await ChangeLogs
|
||||
.OrderByDescending(cl => cl.ChangeTime)
|
||||
.FirstOrDefaultAsync(ct);
|
||||
}
|
||||
|
||||
public DbSet<History> Histories { get; set; }
|
||||
public DbSet<Playlist> Playlists { get; set; }
|
||||
|
|
@ -26,4 +73,5 @@ public class DataContext : DbContext
|
|||
public DbSet<Setting> Settings { get; set; }
|
||||
public DbSet<Subscription> Subscriptions { get; set; }
|
||||
public DbSet<Video> Videos { get; set; }
|
||||
public DbSet<ChangeLog> ChangeLogs { get; set; }
|
||||
}
|
||||
29
FreeTubeSync/EndPoints/PingEndpoint.cs
Normal file
29
FreeTubeSync/EndPoints/PingEndpoint.cs
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
using FreeTubeSync.Database;
|
||||
using FreeTubeSync.Model.Database;
|
||||
|
||||
namespace FreeTubeSync.EndPoints;
|
||||
|
||||
public static class PingEndpoint
|
||||
{
|
||||
public static void MapPingEndpoints(this WebApplication app)
|
||||
{
|
||||
var group = app.MapGroup("ping");
|
||||
group.MapGet("/", async (CancellationToken token) =>
|
||||
{
|
||||
await Task.Delay(10);
|
||||
var dict = new { AppVersion = "0.1.3" };
|
||||
return Results.Ok(dict);
|
||||
});
|
||||
|
||||
group.MapGet("/lastUpdated", async (DataContext dbContext, CancellationToken token) =>
|
||||
{
|
||||
var log = await dbContext.GetLatestChangeAsync(token);
|
||||
|
||||
if (log == null)
|
||||
return Results.NotFound();
|
||||
|
||||
var dict = new { LastUpdated = log.ChangeTime };
|
||||
return Results.Ok(dict);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -51,7 +51,10 @@ public static class ProfileEndpoint
|
|||
if (f == null)
|
||||
notFound.Add(subscription);
|
||||
else
|
||||
{
|
||||
subscription.MapFrom(f);
|
||||
await subRepo.UpdateAsync(subscription, ct, false);
|
||||
}
|
||||
}
|
||||
var newSubs = (from subscription in profileJson.subscriptions let f = res.subscriptions.FirstOrDefault(s => s.id == subscription.id) where f == null select subscription).ToList();
|
||||
|
||||
|
|
@ -72,7 +75,7 @@ public static class ProfileEndpoint
|
|||
{
|
||||
res.subscriptions.Remove(nfSub);
|
||||
}
|
||||
|
||||
|
||||
await repository.UpdateAsync(res, ct);
|
||||
}
|
||||
|
||||
|
|
|
|||
269
FreeTubeSync/Migrations/20250731174538_AddChangeLogTracking.Designer.cs
generated
Normal file
269
FreeTubeSync/Migrations/20250731174538_AddChangeLogTracking.Designer.cs
generated
Normal file
|
|
@ -0,0 +1,269 @@
|
|||
// <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("20250731174538_AddChangeLogTracking")]
|
||||
partial class AddChangeLogTracking
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder.HasAnnotation("ProductVersion", "9.0.7");
|
||||
|
||||
modelBuilder.Entity("FreeTubeSync.Model.Database.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.Database.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.Database.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.Database.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.Database.SearchHistory", b =>
|
||||
{
|
||||
b.Property<string>("_id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<long>("lastUpdatedAt")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("_id");
|
||||
|
||||
b.ToTable("SearchHistories");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FreeTubeSync.Model.Database.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.Database.Subscription", 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.Property<string>("playlistItemId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Playlist_id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("author")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("authorId")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("lengthSeconds")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<long>("pubished")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<long>("timeAdded")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("title")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("type")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("videoId")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("playlistItemId");
|
||||
|
||||
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")
|
||||
.HasForeignKey("Playlist_id");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FreeTubeSync.Model.Database.Playlist", b =>
|
||||
{
|
||||
b.Navigation("videos");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FreeTubeSync.Model.Database.Profile", b =>
|
||||
{
|
||||
b.Navigation("subscriptions");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace FreeTubeSync.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddChangeLogTracking : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "ChangeLogs",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
TableName = table.Column<string>(type: "TEXT", nullable: false),
|
||||
ChangeType = table.Column<string>(type: "TEXT", nullable: false),
|
||||
ChangeTime = table.Column<DateTime>(type: "TEXT", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_ChangeLogs", x => x.Id);
|
||||
});
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "ChangeLogs");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
// <auto-generated />
|
||||
using System;
|
||||
using FreeTubeSync.Database;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
|
|
@ -16,6 +17,28 @@ namespace FreeTubeSync.Migrations
|
|||
#pragma warning disable 612, 618
|
||||
modelBuilder.HasAnnotation("ProductVersion", "9.0.7");
|
||||
|
||||
modelBuilder.Entity("FreeTubeSync.Model.Database.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.Database.History", b =>
|
||||
{
|
||||
b.Property<string>("_id")
|
||||
|
|
|
|||
9
FreeTubeSync/Model/Database/ChangeLog.cs
Normal file
9
FreeTubeSync/Model/Database/ChangeLog.cs
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
namespace FreeTubeSync.Model.Database;
|
||||
|
||||
public class ChangeLog
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string TableName { get; set; } = string.Empty;
|
||||
public string ChangeType { get; set; } = string.Empty;
|
||||
public DateTime ChangeTime { get; set; } = DateTime.MinValue;
|
||||
}
|
||||
|
|
@ -22,6 +22,7 @@ app.MapPlaylistEndpoints();
|
|||
app.MapProfileEndpoints();
|
||||
app.MapSearchHistoryEndpoints();
|
||||
app.MapSettingEndpoints();
|
||||
app.MapPingEndpoints();
|
||||
|
||||
await using(var serviceScope = app.Services.CreateAsyncScope())
|
||||
await using (var dbContext = serviceScope.ServiceProvider.GetRequiredService<DataContext>())
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue