mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-07-09 03:04:20 -04:00
commit
fc65716906
@ -1,11 +1,12 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using JetBrains.Annotations;
|
||||
using Kyoo.Models;
|
||||
|
||||
namespace Kyoo.Controllers
|
||||
{
|
||||
public interface ILibraryManager
|
||||
public interface ILibraryManager : IDisposable, IAsyncDisposable
|
||||
{
|
||||
// Get by slug
|
||||
Task<Library> GetLibrary(string slug);
|
||||
|
@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using JetBrains.Annotations;
|
||||
@ -5,7 +6,7 @@ using Kyoo.Models;
|
||||
|
||||
namespace Kyoo.Controllers
|
||||
{
|
||||
public interface IRepository<T>
|
||||
public interface IRepository<T> : IDisposable, IAsyncDisposable
|
||||
{
|
||||
Task<T> Get(int id);
|
||||
Task<T> Get(string slug);
|
||||
|
14
Kyoo.Common/Models/Exceptions/DuplicatedItemException.cs
Normal file
14
Kyoo.Common/Models/Exceptions/DuplicatedItemException.cs
Normal file
@ -0,0 +1,14 @@
|
||||
using System;
|
||||
|
||||
namespace Kyoo.Models.Exceptions
|
||||
{
|
||||
public class DuplicatedItemException : Exception
|
||||
{
|
||||
public override string Message { get; }
|
||||
|
||||
public DuplicatedItemException(string message)
|
||||
{
|
||||
Message = message;
|
||||
}
|
||||
}
|
||||
}
|
@ -40,6 +40,36 @@ namespace Kyoo.Controllers
|
||||
_providers = providers;
|
||||
_people = people;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_libraries.Dispose();
|
||||
_collections.Dispose();
|
||||
_shows.Dispose();
|
||||
_seasons.Dispose();
|
||||
_episodes.Dispose();
|
||||
_tracks.Dispose();
|
||||
_genres.Dispose();
|
||||
_studios.Dispose();
|
||||
_people.Dispose();
|
||||
_providers.Dispose();
|
||||
}
|
||||
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
await Task.WhenAll(
|
||||
_libraries.DisposeAsync().AsTask(),
|
||||
_collections.DisposeAsync().AsTask(),
|
||||
_shows.DisposeAsync().AsTask(),
|
||||
_seasons.DisposeAsync().AsTask(),
|
||||
_episodes.DisposeAsync().AsTask(),
|
||||
_tracks.DisposeAsync().AsTask(),
|
||||
_genres.DisposeAsync().AsTask(),
|
||||
_studios.DisposeAsync().AsTask(),
|
||||
_people.DisposeAsync().AsTask(),
|
||||
_providers.DisposeAsync().AsTask()
|
||||
);
|
||||
}
|
||||
|
||||
public Task<Library> GetLibrary(string slug)
|
||||
{
|
||||
|
@ -5,6 +5,7 @@ using System.Threading.Tasks;
|
||||
using Kyoo.Models;
|
||||
using Kyoo.Models.Exceptions;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Npgsql;
|
||||
|
||||
namespace Kyoo.Controllers
|
||||
{
|
||||
@ -18,6 +19,16 @@ namespace Kyoo.Controllers
|
||||
_database = database;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_database.Dispose();
|
||||
}
|
||||
|
||||
public ValueTask DisposeAsync()
|
||||
{
|
||||
return _database.DisposeAsync();
|
||||
}
|
||||
|
||||
public Task<Collection> Get(int id)
|
||||
{
|
||||
return _database.Collections.FirstOrDefaultAsync(x => x.ID == id);
|
||||
@ -45,9 +56,20 @@ namespace Kyoo.Controllers
|
||||
{
|
||||
if (obj == null)
|
||||
throw new ArgumentNullException(nameof(obj));
|
||||
|
||||
_database.Entry(obj).State = EntityState.Added;
|
||||
|
||||
await _database.Collections.AddAsync(obj);
|
||||
await _database.SaveChangesAsync();
|
||||
try
|
||||
{
|
||||
await _database.SaveChangesAsync();
|
||||
}
|
||||
catch (DbUpdateException ex)
|
||||
{
|
||||
if (Helper.IsDuplicateException(ex))
|
||||
throw new DuplicatedItemException($"Trying to insert a duplicated collection (slug {obj.Slug} already exists).");
|
||||
throw;
|
||||
}
|
||||
|
||||
return obj.ID;
|
||||
}
|
||||
|
||||
@ -59,7 +81,17 @@ namespace Kyoo.Controllers
|
||||
Collection old = await Get(obj.Slug);
|
||||
if (old != null)
|
||||
return old.ID;
|
||||
return await Create(obj);
|
||||
try
|
||||
{
|
||||
return await Create(obj);
|
||||
}
|
||||
catch (DuplicatedItemException)
|
||||
{
|
||||
old = await Get(obj.Slug);
|
||||
if (old == null)
|
||||
throw new SystemException("Unknown database state.");
|
||||
return old.ID;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task Edit(Collection edited, bool resetOld)
|
||||
|
@ -6,6 +6,7 @@ using Kyoo.Models;
|
||||
using Kyoo.Models.Exceptions;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Npgsql;
|
||||
|
||||
namespace Kyoo.Controllers
|
||||
{
|
||||
@ -21,6 +22,16 @@ namespace Kyoo.Controllers
|
||||
_serviceProvider = serviceProvider;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_database.Dispose();
|
||||
}
|
||||
|
||||
public ValueTask DisposeAsync()
|
||||
{
|
||||
return _database.DisposeAsync();
|
||||
}
|
||||
|
||||
public async Task<Episode> Get(int id)
|
||||
{
|
||||
return await _database.Episodes.FirstOrDefaultAsync(x => x.ID == id);
|
||||
@ -73,7 +84,17 @@ namespace Kyoo.Controllers
|
||||
if (obj.Tracks != null)
|
||||
foreach (Track entry in obj.Tracks)
|
||||
_database.Entry(entry).State = EntityState.Added;
|
||||
await _database.SaveChangesAsync();
|
||||
|
||||
try
|
||||
{
|
||||
await _database.SaveChangesAsync();
|
||||
}
|
||||
catch (DbUpdateException ex)
|
||||
{
|
||||
if (Helper.IsDuplicateException(ex))
|
||||
throw new DuplicatedItemException($"Trying to insert a duplicated episode (slug {obj.Slug} already exists).");
|
||||
throw;
|
||||
}
|
||||
return obj.ID;
|
||||
}
|
||||
|
||||
@ -85,7 +106,17 @@ namespace Kyoo.Controllers
|
||||
Episode old = await Get(obj.Slug);
|
||||
if (old != null)
|
||||
return old.ID;
|
||||
return await Create(obj);
|
||||
try
|
||||
{
|
||||
return await Create(obj);
|
||||
}
|
||||
catch (DuplicatedItemException)
|
||||
{
|
||||
old = await Get(obj.Slug);
|
||||
if (old == null)
|
||||
throw new SystemException("Unknown database state.");
|
||||
return old.ID;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task Edit(Episode edited, bool resetOld)
|
||||
@ -116,7 +147,7 @@ namespace Kyoo.Controllers
|
||||
obj.ExternalIDs = (await Task.WhenAll(obj.ExternalIDs.Select(async x =>
|
||||
{
|
||||
using IServiceScope serviceScope = _serviceProvider.CreateScope();
|
||||
IProviderRepository providers = serviceScope.ServiceProvider.GetService<IProviderRepository>();
|
||||
await using IProviderRepository providers = serviceScope.ServiceProvider.GetService<IProviderRepository>();
|
||||
|
||||
x.ProviderID = await providers.CreateIfNotExists(x.Provider);
|
||||
return x;
|
||||
|
@ -17,6 +17,16 @@ namespace Kyoo.Controllers
|
||||
{
|
||||
_database = database;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_database.Dispose();
|
||||
}
|
||||
|
||||
public ValueTask DisposeAsync()
|
||||
{
|
||||
return _database.DisposeAsync();
|
||||
}
|
||||
|
||||
public async Task<Genre> Get(int id)
|
||||
{
|
||||
@ -47,7 +57,18 @@ namespace Kyoo.Controllers
|
||||
throw new ArgumentNullException(nameof(obj));
|
||||
|
||||
await _database.Genres.AddAsync(obj);
|
||||
await _database.SaveChangesAsync();
|
||||
|
||||
try
|
||||
{
|
||||
await _database.SaveChangesAsync();
|
||||
}
|
||||
catch (DbUpdateException ex)
|
||||
{
|
||||
if (Helper.IsDuplicateException(ex))
|
||||
throw new DuplicatedItemException($"Trying to insert a duplicated genre (slug {obj.Slug} already exists).");
|
||||
throw;
|
||||
}
|
||||
|
||||
return obj.ID;
|
||||
}
|
||||
|
||||
@ -59,7 +80,17 @@ namespace Kyoo.Controllers
|
||||
Genre old = await Get(obj.Slug);
|
||||
if (old != null)
|
||||
return old.ID;
|
||||
return await Create(obj);
|
||||
try
|
||||
{
|
||||
return await Create(obj);
|
||||
}
|
||||
catch (DuplicatedItemException)
|
||||
{
|
||||
old = await Get(obj.Slug);
|
||||
if (old == null)
|
||||
throw new SystemException("Unknown database state.");
|
||||
return old.ID;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task Edit(Genre edited, bool resetOld)
|
||||
|
14
Kyoo/Controllers/Repositories/Helper.cs
Normal file
14
Kyoo/Controllers/Repositories/Helper.cs
Normal file
@ -0,0 +1,14 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Npgsql;
|
||||
|
||||
namespace Kyoo.Controllers
|
||||
{
|
||||
public static class Helper
|
||||
{
|
||||
public static bool IsDuplicateException(DbUpdateException ex)
|
||||
{
|
||||
return ex.InnerException is PostgresException inner
|
||||
&& inner.SqlState == PostgresErrorCodes.UniqueViolation;
|
||||
}
|
||||
}
|
||||
}
|
@ -20,7 +20,17 @@ namespace Kyoo.Controllers
|
||||
_database = database;
|
||||
_serviceProvider = serviceProvider;
|
||||
}
|
||||
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_database.Dispose();
|
||||
}
|
||||
|
||||
public ValueTask DisposeAsync()
|
||||
{
|
||||
return _database.DisposeAsync();
|
||||
}
|
||||
|
||||
public Task<Library> Get(int id)
|
||||
{
|
||||
return _database.Libraries.FirstOrDefaultAsync(x => x.ID == id);
|
||||
@ -54,7 +64,18 @@ namespace Kyoo.Controllers
|
||||
if (obj.ProviderLinks != null)
|
||||
foreach (ProviderLink entry in obj.ProviderLinks)
|
||||
_database.Entry(entry).State = EntityState.Added;
|
||||
await _database.SaveChangesAsync();
|
||||
|
||||
try
|
||||
{
|
||||
await _database.SaveChangesAsync();
|
||||
}
|
||||
catch (DbUpdateException ex)
|
||||
{
|
||||
if (Helper.IsDuplicateException(ex))
|
||||
throw new DuplicatedItemException($"Trying to insert a duplicated library (slug {obj.Slug} already exists).");
|
||||
throw;
|
||||
}
|
||||
|
||||
return obj.ID;
|
||||
}
|
||||
|
||||
@ -63,10 +84,20 @@ namespace Kyoo.Controllers
|
||||
if (obj == null)
|
||||
throw new ArgumentNullException(nameof(obj));
|
||||
|
||||
Library old = await Get(obj.Name);
|
||||
Library old = await Get(obj.Slug);
|
||||
if (old != null)
|
||||
return old.ID;
|
||||
return await Create(obj);
|
||||
try
|
||||
{
|
||||
return await Create(obj);
|
||||
}
|
||||
catch (DuplicatedItemException)
|
||||
{
|
||||
old = await Get(obj.Slug);
|
||||
if (old == null)
|
||||
throw new SystemException("Unknown database state.");
|
||||
return old.ID;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task Edit(Library edited, bool resetOld)
|
||||
@ -91,7 +122,7 @@ namespace Kyoo.Controllers
|
||||
obj.ProviderLinks = (await Task.WhenAll(obj.ProviderLinks.Select(async x =>
|
||||
{
|
||||
using IServiceScope serviceScope = _serviceProvider.CreateScope();
|
||||
IProviderRepository providers = serviceScope.ServiceProvider.GetService<IProviderRepository>();
|
||||
await using IProviderRepository providers = serviceScope.ServiceProvider.GetService<IProviderRepository>();
|
||||
|
||||
x.ProviderID = await providers.CreateIfNotExists(x.Provider);
|
||||
return x;
|
||||
|
@ -19,6 +19,16 @@ namespace Kyoo.Controllers
|
||||
_database = database;
|
||||
_serviceProvider = serviceProvider;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_database.Dispose();
|
||||
}
|
||||
|
||||
public ValueTask DisposeAsync()
|
||||
{
|
||||
return _database.DisposeAsync();
|
||||
}
|
||||
|
||||
public Task<People> Get(int id)
|
||||
{
|
||||
@ -53,7 +63,18 @@ namespace Kyoo.Controllers
|
||||
if (obj.ExternalIDs != null)
|
||||
foreach (MetadataID entry in obj.ExternalIDs)
|
||||
_database.Entry(entry).State = EntityState.Added;
|
||||
await _database.SaveChangesAsync();
|
||||
|
||||
try
|
||||
{
|
||||
await _database.SaveChangesAsync();
|
||||
}
|
||||
catch (DbUpdateException ex)
|
||||
{
|
||||
if (Helper.IsDuplicateException(ex))
|
||||
throw new DuplicatedItemException($"Trying to insert a duplicated people (slug {obj.Slug} already exists).");
|
||||
throw;
|
||||
}
|
||||
|
||||
return obj.ID;
|
||||
}
|
||||
|
||||
@ -65,7 +86,17 @@ namespace Kyoo.Controllers
|
||||
People old = await Get(obj.Slug);
|
||||
if (old != null)
|
||||
return old.ID;
|
||||
return await Create(obj);
|
||||
try
|
||||
{
|
||||
return await Create(obj);
|
||||
}
|
||||
catch (DuplicatedItemException)
|
||||
{
|
||||
old = await Get(obj.Slug);
|
||||
if (old == null)
|
||||
throw new SystemException("Unknown database state.");
|
||||
return old.ID;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task Edit(People edited, bool resetOld)
|
||||
@ -90,7 +121,7 @@ namespace Kyoo.Controllers
|
||||
obj.ExternalIDs = (await Task.WhenAll(obj.ExternalIDs.Select(async x =>
|
||||
{
|
||||
using IServiceScope serviceScope = _serviceProvider.CreateScope();
|
||||
IProviderRepository providers = serviceScope.ServiceProvider.GetService<IProviderRepository>();
|
||||
await using IProviderRepository providers = serviceScope.ServiceProvider.GetService<IProviderRepository>();
|
||||
|
||||
x.ProviderID = await providers.CreateIfNotExists(x.Provider);
|
||||
return x;
|
||||
|
@ -18,6 +18,16 @@ namespace Kyoo.Controllers
|
||||
_database = database;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_database.Dispose();
|
||||
}
|
||||
|
||||
public ValueTask DisposeAsync()
|
||||
{
|
||||
return _database.DisposeAsync();
|
||||
}
|
||||
|
||||
public async Task<ProviderID> Get(int id)
|
||||
{
|
||||
return await _database.Providers.FirstOrDefaultAsync(x => x.ID == id);
|
||||
@ -46,8 +56,19 @@ namespace Kyoo.Controllers
|
||||
if (obj == null)
|
||||
throw new ArgumentNullException(nameof(obj));
|
||||
|
||||
await _database.Providers.AddAsync(obj);
|
||||
await _database.SaveChangesAsync();
|
||||
_database.Entry(obj).State = EntityState.Added;
|
||||
|
||||
try
|
||||
{
|
||||
await _database.SaveChangesAsync();
|
||||
}
|
||||
catch (DbUpdateException ex)
|
||||
{
|
||||
if (Helper.IsDuplicateException(ex))
|
||||
throw new DuplicatedItemException($"Trying to insert a duplicated provider (name {obj.Name} already exists).");
|
||||
throw;
|
||||
}
|
||||
|
||||
return obj.ID;
|
||||
}
|
||||
|
||||
@ -59,7 +80,17 @@ namespace Kyoo.Controllers
|
||||
ProviderID old = await Get(obj.Name);
|
||||
if (old != null)
|
||||
return old.ID;
|
||||
return await Create(obj);
|
||||
try
|
||||
{
|
||||
return await Create(obj);
|
||||
}
|
||||
catch (DuplicatedItemException)
|
||||
{
|
||||
old = await Get(obj.Name);
|
||||
if (old == null)
|
||||
throw new SystemException("Unknown database state.");
|
||||
return old.ID;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task Edit(ProviderID edited, bool resetOld)
|
||||
|
@ -21,6 +21,16 @@ namespace Kyoo.Controllers
|
||||
_serviceProvider = serviceProvider;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_database.Dispose();
|
||||
}
|
||||
|
||||
public ValueTask DisposeAsync()
|
||||
{
|
||||
return _database.DisposeAsync();
|
||||
}
|
||||
|
||||
public async Task<Season> Get(int id)
|
||||
{
|
||||
return await _database.Seasons.FirstOrDefaultAsync(x => x.ID == id);
|
||||
@ -66,7 +76,18 @@ namespace Kyoo.Controllers
|
||||
if (obj.ExternalIDs != null)
|
||||
foreach (MetadataID entry in obj.ExternalIDs)
|
||||
_database.Entry(entry).State = EntityState.Added;
|
||||
await _database.SaveChangesAsync();
|
||||
|
||||
try
|
||||
{
|
||||
await _database.SaveChangesAsync();
|
||||
}
|
||||
catch (DbUpdateException ex)
|
||||
{
|
||||
if (Helper.IsDuplicateException(ex))
|
||||
throw new DuplicatedItemException($"Trying to insert a duplicated season (slug {obj.Slug} already exists).");
|
||||
throw;
|
||||
}
|
||||
|
||||
return obj.ID;
|
||||
}
|
||||
|
||||
@ -78,7 +99,17 @@ namespace Kyoo.Controllers
|
||||
Season old = await Get(obj.Slug);
|
||||
if (old != null)
|
||||
return old.ID;
|
||||
return await Create(obj);
|
||||
try
|
||||
{
|
||||
return await Create(obj);
|
||||
}
|
||||
catch (DuplicatedItemException)
|
||||
{
|
||||
old = await Get(obj.Slug);
|
||||
if (old == null)
|
||||
throw new SystemException("Unknown database state.");
|
||||
return old.ID;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task Edit(Season edited, bool resetOld)
|
||||
@ -109,7 +140,7 @@ namespace Kyoo.Controllers
|
||||
obj.ExternalIDs = (await Task.WhenAll(obj.ExternalIDs.Select(async x =>
|
||||
{
|
||||
using IServiceScope serviceScope = _serviceProvider.CreateScope();
|
||||
IProviderRepository providers = serviceScope.ServiceProvider.GetService<IProviderRepository>();
|
||||
await using IProviderRepository providers = serviceScope.ServiceProvider.GetService<IProviderRepository>();
|
||||
|
||||
x.ProviderID = await providers.CreateIfNotExists(x.Provider);
|
||||
return x;
|
||||
|
@ -24,6 +24,17 @@ namespace Kyoo.Controllers
|
||||
_studios = studios;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_database.Dispose();
|
||||
_studios.Dispose();
|
||||
}
|
||||
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
await Task.WhenAll(_database.DisposeAsync().AsTask(), _studios.DisposeAsync().AsTask());
|
||||
}
|
||||
|
||||
public async Task<Show> Get(int id)
|
||||
{
|
||||
return await _database.Shows.FirstOrDefaultAsync(x => x.ID == id);
|
||||
@ -69,7 +80,18 @@ namespace Kyoo.Controllers
|
||||
if (obj.ExternalIDs != null)
|
||||
foreach (MetadataID entry in obj.ExternalIDs)
|
||||
_database.Entry(entry).State = EntityState.Added;
|
||||
await _database.SaveChangesAsync();
|
||||
|
||||
try
|
||||
{
|
||||
await _database.SaveChangesAsync();
|
||||
}
|
||||
catch (DbUpdateException ex)
|
||||
{
|
||||
if (Helper.IsDuplicateException(ex))
|
||||
throw new DuplicatedItemException($"Trying to insert a duplicated show (slug {obj.Slug} already exists).");
|
||||
throw;
|
||||
}
|
||||
|
||||
return obj.ID;
|
||||
}
|
||||
|
||||
@ -81,7 +103,17 @@ namespace Kyoo.Controllers
|
||||
Show old = await Get(obj.Slug);
|
||||
if (old != null)
|
||||
return old.ID;
|
||||
return await Create(obj);
|
||||
try
|
||||
{
|
||||
return await Create(obj);
|
||||
}
|
||||
catch (DuplicatedItemException)
|
||||
{
|
||||
old = await Get(obj.Slug);
|
||||
if (old == null)
|
||||
throw new SystemException("Unknown database state.");
|
||||
return old.ID;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task Edit(Show edited, bool resetOld)
|
||||
@ -111,7 +143,7 @@ namespace Kyoo.Controllers
|
||||
obj.GenreLinks = (await Task.WhenAll(obj.GenreLinks.Select(async x =>
|
||||
{
|
||||
using IServiceScope serviceScope = _serviceProvider.CreateScope();
|
||||
IGenreRepository genres = serviceScope.ServiceProvider.GetService<IGenreRepository>();
|
||||
await using IGenreRepository genres = serviceScope.ServiceProvider.GetService<IGenreRepository>();
|
||||
|
||||
x.GenreID = await genres.CreateIfNotExists(x.Genre);
|
||||
return x;
|
||||
@ -123,7 +155,7 @@ namespace Kyoo.Controllers
|
||||
obj.People = (await Task.WhenAll(obj.People.Select(async x =>
|
||||
{
|
||||
using IServiceScope serviceScope = _serviceProvider.CreateScope();
|
||||
IPeopleRepository people = serviceScope.ServiceProvider.GetService<IPeopleRepository>();
|
||||
await using IPeopleRepository people = serviceScope.ServiceProvider.GetService<IPeopleRepository>();
|
||||
|
||||
x.PeopleID = await people.CreateIfNotExists(x.People);
|
||||
return x;
|
||||
@ -135,7 +167,7 @@ namespace Kyoo.Controllers
|
||||
obj.ExternalIDs = (await Task.WhenAll(obj.ExternalIDs.Select(async x =>
|
||||
{
|
||||
using IServiceScope serviceScope = _serviceProvider.CreateScope();
|
||||
IProviderRepository providers = serviceScope.ServiceProvider.GetService<IProviderRepository>();
|
||||
await using IProviderRepository providers = serviceScope.ServiceProvider.GetService<IProviderRepository>();
|
||||
|
||||
x.ProviderID = await providers.CreateIfNotExists(x.Provider);
|
||||
return x;
|
||||
|
@ -18,6 +18,16 @@ namespace Kyoo.Controllers
|
||||
_database = database;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_database.Dispose();
|
||||
}
|
||||
|
||||
public ValueTask DisposeAsync()
|
||||
{
|
||||
return _database.DisposeAsync();
|
||||
}
|
||||
|
||||
public async Task<Studio> Get(int id)
|
||||
{
|
||||
return await _database.Studios.FirstOrDefaultAsync(x => x.ID == id);
|
||||
@ -46,8 +56,18 @@ namespace Kyoo.Controllers
|
||||
if (obj == null)
|
||||
throw new ArgumentNullException(nameof(obj));
|
||||
|
||||
await _database.Studios.AddAsync(obj);
|
||||
await _database.SaveChangesAsync();
|
||||
_database.Entry(obj).State = EntityState.Added;
|
||||
|
||||
try
|
||||
{
|
||||
await _database.SaveChangesAsync();
|
||||
}
|
||||
catch (DbUpdateException ex)
|
||||
{
|
||||
if (Helper.IsDuplicateException(ex))
|
||||
throw new DuplicatedItemException($"Trying to insert a duplicated studio (slug {obj.Slug} already exists).");
|
||||
throw;
|
||||
}
|
||||
return obj.ID;
|
||||
}
|
||||
|
||||
@ -59,7 +79,17 @@ namespace Kyoo.Controllers
|
||||
Studio old = await Get(obj.Slug);
|
||||
if (old != null)
|
||||
return old.ID;
|
||||
return await Create(obj);
|
||||
try
|
||||
{
|
||||
return await Create(obj);
|
||||
}
|
||||
catch (DuplicatedItemException)
|
||||
{
|
||||
old = await Get(obj.Slug);
|
||||
if (old == null)
|
||||
throw new SystemException("Unknown database state.");
|
||||
return old.ID;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task Edit(Studio edited, bool resetOld)
|
||||
|
@ -17,6 +17,16 @@ namespace Kyoo.Controllers
|
||||
_database = database;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_database.Dispose();
|
||||
}
|
||||
|
||||
public ValueTask DisposeAsync()
|
||||
{
|
||||
return _database.DisposeAsync();
|
||||
}
|
||||
|
||||
public async Task<Track> Get(int id)
|
||||
{
|
||||
return await _database.Tracks.FirstOrDefaultAsync(x => x.ID == id);
|
||||
@ -51,9 +61,19 @@ namespace Kyoo.Controllers
|
||||
|
||||
if (obj.EpisodeID <= 0)
|
||||
throw new InvalidOperationException($"Can't store a track not related to any episode (episodeID: {obj.EpisodeID}).");
|
||||
|
||||
_database.Entry(obj).State = EntityState.Added;
|
||||
|
||||
await _database.Tracks.AddAsync(obj);
|
||||
await _database.SaveChangesAsync();
|
||||
try
|
||||
{
|
||||
await _database.SaveChangesAsync();
|
||||
}
|
||||
catch (DbUpdateException ex)
|
||||
{
|
||||
if (Helper.IsDuplicateException(ex))
|
||||
throw new DuplicatedItemException($"Trying to insert a duplicated track (slug {obj.Slug} already exists).");
|
||||
throw;
|
||||
}
|
||||
return obj.ID;
|
||||
}
|
||||
|
||||
|
@ -49,21 +49,6 @@ namespace Kyoo
|
||||
|
||||
}
|
||||
|
||||
public class DatabaseFactory
|
||||
{
|
||||
private readonly DbContextOptions<DatabaseContext> _options;
|
||||
|
||||
public DatabaseFactory(DbContextOptions<DatabaseContext> options)
|
||||
{
|
||||
_options = options;
|
||||
}
|
||||
|
||||
public DatabaseContext NewDatabaseConnection()
|
||||
{
|
||||
return new DatabaseContext(_options);
|
||||
}
|
||||
}
|
||||
|
||||
public class DatabaseContext : DbContext
|
||||
{
|
||||
public DatabaseContext(DbContextOptions<DatabaseContext> options) : base(options) { }
|
||||
|
@ -43,16 +43,11 @@ namespace Kyoo
|
||||
services.AddControllers().AddNewtonsoftJson();
|
||||
services.AddHttpClient();
|
||||
|
||||
services.AddSingleton(x => new DatabaseFactory(
|
||||
new DbContextOptionsBuilder<DatabaseContext>()
|
||||
.UseLazyLoadingProxies()
|
||||
.UseNpgsql(_configuration.GetConnectionString("Database")).Options));
|
||||
|
||||
services.AddDbContext<DatabaseContext>(options =>
|
||||
{
|
||||
options.UseLazyLoadingProxies()
|
||||
.UseNpgsql(_configuration.GetConnectionString("Database"));
|
||||
// .EnableSensitiveDataLogging()
|
||||
.UseNpgsql(_configuration.GetConnectionString("Database"))
|
||||
.EnableSensitiveDataLogging();
|
||||
// .UseLoggerFactory(LoggerFactory.Create(builder => builder.AddConsole()));
|
||||
});
|
||||
|
||||
|
@ -7,6 +7,7 @@ using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Kyoo.Models.Exceptions;
|
||||
using Kyoo.Models.Watch;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
@ -30,7 +31,7 @@ namespace Kyoo.Controllers
|
||||
public async Task<IEnumerable<string>> GetPossibleParameters()
|
||||
{
|
||||
using IServiceScope serviceScope = _serviceProvider.CreateScope();
|
||||
ILibraryManager libraryManager = serviceScope.ServiceProvider.GetService<ILibraryManager>();
|
||||
await using ILibraryManager libraryManager = serviceScope.ServiceProvider.GetService<ILibraryManager>();
|
||||
return (await libraryManager.GetLibraries()).Select(x => x.Slug);
|
||||
}
|
||||
|
||||
@ -40,7 +41,9 @@ namespace Kyoo.Controllers
|
||||
return null;
|
||||
}
|
||||
|
||||
public async Task Run(IServiceProvider serviceProvider, CancellationToken cancellationToken, string argument = null)
|
||||
public async Task Run(IServiceProvider serviceProvider,
|
||||
CancellationToken cancellationToken,
|
||||
string argument = null)
|
||||
{
|
||||
_serviceProvider = serviceProvider;
|
||||
_thumbnailsManager = serviceProvider.GetService<IThumbnailsManager>();
|
||||
@ -51,7 +54,7 @@ namespace Kyoo.Controllers
|
||||
try
|
||||
{
|
||||
using IServiceScope serviceScope = _serviceProvider.CreateScope();
|
||||
ILibraryManager libraryManager = serviceScope.ServiceProvider.GetService<ILibraryManager>();
|
||||
await using ILibraryManager libraryManager = serviceScope.ServiceProvider.GetService<ILibraryManager>();
|
||||
ICollection<Episode> episodes = await libraryManager.GetEpisodes();
|
||||
ICollection<Library> libraries = argument == null
|
||||
? await libraryManager.GetLibraries()
|
||||
@ -63,7 +66,11 @@ namespace Kyoo.Controllers
|
||||
await libraryManager.DeleteEpisode(episode);
|
||||
}
|
||||
|
||||
await Task.WhenAll(libraries.Select(x => Scan(x, episodes, cancellationToken)));
|
||||
// TODO replace this grotesque way to load the providers.
|
||||
foreach (Library library in libraries)
|
||||
library.Providers = library.Providers;
|
||||
|
||||
await Task.WhenAll(libraries.Select(x => Scan(x, episodes, cancellationToken)).ToArray());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -72,10 +79,10 @@ namespace Kyoo.Controllers
|
||||
Console.WriteLine("Scan finished!");
|
||||
}
|
||||
|
||||
private async Task Scan(Library library, ICollection<Episode> episodes, CancellationToken cancellationToken)
|
||||
private Task Scan(Library library, IEnumerable<Episode> episodes, CancellationToken cancellationToken)
|
||||
{
|
||||
Console.WriteLine($"Scanning library {library.Name} at {string.Join(", ", library.Paths)}.");
|
||||
foreach (string path in library.Paths)
|
||||
return Task.WhenAll(library.Paths.Select(async path =>
|
||||
{
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
return;
|
||||
@ -87,34 +94,40 @@ namespace Kyoo.Controllers
|
||||
}
|
||||
catch (DirectoryNotFoundException)
|
||||
{
|
||||
Console.Error.WriteLine($"The library's directory {path} could not be found (library slug: {library.Slug})");
|
||||
await Console.Error.WriteLineAsync($"The library's directory {path} could not be found (library slug: {library.Slug})");
|
||||
return;
|
||||
}
|
||||
catch (PathTooLongException)
|
||||
{
|
||||
Console.Error.WriteLine($"The library's directory {path} is too long for this system. (library slug: {library.Slug})");
|
||||
await Console.Error.WriteLineAsync($"The library's directory {path} is too long for this system. (library slug: {library.Slug})");
|
||||
return;
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
Console.Error.WriteLine($"The library's directory {path} is invalid. (library slug: {library.Slug})");
|
||||
await Console.Error.WriteLineAsync($"The library's directory {path} is invalid. (library slug: {library.Slug})");
|
||||
return;
|
||||
}
|
||||
catch (UnauthorizedAccessException)
|
||||
{
|
||||
Console.Error.WriteLine($"Permission denied: can't access library's directory at {path}. (library slug: {library.Slug})");
|
||||
await Console.Error.WriteLineAsync($"Permission denied: can't access library's directory at {path}. (library slug: {library.Slug})");
|
||||
return;
|
||||
}
|
||||
|
||||
// return Task.WhenAll(files.Select(file =>
|
||||
foreach (string file in files)
|
||||
{
|
||||
if (!IsVideo(file) || episodes.Any(x => x.Path == file))
|
||||
continue; //return Task.CompletedTask;
|
||||
string relativePath = file.Substring(path.Length);
|
||||
/*return*/ await RegisterFile(file, relativePath, library, cancellationToken);
|
||||
}//));
|
||||
}//));
|
||||
List<IGrouping<string, string>> shows = files
|
||||
.Where(x => IsVideo(x) && episodes.All(y => y.Path != x))
|
||||
.GroupBy(Path.GetDirectoryName)
|
||||
.ToList();
|
||||
|
||||
await Task.WhenAll(shows
|
||||
.Select(x => x.First())
|
||||
.Select(x => RegisterFile(x, x.Substring(path.Length), library, cancellationToken))
|
||||
.ToArray());
|
||||
|
||||
await Task.WhenAll(shows
|
||||
.SelectMany(x => x.Skip(1))
|
||||
.Select(x => RegisterFile(x, x.Substring(path.Length), library, cancellationToken))
|
||||
.ToArray());
|
||||
}).ToArray());
|
||||
}
|
||||
|
||||
private async Task RegisterFile(string path, string relativePath, Library library, CancellationToken token)
|
||||
@ -123,7 +136,7 @@ namespace Kyoo.Controllers
|
||||
return;
|
||||
|
||||
using IServiceScope serviceScope = _serviceProvider.CreateScope();
|
||||
ILibraryManager libraryManager = serviceScope.ServiceProvider.GetService<ILibraryManager>();
|
||||
await using ILibraryManager libraryManager = serviceScope.ServiceProvider.GetService<ILibraryManager>();
|
||||
|
||||
string patern = _config.GetValue<string>("regex");
|
||||
Regex regex = new Regex(patern, RegexOptions.IgnoreCase);
|
||||
@ -162,8 +175,16 @@ namespace Kyoo.Controllers
|
||||
if (collection != null)
|
||||
return collection;
|
||||
collection = await _metadataProvider.GetCollectionFromName(collectionName, library);
|
||||
await libraryManager.RegisterCollection(collection);
|
||||
return collection;
|
||||
|
||||
try
|
||||
{
|
||||
await libraryManager.RegisterCollection(collection);
|
||||
return collection;
|
||||
}
|
||||
catch (DuplicatedItemException)
|
||||
{
|
||||
return await libraryManager.GetCollection(collection.Slug);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<Show> GetShow(ILibraryManager libraryManager,
|
||||
@ -178,10 +199,18 @@ namespace Kyoo.Controllers
|
||||
show = await _metadataProvider.SearchShow(showTitle, isMovie, library);
|
||||
show.Path = showPath;
|
||||
show.People = await _metadataProvider.GetPeople(show, library);
|
||||
await libraryManager.RegisterShow(show);
|
||||
await _thumbnailsManager.Validate(show.People);
|
||||
await _thumbnailsManager.Validate(show);
|
||||
return show;
|
||||
|
||||
try
|
||||
{
|
||||
await libraryManager.RegisterShow(show);
|
||||
await _thumbnailsManager.Validate(show.People);
|
||||
await _thumbnailsManager.Validate(show);
|
||||
return show;
|
||||
}
|
||||
catch (DuplicatedItemException)
|
||||
{
|
||||
return await libraryManager.GetShow(show.Slug);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<Season> GetSeason(ILibraryManager libraryManager,
|
||||
@ -195,8 +224,15 @@ namespace Kyoo.Controllers
|
||||
if (season == null)
|
||||
{
|
||||
season = await _metadataProvider.GetSeason(show, seasonNumber, library);
|
||||
await libraryManager.RegisterSeason(season);
|
||||
await _thumbnailsManager.Validate(season);
|
||||
try
|
||||
{
|
||||
await libraryManager.RegisterSeason(season);
|
||||
await _thumbnailsManager.Validate(season);
|
||||
}
|
||||
catch (DuplicatedItemException)
|
||||
{
|
||||
season = await libraryManager.GetSeason(show.Slug, season.SeasonNumber);
|
||||
}
|
||||
}
|
||||
season.Show = show;
|
||||
return season;
|
||||
|
@ -7,12 +7,14 @@
|
||||
"LogLevel": {
|
||||
"Default": "Warning",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
"Microsoft.Hosting.Lifetime": "Information",
|
||||
"Microsoft.EntityFrameworkCore.DbUpdateException": "None",
|
||||
"Microsoft.EntityFrameworkCore.Update": "None"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*",
|
||||
"ConnectionStrings": {
|
||||
"Database": "Server=127.0.0.1; Port=5432; Database=kyooDB; User Id=kyoo; Password=kyooPassword;"
|
||||
"Database": "Server=127.0.0.1; Port=5432; Database=kyooDB; User Id=kyoo; Password=kyooPassword; Pooling=true; MaxPoolSize=60;"
|
||||
},
|
||||
|
||||
"scheduledTasks": {
|
||||
|
Loading…
x
Reference in New Issue
Block a user