diff --git a/.vscode/extensions.json b/.vscode/extensions.json deleted file mode 100644 index 698bc34..0000000 --- a/.vscode/extensions.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - // See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations. - // Extension identifier format: ${publisher}.${name}. Example: vscode.csharp - // List of extensions which should be recommended for users of this workspace. - "recommendations": [ - "ms-dotnettools.csharp", - "editorconfig.editorconfig" - ], - // List of extensions recommended by VS Code that should not be recommended for users of this workspace. - "unwantedRecommendations": [] -} \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index 9f17676..0000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - // Paths and plugin names are configured in settings.json - "version": "0.2.0", - "configurations": [ - { - "type": "coreclr", - "name": "Launch", - "request": "launch", - "preLaunchTask": "build-and-copy", - "program": "${config:jellyfinDir}/bin/Debug/net9.0/jellyfin.dll", - "args": [ - //"--nowebclient" - "--webdir", - "${config:jellyfinWebDir}/dist/" - ], - "cwd": "${config:jellyfinDir}", - } - ] -} diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index b075e97..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - // jellyfinDir : The directory of the cloned jellyfin server project - // This needs to be built once before it can be used - "jellyfinDir": "${workspaceFolder}/../jellyfin/Jellyfin.Server", - // jellyfinWebDir : The directory of the cloned jellyfin-web project - // This needs to be built once before it can be used - "jellyfinWebDir": "${workspaceFolder}/../jellyfin-web", - // jellyfinDataDir : the root data directory for a running jellyfin instance - // This is where jellyfin stores its configs, plugins, metadata etc - // This is platform specific by default, but on Windows defaults to - // ${env:LOCALAPPDATA}/jellyfin - // and on Linux, it defaults to - // ${env:XDG_DATA_HOME}/jellyfin - // However ${env:XDG_DATA_HOME} does not work in Visual Studio Code's development container! - "jellyfinWindowsDataDir": "${env:LOCALAPPDATA}/jellyfin", - "jellyfinLinuxDataDir": "$HOME/.local/share/jellyfin", - // The name of the plugin - "pluginName": "Jellyfin.Plugin.MediaCleaner", -} diff --git a/.vscode/tasks.json b/.vscode/tasks.json deleted file mode 100644 index 62e3e70..0000000 --- a/.vscode/tasks.json +++ /dev/null @@ -1,76 +0,0 @@ -{ - // Paths and plugin name are configured in settings.json - "version": "2.0.0", - "tasks": [ - { - // A chain task - build the plugin, then copy it to your - // jellyfin server's plugin directory - "label": "build-and-copy", - "dependsOrder": "sequence", - "dependsOn": [ - "build", - "make-plugin-dir", - "copy-dll" - ] - }, - { - // Build the plugin - "label": "build", - "command": "dotnet", - "type": "shell", - "args": [ - "publish", - "--configuration=Debug", - "${workspaceFolder}\\${config:pluginName}.sln", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "group": "build", - "presentation": { - "reveal": "silent" - }, - "problemMatcher": "$msCompile" - }, - { - // Ensure the plugin directory exists before trying to use it - "label": "make-plugin-dir", - "type": "shell", - "command": "mkdir", - "windows": { - "args": [ - "-Force", - "-Path", - "${config:jellyfinWindowsDataDir}/plugins/${config:pluginName}/" - ] - }, - "linux": { - "args": [ - "-p", - "${config:jellyfinLinuxDataDir}/plugins/${config:pluginName}/" - ] - } - }, - { - // Copy the plugin dll to the jellyfin plugin install path - // This command copies every .dll from the build directory to the plugin dir - // Usually, you probablly only need ${config:pluginName}.dll - // But some plugins may bundle extra requirements - "label": "copy-dll", - "type": "shell", - "command": "cp", - "windows": { - "args": [ - "./${config:pluginName}/bin/Debug/net9.0/publish/*", - "${config:jellyfinWindowsDataDir}/plugins/${config:pluginName}/" - ] - }, - "linux": { - "args": [ - "-r", - "./${config:pluginName}/bin/Debug/net9.0/publish/*", - "${config:jellyfinLinuxDataDir}/plugins/${config:pluginName}/" - ] - } - }, - ] -} diff --git a/Jellyfin.Plugin.MediaCleaner/Jellyfin.Plugin.MediaCleaner.csproj b/Jellyfin.Plugin.MediaCleaner/Jellyfin.Plugin.MediaCleaner.csproj index 6fb1a62..7dbda16 100644 --- a/Jellyfin.Plugin.MediaCleaner/Jellyfin.Plugin.MediaCleaner.csproj +++ b/Jellyfin.Plugin.MediaCleaner/Jellyfin.Plugin.MediaCleaner.csproj @@ -11,10 +11,10 @@ - + runtime - + runtime diff --git a/Jellyfin.Plugin.MediaCleaner/Plugin.cs b/Jellyfin.Plugin.MediaCleaner/Plugin.cs index 530c2e6..f28a686 100644 --- a/Jellyfin.Plugin.MediaCleaner/Plugin.cs +++ b/Jellyfin.Plugin.MediaCleaner/Plugin.cs @@ -4,6 +4,7 @@ using System.Globalization; using Jellyfin.Plugin.MediaCleaner.Configuration; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Plugins; +using MediaBrowser.Controller.Entities; using MediaBrowser.Model.Plugins; using MediaBrowser.Model.Serialization; @@ -36,6 +37,10 @@ public class Plugin : BasePlugin, IHasWebPages /// public static Plugin? Instance { get; private set; } + private static List StaleMovies { get; set; } = new(); + + private static List StaleShows { get; set; } = new(); + /// public IEnumerable GetPages() { diff --git a/Jellyfin.Plugin.MediaCleaner/ScheduledTasks/StaleMediaTask.cs b/Jellyfin.Plugin.MediaCleaner/ScheduledTasks/StaleMediaTask.cs new file mode 100644 index 0000000..8f187c9 --- /dev/null +++ b/Jellyfin.Plugin.MediaCleaner/ScheduledTasks/StaleMediaTask.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Jellyfin.Data.Enums; +using Jellyfin.Database.Implementations.Entities; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Library; +using MediaBrowser.Model.Tasks; +using Microsoft.Extensions.Logging; + +namespace Jellyfin.Plugin.MediaCleaner.ScheduledTasks; + +/// +/// A task to scan media for stale files. +/// +public sealed class StaleMediaTask : IScheduledTask +{ + private readonly ILogger _logger; + private readonly IUserManager _userManager; + private readonly ILibraryManager _libraryManager; + + /// + /// Initializes a new instance of the class. + /// + /// Logger. + /// User manager. + /// . + public StaleMediaTask(ILogger logger, IUserManager userManager, ILibraryManager libraryManager) + { + _logger = logger; + _userManager = userManager; + _libraryManager = libraryManager; + } + + string IScheduledTask.Name => "Scan Stale Media"; + + string IScheduledTask.Key => "Stale Media"; + + string IScheduledTask.Description => "Scan Stale Media"; + + string IScheduledTask.Category => "Media"; + + Task IScheduledTask.ExecuteAsync(IProgress progress, CancellationToken cancellationToken) + { + var query = new InternalItemsQuery + { + IncludeItemTypes = new[] { BaseItemKind.Movie, BaseItemKind.Series }, + Recursive = true + }; + var allItems = _libraryManager.GetItemsResult(query).Items; + + _logger.LogInformation("Total items found: {AllItems}", allItems); + + foreach (BaseItem item in allItems) + { + var userData = item.UserData.ToList(); + var mostRecentUserData = userData.OrderByDescending(data => data.LastPlayedDate).First(); + if (mostRecentUserData.LastPlayedDate < DateTime.Now.AddDays(1)) + { + // Stale data + } + } + + Debugger.Break(); + + return Task.CompletedTask; + } + + IEnumerable IScheduledTask.GetDefaultTriggers() + { + // Run this task every 24 hours + yield return new TaskTriggerInfo + { + Type = TaskTriggerInfoType.IntervalTrigger, + IntervalTicks = TimeSpan.FromHours(24).Ticks + }; + } +}