Source Code

Our source code is documented using the standard documentation guidelines.

Source

class Jellyfin.Plugin.Themerr.Storage.Migrations.InitialCreate : Migration

Inheritance diagram for Jellyfin::Plugin::Themerr::Storage::Migrations::InitialCreate:

digraph {
    graph [bgcolor="#00000000"]
    node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2]
    edge [color="#1414CE"]
    "1" [label="Jellyfin.Plugin.Themerr.Storage.Migrations.InitialCreate" tooltip="Jellyfin.Plugin.Themerr.Storage.Migrations.InitialCreate" fillcolor="#BFBFBF"]
    "2" [label="Migration" tooltip="Migration"]
    "1" -> "2" [dir=forward tooltip="public-inheritance"]
}

Collaboration diagram for Jellyfin::Plugin::Themerr::Storage::Migrations::InitialCreate:

digraph {
    graph [bgcolor="#00000000"]
    node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2]
    edge [color="#1414CE"]
    "1" [label="Jellyfin.Plugin.Themerr.Storage.Migrations.InitialCreate" tooltip="Jellyfin.Plugin.Themerr.Storage.Migrations.InitialCreate" fillcolor="#BFBFBF"]
    "2" [label="Migration" tooltip="Migration"]
    "1" -> "2" [dir=forward tooltip="public-inheritance"]
}

Creates the initial Themerr sqlite schema.

Protected Functions

override void Down (MigrationBuilder migrationBuilder)
override void Up (MigrationBuilder migrationBuilder)
interface Jellyfin.Plugin.Themerr.IYoutubeClientWrapper

Inheritance diagram for Jellyfin::Plugin::Themerr::IYoutubeClientWrapper:

digraph {
    graph [bgcolor="#00000000"]
    node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2]
    edge [color="#1414CE"]
    "1" [label="Jellyfin.Plugin.Themerr.IYoutubeClientWrapper" tooltip="Jellyfin.Plugin.Themerr.IYoutubeClientWrapper" fillcolor="#BFBFBF"]
    "2" [label="Jellyfin.Plugin.Themerr.YoutubeClientWrapper" tooltip="Jellyfin.Plugin.Themerr.YoutubeClientWrapper"]
    "2" -> "1" [dir=forward tooltip="public-inheritance"]
}

Abstraction over YoutubeExplode to allow mocking in tests.

Subclassed by Jellyfin.Plugin.Themerr.YoutubeClientWrapper

Public Functions

Task DownloadAudioAsync (string videoUrl, string destination)

Download the highest-bitrate MP4 audio stream from a YouTube video to a file.

Param videoUrl:

The YouTube video URL.

Param destination:

The destination file path.

Return:

A Task representing the asynchronous operation.

class Jellyfin.Plugin.Themerr.Storage.LegacyThemerrData

Represents the old per-item themerr.json file format.

Properties

DateTime? DownloadedTimestampUtc { get; set; }

Gets or sets the timestamp when Themerr downloaded the theme.

string LegacyThemeMd5 { get; set; }

Gets or sets the legacy MD5 hash of the downloaded theme file.

string YoutubeThemeUrl { get; set; }

Gets or sets the source YouTube theme url.

class Jellyfin.Plugin.Themerr.Storage.Migrations.MigrateThemeHashToSha256 : Migration

Inheritance diagram for Jellyfin::Plugin::Themerr::Storage::Migrations::MigrateThemeHashToSha256:

digraph {
    graph [bgcolor="#00000000"]
    node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2]
    edge [color="#1414CE"]
    "1" [label="Jellyfin.Plugin.Themerr.Storage.Migrations.MigrateThemeHashToSha256" tooltip="Jellyfin.Plugin.Themerr.Storage.Migrations.MigrateThemeHashToSha256" fillcolor="#BFBFBF"]
    "2" [label="Migration" tooltip="Migration"]
    "1" -> "2" [dir=forward tooltip="public-inheritance"]
}

Collaboration diagram for Jellyfin::Plugin::Themerr::Storage::Migrations::MigrateThemeHashToSha256:

digraph {
    graph [bgcolor="#00000000"]
    node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2]
    edge [color="#1414CE"]
    "1" [label="Jellyfin.Plugin.Themerr.Storage.Migrations.MigrateThemeHashToSha256" tooltip="Jellyfin.Plugin.Themerr.Storage.Migrations.MigrateThemeHashToSha256" fillcolor="#BFBFBF"]
    "2" [label="Migration" tooltip="Migration"]
    "1" -> "2" [dir=forward tooltip="public-inheritance"]
}

Replaces legacy theme MD5 storage with SHA-256 theme hash storage.

Protected Functions

override void Down (MigrationBuilder migrationBuilder)
override void Up (MigrationBuilder migrationBuilder)
class Jellyfin.Plugin.Themerr.Configuration.PluginConfiguration : BasePluginConfiguration

Inheritance diagram for Jellyfin::Plugin::Themerr::Configuration::PluginConfiguration:

digraph {
    graph [bgcolor="#00000000"]
    node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2]
    edge [color="#1414CE"]
    "2" [label="BasePluginConfiguration" tooltip="BasePluginConfiguration"]
    "1" [label="Jellyfin.Plugin.Themerr.Configuration.PluginConfiguration" tooltip="Jellyfin.Plugin.Themerr.Configuration.PluginConfiguration" fillcolor="#BFBFBF"]
    "1" -> "2" [dir=forward tooltip="public-inheritance"]
}

Collaboration diagram for Jellyfin::Plugin::Themerr::Configuration::PluginConfiguration:

digraph {
    graph [bgcolor="#00000000"]
    node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2]
    edge [color="#1414CE"]
    "2" [label="BasePluginConfiguration" tooltip="BasePluginConfiguration"]
    "1" [label="Jellyfin.Plugin.Themerr.Configuration.PluginConfiguration" tooltip="Jellyfin.Plugin.Themerr.Configuration.PluginConfiguration" fillcolor="#BFBFBF"]
    "1" -> "2" [dir=forward tooltip="public-inheritance"]
}

Initializes a new instance of the PluginConfiguration class.

Public Functions

PluginConfiguration ()

Initializes a new instance of the PluginConfiguration class.

Properties

bool BackupUserSuppliedTheme { get; set; }

Gets or sets a value indicating whether to back up a user-supplied theme.mp3 as theme.backup.mp3 before replacing it.

int UpdateInterval { get; set; }

Gets or sets the time between scheduled updates, in minutes.

Minimum value of 15.

Public Static Attributes

const int MinimumUpdateIntervalMinutes = 15

The minimum interval between scheduled updates, in minutes.

Private Members

int _updateInterval
class Jellyfin.Plugin.Themerr.Api.ThemerrController : ControllerBase

Inheritance diagram for Jellyfin::Plugin::Themerr::Api::ThemerrController:

digraph {
    graph [bgcolor="#00000000"]
    node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2]
    edge [color="#1414CE"]
    "2" [label="ControllerBase" tooltip="ControllerBase"]
    "1" [label="Jellyfin.Plugin.Themerr.Api.ThemerrController" tooltip="Jellyfin.Plugin.Themerr.Api.ThemerrController" fillcolor="#BFBFBF"]
    "1" -> "2" [dir=forward tooltip="public-inheritance"]
}

Collaboration diagram for Jellyfin::Plugin::Themerr::Api::ThemerrController:

digraph {
    graph [bgcolor="#00000000"]
    node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2]
    edge [color="#1414CE"]
    "2" [label="ControllerBase" tooltip="ControllerBase"]
    "1" [label="Jellyfin.Plugin.Themerr.Api.ThemerrController" tooltip="Jellyfin.Plugin.Themerr.Api.ThemerrController" fillcolor="#BFBFBF"]
    "1" -> "2" [dir=forward tooltip="public-inheritance"]
}

The Themerr api controller.

Public Functions

ActionResult GetProgress ()

Get the data required to populate the progress dashboard.

Reads directly from the sqlite database — no live library scan or ThemerrDB calls.

Return:

JSON object containing progress data.

async Task<ActionResult> ReplaceTheme (Guid itemId)

Replace a user-supplied theme with the ThemerrDB version.

A response code of 204 indicates the theme was replaced successfully. A response code of 404 indicates the item was not found or has no ThemerrDB theme URL stored.

Param itemId:

The Jellyfin item ID.

Return:

A NoContentResult on success or NotFoundResult otherwise.

ThemerrController (IApplicationPaths applicationPaths, ILibraryManager libraryManager, ILogger<ThemerrController> logger, ILoggerFactory loggerFactory)

Initializes a new instance of the ThemerrController class.

Param applicationPaths:

The application paths.

Param libraryManager:

The library manager.

Param logger:

The logger.

Param loggerFactory:

The logger factory.

async Task TriggerUpdateRequest ()

Trigger an update from the configuration html page.

A response code of 204 indicates that the download has started successfully.

Return:

A NoContentResult indicating success.

Private Members

readonly ILogger<ThemerrController> _logger
readonly ThemerrManager _themerrManager
class Jellyfin.Plugin.Themerr.Storage.ThemerrDatabaseMigrator

Applies Themerr database migrations.

Public Functions

void MigrateDown ()

Reverts all migrations.

bool MigrateUp ()

Applies all pending migrations.

Return:

True when the sqlite database file was created during migration; otherwise, false.

ThemerrDatabaseMigrator (string databasePath)

Initializes a new instance of the ThemerrDatabaseMigrator class.

Param databasePath:

The sqlite database path.

Private Members

readonly string _databasePath
class Jellyfin.Plugin.Themerr.Storage.ThemerrDatabasePath

Resolves the Themerr database location.

Public Static Functions

string GetDatabasePath (IApplicationPaths applicationPaths)

Gets the Themerr sqlite database path.

Param applicationPaths:

The Jellyfin application paths.

Return:

The sqlite database path.

class Jellyfin.Plugin.Themerr.ThemerrManager.ThemerrDbAvailability

Stores cached ThemerrDB availability for a media item.

Properties

DateTime CheckedUtc { get; set; }

Gets or sets when ThemerrDB availability was checked.

bool InThemerrDb { get; set; }

Gets or sets a value indicating whether ThemerrDB has a theme for this item.

string YoutubeThemeUrl { get; set; }

Gets or sets the ThemerrDB YouTube theme url.

class Jellyfin.Plugin.Themerr.Storage.ThemerrDbContext : DbContext

Inheritance diagram for Jellyfin::Plugin::Themerr::Storage::ThemerrDbContext:

digraph {
    graph [bgcolor="#00000000"]
    node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2]
    edge [color="#1414CE"]
    "2" [label="DbContext" tooltip="DbContext"]
    "1" [label="Jellyfin.Plugin.Themerr.Storage.ThemerrDbContext" tooltip="Jellyfin.Plugin.Themerr.Storage.ThemerrDbContext" fillcolor="#BFBFBF"]
    "1" -> "2" [dir=forward tooltip="public-inheritance"]
}

Collaboration diagram for Jellyfin::Plugin::Themerr::Storage::ThemerrDbContext:

digraph {
    graph [bgcolor="#00000000"]
    node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2]
    edge [color="#1414CE"]
    "2" [label="DbContext" tooltip="DbContext"]
    "1" [label="Jellyfin.Plugin.Themerr.Storage.ThemerrDbContext" tooltip="Jellyfin.Plugin.Themerr.Storage.ThemerrDbContext" fillcolor="#BFBFBF"]
    "1" -> "2" [dir=forward tooltip="public-inheritance"]
}

Entity Framework Core context for Themerr plugin data.

Public Functions

ThemerrDbContext (DbContextOptions<ThemerrDbContext> options)

Initializes a new instance of the ThemerrDbContext class.

Param options:

The context options.

ThemerrDbContext (string databasePath)

Initializes a new instance of the ThemerrDbContext class.

Param databasePath:

The sqlite database path.

Properties

ThemerrMediaItem > MediaItems { get; set; }

Gets or sets Themerr media item metadata.

Protected Functions

override void OnConfiguring (DbContextOptionsBuilder optionsBuilder)
override void OnModelCreating (ModelBuilder modelBuilder)

Private Members

readonly string _databasePath
class Jellyfin.Plugin.Themerr.Storage.Migrations.ThemerrDbContextModelSnapshot : ModelSnapshot

Inheritance diagram for Jellyfin::Plugin::Themerr::Storage::Migrations::ThemerrDbContextModelSnapshot:

digraph {
    graph [bgcolor="#00000000"]
    node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2]
    edge [color="#1414CE"]
    "1" [label="Jellyfin.Plugin.Themerr.Storage.Migrations.ThemerrDbContextModelSnapshot" tooltip="Jellyfin.Plugin.Themerr.Storage.Migrations.ThemerrDbContextModelSnapshot" fillcolor="#BFBFBF"]
    "2" [label="ModelSnapshot" tooltip="ModelSnapshot"]
    "1" -> "2" [dir=forward tooltip="public-inheritance"]
}

Collaboration diagram for Jellyfin::Plugin::Themerr::Storage::Migrations::ThemerrDbContextModelSnapshot:

digraph {
    graph [bgcolor="#00000000"]
    node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2]
    edge [color="#1414CE"]
    "1" [label="Jellyfin.Plugin.Themerr.Storage.Migrations.ThemerrDbContextModelSnapshot" tooltip="Jellyfin.Plugin.Themerr.Storage.Migrations.ThemerrDbContextModelSnapshot" fillcolor="#BFBFBF"]
    "2" [label="ModelSnapshot" tooltip="ModelSnapshot"]
    "1" -> "2" [dir=forward tooltip="public-inheritance"]
}

Snapshot of the Themerr database model.

Protected Functions

override void BuildModel (ModelBuilder modelBuilder)
class Jellyfin.Plugin.Themerr.ThemerrDbType

Resolves ThemerrDB media type names for Jellyfin items.

Public Static Functions

string Get (BaseItem item)

Gets the ThemerrDB media type for an item.

Param item:

The Jellyfin media item.

Return:

The ThemerrDB media type when supported; otherwise, null.

class Jellyfin.Plugin.Themerr.Api.ThemerrLocalizationController : ControllerBase

Inheritance diagram for Jellyfin::Plugin::Themerr::Api::ThemerrLocalizationController:

digraph {
    graph [bgcolor="#00000000"]
    node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2]
    edge [color="#1414CE"]
    "2" [label="ControllerBase" tooltip="ControllerBase"]
    "1" [label="Jellyfin.Plugin.Themerr.Api.ThemerrLocalizationController" tooltip="Jellyfin.Plugin.Themerr.Api.ThemerrLocalizationController" fillcolor="#BFBFBF"]
    "1" -> "2" [dir=forward tooltip="public-inheritance"]
}

Collaboration diagram for Jellyfin::Plugin::Themerr::Api::ThemerrLocalizationController:

digraph {
    graph [bgcolor="#00000000"]
    node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2]
    edge [color="#1414CE"]
    "2" [label="ControllerBase" tooltip="ControllerBase"]
    "1" [label="Jellyfin.Plugin.Themerr.Api.ThemerrLocalizationController" tooltip="Jellyfin.Plugin.Themerr.Api.ThemerrLocalizationController" fillcolor="#BFBFBF"]
    "1" -> "2" [dir=forward tooltip="public-inheritance"]
}

The Themerr localization api controller.

Public Functions

ActionResult GetTranslations ()

Get the localization strings from Locale/{selected_locale}.json.

Return:

JSON object containing localization strings.

ThemerrLocalizationController (IServerConfigurationManager configurationManager, ILogger<ThemerrLocalizationController> logger)

Initializes a new instance of the ThemerrLocalizationController class.

Param configurationManager:

The configuration manager.

Param logger:

The logger.

Protected Functions

Stream GetResourceStream (string resourceName)

Get an embedded locale resource stream.

Param resourceName:

The resource name.

Return:

The resource stream.

Private Members

readonly IServerConfigurationManager _configurationManager
readonly ILogger<ThemerrLocalizationController> _logger
class Jellyfin.Plugin.Themerr.ThemerrLocalizationManager

Manages localization resource selection for the Themerr plugin.

Public Static Functions

List<string> GetCultureResource (string culture)

Get the resources of the given culture.

Param culture:

The culture to get the resource for.

Return:

A list of file names.

class Jellyfin.Plugin.Themerr.ThemerrManager : IDisposable

Inheritance diagram for Jellyfin::Plugin::Themerr::ThemerrManager:

digraph {
    graph [bgcolor="#00000000"]
    node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2]
    edge [color="#1414CE"]
    "2" [label="IDisposable" tooltip="IDisposable"]
    "1" [label="Jellyfin.Plugin.Themerr.ThemerrManager" tooltip="Jellyfin.Plugin.Themerr.ThemerrManager" fillcolor="#BFBFBF"]
    "1" -> "2" [dir=forward tooltip="public-inheritance"]
}

Collaboration diagram for Jellyfin::Plugin::Themerr::ThemerrManager:

digraph {
    graph [bgcolor="#00000000"]
    node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2]
    edge [color="#1414CE"]
    "2" [label="IDisposable" tooltip="IDisposable"]
    "1" [label="Jellyfin.Plugin.Themerr.ThemerrManager" tooltip="Jellyfin.Plugin.Themerr.ThemerrManager" fillcolor="#BFBFBF"]
    "1" -> "2" [dir=forward tooltip="public-inheritance"]
}

Manages theme song downloads and library synchronisation for the Themerr plugin.

Public Functions

bool ContinueDownload (BaseItem item, string themePath)

Check if the theme song should be downloaded.

Various checks are performed to determine if the theme song should be downloaded.

Param themePath:

The path to the theme song.

Param item:

The Jellyfin media object.

Return:

True to continue with downloaded, false otherwise.

void Dispose ()

Cleanup.

IReadOnlyList<ThemerrMediaItem> GetAllTrackedItems ()

Returns all items currently tracked in the database, sorted for display.

Return:

All tracked media items.

async Task<string> GetThemeProvider (BaseItem item)

Get the theme provider.

Param item:

The Jellyfin media object.

Return:

The theme provider.

IEnumerable<BaseItem> GetTmdbItemsFromLibrary ()

Get all supported items from the library that have a tmdb id.

Return:

List of BaseItem objects.

async Task<string> GetYoutubeThemeUrl (string themerrDbUrl, BaseItem item)

Get the YouTube theme url from the themerr database.

Param themerrDbUrl:

The themerr database url.

Param item:

The Jellyfin media object.

Return:

The YouTube theme url.

async Task<bool> IsInThemerrDb (BaseItem item)

Check if an item has an entry in the ThemerrDB database.

Param item:

The Jellyfin media object.

Return:

True if the item exists in ThemerrDB, false otherwise.

bool MigrateLegacyThemerrData (BaseItem item)

Migrate a legacy themerr.json file to sqlite.

Param item:

The Jellyfin media object.

Return:

True if a legacy file was migrated; otherwise, false.

async Task ProcessItemTheme (BaseItem item)

Download the theme song for a media item if it doesn’t already exist.

Param item:

The Jellyfin media object.

async Task<bool> ReplaceWithThemerTheme (Guid itemId)

Replace a user-supplied theme with the ThemerrDB version. Always fetches the latest URL from ThemerrDB, falling back to the stored URL on failure.

Param itemId:

The Jellyfin item ID.

Return:

True if the theme was replaced successfully; otherwise false.

async Task<bool> SaveMp3 (string destination, string videoUrl)

Save a mp3 file from a YouTube video url.

Param destination:

The destination path.

Param videoUrl:

The YouTube video url.

Return:

True if the file was saved successfully, false otherwise.

bool SaveThemerrData (BaseItem item, string themePath, string youtubeThemeUrl)

Save the themerr data for an item.

Param item:

The Jellyfin media object.

Param themePath:

The path to the theme song.

Param youtubeThemeUrl:

The YouTube theme url.

Return:

True if the data was saved successfully, false otherwise.

void StartInitialMigrationUpdate ()

Starts the first database migration update when the sqlite database was just created.

async Task<ThemerrMediaItem> SyncLibraryItem (BaseItem item)

Synchronizes one supported TMDB-backed library item into sqlite.

Param item:

The Jellyfin media object.

Return:

The synchronized sqlite row when the item is supported; otherwise, null.

async Task<IReadOnlyList<ThemerrMediaItem>> SyncLibraryItems ()

Synchronizes supported TMDB-backed library items into sqlite.

Return:

The synchronized sqlite rows.

ThemerrManager (IApplicationPaths applicationPaths, ILibraryManager libraryManager, ILogger<ThemerrManager> logger, IYoutubeClientWrapper youtubeClientWrapper = null, ThemerrRepository themerrRepository = null)

Initializes a new instance of the ThemerrManager class.

Param applicationPaths:

The application paths.

Param libraryManager:

The library manager.

Param logger:

The logger.

Param youtubeClientWrapper:

The YouTube client wrapper. Uses the default implementation when null.

Param themerrRepository:

The Themerr sqlite repository. Uses the default implementation when null.

async Task UpdateAll ()

Enumerate through all supported items in the library and downloads their theme songs as required.

Return:

A Task representing the asynchronous operation.

Public Static Functions

Create a link to the themerr database.

Param tmdbId:

The tmdb id.

Param dbType:

The database type.

Return:

The themerr database link.

string GetIssueUrl (BaseItem item)

Get ThemerrDB issue url.

This url can be used to easily add/edit theme songs in ThemerrDB.

Param item:

The Jellyfin media object.

Return:

The ThemerrDB issue url.

string GetThemeHash (string filePath)

Get the current theme hash of a file.

Param filePath:

The file path.

Return:

The SHA-256 hash of the file.

string GetThemePath (BaseItem item)

Get the path to the theme song.

Param item:

The Jellyfin media object.

Return:

The path to the theme song.

string GetThemerrDataPath (BaseItem item)

Get the path to the themerr data file.

Param item:

The Jellyfin media object.

Return:

The path to the themerr data file.

string GetTmdbId (BaseItem item)

Get TMDB id from an item.

Param item:

The Jellyfin media object.

Return:

TMDB id.

Task RunAsync ()

Run the task, asynchronously.

Return:

A Task representing the asynchronous operation.

Protected Functions

void Dispose (bool disposing)

Releases unmanaged and optionally managed resources.

Param disposing:

Whether managed resources should be disposed.

Private Functions

void AddThemerrDataPathFromMatchingChildDirectory (List<string> paths, BaseItem item, string rootDirectory)
string GetExistingThemePath (BaseItem item, string themePath)
IEnumerable<string> GetLegacyThemerrDataPathCandidates (BaseItem item, string themePath, ThemerrMediaItem existingData)
async Task<ThemerrDbAvailability> GetThemerrDbAvailability (BaseItem item, string dbType, ThemerrMediaItem existingData)
bool IsMatchingMediaDirectory (BaseItem item, string directory)
bool MigrateLegacyThemerrData (BaseItem item, string themePath, ThemerrMediaItem existingData)
void OnTimerElapsed ()

Called when the plugin is loaded.

ThemerrMediaItem SaveTrackedItem (BaseItem item, string themePath, ThemerrMediaItem existingData, bool inThemerrDb, string youtubeThemeUrl, DateTime inThemerrDbCheckedUtc)
bool TryGetOrStartInitialMigrationUpdateTask (out Task initialUpdateTask)
async Task UpdateAllCore ()

Private Members

readonly ILibraryManager _libraryManager
readonly ILogger<ThemerrManager> _logger
readonly ThemerrRepository _themerrRepository
readonly Timer _timer
readonly IYoutubeClientWrapper _youtubeClientWrapper

Private Static Functions

string GetCurrentThemeHash (string themeProvider, string existingThemePath, ThemerrMediaItem existingData)
string GetCurrentThemeProvider (string existingThemePath, ThemerrMediaItem existingData)
string GetYoutubeThemeUrlFromJson (string jsonString)
bool HasCurrentThemeHash (ThemerrMediaItem existingData)

Private Static Attributes

readonly HttpClient HttpClient = new HttpClient()
readonly HashSet<string> InitialUpdateCompletedDatabasePaths = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
readonly object InitialUpdateLock = new object()
readonly HashSet<string> InitialUpdateRequiredDatabasePaths = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
readonly Dictionary<string, Task> InitialUpdateTasks = new Dictionary<string, Task>(StringComparer.OrdinalIgnoreCase)
readonly TimeSpan ThemerrDbCacheDuration = TimeSpan.FromHours(24)
class Jellyfin.Plugin.Themerr.Storage.ThemerrMediaItem

Stores Themerr metadata for one Jellyfin media item.

Properties

DateTime CreatedUtc { get; set; }

Gets or sets the timestamp when the row was first created.

DateTime? DownloadedTimestampUtc { get; set; }

Gets or sets the timestamp when Themerr downloaded the theme.

int Id { get; set; }

Gets or sets the database primary key.

bool InThemerrDb { get; set; }

Gets or sets a value indicating whether ThemerrDB has a theme for this item.

DateTime? InThemerrDbCheckedUtc { get; set; }

Gets or sets the timestamp when ThemerrDB availability was last checked.

string IssueUrl { get; set; }

Gets or sets the cached ThemerrDB issue url.

string ItemId { get; set; }

Gets or sets the Jellyfin item id when available.

string ItemKey { get; set; }

Gets or sets the stable lookup key used by the plugin.

string ItemName { get; set; }

Gets or sets the display name of the Jellyfin item.

string ItemPath { get; set; }

Gets or sets the current media folder path.

string ItemType { get; set; }

Gets or sets the Jellyfin item type.

int? ProductionYear { get; set; }

Gets or sets the production year of the Jellyfin item.

string ThemeHash { get; set; }

Gets or sets the hash of the downloaded theme file.

string ThemeHashAlgorithm { get; set; }

Gets or sets the algorithm used for ThemeHash.

string ThemePath { get; set; }

Gets or sets the current theme file path.

string ThemeProvider { get; set; }

Gets or sets the current theme provider.

string TmdbId { get; set; }

Gets or sets the TMDB id for the media item.

DateTime UpdatedUtc { get; set; }

Gets or sets the timestamp when the row was last updated.

string YoutubeThemeUrl { get; set; }

Gets or sets the source YouTube theme url.

class Jellyfin.Plugin.Themerr.Storage.ThemerrMediaItemSaveOptions

Contains optional Themerr metadata values to save for a Jellyfin media item.

Properties

DateTime? DownloadedTimestampUtc { get; set; }

Gets or sets the download timestamp.

bool? InThemerrDb { get; set; }

Gets or sets whether ThemerrDB has a theme for this item.

DateTime? InThemerrDbCheckedUtc { get; set; }

Gets or sets when ThemerrDB availability was checked.

string IssueUrl { get; set; }

Gets or sets the cached ThemerrDB issue url.

string ThemeHash { get; set; }

Gets or sets the theme file hash.

string ThemeHashAlgorithm { get; set; }

Gets or sets the theme hash algorithm.

string ThemePath { get; set; }

Gets or sets the theme file path.

string ThemeProvider { get; set; }

Gets or sets the theme provider.

string YoutubeThemeUrl { get; set; }

Gets or sets the YouTube theme url.

class Jellyfin.Plugin.Themerr.Storage.ThemerrMediaPath

Resolves filesystem paths for supported Themerr media items.

Public Static Functions

string GetItemDirectory (BaseItem item)

Gets the media item folder path.

Param item:

The Jellyfin media item.

Return:

The folder path when available; otherwise, null.

string GetThemePath (BaseItem item)

Gets the path to the theme song.

Param item:

The Jellyfin media item.

Return:

The theme song path for supported item types; otherwise, null.

string GetThemerrDataPath (BaseItem item)

Gets the path to the legacy themerr.json file.

Param item:

The Jellyfin media item.

Return:

The themerr.json path for supported item types; otherwise, null.

Private Static Functions

string GetDirectoryFromPath (string path)
string GetMovieDirectory (Movie movie)
class Jellyfin.Plugin.Themerr.ThemerrPlugin : BasePlugin<PluginConfiguration>, IHasWebPages

Inheritance diagram for Jellyfin::Plugin::Themerr::ThemerrPlugin:

digraph {
    graph [bgcolor="#00000000"]
    node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2]
    edge [color="#1414CE"]
    "2" [label="BasePlugin< PluginConfiguration >" tooltip="BasePlugin< PluginConfiguration >"]
    "3" [label="IHasWebPages" tooltip="IHasWebPages"]
    "1" [label="Jellyfin.Plugin.Themerr.ThemerrPlugin" tooltip="Jellyfin.Plugin.Themerr.ThemerrPlugin" fillcolor="#BFBFBF"]
    "1" -> "2" [dir=forward tooltip="public-inheritance"]
    "1" -> "3" [dir=forward tooltip="public-inheritance"]
}

Collaboration diagram for Jellyfin::Plugin::Themerr::ThemerrPlugin:

digraph {
    graph [bgcolor="#00000000"]
    node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2]
    edge [color="#1414CE"]
    "2" [label="BasePlugin< PluginConfiguration >" tooltip="BasePlugin< PluginConfiguration >"]
    "3" [label="IHasWebPages" tooltip="IHasWebPages"]
    "1" [label="Jellyfin.Plugin.Themerr.ThemerrPlugin" tooltip="Jellyfin.Plugin.Themerr.ThemerrPlugin" fillcolor="#BFBFBF"]
    "1" -> "2" [dir=forward tooltip="public-inheritance"]
    "1" -> "3" [dir=forward tooltip="public-inheritance"]
}

The Themerr plugin class.

Public Functions

IEnumerable<PluginPageInfo> GetPages ()

Get the plugin’s html config page.

Return:

Instance of the PluginPageInfo configuration page.

ThemerrPlugin (IApplicationPaths applicationPaths, IXmlSerializer xmlSerializer)

Initializes a new instance of the ThemerrPlugin class.

Param applicationPaths:

Instance of the IApplicationPaths interface.

Param xmlSerializer:

Instance of the IXmlSerializer interface.

Properties

override string Description { get; set; }

Gets the description of the plugin.

override Guid Id { get; set; }

Gets the plugin instance id.

ThemerrPlugin Instance { get; set; }

Gets the plugin instance.

override string Name { get; set; }

Gets the name of the plugin.

Private Members

readonly Guid _id = new Guid("e41ef0c4-c413-41ba-b4fa-8c565dc3c969")
class Jellyfin.Plugin.Themerr.Storage.ThemerrRepository

Reads and writes Themerr metadata from the sqlite database.

Public Functions

bool Delete (BaseItem item, string themePath)

Deletes Themerr metadata for a media item.

Param item:

The Jellyfin media item.

Param themePath:

The theme file path.

Return:

True when a row was deleted; otherwise, false.

ThemerrMediaItem Get (BaseItem item, string themePath)

Gets Themerr metadata for a media item.

Param item:

The Jellyfin media item.

Param themePath:

The theme file path.

Return:

The Themerr metadata row if it exists; otherwise, null.

IReadOnlyList<ThemerrMediaItem> GetAll ()

Gets all tracked Themerr media item rows.

Return:

All tracked media items sorted for display.

void MigrateDown ()

Reverts all migrations.

bool MigrateLegacyData (BaseItem item, string themePath, string legacyDataPath)

Imports a legacy themerr.json file into sqlite and removes the json file after a successful save.

Param item:

The Jellyfin media item.

Param themePath:

The theme file path.

Param legacyDataPath:

The old themerr.json path.

Return:

True when a legacy file was imported and deleted; otherwise, false.

void MigrateUp ()

Applies pending migrations.

ThemerrMediaItem Save (BaseItem item, ThemerrMediaItemSaveOptions saveOptions)

Saves Themerr metadata for a media item.

Param item:

The Jellyfin media item.

Param saveOptions:

The metadata values to save.

Return:

The saved Themerr metadata row.

ThemerrRepository (string databasePath, ILogger logger)

Initializes a new instance of the ThemerrRepository class.

Param databasePath:

The sqlite database path.

Param logger:

The logger.

Properties

bool DatabaseCreatedDuringMigration { get; set; }

Gets a value indicating whether this repository created the database file while applying migrations.

string DatabasePath { get; set; }

Gets the sqlite database path used by this repository.

bool ThemeHashMigrationRequired { get; set; }

Gets a value indicating whether stored Themerr theme rows still need SHA-256 hashes.

Public Static Functions

string GetItemKey (BaseItem item, string themePath)

Gets the stable key for a Jellyfin media item.

Param item:

The Jellyfin media item.

Param themePath:

The theme file path.

Return:

The stable item key.

string GetItemPath (BaseItem item)

Gets the media item folder path.

Param item:

The Jellyfin media item.

Return:

The folder path when available; otherwise, null.

string GetItemType (BaseItem item)

Gets the storage item type.

Param item:

The Jellyfin media item.

Return:

The storage item type.

Private Functions

void EnsureMigrated ()

Private Members

bool _databaseCreatedDuringMigration
readonly ThemerrDatabaseMigrator _databaseMigrator
readonly string _databasePath
readonly ILogger _logger
readonly object _migrationLock = new object()
bool _migrationsApplied

Private Static Functions

string GetMigratedThemeHash (string themePath, string legacyDataPath)
IEnumerable<string> GetMigratedThemeHashPathCandidates (string themePath, string legacyDataPath)
class Jellyfin.Plugin.Themerr.ThemerrServiceRegistrator : IPluginServiceRegistrator

Inheritance diagram for Jellyfin::Plugin::Themerr::ThemerrServiceRegistrator:

digraph {
    graph [bgcolor="#00000000"]
    node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2]
    edge [color="#1414CE"]
    "2" [label="IPluginServiceRegistrator" tooltip="IPluginServiceRegistrator"]
    "1" [label="Jellyfin.Plugin.Themerr.ThemerrServiceRegistrator" tooltip="Jellyfin.Plugin.Themerr.ThemerrServiceRegistrator" fillcolor="#BFBFBF"]
    "1" -> "2" [dir=forward tooltip="public-inheritance"]
}

Collaboration diagram for Jellyfin::Plugin::Themerr::ThemerrServiceRegistrator:

digraph {
    graph [bgcolor="#00000000"]
    node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2]
    edge [color="#1414CE"]
    "2" [label="IPluginServiceRegistrator" tooltip="IPluginServiceRegistrator"]
    "1" [label="Jellyfin.Plugin.Themerr.ThemerrServiceRegistrator" tooltip="Jellyfin.Plugin.Themerr.ThemerrServiceRegistrator" fillcolor="#BFBFBF"]
    "1" -> "2" [dir=forward tooltip="public-inheritance"]
}

Registers Themerr services with Jellyfin.

Public Functions

void RegisterServices (IServiceCollection serviceCollection, IServerApplicationHost applicationHost)
class Jellyfin.Plugin.Themerr.ThemerrStartupService : IHostedService

Inheritance diagram for Jellyfin::Plugin::Themerr::ThemerrStartupService:

digraph {
    graph [bgcolor="#00000000"]
    node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2]
    edge [color="#1414CE"]
    "2" [label="IHostedService" tooltip="IHostedService"]
    "1" [label="Jellyfin.Plugin.Themerr.ThemerrStartupService" tooltip="Jellyfin.Plugin.Themerr.ThemerrStartupService" fillcolor="#BFBFBF"]
    "1" -> "2" [dir=forward tooltip="public-inheritance"]
}

Collaboration diagram for Jellyfin::Plugin::Themerr::ThemerrStartupService:

digraph {
    graph [bgcolor="#00000000"]
    node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2]
    edge [color="#1414CE"]
    "2" [label="IHostedService" tooltip="IHostedService"]
    "1" [label="Jellyfin.Plugin.Themerr.ThemerrStartupService" tooltip="Jellyfin.Plugin.Themerr.ThemerrStartupService" fillcolor="#BFBFBF"]
    "1" -> "2" [dir=forward tooltip="public-inheritance"]
}

Starts Themerr database initialization when Jellyfin loads the plugin.

Public Functions

Task StartAsync (CancellationToken cancellationToken)
Task StopAsync (CancellationToken cancellationToken)
ThemerrStartupService (IApplicationPaths applicationPaths, ILibraryManager libraryManager, ILoggerFactory loggerFactory, ITaskManager taskManager)

Initializes a new instance of the ThemerrStartupService class.

Param applicationPaths:

The application paths.

Param libraryManager:

The library manager.

Param loggerFactory:

The logger factory.

Param taskManager:

The task manager.

Private Functions

void OnPluginConfigurationChanged (object sender, BasePluginConfiguration configuration)
void UpdateTaskTrigger (PluginConfiguration configuration)

Private Members

readonly ITaskManager _taskManager
readonly ThemerrManager _themerrManager
class Jellyfin.Plugin.Themerr.ScheduledTasks.ThemerrTasks : IScheduledTask

Inheritance diagram for Jellyfin::Plugin::Themerr::ScheduledTasks::ThemerrTasks:

digraph {
    graph [bgcolor="#00000000"]
    node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2]
    edge [color="#1414CE"]
    "2" [label="IScheduledTask" tooltip="IScheduledTask"]
    "1" [label="Jellyfin.Plugin.Themerr.ScheduledTasks.ThemerrTasks" tooltip="Jellyfin.Plugin.Themerr.ScheduledTasks.ThemerrTasks" fillcolor="#BFBFBF"]
    "1" -> "2" [dir=forward tooltip="public-inheritance"]
}

Collaboration diagram for Jellyfin::Plugin::Themerr::ScheduledTasks::ThemerrTasks:

digraph {
    graph [bgcolor="#00000000"]
    node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2]
    edge [color="#1414CE"]
    "2" [label="IScheduledTask" tooltip="IScheduledTask"]
    "1" [label="Jellyfin.Plugin.Themerr.ScheduledTasks.ThemerrTasks" tooltip="Jellyfin.Plugin.Themerr.ScheduledTasks.ThemerrTasks" fillcolor="#BFBFBF"]
    "1" -> "2" [dir=forward tooltip="public-inheritance"]
}

The Themerr scheduled task.

Public Functions

async Task ExecuteAsync (IProgress<double> progress, CancellationToken cancellationToken)

Execute the task, asynchronously.

Param progress:

The progress reporter.

Param cancellationToken:

The cancellation token.

Return:

A Task representing the asynchronous operation.

IEnumerable<TaskTriggerInfo> GetDefaultTriggers ()

Gets the default triggers.

Return:

A list of TaskTriggerInfo.

ThemerrTasks (IApplicationPaths applicationPaths, ILibraryManager libraryManager, ILogger<ThemerrTasks> logger, ILoggerFactory loggerFactory)

Initializes a new instance of the ThemerrTasks class.

Param applicationPaths:

The application paths.

Param libraryManager:

The library manager.

Param logger:

The logger.

Param loggerFactory:

The logger factory.

Properties

string Category { get; set; }

Gets the category of the task.

string Description { get; set; }

Gets the description of the task.

string Key { get; set; }

Gets the key of the task.

string Name { get; set; }

Gets the name of the task.

Public Static Functions

IReadOnlyList<TaskTriggerInfo> GetTriggers (int updateInterval)

Gets triggers for the configured update interval.

Param updateInterval:

The update interval, in minutes.

Return:

A list of TaskTriggerInfo.

Private Members

readonly ILogger<ThemerrTasks> _logger
readonly ThemerrManager _themerrManager
class Jellyfin.Plugin.Themerr.Storage.ThemerrThemeHashAlgorithm

Theme hash algorithm values stored in sqlite.

Public Static Attributes

const string Sha256 = "SHA256"

SHA-256 theme file hash.

class Jellyfin.Plugin.Themerr.Storage.ThemerrThemeHasher

Computes theme file hashes used to identify Themerr-managed files.

Public Static Functions

string ComputeHash (string filePath)

Computes the SHA-256 hash of a file.

Param filePath:

The file path.

Return:

The SHA-256 hash of the file.

Public Static Attributes

const string CurrentAlgorithm = ThemerrThemeHashAlgorithm.Sha256

Gets the current theme hash algorithm.

class Jellyfin.Plugin.Themerr.Storage.ThemerrThemeProvider

Theme provider values stored in sqlite and returned by the web API.

Public Static Attributes

const string Themerr = "themerr"

Theme downloaded and managed by Themerr.

const string User = "user"

Theme supplied outside of Themerr.

class Jellyfin.Plugin.Themerr.YoutubeClientWrapper : Jellyfin.Plugin.Themerr.IYoutubeClientWrapper

Inheritance diagram for Jellyfin::Plugin::Themerr::YoutubeClientWrapper:

digraph {
    graph [bgcolor="#00000000"]
    node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2]
    edge [color="#1414CE"]
    "2" [label="IYoutubeClientWrapper" tooltip="IYoutubeClientWrapper"]
    "1" [label="Jellyfin.Plugin.Themerr.YoutubeClientWrapper" tooltip="Jellyfin.Plugin.Themerr.YoutubeClientWrapper" fillcolor="#BFBFBF"]
    "1" -> "2" [dir=forward tooltip="public-inheritance"]
}

Collaboration diagram for Jellyfin::Plugin::Themerr::YoutubeClientWrapper:

digraph {
    graph [bgcolor="#00000000"]
    node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2]
    edge [color="#1414CE"]
    "2" [label="IYoutubeClientWrapper" tooltip="IYoutubeClientWrapper"]
    "1" [label="Jellyfin.Plugin.Themerr.YoutubeClientWrapper" tooltip="Jellyfin.Plugin.Themerr.YoutubeClientWrapper" fillcolor="#BFBFBF"]
    "1" -> "2" [dir=forward tooltip="public-inheritance"]
}

Default implementation of IYoutubeClientWrapper using YoutubeExplode.

Public Functions

async Task DownloadAudioAsync (string videoUrl, string destination)

namespace Jellyfin
namespace Jellyfin.Data.Enums
namespace Jellyfin.Plugin
namespace Jellyfin.Plugin.Themerr
namespace Jellyfin.Plugin.Themerr.Api
namespace Jellyfin.Plugin.Themerr.Configuration
namespace Jellyfin.Plugin.Themerr.ScheduledTasks
namespace Jellyfin.Plugin.Themerr.Storage
namespace Jellyfin.Plugin.Themerr.Storage.Migrations
namespace MediaBrowser.Common.Api
namespace MediaBrowser.Common.Configuration
namespace MediaBrowser.Common.Plugins
namespace MediaBrowser.Controller
namespace MediaBrowser.Controller.Configuration
namespace MediaBrowser.Controller.Entities
namespace MediaBrowser.Controller.Entities.Movies
namespace MediaBrowser.Controller.Entities.TV
namespace MediaBrowser.Controller.Library
namespace MediaBrowser.Controller.Plugins
namespace MediaBrowser.Model.Entities
namespace MediaBrowser.Model.Plugins
namespace MediaBrowser.Model.Serialization
namespace MediaBrowser.Model.Tasks
namespace Microsoft.AspNetCore.Authorization
namespace Microsoft.AspNetCore.Http
namespace Microsoft.AspNetCore.Mvc
namespace Microsoft.EntityFrameworkCore
namespace Microsoft.EntityFrameworkCore.Infrastructure
namespace Microsoft.EntityFrameworkCore.Migrations
namespace Microsoft.Extensions.DependencyInjection
namespace Microsoft.Extensions.Hosting
namespace Microsoft.Extensions.Logging
namespace Newtonsoft.Json
namespace Newtonsoft.Json.Linq
namespace System
namespace System.Collections.Generic
namespace System.IO
namespace System.Linq
namespace System.Net
namespace System.Net.Http
namespace System.Net.Mime
namespace System.Reflection
namespace System.Security.Cryptography
namespace System.Threading
namespace System.Threading.Tasks
namespace YoutubeExplode
namespace YoutubeExplode.Videos.Streams
file ThemerrController.cs
file ThemerrLocalizationController.cs
file PluginConfiguration.cs
file IYoutubeClientWrapper.cs
file ThemerrTasks.cs
file LegacyThemerrData.cs
file 20260512230000_InitialCreate.cs
file 20260601180000_MigrateThemeHashToSha256.cs
file ThemerrDbContextModelSnapshot.cs
file ThemerrDatabaseMigrator.cs
file ThemerrDatabasePath.cs
file ThemerrDbContext.cs
file ThemerrMediaItem.cs
file ThemerrMediaItemSaveOptions.cs
file ThemerrMediaPath.cs
file ThemerrRepository.cs
file ThemerrThemeHashAlgorithm.cs
file ThemerrThemeHasher.cs
file ThemerrThemeProvider.cs
file ThemerrDbType.cs
file ThemerrLocalizationManager.cs
file ThemerrManager.cs
file ThemerrPlugin.cs
file ThemerrServiceRegistrator.cs
file ThemerrStartupService.cs
file YoutubeClientWrapper.cs
dir Jellyfin.Plugin.Themerr/Api
dir Jellyfin.Plugin.Themerr/Configuration
dir Jellyfin.Plugin.Themerr
dir Jellyfin.Plugin.Themerr/Storage/Migrations
dir Jellyfin.Plugin.Themerr/ScheduledTasks
dir Jellyfin.Plugin.Themerr/Storage