mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-07-09 03:04:20 -04:00
Adding a TrackIndex for tracks, support duplicated values & slugs for tracks that are not subtitles
This commit is contained in:
parent
aac1975a75
commit
2138f0909b
@ -103,19 +103,13 @@ namespace Kyoo.Models
|
||||
StreamType.Font => "font.",
|
||||
_ => ""
|
||||
};
|
||||
string slug = $"{Episode.Slug}.{type}{Language}{(TrackIndex != 0 ? TrackIndex : "")}";
|
||||
if (IsForced)
|
||||
slug += "-forced";
|
||||
switch (Codec)
|
||||
string index = TrackIndex != 0 ? $"-{TrackIndex}" : string.Empty;
|
||||
string codec = Codec switch
|
||||
{
|
||||
case "ass":
|
||||
slug += ".ass";
|
||||
break;
|
||||
case "subrip":
|
||||
slug += ".srt";
|
||||
break;
|
||||
}
|
||||
return slug;
|
||||
"subrip" => ".srt",
|
||||
{} x => $".{x}"
|
||||
};
|
||||
return $"{Episode.Slug}.{type}{Language}{index}{(IsForced ? "-forced" : "")}{codec}";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -188,7 +188,7 @@ namespace Kyoo.Controllers
|
||||
&& x.IsForced == y.IsForced
|
||||
&& x.Codec == y.Codec
|
||||
&& x.Type == y.Type);
|
||||
return _tracks.CreateIfNotExists(x, true);
|
||||
return _tracks.Create(x);
|
||||
}).ToListAsync();
|
||||
return resource;
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ using System.Linq.Expressions;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using Kyoo.Models;
|
||||
using Kyoo.Models.Exceptions;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Kyoo.Controllers
|
||||
@ -12,7 +13,7 @@ namespace Kyoo.Controllers
|
||||
{
|
||||
private bool _disposed;
|
||||
private readonly DatabaseContext _database;
|
||||
protected override Expression<Func<Track, object>> DefaultSort => x => x.ID;
|
||||
protected override Expression<Func<Track, object>> DefaultSort => x => x.TrackIndex;
|
||||
|
||||
|
||||
public TrackRepository(DatabaseContext database) : base(database)
|
||||
@ -44,7 +45,7 @@ namespace Kyoo.Controllers
|
||||
public Task<Track> Get(string slug, StreamType type)
|
||||
{
|
||||
Match match = Regex.Match(slug,
|
||||
@"(?<show>.*)-s(?<season>\d+)e(?<episode>\d+)\.(?<language>.{0,3})(?<forced>-forced)?(\..*)?");
|
||||
@"(?<show>.*)-s(?<season>\d+)e(?<episode>\d+)(\.(?<type>\w*))?\.(?<language>.{0,3})(?<forced>-forced)?(\..*)?");
|
||||
|
||||
if (!match.Success)
|
||||
{
|
||||
@ -61,6 +62,8 @@ namespace Kyoo.Controllers
|
||||
int episodeNumber = match.Groups["episode"].Success ? int.Parse(match.Groups["episode"].Value) : -1;
|
||||
string language = match.Groups["language"].Value;
|
||||
bool forced = match.Groups["forced"].Success;
|
||||
if (match.Groups["type"].Success)
|
||||
type = Enum.Parse<StreamType>(match.Groups["type"].Value, true);
|
||||
|
||||
if (type == StreamType.Unknown)
|
||||
{
|
||||
@ -94,7 +97,13 @@ namespace Kyoo.Controllers
|
||||
|
||||
await base.Create(obj);
|
||||
_database.Entry(obj).State = EntityState.Added;
|
||||
await _database.SaveChangesAsync($"Trying to insert a duplicated track (slug {obj.Slug} already exists).");
|
||||
await _database.SaveOrRetry(obj, (x, i) =>
|
||||
{
|
||||
if (i > 10)
|
||||
throw new DuplicatedItemException($"More than 10 same tracks exists {x.Slug}. Aborting...");
|
||||
x.TrackIndex++;
|
||||
return x;
|
||||
});
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
@ -185,6 +185,9 @@ namespace Kyoo
|
||||
modelBuilder.Entity<Episode>()
|
||||
.HasIndex(x => new {x.ShowID, x.SeasonNumber, x.EpisodeNumber, x.AbsoluteNumber})
|
||||
.IsUnique();
|
||||
modelBuilder.Entity<Track>()
|
||||
.HasIndex(x => new {x.EpisodeID, x.Type, x.Language, x.TrackIndex, x.IsForced})
|
||||
.IsUnique();
|
||||
}
|
||||
|
||||
public T GetTemporaryObject<T>(T model)
|
||||
@ -301,6 +304,33 @@ namespace Kyoo
|
||||
}
|
||||
}
|
||||
|
||||
public Task<T> SaveOrRetry<T>(T obj, Func<T, int, T> onFail, CancellationToken cancellationToken = new())
|
||||
{
|
||||
return SaveOrRetry(obj, onFail, 0, cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<T> SaveOrRetry<T>(T obj,
|
||||
Func<T, int, T> onFail,
|
||||
int recurse,
|
||||
CancellationToken cancellationToken = new())
|
||||
{
|
||||
try
|
||||
{
|
||||
await base.SaveChangesAsync(true, cancellationToken);
|
||||
return obj;
|
||||
}
|
||||
catch (DbUpdateException ex) when (IsDuplicateException(ex))
|
||||
{
|
||||
recurse++;
|
||||
return await SaveOrRetry(onFail(obj, recurse), onFail, recurse, cancellationToken);
|
||||
}
|
||||
catch (DbUpdateException)
|
||||
{
|
||||
DiscardChanges();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsDuplicateException(Exception ex)
|
||||
{
|
||||
return ex.InnerException is PostgresException {SqlState: PostgresErrorCodes.UniqueViolation};
|
||||
|
@ -10,7 +10,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
namespace Kyoo.Models.DatabaseMigrations.Internal
|
||||
{
|
||||
[DbContext(typeof(DatabaseContext))]
|
||||
[Migration("20210317180448_Initial")]
|
||||
[Migration("20210317220956_Initial")]
|
||||
partial class Initial
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
@ -499,7 +499,8 @@ namespace Kyoo.Models.DatabaseMigrations.Internal
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("EpisodeID");
|
||||
b.HasIndex("EpisodeID", "Type", "Language", "TrackIndex", "IsForced")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Tracks");
|
||||
});
|
@ -543,9 +543,10 @@ namespace Kyoo.Models.DatabaseMigrations.Internal
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Tracks_EpisodeID",
|
||||
name: "IX_Tracks_EpisodeID_Type_Language_TrackIndex_IsForced",
|
||||
table: "Tracks",
|
||||
column: "EpisodeID");
|
||||
columns: new[] { "EpisodeID", "Type", "Language", "TrackIndex", "IsForced" },
|
||||
unique: true);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
@ -497,7 +497,8 @@ namespace Kyoo.Models.DatabaseMigrations.Internal
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("EpisodeID");
|
||||
b.HasIndex("EpisodeID", "Type", "Language", "TrackIndex", "IsForced")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Tracks");
|
||||
});
|
||||
|
@ -196,7 +196,7 @@ namespace Kyoo
|
||||
ctx.Response.Headers.Remove("X-Powered-By");
|
||||
ctx.Response.Headers.Remove("Server");
|
||||
ctx.Response.Headers.Add("Feature-Policy", "autoplay 'self'; fullscreen");
|
||||
ctx.Response.Headers.Add("Content-Security-Policy", "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'");
|
||||
ctx.Response.Headers.Add("Content-Security-Policy", "default-src 'self'; script-src 'self' blob: 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'");
|
||||
ctx.Response.Headers.Add("X-Frame-Options", "SAMEORIGIN");
|
||||
ctx.Response.Headers.Add("Referrer-Policy", "no-referrer");
|
||||
ctx.Response.Headers.Add("Access-Control-Allow-Origin", "null");
|
||||
|
@ -35,7 +35,7 @@ namespace Kyoo.Api
|
||||
return BadRequest(new {error = ex.Message});
|
||||
}
|
||||
|
||||
if (subtitle == null)
|
||||
if (subtitle == null || subtitle.Type != StreamType.Subtitle)
|
||||
return NotFound();
|
||||
|
||||
if (subtitle.Codec == "subrip" && extension == "vtt")
|
||||
|
Loading…
x
Reference in New Issue
Block a user