Skip to content

Commit

Permalink
Remove extra videos on delete
Browse files Browse the repository at this point in the history
  • Loading branch information
revam committed Sep 17, 2021
1 parent 63fefcd commit b662115
Showing 1 changed file with 85 additions and 32 deletions.
117 changes: 85 additions & 32 deletions Shokofin/Providers/ExtraMetadataProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,19 +89,22 @@ private void OnLibraryManagerItemAdded(object sender, ItemChangeEventArgs itemCh
if (!IsEnabledForSeries(series, out var seriesId))
return;

HandleSeries(series, seriesId);
UpdateSeries(series, seriesId);
break;
}
case Season season: {
// We're not interested in the dummy season.
if (!season.IndexNumber.HasValue)
return;

if (!(itemChangeEventArgs.Parent is Series series))
return;

// Abort if we're unable to get the shoko series id
if (!IsEnabledForSeason(season, out var seriesId))
return;

HandleSeason(season, seriesId, season.Series);
UpdateSeason(season, seriesId, series);
break;
}
case Episode episode: {
Expand Down Expand Up @@ -145,11 +148,10 @@ private void OnLibraryManagerItemUpdated(object sender, ItemChangeEventArgs item
if (!IsEnabledForSeries(series, out var seriesId))
return;

if (Plugin.Instance.Configuration.AddMissingMetadata) {
if (Plugin.Instance.Configuration.AddMissingMetadata)
RemoveDuplicateEpisodes(series, seriesId);
}

HandleSeries(series, seriesId);
UpdateSeries(series, seriesId);
return;
}
case Season season: {
Expand All @@ -161,11 +163,13 @@ private void OnLibraryManagerItemUpdated(object sender, ItemChangeEventArgs item
if (!IsEnabledForSeason(season, out var seriesId))
return;

if (Plugin.Instance.Configuration.AddMissingMetadata) {
if (Plugin.Instance.Configuration.AddMissingMetadata)
RemoveDuplicateEpisodes(season, seriesId);
}

HandleSeason(season, seriesId, season.Series);
if (!(itemChangeEventArgs.Parent is Series series))
return;

UpdateSeason(season, seriesId, series);
return;
}
case Episode episode: {
Expand All @@ -184,26 +188,45 @@ private void OnLibraryManagerItemUpdated(object sender, ItemChangeEventArgs item

private void OnLibraryManagerItemRemoved(object sender, ItemChangeEventArgs itemChangeEventArgs)
{
// No action needed if either 1) the setting is turned of, 2) the item is virtual, 3) the provider is not enabled for the item
if (itemChangeEventArgs.Item.IsVirtualItem || !IsEnabledForItem(itemChangeEventArgs.Item))
if (itemChangeEventArgs.Item.IsVirtualItem)
return;

switch (itemChangeEventArgs.Item) {
// Create a new virtual season if the real one was deleted.
// Clean up after removing a series.
case Series series: {
if (!IsEnabledForSeries(series, out var seriesId))
return;

RemoveExtras(series, seriesId);

if (Plugin.Instance.Configuration.SeriesGrouping == Ordering.GroupType.ShokoGroup) {
foreach (var season in series.Children.OfType<Season>()) {
OnLibraryManagerItemRemoved(this, new ItemChangeEventArgs { Item = season, Parent = series, UpdateReason = ItemUpdateType.None });
}
}

return;
}
// Create a new virtual season if the real one was deleted and clean up extras if the season was deleted.
case Season season: {
// Abort if we're unable to get the shoko episode id
if (!IsEnabledForSeason(season, out var seriesId))
if (!(IsEnabledForSeason(season, out var seriesId) && (itemChangeEventArgs.Parent is Series series)))
return;

HandleSeason(season, seriesId, itemChangeEventArgs.Parent as Series, true);
if (itemChangeEventArgs.UpdateReason == ItemUpdateType.None)
RemoveExtras(season, seriesId);
else
UpdateSeason(season, seriesId, series, true);
break;
}
// Similarly, create a new virtual episode if the real one was deleted.
case Episode episode: {
if (!IsEnabledForEpisode(episode, out var episodeId))
return;

HandleEpisode(episode, episodeId);
RemoveDuplicateEpisodes(episode, episodeId);

UpdateEpisode(episode, episodeId);
break;
}
}
Expand Down Expand Up @@ -236,7 +259,7 @@ private bool IsEnabledForSeries(Series series, out string seriesId)
return false;
}

private void HandleSeries(Series series, string seriesId)
private void UpdateSeries(Series series, string seriesId)
{
if (!ApiManager.TryLockActionForIdOFType("series", seriesId, "update"))
return;
Expand Down Expand Up @@ -369,7 +392,7 @@ private bool IsEnabledForSeason(Season season, out string seriesId)
return IsEnabledForSeries(season.Series, out seriesId);
}

private void HandleSeason(Season season, string seriesId, Series series, bool deleted = false)
private void UpdateSeason(Season season, string seriesId, Series series, bool deleted = false)
{
var seasonId = $"{seriesId}:{season.IndexNumber.Value}";
try {
Expand Down Expand Up @@ -477,7 +500,7 @@ private bool IsEnabledForEpisode(Episode episode, out string episodeId)
) && !string.IsNullOrEmpty(episodeId);
}

private void HandleEpisode(Episode episode, string episodeId)
private void UpdateEpisode(Episode episode, string episodeId)
{
Info.GroupInfo groupInfo = null;
Info.SeriesInfo seriesInfo = ApiManager.GetSeriesInfoForEpisodeSync(episodeId);
Expand Down Expand Up @@ -669,6 +692,7 @@ private void AddExtras(Folder parent, Info.SeriesInfo seriesInfo)
return;

var needsUpdate = false;
var extraIds = new List<Guid>();
foreach (var episodeInfo in seriesInfo.ExtrasList) {
if (!ApiManager.TryGetEpisodePathForId(episodeInfo.Id, out var episodePath))
continue;
Expand All @@ -684,16 +708,22 @@ private void AddExtras(Folder parent, Info.SeriesInfo seriesInfo)
}

var item = LibraryManager.FindByPath(episodePath, false);
if (item != null && item is Video result) {
result.ParentId = Guid.Empty;
result.OwnerId = parent.Id;
result.Name = episodeInfo.Shoko.Name;
result.ExtraType = episodeInfo.ExtraType;
LibraryManager.UpdateItemAsync(result, null, ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
if (item != null && item is Video video) {
video.ParentId = Guid.Empty;
video.OwnerId = parent.Id;
video.Name = episodeInfo.Shoko.Name;
video.ExtraType = episodeInfo.ExtraType;
video.ProviderIds.TryAdd("Shoko Episode", episodeInfo.Id);
video.ProviderIds.TryAdd("Shoko Series", seriesInfo.Id);
LibraryManager.UpdateItemAsync(video, null, ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
if (!parent.ExtraIds.Contains(video.Id)) {
needsUpdate = true;
extraIds.Add(video.Id);
}
}
else {
Logger.LogInformation("Addding {ExtraType} {EpisodeName} to {ParentName}", episodeInfo.ExtraType, parent.Name);
result = new Video {
Logger.LogInformation("Addding {ExtraType} {VideoName} to parent {ParentName} (Series={SeriesId})", episodeInfo.ExtraType, parent.Name, seriesInfo.Id);
video = new Video {
Id = LibraryManager.GetNewItemId($"{parent.Id} {episodeInfo.ExtraType} {episodeInfo.Id}", typeof (Video)),
Name = episodeInfo.Shoko.Name,
Path = episodePath,
Expand All @@ -703,17 +733,40 @@ private void AddExtras(Folder parent, Info.SeriesInfo seriesInfo)
DateCreated = DateTime.UtcNow,
DateModified = DateTime.UtcNow,
};
LibraryManager.CreateItem(result, null);
video.ProviderIds.Add("Shoko Episode", episodeInfo.Id);
video.ProviderIds.Add("Shoko Series", seriesInfo.Id);
LibraryManager.CreateItem(video, null);
needsUpdate = true;
extraIds.Add(video.Id);
}

parent.ExtraIds = parent.ExtraIds.Append(result.Id).Distinct().ToArray();
}
// The extra video is available locally.
if (needsUpdate) {
parent.ExtraIds = parent.ExtraIds.Concat(extraIds).Distinct().ToArray();
LibraryManager.UpdateItemAsync(parent, parent.Parent, ItemUpdateType.None, CancellationToken.None).ConfigureAwait(false);
}
}

public void RemoveExtras(Folder parent, string seriesId)
{
var searchList = LibraryManager.GetItemList(new InternalItemsQuery {
IsVirtualItem = false,
IncludeItemTypes = new [] { nameof (Video) },
HasOwnerId = true,
HasAnyProviderId = { ["Shoko Series"] = seriesId},
DtoOptions = new DtoOptions(true),
}, true);

var deleteOptions = new DeleteOptions {
DeleteFileLocation = false,
};

foreach (var video in searchList)
LibraryManager.DeleteItem(video, deleteOptions);

if (searchList.Count > 0)
Logger.LogInformation("Removed {Count} extras from parent {ParentName}. (Series={SeriesId})", searchList.Count, parent.Name, seriesId);
}

private void RemoveDuplicateEpisodes(Episode episode, string episodeId)
{
var query = new InternalItemsQuery {
Expand All @@ -732,9 +785,9 @@ private void RemoveDuplicateEpisodes(Episode episode, string episodeId)
};

// Remove the virtual season/episode that matches the newly updated item
foreach (var item in existingVirtualItems) {
foreach (var item in existingVirtualItems)
LibraryManager.DeleteItem(item, deleteOptions);
}

if (existingVirtualItems.Count > 0)
Logger.LogInformation("Removed {Count} duplicate episodes for episode {EpisodeName}. (Episode={EpisodeId})", existingVirtualItems.Count, episode.Name, episodeId);
}
Expand All @@ -750,7 +803,7 @@ private void RemoveDuplicateEpisodes(Season season, string seriesId)
// We're only interested in physical episodes.
if (episode.IsVirtualItem)
continue;

// Abort if we're unable to get the shoko episode id
if (!IsEnabledForEpisode(episode, out var episodeId))
continue;
Expand Down

0 comments on commit b662115

Please sign in to comment.