From ee683d5737c0293ab4508e7d8afefaca3eb60027 Mon Sep 17 00:00:00 2001 From: jadon <16850875+wolffshots@users.noreply.github.com> Date: Wed, 7 May 2025 22:53:17 +0200 Subject: [PATCH 01/17] feat: set e# and logging --- .../Providers/EpisodeMetadataProvider.cs | 2 ++ .../TubeArchivist/TubeArchivistApi.cs | 1 + .../TubeArchivist/Video/Video.cs | 4 +++- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Jellyfin.Plugin.TubeArchivistMetadata/Providers/EpisodeMetadataProvider.cs b/Jellyfin.Plugin.TubeArchivistMetadata/Providers/EpisodeMetadataProvider.cs index a5f1f38..a3c1e70 100644 --- a/Jellyfin.Plugin.TubeArchivistMetadata/Providers/EpisodeMetadataProvider.cs +++ b/Jellyfin.Plugin.TubeArchivistMetadata/Providers/EpisodeMetadataProvider.cs @@ -67,8 +67,10 @@ namespace Jellyfin.Plugin.TubeArchivistMetadata.Providers }); result.HasMetadata = true; result.Item = video.ToEpisode(); + result.Item.Path = info.Path; result.Provider = Name; result.People = peopleInfo; + _logger.LogInformation("{Message}", "Result of video to episode: \n" + JsonConvert.SerializeObject(result)); } return result; diff --git a/Jellyfin.Plugin.TubeArchivistMetadata/TubeArchivist/TubeArchivistApi.cs b/Jellyfin.Plugin.TubeArchivistMetadata/TubeArchivist/TubeArchivistApi.cs index 18e4672..136e2e4 100644 --- a/Jellyfin.Plugin.TubeArchivistMetadata/TubeArchivist/TubeArchivistApi.cs +++ b/Jellyfin.Plugin.TubeArchivistMetadata/TubeArchivist/TubeArchivistApi.cs @@ -82,6 +82,7 @@ namespace Jellyfin.Plugin.TubeArchivistMetadata.TubeArchivist if (response.IsSuccessStatusCode) { string rawData = await response.Content.ReadAsStringAsync().ConfigureAwait(true); + _logger.LogInformation("{Message}", url + ": " + rawData); channel = JsonConvert.DeserializeObject(rawData); } diff --git a/Jellyfin.Plugin.TubeArchivistMetadata/TubeArchivist/Video/Video.cs b/Jellyfin.Plugin.TubeArchivistMetadata/TubeArchivist/Video/Video.cs index dec2ec0..8a7985c 100644 --- a/Jellyfin.Plugin.TubeArchivistMetadata/TubeArchivist/Video/Video.cs +++ b/Jellyfin.Plugin.TubeArchivistMetadata/TubeArchivist/Video/Video.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Globalization; +using System.IO; using System.Linq; using Jellyfin.Plugin.TubeArchivistMetadata.Utilities; using MediaBrowser.Controller.Entities; @@ -124,8 +125,9 @@ namespace Jellyfin.Plugin.TubeArchivistMetadata.TubeArchivist { Name = Title, Overview = Utils.FormatDescription(Description), - SeasonName = Published.Year.ToString(CultureInfo.CurrentCulture), + // SeasonName = Published.Year.ToString(CultureInfo.CurrentCulture), ParentIndexNumber = Published.Year, + IndexNumber = (Published.Year * 10000) + (Published.Month * 100) + Published.Day, SeriesName = Channel.Name, ProductionYear = Published.Year, PremiereDate = Published, From af375987ee198179b7e22440330ceb89dfef71a7 Mon Sep 17 00:00:00 2001 From: jadon <16850875+wolffshots@users.noreply.github.com> Date: Thu, 8 May 2025 00:06:50 +0200 Subject: [PATCH 02/17] chore: check library before updating watch status --- .../Plugin.cs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/Jellyfin.Plugin.TubeArchivistMetadata/Plugin.cs b/Jellyfin.Plugin.TubeArchivistMetadata/Plugin.cs index 600fabb..2c1482d 100644 --- a/Jellyfin.Plugin.TubeArchivistMetadata/Plugin.cs +++ b/Jellyfin.Plugin.TubeArchivistMetadata/Plugin.cs @@ -177,6 +177,11 @@ namespace Jellyfin.Plugin.TubeArchivistMetadata { BaseItem? season = LibraryManager.GetItemById(eventArgs.Item.ParentId); BaseItem? channel = LibraryManager.GetItemById(season!.ParentId); + var topParent = eventArgs.Item.GetTopParent(); + + if ((topParent?.Name ?? string.Empty) == (Instance?.Configuration.CollectionTitle ?? string.Empty) && topParent?.Name is not null) + { + BaseItem? channel = LibraryManager.GetItemById(eventArgs.Item.ParentId); BaseItem? collection = LibraryManager.GetItemById(channel!.ParentId); if (collection?.Name.ToLower(CultureInfo.CurrentCulture) == Instance?.Configuration.CollectionTitle.ToLower(CultureInfo.CurrentCulture) && eventArgs.PlaybackPositionTicks != null) { @@ -188,6 +193,11 @@ namespace Jellyfin.Plugin.TubeArchivistMetadata Logger.LogCritical("{Message}", $"POST /video/{videoId}/progress returned {statusCode} for video {eventArgs.Item.Name} with progress {progress} seconds"); } } + } + else + { + Logger.LogDebug("Parent name ({ParentName}) is not collection title({CollectionTitle})", topParent?.Name ?? string.Empty, Instance?.Configuration.CollectionTitle); + } } } @@ -196,6 +206,10 @@ namespace Jellyfin.Plugin.TubeArchivistMetadata var user = _userManager.GetUserById(eventArgs.UserId); if (Configuration.JFTASync && user != null && Configuration.GetJFUsernamesToArray().Contains(user!.Username)) { + var topParent = eventArgs.Item.GetTopParent(); + + if ((topParent?.Name ?? string.Empty) == (Instance?.Configuration.CollectionTitle ?? string.Empty) && topParent?.Name is not null) + { var isPlayed = eventArgs.Item.IsPlayed(user); Logger.LogDebug("User {UserId} changed watched status to {Status} for the item {ItemName}", eventArgs.UserId, isPlayed, eventArgs.Item.Name); string itemYTId; @@ -243,6 +257,11 @@ namespace Jellyfin.Plugin.TubeArchivistMetadata { Logger.LogCritical("An exception occurred while calling POST /watched for item {ItemName} ({VideoYTId}) with watched status {IsPlayed}: {ExceptionMessage}", eventArgs.Item.Name, itemYTId, isPlayed, ex.Message); } + } + else + { + Logger.LogDebug("Parent name ({ParentName}) is not collection title({CollectionTitle})", topParent?.Name ?? string.Empty, Instance?.Configuration.CollectionTitle); + } } } } From 2f90d6a03ed60f48f4c910b70c58c1c852417065 Mon Sep 17 00:00:00 2001 From: jadon <16850875+wolffshots@users.noreply.github.com> Date: Wed, 28 May 2025 23:32:06 +0200 Subject: [PATCH 03/17] chore: remove extra season and move into if --- Jellyfin.Plugin.TubeArchivistMetadata/Plugin.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Jellyfin.Plugin.TubeArchivistMetadata/Plugin.cs b/Jellyfin.Plugin.TubeArchivistMetadata/Plugin.cs index 2c1482d..2ef5ab7 100644 --- a/Jellyfin.Plugin.TubeArchivistMetadata/Plugin.cs +++ b/Jellyfin.Plugin.TubeArchivistMetadata/Plugin.cs @@ -175,13 +175,12 @@ namespace Jellyfin.Plugin.TubeArchivistMetadata { if (Instance!.Configuration.JFTASync && eventArgs.Users.Any(u => Instance!.Configuration.JFUsernameFrom.Equals(u.Username, StringComparison.Ordinal))) { - BaseItem? season = LibraryManager.GetItemById(eventArgs.Item.ParentId); - BaseItem? channel = LibraryManager.GetItemById(season!.ParentId); var topParent = eventArgs.Item.GetTopParent(); if ((topParent?.Name ?? string.Empty) == (Instance?.Configuration.CollectionTitle ?? string.Empty) && topParent?.Name is not null) { - BaseItem? channel = LibraryManager.GetItemById(eventArgs.Item.ParentId); + BaseItem? season = LibraryManager.GetItemById(eventArgs.Item.ParentId); + BaseItem? channel = LibraryManager.GetItemById(season!.ParentId); BaseItem? collection = LibraryManager.GetItemById(channel!.ParentId); if (collection?.Name.ToLower(CultureInfo.CurrentCulture) == Instance?.Configuration.CollectionTitle.ToLower(CultureInfo.CurrentCulture) && eventArgs.PlaybackPositionTicks != null) { From 784592b3623e1ac6fb8230c62096cbeb5b1c08da Mon Sep 17 00:00:00 2001 From: wolffshots <16850875+wolffshots@users.noreply.github.com> Date: Thu, 29 May 2025 10:52:07 +0200 Subject: [PATCH 04/17] chore: remove debugging log statements --- .../Providers/EpisodeMetadataProvider.cs | 1 - .../TubeArchivist/TubeArchivistApi.cs | 1 - .../TubeArchivist/Video/Video.cs | 2 +- 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/Jellyfin.Plugin.TubeArchivistMetadata/Providers/EpisodeMetadataProvider.cs b/Jellyfin.Plugin.TubeArchivistMetadata/Providers/EpisodeMetadataProvider.cs index a3c1e70..d46c448 100644 --- a/Jellyfin.Plugin.TubeArchivistMetadata/Providers/EpisodeMetadataProvider.cs +++ b/Jellyfin.Plugin.TubeArchivistMetadata/Providers/EpisodeMetadataProvider.cs @@ -70,7 +70,6 @@ namespace Jellyfin.Plugin.TubeArchivistMetadata.Providers result.Item.Path = info.Path; result.Provider = Name; result.People = peopleInfo; - _logger.LogInformation("{Message}", "Result of video to episode: \n" + JsonConvert.SerializeObject(result)); } return result; diff --git a/Jellyfin.Plugin.TubeArchivistMetadata/TubeArchivist/TubeArchivistApi.cs b/Jellyfin.Plugin.TubeArchivistMetadata/TubeArchivist/TubeArchivistApi.cs index 136e2e4..18e4672 100644 --- a/Jellyfin.Plugin.TubeArchivistMetadata/TubeArchivist/TubeArchivistApi.cs +++ b/Jellyfin.Plugin.TubeArchivistMetadata/TubeArchivist/TubeArchivistApi.cs @@ -82,7 +82,6 @@ namespace Jellyfin.Plugin.TubeArchivistMetadata.TubeArchivist if (response.IsSuccessStatusCode) { string rawData = await response.Content.ReadAsStringAsync().ConfigureAwait(true); - _logger.LogInformation("{Message}", url + ": " + rawData); channel = JsonConvert.DeserializeObject(rawData); } diff --git a/Jellyfin.Plugin.TubeArchivistMetadata/TubeArchivist/Video/Video.cs b/Jellyfin.Plugin.TubeArchivistMetadata/TubeArchivist/Video/Video.cs index 8a7985c..03d5fd2 100644 --- a/Jellyfin.Plugin.TubeArchivistMetadata/TubeArchivist/Video/Video.cs +++ b/Jellyfin.Plugin.TubeArchivistMetadata/TubeArchivist/Video/Video.cs @@ -125,7 +125,7 @@ namespace Jellyfin.Plugin.TubeArchivistMetadata.TubeArchivist { Name = Title, Overview = Utils.FormatDescription(Description), - // SeasonName = Published.Year.ToString(CultureInfo.CurrentCulture), + SeasonName = Published.Year.ToString(CultureInfo.CurrentCulture), ParentIndexNumber = Published.Year, IndexNumber = (Published.Year * 10000) + (Published.Month * 100) + Published.Day, SeriesName = Channel.Name, From d36d6771798c60b2a7da9192527202922496b313 Mon Sep 17 00:00:00 2001 From: wolffshots <16850875+wolffshots@users.noreply.github.com> Date: Thu, 29 May 2025 10:57:02 +0200 Subject: [PATCH 05/17] chore: remove unused import --- .../TubeArchivist/Video/Video.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/Jellyfin.Plugin.TubeArchivistMetadata/TubeArchivist/Video/Video.cs b/Jellyfin.Plugin.TubeArchivistMetadata/TubeArchivist/Video/Video.cs index 03d5fd2..0d054a2 100644 --- a/Jellyfin.Plugin.TubeArchivistMetadata/TubeArchivist/Video/Video.cs +++ b/Jellyfin.Plugin.TubeArchivistMetadata/TubeArchivist/Video/Video.cs @@ -2,7 +2,6 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Globalization; -using System.IO; using System.Linq; using Jellyfin.Plugin.TubeArchivistMetadata.Utilities; using MediaBrowser.Controller.Entities; From 5ab52243281f13a32e337673a37807d4eb88254f Mon Sep 17 00:00:00 2001 From: wolffshots <16850875+wolffshots@users.noreply.github.com> Date: Thu, 29 May 2025 11:00:44 +0200 Subject: [PATCH 06/17] chore: ran dotnet format on Plugin.cs --- .../Plugin.cs | 108 +++++++++--------- 1 file changed, 54 insertions(+), 54 deletions(-) diff --git a/Jellyfin.Plugin.TubeArchivistMetadata/Plugin.cs b/Jellyfin.Plugin.TubeArchivistMetadata/Plugin.cs index 2ef5ab7..b5f4b93 100644 --- a/Jellyfin.Plugin.TubeArchivistMetadata/Plugin.cs +++ b/Jellyfin.Plugin.TubeArchivistMetadata/Plugin.cs @@ -179,20 +179,20 @@ namespace Jellyfin.Plugin.TubeArchivistMetadata if ((topParent?.Name ?? string.Empty) == (Instance?.Configuration.CollectionTitle ?? string.Empty) && topParent?.Name is not null) { - BaseItem? season = LibraryManager.GetItemById(eventArgs.Item.ParentId); - BaseItem? channel = LibraryManager.GetItemById(season!.ParentId); - BaseItem? collection = LibraryManager.GetItemById(channel!.ParentId); - if (collection?.Name.ToLower(CultureInfo.CurrentCulture) == Instance?.Configuration.CollectionTitle.ToLower(CultureInfo.CurrentCulture) && eventArgs.PlaybackPositionTicks != null) - { - long progress = (long)eventArgs.PlaybackPositionTicks / TimeSpan.TicksPerSecond; - var videoId = Utils.GetVideoNameFromPath(eventArgs.Item.Path); - var statusCode = await TubeArchivistApi.GetInstance().SetProgress(videoId, progress).ConfigureAwait(true); - if (statusCode != System.Net.HttpStatusCode.OK) + BaseItem? season = LibraryManager.GetItemById(eventArgs.Item.ParentId); + BaseItem? channel = LibraryManager.GetItemById(season!.ParentId); + BaseItem? collection = LibraryManager.GetItemById(channel!.ParentId); + if (collection?.Name.ToLower(CultureInfo.CurrentCulture) == Instance?.Configuration.CollectionTitle.ToLower(CultureInfo.CurrentCulture) && eventArgs.PlaybackPositionTicks != null) { - Logger.LogCritical("{Message}", $"POST /video/{videoId}/progress returned {statusCode} for video {eventArgs.Item.Name} with progress {progress} seconds"); + long progress = (long)eventArgs.PlaybackPositionTicks / TimeSpan.TicksPerSecond; + var videoId = Utils.GetVideoNameFromPath(eventArgs.Item.Path); + var statusCode = await TubeArchivistApi.GetInstance().SetProgress(videoId, progress).ConfigureAwait(true); + if (statusCode != System.Net.HttpStatusCode.OK) + { + Logger.LogCritical("{Message}", $"POST /video/{videoId}/progress returned {statusCode} for video {eventArgs.Item.Name} with progress {progress} seconds"); + } } } - } else { Logger.LogDebug("Parent name ({ParentName}) is not collection title({CollectionTitle})", topParent?.Name ?? string.Empty, Instance?.Configuration.CollectionTitle); @@ -209,53 +209,53 @@ namespace Jellyfin.Plugin.TubeArchivistMetadata if ((topParent?.Name ?? string.Empty) == (Instance?.Configuration.CollectionTitle ?? string.Empty) && topParent?.Name is not null) { - var isPlayed = eventArgs.Item.IsPlayed(user); - Logger.LogDebug("User {UserId} changed watched status to {Status} for the item {ItemName}", eventArgs.UserId, isPlayed, eventArgs.Item.Name); - string itemYTId; - try - { - if (eventArgs.Item is Series) + var isPlayed = eventArgs.Item.IsPlayed(user); + Logger.LogDebug("User {UserId} changed watched status to {Status} for the item {ItemName}", eventArgs.UserId, isPlayed, eventArgs.Item.Name); + string itemYTId; + try { - itemYTId = Utils.GetChannelNameFromPath(eventArgs.Item.Path); - } - else if (eventArgs.Item is Episode) - { - itemYTId = Utils.GetVideoNameFromPath(eventArgs.Item.Path); - } - else - { - return; - } - } - catch (Exception ex) - { - Logger.LogError(ex, "Error while processing item path: {ItemPath}", eventArgs.Item.Path ?? "null"); - return; - } - - try - { - var statusCode = await TubeArchivistApi.GetInstance().SetWatchedStatus(itemYTId, isPlayed).ConfigureAwait(true); - if (statusCode != System.Net.HttpStatusCode.OK) - { - Logger.LogCritical("POST /watched returned {StatusCode} for item {ItemName} ({VideoYTId}) with watched status {IsPlayed}", statusCode, eventArgs.Item.Name, itemYTId, isPlayed); - } - - if (eventArgs.Item is Episode) - { - var progress = _userDataManager.GetUserData(user, eventArgs.Item).PlaybackPositionTicks / TimeSpan.TicksPerSecond; - var videoId = Utils.GetVideoNameFromPath(eventArgs.Item.Path); - statusCode = await TubeArchivistApi.GetInstance().SetProgress(videoId, progress).ConfigureAwait(true); - if (statusCode != System.Net.HttpStatusCode.OK) + if (eventArgs.Item is Series) { - Logger.LogCritical("{Message}", $"POST /video/{videoId}/progress returned {statusCode} for video {eventArgs.Item.Name} with progress {progress} seconds"); + itemYTId = Utils.GetChannelNameFromPath(eventArgs.Item.Path); + } + else if (eventArgs.Item is Episode) + { + itemYTId = Utils.GetVideoNameFromPath(eventArgs.Item.Path); + } + else + { + return; } } - } - catch (Exception ex) - { - Logger.LogCritical("An exception occurred while calling POST /watched for item {ItemName} ({VideoYTId}) with watched status {IsPlayed}: {ExceptionMessage}", eventArgs.Item.Name, itemYTId, isPlayed, ex.Message); - } + catch (Exception ex) + { + Logger.LogError(ex, "Error while processing item path: {ItemPath}", eventArgs.Item.Path ?? "null"); + return; + } + + try + { + var statusCode = await TubeArchivistApi.GetInstance().SetWatchedStatus(itemYTId, isPlayed).ConfigureAwait(true); + if (statusCode != System.Net.HttpStatusCode.OK) + { + Logger.LogCritical("POST /watched returned {StatusCode} for item {ItemName} ({VideoYTId}) with watched status {IsPlayed}", statusCode, eventArgs.Item.Name, itemYTId, isPlayed); + } + + if (eventArgs.Item is Episode) + { + var progress = _userDataManager.GetUserData(user, eventArgs.Item).PlaybackPositionTicks / TimeSpan.TicksPerSecond; + var videoId = Utils.GetVideoNameFromPath(eventArgs.Item.Path); + statusCode = await TubeArchivistApi.GetInstance().SetProgress(videoId, progress).ConfigureAwait(true); + if (statusCode != System.Net.HttpStatusCode.OK) + { + Logger.LogCritical("{Message}", $"POST /video/{videoId}/progress returned {statusCode} for video {eventArgs.Item.Name} with progress {progress} seconds"); + } + } + } + catch (Exception ex) + { + Logger.LogCritical("An exception occurred while calling POST /watched for item {ItemName} ({VideoYTId}) with watched status {IsPlayed}: {ExceptionMessage}", eventArgs.Item.Name, itemYTId, isPlayed, ex.Message); + } } else { From a58139eca08968e6fc85a2269ff946e3c8e468ed Mon Sep 17 00:00:00 2001 From: wolffshots <16850875+wolffshots@users.noreply.github.com> Date: Thu, 29 May 2025 11:19:27 +0200 Subject: [PATCH 07/17] chore: remove duplicated efforts --- .../Plugin.cs | 114 ++++++++---------- 1 file changed, 51 insertions(+), 63 deletions(-) diff --git a/Jellyfin.Plugin.TubeArchivistMetadata/Plugin.cs b/Jellyfin.Plugin.TubeArchivistMetadata/Plugin.cs index b5f4b93..29f4233 100644 --- a/Jellyfin.Plugin.TubeArchivistMetadata/Plugin.cs +++ b/Jellyfin.Plugin.TubeArchivistMetadata/Plugin.cs @@ -173,93 +173,81 @@ namespace Jellyfin.Plugin.TubeArchivistMetadata private async void OnPlaybackProgress(object? sender, PlaybackProgressEventArgs eventArgs) { - if (Instance!.Configuration.JFTASync && eventArgs.Users.Any(u => Instance!.Configuration.JFUsernameFrom.Equals(u.Username, StringComparison.Ordinal))) + var topParent = eventArgs.Item.GetTopParent(); + if ( + Instance!.Configuration.JFTASync && + eventArgs.Users.Any(u => Instance!.Configuration.JFUsernameFrom.Equals(u.Username, StringComparison.Ordinal)) && + eventArgs.PlaybackPositionTicks.HasValue && + string.Equals(topParent?.Name, Instance?.Configuration.CollectionTitle, StringComparison.OrdinalIgnoreCase) + ) { - var topParent = eventArgs.Item.GetTopParent(); - - if ((topParent?.Name ?? string.Empty) == (Instance?.Configuration.CollectionTitle ?? string.Empty) && topParent?.Name is not null) + long progress = (long)eventArgs.PlaybackPositionTicks / TimeSpan.TicksPerSecond; + var videoId = Utils.GetVideoNameFromPath(eventArgs.Item.Path); + var statusCode = await TubeArchivistApi.GetInstance().SetProgress(videoId, progress).ConfigureAwait(true); + if (statusCode != System.Net.HttpStatusCode.OK) { - BaseItem? season = LibraryManager.GetItemById(eventArgs.Item.ParentId); - BaseItem? channel = LibraryManager.GetItemById(season!.ParentId); - BaseItem? collection = LibraryManager.GetItemById(channel!.ParentId); - if (collection?.Name.ToLower(CultureInfo.CurrentCulture) == Instance?.Configuration.CollectionTitle.ToLower(CultureInfo.CurrentCulture) && eventArgs.PlaybackPositionTicks != null) - { - long progress = (long)eventArgs.PlaybackPositionTicks / TimeSpan.TicksPerSecond; - var videoId = Utils.GetVideoNameFromPath(eventArgs.Item.Path); - var statusCode = await TubeArchivistApi.GetInstance().SetProgress(videoId, progress).ConfigureAwait(true); - if (statusCode != System.Net.HttpStatusCode.OK) - { - Logger.LogCritical("{Message}", $"POST /video/{videoId}/progress returned {statusCode} for video {eventArgs.Item.Name} with progress {progress} seconds"); - } - } - } - else - { - Logger.LogDebug("Parent name ({ParentName}) is not collection title({CollectionTitle})", topParent?.Name ?? string.Empty, Instance?.Configuration.CollectionTitle); + Logger.LogCritical("{Message}", $"POST /video/{videoId}/progress returned {statusCode} for video {eventArgs.Item.Name} with progress {progress} seconds"); } } } private async void OnWatchedStatusChange(object? sender, UserDataSaveEventArgs eventArgs) { + var topParent = eventArgs.Item.GetTopParent(); var user = _userManager.GetUserById(eventArgs.UserId); - if (Configuration.JFTASync && user != null && Configuration.GetJFUsernamesToArray().Contains(user!.Username)) + if ( + Configuration.JFTASync && + user != null && + Configuration.GetJFUsernamesToArray().Contains(user!.Username) && + string.Equals(topParent?.Name, Instance?.Configuration.CollectionTitle, StringComparison.OrdinalIgnoreCase) + ) { - var topParent = eventArgs.Item.GetTopParent(); - - if ((topParent?.Name ?? string.Empty) == (Instance?.Configuration.CollectionTitle ?? string.Empty) && topParent?.Name is not null) + var isPlayed = eventArgs.Item.IsPlayed(user); + Logger.LogDebug("User {UserId} changed watched status to {Status} for the item {ItemName}", eventArgs.UserId, isPlayed, eventArgs.Item.Name); + string itemYTId; + try { - var isPlayed = eventArgs.Item.IsPlayed(user); - Logger.LogDebug("User {UserId} changed watched status to {Status} for the item {ItemName}", eventArgs.UserId, isPlayed, eventArgs.Item.Name); - string itemYTId; - try + if (eventArgs.Item is Series) { - if (eventArgs.Item is Series) - { - itemYTId = Utils.GetChannelNameFromPath(eventArgs.Item.Path); - } - else if (eventArgs.Item is Episode) - { - itemYTId = Utils.GetVideoNameFromPath(eventArgs.Item.Path); - } - else - { - return; - } + itemYTId = Utils.GetChannelNameFromPath(eventArgs.Item.Path); } - catch (Exception ex) + else if (eventArgs.Item is Episode) + { + itemYTId = Utils.GetVideoNameFromPath(eventArgs.Item.Path); + } + else { - Logger.LogError(ex, "Error while processing item path: {ItemPath}", eventArgs.Item.Path ?? "null"); return; } + } + catch (Exception ex) + { + Logger.LogError(ex, "Error while processing item path: {ItemPath}", eventArgs.Item.Path ?? "null"); + return; + } - try + try + { + var statusCode = await TubeArchivistApi.GetInstance().SetWatchedStatus(itemYTId, isPlayed).ConfigureAwait(true); + if (statusCode != System.Net.HttpStatusCode.OK) { - var statusCode = await TubeArchivistApi.GetInstance().SetWatchedStatus(itemYTId, isPlayed).ConfigureAwait(true); + Logger.LogCritical("POST /watched returned {StatusCode} for item {ItemName} ({VideoYTId}) with watched status {IsPlayed}", statusCode, eventArgs.Item.Name, itemYTId, isPlayed); + } + + if (eventArgs.Item is Episode) + { + var progress = _userDataManager.GetUserData(user, eventArgs.Item).PlaybackPositionTicks / TimeSpan.TicksPerSecond; + var videoId = Utils.GetVideoNameFromPath(eventArgs.Item.Path); + statusCode = await TubeArchivistApi.GetInstance().SetProgress(videoId, progress).ConfigureAwait(true); if (statusCode != System.Net.HttpStatusCode.OK) { - Logger.LogCritical("POST /watched returned {StatusCode} for item {ItemName} ({VideoYTId}) with watched status {IsPlayed}", statusCode, eventArgs.Item.Name, itemYTId, isPlayed); + Logger.LogCritical("{Message}", $"POST /video/{videoId}/progress returned {statusCode} for video {eventArgs.Item.Name} with progress {progress} seconds"); } - - if (eventArgs.Item is Episode) - { - var progress = _userDataManager.GetUserData(user, eventArgs.Item).PlaybackPositionTicks / TimeSpan.TicksPerSecond; - var videoId = Utils.GetVideoNameFromPath(eventArgs.Item.Path); - statusCode = await TubeArchivistApi.GetInstance().SetProgress(videoId, progress).ConfigureAwait(true); - if (statusCode != System.Net.HttpStatusCode.OK) - { - Logger.LogCritical("{Message}", $"POST /video/{videoId}/progress returned {statusCode} for video {eventArgs.Item.Name} with progress {progress} seconds"); - } - } - } - catch (Exception ex) - { - Logger.LogCritical("An exception occurred while calling POST /watched for item {ItemName} ({VideoYTId}) with watched status {IsPlayed}: {ExceptionMessage}", eventArgs.Item.Name, itemYTId, isPlayed, ex.Message); } } - else + catch (Exception ex) { - Logger.LogDebug("Parent name ({ParentName}) is not collection title({CollectionTitle})", topParent?.Name ?? string.Empty, Instance?.Configuration.CollectionTitle); + Logger.LogCritical("An exception occurred while calling POST /watched for item {ItemName} ({VideoYTId}) with watched status {IsPlayed}: {ExceptionMessage}", eventArgs.Item.Name, itemYTId, isPlayed, ex.Message); } } } From 3e95ca26aaf67daffe44bc66c56a0e42f9d41980 Mon Sep 17 00:00:00 2001 From: wolffshots <16850875+wolffshots@users.noreply.github.com> Date: Thu, 29 May 2025 11:23:44 +0200 Subject: [PATCH 08/17] chore: make sync task logs debugs --- .../Tasks/JFToTubeArchivistProgressSyncTask.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Jellyfin.Plugin.TubeArchivistMetadata/Tasks/JFToTubeArchivistProgressSyncTask.cs b/Jellyfin.Plugin.TubeArchivistMetadata/Tasks/JFToTubeArchivistProgressSyncTask.cs index cc04711..8c5c9b0 100644 --- a/Jellyfin.Plugin.TubeArchivistMetadata/Tasks/JFToTubeArchivistProgressSyncTask.cs +++ b/Jellyfin.Plugin.TubeArchivistMetadata/Tasks/JFToTubeArchivistProgressSyncTask.cs @@ -151,7 +151,7 @@ namespace Jellyfin.Plugin.TubeArchivistMetadata.Tasks foreach (Episode video in videos) { var videoYTId = Utils.GetVideoNameFromPath(video.Path); - _logger.LogInformation("{VideoYtId}", videoYTId); + _logger.LogDebug("{VideoYtId}", videoYTId); HttpStatusCode statusCode; if (!isChannelCheckedForWatched && channel.IsPlayed(user)) @@ -179,7 +179,7 @@ namespace Jellyfin.Plugin.TubeArchivistMetadata.Tasks _logger.LogCritical("{Message}", $"POST /watched returned {statusCode} for video {video.Name} ({videoYTId}) with wacthed status {isVideoPlayed}"); } - _logger.LogInformation("{Message}", isVideoPlayed); + _logger.LogDebug("{Message}", isVideoPlayed); if (!isVideoPlayed) { var playbackProgress = _userDataManager.GetUserData(user, video).PlaybackPositionTicks / TimeSpan.TicksPerSecond; From 5b62e4c0016300192b45feb256caeb121d305a66 Mon Sep 17 00:00:00 2001 From: DarkFighterLuke <31162436+DarkFighterLuke@users.noreply.github.com> Date: Sun, 13 Jul 2025 13:22:18 +0200 Subject: [PATCH 09/17] Update JFToTubeArchivistProgressSyncTask.cs --- .../Tasks/JFToTubeArchivistProgressSyncTask.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jellyfin.Plugin.TubeArchivistMetadata/Tasks/JFToTubeArchivistProgressSyncTask.cs b/Jellyfin.Plugin.TubeArchivistMetadata/Tasks/JFToTubeArchivistProgressSyncTask.cs index 8c5c9b0..3966494 100644 --- a/Jellyfin.Plugin.TubeArchivistMetadata/Tasks/JFToTubeArchivistProgressSyncTask.cs +++ b/Jellyfin.Plugin.TubeArchivistMetadata/Tasks/JFToTubeArchivistProgressSyncTask.cs @@ -151,7 +151,7 @@ namespace Jellyfin.Plugin.TubeArchivistMetadata.Tasks foreach (Episode video in videos) { var videoYTId = Utils.GetVideoNameFromPath(video.Path); - _logger.LogDebug("{VideoYtId}", videoYTId); + _logger.LogDebug("Current video extracted YouTube id: {VideoYtId}", videoYTId); HttpStatusCode statusCode; if (!isChannelCheckedForWatched && channel.IsPlayed(user)) From ff55b9f517b1de48d2408dee88348052f633097c Mon Sep 17 00:00:00 2001 From: DarkFighterLuke <31162436+DarkFighterLuke@users.noreply.github.com> Date: Sun, 13 Jul 2025 14:49:41 +0200 Subject: [PATCH 10/17] Update Plugin.cs --- Jellyfin.Plugin.TubeArchivistMetadata/Plugin.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jellyfin.Plugin.TubeArchivistMetadata/Plugin.cs b/Jellyfin.Plugin.TubeArchivistMetadata/Plugin.cs index fb4951d..de11f03 100644 --- a/Jellyfin.Plugin.TubeArchivistMetadata/Plugin.cs +++ b/Jellyfin.Plugin.TubeArchivistMetadata/Plugin.cs @@ -173,7 +173,7 @@ namespace Jellyfin.Plugin.TubeArchivistMetadata private async void OnPlaybackProgress(object? sender, PlaybackProgressEventArgs eventArgs) { - if (eventArgs == null || eventArgs.ItemId == Guid.Empty) + if (eventArgs == null || eventArgs.Item.Id == Guid.Empty) { Logger.LogDebug("Skipping progress synchronization: PlaybackProgress event triggered with null or empty Guid."); return; From 4358072001f505c02e70c5a60de5d9d676a4c987 Mon Sep 17 00:00:00 2001 From: wolffshots <16850875+wolffshots@users.noreply.github.com> Date: Mon, 4 Aug 2025 18:21:30 +0200 Subject: [PATCH 11/17] feat: add configuration for episode numbering scheme --- .../Configuration/NumberingScheme.cs | 17 +++++++++++++++++ .../Configuration/PluginConfiguration.cs | 5 +++++ .../Configuration/configPage.html | 14 ++++++++++++++ .../TubeArchivist/Video/Video.cs | 7 ++++++- 4 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 Jellyfin.Plugin.TubeArchivistMetadata/Configuration/NumberingScheme.cs diff --git a/Jellyfin.Plugin.TubeArchivistMetadata/Configuration/NumberingScheme.cs b/Jellyfin.Plugin.TubeArchivistMetadata/Configuration/NumberingScheme.cs new file mode 100644 index 0000000..c8a99d2 --- /dev/null +++ b/Jellyfin.Plugin.TubeArchivistMetadata/Configuration/NumberingScheme.cs @@ -0,0 +1,17 @@ +namespace Jellyfin.Plugin.TubeArchivistMetadata.Configuration; + +/// +/// The NumberingScheme. +/// +public enum NumberingScheme +{ + /// + /// Default (no numbering). + /// + Default, + + /// + /// YYYYMMDD (e.g. 20250804 for August 4th, 2025). + /// + YYYYMMDD, +} diff --git a/Jellyfin.Plugin.TubeArchivistMetadata/Configuration/PluginConfiguration.cs b/Jellyfin.Plugin.TubeArchivistMetadata/Configuration/PluginConfiguration.cs index ce10eef..e7acccc 100644 --- a/Jellyfin.Plugin.TubeArchivistMetadata/Configuration/PluginConfiguration.cs +++ b/Jellyfin.Plugin.TubeArchivistMetadata/Configuration/PluginConfiguration.cs @@ -148,6 +148,11 @@ namespace Jellyfin.Plugin.TubeArchivistMetadata.Configuration /// public int TAJFTaskInterval { get; set; } + /// + /// Gets or sets the preferred numbering scheme for episodes (index number) in Jellyfin. + /// + public NumberingScheme EpisodeNumberingScheme { get; set; } = NumberingScheme.Default; + /// /// Gets the playback progress owners Jellyfin usernames to synchronize data from TubeArchivist. /// diff --git a/Jellyfin.Plugin.TubeArchivistMetadata/Configuration/configPage.html b/Jellyfin.Plugin.TubeArchivistMetadata/Configuration/configPage.html index d4e07d5..ac93f4d 100644 --- a/Jellyfin.Plugin.TubeArchivistMetadata/Configuration/configPage.html +++ b/Jellyfin.Plugin.TubeArchivistMetadata/Configuration/configPage.html @@ -79,6 +79,18 @@
This is the TubeArchivist to Jellyfin playback progress synchronization interval in seconds (Jellyfin restart required).
+
+ + +
+ +
+
This is the numbering scheme for episodes in Jellyfin (IndexNumber). + Default is the same as no numbering which allows Jellyfin to use the fallback numbering scheme.
+
+
+ + +
+ +
+
This is the numbering scheme for episodes in Jellyfin (IndexNumber). + Default is the same as no numbering which allows Jellyfin to use the fallback numbering scheme. +

Synchronization

@@ -118,17 +130,6 @@
This is the TubeArchivist to Jellyfin playback progress synchronization interval in seconds (Jellyfin restart required).
-
- - -
- -
-
This is the numbering scheme for episodes in Jellyfin (IndexNumber). - Default is the same as no numbering which allows Jellyfin to use the fallback numbering scheme.
From 0c8bc243c61929c454d52ac93f40fb8abaa31e77 Mon Sep 17 00:00:00 2001 From: DarkFighterLuke <31162436+DarkFighterLuke@users.noreply.github.com> Date: Thu, 23 Oct 2025 22:19:22 +0200 Subject: [PATCH 17/17] Update Utils.cs --- Jellyfin.Plugin.TubeArchivistMetadata/Utils/Utils.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jellyfin.Plugin.TubeArchivistMetadata/Utils/Utils.cs b/Jellyfin.Plugin.TubeArchivistMetadata/Utils/Utils.cs index 7077d52..d61e626 100644 --- a/Jellyfin.Plugin.TubeArchivistMetadata/Utils/Utils.cs +++ b/Jellyfin.Plugin.TubeArchivistMetadata/Utils/Utils.cs @@ -49,7 +49,7 @@ namespace Jellyfin.Plugin.TubeArchivistMetadata.Utilities { if (description == null) { - return "Description is null"; + return ""; } var maxLength = 500;