Add configuration options

This commit is contained in:
DarkFighterLuke
2025-07-10 22:32:22 +02:00
parent 46dd4fcf5b
commit d386f79dfd
7 changed files with 139 additions and 41 deletions
@@ -36,11 +36,17 @@ namespace Jellyfin.Plugin.TubeArchivistMetadata.Configuration
_tubeArchivistUrl = string.Empty;
_tubeArchivistApiKey = string.Empty;
MaxDescriptionLength = 500;
JFTASync = false;
JFTAProgressSync = false;
JFUsernameFrom = string.Empty;
TAJFSync = false;
TAJFProgressSync = false;
JFTAPlaylistsSync = false;
JFTAPlaylistsDelete = false;
TAJFPlaylistsSync = false;
TAJFPlaylistsDelete = false;
_jfUsernamesTo = new HashSet<string>();
TAJFTaskInterval = 1;
TAJFProgressTaskInterval = 60;
JFTAPlaylistsSyncTaskInterval = 60;
TAJFPlaylistsSyncTaskInterval = 60;
}
/// <summary>
@@ -100,12 +106,32 @@ namespace Jellyfin.Plugin.TubeArchivistMetadata.Configuration
/// <summary>
/// Gets or sets a value indicating whether to enable TA->JF playback progress synchronization.
/// </summary>
public bool TAJFSync { get; set; }
public bool TAJFProgressSync { get; set; }
/// <summary>
/// Gets or sets a value indicating whether to enable JF->TA playback progress synchronization.
/// </summary>
public bool JFTASync { get; set; }
public bool JFTAProgressSync { get; set; }
/// <summary>
/// Gets or sets a value indicating whether to enable JF->TA playlists synchronization.
/// </summary>
public bool JFTAPlaylistsSync { get; set; }
/// <summary>
/// Gets or sets a value indicating whether to delete playlists from TA when not found on JF.
/// </summary>
public bool JFTAPlaylistsDelete { get; set; }
/// <summary>
/// Gets or sets a value indicating whether to enable TA->JF playlists synchronization.
/// </summary>
public bool TAJFPlaylistsSync { get; set; }
/// <summary>
/// Gets or sets a value indicating whether to delete playlists from JF when not found on TA.
/// </summary>
public bool TAJFPlaylistsDelete { get; set; }
/// <summary>
/// Gets or sets the playback progress owner Jellyfin username to synchronize data to TubeArchivist.
@@ -146,7 +172,19 @@ namespace Jellyfin.Plugin.TubeArchivistMetadata.Configuration
/// Gets or sets the interval in seconds at which the TubeArchivist to Jellyfin playback progress synchronization task should run.
/// It requires Jellyfin server restart to take effect.
/// </summary>
public int TAJFTaskInterval { get; set; }
public int TAJFProgressTaskInterval { get; set; }
/// <summary>
/// Gets or sets the interval in seconds at which the Jellyfin to TubeArchivist playlists synchronization task should run.
/// It requires Jellyfin server restart to take effect.
/// </summary>
public int JFTAPlaylistsSyncTaskInterval { get; set; }
/// <summary>
/// Gets or sets the interval in seconds at which the TubeArchivist to Jellyfin playlists synchronization task should run.
/// It requires Jellyfin server restart to take effect.
/// </summary>
public int TAJFPlaylistsSyncTaskInterval { get; set; }
/// <summary>
/// Gets the playback progress owners Jellyfin usernames to synchronize data from TubeArchivist.
@@ -42,28 +42,43 @@
and episodes</div>
</div>
<div>
<h2>Playback synchronization</h2>
<h2>Synchronization</h2>
</div>
<div class="checkboxContainer checkboxContainer-withDescription">
<label class="emby-checkbox-label" for="JFTASync">
<input id="JFTASync" name="JFTASync" type="checkbox" is="emby-checkbox" />
<span>Synchronize Jellyfin playback progress to TubeArchivist</span>
</label>
<div>
<h3>Jellyfin to TubeArchivist</h3>
</div>
<div class="inputContainer">
<label class="inputLabel inputLabelUnfocused" for="JFUsernameFrom">Jellyfin username to sync
playback status from</label>
from</label>
<input id="JFUsernameFrom" name="JFUsernameFrom" type="text" is="emby-input"
placeholder="Username1, username2, ..." />
<div class="fieldDescription">This is the Jellyfin username to synchronize data from on
placeholder="Username" />
<div class="fieldDescription">This is the Jellyfin username to synchronize data to
TubeArchivist</div>
</div>
<div class="checkboxContainer checkboxContainer-withDescription">
<label class="emby-checkbox-label" for="TAJFSync">
<input id="TAJFSync" name="TAJFSync" type="checkbox" is="emby-checkbox" />
<span>Synchronize TubeArchivist playback progress to Jellyfin</span>
<label class="emby-checkbox-label" for="JFTAProgressSync">
<input id="JFTAProgressSync" name="JFTAProgressSync" type="checkbox" is="emby-checkbox" />
<span>Synchronize Jellyfin playback progress to TubeArchivist</span>
</label>
</div>
<div style="display: flex; gap: 2em;">
<div class="checkboxContainer checkboxContainer-withDescription">
<label class="emby-checkbox-label" for="JFTAPlaylistsSync">
<input id="JFTAPlaylistsSync" name="JFTAPlaylistsSync" type="checkbox" is="emby-checkbox" />
<span>Synchronize Jellyfin playlists to TubeArchivist</span>
</label>
</div>
<div class="checkboxContainer checkboxContainer-withDescription">
<label class="emby-checkbox-label" for="JFTAPlaylistsDelete">
<input id="JFTAPlaylistsDelete" name="JFTAPlaylistsDelete" type="checkbox" is="emby-checkbox" />
<span>Delete TubeArchivist playlists when no more present on Jellyfin</span>
</label>
</div>
</div>
<div>
<h3>TubeArchivist to Jellyfin</h3>
</div>
<div class="inputContainer">
<label class="inputLabel inputLabelUnfocused" for="JFUsernamesTo">Jellyfin usernames to sync
playback status to</label>
@@ -72,13 +87,52 @@
<div class="fieldDescription">These are the (comma separated) Jellyfin usernames to synchronize
data from TubeArchivist</div>
</div>
<div class="checkboxContainer checkboxContainer-withDescription">
<label class="emby-checkbox-label" for="TAJFProgressSync">
<input id="TAJFProgressSync" name="TAJFProgressSync" type="checkbox" is="emby-checkbox" />
<span>Synchronize TubeArchivist playback progress to Jellyfin</span>
</label>
</div>
<div style="display: flex; gap: 2em;">
<div class="checkboxContainer checkboxContainer-withDescription">
<label class="emby-checkbox-label" for="TAJFPlaylistsSync">
<input id="TAJFPlaylistsSync" name="TAJFPlaylistsSync" type="checkbox" is="emby-checkbox" />
<span>Synchronize TubeArchivist playlists to Jellyfin</span>
</label>
</div>
<div class="checkboxContainer checkboxContainer-withDescription">
<label class="emby-checkbox-label" for="TAJFPlaylistsDelete">
<input id="TAJFPlaylistsDelete" name="TAJFPlaylistsDelete" type="checkbox" is="emby-checkbox" />
<span>Delete Jellyfin playlists when no more present on TubeArchivist</span>
</label>
</div>
</div>
<div>
<h2>Tasks intervals</h2>
</div>
<div class="inputContainer">
<label class="inputLabel inputLabelUnfocused" for="TAJFTaskInterval">TubeArchivist to Jellyfin
<label class="inputLabel inputLabelUnfocused" for="TAJFProgressTaskInterval">TubeArchivist to Jellyfin
playback progress synchronization interval</label>
<input id="TAJFTaskInterval" name="TAJFTaskInterval" type="number" is="emby-input" min="1" />
<input id="TAJFProgressTaskInterval" name="TAJFProgressTaskInterval" type="number" is="emby-input" min="60" />
<div class="fieldDescription">This is the TubeArchivist to Jellyfin playback progress
synchronization interval in seconds (Jellyfin restart required).</div>
</div>
<div class="inputContainer">
<label class="inputLabel inputLabelUnfocused" for="JFTAPlaylistsSyncTaskInterval">Jellyfin to TubeArchivist
playlists synchronization interval</label>
<input id="JFTAPlaylistsSyncTaskInterval" name="JFTAPlaylistsSyncTaskInterval" type="number" is="emby-input" min="60" />
<div class="fieldDescription">This is the Jellyfin to TubeArchivist playlists
synchronization interval in seconds (Jellyfin restart required).</div>
</div>
<div class="inputContainer">
<label class="inputLabel inputLabelUnfocused" for="TAJFPlaylistsSyncTaskInterval">TubeArchivist to Jellyfin
playlists synchronization interval</label>
<input id="TAJFPlaylistsSyncTaskInterval" name="TAJFPlaylistsSyncTaskInterval" type="number" is="emby-input"
min="60" />
<div class="fieldDescription">This is the TubeArchivist to Jellyfin playlists
synchronization interval in seconds (Jellyfin restart required).</div>
</div>
<div>
<button is="emby-button" type="submit" class="raised button-submit block emby-button">
<span>Save</span>
@@ -100,11 +154,15 @@
document.querySelector('#TubeArchivistUrl').value = config.TubeArchivistUrl;
document.querySelector('#TubeArchivistApiKey').value = config.TubeArchivistApiKey;
document.querySelector('#MaxDescriptionLength').value = config.MaxDescriptionLength;
document.querySelector('#JFTASync').checked = config.JFTASync;
document.querySelector('#JFTAProgressSync').checked = config.JFTAProgressSync;
document.querySelector('#JFUsernamesTo').value = config.JFUsernamesTo;
document.querySelector('#TAJFSync').checked = config.TAJFSync;
document.querySelector('#TAJFProgressSync').checked = config.TAJFProgressSync;
document.querySelector('#JFTAPlaylistsSync').checked = config.JFTAPlaylistsSync;
document.querySelector('#TAJFPlaylistsSync').checked = config.TAJFPlaylistsSync;
document.querySelector('#JFUsernameFrom').value = config.JFUsernameFrom;
document.querySelector('#TAJFTaskInterval').value = config.TAJFTaskInterval;
document.querySelector('#TAJFProgressTaskInterval').value = config.TAJFProgressTaskInterval;
document.querySelector('#JFTAPlaylistsSyncTaskInterval').value = config.JFTAPlaylistsSyncTaskInterval;
document.querySelector('#TAJFPlaylistsSyncTaskInterval').value = config.TAJFPlaylistsSyncTaskInterval;
Dashboard.hideLoadingMsg();
});
});
@@ -117,11 +175,15 @@
config.TubeArchivistUrl = document.querySelector('#TubeArchivistUrl').value;
config.TubeArchivistApiKey = document.querySelector('#TubeArchivistApiKey').value;
config.MaxDescriptionLength = document.querySelector('#MaxDescriptionLength').value;
config.JFTASync = document.querySelector('#JFTASync').checked;
config.JFTAProgressSync = document.querySelector('#JFTAProgressSync').checked;
config.JFUsernamesTo = document.querySelector('#JFUsernamesTo').value;
config.TAJFSync = document.querySelector('#TAJFSync').checked;
config.TAJFProgressSync = document.querySelector('#TAJFProgressSync').checked;
config.JFTAPlaylistsSync = document.querySelector('#JFTAPlaylistsSync').checked;
config.TAJFPlaylistsSync = document.querySelector('#TAJFPlaylistsSync').checked;
config.JFUsernameFrom = document.querySelector('#JFUsernameFrom').value;
config.TAJFTaskInterval = document.querySelector('#TAJFTaskInterval').value;
config.TAJFProgressTaskInterval = document.querySelector('#TAJFProgressTaskInterval').value;
config.JFTAPlaylistsSyncTaskInterval = document.querySelector('#JFTAPlaylistsSyncTaskInterval').value;
config.TAJFPlaylistsSyncTaskInterval = document.querySelector('#TAJFPlaylistsSyncTaskInterval').value;
ApiClient.updatePluginConfiguration(TAMetadataConfig.pluginUniqueId, config).then(function (result) {
Dashboard.processPluginConfigurationUpdateResult(result);
});
@@ -75,7 +75,7 @@ namespace Jellyfin.Plugin.TubeArchivistMetadata
var jfToTubeArchivistProgressSyncTask = new JFToTubeArchivistProgressSyncTask(logger, libraryManager, userManager, userDataManager);
var jfToTubeArchivistPlaylistsSyncTask = new JFToTubeArchivistPlaylistsSyncTask(logger, libraryManager, userManager, playlistManager);
var isTAJFTaskPresent = taskManager.ScheduledTasks.Any(t => t.Name.Equals(taToJellyfinProgressSyncTask.Name, StringComparison.Ordinal));
if (Instance!.Configuration.TAJFSync && !isTAJFTaskPresent)
if (Instance!.Configuration.TAJFProgressSync && !isTAJFTaskPresent)
{
logger.LogInformation("Queueing task {TaskName}.", taToJellyfinProgressSyncTask.Name);
taskManager.AddTasks([taToJellyfinProgressSyncTask]);
@@ -87,7 +87,7 @@ namespace Jellyfin.Plugin.TubeArchivistMetadata
}
var isJFTATaskPresent = taskManager.ScheduledTasks.Any(t => t.Name.Equals(jfToTubeArchivistProgressSyncTask.Name, StringComparison.Ordinal));
if (Instance!.Configuration.JFTASync && !isJFTATaskPresent)
if (Instance!.Configuration.JFTAProgressSync && !isJFTATaskPresent)
{
logger.LogInformation("Queueing task {TaskName}.", jfToTubeArchivistProgressSyncTask.Name);
taskManager.AddTasks([jfToTubeArchivistProgressSyncTask]);
@@ -186,7 +186,7 @@ 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)))
if (Instance!.Configuration.JFTAProgressSync && 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);
@@ -207,7 +207,7 @@ namespace Jellyfin.Plugin.TubeArchivistMetadata
private async void OnWatchedStatusChange(object? sender, UserDataSaveEventArgs eventArgs)
{
var user = _userManager.GetUserById(eventArgs.UserId);
if (Configuration.JFTASync && user != null && Configuration.GetJFUsernamesToArray().Contains(user!.Username))
if (Configuration.JFTAProgressSync && user != null && Configuration.GetJFUsernamesToArray().Contains(user!.Username))
{
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);
@@ -108,7 +108,7 @@ namespace Jellyfin.Plugin.TubeArchivistMetadata.Tasks
public async Task ExecuteAsync(IProgress<double> progress, CancellationToken cancellationToken)
{
progress.Report(0);
if (Plugin.Instance!.Configuration.JFTASync)
if (Plugin.Instance!.Configuration.JFTAPlaylistsSync)
{
var start = DateTime.Now;
_logger.LogInformation("Starting Jellyfin->TubeArchivist playlists synchronization.");
@@ -130,8 +130,7 @@ namespace Jellyfin.Plugin.TubeArchivistMetadata.Tasks
var processedVideosCount = 0;
_logger.LogInformation("Found a total of {PlaylistsCount} playlists to analyze with a total of {VideosCount} videos", userPlaylists.Count, totalVideosCount);
// TODO: Implement playlist deletion based on a configuration switch
if (taPlaylists != null && true)
if (taPlaylists != null && Plugin.Instance!.Configuration.JFTAPlaylistsDelete)
{
var taPlaylistsToDelete = taPlaylists.Where(tp => !userPlaylists.Select(up => Utils.GetTAPlaylistIdFromName(up.Name)).Contains(tp.Id));
foreach (var taPlaylistToDelete in taPlaylistsToDelete)
@@ -380,7 +379,7 @@ namespace Jellyfin.Plugin.TubeArchivistMetadata.Tasks
new TaskTriggerInfo
{
Type = TaskTriggerInfoType.IntervalTrigger,
IntervalTicks = TimeSpan.FromSeconds(Plugin.Instance!.Configuration.TAJFTaskInterval).Ticks
IntervalTicks = TimeSpan.FromSeconds(Plugin.Instance!.Configuration.TAJFProgressTaskInterval).Ticks
},
];
}
@@ -58,7 +58,7 @@ namespace Jellyfin.Plugin.TubeArchivistMetadata.Tasks
public async Task ExecuteAsync(IProgress<double> progress, CancellationToken cancellationToken)
{
progress.Report(0);
if (Plugin.Instance!.Configuration.JFTASync)
if (Plugin.Instance!.Configuration.JFTAProgressSync)
{
var start = DateTime.Now;
_logger.LogInformation("Starting Jellyfin->TubeArchivist playback progresses synchronization.");
@@ -70,7 +70,7 @@ namespace Jellyfin.Plugin.TubeArchivistMetadata.Tasks
public async Task ExecuteAsync(IProgress<double> progress, CancellationToken cancellationToken)
{
progress.Report(0);
if (Plugin.Instance!.Configuration.TAJFSync)
if (Plugin.Instance!.Configuration.TAJFPlaylistsSync)
{
var start = DateTime.Now;
_logger.LogInformation("Starting TubeArchivist->Jellyfin playlists synchronization.");
@@ -93,8 +93,7 @@ namespace Jellyfin.Plugin.TubeArchivistMetadata.Tasks
var userPlaylists = _playlistManager.GetPlaylists(user.Id).ToList();
// TODO: Implement playlist deletion based on a configuration switch
if (true)
if (Plugin.Instance!.Configuration.TAJFPlaylistsDelete)
{
var jfPlaylistsToDelete = userPlaylists.Where(up => !taPlaylists.Select(tp => tp.Id).Contains(Utils.GetTAPlaylistIdFromName(up.Name)));
foreach (var jfPlaylistToDelete in jfPlaylistsToDelete)
@@ -194,7 +193,7 @@ namespace Jellyfin.Plugin.TubeArchivistMetadata.Tasks
new TaskTriggerInfo
{
Type = TaskTriggerInfoType.IntervalTrigger,
IntervalTicks = TimeSpan.FromSeconds(Plugin.Instance!.Configuration.TAJFTaskInterval).Ticks
IntervalTicks = TimeSpan.FromSeconds(Plugin.Instance!.Configuration.TAJFProgressTaskInterval).Ticks
},
];
}
@@ -57,7 +57,7 @@ namespace Jellyfin.Plugin.TubeArchivistMetadata.Tasks
public async Task ExecuteAsync(IProgress<double> progress, CancellationToken cancellationToken)
{
progress.Report(0);
if (Plugin.Instance!.Configuration.TAJFSync)
if (Plugin.Instance!.Configuration.TAJFProgressSync)
{
var start = DateTime.Now;
_logger.LogInformation("Starting TubeArchivist->Jellyfin playback progresses synchronization.");
@@ -219,7 +219,7 @@ namespace Jellyfin.Plugin.TubeArchivistMetadata.Tasks
new TaskTriggerInfo
{
Type = TaskTriggerInfoType.IntervalTrigger,
IntervalTicks = TimeSpan.FromSeconds(Plugin.Instance!.Configuration.TAJFTaskInterval).Ticks
IntervalTicks = TimeSpan.FromSeconds(Plugin.Instance!.Configuration.TAJFProgressTaskInterval).Ticks
},
];
}