|
|
|
@ -1,6 +1,10 @@ |
|
|
|
using Dapper; |
|
|
|
using Dapper; |
|
|
|
|
|
|
|
using ErsatzTV.Core; |
|
|
|
using ErsatzTV.Core.Domain; |
|
|
|
using ErsatzTV.Core.Domain; |
|
|
|
|
|
|
|
using ErsatzTV.Core.Emby; |
|
|
|
using ErsatzTV.Core.Interfaces.Repositories; |
|
|
|
using ErsatzTV.Core.Interfaces.Repositories; |
|
|
|
|
|
|
|
using ErsatzTV.Core.Jellyfin; |
|
|
|
|
|
|
|
using ErsatzTV.Infrastructure.Extensions; |
|
|
|
using Microsoft.EntityFrameworkCore; |
|
|
|
using Microsoft.EntityFrameworkCore; |
|
|
|
|
|
|
|
|
|
|
|
namespace ErsatzTV.Infrastructure.Data.Repositories; |
|
|
|
namespace ErsatzTV.Infrastructure.Data.Repositories; |
|
|
|
@ -159,26 +163,50 @@ public class MediaSourceRepository : IMediaSourceRepository |
|
|
|
public async Task<List<int>> UpdateLibraries( |
|
|
|
public async Task<List<int>> UpdateLibraries( |
|
|
|
int jellyfinMediaSourceId, |
|
|
|
int jellyfinMediaSourceId, |
|
|
|
List<JellyfinLibrary> toAdd, |
|
|
|
List<JellyfinLibrary> toAdd, |
|
|
|
List<JellyfinLibrary> toDelete) |
|
|
|
List<JellyfinLibrary> toDelete, |
|
|
|
|
|
|
|
List<JellyfinLibrary> toUpdate) |
|
|
|
{ |
|
|
|
{ |
|
|
|
await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(); |
|
|
|
await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(); |
|
|
|
|
|
|
|
|
|
|
|
foreach (JellyfinLibrary add in toAdd) |
|
|
|
foreach (JellyfinLibrary add in toAdd) |
|
|
|
{ |
|
|
|
{ |
|
|
|
add.MediaSourceId = jellyfinMediaSourceId; |
|
|
|
add.MediaSourceId = jellyfinMediaSourceId; |
|
|
|
dbContext.Entry(add).State = EntityState.Added; |
|
|
|
dbContext.JellyfinLibraries.Add(add); |
|
|
|
foreach (LibraryPath path in add.Paths) |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
dbContext.JellyfinLibraries.RemoveRange(toDelete); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
List<int> ids = await DisableJellyfinLibrarySync(toDelete.Map(l => l.Id).ToList()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
foreach (JellyfinLibrary incoming in toUpdate) |
|
|
|
{ |
|
|
|
{ |
|
|
|
dbContext.Entry(path).State = EntityState.Added; |
|
|
|
Option<JellyfinLibrary> maybeExisting = await dbContext.JellyfinLibraries |
|
|
|
|
|
|
|
.Include(l => l.PathInfos) |
|
|
|
|
|
|
|
.SelectOneAsync(l => l.ItemId, l => l.ItemId == incoming.ItemId); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
foreach (JellyfinLibrary existing in maybeExisting) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// remove paths that are not on the incoming version
|
|
|
|
|
|
|
|
existing.PathInfos.RemoveAll(pi => incoming.PathInfos.All(upi => upi.Path != pi.Path)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// update all remaining paths
|
|
|
|
|
|
|
|
foreach (JellyfinPathInfo existingPathInfo in existing.PathInfos) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
Option<JellyfinPathInfo> maybeIncoming = incoming.PathInfos |
|
|
|
|
|
|
|
.Find(pi => pi.Path == existingPathInfo.Path); |
|
|
|
|
|
|
|
foreach (JellyfinPathInfo incomingPathInfo in maybeIncoming) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
existingPathInfo.NetworkPath = incomingPathInfo.NetworkPath; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
foreach (JellyfinLibrary delete in toDelete) |
|
|
|
foreach (JellyfinPathInfo incomingPathInfo in incoming.PathInfos |
|
|
|
|
|
|
|
.Filter(pi => existing.PathInfos.All(epi => epi.Path != pi.Path))) |
|
|
|
{ |
|
|
|
{ |
|
|
|
dbContext.Entry(delete).State = EntityState.Deleted; |
|
|
|
existing.PathInfos.Add(incomingPathInfo); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
List<int> ids = await DisableJellyfinLibrarySync(toDelete.Map(l => l.Id).ToList()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
await dbContext.SaveChangesAsync(); |
|
|
|
await dbContext.SaveChangesAsync(); |
|
|
|
|
|
|
|
|
|
|
|
@ -188,26 +216,50 @@ public class MediaSourceRepository : IMediaSourceRepository |
|
|
|
public async Task<List<int>> UpdateLibraries( |
|
|
|
public async Task<List<int>> UpdateLibraries( |
|
|
|
int embyMediaSourceId, |
|
|
|
int embyMediaSourceId, |
|
|
|
List<EmbyLibrary> toAdd, |
|
|
|
List<EmbyLibrary> toAdd, |
|
|
|
List<EmbyLibrary> toDelete) |
|
|
|
List<EmbyLibrary> toDelete, |
|
|
|
|
|
|
|
List<EmbyLibrary> toUpdate) |
|
|
|
{ |
|
|
|
{ |
|
|
|
await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(); |
|
|
|
await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(); |
|
|
|
|
|
|
|
|
|
|
|
foreach (EmbyLibrary add in toAdd) |
|
|
|
foreach (EmbyLibrary add in toAdd) |
|
|
|
{ |
|
|
|
{ |
|
|
|
add.MediaSourceId = embyMediaSourceId; |
|
|
|
add.MediaSourceId = embyMediaSourceId; |
|
|
|
dbContext.Entry(add).State = EntityState.Added; |
|
|
|
dbContext.EmbyLibraries.Add(add); |
|
|
|
foreach (LibraryPath path in add.Paths) |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
dbContext.EmbyLibraries.RemoveRange(toDelete); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
List<int> ids = await DisableEmbyLibrarySync(toDelete.Map(l => l.Id).ToList()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
foreach (EmbyLibrary incoming in toUpdate) |
|
|
|
{ |
|
|
|
{ |
|
|
|
dbContext.Entry(path).State = EntityState.Added; |
|
|
|
Option<EmbyLibrary> maybeExisting = await dbContext.EmbyLibraries |
|
|
|
|
|
|
|
.Include(l => l.PathInfos) |
|
|
|
|
|
|
|
.SelectOneAsync(l => l.ItemId, l => l.ItemId == incoming.ItemId); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
foreach (EmbyLibrary existing in maybeExisting) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// remove paths that are not on the incoming version
|
|
|
|
|
|
|
|
existing.PathInfos.RemoveAll(pi => incoming.PathInfos.All(upi => upi.Path != pi.Path)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// update all remaining paths
|
|
|
|
|
|
|
|
foreach (EmbyPathInfo existingPathInfo in existing.PathInfos) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
Option<EmbyPathInfo> maybeIncoming = incoming.PathInfos |
|
|
|
|
|
|
|
.Find(pi => pi.Path == existingPathInfo.Path); |
|
|
|
|
|
|
|
foreach (EmbyPathInfo incomingPathInfo in maybeIncoming) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
existingPathInfo.NetworkPath = incomingPathInfo.NetworkPath; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
foreach (EmbyLibrary delete in toDelete) |
|
|
|
foreach (EmbyPathInfo incomingPathInfo in incoming.PathInfos |
|
|
|
|
|
|
|
.Filter(pi => existing.PathInfos.All(epi => epi.Path != pi.Path))) |
|
|
|
{ |
|
|
|
{ |
|
|
|
dbContext.Entry(delete).State = EntityState.Deleted; |
|
|
|
existing.PathInfos.Add(incomingPathInfo); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
List<int> ids = await DisableEmbyLibrarySync(toDelete.Map(l => l.Id).ToList()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
await dbContext.SaveChangesAsync(); |
|
|
|
await dbContext.SaveChangesAsync(); |
|
|
|
|
|
|
|
|
|
|
|
@ -259,14 +311,16 @@ public class MediaSourceRepository : IMediaSourceRepository |
|
|
|
|
|
|
|
|
|
|
|
List<PlexLibrary> allPlexLibraries = await dbContext.PlexLibraries.ToListAsync(); |
|
|
|
List<PlexLibrary> allPlexLibraries = await dbContext.PlexLibraries.ToListAsync(); |
|
|
|
dbContext.PlexLibraries.RemoveRange(allPlexLibraries); |
|
|
|
dbContext.PlexLibraries.RemoveRange(allPlexLibraries); |
|
|
|
|
|
|
|
var libraryIds = allPlexLibraries.Map(l => l.Id).ToList(); |
|
|
|
|
|
|
|
|
|
|
|
List<int> movieIds = await dbContext.PlexMovies.Map(pm => pm.Id).ToListAsync(); |
|
|
|
List<int> deletedMediaIds = await dbContext.MediaItems |
|
|
|
List<int> showIds = await dbContext.PlexShows.Map(ps => ps.Id).ToListAsync(); |
|
|
|
.Filter(mi => libraryIds.Contains(mi.LibraryPath.LibraryId)) |
|
|
|
List<int> episodeIds = await dbContext.PlexEpisodes.Map(pe => pe.Id).ToListAsync(); |
|
|
|
.Map(mi => mi.Id) |
|
|
|
|
|
|
|
.ToListAsync(); |
|
|
|
|
|
|
|
|
|
|
|
await dbContext.SaveChangesAsync(); |
|
|
|
await dbContext.SaveChangesAsync(); |
|
|
|
|
|
|
|
|
|
|
|
return movieIds.Append(showIds).Append(episodeIds).ToList(); |
|
|
|
return deletedMediaIds; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public async Task<List<int>> DeletePlex(PlexMediaSource plexMediaSource) |
|
|
|
public async Task<List<int>> DeletePlex(PlexMediaSource plexMediaSource) |
|
|
|
@ -292,83 +346,30 @@ public class MediaSourceRepository : IMediaSourceRepository |
|
|
|
{ |
|
|
|
{ |
|
|
|
await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(); |
|
|
|
await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(); |
|
|
|
|
|
|
|
|
|
|
|
await dbContext.Connection.ExecuteAsync( |
|
|
|
List<int> deletedMediaIds = await dbContext.MediaItems |
|
|
|
"UPDATE PlexLibrary SET ShouldSyncItems = 0 WHERE Id IN @ids", |
|
|
|
.Filter(mi => libraryIds.Contains(mi.LibraryPath.LibraryId)) |
|
|
|
new { ids = libraryIds }); |
|
|
|
.Map(mi => mi.Id) |
|
|
|
|
|
|
|
.ToListAsync(); |
|
|
|
await dbContext.Connection.ExecuteAsync( |
|
|
|
|
|
|
|
"UPDATE Library SET LastScan = null WHERE Id IN @ids", |
|
|
|
|
|
|
|
new { ids = libraryIds }); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
List<int> movieIds = await dbContext.Connection.QueryAsync<int>( |
|
|
|
|
|
|
|
@"SELECT m.Id FROM MediaItem m
|
|
|
|
|
|
|
|
INNER JOIN PlexMovie pm ON pm.Id = m.Id |
|
|
|
|
|
|
|
INNER JOIN LibraryPath lp ON lp.Id = m.LibraryPathId |
|
|
|
|
|
|
|
INNER JOIN Library l ON l.Id = lp.LibraryId |
|
|
|
|
|
|
|
WHERE l.Id IN @ids",
|
|
|
|
|
|
|
|
new { ids = libraryIds }).Map(result => result.ToList()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
await dbContext.Connection.ExecuteAsync( |
|
|
|
|
|
|
|
@"DELETE FROM MediaItem WHERE Id IN
|
|
|
|
|
|
|
|
(SELECT m.Id FROM MediaItem m |
|
|
|
|
|
|
|
INNER JOIN PlexMovie pm ON pm.Id = m.Id |
|
|
|
|
|
|
|
INNER JOIN LibraryPath lp ON lp.Id = m.LibraryPathId |
|
|
|
|
|
|
|
INNER JOIN Library l ON l.Id = lp.LibraryId |
|
|
|
|
|
|
|
WHERE l.Id IN @ids)",
|
|
|
|
|
|
|
|
new { ids = libraryIds }); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
List<int> episodeIds = await dbContext.Connection.QueryAsync<int>( |
|
|
|
|
|
|
|
@"SELECT m.Id FROM MediaItem m
|
|
|
|
|
|
|
|
INNER JOIN PlexEpisode pe ON pe.Id = m.Id |
|
|
|
|
|
|
|
INNER JOIN LibraryPath lp ON lp.Id = m.LibraryPathId |
|
|
|
|
|
|
|
INNER JOIN Library l ON l.Id = lp.LibraryId |
|
|
|
|
|
|
|
WHERE l.Id IN @ids",
|
|
|
|
|
|
|
|
new { ids = libraryIds }).Map(result => result.ToList()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
await dbContext.Connection.ExecuteAsync( |
|
|
|
|
|
|
|
@"DELETE FROM MediaItem WHERE Id IN
|
|
|
|
|
|
|
|
(SELECT m.Id FROM MediaItem m |
|
|
|
|
|
|
|
INNER JOIN PlexEpisode pe ON pe.Id = m.Id |
|
|
|
|
|
|
|
INNER JOIN LibraryPath lp ON lp.Id = m.LibraryPathId |
|
|
|
|
|
|
|
INNER JOIN Library l ON l.Id = lp.LibraryId |
|
|
|
|
|
|
|
WHERE l.Id IN @ids)",
|
|
|
|
|
|
|
|
new { ids = libraryIds }); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
List<int> seasonIds = await dbContext.Connection.QueryAsync<int>( |
|
|
|
List<PlexLibrary> libraries = await dbContext.PlexLibraries |
|
|
|
@"SELECT m.Id FROM MediaItem m
|
|
|
|
.Include(l => l.Paths) |
|
|
|
INNER JOIN PlexSeason ps ON ps.Id = m.Id |
|
|
|
.Filter(l => libraryIds.Contains(l.Id)) |
|
|
|
INNER JOIN LibraryPath lp ON lp.Id = m.LibraryPathId |
|
|
|
.ToListAsync(); |
|
|
|
INNER JOIN Library l ON l.Id = lp.LibraryId |
|
|
|
|
|
|
|
WHERE l.Id IN @ids",
|
|
|
|
|
|
|
|
new { ids = libraryIds }).Map(result => result.ToList()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
await dbContext.Connection.ExecuteAsync( |
|
|
|
dbContext.PlexLibraries.RemoveRange(libraries); |
|
|
|
@"DELETE FROM MediaItem WHERE Id IN
|
|
|
|
await dbContext.SaveChangesAsync(); |
|
|
|
(SELECT m.Id FROM MediaItem m |
|
|
|
|
|
|
|
INNER JOIN PlexSeason ps ON ps.Id = m.Id |
|
|
|
|
|
|
|
INNER JOIN LibraryPath lp ON lp.Id = m.LibraryPathId |
|
|
|
|
|
|
|
INNER JOIN Library l ON l.Id = lp.LibraryId |
|
|
|
|
|
|
|
WHERE l.Id IN @ids)",
|
|
|
|
|
|
|
|
new { ids = libraryIds }); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
List<int> showIds = await dbContext.Connection.QueryAsync<int>( |
|
|
|
foreach (PlexLibrary library in libraries) |
|
|
|
@"SELECT m.Id FROM MediaItem m
|
|
|
|
{ |
|
|
|
INNER JOIN PlexShow ps ON ps.Id = m.Id |
|
|
|
library.Id = 0; |
|
|
|
INNER JOIN LibraryPath lp ON lp.Id = m.LibraryPathId |
|
|
|
library.ShouldSyncItems = false; |
|
|
|
INNER JOIN Library l ON l.Id = lp.LibraryId |
|
|
|
library.LastScan = SystemTime.MinValueUtc; |
|
|
|
WHERE l.Id IN @ids",
|
|
|
|
} |
|
|
|
new { ids = libraryIds }).Map(result => result.ToList()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
await dbContext.Connection.ExecuteAsync( |
|
|
|
await dbContext.PlexLibraries.AddRangeAsync(libraries); |
|
|
|
@"DELETE FROM MediaItem WHERE Id IN
|
|
|
|
await dbContext.SaveChangesAsync(); |
|
|
|
(SELECT m.Id FROM MediaItem m |
|
|
|
|
|
|
|
INNER JOIN PlexShow ps ON ps.Id = m.Id |
|
|
|
|
|
|
|
INNER JOIN LibraryPath lp ON lp.Id = m.LibraryPathId |
|
|
|
|
|
|
|
INNER JOIN Library l ON l.Id = lp.LibraryId |
|
|
|
|
|
|
|
WHERE l.Id IN @ids)",
|
|
|
|
|
|
|
|
new { ids = libraryIds }); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return movieIds.Append(showIds).Append(seasonIds).Append(episodeIds).ToList(); |
|
|
|
return deletedMediaIds; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public async Task EnablePlexLibrarySync(IEnumerable<int> libraryIds) |
|
|
|
public async Task EnablePlexLibrarySync(IEnumerable<int> libraryIds) |
|
|
|
@ -447,6 +448,7 @@ public class MediaSourceRepository : IMediaSourceRepository |
|
|
|
return await context.JellyfinMediaSources |
|
|
|
return await context.JellyfinMediaSources |
|
|
|
.Include(p => p.Connections) |
|
|
|
.Include(p => p.Connections) |
|
|
|
.Include(p => p.Libraries) |
|
|
|
.Include(p => p.Libraries) |
|
|
|
|
|
|
|
.ThenInclude(l => (l as JellyfinLibrary).PathInfos) |
|
|
|
.Include(p => p.PathReplacements) |
|
|
|
.Include(p => p.PathReplacements) |
|
|
|
.OrderBy(s => s.Id) // https://github.com/dotnet/efcore/issues/22579
|
|
|
|
.OrderBy(s => s.Id) // https://github.com/dotnet/efcore/issues/22579
|
|
|
|
.SingleOrDefaultAsync(p => p.Id == id) |
|
|
|
.SingleOrDefaultAsync(p => p.Id == id) |
|
|
|
@ -473,83 +475,31 @@ public class MediaSourceRepository : IMediaSourceRepository |
|
|
|
{ |
|
|
|
{ |
|
|
|
await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(); |
|
|
|
await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(); |
|
|
|
|
|
|
|
|
|
|
|
await dbContext.Connection.ExecuteAsync( |
|
|
|
List<int> deletedMediaIds = await dbContext.MediaItems |
|
|
|
"UPDATE JellyfinLibrary SET ShouldSyncItems = 0 WHERE Id IN @ids", |
|
|
|
.Filter(mi => libraryIds.Contains(mi.LibraryPath.LibraryId)) |
|
|
|
new { ids = libraryIds }); |
|
|
|
.Map(mi => mi.Id) |
|
|
|
|
|
|
|
.ToListAsync(); |
|
|
|
await dbContext.Connection.ExecuteAsync( |
|
|
|
|
|
|
|
"UPDATE Library SET LastScan = null WHERE Id IN @ids", |
|
|
|
|
|
|
|
new { ids = libraryIds }); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
List<int> movieIds = await dbContext.Connection.QueryAsync<int>( |
|
|
|
|
|
|
|
@"SELECT m.Id FROM MediaItem m
|
|
|
|
|
|
|
|
INNER JOIN JellyfinMovie pm ON pm.Id = m.Id |
|
|
|
|
|
|
|
INNER JOIN LibraryPath lp ON lp.Id = m.LibraryPathId |
|
|
|
|
|
|
|
INNER JOIN Library l ON l.Id = lp.LibraryId |
|
|
|
|
|
|
|
WHERE l.Id IN @ids",
|
|
|
|
|
|
|
|
new { ids = libraryIds }).Map(result => result.ToList()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
await dbContext.Connection.ExecuteAsync( |
|
|
|
|
|
|
|
@"DELETE FROM MediaItem WHERE Id IN
|
|
|
|
|
|
|
|
(SELECT m.Id FROM MediaItem m |
|
|
|
|
|
|
|
INNER JOIN JellyfinMovie pm ON pm.Id = m.Id |
|
|
|
|
|
|
|
INNER JOIN LibraryPath lp ON lp.Id = m.LibraryPathId |
|
|
|
|
|
|
|
INNER JOIN Library l ON l.Id = lp.LibraryId |
|
|
|
|
|
|
|
WHERE l.Id IN @ids)",
|
|
|
|
|
|
|
|
new { ids = libraryIds }); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
List<int> episodeIds = await dbContext.Connection.QueryAsync<int>( |
|
|
|
|
|
|
|
@"SELECT m.Id FROM MediaItem m
|
|
|
|
|
|
|
|
INNER JOIN JellyfinEpisode pe ON pe.Id = m.Id |
|
|
|
|
|
|
|
INNER JOIN LibraryPath lp ON lp.Id = m.LibraryPathId |
|
|
|
|
|
|
|
INNER JOIN Library l ON l.Id = lp.LibraryId |
|
|
|
|
|
|
|
WHERE l.Id IN @ids",
|
|
|
|
|
|
|
|
new { ids = libraryIds }).Map(result => result.ToList()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
await dbContext.Connection.ExecuteAsync( |
|
|
|
|
|
|
|
@"DELETE FROM MediaItem WHERE Id IN
|
|
|
|
|
|
|
|
(SELECT m.Id FROM MediaItem m |
|
|
|
|
|
|
|
INNER JOIN JellyfinEpisode pe ON pe.Id = m.Id |
|
|
|
|
|
|
|
INNER JOIN LibraryPath lp ON lp.Id = m.LibraryPathId |
|
|
|
|
|
|
|
INNER JOIN Library l ON l.Id = lp.LibraryId |
|
|
|
|
|
|
|
WHERE l.Id IN @ids)",
|
|
|
|
|
|
|
|
new { ids = libraryIds }); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
List<int> seasonIds = await dbContext.Connection.QueryAsync<int>( |
|
|
|
List<JellyfinLibrary> libraries = await dbContext.JellyfinLibraries |
|
|
|
@"SELECT m.Id FROM MediaItem m
|
|
|
|
.Include(l => l.Paths) |
|
|
|
INNER JOIN JellyfinSeason js ON js.Id = m.Id |
|
|
|
.Include(l => l.PathInfos) |
|
|
|
INNER JOIN LibraryPath lp ON lp.Id = m.LibraryPathId |
|
|
|
.Filter(l => libraryIds.Contains(l.Id)) |
|
|
|
INNER JOIN Library l ON l.Id = lp.LibraryId |
|
|
|
.ToListAsync(); |
|
|
|
WHERE l.Id IN @ids",
|
|
|
|
|
|
|
|
new { ids = libraryIds }).Map(result => result.ToList()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
await dbContext.Connection.ExecuteAsync( |
|
|
|
dbContext.JellyfinLibraries.RemoveRange(libraries); |
|
|
|
@"DELETE FROM MediaItem WHERE Id IN
|
|
|
|
await dbContext.SaveChangesAsync(); |
|
|
|
(SELECT m.Id FROM MediaItem m |
|
|
|
|
|
|
|
INNER JOIN JellyfinSeason ps ON ps.Id = m.Id |
|
|
|
|
|
|
|
INNER JOIN LibraryPath lp ON lp.Id = m.LibraryPathId |
|
|
|
|
|
|
|
INNER JOIN Library l ON l.Id = lp.LibraryId |
|
|
|
|
|
|
|
WHERE l.Id IN @ids)",
|
|
|
|
|
|
|
|
new { ids = libraryIds }); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
List<int> showIds = await dbContext.Connection.QueryAsync<int>( |
|
|
|
foreach (JellyfinLibrary library in libraries) |
|
|
|
@"SELECT m.Id FROM MediaItem m
|
|
|
|
{ |
|
|
|
INNER JOIN JellyfinShow ps ON ps.Id = m.Id |
|
|
|
library.Id = 0; |
|
|
|
INNER JOIN LibraryPath lp ON lp.Id = m.LibraryPathId |
|
|
|
library.ShouldSyncItems = false; |
|
|
|
INNER JOIN Library l ON l.Id = lp.LibraryId |
|
|
|
library.LastScan = SystemTime.MinValueUtc; |
|
|
|
WHERE l.Id IN @ids",
|
|
|
|
} |
|
|
|
new { ids = libraryIds }).Map(result => result.ToList()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
await dbContext.Connection.ExecuteAsync( |
|
|
|
await dbContext.JellyfinLibraries.AddRangeAsync(libraries); |
|
|
|
@"DELETE FROM MediaItem WHERE Id IN
|
|
|
|
await dbContext.SaveChangesAsync(); |
|
|
|
(SELECT m.Id FROM MediaItem m |
|
|
|
|
|
|
|
INNER JOIN JellyfinShow ps ON ps.Id = m.Id |
|
|
|
|
|
|
|
INNER JOIN LibraryPath lp ON lp.Id = m.LibraryPathId |
|
|
|
|
|
|
|
INNER JOIN Library l ON l.Id = lp.LibraryId |
|
|
|
|
|
|
|
WHERE l.Id IN @ids)",
|
|
|
|
|
|
|
|
new { ids = libraryIds }); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return movieIds.Append(showIds).Append(seasonIds).Append(episodeIds).ToList(); |
|
|
|
return deletedMediaIds; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public async Task<Option<JellyfinLibrary>> GetJellyfinLibrary(int jellyfinLibraryId) |
|
|
|
public async Task<Option<JellyfinLibrary>> GetJellyfinLibrary(int jellyfinLibraryId) |
|
|
|
@ -557,6 +507,8 @@ public class MediaSourceRepository : IMediaSourceRepository |
|
|
|
await using TvContext context = await _dbContextFactory.CreateDbContextAsync(); |
|
|
|
await using TvContext context = await _dbContextFactory.CreateDbContextAsync(); |
|
|
|
return await context.JellyfinLibraries |
|
|
|
return await context.JellyfinLibraries |
|
|
|
.Include(l => l.Paths) |
|
|
|
.Include(l => l.Paths) |
|
|
|
|
|
|
|
.Include(l => l.PathInfos) |
|
|
|
|
|
|
|
.Include(l => l.MediaSource) |
|
|
|
.OrderBy(l => l.Id) // https://github.com/dotnet/efcore/issues/22579
|
|
|
|
.OrderBy(l => l.Id) // https://github.com/dotnet/efcore/issues/22579
|
|
|
|
.SingleOrDefaultAsync(l => l.Id == jellyfinLibraryId) |
|
|
|
.SingleOrDefaultAsync(l => l.Id == jellyfinLibraryId) |
|
|
|
.Map(Optional); |
|
|
|
.Map(Optional); |
|
|
|
@ -654,24 +606,14 @@ public class MediaSourceRepository : IMediaSourceRepository |
|
|
|
var libraryIds = allJellyfinLibraries.Map(l => l.Id).ToList(); |
|
|
|
var libraryIds = allJellyfinLibraries.Map(l => l.Id).ToList(); |
|
|
|
dbContext.JellyfinLibraries.RemoveRange(allJellyfinLibraries); |
|
|
|
dbContext.JellyfinLibraries.RemoveRange(allJellyfinLibraries); |
|
|
|
|
|
|
|
|
|
|
|
List<int> movieIds = await dbContext.JellyfinMovies |
|
|
|
List<int> deletedMediaIds = await dbContext.MediaItems |
|
|
|
.Where(m => libraryIds.Contains(m.LibraryPath.LibraryId)) |
|
|
|
.Filter(mi => libraryIds.Contains(mi.LibraryPath.LibraryId)) |
|
|
|
.Map(pm => pm.Id) |
|
|
|
.Map(mi => mi.Id) |
|
|
|
.ToListAsync(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
List<int> showIds = await dbContext.JellyfinShows |
|
|
|
|
|
|
|
.Where(m => libraryIds.Contains(m.LibraryPath.LibraryId)) |
|
|
|
|
|
|
|
.Map(ps => ps.Id) |
|
|
|
|
|
|
|
.ToListAsync(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
List<int> episodeIds = await dbContext.JellyfinEpisodes |
|
|
|
|
|
|
|
.Where(m => libraryIds.Contains(m.LibraryPath.LibraryId)) |
|
|
|
|
|
|
|
.Map(ps => ps.Id) |
|
|
|
|
|
|
|
.ToListAsync(); |
|
|
|
.ToListAsync(); |
|
|
|
|
|
|
|
|
|
|
|
await dbContext.SaveChangesAsync(); |
|
|
|
await dbContext.SaveChangesAsync(); |
|
|
|
|
|
|
|
|
|
|
|
return movieIds.Append(showIds).Append(episodeIds).ToList(); |
|
|
|
return deletedMediaIds; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public async Task<Unit> UpsertEmby(string address, string serverName, string operatingSystem) |
|
|
|
public async Task<Unit> UpsertEmby(string address, string serverName, string operatingSystem) |
|
|
|
@ -742,10 +684,9 @@ public class MediaSourceRepository : IMediaSourceRepository |
|
|
|
return await context.EmbyMediaSources |
|
|
|
return await context.EmbyMediaSources |
|
|
|
.Include(p => p.Connections) |
|
|
|
.Include(p => p.Connections) |
|
|
|
.Include(p => p.Libraries) |
|
|
|
.Include(p => p.Libraries) |
|
|
|
|
|
|
|
.ThenInclude(l => (l as EmbyLibrary).PathInfos) |
|
|
|
.Include(p => p.PathReplacements) |
|
|
|
.Include(p => p.PathReplacements) |
|
|
|
.OrderBy(s => s.Id) // https://github.com/dotnet/efcore/issues/22579
|
|
|
|
.SelectOneAsync(s => s.Id, s => s.Id == id); |
|
|
|
.SingleOrDefaultAsync(p => p.Id == id) |
|
|
|
|
|
|
|
.Map(Optional); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public async Task<Option<EmbyMediaSource>> GetEmbyByLibraryId(int embyLibraryId) |
|
|
|
public async Task<Option<EmbyMediaSource>> GetEmbyByLibraryId(int embyLibraryId) |
|
|
|
@ -771,9 +712,9 @@ public class MediaSourceRepository : IMediaSourceRepository |
|
|
|
await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(); |
|
|
|
await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(); |
|
|
|
return await dbContext.EmbyLibraries |
|
|
|
return await dbContext.EmbyLibraries |
|
|
|
.Include(l => l.Paths) |
|
|
|
.Include(l => l.Paths) |
|
|
|
.OrderBy(l => l.Id) // https://github.com/dotnet/efcore/issues/22579
|
|
|
|
.Include(l => l.PathInfos) |
|
|
|
.SingleOrDefaultAsync(l => l.Id == embyLibraryId) |
|
|
|
.Include(l => l.MediaSource) |
|
|
|
.Map(Optional); |
|
|
|
.SelectOneAsync(l => l.Id, l => l.Id == embyLibraryId); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public async Task<List<EmbyLibrary>> GetEmbyLibraries(int embyMediaSourceId) |
|
|
|
public async Task<List<EmbyLibrary>> GetEmbyLibraries(int embyMediaSourceId) |
|
|
|
@ -858,24 +799,14 @@ public class MediaSourceRepository : IMediaSourceRepository |
|
|
|
var libraryIds = allEmbyLibraries.Map(l => l.Id).ToList(); |
|
|
|
var libraryIds = allEmbyLibraries.Map(l => l.Id).ToList(); |
|
|
|
dbContext.EmbyLibraries.RemoveRange(allEmbyLibraries); |
|
|
|
dbContext.EmbyLibraries.RemoveRange(allEmbyLibraries); |
|
|
|
|
|
|
|
|
|
|
|
List<int> movieIds = await dbContext.EmbyMovies |
|
|
|
List<int> deletedMediaIds = await dbContext.MediaItems |
|
|
|
.Where(m => libraryIds.Contains(m.LibraryPath.LibraryId)) |
|
|
|
.Filter(mi => libraryIds.Contains(mi.LibraryPath.LibraryId)) |
|
|
|
.Map(pm => pm.Id) |
|
|
|
.Map(mi => mi.Id) |
|
|
|
.ToListAsync(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
List<int> showIds = await dbContext.EmbyShows |
|
|
|
|
|
|
|
.Where(m => libraryIds.Contains(m.LibraryPath.LibraryId)) |
|
|
|
|
|
|
|
.Map(ps => ps.Id) |
|
|
|
|
|
|
|
.ToListAsync(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
List<int> episodeIds = await dbContext.EmbyEpisodes |
|
|
|
|
|
|
|
.Where(m => libraryIds.Contains(m.LibraryPath.LibraryId)) |
|
|
|
|
|
|
|
.Map(ps => ps.Id) |
|
|
|
|
|
|
|
.ToListAsync(); |
|
|
|
.ToListAsync(); |
|
|
|
|
|
|
|
|
|
|
|
await dbContext.SaveChangesAsync(); |
|
|
|
await dbContext.SaveChangesAsync(); |
|
|
|
|
|
|
|
|
|
|
|
return movieIds.Append(showIds).Append(episodeIds).ToList(); |
|
|
|
return deletedMediaIds; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public async Task<Unit> EnableEmbyLibrarySync(IEnumerable<int> libraryIds) |
|
|
|
public async Task<Unit> EnableEmbyLibrarySync(IEnumerable<int> libraryIds) |
|
|
|
@ -890,122 +821,30 @@ public class MediaSourceRepository : IMediaSourceRepository |
|
|
|
{ |
|
|
|
{ |
|
|
|
await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(); |
|
|
|
await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(); |
|
|
|
|
|
|
|
|
|
|
|
await dbContext.Connection.ExecuteAsync( |
|
|
|
List<int> deletedMediaIds = await dbContext.MediaItems |
|
|
|
"UPDATE EmbyLibrary SET ShouldSyncItems = 0 WHERE Id IN @ids", |
|
|
|
.Filter(mi => libraryIds.Contains(mi.LibraryPath.LibraryId)) |
|
|
|
new { ids = libraryIds }); |
|
|
|
.Map(mi => mi.Id) |
|
|
|
|
|
|
|
.ToListAsync(); |
|
|
|
await dbContext.Connection.ExecuteAsync( |
|
|
|
|
|
|
|
"UPDATE Library SET LastScan = null WHERE Id IN @ids", |
|
|
|
|
|
|
|
new { ids = libraryIds }); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
List<int> movieIds = await dbContext.Connection.QueryAsync<int>( |
|
|
|
|
|
|
|
@"SELECT m.Id FROM MediaItem m
|
|
|
|
|
|
|
|
INNER JOIN EmbyMovie pm ON pm.Id = m.Id |
|
|
|
|
|
|
|
INNER JOIN LibraryPath lp ON lp.Id = m.LibraryPathId AND lp.LibraryId IN @ids",
|
|
|
|
|
|
|
|
new { ids = libraryIds }).Map(result => result.ToList()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
await dbContext.Connection.ExecuteAsync( |
|
|
|
|
|
|
|
@"DELETE FROM EmbyMovie WHERE Id IN
|
|
|
|
|
|
|
|
(SELECT m.Id FROM MediaItem m |
|
|
|
|
|
|
|
INNER JOIN EmbyMovie pm ON pm.Id = m.Id |
|
|
|
|
|
|
|
INNER JOIN LibraryPath lp ON lp.Id = m.LibraryPathId AND lp.LibraryId IN @ids)",
|
|
|
|
|
|
|
|
new { ids = libraryIds }); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
await dbContext.Connection.ExecuteAsync( |
|
|
|
|
|
|
|
@"DELETE FROM Movie WHERE Id IN
|
|
|
|
|
|
|
|
(SELECT m.Id FROM MediaItem m |
|
|
|
|
|
|
|
INNER JOIN EmbyMovie pm ON pm.Id = m.Id |
|
|
|
|
|
|
|
INNER JOIN LibraryPath lp ON lp.Id = m.LibraryPathId AND lp.LibraryId IN @ids)",
|
|
|
|
|
|
|
|
new { ids = libraryIds }); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
await dbContext.Connection.ExecuteAsync( |
|
|
|
|
|
|
|
@"DELETE FROM MediaItem WHERE Id IN
|
|
|
|
|
|
|
|
(SELECT m.Id FROM MediaItem m |
|
|
|
|
|
|
|
INNER JOIN EmbyMovie pm ON pm.Id = m.Id |
|
|
|
|
|
|
|
INNER JOIN LibraryPath lp ON lp.Id = m.LibraryPathId AND lp.LibraryId IN @ids)",
|
|
|
|
|
|
|
|
new { ids = libraryIds }); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
List<int> episodeIds = await dbContext.Connection.QueryAsync<int>( |
|
|
|
|
|
|
|
@"SELECT m.Id FROM MediaItem m
|
|
|
|
|
|
|
|
INNER JOIN EmbyEpisode pe ON pe.Id = m.Id |
|
|
|
|
|
|
|
INNER JOIN LibraryPath lp ON lp.Id = m.LibraryPathId AND lp.LibraryId IN @ids",
|
|
|
|
|
|
|
|
new { ids = libraryIds }).Map(result => result.ToList()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
await dbContext.Connection.ExecuteAsync( |
|
|
|
|
|
|
|
@"DELETE FROM EmbyEpisode WHERE Id IN
|
|
|
|
|
|
|
|
(SELECT m.Id FROM MediaItem m |
|
|
|
|
|
|
|
INNER JOIN EmbyEpisode pe ON pe.Id = m.Id |
|
|
|
|
|
|
|
INNER JOIN LibraryPath lp ON lp.Id = m.LibraryPathId AND lp.LibraryId IN @ids)",
|
|
|
|
|
|
|
|
new { ids = libraryIds }); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
await dbContext.Connection.ExecuteAsync( |
|
|
|
|
|
|
|
@"DELETE FROM Episode WHERE Id IN
|
|
|
|
|
|
|
|
(SELECT m.Id FROM MediaItem m |
|
|
|
|
|
|
|
INNER JOIN EmbyEpisode pe ON pe.Id = m.Id |
|
|
|
|
|
|
|
INNER JOIN LibraryPath lp ON lp.Id = m.LibraryPathId AND lp.LibraryId IN @ids)",
|
|
|
|
|
|
|
|
new { ids = libraryIds }); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
await dbContext.Connection.ExecuteAsync( |
|
|
|
|
|
|
|
@"DELETE FROM MediaItem WHERE Id IN
|
|
|
|
|
|
|
|
(SELECT m.Id FROM MediaItem m |
|
|
|
|
|
|
|
INNER JOIN EmbyEpisode pe ON pe.Id = m.Id |
|
|
|
|
|
|
|
INNER JOIN LibraryPath lp ON lp.Id = m.LibraryPathId AND lp.LibraryId IN @ids)",
|
|
|
|
|
|
|
|
new { ids = libraryIds }); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
List<int> seasonIds = await dbContext.Connection.QueryAsync<int>( |
|
|
|
|
|
|
|
@"SELECT m.Id FROM MediaItem m
|
|
|
|
|
|
|
|
INNER JOIN EmbySeason es ON es.Id = m.Id |
|
|
|
|
|
|
|
INNER JOIN LibraryPath lp ON lp.Id = m.LibraryPathId AND lp.LibraryId IN @ids",
|
|
|
|
|
|
|
|
new { ids = libraryIds }).Map(result => result.ToList()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
await dbContext.Connection.ExecuteAsync( |
|
|
|
|
|
|
|
@"DELETE FROM EmbySeason WHERE Id IN
|
|
|
|
|
|
|
|
(SELECT m.Id FROM MediaItem m |
|
|
|
|
|
|
|
INNER JOIN EmbySeason es ON es.Id = m.Id |
|
|
|
|
|
|
|
INNER JOIN LibraryPath lp ON lp.Id = m.LibraryPathId AND lp.LibraryId IN @ids)",
|
|
|
|
|
|
|
|
new { ids = libraryIds }); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
await dbContext.Connection.ExecuteAsync( |
|
|
|
|
|
|
|
@"DELETE FROM Season WHERE Id IN
|
|
|
|
|
|
|
|
(SELECT m.Id FROM MediaItem m |
|
|
|
|
|
|
|
INNER JOIN EmbySeason es ON es.Id = m.Id |
|
|
|
|
|
|
|
INNER JOIN LibraryPath lp ON lp.Id = m.LibraryPathId AND lp.LibraryId IN @ids)",
|
|
|
|
|
|
|
|
new { ids = libraryIds }); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
await dbContext.Connection.ExecuteAsync( |
|
|
|
|
|
|
|
@"DELETE FROM MediaItem WHERE Id IN
|
|
|
|
|
|
|
|
(SELECT m.Id FROM MediaItem m |
|
|
|
|
|
|
|
INNER JOIN EmbySeason es ON es.Id = m.Id |
|
|
|
|
|
|
|
INNER JOIN LibraryPath lp ON lp.Id = m.LibraryPathId AND lp.LibraryId IN @ids)",
|
|
|
|
|
|
|
|
new { ids = libraryIds }); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
List<int> showIds = await dbContext.Connection.QueryAsync<int>( |
|
|
|
List<EmbyLibrary> libraries = await dbContext.EmbyLibraries |
|
|
|
@"SELECT m.Id FROM MediaItem m
|
|
|
|
.Include(l => l.Paths) |
|
|
|
INNER JOIN EmbyShow ps ON ps.Id = m.Id |
|
|
|
.Include(l => l.PathInfos) |
|
|
|
INNER JOIN LibraryPath lp ON lp.Id = m.LibraryPathId AND lp.LibraryId IN @ids",
|
|
|
|
.Filter(l => libraryIds.Contains(l.Id)) |
|
|
|
new { ids = libraryIds }).Map(result => result.ToList()); |
|
|
|
.ToListAsync(); |
|
|
|
|
|
|
|
|
|
|
|
await dbContext.Connection.ExecuteAsync( |
|
|
|
dbContext.EmbyLibraries.RemoveRange(libraries); |
|
|
|
@"DELETE FROM EmbyShow WHERE Id IN
|
|
|
|
await dbContext.SaveChangesAsync(); |
|
|
|
(SELECT m.Id FROM MediaItem m |
|
|
|
|
|
|
|
INNER JOIN EmbyShow ps ON ps.Id = m.Id |
|
|
|
|
|
|
|
INNER JOIN LibraryPath lp ON lp.Id = m.LibraryPathId AND lp.LibraryId IN @ids)",
|
|
|
|
|
|
|
|
new { ids = libraryIds }); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
await dbContext.Connection.ExecuteAsync( |
|
|
|
foreach (EmbyLibrary library in libraries) |
|
|
|
@"DELETE FROM Show WHERE Id IN
|
|
|
|
{ |
|
|
|
(SELECT m.Id FROM MediaItem m |
|
|
|
library.Id = 0; |
|
|
|
INNER JOIN EmbyShow ps ON ps.Id = m.Id |
|
|
|
library.ShouldSyncItems = false; |
|
|
|
INNER JOIN LibraryPath lp ON lp.Id = m.LibraryPathId AND lp.LibraryId IN @ids)",
|
|
|
|
library.LastScan = SystemTime.MinValueUtc; |
|
|
|
new { ids = libraryIds }); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
await dbContext.Connection.ExecuteAsync( |
|
|
|
await dbContext.EmbyLibraries.AddRangeAsync(libraries); |
|
|
|
@"DELETE FROM MediaItem WHERE Id IN
|
|
|
|
await dbContext.SaveChangesAsync(); |
|
|
|
(SELECT m.Id FROM MediaItem m |
|
|
|
|
|
|
|
INNER JOIN EmbyShow ps ON ps.Id = m.Id |
|
|
|
|
|
|
|
INNER JOIN LibraryPath lp ON lp.Id = m.LibraryPathId AND lp.LibraryId IN @ids)",
|
|
|
|
|
|
|
|
new { ids = libraryIds }); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return movieIds.Append(showIds).Append(seasonIds).Append(episodeIds).ToList(); |
|
|
|
return deletedMediaIds; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|