diff --git a/Jellyfin.Plugin.TubeArchivistMetadata/Tasks/JFToTubeArchivistProgressSyncTask.cs b/Jellyfin.Plugin.TubeArchivistMetadata/Tasks/JFToTubeArchivistProgressSyncTask.cs new file mode 100644 index 0000000..103c3d5 --- /dev/null +++ b/Jellyfin.Plugin.TubeArchivistMetadata/Tasks/JFToTubeArchivistProgressSyncTask.cs @@ -0,0 +1,145 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Jellyfin.Data.Enums; +using Jellyfin.Plugin.TubeArchivistMetadata.TubeArchivist; +using Jellyfin.Plugin.TubeArchivistMetadata.Utilities; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.TV; +using MediaBrowser.Controller.Library; +using MediaBrowser.Model.Dto; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Tasks; +using Microsoft.Extensions.Logging; + +namespace Jellyfin.Plugin.TubeArchivistMetadata.Tasks +{ + /// + /// Task to sync Jellyfin playback progresses to TubeArchivist. + /// + public class JFToTubearchivistProgressSyncTask : IScheduledTask + { + private readonly ILogger _logger; + private readonly ILibraryManager _libraryManager; + private readonly IUserManager _userManager; + private readonly IUserDataManager _userDataManager; + + /// + /// Initializes a new instance of the class. + /// + /// Logger. + /// Library manager. + /// User manager. + /// User data manager. + public JFToTubearchivistProgressSyncTask(ILogger logger, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataManager) + { + _logger = logger; + _libraryManager = libraryManager; + _userManager = userManager; + _userDataManager = userDataManager; + } + + /// + public string Name => "JFToTubearchivistProgressSyncTask"; + + /// + public string Description => "This tasks syncs TubeArchivist playback progresses to Jellyfin"; + + /// + public string Category => "TubeArchivistMetadata"; + + /// + public string Key => "JFToTubearchivistProgressSyncTask"; + + /// + public async Task ExecuteAsync(IProgress progress, CancellationToken cancellationToken) + { + if (Plugin.Instance!.Configuration.TAJFSync) + { + var start = DateTime.Now; + _logger.LogInformation("Starting Jellyfin->TubeArchivist playback progresses synchronization."); + var taApi = TubeArchivistApi.GetInstance(); + foreach (var jfUsername in Plugin.Instance!.Configuration.GetJFUsernamesToArray()) + { + var user = _userManager.GetUserByName(jfUsername); + if (user == null) + { + _logger.LogInformation("{Message}", $"Jellyfin user with username {jfUsername} not found"); + continue; + } + + var collectionItem = _libraryManager.GetItemList(new InternalItemsQuery + { + Name = Plugin.Instance?.Configuration.CollectionTitle, + IncludeItemTypes = new[] { BaseItemKind.CollectionFolder } + }).FirstOrDefault(); + + if (collectionItem == null) + { + var message = $"Collection '{Plugin.Instance?.Configuration.CollectionTitle}' not found."; + _logger.LogCritical("{Message}", message); + } + else + { + var collection = (CollectionFolder)collectionItem; + var channels = collection.GetChildren(user, false, new InternalItemsQuery + { + IncludeItemTypes = new[] { BaseItemKind.Series } + }); + _logger.LogInformation("Analyzing collection {Id} with name {Name}", collectionItem.Id, collectionItem.Name); + _logger.LogInformation("Found {Message} channels", channels.Count); + + foreach (Series channel in channels) + { + var years = channel.GetChildren(user, false, new InternalItemsQuery + { + IncludeItemTypes = new[] { BaseItemKind.Season } + }); + _logger.LogInformation("Found {Years} years in channel {ChannelName}", years.Count, channel.Name); + + foreach (Season year in years) + { + var videos = year.GetChildren(user, false, new InternalItemsQuery + { + IncludeItemTypes = new[] { BaseItemKind.Episode } + }); + _logger.LogInformation("Found {Videos} videos in year {YearName} of the channel {ChannelName}", videos.Count, year.Name, channel.Name); + + foreach (Episode video in videos) + { + var videoYTId = Utils.GetVideoNameFromPath(video.Path); + var playbackProgress = _userDataManager.GetUserData(user.Id, video).PlaybackPositionTicks / TimeSpan.TicksPerSecond; + var statusCode = await taApi.SetProgress(videoYTId, playbackProgress).ConfigureAwait(true); + if (statusCode != System.Net.HttpStatusCode.OK) + { + _logger.LogInformation("{Message}", $"POST /video/{videoYTId}/progress returned {statusCode} for video {video.Name} with progress {progress} seconds"); + } + } + } + } + } + } + + _logger.LogInformation("Time elapsed: {Time}", DateTime.Now - start); + } + else + { + _logger.LogInformation("Jellyfin->TubeArchivist playback synchronization is currently disabled."); + } + } + + /// + public IEnumerable GetDefaultTriggers() + { + return + [ + new TaskTriggerInfo + { + Type = TaskTriggerInfo.TriggerStartup, + }, + ]; + } + } +}