mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-07-08 02:34:16 -04:00
Finishing the repositories's rework
This commit is contained in:
parent
2ad4c89806
commit
81f555ca7e
@ -93,9 +93,10 @@ namespace Kyoo.Models
|
|||||||
{
|
{
|
||||||
if (Type != StreamType.Subtitle)
|
if (Type != StreamType.Subtitle)
|
||||||
return null;
|
return null;
|
||||||
string slug = $"/subtitle/{Episode.Slug}.{Language ?? ID.ToString()}";
|
|
||||||
if (IsForced)
|
string slug = string.IsNullOrEmpty(Language)
|
||||||
slug += "-forced";
|
? ID.ToString()
|
||||||
|
: $"{Episode.Slug}.{Language}{(IsForced ? "-forced" : "")}";
|
||||||
switch (Codec)
|
switch (Codec)
|
||||||
{
|
{
|
||||||
case "ass":
|
case "ass":
|
||||||
|
@ -22,7 +22,7 @@ namespace Kyoo.Controllers
|
|||||||
public override async Task<ICollection<Collection>> Search(string query)
|
public override async Task<ICollection<Collection>> Search(string query)
|
||||||
{
|
{
|
||||||
return await _database.Collections
|
return await _database.Collections
|
||||||
.Where(x => EF.Functions.Like(x.Name, $"%{query}%"))
|
.Where(x => EF.Functions.ILike(x.Name, $"%{query}%"))
|
||||||
.Take(20)
|
.Take(20)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ namespace Kyoo.Controllers
|
|||||||
|
|
||||||
public override Task<Episode> Get(string slug)
|
public override Task<Episode> Get(string slug)
|
||||||
{
|
{
|
||||||
Match match = Regex.Match(slug, @"(<show>.*)-s(<season>\d*)-e(<episode>\d*)");
|
Match match = Regex.Match(slug, @"(?<show>.*)-s(?<season>\d*)-e(?<episode>\d*)");
|
||||||
|
|
||||||
if (!match.Success)
|
if (!match.Success)
|
||||||
return _database.Episodes.FirstOrDefaultAsync(x => x.Show.Slug == slug);
|
return _database.Episodes.FirstOrDefaultAsync(x => x.Show.Slug == slug);
|
||||||
@ -57,7 +57,7 @@ namespace Kyoo.Controllers
|
|||||||
public override async Task<ICollection<Episode>> Search(string query)
|
public override async Task<ICollection<Episode>> Search(string query)
|
||||||
{
|
{
|
||||||
return await _database.Episodes
|
return await _database.Episodes
|
||||||
.Where(x => EF.Functions.Like(x.Title, $"%{query}%"))
|
.Where(x => EF.Functions.ILike(x.Title, $"%{query}%"))
|
||||||
.Take(20)
|
.Take(20)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
}
|
}
|
||||||
|
@ -21,10 +21,10 @@ namespace Kyoo.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public async Task<ICollection<Genre>> Search(string query)
|
public override async Task<ICollection<Genre>> Search(string query)
|
||||||
{
|
{
|
||||||
return await _database.Genres
|
return await _database.Genres
|
||||||
.Where(genre => EF.Functions.Like(genre.Name, $"%{query}%"))
|
.Where(genre => EF.Functions.ILike(genre.Name, $"%{query}%"))
|
||||||
.Take(20)
|
.Take(20)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
}
|
}
|
||||||
@ -57,7 +57,7 @@ namespace Kyoo.Controllers
|
|||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Delete(Genre obj)
|
public override async Task Delete(Genre obj)
|
||||||
{
|
{
|
||||||
if (obj == null)
|
if (obj == null)
|
||||||
throw new ArgumentNullException(nameof(obj));
|
throw new ArgumentNullException(nameof(obj));
|
||||||
|
@ -9,54 +9,41 @@ using Microsoft.EntityFrameworkCore;
|
|||||||
|
|
||||||
namespace Kyoo.Controllers
|
namespace Kyoo.Controllers
|
||||||
{
|
{
|
||||||
public class LibraryRepository : ILibraryRepository
|
public class LibraryRepository : LocalRepository<Library>, ILibraryRepository
|
||||||
{
|
{
|
||||||
private readonly DatabaseContext _database;
|
private readonly DatabaseContext _database;
|
||||||
private readonly IProviderRepository _providers;
|
private readonly IProviderRepository _providers;
|
||||||
|
protected override Expression<Func<Library, object>> DefaultSort => x => x.ID;
|
||||||
|
|
||||||
|
|
||||||
public LibraryRepository(DatabaseContext database, IProviderRepository providers)
|
public LibraryRepository(DatabaseContext database, IProviderRepository providers) : base(database)
|
||||||
{
|
{
|
||||||
_database = database;
|
_database = database;
|
||||||
_providers = providers;
|
_providers = providers;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
|
public override void Dispose()
|
||||||
{
|
{
|
||||||
_database.Dispose();
|
_database.Dispose();
|
||||||
|
_providers.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueTask DisposeAsync()
|
public override async ValueTask DisposeAsync()
|
||||||
{
|
{
|
||||||
return _database.DisposeAsync();
|
await _database.DisposeAsync();
|
||||||
|
await _providers.DisposeAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<Library> Get(int id)
|
public override async Task<ICollection<Library>> Search(string query)
|
||||||
{
|
|
||||||
return _database.Libraries.FirstOrDefaultAsync(x => x.ID == id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task<Library> Get(string slug)
|
|
||||||
{
|
|
||||||
return _database.Libraries.FirstOrDefaultAsync(x => x.Slug == slug);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<ICollection<Library>> Search(string query)
|
|
||||||
{
|
{
|
||||||
return await _database.Libraries
|
return await _database.Libraries
|
||||||
.Where(x => EF.Functions.Like(x.Name, $"%{query}%"))
|
.Where(x => EF.Functions.ILike(x.Name, $"%{query}%"))
|
||||||
.Take(20)
|
.Take(20)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<ICollection<Library>> GetAll(Expression<Func<Library, bool>> where = null,
|
public override async Task<Library> Create(Library obj)
|
||||||
Sort<Library> sort = default,
|
|
||||||
Pagination limit = default)
|
|
||||||
{
|
|
||||||
return await _database.Libraries.ToListAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<Library> Create(Library obj)
|
|
||||||
{
|
{
|
||||||
if (obj == null)
|
if (obj == null)
|
||||||
throw new ArgumentNullException(nameof(obj));
|
throw new ArgumentNullException(nameof(obj));
|
||||||
@ -74,7 +61,7 @@ namespace Kyoo.Controllers
|
|||||||
catch (DbUpdateException ex)
|
catch (DbUpdateException ex)
|
||||||
{
|
{
|
||||||
_database.DiscardChanges();
|
_database.DiscardChanges();
|
||||||
if (Helper.IsDuplicateException(ex))
|
if (IsDuplicateException(ex))
|
||||||
throw new DuplicatedItemException($"Trying to insert a duplicated library (slug {obj.Slug} already exists).");
|
throw new DuplicatedItemException($"Trying to insert a duplicated library (slug {obj.Slug} already exists).");
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
@ -82,65 +69,14 @@ namespace Kyoo.Controllers
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Library> CreateIfNotExists(Library obj)
|
protected override async Task Validate(Library obj)
|
||||||
{
|
|
||||||
if (obj == null)
|
|
||||||
throw new ArgumentNullException(nameof(obj));
|
|
||||||
|
|
||||||
Library old = await Get(obj.Slug);
|
|
||||||
if (old != null)
|
|
||||||
return old;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await Create(obj);
|
|
||||||
}
|
|
||||||
catch (DuplicatedItemException)
|
|
||||||
{
|
|
||||||
old = await Get(obj.Slug);
|
|
||||||
if (old == null)
|
|
||||||
throw new SystemException("Unknown database state.");
|
|
||||||
return old;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<Library> Edit(Library edited, bool resetOld)
|
|
||||||
{
|
|
||||||
if (edited == null)
|
|
||||||
throw new ArgumentNullException(nameof(edited));
|
|
||||||
|
|
||||||
Library old = await Get(edited.Name);
|
|
||||||
|
|
||||||
if (old == null)
|
|
||||||
throw new ItemNotFound($"No library found with the name {edited.Name}.");
|
|
||||||
|
|
||||||
if (resetOld)
|
|
||||||
Utility.Nullify(old);
|
|
||||||
Utility.Merge(old, edited);
|
|
||||||
await Validate(old);
|
|
||||||
await _database.SaveChangesAsync();
|
|
||||||
return old;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task Validate(Library obj)
|
|
||||||
{
|
{
|
||||||
if (obj.ProviderLinks != null)
|
if (obj.ProviderLinks != null)
|
||||||
foreach (ProviderLink link in obj.ProviderLinks)
|
foreach (ProviderLink link in obj.ProviderLinks)
|
||||||
link.Provider = await _providers.CreateIfNotExists(link.Provider);
|
link.Provider = await _providers.CreateIfNotExists(link.Provider);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Delete(int id)
|
public override async Task Delete(Library obj)
|
||||||
{
|
|
||||||
Library obj = await Get(id);
|
|
||||||
await Delete(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task Delete(string slug)
|
|
||||||
{
|
|
||||||
Library obj = await Get(slug);
|
|
||||||
await Delete(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task Delete(Library obj)
|
|
||||||
{
|
{
|
||||||
if (obj == null)
|
if (obj == null)
|
||||||
throw new ArgumentNullException(nameof(obj));
|
throw new ArgumentNullException(nameof(obj));
|
||||||
@ -154,23 +90,5 @@ namespace Kyoo.Controllers
|
|||||||
_database.Entry(entry).State = EntityState.Deleted;
|
_database.Entry(entry).State = EntityState.Deleted;
|
||||||
await _database.SaveChangesAsync();
|
await _database.SaveChangesAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task DeleteRange(IEnumerable<Library> objs)
|
|
||||||
{
|
|
||||||
foreach (Library obj in objs)
|
|
||||||
await Delete(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task DeleteRange(IEnumerable<int> ids)
|
|
||||||
{
|
|
||||||
foreach (int id in ids)
|
|
||||||
await Delete(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task DeleteRange(IEnumerable<string> slugs)
|
|
||||||
{
|
|
||||||
foreach (string slug in slugs)
|
|
||||||
await Delete(slug);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -9,53 +9,40 @@ using Microsoft.EntityFrameworkCore;
|
|||||||
|
|
||||||
namespace Kyoo.Controllers
|
namespace Kyoo.Controllers
|
||||||
{
|
{
|
||||||
public class PeopleRepository : IPeopleRepository
|
public class PeopleRepository : LocalRepository<People>, IPeopleRepository
|
||||||
{
|
{
|
||||||
private readonly DatabaseContext _database;
|
private readonly DatabaseContext _database;
|
||||||
private readonly IProviderRepository _providers;
|
private readonly IProviderRepository _providers;
|
||||||
|
protected override Expression<Func<People, object>> DefaultSort => x => x.Name;
|
||||||
|
|
||||||
public PeopleRepository(DatabaseContext database, IProviderRepository providers)
|
public PeopleRepository(DatabaseContext database, IProviderRepository providers) : base(database)
|
||||||
{
|
{
|
||||||
_database = database;
|
_database = database;
|
||||||
_providers = providers;
|
_providers = providers;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
|
public override void Dispose()
|
||||||
{
|
{
|
||||||
_database.Dispose();
|
_database.Dispose();
|
||||||
|
_providers.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueTask DisposeAsync()
|
public override async ValueTask DisposeAsync()
|
||||||
{
|
{
|
||||||
return _database.DisposeAsync();
|
await _database.DisposeAsync();
|
||||||
|
await _providers.DisposeAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<People> Get(int id)
|
public override async Task<ICollection<People>> Search(string query)
|
||||||
{
|
|
||||||
return _database.Peoples.FirstOrDefaultAsync(x => x.ID == id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task<People> Get(string slug)
|
|
||||||
{
|
|
||||||
return _database.Peoples.FirstOrDefaultAsync(x => x.Slug == slug);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<ICollection<People>> Search(string query)
|
|
||||||
{
|
{
|
||||||
return await _database.Peoples
|
return await _database.Peoples
|
||||||
.Where(people => EF.Functions.Like(people.Name, $"%{query}%"))
|
.Where(people => EF.Functions.ILike(people.Name, $"%{query}%"))
|
||||||
.Take(20)
|
.Take(20)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<ICollection<People>> GetAll(Expression<Func<People, bool>> where = null,
|
public override async Task<People> Create(People obj)
|
||||||
Sort<People> sort = default,
|
|
||||||
Pagination limit = default)
|
|
||||||
{
|
|
||||||
return await _database.Peoples.ToListAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<People> Create(People obj)
|
|
||||||
{
|
{
|
||||||
if (obj == null)
|
if (obj == null)
|
||||||
throw new ArgumentNullException(nameof(obj));
|
throw new ArgumentNullException(nameof(obj));
|
||||||
@ -73,7 +60,7 @@ namespace Kyoo.Controllers
|
|||||||
catch (DbUpdateException ex)
|
catch (DbUpdateException ex)
|
||||||
{
|
{
|
||||||
_database.DiscardChanges();
|
_database.DiscardChanges();
|
||||||
if (Helper.IsDuplicateException(ex))
|
if (IsDuplicateException(ex))
|
||||||
throw new DuplicatedItemException($"Trying to insert a duplicated people (slug {obj.Slug} already exists).");
|
throw new DuplicatedItemException($"Trying to insert a duplicated people (slug {obj.Slug} already exists).");
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
@ -81,65 +68,14 @@ namespace Kyoo.Controllers
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<People> CreateIfNotExists(People obj)
|
protected override async Task Validate(People obj)
|
||||||
{
|
|
||||||
if (obj == null)
|
|
||||||
throw new ArgumentNullException(nameof(obj));
|
|
||||||
|
|
||||||
People old = await Get(obj.Slug);
|
|
||||||
if (old != null)
|
|
||||||
return old;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await Create(obj);
|
|
||||||
}
|
|
||||||
catch (DuplicatedItemException)
|
|
||||||
{
|
|
||||||
old = await Get(obj.Slug);
|
|
||||||
if (old == null)
|
|
||||||
throw new SystemException("Unknown database state.");
|
|
||||||
return old;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<People> Edit(People edited, bool resetOld)
|
|
||||||
{
|
|
||||||
if (edited == null)
|
|
||||||
throw new ArgumentNullException(nameof(edited));
|
|
||||||
|
|
||||||
People old = await Get(edited.Slug);
|
|
||||||
|
|
||||||
if (old == null)
|
|
||||||
throw new ItemNotFound($"No people found with the slug {edited.Slug}.");
|
|
||||||
|
|
||||||
if (resetOld)
|
|
||||||
Utility.Nullify(old);
|
|
||||||
Utility.Merge(old, edited);
|
|
||||||
await Validate(old);
|
|
||||||
await _database.SaveChangesAsync();
|
|
||||||
return old;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task Validate(People obj)
|
|
||||||
{
|
{
|
||||||
if (obj.ExternalIDs != null)
|
if (obj.ExternalIDs != null)
|
||||||
foreach (MetadataID link in obj.ExternalIDs)
|
foreach (MetadataID link in obj.ExternalIDs)
|
||||||
link.Provider = await _providers.CreateIfNotExists(link.Provider);
|
link.Provider = await _providers.CreateIfNotExists(link.Provider);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Delete(int id)
|
public override async Task Delete(People obj)
|
||||||
{
|
|
||||||
People obj = await Get(id);
|
|
||||||
await Delete(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task Delete(string slug)
|
|
||||||
{
|
|
||||||
People obj = await Get(slug);
|
|
||||||
await Delete(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task Delete(People obj)
|
|
||||||
{
|
{
|
||||||
if (obj == null)
|
if (obj == null)
|
||||||
throw new ArgumentNullException(nameof(obj));
|
throw new ArgumentNullException(nameof(obj));
|
||||||
@ -153,23 +89,5 @@ namespace Kyoo.Controllers
|
|||||||
_database.Entry(link).State = EntityState.Deleted;
|
_database.Entry(link).State = EntityState.Deleted;
|
||||||
await _database.SaveChangesAsync();
|
await _database.SaveChangesAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task DeleteRange(IEnumerable<People> objs)
|
|
||||||
{
|
|
||||||
foreach (People obj in objs)
|
|
||||||
await Delete(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task DeleteRange(IEnumerable<int> ids)
|
|
||||||
{
|
|
||||||
foreach (int id in ids)
|
|
||||||
await Delete(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task DeleteRange(IEnumerable<string> slugs)
|
|
||||||
{
|
|
||||||
foreach (string slug in slugs)
|
|
||||||
await Delete(slug);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -9,52 +9,26 @@ using Microsoft.EntityFrameworkCore;
|
|||||||
|
|
||||||
namespace Kyoo.Controllers
|
namespace Kyoo.Controllers
|
||||||
{
|
{
|
||||||
public class ProviderRepository : IProviderRepository
|
public class ProviderRepository : LocalRepository<ProviderID>, IProviderRepository
|
||||||
{
|
{
|
||||||
private readonly DatabaseContext _database;
|
private readonly DatabaseContext _database;
|
||||||
|
protected override Expression<Func<ProviderID, object>> DefaultSort => x => x.Slug;
|
||||||
|
|
||||||
|
|
||||||
public ProviderRepository(DatabaseContext database)
|
public ProviderRepository(DatabaseContext database) : base(database)
|
||||||
{
|
{
|
||||||
_database = database;
|
_database = database;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public override async Task<ICollection<ProviderID>> Search(string query)
|
||||||
{
|
|
||||||
_database.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
public ValueTask DisposeAsync()
|
|
||||||
{
|
|
||||||
return _database.DisposeAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<ProviderID> Get(int id)
|
|
||||||
{
|
|
||||||
return await _database.Providers.FirstOrDefaultAsync(x => x.ID == id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<ProviderID> Get(string slug)
|
|
||||||
{
|
|
||||||
return await _database.Providers.FirstOrDefaultAsync(x => x.Name == slug);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<ICollection<ProviderID>> Search(string query)
|
|
||||||
{
|
{
|
||||||
return await _database.Providers
|
return await _database.Providers
|
||||||
.Where(x => EF.Functions.Like(x.Name, $"%{query}%"))
|
.Where(x => EF.Functions.ILike(x.Name, $"%{query}%"))
|
||||||
.Take(20)
|
.Take(20)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<ICollection<ProviderID>> GetAll(Expression<Func<ProviderID, bool>> where = null,
|
public override async Task<ProviderID> Create(ProviderID obj)
|
||||||
Sort<ProviderID> sort = default,
|
|
||||||
Pagination limit = default)
|
|
||||||
{
|
|
||||||
return await _database.Providers.ToListAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<ProviderID> Create(ProviderID obj)
|
|
||||||
{
|
{
|
||||||
if (obj == null)
|
if (obj == null)
|
||||||
throw new ArgumentNullException(nameof(obj));
|
throw new ArgumentNullException(nameof(obj));
|
||||||
@ -68,7 +42,7 @@ namespace Kyoo.Controllers
|
|||||||
catch (DbUpdateException ex)
|
catch (DbUpdateException ex)
|
||||||
{
|
{
|
||||||
_database.DiscardChanges();
|
_database.DiscardChanges();
|
||||||
if (Helper.IsDuplicateException(ex))
|
if (IsDuplicateException(ex))
|
||||||
throw new DuplicatedItemException($"Trying to insert a duplicated provider (name {obj.Name} already exists).");
|
throw new DuplicatedItemException($"Trying to insert a duplicated provider (name {obj.Name} already exists).");
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
@ -76,57 +50,12 @@ namespace Kyoo.Controllers
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<ProviderID> CreateIfNotExists(ProviderID obj)
|
protected override Task Validate(ProviderID ressource)
|
||||||
{
|
{
|
||||||
if (obj == null)
|
return Task.CompletedTask;
|
||||||
throw new ArgumentNullException(nameof(obj));
|
|
||||||
|
|
||||||
ProviderID old = await Get(obj.Name);
|
|
||||||
if (old != null)
|
|
||||||
return old;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await Create(obj);
|
|
||||||
}
|
|
||||||
catch (DuplicatedItemException)
|
|
||||||
{
|
|
||||||
old = await Get(obj.Name);
|
|
||||||
if (old == null)
|
|
||||||
throw new SystemException("Unknown database state.");
|
|
||||||
return old;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<ProviderID> Edit(ProviderID edited, bool resetOld)
|
public override async Task Delete(ProviderID obj)
|
||||||
{
|
|
||||||
if (edited == null)
|
|
||||||
throw new ArgumentNullException(nameof(edited));
|
|
||||||
|
|
||||||
ProviderID old = await Get(edited.Name);
|
|
||||||
|
|
||||||
if (old == null)
|
|
||||||
throw new ItemNotFound($"No provider found with the name {edited.Name}.");
|
|
||||||
|
|
||||||
if (resetOld)
|
|
||||||
Utility.Nullify(old);
|
|
||||||
Utility.Merge(old, edited);
|
|
||||||
await _database.SaveChangesAsync();
|
|
||||||
return old;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task Delete(int id)
|
|
||||||
{
|
|
||||||
ProviderID obj = await Get(id);
|
|
||||||
await Delete(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task Delete(string slug)
|
|
||||||
{
|
|
||||||
ProviderID obj = await Get(slug);
|
|
||||||
await Delete(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task Delete(ProviderID obj)
|
|
||||||
{
|
{
|
||||||
if (obj == null)
|
if (obj == null)
|
||||||
throw new ArgumentNullException(nameof(obj));
|
throw new ArgumentNullException(nameof(obj));
|
||||||
@ -135,23 +64,5 @@ namespace Kyoo.Controllers
|
|||||||
// TODO handle ExternalID deletion when they refer to this providerID.
|
// TODO handle ExternalID deletion when they refer to this providerID.
|
||||||
await _database.SaveChangesAsync();
|
await _database.SaveChangesAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task DeleteRange(IEnumerable<ProviderID> objs)
|
|
||||||
{
|
|
||||||
foreach (ProviderID obj in objs)
|
|
||||||
await Delete(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task DeleteRange(IEnumerable<int> ids)
|
|
||||||
{
|
|
||||||
foreach (int id in ids)
|
|
||||||
await Delete(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task DeleteRange(IEnumerable<string> slugs)
|
|
||||||
{
|
|
||||||
foreach (string slug in slugs)
|
|
||||||
await Delete(slug);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -2,6 +2,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Kyoo.Models;
|
using Kyoo.Models;
|
||||||
using Kyoo.Models.Exceptions;
|
using Kyoo.Models.Exceptions;
|
||||||
@ -9,44 +10,44 @@ using Microsoft.EntityFrameworkCore;
|
|||||||
|
|
||||||
namespace Kyoo.Controllers
|
namespace Kyoo.Controllers
|
||||||
{
|
{
|
||||||
public class SeasonRepository : ISeasonRepository
|
public class SeasonRepository : LocalRepository<Season>, ISeasonRepository
|
||||||
{
|
{
|
||||||
private readonly DatabaseContext _database;
|
private readonly DatabaseContext _database;
|
||||||
private readonly IProviderRepository _providers;
|
private readonly IProviderRepository _providers;
|
||||||
private readonly IEpisodeRepository _episodes;
|
private readonly IEpisodeRepository _episodes;
|
||||||
|
protected override Expression<Func<Season, object>> DefaultSort => x => x.SeasonNumber;
|
||||||
|
|
||||||
|
|
||||||
public SeasonRepository(DatabaseContext database, IProviderRepository providers, IEpisodeRepository episodes)
|
public SeasonRepository(DatabaseContext database, IProviderRepository providers, IEpisodeRepository episodes)
|
||||||
|
: base(database)
|
||||||
{
|
{
|
||||||
_database = database;
|
_database = database;
|
||||||
_providers = providers;
|
_providers = providers;
|
||||||
_episodes = episodes;
|
_episodes = episodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
|
public override void Dispose()
|
||||||
{
|
{
|
||||||
_database.Dispose();
|
_database.Dispose();
|
||||||
|
_providers.Dispose();
|
||||||
|
_episodes.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueTask DisposeAsync()
|
public override async ValueTask DisposeAsync()
|
||||||
{
|
{
|
||||||
return _database.DisposeAsync();
|
await _database.DisposeAsync();
|
||||||
|
await _providers.DisposeAsync();
|
||||||
|
await _episodes.DisposeAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<Season> Get(int id)
|
public override Task<Season> Get(string slug)
|
||||||
{
|
{
|
||||||
return _database.Seasons.FirstOrDefaultAsync(x => x.ID == id);
|
Match match = Regex.Match(slug, @"(?<show>.*)-s(?<season>\d*)");
|
||||||
}
|
|
||||||
|
|
||||||
public Task<Season> Get(string slug)
|
if (!match.Success)
|
||||||
{
|
throw new ArgumentException("Invalid season slug. Format: {showSlug}-s{seasonNumber}");
|
||||||
int index = slug.IndexOf("-s", StringComparison.Ordinal);
|
return Get(match.Groups["show"].Value, int.Parse(match.Groups["season"].Value));
|
||||||
if (index == -1)
|
|
||||||
throw new InvalidOperationException("Invalid season slug. Format: {showSlug}-s{seasonNumber}");
|
|
||||||
string showSlug = slug.Substring(0, index);
|
|
||||||
if (!int.TryParse(slug.Substring(index + 2), out int seasonNumber))
|
|
||||||
throw new InvalidOperationException("Invalid season slug. Format: {showSlug}-s{seasonNumber}");
|
|
||||||
return Get(showSlug, seasonNumber);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<Season> Get(string showSlug, int seasonNumber)
|
public Task<Season> Get(string showSlug, int seasonNumber)
|
||||||
@ -55,22 +56,15 @@ namespace Kyoo.Controllers
|
|||||||
&& x.SeasonNumber == seasonNumber);
|
&& x.SeasonNumber == seasonNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<ICollection<Season>> Search(string query)
|
public override async Task<ICollection<Season>> Search(string query)
|
||||||
{
|
{
|
||||||
return await _database.Seasons
|
return await _database.Seasons
|
||||||
.Where(x => EF.Functions.Like(x.Title, $"%{query}%"))
|
.Where(x => EF.Functions.ILike(x.Title, $"%{query}%"))
|
||||||
.Take(20)
|
.Take(20)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<ICollection<Season>> GetAll(Expression<Func<Season, bool>> where = null,
|
public override async Task<Season> Create(Season obj)
|
||||||
Sort<Season> sort = default,
|
|
||||||
Pagination limit = default)
|
|
||||||
{
|
|
||||||
return await _database.Seasons.ToListAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<Season> Create(Season obj)
|
|
||||||
{
|
{
|
||||||
if (obj == null)
|
if (obj == null)
|
||||||
throw new ArgumentNullException(nameof(obj));
|
throw new ArgumentNullException(nameof(obj));
|
||||||
@ -88,7 +82,7 @@ namespace Kyoo.Controllers
|
|||||||
catch (DbUpdateException ex)
|
catch (DbUpdateException ex)
|
||||||
{
|
{
|
||||||
_database.DiscardChanges();
|
_database.DiscardChanges();
|
||||||
if (Helper.IsDuplicateException(ex))
|
if (IsDuplicateException(ex))
|
||||||
throw new DuplicatedItemException($"Trying to insert a duplicated season (slug {obj.Slug} already exists).");
|
throw new DuplicatedItemException($"Trying to insert a duplicated season (slug {obj.Slug} already exists).");
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
@ -96,47 +90,7 @@ namespace Kyoo.Controllers
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Season> CreateIfNotExists(Season obj)
|
protected override async Task Validate(Season obj)
|
||||||
{
|
|
||||||
if (obj == null)
|
|
||||||
throw new ArgumentNullException(nameof(obj));
|
|
||||||
|
|
||||||
Season old = await Get(obj.Slug);
|
|
||||||
if (old != null)
|
|
||||||
return old;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await Create(obj);
|
|
||||||
}
|
|
||||||
catch (DuplicatedItemException)
|
|
||||||
{
|
|
||||||
old = await Get(obj.Slug);
|
|
||||||
if (old == null)
|
|
||||||
throw new SystemException("Unknown database state.");
|
|
||||||
return old;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<Season> Edit(Season edited, bool resetOld)
|
|
||||||
{
|
|
||||||
if (edited == null)
|
|
||||||
throw new ArgumentNullException(nameof(edited));
|
|
||||||
|
|
||||||
Season old = await Get(edited.Slug);
|
|
||||||
|
|
||||||
if (old == null)
|
|
||||||
throw new ItemNotFound($"No season found with the slug {edited.Slug}.");
|
|
||||||
|
|
||||||
if (resetOld)
|
|
||||||
Utility.Nullify(old);
|
|
||||||
Utility.Merge(old, edited);
|
|
||||||
|
|
||||||
await Validate(old);
|
|
||||||
await _database.SaveChangesAsync();
|
|
||||||
return old;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task Validate(Season obj)
|
|
||||||
{
|
{
|
||||||
if (obj.ShowID <= 0)
|
if (obj.ShowID <= 0)
|
||||||
throw new InvalidOperationException($"Can't store a season not related to any show (showID: {obj.ShowID}).");
|
throw new InvalidOperationException($"Can't store a season not related to any show (showID: {obj.ShowID}).");
|
||||||
@ -158,25 +112,13 @@ namespace Kyoo.Controllers
|
|||||||
return await _database.Seasons.Where(x => x.Show.Slug == showSlug).ToListAsync();
|
return await _database.Seasons.Where(x => x.Show.Slug == showSlug).ToListAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Delete(int id)
|
|
||||||
{
|
|
||||||
Season obj = await Get(id);
|
|
||||||
await Delete(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task Delete(string slug)
|
|
||||||
{
|
|
||||||
Season obj = await Get(slug);
|
|
||||||
await Delete(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task Delete(string showSlug, int seasonNumber)
|
public async Task Delete(string showSlug, int seasonNumber)
|
||||||
{
|
{
|
||||||
Season obj = await Get(showSlug, seasonNumber);
|
Season obj = await Get(showSlug, seasonNumber);
|
||||||
await Delete(obj);
|
await Delete(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Delete(Season obj)
|
public override async Task Delete(Season obj)
|
||||||
{
|
{
|
||||||
if (obj == null)
|
if (obj == null)
|
||||||
throw new ArgumentNullException(nameof(obj));
|
throw new ArgumentNullException(nameof(obj));
|
||||||
@ -192,23 +134,5 @@ namespace Kyoo.Controllers
|
|||||||
if (obj.Episodes != null)
|
if (obj.Episodes != null)
|
||||||
await _episodes.DeleteRange(obj.Episodes);
|
await _episodes.DeleteRange(obj.Episodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task DeleteRange(IEnumerable<Season> objs)
|
|
||||||
{
|
|
||||||
foreach (Season obj in objs)
|
|
||||||
await Delete(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task DeleteRange(IEnumerable<int> ids)
|
|
||||||
{
|
|
||||||
foreach (int id in ids)
|
|
||||||
await Delete(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task DeleteRange(IEnumerable<string> slugs)
|
|
||||||
{
|
|
||||||
foreach (string slug in slugs)
|
|
||||||
await Delete(slug);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -3,14 +3,13 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Kyoo.CommonApi;
|
|
||||||
using Kyoo.Models;
|
using Kyoo.Models;
|
||||||
using Kyoo.Models.Exceptions;
|
using Kyoo.Models.Exceptions;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
namespace Kyoo.Controllers
|
namespace Kyoo.Controllers
|
||||||
{
|
{
|
||||||
public class ShowRepository : IShowRepository
|
public class ShowRepository : LocalRepository<Show>, IShowRepository
|
||||||
{
|
{
|
||||||
private readonly DatabaseContext _database;
|
private readonly DatabaseContext _database;
|
||||||
private readonly IStudioRepository _studios;
|
private readonly IStudioRepository _studios;
|
||||||
@ -19,6 +18,7 @@ namespace Kyoo.Controllers
|
|||||||
private readonly IProviderRepository _providers;
|
private readonly IProviderRepository _providers;
|
||||||
private readonly ISeasonRepository _seasons;
|
private readonly ISeasonRepository _seasons;
|
||||||
private readonly IEpisodeRepository _episodes;
|
private readonly IEpisodeRepository _episodes;
|
||||||
|
protected override Expression<Func<Show, object>> DefaultSort => x => x.Title;
|
||||||
|
|
||||||
public ShowRepository(DatabaseContext database,
|
public ShowRepository(DatabaseContext database,
|
||||||
IStudioRepository studios,
|
IStudioRepository studios,
|
||||||
@ -27,6 +27,7 @@ namespace Kyoo.Controllers
|
|||||||
IProviderRepository providers,
|
IProviderRepository providers,
|
||||||
ISeasonRepository seasons,
|
ISeasonRepository seasons,
|
||||||
IEpisodeRepository episodes)
|
IEpisodeRepository episodes)
|
||||||
|
: base(database)
|
||||||
{
|
{
|
||||||
_database = database;
|
_database = database;
|
||||||
_studios = studios;
|
_studios = studios;
|
||||||
@ -37,69 +38,38 @@ namespace Kyoo.Controllers
|
|||||||
_episodes = episodes;
|
_episodes = episodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public override void Dispose()
|
||||||
{
|
{
|
||||||
_database.Dispose();
|
_database.Dispose();
|
||||||
_studios.Dispose();
|
_studios.Dispose();
|
||||||
|
_people.Dispose();
|
||||||
|
_genres.Dispose();
|
||||||
|
_providers.Dispose();
|
||||||
|
_seasons.Dispose();
|
||||||
|
_episodes.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async ValueTask DisposeAsync()
|
public override async ValueTask DisposeAsync()
|
||||||
{
|
{
|
||||||
await Task.WhenAll(_database.DisposeAsync().AsTask(), _studios.DisposeAsync().AsTask());
|
await _database.DisposeAsync();
|
||||||
|
await _studios.DisposeAsync();
|
||||||
|
await _people.DisposeAsync();
|
||||||
|
await _genres.DisposeAsync();
|
||||||
|
await _providers.DisposeAsync();
|
||||||
|
await _seasons.DisposeAsync();
|
||||||
|
await _episodes.DisposeAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<Show> Get(int id)
|
public override async Task<ICollection<Show>> Search(string query)
|
||||||
{
|
|
||||||
return _database.Shows.FirstOrDefaultAsync(x => x.ID == id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task<Show> Get(string slug)
|
|
||||||
{
|
|
||||||
return _database.Shows.FirstOrDefaultAsync(x => x.Slug == slug);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task<Show> GetByPath(string path)
|
|
||||||
{
|
|
||||||
return _database.Shows.FirstOrDefaultAsync(x => x.Path == path);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<ICollection<Show>> Search(string query)
|
|
||||||
{
|
{
|
||||||
return await _database.Shows
|
return await _database.Shows
|
||||||
.FromSqlInterpolated($@"SELECT * FROM Shows WHERE 'Shows.Title' LIKE {$"%{query}%"}
|
.Where(x => EF.Functions.ILike(x.Title, $"%{query}%")
|
||||||
OR 'Shows.Aliases' LIKE {$"%{query}%"}")
|
/*|| EF.Functions.ILike(x.Aliases, $"%{query}%")*/)
|
||||||
.Take(20)
|
.Take(20)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<ICollection<Show>> GetAll(Expression<Func<Show, bool>> where = null,
|
public override async Task<Show> Create(Show obj)
|
||||||
Sort<Show> sort = default,
|
|
||||||
Pagination limit = default)
|
|
||||||
{
|
|
||||||
IQueryable<Show> query = _database.Shows;
|
|
||||||
|
|
||||||
if (where != null)
|
|
||||||
query = query.Where(where);
|
|
||||||
|
|
||||||
Expression<Func<Show, object>> sortKey = sort.Key ?? (x => x.Title);
|
|
||||||
query = sort.Descendant ? query.OrderByDescending(sortKey) : query.OrderBy(sortKey);
|
|
||||||
|
|
||||||
if (limit.AfterID != 0)
|
|
||||||
{
|
|
||||||
Show after = await Get(limit.AfterID);
|
|
||||||
object afterObj = sortKey.Compile()(after);
|
|
||||||
query = query.Where(Expression.Lambda<Func<Show, bool>>(
|
|
||||||
ApiHelper.StringCompatibleExpression(Expression.GreaterThan, sortKey.Body, Expression.Constant(afterObj)),
|
|
||||||
(ParameterExpression)((MemberExpression)sortKey.Body).Expression
|
|
||||||
));
|
|
||||||
}
|
|
||||||
if (limit.Count > 0)
|
|
||||||
query = query.Take(limit.Count);
|
|
||||||
|
|
||||||
return await query.ToListAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<Show> Create(Show obj)
|
|
||||||
{
|
{
|
||||||
if (obj == null)
|
if (obj == null)
|
||||||
throw new ArgumentNullException(nameof(obj));
|
throw new ArgumentNullException(nameof(obj));
|
||||||
@ -123,7 +93,7 @@ namespace Kyoo.Controllers
|
|||||||
catch (DbUpdateException ex)
|
catch (DbUpdateException ex)
|
||||||
{
|
{
|
||||||
_database.DiscardChanges();
|
_database.DiscardChanges();
|
||||||
if (Helper.IsDuplicateException(ex))
|
if (IsDuplicateException(ex))
|
||||||
throw new DuplicatedItemException($"Trying to insert a duplicated show (slug {obj.Slug} already exists).");
|
throw new DuplicatedItemException($"Trying to insert a duplicated show (slug {obj.Slug} already exists).");
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
@ -131,46 +101,7 @@ namespace Kyoo.Controllers
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Show> CreateIfNotExists(Show obj)
|
protected override async Task Validate(Show obj)
|
||||||
{
|
|
||||||
if (obj == null)
|
|
||||||
throw new ArgumentNullException(nameof(obj));
|
|
||||||
|
|
||||||
Show old = await Get(obj.Slug);
|
|
||||||
if (old != null)
|
|
||||||
return old;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await Create(obj);
|
|
||||||
}
|
|
||||||
catch (DuplicatedItemException)
|
|
||||||
{
|
|
||||||
old = await Get(obj.Slug);
|
|
||||||
if (old == null)
|
|
||||||
throw new SystemException("Unknown database state.");
|
|
||||||
return old;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<Show> Edit(Show edited, bool resetOld)
|
|
||||||
{
|
|
||||||
if (edited == null)
|
|
||||||
throw new ArgumentNullException(nameof(edited));
|
|
||||||
|
|
||||||
Show old = await Get(edited.Slug);
|
|
||||||
|
|
||||||
if (old == null)
|
|
||||||
throw new ItemNotFound($"No show found with the slug {edited.Slug}.");
|
|
||||||
|
|
||||||
if (resetOld)
|
|
||||||
Utility.Nullify(old);
|
|
||||||
Utility.Merge(old, edited);
|
|
||||||
await Validate(old);
|
|
||||||
await _database.SaveChangesAsync();
|
|
||||||
return old;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task Validate(Show obj)
|
|
||||||
{
|
{
|
||||||
if (obj.Studio != null)
|
if (obj.Studio != null)
|
||||||
obj.Studio = await _studios.CreateIfNotExists(obj.Studio);
|
obj.Studio = await _studios.CreateIfNotExists(obj.Studio);
|
||||||
@ -211,19 +142,7 @@ namespace Kyoo.Controllers
|
|||||||
await _database.SaveChangesAsync();
|
await _database.SaveChangesAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Delete(int id)
|
public override async Task Delete(Show obj)
|
||||||
{
|
|
||||||
Show obj = await Get(id);
|
|
||||||
await Delete(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task Delete(string slug)
|
|
||||||
{
|
|
||||||
Show obj = await Get(slug);
|
|
||||||
await Delete(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task Delete(Show obj)
|
|
||||||
{
|
{
|
||||||
if (obj == null)
|
if (obj == null)
|
||||||
throw new ArgumentNullException(nameof(obj));
|
throw new ArgumentNullException(nameof(obj));
|
||||||
@ -258,23 +177,5 @@ namespace Kyoo.Controllers
|
|||||||
if (obj.Episodes != null)
|
if (obj.Episodes != null)
|
||||||
await _episodes.DeleteRange(obj.Episodes);
|
await _episodes.DeleteRange(obj.Episodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task DeleteRange(IEnumerable<Show> objs)
|
|
||||||
{
|
|
||||||
foreach (Show obj in objs)
|
|
||||||
await Delete(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task DeleteRange(IEnumerable<int> ids)
|
|
||||||
{
|
|
||||||
foreach (int id in ids)
|
|
||||||
await Delete(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task DeleteRange(IEnumerable<string> slugs)
|
|
||||||
{
|
|
||||||
foreach (string slug in slugs)
|
|
||||||
await Delete(slug);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -9,52 +9,26 @@ using Microsoft.EntityFrameworkCore;
|
|||||||
|
|
||||||
namespace Kyoo.Controllers
|
namespace Kyoo.Controllers
|
||||||
{
|
{
|
||||||
public class StudioRepository : IStudioRepository
|
public class StudioRepository : LocalRepository<Studio>, IStudioRepository
|
||||||
{
|
{
|
||||||
private readonly DatabaseContext _database;
|
private readonly DatabaseContext _database;
|
||||||
|
protected override Expression<Func<Studio, object>> DefaultSort => x => x.Name;
|
||||||
|
|
||||||
|
|
||||||
public StudioRepository(DatabaseContext database)
|
public StudioRepository(DatabaseContext database) : base(database)
|
||||||
{
|
{
|
||||||
_database = database;
|
_database = database;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public override async Task<ICollection<Studio>> Search(string query)
|
||||||
{
|
|
||||||
_database.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
public ValueTask DisposeAsync()
|
|
||||||
{
|
|
||||||
return _database.DisposeAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<Studio> Get(int id)
|
|
||||||
{
|
|
||||||
return await _database.Studios.FirstOrDefaultAsync(x => x.ID == id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<Studio> Get(string slug)
|
|
||||||
{
|
|
||||||
return await _database.Studios.FirstOrDefaultAsync(x => x.Slug == slug);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<ICollection<Studio>> Search(string query)
|
|
||||||
{
|
{
|
||||||
return await _database.Studios
|
return await _database.Studios
|
||||||
.Where(x => EF.Functions.Like(x.Name, $"%{query}%"))
|
.Where(x => EF.Functions.ILike(x.Name, $"%{query}%"))
|
||||||
.Take(20)
|
.Take(20)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<ICollection<Studio>> GetAll(Expression<Func<Studio, bool>> where = null,
|
public override async Task<Studio> Create(Studio obj)
|
||||||
Sort<Studio> sort = default,
|
|
||||||
Pagination limit = default)
|
|
||||||
{
|
|
||||||
return await _database.Studios.ToListAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<Studio> Create(Studio obj)
|
|
||||||
{
|
{
|
||||||
if (obj == null)
|
if (obj == null)
|
||||||
throw new ArgumentNullException(nameof(obj));
|
throw new ArgumentNullException(nameof(obj));
|
||||||
@ -68,64 +42,19 @@ namespace Kyoo.Controllers
|
|||||||
catch (DbUpdateException ex)
|
catch (DbUpdateException ex)
|
||||||
{
|
{
|
||||||
_database.DiscardChanges();
|
_database.DiscardChanges();
|
||||||
if (Helper.IsDuplicateException(ex))
|
if (IsDuplicateException(ex))
|
||||||
throw new DuplicatedItemException($"Trying to insert a duplicated studio (slug {obj.Slug} already exists).");
|
throw new DuplicatedItemException($"Trying to insert a duplicated studio (slug {obj.Slug} already exists).");
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Studio> CreateIfNotExists(Studio obj)
|
protected override Task Validate(Studio ressource)
|
||||||
{
|
{
|
||||||
if (obj == null)
|
return Task.CompletedTask;
|
||||||
throw new ArgumentNullException(nameof(obj));
|
|
||||||
|
|
||||||
Studio old = await Get(obj.Slug);
|
|
||||||
if (old != null)
|
|
||||||
return old;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await Create(obj);
|
|
||||||
}
|
|
||||||
catch (DuplicatedItemException)
|
|
||||||
{
|
|
||||||
old = await Get(obj.Slug);
|
|
||||||
if (old == null)
|
|
||||||
throw new SystemException("Unknown database state.");
|
|
||||||
return old;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Studio> Edit(Studio edited, bool resetOld)
|
public override async Task Delete(Studio obj)
|
||||||
{
|
|
||||||
if (edited == null)
|
|
||||||
throw new ArgumentNullException(nameof(edited));
|
|
||||||
|
|
||||||
Studio old = await Get(edited.Name);
|
|
||||||
|
|
||||||
if (old == null)
|
|
||||||
throw new ItemNotFound($"No studio found with the name {edited.Name}.");
|
|
||||||
|
|
||||||
if (resetOld)
|
|
||||||
Utility.Nullify(old);
|
|
||||||
Utility.Merge(old, edited);
|
|
||||||
await _database.SaveChangesAsync();
|
|
||||||
return old;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task Delete(int id)
|
|
||||||
{
|
|
||||||
Studio obj = await Get(id);
|
|
||||||
await Delete(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task Delete(string slug)
|
|
||||||
{
|
|
||||||
Studio obj = await Get(slug);
|
|
||||||
await Delete(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task Delete(Studio obj)
|
|
||||||
{
|
{
|
||||||
if (obj == null)
|
if (obj == null)
|
||||||
throw new ArgumentNullException(nameof(obj));
|
throw new ArgumentNullException(nameof(obj));
|
||||||
@ -137,23 +66,5 @@ namespace Kyoo.Controllers
|
|||||||
show.StudioID = null;
|
show.StudioID = null;
|
||||||
await _database.SaveChangesAsync();
|
await _database.SaveChangesAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task DeleteRange(IEnumerable<Studio> objs)
|
|
||||||
{
|
|
||||||
foreach (Studio obj in objs)
|
|
||||||
await Delete(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task DeleteRange(IEnumerable<int> ids)
|
|
||||||
{
|
|
||||||
foreach (int id in ids)
|
|
||||||
await Delete(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task DeleteRange(IEnumerable<string> slugs)
|
|
||||||
{
|
|
||||||
foreach (string slug in slugs)
|
|
||||||
await Delete(slug);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Kyoo.Models;
|
using Kyoo.Models;
|
||||||
using Kyoo.Models.Exceptions;
|
using Kyoo.Models.Exceptions;
|
||||||
@ -8,34 +9,39 @@ using Microsoft.EntityFrameworkCore;
|
|||||||
|
|
||||||
namespace Kyoo.Controllers
|
namespace Kyoo.Controllers
|
||||||
{
|
{
|
||||||
public class TrackRepository : ITrackRepository
|
public class TrackRepository : LocalRepository<Track>, ITrackRepository
|
||||||
{
|
{
|
||||||
private readonly DatabaseContext _database;
|
private readonly DatabaseContext _database;
|
||||||
|
protected override Expression<Func<Track, object>> DefaultSort => x => x.ID;
|
||||||
|
|
||||||
|
|
||||||
public TrackRepository(DatabaseContext database)
|
public TrackRepository(DatabaseContext database) : base(database)
|
||||||
{
|
{
|
||||||
_database = database;
|
_database = database;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public override Task<Track> Get(string slug)
|
||||||
{
|
{
|
||||||
_database.Dispose();
|
Match match = Regex.Match(slug,
|
||||||
|
@"(?<show>.*)-s(?<season>\d*)-e(?<episode>\d*).(?<language>.{0,3})(?<forced>-forced)?(\..*)?");
|
||||||
|
|
||||||
|
if (!match.Success)
|
||||||
|
{
|
||||||
|
if (int.TryParse(slug, out int id))
|
||||||
|
return Get(id);
|
||||||
|
throw new ArgumentException("Invalid track slug. Format: {episodeSlug}.{language}[-forced][.{extension}]");
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueTask DisposeAsync()
|
string showSlug = match.Groups["show"].Value;
|
||||||
{
|
int seasonNumber = int.Parse(match.Groups["season"].Value);
|
||||||
return _database.DisposeAsync();
|
int episodeNumber = int.Parse(match.Groups["episode"].Value);
|
||||||
}
|
string language = match.Groups["language"].Value;
|
||||||
|
bool forced = match.Groups["forced"].Success;
|
||||||
public async Task<Track> Get(int id)
|
return _database.Tracks.FirstOrDefaultAsync(x => x.Episode.Show.Slug == showSlug
|
||||||
{
|
&& x.Episode.SeasonNumber == seasonNumber
|
||||||
return await _database.Tracks.FirstOrDefaultAsync(x => x.ID == id);
|
&& x.Episode.EpisodeNumber == episodeNumber
|
||||||
}
|
&& x.Language == language
|
||||||
|
&& x.IsForced == forced);
|
||||||
public Task<Track> Get(string slug)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException("Tracks do not support the get by slug method.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<Track> Get(int episodeID, string languageTag, bool isForced)
|
public Task<Track> Get(int episodeID, string languageTag, bool isForced)
|
||||||
@ -45,19 +51,12 @@ namespace Kyoo.Controllers
|
|||||||
&& x.IsForced == isForced);
|
&& x.IsForced == isForced);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<ICollection<Track>> Search(string query)
|
public override Task<ICollection<Track>> Search(string query)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Tracks do not support the search method.");
|
throw new InvalidOperationException("Tracks do not support the search method.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<ICollection<Track>> GetAll(Expression<Func<Track, bool>> where = null,
|
public override async Task<Track> Create(Track obj)
|
||||||
Sort<Track> sort = default,
|
|
||||||
Pagination limit = default)
|
|
||||||
{
|
|
||||||
return await _database.Tracks.ToListAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<Track> Create(Track obj)
|
|
||||||
{
|
{
|
||||||
if (obj == null)
|
if (obj == null)
|
||||||
throw new ArgumentNullException(nameof(obj));
|
throw new ArgumentNullException(nameof(obj));
|
||||||
@ -74,48 +73,19 @@ namespace Kyoo.Controllers
|
|||||||
catch (DbUpdateException ex)
|
catch (DbUpdateException ex)
|
||||||
{
|
{
|
||||||
_database.DiscardChanges();
|
_database.DiscardChanges();
|
||||||
if (Helper.IsDuplicateException(ex))
|
if (IsDuplicateException(ex))
|
||||||
throw new DuplicatedItemException($"Trying to insert a duplicated track (slug {obj.Slug} already exists).");
|
throw new DuplicatedItemException($"Trying to insert a duplicated track (slug {obj.Slug} already exists).");
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<Track> CreateIfNotExists(Track obj)
|
protected override Task Validate(Track ressource)
|
||||||
{
|
{
|
||||||
return Create(obj);
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Track> Edit(Track edited, bool resetOld)
|
public override async Task Delete(Track obj)
|
||||||
{
|
|
||||||
if (edited == null)
|
|
||||||
throw new ArgumentNullException(nameof(edited));
|
|
||||||
|
|
||||||
Track old = await Get(edited.ID);
|
|
||||||
|
|
||||||
if (old == null)
|
|
||||||
throw new ItemNotFound($"No track found with the ID {edited.ID}.");
|
|
||||||
|
|
||||||
if (resetOld)
|
|
||||||
Utility.Nullify(old);
|
|
||||||
Utility.Merge(old, edited);
|
|
||||||
await _database.SaveChangesAsync();
|
|
||||||
return old;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task Delete(int id)
|
|
||||||
{
|
|
||||||
Track obj = await Get(id);
|
|
||||||
await Delete(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task Delete(string slug)
|
|
||||||
{
|
|
||||||
Track obj = await Get(slug);
|
|
||||||
await Delete(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task Delete(Track obj)
|
|
||||||
{
|
{
|
||||||
if (obj == null)
|
if (obj == null)
|
||||||
throw new ArgumentNullException(nameof(obj));
|
throw new ArgumentNullException(nameof(obj));
|
||||||
@ -123,23 +93,5 @@ namespace Kyoo.Controllers
|
|||||||
_database.Entry(obj).State = EntityState.Deleted;
|
_database.Entry(obj).State = EntityState.Deleted;
|
||||||
await _database.SaveChangesAsync();
|
await _database.SaveChangesAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task DeleteRange(IEnumerable<Track> objs)
|
|
||||||
{
|
|
||||||
foreach (Track obj in objs)
|
|
||||||
await Delete(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task DeleteRange(IEnumerable<int> ids)
|
|
||||||
{
|
|
||||||
foreach (int id in ids)
|
|
||||||
await Delete(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task DeleteRange(IEnumerable<string> slugs)
|
|
||||||
{
|
|
||||||
foreach (string slug in slugs)
|
|
||||||
await Delete(slug);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user