Compare commits
3 Commits
10.10
...
regex-seas
Author | SHA1 | Date | |
---|---|---|---|
|
f0113691e8 | ||
|
983d1e346b | ||
|
700c025fef |
@ -33,14 +33,19 @@ public class ChapterAnalyzer(ILogger<ChapterAnalyzer> logger) : IMediaFileAnalyz
|
|||||||
AnalysisMode mode,
|
AnalysisMode mode,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var expression = mode switch
|
var expression = Plugin.Instance!.GetSeasonRegex(analysisQueue[0].SeasonId, mode);
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(expression))
|
||||||
{
|
{
|
||||||
AnalysisMode.Introduction => _config.ChapterAnalyzerIntroductionPattern,
|
expression = mode switch
|
||||||
AnalysisMode.Credits => _config.ChapterAnalyzerEndCreditsPattern,
|
{
|
||||||
AnalysisMode.Recap => _config.ChapterAnalyzerRecapPattern,
|
AnalysisMode.Introduction => _config.ChapterAnalyzerIntroductionPattern,
|
||||||
AnalysisMode.Preview => _config.ChapterAnalyzerPreviewPattern,
|
AnalysisMode.Credits => _config.ChapterAnalyzerEndCreditsPattern,
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(mode), $"Unexpected analysis mode: {mode}")
|
AnalysisMode.Recap => _config.ChapterAnalyzerRecapPattern,
|
||||||
};
|
AnalysisMode.Preview => _config.ChapterAnalyzerPreviewPattern,
|
||||||
|
_ => throw new ArgumentOutOfRangeException(nameof(mode), $"Unexpected analysis mode: {mode}")
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(expression))
|
if (string.IsNullOrWhiteSpace(expression))
|
||||||
{
|
{
|
||||||
|
@ -471,6 +471,12 @@
|
|||||||
<option value="None">None</option>
|
<option value="None">None</option>
|
||||||
</select>
|
</select>
|
||||||
</label>
|
</label>
|
||||||
|
<label for="regexRecap" style="margin-right: 1.5em; display: inline-block">
|
||||||
|
<span>Recap Chapter Regex</span>
|
||||||
|
<input type="text" id="regexRecap" class="emby-input" />
|
||||||
|
</label>
|
||||||
|
</label>
|
||||||
|
<br />
|
||||||
<label for="actionIntro" style="margin-right: 1.5em; display: inline-block">
|
<label for="actionIntro" style="margin-right: 1.5em; display: inline-block">
|
||||||
<span>Introduction analysis</span>
|
<span>Introduction analysis</span>
|
||||||
<select is="emby-select" id="actionIntro" class="emby-select-withcolor emby-select">
|
<select is="emby-select" id="actionIntro" class="emby-select-withcolor emby-select">
|
||||||
@ -480,6 +486,11 @@
|
|||||||
<option value="None">None</option>
|
<option value="None">None</option>
|
||||||
</select>
|
</select>
|
||||||
</label>
|
</label>
|
||||||
|
<label for="regexIntro" style="margin-right: 1.5em; display: inline-block">
|
||||||
|
<span>Introduction Chapter Regex</span>
|
||||||
|
<input type="text" id="regexIntro" class="emby-input" />
|
||||||
|
</label>
|
||||||
|
<br />
|
||||||
<label for="actionCredits" style="margin-right: 1.5em; display: inline-block">
|
<label for="actionCredits" style="margin-right: 1.5em; display: inline-block">
|
||||||
<span>Credits (Outro) analysis</span>
|
<span>Credits (Outro) analysis</span>
|
||||||
<select is="emby-select" id="actionCredits" class="emby-select-withcolor emby-select">
|
<select is="emby-select" id="actionCredits" class="emby-select-withcolor emby-select">
|
||||||
@ -490,6 +501,11 @@
|
|||||||
<option value="None">None</option>
|
<option value="None">None</option>
|
||||||
</select>
|
</select>
|
||||||
</label>
|
</label>
|
||||||
|
<label for="regexCredits" style="margin-right: 1.5em; display: inline-block">
|
||||||
|
<span>Credits (Outro) Chapter Regex</span>
|
||||||
|
<input type="text" id="regexCredits" class="emby-input" />
|
||||||
|
</label>
|
||||||
|
<br />
|
||||||
<label for="actionPreview" style="margin-right: 1.5em; display: inline-block">
|
<label for="actionPreview" style="margin-right: 1.5em; display: inline-block">
|
||||||
<span>Preview analysis</span>
|
<span>Preview analysis</span>
|
||||||
<select is="emby-select" id="actionPreview" class="emby-select-withcolor emby-select">
|
<select is="emby-select" id="actionPreview" class="emby-select-withcolor emby-select">
|
||||||
@ -498,6 +514,10 @@
|
|||||||
<option value="None">None</option>
|
<option value="None">None</option>
|
||||||
</select>
|
</select>
|
||||||
</label>
|
</label>
|
||||||
|
<label for="regexPreview" style="margin-right: 1.5em; display: inline-block">
|
||||||
|
<span>Preview Chapter Regex</span>
|
||||||
|
<input type="text" id="regexPreview" class="emby-input" />
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
@ -797,9 +817,13 @@
|
|||||||
// visualizer elements
|
// visualizer elements
|
||||||
var analyzerActionsSection = document.querySelector("div#analyzerActionsSection");
|
var analyzerActionsSection = document.querySelector("div#analyzerActionsSection");
|
||||||
var actionIntro = analyzerActionsSection.querySelector("select#actionIntro");
|
var actionIntro = analyzerActionsSection.querySelector("select#actionIntro");
|
||||||
|
var regexIntro = analyzerActionsSection.querySelector("input#regexIntro");
|
||||||
var actionCredits = analyzerActionsSection.querySelector("select#actionCredits");
|
var actionCredits = analyzerActionsSection.querySelector("select#actionCredits");
|
||||||
|
var regexCredits = analyzerActionsSection.querySelector("input#regexCredits");
|
||||||
var actionRecap = analyzerActionsSection.querySelector("select#actionRecap");
|
var actionRecap = analyzerActionsSection.querySelector("select#actionRecap");
|
||||||
|
var regexRecap = analyzerActionsSection.querySelector("input#regexRecap");
|
||||||
var actionPreview = analyzerActionsSection.querySelector("select#actionPreview");
|
var actionPreview = analyzerActionsSection.querySelector("select#actionPreview");
|
||||||
|
var regexPreview = analyzerActionsSection.querySelector("input#regexPreview");
|
||||||
var saveAnalyzerActionsButton = analyzerActionsSection.querySelector("button#saveAnalyzerActions");
|
var saveAnalyzerActionsButton = analyzerActionsSection.querySelector("button#saveAnalyzerActions");
|
||||||
var canvas = document.querySelector("canvas#troubleshooter");
|
var canvas = document.querySelector("canvas#troubleshooter");
|
||||||
var selectShow = document.querySelector("select#troubleshooterShow");
|
var selectShow = document.querySelector("select#troubleshooterShow");
|
||||||
@ -1082,6 +1106,11 @@
|
|||||||
actionCredits.value = analyzerActions.Credits || "Default";
|
actionCredits.value = analyzerActions.Credits || "Default";
|
||||||
actionRecap.value = analyzerActions.Recap || "Default";
|
actionRecap.value = analyzerActions.Recap || "Default";
|
||||||
actionPreview.value = analyzerActions.Preview || "Default";
|
actionPreview.value = analyzerActions.Preview || "Default";
|
||||||
|
const analyzerRegexs = await getJson("Intros/AnalyzerRegexs/" + encodeURI(selectSeason.value));
|
||||||
|
regexIntro.value = analyzerRegexs.Introduction || "";
|
||||||
|
regexCredits.value = analyzerRegexs.Credits || "";
|
||||||
|
regexRecap.value = analyzerRegexs.Recap || "";
|
||||||
|
regexPreview.value = analyzerRegexs.Preview || "";
|
||||||
analyzerActionsSection.style.display = "unset";
|
analyzerActionsSection.style.display = "unset";
|
||||||
|
|
||||||
// show the erase season button
|
// show the erase season button
|
||||||
@ -1539,7 +1568,7 @@
|
|||||||
saveAnalyzerActionsButton.addEventListener("click", () => {
|
saveAnalyzerActionsButton.addEventListener("click", () => {
|
||||||
Dashboard.showLoadingMsg();
|
Dashboard.showLoadingMsg();
|
||||||
|
|
||||||
var url = "Intros/AnalyzerActions/UpdateSeason";
|
var url1 = "Intros/AnalyzerActions/UpdateSeason";
|
||||||
const actions = {
|
const actions = {
|
||||||
id: selectSeason.value,
|
id: selectSeason.value,
|
||||||
analyzerActions: {
|
analyzerActions: {
|
||||||
@ -1550,7 +1579,20 @@
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
fetchWithAuth(url, "POST", JSON.stringify(actions));
|
var url2 = "Intros/AnalyzerRegexs/UpdateSeason";
|
||||||
|
|
||||||
|
const regexs = {
|
||||||
|
id: selectSeason.value,
|
||||||
|
regexs: {
|
||||||
|
Introduction: regexIntro.value,
|
||||||
|
Credits: regexCredits.value,
|
||||||
|
Recap: regexRecap.value,
|
||||||
|
Preview: regexPreview.value,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
fetchWithAuth(url1, "POST", JSON.stringify(actions));
|
||||||
|
fetchWithAuth(url2, "POST", JSON.stringify(regexs));
|
||||||
|
|
||||||
Dashboard.alert("Analyzer actions updated for " + selectSeason.value + " of " + selectShow.value);
|
Dashboard.alert("Analyzer actions updated for " + selectSeason.value + " of " + selectShow.value);
|
||||||
Dashboard.hideLoadingMsg();
|
Dashboard.hideLoadingMsg();
|
||||||
|
@ -105,6 +105,28 @@ public class VisualizationController(ILogger<VisualizationController> logger, Me
|
|||||||
return Ok(analyzerActions);
|
return Ok(analyzerActions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the analyzer actions for the provided season.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="seasonId">Season ID.</param>
|
||||||
|
/// <returns>List of episode titles.</returns>
|
||||||
|
[HttpGet("AnalyzerRegexs/{SeasonId}")]
|
||||||
|
public ActionResult<IReadOnlyDictionary<AnalysisMode, string>> GetSeasonRegexs([FromRoute] Guid seasonId)
|
||||||
|
{
|
||||||
|
if (!Plugin.Instance!.QueuedMediaItems.ContainsKey(seasonId))
|
||||||
|
{
|
||||||
|
return NotFound();
|
||||||
|
}
|
||||||
|
|
||||||
|
var seasonRegexs = new Dictionary<AnalysisMode, string>();
|
||||||
|
foreach (var mode in Enum.GetValues<AnalysisMode>())
|
||||||
|
{
|
||||||
|
seasonRegexs[mode] = Plugin.Instance!.GetSeasonRegex(seasonId, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(seasonRegexs);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the names and unique identifiers of all episodes in the provided season.
|
/// Returns the names and unique identifiers of all episodes in the provided season.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -227,6 +249,19 @@ public class VisualizationController(ILogger<VisualizationController> logger, Me
|
|||||||
return NoContent();
|
return NoContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates the analyzer regexs for the provided season.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request">Update analyzer regexs request.</param>
|
||||||
|
/// <returns>No content.</returns>
|
||||||
|
[HttpPost("AnalyzerRegexs/UpdateSeason")]
|
||||||
|
public async Task<ActionResult> UpdateAnalyzerRegexs([FromBody] UpdateSeasonRegexRequest request)
|
||||||
|
{
|
||||||
|
await Plugin.Instance!.SetSeasonRegexAsync(request.Id, request.SeasonRegexs).ConfigureAwait(false);
|
||||||
|
|
||||||
|
return NoContent();
|
||||||
|
}
|
||||||
|
|
||||||
private static string GetProductionYear(Guid seriesId)
|
private static string GetProductionYear(Guid seriesId)
|
||||||
{
|
{
|
||||||
return seriesId == Guid.Empty
|
return seriesId == Guid.Empty
|
||||||
|
21
IntroSkipper/Data/UpdateSeasonRegexRequest.cs
Normal file
21
IntroSkipper/Data/UpdateSeasonRegexRequest.cs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace IntroSkipper.Data
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// /// Update analyzer actions request.
|
||||||
|
/// </summary>
|
||||||
|
public class UpdateSeasonRegexRequest
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets season ID.
|
||||||
|
/// </summary>
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets analyzer actions.
|
||||||
|
/// </summary>
|
||||||
|
public IReadOnlyDictionary<AnalysisMode, string> SeasonRegexs { get; set; } = new Dictionary<AnalysisMode, string>();
|
||||||
|
}
|
||||||
|
}
|
@ -22,12 +22,14 @@ public class DbSeasonInfo
|
|||||||
/// <param name="mode">Analysis mode.</param>
|
/// <param name="mode">Analysis mode.</param>
|
||||||
/// <param name="action">Analyzer action.</param>
|
/// <param name="action">Analyzer action.</param>
|
||||||
/// <param name="episodeIds">Episode IDs.</param>
|
/// <param name="episodeIds">Episode IDs.</param>
|
||||||
public DbSeasonInfo(Guid seasonId, AnalysisMode mode, AnalyzerAction action, IEnumerable<Guid>? episodeIds = null)
|
/// <param name="regex">Regex.</param>
|
||||||
|
public DbSeasonInfo(Guid seasonId, AnalysisMode mode, AnalyzerAction action, IEnumerable<Guid>? episodeIds = null, string? regex = null)
|
||||||
{
|
{
|
||||||
SeasonId = seasonId;
|
SeasonId = seasonId;
|
||||||
Type = mode;
|
Type = mode;
|
||||||
Action = action;
|
Action = action;
|
||||||
EpisodeIds = episodeIds ?? [];
|
EpisodeIds = episodeIds ?? [];
|
||||||
|
Regex = regex ?? string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -56,4 +58,9 @@ public class DbSeasonInfo
|
|||||||
/// Gets the season number.
|
/// Gets the season number.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IEnumerable<Guid> EpisodeIds { get; private set; } = [];
|
public IEnumerable<Guid> EpisodeIds { get; private set; } = [];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the season number.
|
||||||
|
/// </summary>
|
||||||
|
public string Regex { get; private set; } = string.Empty;
|
||||||
}
|
}
|
||||||
|
@ -99,6 +99,9 @@ public class IntroSkipperDbContext : DbContext
|
|||||||
(c1, c2) => (c1 ?? new List<Guid>()).SequenceEqual(c2 ?? new List<Guid>()),
|
(c1, c2) => (c1 ?? new List<Guid>()).SequenceEqual(c2 ?? new List<Guid>()),
|
||||||
c => c.Aggregate(0, (a, v) => HashCode.Combine(a, v.GetHashCode())),
|
c => c.Aggregate(0, (a, v) => HashCode.Combine(a, v.GetHashCode())),
|
||||||
c => c.ToList()));
|
c => c.ToList()));
|
||||||
|
|
||||||
|
entity.Property(e => e.Regex)
|
||||||
|
.HasDefaultValue(string.Empty);
|
||||||
});
|
});
|
||||||
|
|
||||||
base.OnModelCreating(modelBuilder);
|
base.OnModelCreating(modelBuilder);
|
||||||
|
79
IntroSkipper/Migrations/20241125172633_SeasonRegex.Designer.cs
generated
Normal file
79
IntroSkipper/Migrations/20241125172633_SeasonRegex.Designer.cs
generated
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using IntroSkipper.Db;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace IntroSkipper.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(IntroSkipperDbContext))]
|
||||||
|
[Migration("20241125172633_SeasonRegex")]
|
||||||
|
partial class SeasonRegex
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder.HasAnnotation("ProductVersion", "8.0.11");
|
||||||
|
|
||||||
|
modelBuilder.Entity("IntroSkipper.Db.DbSeasonInfo", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("SeasonId")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<int>("Type")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<int>("Action")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("INTEGER")
|
||||||
|
.HasDefaultValue(0);
|
||||||
|
|
||||||
|
b.Property<string>("EpisodeIds")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("Regex")
|
||||||
|
.IsRequired()
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("TEXT")
|
||||||
|
.HasDefaultValue("");
|
||||||
|
|
||||||
|
b.HasKey("SeasonId", "Type");
|
||||||
|
|
||||||
|
b.HasIndex("SeasonId");
|
||||||
|
|
||||||
|
b.ToTable("DbSeasonInfo", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IntroSkipper.Db.DbSegment", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("ItemId")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<int>("Type")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<double>("End")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("REAL")
|
||||||
|
.HasDefaultValue(0.0);
|
||||||
|
|
||||||
|
b.Property<double>("Start")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("REAL")
|
||||||
|
.HasDefaultValue(0.0);
|
||||||
|
|
||||||
|
b.HasKey("ItemId", "Type");
|
||||||
|
|
||||||
|
b.HasIndex("ItemId");
|
||||||
|
|
||||||
|
b.ToTable("DbSegment", (string)null);
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
29
IntroSkipper/Migrations/20241125172633_SeasonRegex.cs
Normal file
29
IntroSkipper/Migrations/20241125172633_SeasonRegex.cs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace IntroSkipper.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class SeasonRegex : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "Regex",
|
||||||
|
table: "DbSeasonInfo",
|
||||||
|
type: "TEXT",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: string.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "Regex",
|
||||||
|
table: "DbSeasonInfo");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,6 +3,7 @@ using System;
|
|||||||
using IntroSkipper.Db;
|
using IntroSkipper.Db;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
|
||||||
#nullable disable
|
#nullable disable
|
||||||
|
|
||||||
@ -14,7 +15,7 @@ namespace IntroSkipper.Migrations
|
|||||||
protected override void BuildModel(ModelBuilder modelBuilder)
|
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||||
{
|
{
|
||||||
#pragma warning disable 612, 618
|
#pragma warning disable 612, 618
|
||||||
modelBuilder.HasAnnotation("ProductVersion", "8.0.10");
|
modelBuilder.HasAnnotation("ProductVersion", "8.0.11");
|
||||||
|
|
||||||
modelBuilder.Entity("IntroSkipper.Db.DbSeasonInfo", b =>
|
modelBuilder.Entity("IntroSkipper.Db.DbSeasonInfo", b =>
|
||||||
{
|
{
|
||||||
@ -33,6 +34,12 @@ namespace IntroSkipper.Migrations
|
|||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasColumnType("TEXT");
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("Regex")
|
||||||
|
.IsRequired()
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("TEXT")
|
||||||
|
.HasDefaultValue("");
|
||||||
|
|
||||||
b.HasKey("SeasonId", "Type");
|
b.HasKey("SeasonId", "Type");
|
||||||
|
|
||||||
b.HasIndex("SeasonId");
|
b.HasIndex("SeasonId");
|
||||||
|
@ -308,6 +308,35 @@ public class Plugin : BasePlugin<PluginConfiguration>, IHasWebPages
|
|||||||
.ToDictionary(s => s.Type, s => s.EpisodeIds);
|
.ToDictionary(s => s.Type, s => s.EpisodeIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal string GetSeasonRegex(Guid id, AnalysisMode mode)
|
||||||
|
{
|
||||||
|
using var db = new IntroSkipperDbContext(_dbPath);
|
||||||
|
return db.DbSeasonInfo.FirstOrDefault(s => s.SeasonId == id && s.Type == mode)?.Regex ?? string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal async Task SetSeasonRegexAsync(Guid id, IReadOnlyDictionary<AnalysisMode, string> regexs)
|
||||||
|
{
|
||||||
|
using var db = new IntroSkipperDbContext(_dbPath);
|
||||||
|
var existingEntries = await db.DbSeasonInfo
|
||||||
|
.Where(s => s.SeasonId == id)
|
||||||
|
.ToDictionaryAsync(s => s.Type)
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
|
foreach (var (mode, regex) in regexs)
|
||||||
|
{
|
||||||
|
if (existingEntries.TryGetValue(mode, out var existing))
|
||||||
|
{
|
||||||
|
db.Entry(existing).Property(s => s.Regex).CurrentValue = regex;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
db.DbSeasonInfo.Add(new DbSeasonInfo(id, mode, AnalyzerAction.Default, regex: regex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await db.SaveChangesAsync().ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
internal AnalyzerAction GetAnalyzerAction(Guid id, AnalysisMode mode)
|
internal AnalyzerAction GetAnalyzerAction(Guid id, AnalysisMode mode)
|
||||||
{
|
{
|
||||||
using var db = new IntroSkipperDbContext(_dbPath);
|
using var db = new IntroSkipperDbContext(_dbPath);
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
@ -15,7 +15,23 @@
|
|||||||
"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.11/intro-skipper-v1.10.10.11.zip",
|
||||||
"checksum": "30a71fd3996e0fbe9076371539b1ca56",
|
"checksum": "30a71fd3996e0fbe9076371539b1ca56",
|
||||||
"timestamp": "2024-11-25T17:07:33Z"
|
"timestamp": "2024-11-25T17:07:33Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"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.10)\n",
|
||||||
|
"targetAbi": "10.10.3.0",
|
||||||
|
"sourceUrl": "https://github.com/intro-skipper/intro-skipper/releases/download/10.10/v1.10.10.10/intro-skipper-v1.10.10.10.zip",
|
||||||
|
"checksum": "96ec29871e726ece01fbf7ccb24ae392",
|
||||||
|
"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