Compare commits
1 Commits
10.10
...
rebuild-db
Author | SHA1 | Date | |
---|---|---|---|
|
35cbf57f41 |
6
.github/workflows/codeql.yml
vendored
6
.github/workflows/codeql.yml
vendored
@ -55,13 +55,13 @@ jobs:
|
|||||||
run: dotnet restore
|
run: dotnet restore
|
||||||
|
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@f09c1c0a94de965c15400f5634aa42fac8fb8f88 # v3.27.5
|
uses: github/codeql-action/init@ea9e4e37992a54ee68a9622e985e60c8e8f12d9f # v3.27.4
|
||||||
with:
|
with:
|
||||||
languages: ${{ matrix.language }}
|
languages: ${{ matrix.language }}
|
||||||
queries: +security-extended
|
queries: +security-extended
|
||||||
|
|
||||||
- name: Autobuild
|
- name: Autobuild
|
||||||
uses: github/codeql-action/autobuild@f09c1c0a94de965c15400f5634aa42fac8fb8f88 # v3.27.5
|
uses: github/codeql-action/autobuild@ea9e4e37992a54ee68a9622e985e60c8e8f12d9f # v3.27.4
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
- name: Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@f09c1c0a94de965c15400f5634aa42fac8fb8f88 # v3.27.5
|
uses: github/codeql-action/analyze@ea9e4e37992a54ee68a9622e985e60c8e8f12d9f # v3.27.4
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
|
||||||
<PackageReference Include="xunit" Version="2.9.2" />
|
<PackageReference Include="xunit" Version="2.9.2" />
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2">
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2">
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
@ -455,10 +455,8 @@
|
|||||||
<h3 style="margin: 0">Analyzer actions</h3>
|
<h3 style="margin: 0">Analyzer actions</h3>
|
||||||
<p style="margin: 0">
|
<p style="margin: 0">
|
||||||
Choose how segments should be analyzed for this season.<br />
|
Choose how segments should be analyzed for this season.<br />
|
||||||
<i>
|
|
||||||
Default uses all available detection methods (Chromaprint, Chapter, and BlackFrame for credits).<br />
|
Default uses all available detection methods (Chromaprint, Chapter, and BlackFrame for credits).<br />
|
||||||
Select specific methods to limit analysis, or None to skip detection entirely.
|
Select specific methods to limit analysis, or None to skip detection entirely.
|
||||||
</i>
|
|
||||||
</p>
|
</p>
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
@ -625,9 +623,10 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="timestampErrorDiv" style="display: none">
|
<div id="timestampErrorDiv" style="display: none">
|
||||||
<p>
|
<br />
|
||||||
<textarea id="timestampError" rows="2" cols="75" readonly></textarea>
|
<textarea id="timestampError" rows="2" cols="75" readonly></textarea>
|
||||||
</p>
|
<br />
|
||||||
|
<br />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="fingerprintVisualizer" style="display: none">
|
<div id="fingerprintVisualizer" style="display: none">
|
||||||
@ -666,11 +665,12 @@
|
|||||||
|
|
||||||
<span>Shift amount:</span>
|
<span>Shift amount:</span>
|
||||||
<input type="number" min="-3000" max="3000" value="0" id="offset" />
|
<input type="number" min="-3000" max="3000" value="0" id="offset" />
|
||||||
<p>
|
<br />
|
||||||
<span id="suggestedShifts">
|
<span id="suggestedShifts">
|
||||||
<span>Suggested shifts: </span>
|
<span>Suggested shifts: </span>
|
||||||
</span>
|
</span>
|
||||||
</p>
|
<br />
|
||||||
|
<br />
|
||||||
<canvas id="troubleshooter" style="display: none"></canvas>
|
<canvas id="troubleshooter" style="display: none"></canvas>
|
||||||
<span id="timestampContainer">
|
<span id="timestampContainer">
|
||||||
<span id="timestamps"></span>
|
<span id="timestamps"></span>
|
||||||
@ -679,27 +679,26 @@
|
|||||||
</span>
|
</span>
|
||||||
<br />
|
<br />
|
||||||
</div>
|
</div>
|
||||||
|
<br />
|
||||||
|
|
||||||
<div id="eraseSeasonContainer" style="display: none">
|
<div id="eraseSeasonContainer" style="display: none">
|
||||||
<p>
|
|
||||||
<button is="emby-button" id="btnEraseSeasonTimestamps" class="button-submit emby-button" type="button">Erase all timestamps for this season</button>
|
<button is="emby-button" id="btnEraseSeasonTimestamps" class="button-submit emby-button" type="button">Erase all timestamps for this season</button>
|
||||||
|
|
||||||
<input type="checkbox" id="eraseSeasonCacheCheckbox" style="margin-left: 10px" />
|
<input type="checkbox" id="eraseSeasonCacheCheckbox" style="margin-left: 10px" />
|
||||||
<label for="eraseSeasonCacheCheckbox" style="margin-left: 5px">Erase cached fingerprint files</label>
|
<label for="eraseSeasonCacheCheckbox" style="margin-left: 5px">Erase cached fingerprint files</label>
|
||||||
</p>
|
<br />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="eraseMovieContainer" style="display: none">
|
<div id="eraseMovieContainer" style="display: none">
|
||||||
<p>
|
|
||||||
<button is="emby-button" id="btnEraseMovieTimestamps" class="button-submit emby-button" type="button">Erase all timestamps for this movie</button>
|
<button is="emby-button" id="btnEraseMovieTimestamps" class="button-submit emby-button" type="button">Erase all timestamps for this movie</button>
|
||||||
|
|
||||||
<input type="checkbox" id="eraseMovieCacheCheckbox" style="margin-left: 10px" />
|
<input type="checkbox" id="eraseMovieCacheCheckbox" style="margin-left: 10px" />
|
||||||
<label for="eraseMovieCacheCheckbox" style="margin-left: 5px">Erase cached fingerprint files</label>
|
<label for="eraseMovieCacheCheckbox" style="margin-left: 5px">Erase cached fingerprint files</label>
|
||||||
</p>
|
<br />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style="display: flex; align-items: center;">
|
<div style="display: flex; align-items: center;">
|
||||||
<p>
|
<div>
|
||||||
<button is="emby-button" class="button-submit emby-button" id="btnEraseIntroTimestamps">Erase all introduction timestamps (globally)</button>
|
<button is="emby-button" class="button-submit emby-button" id="btnEraseIntroTimestamps">Erase all introduction timestamps (globally)</button>
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
@ -710,16 +709,21 @@
|
|||||||
<br />
|
<br />
|
||||||
|
|
||||||
<button is="emby-button" class="button-submit emby-button" id="btnErasePreviewTimestamps">Erase all preview timestamps (globally)</button>
|
<button is="emby-button" class="button-submit emby-button" id="btnErasePreviewTimestamps">Erase all preview timestamps (globally)</button>
|
||||||
</p>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<input type="checkbox" id="eraseModeCacheCheckbox" style="margin-left: 10px" />
|
<input type="checkbox" id="eraseModeCacheCheckbox" style="margin-left: 10px" />
|
||||||
<label for="eraseModeCacheCheckbox" style="margin-left: 5px">Erase global cached fingerprint files</label>
|
<label for="eraseModeCacheCheckbox" style="margin-left: 5px">Erase global cached fingerprint files</label>
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<button is="emby-button" class="button-submit emby-button" id="btnRebuildDatabase">Rebuild database</button>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
<details id="support">
|
<details id="support">
|
||||||
<summary>Intro Skipper Support Log</summary>
|
<summary>Support Bundle Info</summary>
|
||||||
|
|
||||||
<textarea id="supportBundle" rows="20" cols="75" readonly></textarea>
|
<textarea id="supportBundle" rows="20" cols="75" readonly></textarea>
|
||||||
</details>
|
</details>
|
||||||
@ -757,6 +761,7 @@
|
|||||||
var btnEraseRecapTimestamps = document.querySelector("button#btnEraseRecapTimestamps");
|
var btnEraseRecapTimestamps = document.querySelector("button#btnEraseRecapTimestamps");
|
||||||
var btnEraseCreditTimestamps = document.querySelector("button#btnEraseCreditTimestamps");
|
var btnEraseCreditTimestamps = document.querySelector("button#btnEraseCreditTimestamps");
|
||||||
var btnErasePreviewTimestamps = document.querySelector("button#btnErasePreviewTimestamps");
|
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).
|
// all plugin configuration fields that can be get or set with .value (i.e. strings or numbers).
|
||||||
var configurationFields = [
|
var configurationFields = [
|
||||||
@ -1503,6 +1508,9 @@
|
|||||||
eraseTimestamps("Preview");
|
eraseTimestamps("Preview");
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
});
|
});
|
||||||
|
btnRebuildDatabase.addEventListener("click", () => {
|
||||||
|
fetchWithAuth("Intros/RebuildDatabase", "POST", null);
|
||||||
|
});
|
||||||
btnSeasonEraseTimestamps.addEventListener("click", () => {
|
btnSeasonEraseTimestamps.addEventListener("click", () => {
|
||||||
Dashboard.confirm("Are you sure you want to erase all timestamps for this season?", "Confirm timestamp erasure", (result) => {
|
Dashboard.confirm("Are you sure you want to erase all timestamps for this season?", "Confirm timestamp erasure", (result) => {
|
||||||
if (!result) {
|
if (!result) {
|
||||||
|
@ -251,6 +251,20 @@ public class SkipIntroController(MediaSegmentUpdateManager mediaSegmentUpdateMan
|
|||||||
return NoContent();
|
return NoContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Rebuilds the database.
|
||||||
|
/// </summary>
|
||||||
|
/// <response code="204">Database rebuilt.</response>
|
||||||
|
/// <returns>No content.</returns>
|
||||||
|
[Authorize(Policy = Policies.RequiresElevation)]
|
||||||
|
[HttpPost("Intros/RebuildDatabase")]
|
||||||
|
public ActionResult RebuildDatabase()
|
||||||
|
{
|
||||||
|
using var db = new IntroSkipperDbContext(Plugin.Instance!.DbPath);
|
||||||
|
db.RebuildDatabase();
|
||||||
|
return NoContent();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the user interface configuration.
|
/// Gets the user interface configuration.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -109,22 +109,52 @@ public class IntroSkipperDbContext : DbContext
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void ApplyMigrations()
|
public void ApplyMigrations()
|
||||||
{
|
{
|
||||||
// If migrations table exists, just apply pending migrations normally
|
// If database doesn't exist or can't connect, create it with migrations
|
||||||
if (Database.GetAppliedMigrations().Any() || !Database.CanConnect())
|
if (!Database.CanConnect())
|
||||||
|
{
|
||||||
|
Database.Migrate();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If migrations table exists, apply pending migrations normally
|
||||||
|
if (Database.GetAppliedMigrations().Any())
|
||||||
{
|
{
|
||||||
Database.Migrate();
|
Database.Migrate();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// For databases without migration history
|
// For databases without migration history
|
||||||
try
|
RebuildDatabase();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Rebuilds the database while preserving valid segments and season information.
|
||||||
|
/// </summary>
|
||||||
|
public void RebuildDatabase()
|
||||||
{
|
{
|
||||||
// Backup existing data
|
// Backup existing data
|
||||||
List<DbSegment> segments;
|
List<DbSegment> segments = [];
|
||||||
|
List<DbSeasonInfo> seasonInfos = [];
|
||||||
using (var db = new IntroSkipperDbContext(_dbPath))
|
using (var db = new IntroSkipperDbContext(_dbPath))
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
segments = [.. db.DbSegment.AsEnumerable().Where(s => s.ToSegment().Valid)];
|
segments = [.. db.DbSegment.AsEnumerable().Where(s => s.ToSegment().Valid)];
|
||||||
}
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Delete old database
|
// Delete old database
|
||||||
Database.EnsureDeleted();
|
Database.EnsureDeleted();
|
||||||
@ -134,14 +164,18 @@ public class IntroSkipperDbContext : DbContext
|
|||||||
|
|
||||||
// Restore the data
|
// Restore the data
|
||||||
using (var db = new IntroSkipperDbContext(_dbPath))
|
using (var db = new IntroSkipperDbContext(_dbPath))
|
||||||
|
{
|
||||||
|
if (segments.Count > 0)
|
||||||
{
|
{
|
||||||
db.DbSegment.AddRange(segments);
|
db.DbSegment.AddRange(segments);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (seasonInfos.Count > 0)
|
||||||
|
{
|
||||||
|
db.DbSeasonInfo.AddRange(seasonInfos);
|
||||||
|
}
|
||||||
|
|
||||||
db.SaveChanges();
|
db.SaveChanges();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException("Failed to apply migrations", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<RootNamespace>IntroSkipper</RootNamespace>
|
<RootNamespace>IntroSkipper</RootNamespace>
|
||||||
<AssemblyVersion>1.10.10.11</AssemblyVersion>
|
<AssemblyVersion>1.10.10.10</AssemblyVersion>
|
||||||
<FileVersion>1.10.10.11</FileVersion>
|
<FileVersion>1.10.10.10</FileVersion>
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
@ -77,6 +77,15 @@ public class Plugin : BasePlugin<PluginConfiguration>, IHasWebPages
|
|||||||
Directory.CreateDirectory(FingerprintCachePath);
|
Directory.CreateDirectory(FingerprintCachePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
LegacyMigrations.MigrateAll(this, serverConfiguration, logger, applicationPaths);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
logger.LogError("Failed to perform migrations. Error: {Error}", ex);
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize database, restore timestamps if available.
|
// Initialize database, restore timestamps if available.
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -88,15 +97,6 @@ public class Plugin : BasePlugin<PluginConfiguration>, IHasWebPages
|
|||||||
logger.LogWarning("Error initializing database: {Exception}", ex);
|
logger.LogWarning("Error initializing database: {Exception}", ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
LegacyMigrations.MigrateAll(this, serverConfiguration, logger, applicationPaths);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
logger.LogError("Failed to perform migrations. Error: {Error}", ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
FFmpegWrapper.CheckFFmpegVersion();
|
FFmpegWrapper.CheckFFmpegVersion();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ https://manifest.intro-skipper.org/manifest.json
|
|||||||
- #### [Scheduled tasks fail instantly](https://github.com/intro-skipper/intro-skipper/wiki/Troubleshooting#scheduled-tasks-fail-instantly)
|
- #### [Scheduled tasks fail instantly](https://github.com/intro-skipper/intro-skipper/wiki/Troubleshooting#scheduled-tasks-fail-instantly)
|
||||||
- #### [Plugin settings not saved](https://github.com/intro-skipper/intro-skipper/wiki/Troubleshooting#plugin-settings-not-saved)
|
- #### [Plugin settings not saved](https://github.com/intro-skipper/intro-skipper/wiki/Troubleshooting#plugin-settings-not-saved)
|
||||||
- #### [Skip button is not visible](https://github.com/intro-skipper/intro-skipper/wiki/Troubleshooting#skip-button-is-not-visible)
|
- #### [Skip button is not visible](https://github.com/intro-skipper/intro-skipper/wiki/Troubleshooting#skip-button-is-not-visible)
|
||||||
- #### [Auto skip is not working](https://github.com/intro-skipper/intro-skipper/wiki/Troubleshooting#auto-skip-is-not-working)
|
- #### [Autoskip is not working](https://github.com/intro-skipper/intro-skipper/wiki/Troubleshooting#autoskip-is-not-working)
|
||||||
|
|
||||||
## [API Documentation](https://github.com/intro-skipper/intro-skipper/blob/master/docs/api.md)
|
## [API Documentation](https://github.com/intro-skipper/intro-skipper/blob/master/docs/api.md)
|
||||||
|
|
||||||
|
@ -9,12 +9,20 @@
|
|||||||
"imageUrl": "https://raw.githubusercontent.com/intro-skipper/intro-skipper/master/images/logo.png",
|
"imageUrl": "https://raw.githubusercontent.com/intro-skipper/intro-skipper/master/images/logo.png",
|
||||||
"versions": [
|
"versions": [
|
||||||
{
|
{
|
||||||
"version": "1.10.10.11",
|
"version": "1.10.10.10",
|
||||||
"changelog": "- See the full changelog at [GitHub](https://github.com/intro-skipper/intro-skipper/releases/tag/10.10/v1.10.10.11)\n",
|
"changelog": "- See the full changelog at [GitHub](https://github.com/intro-skipper/intro-skipper/releases/tag/10.10/v1.10.10.10)\n",
|
||||||
"targetAbi": "10.10.3.0",
|
"targetAbi": "10.10.3.0",
|
||||||
"sourceUrl": "https://github.com/intro-skipper/intro-skipper/releases/download/10.10/v1.10.10.11/intro-skipper-v1.10.10.11.zip",
|
"sourceUrl": "https://github.com/intro-skipper/intro-skipper/releases/download/10.10/v1.10.10.10/intro-skipper-v1.10.10.10.zip",
|
||||||
"checksum": "30a71fd3996e0fbe9076371539b1ca56",
|
"checksum": "96ec29871e726ece01fbf7ccb24ae392",
|
||||||
"timestamp": "2024-11-25T17:07:33Z"
|
"timestamp": "2024-11-24T18:33:26Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "1.10.10.9",
|
||||||
|
"changelog": "- See the full changelog at [GitHub](https://github.com/intro-skipper/intro-skipper/releases/tag/10.10/v1.10.10.9)\n",
|
||||||
|
"targetAbi": "10.10.2.0",
|
||||||
|
"sourceUrl": "https://github.com/intro-skipper/intro-skipper/releases/download/10.10/v1.10.10.9/intro-skipper-v1.10.10.9.zip",
|
||||||
|
"checksum": "a39436ee4476a4e74acbafbaf1008dfb",
|
||||||
|
"timestamp": "2024-11-17T21:14:18Z"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user