Merge pull request #51 from wolffshots/master

Episodes by YYYYMMDD and some other cleanup
This commit is contained in:
DarkFighterLuke
2025-10-23 22:21:19 +02:00
committed by GitHub
9 changed files with 83 additions and 16 deletions
@@ -0,0 +1,17 @@
namespace Jellyfin.Plugin.TubeArchivistMetadata.Configuration;
/// <summary>
/// The NumberingScheme.
/// </summary>
public enum NumberingScheme
{
/// <summary>
/// Default (no numbering).
/// </summary>
Default,
/// <summary>
/// YYYYMMDD (e.g. 20250804 for August 4th, 2025).
/// </summary>
YYYYMMDD,
}
@@ -186,6 +186,11 @@ namespace Jellyfin.Plugin.TubeArchivistMetadata.Configuration
/// </summary>
public int TAJFPlaylistsSyncTaskInterval { get; set; }
/// <summary>
/// Gets or sets the preferred numbering scheme for episodes (index number) in Jellyfin.
/// </summary>
public NumberingScheme EpisodeNumberingScheme { get; set; } = NumberingScheme.Default;
/// <summary>
/// Gets the playback progress owners Jellyfin usernames to synchronize data from TubeArchivist.
/// </summary>
@@ -41,6 +41,18 @@
<div class="fieldDescription">This is the maximum length of the descriptions showed in series
and episodes</div>
</div>
<div class="selectContainer">
<label class="selectLabel" for="EpisodeNumberingScheme">Episode numbering scheme</label>
<select is="emby-select" id="EpisodeNumberingScheme" name="EpisodeNumberingScheme" label="Description markup" class="emby-select-withcolor emby-select">
<option value="Default">Default (no specified numbering)</option>
<option value="YYYYMMDD">YYYYMMDD (e.g. 20250804 for August 4th, 2025)</option>
</select>
<div class="selectArrowContainer">
<span class="selectArrow material-icons keyboard_arrow_down" aria-hidden="true"></span>
</div>
<div class="fieldDescription">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.
</div>
<div>
<h2>Synchronization</h2>
</div>
@@ -160,6 +172,7 @@
document.querySelector('#JFTAPlaylistsSync').checked = config.JFTAPlaylistsSync;
document.querySelector('#TAJFPlaylistsSync').checked = config.TAJFPlaylistsSync;
document.querySelector('#JFUsernameFrom').value = config.JFUsernameFrom;
document.querySelector('#EpisodeNumberingScheme').value = config.EpisodeNumberingScheme;
document.querySelector('#TAJFProgressTaskInterval').value = config.TAJFProgressTaskInterval;
document.querySelector('#JFTAPlaylistsSyncTaskInterval').value = config.JFTAPlaylistsSyncTaskInterval;
document.querySelector('#TAJFPlaylistsSyncTaskInterval').value = config.TAJFPlaylistsSyncTaskInterval;
@@ -181,6 +194,7 @@
config.JFTAPlaylistsSync = document.querySelector('#JFTAPlaylistsSync').checked;
config.TAJFPlaylistsSync = document.querySelector('#TAJFPlaylistsSync').checked;
config.JFUsernameFrom = document.querySelector('#JFUsernameFrom').value;
config.EpisodeNumberingScheme = document.querySelector('#EpisodeNumberingScheme').value;
config.TAJFProgressTaskInterval = document.querySelector('#TAJFProgressTaskInterval').value;
config.JFTAPlaylistsSyncTaskInterval = document.querySelector('#JFTAPlaylistsSyncTaskInterval').value;
config.TAJFPlaylistsSyncTaskInterval = document.querySelector('#TAJFPlaylistsSyncTaskInterval').value;
+20 -14
View File
@@ -162,20 +162,20 @@ namespace Jellyfin.Plugin.TubeArchivistMetadata
return;
}
if (Instance!.Configuration.JFTAProgressSync && eventArgs.Users.Any(u => Instance!.Configuration.JFUsernameFrom.Equals(u.Username, StringComparison.Ordinal)))
var topParent = eventArgs.Item.GetTopParent();
if (
Instance!.Configuration.JFTAProgressSync &&
eventArgs.Users.Any(u => Instance!.Configuration.JFUsernameFrom.Equals(u.Username, StringComparison.Ordinal)) &&
eventArgs.PlaybackPositionTicks.HasValue &&
string.Equals(topParent?.Name, Instance?.Configuration.CollectionTitle, StringComparison.OrdinalIgnoreCase)
)
{
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)
{
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");
}
Logger.LogCritical("{Message}", $"POST /video/{videoId}/progress returned {statusCode} for video {eventArgs.Item.Name} with progress {progress} seconds");
}
}
}
@@ -188,16 +188,22 @@ namespace Jellyfin.Plugin.TubeArchivistMetadata
return;
}
var topParent = eventArgs.Item.GetTopParent();
var user = _userManager.GetUserById(eventArgs.UserId);
if (user == null)
if (
Configuration.JFTAProgressSync &&
user != null &&
Configuration.GetJFUsernamesToArray().Contains(user!.Username) &&
string.Equals(topParent?.Name, Instance?.Configuration.CollectionTitle, StringComparison.OrdinalIgnoreCase)
)
{
Logger.LogError("OnWatchedStatusChange callback called without user id for item {ItemName}", eventArgs.Item.Name);
return;
}
var userItemData = _userDataManager.GetUserData(user, eventArgs.Item);
if (Configuration.JFTAProgressSync && user != null && Configuration.GetJFUsernamesToArray().Contains(user!.Username))
{
var userItemData = _userDataManager.GetUserData(user, eventArgs.Item);
var isPlayed = eventArgs.Item.IsPlayed(user, userItemData);
Logger.LogDebug("User {UserId} changed watched status to {Status} for the item {ItemName}", eventArgs.UserId, isPlayed, eventArgs.Item.Name);
string itemYTId;
@@ -67,6 +67,7 @@ namespace Jellyfin.Plugin.TubeArchivistMetadata.Providers
});
result.HasMetadata = true;
result.Item = video.ToEpisode();
result.Item.Path = info.Path;
result.Provider = Name;
result.People = peopleInfo;
}
@@ -153,7 +153,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;
var userItemData = _userDataManager.GetUserData(user, channel);
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Linq;
using Jellyfin.Plugin.TubeArchivistMetadata.Configuration;
using Jellyfin.Plugin.TubeArchivistMetadata.Utilities;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.TV;
@@ -126,6 +127,11 @@ namespace Jellyfin.Plugin.TubeArchivistMetadata.TubeArchivist
Overview = Utils.FormatDescription(Description),
SeasonName = Published.Year.ToString(CultureInfo.CurrentCulture),
ParentIndexNumber = Published.Year,
IndexNumber = Plugin.Instance?.Configuration?.EpisodeNumberingScheme switch
{
NumberingScheme.YYYYMMDD => (Published.Year * 10000) + (Published.Month * 100) + Published.Day,
_ => null
},
SeriesName = Channel.Name,
ProductionYear = Published.Year,
PremiereDate = Published,
@@ -1,6 +1,8 @@
using System;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using Microsoft.Extensions.Logging;
namespace Jellyfin.Plugin.TubeArchivistMetadata.Utilities
{
@@ -45,6 +47,11 @@ namespace Jellyfin.Plugin.TubeArchivistMetadata.Utilities
/// <returns>A string with \n replaced by br tags.</returns>
public static string FormatDescription(string description)
{
if (description == null)
{
return "";
}
var maxLength = 500;
if (Plugin.Instance != null)
{
@@ -54,9 +61,10 @@ namespace Jellyfin.Plugin.TubeArchivistMetadata.Utilities
if (description.Length > maxLength)
{
description = description.Substring(0, maxLength);
description = description.Replace("\n", "<br>", System.StringComparison.CurrentCulture);
}
description = description.Replace("\n", "<br>", System.StringComparison.CurrentCulture);
return description;
}
+10
View File
@@ -114,6 +114,16 @@ Keep in mind that Jellyfin lowest accepted period is of 1 minute (60 seconds) an
![Tasks intervals settings](https://github.com/user-attachments/assets/19db6b83-6715-477d-8ce7-b78526e87ba9)
## Episode numbering
<p>There are different ways to number the episodes as they are configured in Jellyfin.<br>
This changes the number after E in S--E-- (for example S2024E100 for episode number 100 of season 2024).</p>
![Episode numbering scheme options](https://github.com/user-attachments/assets/6d36bc2c-ca9d-4a5c-8021-e15d399316fc)
The options correlate with:
- Default - leave the numbering to what Jellyfin does by default (this is what the plugin has always done)
- YYYYMMDD - numbers the episode by the year, month, day (e.g. 20250804 for a video published on the 4th of August 2025)
## Build