mirror of https://github.com/ErsatzTV/ErsatzTV.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
122 lines
4.8 KiB
122 lines
4.8 KiB
using ErsatzTV.Core.Domain; |
|
using ErsatzTV.Core.Interfaces.Jellyfin; |
|
using ErsatzTV.Core.Interfaces.Repositories; |
|
using ErsatzTV.Core.Interfaces.Search; |
|
using Microsoft.Extensions.Logging; |
|
|
|
namespace ErsatzTV.Core.Jellyfin; |
|
|
|
public class JellyfinCollectionScanner : IJellyfinCollectionScanner |
|
{ |
|
private readonly IJellyfinApiClient _jellyfinApiClient; |
|
private readonly IJellyfinCollectionRepository _jellyfinCollectionRepository; |
|
private readonly ILogger<JellyfinCollectionScanner> _logger; |
|
private readonly ISearchIndex _searchIndex; |
|
private readonly ISearchRepository _searchRepository; |
|
|
|
public JellyfinCollectionScanner( |
|
IJellyfinCollectionRepository jellyfinCollectionRepository, |
|
IJellyfinApiClient jellyfinApiClient, |
|
ISearchRepository searchRepository, |
|
ISearchIndex searchIndex, |
|
ILogger<JellyfinCollectionScanner> logger) |
|
{ |
|
_jellyfinCollectionRepository = jellyfinCollectionRepository; |
|
_jellyfinApiClient = jellyfinApiClient; |
|
_searchRepository = searchRepository; |
|
_searchIndex = searchIndex; |
|
_logger = logger; |
|
} |
|
|
|
public async Task<Either<BaseError, Unit>> ScanCollections(string address, string apiKey, int mediaSourceId) |
|
{ |
|
// get all collections from db (item id, etag) |
|
List<JellyfinCollection> existingCollections = await _jellyfinCollectionRepository.GetCollections(); |
|
|
|
// get all collections from jellyfin |
|
Either<BaseError, List<JellyfinCollection>> maybeIncomingCollections = |
|
await _jellyfinApiClient.GetCollectionLibraryItems(address, apiKey, mediaSourceId); |
|
|
|
foreach (BaseError error in maybeIncomingCollections.LeftToSeq()) |
|
{ |
|
_logger.LogWarning("Failed to get collections from Jellyfin: {Error}", error.ToString()); |
|
return error; |
|
} |
|
|
|
foreach (List<JellyfinCollection> incomingCollections in maybeIncomingCollections.RightToSeq()) |
|
{ |
|
// loop over collections |
|
foreach (JellyfinCollection collection in incomingCollections) |
|
{ |
|
Option<JellyfinCollection> maybeExisting = existingCollections.Find(c => c.ItemId == collection.ItemId); |
|
|
|
// skip if unchanged (etag) |
|
if (await maybeExisting.Map(e => e.Etag ?? string.Empty).IfNoneAsync(string.Empty) == collection.Etag) |
|
{ |
|
_logger.LogDebug("Jellyfin collection {Name} is unchanged", collection.Name); |
|
continue; |
|
} |
|
|
|
// add if new |
|
if (maybeExisting.IsNone) |
|
{ |
|
_logger.LogDebug("Jellyfin collection {Name} is new", collection.Name); |
|
await _jellyfinCollectionRepository.AddCollection(collection); |
|
} |
|
else |
|
{ |
|
_logger.LogDebug("Jellyfin collection {Name} has been updated", collection.Name); |
|
} |
|
|
|
await SyncCollectionItems(address, apiKey, mediaSourceId, collection); |
|
|
|
// save collection etag |
|
await _jellyfinCollectionRepository.SetEtag(collection); |
|
} |
|
|
|
// remove missing collections (and remove any lingering tags from those collections) |
|
foreach (JellyfinCollection collection in existingCollections |
|
.Filter(e => incomingCollections.All(i => i.ItemId != e.ItemId))) |
|
{ |
|
await _jellyfinCollectionRepository.RemoveCollection(collection); |
|
} |
|
} |
|
|
|
return Unit.Default; |
|
} |
|
|
|
private async Task SyncCollectionItems( |
|
string address, |
|
string apiKey, |
|
int mediaSourceId, |
|
JellyfinCollection collection) |
|
{ |
|
// get collection items from JF |
|
Either<BaseError, List<MediaItem>> maybeItems = |
|
await _jellyfinApiClient.GetCollectionItems(address, apiKey, mediaSourceId, collection.ItemId); |
|
|
|
foreach (BaseError error in maybeItems.LeftToSeq()) |
|
{ |
|
_logger.LogWarning("Failed to get collection items from Jellyfin: {Error}", error.ToString()); |
|
return; |
|
} |
|
|
|
List<int> removedIds = await _jellyfinCollectionRepository.RemoveAllTags(collection); |
|
|
|
var jellyfinItems = maybeItems.RightToSeq().Flatten().ToList(); |
|
_logger.LogDebug("Jellyfin collection {Name} contains {Count} items", collection.Name, jellyfinItems.Count); |
|
|
|
// sync tags on items |
|
var addedIds = new List<int>(); |
|
foreach (MediaItem item in jellyfinItems) |
|
{ |
|
addedIds.Add(await _jellyfinCollectionRepository.AddTag(item, collection)); |
|
} |
|
|
|
var changedIds = removedIds.Except(addedIds).ToList(); |
|
changedIds.AddRange(addedIds.Except(removedIds)); |
|
|
|
await _searchIndex.RebuildItems(_searchRepository, changedIds); |
|
_searchIndex.Commit(); |
|
} |
|
}
|
|
|