From 35cbf57f419311f349790b9e1126b6dd374b3004 Mon Sep 17 00:00:00 2001
From: rlauu <46294892+rlauu@users.noreply.github.com>
Date: Mon, 25 Nov 2024 16:05:50 +0100
Subject: [PATCH] Add button to recreate db
---
IntroSkipper/Configuration/configPage.html | 7 ++
.../Controllers/SkipIntroController.cs | 14 ++++
IntroSkipper/Db/IntroSkipperDbContext.cs | 72 ++++++++++++++-----
3 files changed, 74 insertions(+), 19 deletions(-)
diff --git a/IntroSkipper/Configuration/configPage.html b/IntroSkipper/Configuration/configPage.html
index 36b41ca..a2a1398 100644
--- a/IntroSkipper/Configuration/configPage.html
+++ b/IntroSkipper/Configuration/configPage.html
@@ -714,6 +714,9 @@
+
+
+
@@ -758,6 +761,7 @@
var btnEraseRecapTimestamps = document.querySelector("button#btnEraseRecapTimestamps");
var btnEraseCreditTimestamps = document.querySelector("button#btnEraseCreditTimestamps");
var btnErasePreviewTimestamps = document.querySelector("button#btnErasePreviewTimestamps");
+ var btnRebuildDatabase = document.querySelector("button#btnRebuildDatabase");
// all plugin configuration fields that can be get or set with .value (i.e. strings or numbers).
var configurationFields = [
@@ -1504,6 +1508,9 @@
eraseTimestamps("Preview");
e.preventDefault();
});
+ btnRebuildDatabase.addEventListener("click", () => {
+ fetchWithAuth("Intros/RebuildDatabase", "POST", null);
+ });
btnSeasonEraseTimestamps.addEventListener("click", () => {
Dashboard.confirm("Are you sure you want to erase all timestamps for this season?", "Confirm timestamp erasure", (result) => {
if (!result) {
diff --git a/IntroSkipper/Controllers/SkipIntroController.cs b/IntroSkipper/Controllers/SkipIntroController.cs
index 9a10e54..4aeafa1 100644
--- a/IntroSkipper/Controllers/SkipIntroController.cs
+++ b/IntroSkipper/Controllers/SkipIntroController.cs
@@ -251,6 +251,20 @@ public class SkipIntroController(MediaSegmentUpdateManager mediaSegmentUpdateMan
return NoContent();
}
+ ///
+ /// Rebuilds the database.
+ ///
+ /// Database rebuilt.
+ /// No content.
+ [Authorize(Policy = Policies.RequiresElevation)]
+ [HttpPost("Intros/RebuildDatabase")]
+ public ActionResult RebuildDatabase()
+ {
+ using var db = new IntroSkipperDbContext(Plugin.Instance!.DbPath);
+ db.RebuildDatabase();
+ return NoContent();
+ }
+
///
/// Gets the user interface configuration.
///
diff --git a/IntroSkipper/Db/IntroSkipperDbContext.cs b/IntroSkipper/Db/IntroSkipperDbContext.cs
index 920d926..58da67c 100644
--- a/IntroSkipper/Db/IntroSkipperDbContext.cs
+++ b/IntroSkipper/Db/IntroSkipperDbContext.cs
@@ -109,39 +109,73 @@ public class IntroSkipperDbContext : DbContext
///
public void ApplyMigrations()
{
- // If migrations table exists, just apply pending migrations normally
- if (Database.GetAppliedMigrations().Any() || !Database.CanConnect())
+ // If database doesn't exist or can't connect, create it with migrations
+ if (!Database.CanConnect())
+ {
+ Database.Migrate();
+ return;
+ }
+
+ // If migrations table exists, apply pending migrations normally
+ if (Database.GetAppliedMigrations().Any())
{
Database.Migrate();
return;
}
// For databases without migration history
- try
+ RebuildDatabase();
+ }
+
+ ///
+ /// Rebuilds the database while preserving valid segments and season information.
+ ///
+ public void RebuildDatabase()
+ {
+ // Backup existing data
+ List segments = [];
+ List seasonInfos = [];
+ using (var db = new IntroSkipperDbContext(_dbPath))
{
- // Backup existing data
- List segments;
- using (var db = new IntroSkipperDbContext(_dbPath))
+ try
{
segments = [.. db.DbSegment.AsEnumerable().Where(s => s.ToSegment().Valid)];
}
-
- // Delete old database
- Database.EnsureDeleted();
-
- // Create new database with proper migration history
- Database.Migrate();
-
- // Restore the data
- using (var db = new IntroSkipperDbContext(_dbPath))
+ catch (Exception ex)
{
- db.DbSegment.AddRange(segments);
- db.SaveChanges();
+ throw new InvalidOperationException("Failed to read DbSegment data", ex);
+ }
+
+ try
+ {
+ seasonInfos = [.. db.DbSeasonInfo];
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException("Failed to read DbSeasonInfo data", ex);
}
}
- catch (Exception ex)
+
+ // Delete old database
+ Database.EnsureDeleted();
+
+ // Create new database with proper migration history
+ Database.Migrate();
+
+ // Restore the data
+ using (var db = new IntroSkipperDbContext(_dbPath))
{
- throw new InvalidOperationException("Failed to apply migrations", ex);
+ if (segments.Count > 0)
+ {
+ db.DbSegment.AddRange(segments);
+ }
+
+ if (seasonInfos.Count > 0)
+ {
+ db.DbSeasonInfo.AddRange(seasonInfos);
+ }
+
+ db.SaveChanges();
}
}
}