Browse Source

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
pull/93/head
Jason Dove 4 years ago committed by GitHub
parent
commit
eca58dbe7f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 8
      ErsatzTV.Application/Plex/Commands/SynchronizePlexLibrariesHandler.cs
  2. 15
      ErsatzTV.Application/Plex/Commands/SynchronizePlexMediaSourcesHandler.cs
  3. 16
      ErsatzTV.Application/Plex/Commands/UpdatePlexPathReplacementsHandler.cs
  4. 14
      ErsatzTV.Core/Interfaces/Repositories/IMediaSourceRepository.cs
  5. 91
      ErsatzTV.Infrastructure/Data/Repositories/MediaSourceRepository.cs
  6. 10
      ErsatzTV.Infrastructure/Plex/PlexTvApiClient.cs
  7. 2
      ErsatzTV/Pages/ChannelEditor.razor

8
ErsatzTV.Application/Plex/Commands/SynchronizePlexLibrariesHandler.cs

@ -78,10 +78,10 @@ namespace ErsatzTV.Application.Plex.Commands @@ -78,10 +78,10 @@ namespace ErsatzTV.Application.Plex.Commands
var existing = connectionParameters.PlexMediaSource.Libraries.OfType<PlexLibrary>().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();
connectionParameters.PlexMediaSource.Libraries.AddRange(toAdd);
toRemove.ForEach(c => connectionParameters.PlexMediaSource.Libraries.Remove(c));
return _mediaSourceRepository.Update(connectionParameters.PlexMediaSource);
return _mediaSourceRepository.UpdateLibraries(
connectionParameters.PlexMediaSource.Id,
toAdd,
toRemove);
},
error =>
{

15
ErsatzTV.Application/Plex/Commands/SynchronizePlexMediaSourcesHandler.cs

@ -66,23 +66,20 @@ namespace ErsatzTV.Application.Plex.Commands @@ -66,23 +66,20 @@ namespace ErsatzTV.Application.Plex.Commands
{
existing.ProductVersion = server.ProductVersion;
existing.ServerName = server.ServerName;
MergeConnections(existing.Connections, server.Connections);
if (existing.Connections.Any() && existing.Connections.All(c => !c.IsActive))
{
existing.Connections.Head().IsActive = true;
}
return _mediaSourceRepository.Update(existing);
var toAdd = server.Connections
.Filter(connection => existing.Connections.All(c => c.Uri != connection.Uri)).ToList();
var toRemove = existing.Connections
.Filter(connection => server.Connections.All(c => c.Uri != connection.Uri)).ToList();
return _mediaSourceRepository.Update(existing, toAdd, toRemove);
},
async () =>
{
await _mediaSourceRepository.Add(server);
if (server.Connections.Any())
{
server.Connections.Head().IsActive = true;
}
await _mediaSourceRepository.Update(server);
await _mediaSourceRepository.Add(server);
});
}

16
ErsatzTV.Application/Plex/Commands/UpdatePlexPathReplacementsHandler.cs

@ -6,7 +6,6 @@ using ErsatzTV.Core; @@ -6,7 +6,6 @@ using ErsatzTV.Core;
using ErsatzTV.Core.Domain;
using ErsatzTV.Core.Interfaces.Repositories;
using LanguageExt;
using static LanguageExt.Prelude;
namespace ErsatzTV.Application.Plex.Commands
{
@ -35,20 +34,7 @@ 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 toUpdate = incoming.Except(toAdd).ToList();
plexMediaSource.PathReplacements.AddRange(toAdd);
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();
return _mediaSourceRepository.UpdatePathReplacements(plexMediaSource.Id, toAdd, toUpdate, toRemove);
}
private static PlexPathReplacement Project(PlexPathReplacementItem vm) =>

14
ErsatzTV.Core/Interfaces/Repositories/IMediaSourceRepository.cs

@ -20,7 +20,19 @@ namespace ErsatzTV.Core.Interfaces.Repositories @@ -20,7 +20,19 @@ namespace ErsatzTV.Core.Interfaces.Repositories
Task<List<PlexPathReplacement>> GetPlexPathReplacementsByLibraryId(int plexLibraryPathId);
Task<int> CountMediaItems(int id);
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 Delete(int mediaSourceId);
Task<Unit> DeleteAllPlex();

91
ErsatzTV.Infrastructure/Data/Repositories/MediaSourceRepository.cs

@ -152,11 +152,94 @@ namespace ErsatzTV.Infrastructure.Data.Repositories @@ -152,11 +152,94 @@ namespace ErsatzTV.Infrastructure.Data.Repositories
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();
context.PlexMediaSources.Update(plexMediaSource);
await context.SaveChangesAsync();
await _dbConnection.ExecuteAsync(
@"UPDATE PlexMediaSource SET ProductVersion = @ProductVersion, ServerName = @ServerName WHERE Id = @Id",
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)

10
ErsatzTV.Infrastructure/Plex/PlexTvApiClient.cs

@ -51,17 +51,17 @@ namespace ErsatzTV.Infrastructure.Plex @@ -51,17 +51,17 @@ namespace ErsatzTV.Infrastructure.Plex
.Append(httpsResources.Filter(resource => resource.HttpsRequired))
.ToList();
IEnumerable<PlexMediaSource> sources = allResources
IEnumerable<PlexMediaSource> sources = await allResources
.Filter(r => r.Provides.Split(",").Any(p => p == "server"))
.Filter(r => r.Owned) // TODO: maybe support non-owned servers in the future
.Map(
resource =>
async resource =>
{
var serverAuthToken = new PlexServerAuthToken(
resource.ClientIdentifier,
resource.AccessToken);
_plexSecretStore.UpsertServerAuthToken(serverAuthToken);
await _plexSecretStore.UpsertServerAuthToken(serverAuthToken);
List<PlexResourceConnection> sortedConnections = resource.HttpsRequired
? resource.Connections
: resource.Connections.OrderBy(c => c.Local ? 0 : 1).ToList();
@ -76,7 +76,9 @@ namespace ErsatzTV.Infrastructure.Plex @@ -76,7 +76,9 @@ namespace ErsatzTV.Infrastructure.Plex
};
return source;
});
})
.Sequence();
result.AddRange(sources);
}

2
ErsatzTV/Pages/ChannelEditor.razor

@ -96,7 +96,7 @@ @@ -96,7 +96,7 @@
else
{
FFmpegSettingsViewModel ffmpegSettings = await Mediator.Send(new GetFFmpegSettings());
// TODO: command for new channel
IEnumerable<int> channelNumbers = await Mediator.Send(new GetAllChannels())
.Map(list => list.Map(c => int.TryParse(c.Number.Split(".").Head(), out int result) ? result : 0));

Loading…
Cancel
Save