plex fixes (#92)
* fix updating plex path replacements * fix adding/removing plex libraries * fix adding/removing plex servers * fix initial plex library sync after sign in * code cleanup
This commit is contained in:
@@ -78,10 +78,10 @@ namespace ErsatzTV.Application.Plex.Commands
|
|||||||
var existing = connectionParameters.PlexMediaSource.Libraries.OfType<PlexLibrary>().ToList();
|
var existing = connectionParameters.PlexMediaSource.Libraries.OfType<PlexLibrary>().ToList();
|
||||||
var toAdd = libraries.Filter(library => existing.All(l => l.Key != library.Key)).ToList();
|
var toAdd = libraries.Filter(library => existing.All(l => l.Key != library.Key)).ToList();
|
||||||
var toRemove = existing.Filter(library => libraries.All(l => l.Key != library.Key)).ToList();
|
var toRemove = existing.Filter(library => libraries.All(l => l.Key != library.Key)).ToList();
|
||||||
connectionParameters.PlexMediaSource.Libraries.AddRange(toAdd);
|
return _mediaSourceRepository.UpdateLibraries(
|
||||||
toRemove.ForEach(c => connectionParameters.PlexMediaSource.Libraries.Remove(c));
|
connectionParameters.PlexMediaSource.Id,
|
||||||
|
toAdd,
|
||||||
return _mediaSourceRepository.Update(connectionParameters.PlexMediaSource);
|
toRemove);
|
||||||
},
|
},
|
||||||
error =>
|
error =>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -66,23 +66,20 @@ namespace ErsatzTV.Application.Plex.Commands
|
|||||||
{
|
{
|
||||||
existing.ProductVersion = server.ProductVersion;
|
existing.ProductVersion = server.ProductVersion;
|
||||||
existing.ServerName = server.ServerName;
|
existing.ServerName = server.ServerName;
|
||||||
MergeConnections(existing.Connections, server.Connections);
|
var toAdd = server.Connections
|
||||||
if (existing.Connections.Any() && existing.Connections.All(c => !c.IsActive))
|
.Filter(connection => existing.Connections.All(c => c.Uri != connection.Uri)).ToList();
|
||||||
{
|
var toRemove = existing.Connections
|
||||||
existing.Connections.Head().IsActive = true;
|
.Filter(connection => server.Connections.All(c => c.Uri != connection.Uri)).ToList();
|
||||||
}
|
return _mediaSourceRepository.Update(existing, toAdd, toRemove);
|
||||||
|
|
||||||
return _mediaSourceRepository.Update(existing);
|
|
||||||
},
|
},
|
||||||
async () =>
|
async () =>
|
||||||
{
|
{
|
||||||
await _mediaSourceRepository.Add(server);
|
|
||||||
if (server.Connections.Any())
|
if (server.Connections.Any())
|
||||||
{
|
{
|
||||||
server.Connections.Head().IsActive = true;
|
server.Connections.Head().IsActive = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
await _mediaSourceRepository.Update(server);
|
await _mediaSourceRepository.Add(server);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ using ErsatzTV.Core;
|
|||||||
using ErsatzTV.Core.Domain;
|
using ErsatzTV.Core.Domain;
|
||||||
using ErsatzTV.Core.Interfaces.Repositories;
|
using ErsatzTV.Core.Interfaces.Repositories;
|
||||||
using LanguageExt;
|
using LanguageExt;
|
||||||
using static LanguageExt.Prelude;
|
|
||||||
|
|
||||||
namespace ErsatzTV.Application.Plex.Commands
|
namespace ErsatzTV.Application.Plex.Commands
|
||||||
{
|
{
|
||||||
@@ -35,20 +34,7 @@ namespace ErsatzTV.Application.Plex.Commands
|
|||||||
var toRemove = plexMediaSource.PathReplacements.Filter(r => incoming.All(pr => pr.Id != r.Id)).ToList();
|
var toRemove = plexMediaSource.PathReplacements.Filter(r => incoming.All(pr => pr.Id != r.Id)).ToList();
|
||||||
var toUpdate = incoming.Except(toAdd).ToList();
|
var toUpdate = incoming.Except(toAdd).ToList();
|
||||||
|
|
||||||
plexMediaSource.PathReplacements.AddRange(toAdd);
|
return _mediaSourceRepository.UpdatePathReplacements(plexMediaSource.Id, toAdd, toUpdate, toRemove);
|
||||||
toRemove.ForEach(pr => plexMediaSource.PathReplacements.Remove(pr));
|
|
||||||
foreach (PlexPathReplacement pathReplacement in toUpdate)
|
|
||||||
{
|
|
||||||
Optional(plexMediaSource.PathReplacements.SingleOrDefault(pr => pr.Id == pathReplacement.Id))
|
|
||||||
.IfSome(
|
|
||||||
pr =>
|
|
||||||
{
|
|
||||||
pr.PlexPath = pathReplacement.PlexPath;
|
|
||||||
pr.LocalPath = pathReplacement.LocalPath;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return _mediaSourceRepository.Update(plexMediaSource).ToUnit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static PlexPathReplacement Project(PlexPathReplacementItem vm) =>
|
private static PlexPathReplacement Project(PlexPathReplacementItem vm) =>
|
||||||
|
|||||||
@@ -20,7 +20,19 @@ namespace ErsatzTV.Core.Interfaces.Repositories
|
|||||||
Task<List<PlexPathReplacement>> GetPlexPathReplacementsByLibraryId(int plexLibraryPathId);
|
Task<List<PlexPathReplacement>> GetPlexPathReplacementsByLibraryId(int plexLibraryPathId);
|
||||||
Task<int> CountMediaItems(int id);
|
Task<int> CountMediaItems(int id);
|
||||||
Task Update(LocalMediaSource localMediaSource);
|
Task Update(LocalMediaSource localMediaSource);
|
||||||
Task Update(PlexMediaSource plexMediaSource);
|
Task Update(PlexMediaSource plexMediaSource, List<PlexConnection> toAdd, List<PlexConnection> toDelete);
|
||||||
|
|
||||||
|
Task<Unit> UpdateLibraries(
|
||||||
|
int plexMediaSourceId,
|
||||||
|
List<PlexLibrary> toAdd,
|
||||||
|
List<PlexLibrary> toDelete);
|
||||||
|
|
||||||
|
Task<Unit> UpdatePathReplacements(
|
||||||
|
int plexMediaSourceId,
|
||||||
|
List<PlexPathReplacement> toAdd,
|
||||||
|
List<PlexPathReplacement> toUpdate,
|
||||||
|
List<PlexPathReplacement> toDelete);
|
||||||
|
|
||||||
Task Update(PlexLibrary plexMediaSourceLibrary);
|
Task Update(PlexLibrary plexMediaSourceLibrary);
|
||||||
Task Delete(int mediaSourceId);
|
Task Delete(int mediaSourceId);
|
||||||
Task<Unit> DeleteAllPlex();
|
Task<Unit> DeleteAllPlex();
|
||||||
|
|||||||
@@ -152,11 +152,94 @@ namespace ErsatzTV.Infrastructure.Data.Repositories
|
|||||||
await context.SaveChangesAsync();
|
await context.SaveChangesAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Update(PlexMediaSource plexMediaSource)
|
public async Task Update(
|
||||||
|
PlexMediaSource plexMediaSource,
|
||||||
|
List<PlexConnection> toAdd,
|
||||||
|
List<PlexConnection> toDelete)
|
||||||
{
|
{
|
||||||
await using TvContext context = _dbContextFactory.CreateDbContext();
|
await _dbConnection.ExecuteAsync(
|
||||||
context.PlexMediaSources.Update(plexMediaSource);
|
@"UPDATE PlexMediaSource SET ProductVersion = @ProductVersion, ServerName = @ServerName WHERE Id = @Id",
|
||||||
await context.SaveChangesAsync();
|
new { plexMediaSource.ProductVersion, plexMediaSource.ServerName, plexMediaSource.Id });
|
||||||
|
|
||||||
|
await using TvContext dbContext = _dbContextFactory.CreateDbContext();
|
||||||
|
|
||||||
|
foreach (PlexConnection add in toAdd)
|
||||||
|
{
|
||||||
|
add.PlexMediaSourceId = plexMediaSource.Id;
|
||||||
|
dbContext.Entry(add).State = EntityState.Added;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (PlexConnection delete in toDelete)
|
||||||
|
{
|
||||||
|
dbContext.Entry(delete).State = EntityState.Deleted;
|
||||||
|
}
|
||||||
|
|
||||||
|
await dbContext.SaveChangesAsync();
|
||||||
|
|
||||||
|
PlexMediaSource pms = await dbContext.PlexMediaSources.FindAsync(plexMediaSource.Id);
|
||||||
|
await dbContext.Entry(pms).Collection(x => x.Connections).LoadAsync();
|
||||||
|
if (plexMediaSource.Connections.Any() && plexMediaSource.Connections.All(c => !c.IsActive))
|
||||||
|
{
|
||||||
|
plexMediaSource.Connections.Head().IsActive = true;
|
||||||
|
await dbContext.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Unit> UpdateLibraries(
|
||||||
|
int plexMediaSourceId,
|
||||||
|
List<PlexLibrary> toAdd,
|
||||||
|
List<PlexLibrary> toDelete)
|
||||||
|
{
|
||||||
|
await using TvContext dbContext = _dbContextFactory.CreateDbContext();
|
||||||
|
|
||||||
|
foreach (PlexLibrary add in toAdd)
|
||||||
|
{
|
||||||
|
add.MediaSourceId = plexMediaSourceId;
|
||||||
|
dbContext.Entry(add).State = EntityState.Added;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (PlexLibrary delete in toDelete)
|
||||||
|
{
|
||||||
|
dbContext.Entry(delete).State = EntityState.Deleted;
|
||||||
|
}
|
||||||
|
|
||||||
|
await dbContext.SaveChangesAsync();
|
||||||
|
|
||||||
|
return Unit.Default;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Unit> UpdatePathReplacements(
|
||||||
|
int plexMediaSourceId,
|
||||||
|
List<PlexPathReplacement> toAdd,
|
||||||
|
List<PlexPathReplacement> toUpdate,
|
||||||
|
List<PlexPathReplacement> toDelete)
|
||||||
|
{
|
||||||
|
foreach (PlexPathReplacement add in toAdd)
|
||||||
|
{
|
||||||
|
await _dbConnection.ExecuteAsync(
|
||||||
|
@"INSERT INTO PlexPathReplacement
|
||||||
|
(PlexPath, LocalPath, PlexMediaSourceId)
|
||||||
|
VALUES (@PlexPath, @LocalPath, @PlexMediaSourceId)",
|
||||||
|
new { add.PlexPath, add.LocalPath, PlexMediaSourceId = plexMediaSourceId });
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (PlexPathReplacement update in toUpdate)
|
||||||
|
{
|
||||||
|
await _dbConnection.ExecuteAsync(
|
||||||
|
@"UPDATE PlexPathReplacement
|
||||||
|
SET PlexPath = @PlexPath, LocalPath = @LocalPath
|
||||||
|
WHERE Id = @Id",
|
||||||
|
new { update.PlexPath, update.LocalPath, update.Id });
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (PlexPathReplacement delete in toDelete)
|
||||||
|
{
|
||||||
|
await _dbConnection.ExecuteAsync(
|
||||||
|
@"DELETE FROM PlexPathReplacement WHERE Id = @Id",
|
||||||
|
new { delete.Id });
|
||||||
|
}
|
||||||
|
|
||||||
|
return Unit.Default;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Update(PlexLibrary plexMediaSourceLibrary)
|
public async Task Update(PlexLibrary plexMediaSourceLibrary)
|
||||||
|
|||||||
@@ -51,17 +51,17 @@ namespace ErsatzTV.Infrastructure.Plex
|
|||||||
.Append(httpsResources.Filter(resource => resource.HttpsRequired))
|
.Append(httpsResources.Filter(resource => resource.HttpsRequired))
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
IEnumerable<PlexMediaSource> sources = allResources
|
IEnumerable<PlexMediaSource> sources = await allResources
|
||||||
.Filter(r => r.Provides.Split(",").Any(p => p == "server"))
|
.Filter(r => r.Provides.Split(",").Any(p => p == "server"))
|
||||||
.Filter(r => r.Owned) // TODO: maybe support non-owned servers in the future
|
.Filter(r => r.Owned) // TODO: maybe support non-owned servers in the future
|
||||||
.Map(
|
.Map(
|
||||||
resource =>
|
async resource =>
|
||||||
{
|
{
|
||||||
var serverAuthToken = new PlexServerAuthToken(
|
var serverAuthToken = new PlexServerAuthToken(
|
||||||
resource.ClientIdentifier,
|
resource.ClientIdentifier,
|
||||||
resource.AccessToken);
|
resource.AccessToken);
|
||||||
|
|
||||||
_plexSecretStore.UpsertServerAuthToken(serverAuthToken);
|
await _plexSecretStore.UpsertServerAuthToken(serverAuthToken);
|
||||||
List<PlexResourceConnection> sortedConnections = resource.HttpsRequired
|
List<PlexResourceConnection> sortedConnections = resource.HttpsRequired
|
||||||
? resource.Connections
|
? resource.Connections
|
||||||
: resource.Connections.OrderBy(c => c.Local ? 0 : 1).ToList();
|
: resource.Connections.OrderBy(c => c.Local ? 0 : 1).ToList();
|
||||||
@@ -76,7 +76,9 @@ namespace ErsatzTV.Infrastructure.Plex
|
|||||||
};
|
};
|
||||||
|
|
||||||
return source;
|
return source;
|
||||||
});
|
})
|
||||||
|
.Sequence();
|
||||||
|
|
||||||
result.AddRange(sources);
|
result.AddRange(sources);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user