|
|
|
@ -290,28 +290,26 @@ public class PlexMovieLibraryScanner : PlexLibraryScanner, IPlexMovieLibraryScan |
|
|
|
Either<BaseError, bool> refreshResult = |
|
|
|
Either<BaseError, bool> refreshResult = |
|
|
|
await _localStatisticsProvider.RefreshStatistics(ffmpegPath, ffprobePath, existing, localPath); |
|
|
|
await _localStatisticsProvider.RefreshStatistics(ffmpegPath, ffprobePath, existing, localPath); |
|
|
|
|
|
|
|
|
|
|
|
await refreshResult.Match( |
|
|
|
foreach (BaseError error in refreshResult.LeftToSeq()) |
|
|
|
async _ => |
|
|
|
{ |
|
|
|
{ |
|
|
|
_logger.LogWarning( |
|
|
|
foreach (MediaItem updated in await _searchRepository.GetItemToIndex(incoming.Id)) |
|
|
|
"Unable to refresh {Attribute} for media item {Path}. Error: {Error}", |
|
|
|
{ |
|
|
|
"Statistics", |
|
|
|
await _searchIndex.UpdateItems( |
|
|
|
localPath, |
|
|
|
_searchRepository, |
|
|
|
error.Value); |
|
|
|
new List<MediaItem> { updated }); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
foreach (bool _ in refreshResult.RightToSeq()) |
|
|
|
await _metadataRepository.UpdatePlexStatistics(existingVersion.Id, incomingVersion); |
|
|
|
{ |
|
|
|
}, |
|
|
|
foreach (MediaItem updated in await _searchRepository.GetItemToIndex(incoming.Id)) |
|
|
|
error => |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
_logger.LogWarning( |
|
|
|
await _searchIndex.UpdateItems( |
|
|
|
"Unable to refresh {Attribute} for media item {Path}. Error: {Error}", |
|
|
|
_searchRepository, |
|
|
|
"Statistics", |
|
|
|
new List<MediaItem> { updated }); |
|
|
|
localPath, |
|
|
|
} |
|
|
|
error.Value); |
|
|
|
|
|
|
|
|
|
|
|
await _metadataRepository.UpdatePlexStatistics(existingVersion.Id, incomingVersion); |
|
|
|
return Task.CompletedTask; |
|
|
|
} |
|
|
|
}); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -340,193 +338,191 @@ public class PlexMovieLibraryScanner : PlexLibraryScanner, IPlexMovieLibraryScan |
|
|
|
connection, |
|
|
|
connection, |
|
|
|
token); |
|
|
|
token); |
|
|
|
|
|
|
|
|
|
|
|
await maybeMetadata.Match( |
|
|
|
foreach (MovieMetadata fullMetadata in maybeMetadata.RightToSeq()) |
|
|
|
async fullMetadata => |
|
|
|
{ |
|
|
|
|
|
|
|
if (existingMetadata.MetadataKind != MetadataKind.External) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (existingMetadata.MetadataKind != MetadataKind.External) |
|
|
|
existingMetadata.MetadataKind = MetadataKind.External; |
|
|
|
{ |
|
|
|
await _metadataRepository.MarkAsExternal(existingMetadata); |
|
|
|
existingMetadata.MetadataKind = MetadataKind.External; |
|
|
|
} |
|
|
|
await _metadataRepository.MarkAsExternal(existingMetadata); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (existingMetadata.ContentRating != fullMetadata.ContentRating) |
|
|
|
if (existingMetadata.ContentRating != fullMetadata.ContentRating) |
|
|
|
{ |
|
|
|
{ |
|
|
|
existingMetadata.ContentRating = fullMetadata.ContentRating; |
|
|
|
existingMetadata.ContentRating = fullMetadata.ContentRating; |
|
|
|
await _metadataRepository.SetContentRating(existingMetadata, fullMetadata.ContentRating); |
|
|
|
await _metadataRepository.SetContentRating(existingMetadata, fullMetadata.ContentRating); |
|
|
|
result.IsUpdated = true; |
|
|
|
result.IsUpdated = true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
foreach (Genre genre in existingMetadata.Genres |
|
|
|
foreach (Genre genre in existingMetadata.Genres |
|
|
|
.Filter(g => fullMetadata.Genres.All(g2 => g2.Name != g.Name)) |
|
|
|
.Filter(g => fullMetadata.Genres.All(g2 => g2.Name != g.Name)) |
|
|
|
.ToList()) |
|
|
|
.ToList()) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
existingMetadata.Genres.Remove(genre); |
|
|
|
|
|
|
|
if (await _metadataRepository.RemoveGenre(genre)) |
|
|
|
{ |
|
|
|
{ |
|
|
|
existingMetadata.Genres.Remove(genre); |
|
|
|
result.IsUpdated = true; |
|
|
|
if (await _metadataRepository.RemoveGenre(genre)) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
result.IsUpdated = true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
foreach (Genre genre in fullMetadata.Genres |
|
|
|
foreach (Genre genre in fullMetadata.Genres |
|
|
|
.Filter(g => existingMetadata.Genres.All(g2 => g2.Name != g.Name)) |
|
|
|
.Filter(g => existingMetadata.Genres.All(g2 => g2.Name != g.Name)) |
|
|
|
.ToList()) |
|
|
|
.ToList()) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
existingMetadata.Genres.Add(genre); |
|
|
|
|
|
|
|
if (await _movieRepository.AddGenre(existingMetadata, genre)) |
|
|
|
{ |
|
|
|
{ |
|
|
|
existingMetadata.Genres.Add(genre); |
|
|
|
result.IsUpdated = true; |
|
|
|
if (await _movieRepository.AddGenre(existingMetadata, genre)) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
result.IsUpdated = true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
foreach (Studio studio in existingMetadata.Studios |
|
|
|
foreach (Studio studio in existingMetadata.Studios |
|
|
|
.Filter(s => fullMetadata.Studios.All(s2 => s2.Name != s.Name)) |
|
|
|
.Filter(s => fullMetadata.Studios.All(s2 => s2.Name != s.Name)) |
|
|
|
.ToList()) |
|
|
|
.ToList()) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
existingMetadata.Studios.Remove(studio); |
|
|
|
|
|
|
|
if (await _metadataRepository.RemoveStudio(studio)) |
|
|
|
{ |
|
|
|
{ |
|
|
|
existingMetadata.Studios.Remove(studio); |
|
|
|
result.IsUpdated = true; |
|
|
|
if (await _metadataRepository.RemoveStudio(studio)) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
result.IsUpdated = true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
foreach (Studio studio in fullMetadata.Studios |
|
|
|
foreach (Studio studio in fullMetadata.Studios |
|
|
|
.Filter(s => existingMetadata.Studios.All(s2 => s2.Name != s.Name)) |
|
|
|
.Filter(s => existingMetadata.Studios.All(s2 => s2.Name != s.Name)) |
|
|
|
.ToList()) |
|
|
|
.ToList()) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
existingMetadata.Studios.Add(studio); |
|
|
|
|
|
|
|
if (await _movieRepository.AddStudio(existingMetadata, studio)) |
|
|
|
{ |
|
|
|
{ |
|
|
|
existingMetadata.Studios.Add(studio); |
|
|
|
result.IsUpdated = true; |
|
|
|
if (await _movieRepository.AddStudio(existingMetadata, studio)) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
result.IsUpdated = true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
foreach (Actor actor in existingMetadata.Actors |
|
|
|
foreach (Actor actor in existingMetadata.Actors |
|
|
|
.Filter( |
|
|
|
.Filter( |
|
|
|
a => fullMetadata.Actors.All( |
|
|
|
a => fullMetadata.Actors.All( |
|
|
|
a2 => a2.Name != a.Name || a.Artwork == null && a2.Artwork != null)) |
|
|
|
a2 => a2.Name != a.Name || a.Artwork == null && a2.Artwork != null)) |
|
|
|
.ToList()) |
|
|
|
.ToList()) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
existingMetadata.Actors.Remove(actor); |
|
|
|
|
|
|
|
if (await _metadataRepository.RemoveActor(actor)) |
|
|
|
{ |
|
|
|
{ |
|
|
|
existingMetadata.Actors.Remove(actor); |
|
|
|
result.IsUpdated = true; |
|
|
|
if (await _metadataRepository.RemoveActor(actor)) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
result.IsUpdated = true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
foreach (Actor actor in fullMetadata.Actors |
|
|
|
foreach (Actor actor in fullMetadata.Actors |
|
|
|
.Filter(a => existingMetadata.Actors.All(a2 => a2.Name != a.Name)) |
|
|
|
.Filter(a => existingMetadata.Actors.All(a2 => a2.Name != a.Name)) |
|
|
|
.ToList()) |
|
|
|
.ToList()) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
existingMetadata.Actors.Add(actor); |
|
|
|
|
|
|
|
if (await _movieRepository.AddActor(existingMetadata, actor)) |
|
|
|
{ |
|
|
|
{ |
|
|
|
existingMetadata.Actors.Add(actor); |
|
|
|
result.IsUpdated = true; |
|
|
|
if (await _movieRepository.AddActor(existingMetadata, actor)) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
result.IsUpdated = true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
foreach (Director director in existingMetadata.Directors |
|
|
|
foreach (Director director in existingMetadata.Directors |
|
|
|
.Filter(g => fullMetadata.Directors.All(g2 => g2.Name != g.Name)) |
|
|
|
.Filter(g => fullMetadata.Directors.All(g2 => g2.Name != g.Name)) |
|
|
|
.ToList()) |
|
|
|
.ToList()) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
existingMetadata.Directors.Remove(director); |
|
|
|
|
|
|
|
if (await _metadataRepository.RemoveDirector(director)) |
|
|
|
{ |
|
|
|
{ |
|
|
|
existingMetadata.Directors.Remove(director); |
|
|
|
result.IsUpdated = true; |
|
|
|
if (await _metadataRepository.RemoveDirector(director)) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
result.IsUpdated = true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
foreach (Director director in fullMetadata.Directors |
|
|
|
foreach (Director director in fullMetadata.Directors |
|
|
|
.Filter(g => existingMetadata.Directors.All(g2 => g2.Name != g.Name)) |
|
|
|
.Filter(g => existingMetadata.Directors.All(g2 => g2.Name != g.Name)) |
|
|
|
.ToList()) |
|
|
|
.ToList()) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
existingMetadata.Directors.Add(director); |
|
|
|
|
|
|
|
if (await _movieRepository.AddDirector(existingMetadata, director)) |
|
|
|
{ |
|
|
|
{ |
|
|
|
existingMetadata.Directors.Add(director); |
|
|
|
result.IsUpdated = true; |
|
|
|
if (await _movieRepository.AddDirector(existingMetadata, director)) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
result.IsUpdated = true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
foreach (Writer writer in existingMetadata.Writers |
|
|
|
foreach (Writer writer in existingMetadata.Writers |
|
|
|
.Filter(g => fullMetadata.Writers.All(g2 => g2.Name != g.Name)) |
|
|
|
.Filter(g => fullMetadata.Writers.All(g2 => g2.Name != g.Name)) |
|
|
|
.ToList()) |
|
|
|
.ToList()) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
existingMetadata.Writers.Remove(writer); |
|
|
|
|
|
|
|
if (await _metadataRepository.RemoveWriter(writer)) |
|
|
|
{ |
|
|
|
{ |
|
|
|
existingMetadata.Writers.Remove(writer); |
|
|
|
result.IsUpdated = true; |
|
|
|
if (await _metadataRepository.RemoveWriter(writer)) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
result.IsUpdated = true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
foreach (Writer writer in fullMetadata.Writers |
|
|
|
foreach (Writer writer in fullMetadata.Writers |
|
|
|
.Filter(g => existingMetadata.Writers.All(g2 => g2.Name != g.Name)) |
|
|
|
.Filter(g => existingMetadata.Writers.All(g2 => g2.Name != g.Name)) |
|
|
|
.ToList()) |
|
|
|
.ToList()) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
existingMetadata.Writers.Add(writer); |
|
|
|
|
|
|
|
if (await _movieRepository.AddWriter(existingMetadata, writer)) |
|
|
|
{ |
|
|
|
{ |
|
|
|
existingMetadata.Writers.Add(writer); |
|
|
|
result.IsUpdated = true; |
|
|
|
if (await _movieRepository.AddWriter(existingMetadata, writer)) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
result.IsUpdated = true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
foreach (MetadataGuid guid in existingMetadata.Guids |
|
|
|
foreach (MetadataGuid guid in existingMetadata.Guids |
|
|
|
.Filter(g => fullMetadata.Guids.All(g2 => g2.Guid != g.Guid)) |
|
|
|
.Filter(g => fullMetadata.Guids.All(g2 => g2.Guid != g.Guid)) |
|
|
|
.ToList()) |
|
|
|
.ToList()) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
existingMetadata.Guids.Remove(guid); |
|
|
|
|
|
|
|
if (await _metadataRepository.RemoveGuid(guid)) |
|
|
|
{ |
|
|
|
{ |
|
|
|
existingMetadata.Guids.Remove(guid); |
|
|
|
result.IsUpdated = true; |
|
|
|
if (await _metadataRepository.RemoveGuid(guid)) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
result.IsUpdated = true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
foreach (MetadataGuid guid in fullMetadata.Guids |
|
|
|
foreach (MetadataGuid guid in fullMetadata.Guids |
|
|
|
.Filter(g => existingMetadata.Guids.All(g2 => g2.Guid != g.Guid)) |
|
|
|
.Filter(g => existingMetadata.Guids.All(g2 => g2.Guid != g.Guid)) |
|
|
|
.ToList()) |
|
|
|
.ToList()) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
existingMetadata.Guids.Add(guid); |
|
|
|
|
|
|
|
if (await _metadataRepository.AddGuid(existingMetadata, guid)) |
|
|
|
{ |
|
|
|
{ |
|
|
|
existingMetadata.Guids.Add(guid); |
|
|
|
result.IsUpdated = true; |
|
|
|
if (await _metadataRepository.AddGuid(existingMetadata, guid)) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
result.IsUpdated = true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
foreach (Tag tag in existingMetadata.Tags |
|
|
|
foreach (Tag tag in existingMetadata.Tags |
|
|
|
.Filter(g => fullMetadata.Tags.All(g2 => g2.Name != g.Name)) |
|
|
|
.Filter(g => fullMetadata.Tags.All(g2 => g2.Name != g.Name)) |
|
|
|
.ToList()) |
|
|
|
.ToList()) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
existingMetadata.Tags.Remove(tag); |
|
|
|
|
|
|
|
if (await _metadataRepository.RemoveTag(tag)) |
|
|
|
{ |
|
|
|
{ |
|
|
|
existingMetadata.Tags.Remove(tag); |
|
|
|
result.IsUpdated = true; |
|
|
|
if (await _metadataRepository.RemoveTag(tag)) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
result.IsUpdated = true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
foreach (Tag tag in fullMetadata.Tags |
|
|
|
foreach (Tag tag in fullMetadata.Tags |
|
|
|
.Filter(g => existingMetadata.Tags.All(g2 => g2.Name != g.Name)) |
|
|
|
.Filter(g => existingMetadata.Tags.All(g2 => g2.Name != g.Name)) |
|
|
|
.ToList()) |
|
|
|
.ToList()) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
existingMetadata.Tags.Add(tag); |
|
|
|
|
|
|
|
if (await _movieRepository.AddTag(existingMetadata, tag)) |
|
|
|
{ |
|
|
|
{ |
|
|
|
existingMetadata.Tags.Add(tag); |
|
|
|
result.IsUpdated = true; |
|
|
|
if (await _movieRepository.AddTag(existingMetadata, tag)) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
result.IsUpdated = true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (fullMetadata.SortTitle != existingMetadata.SortTitle) |
|
|
|
if (fullMetadata.SortTitle != existingMetadata.SortTitle) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
existingMetadata.SortTitle = fullMetadata.SortTitle; |
|
|
|
|
|
|
|
if (await _movieRepository.UpdateSortTitle(existingMetadata)) |
|
|
|
{ |
|
|
|
{ |
|
|
|
existingMetadata.SortTitle = fullMetadata.SortTitle; |
|
|
|
result.IsUpdated = true; |
|
|
|
if (await _movieRepository.UpdateSortTitle(existingMetadata)) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
result.IsUpdated = true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (result.IsUpdated) |
|
|
|
if (result.IsUpdated) |
|
|
|
{ |
|
|
|
{ |
|
|
|
await _metadataRepository.MarkAsUpdated(existingMetadata, fullMetadata.DateUpdated); |
|
|
|
await _metadataRepository.MarkAsUpdated(existingMetadata, fullMetadata.DateUpdated); |
|
|
|
} |
|
|
|
} |
|
|
|
}, |
|
|
|
} |
|
|
|
_ => Task.CompletedTask); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: update other metadata?
|
|
|
|
// TODO: update other metadata?
|
|
|
|
|
|
|
|
|
|
|
|
|