Vanguard media stack: ingest, copyparty, Syncthing, normalize sweep, Authentik, Jellyfin + Vanguard Metadata plugin, MariaDB, Gitea, bot runtime

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
2026-10-30 15:43:30 -05:00
commit c602a6ff52
66 changed files with 4229 additions and 0 deletions

View File

@@ -0,0 +1,51 @@
using MediaBrowser.Model.Plugins;
namespace Jellyfin.Plugin.Vanguard.Configuration;
/// <summary>Plugin settings (edited on the plugin's config page).</summary>
public class PluginConfiguration : BasePluginConfiguration
{
// --- Discord -------------------------------------------------------------------------
public string DiscordBotToken { get; set; } = string.Empty;
public string DiscordGuildId { get; set; } = string.Empty;
// --- Discord feed (new stream / new clip notices) ---------------------------------------
/// <summary>Channel to post notices in (same guild). Empty = feed off.</summary>
public string NotifyChannelId { get; set; } = string.Empty;
public bool NotifyNewStreams { get; set; } = true;
public bool NotifyNewClips { get; set; } = true;
/// <summary>Public Jellyfin URL used in links, e.g. https://watch.example.com</summary>
public string PublicUrl { get; set; } = string.Empty;
/// <summary>Library names that count as streams / clips (case-insensitive substring match on the library name or path).</summary>
public string StreamsLibraryHint { get; set; } = "stream";
public string ClipsLibraryHint { get; set; } = "clip";
// --- Playback policy (no hardware encoder on this box) --------------------------------------
/// <summary>Set direct-play-only on all users automatically (new SSO users included). Turn off when the server can transcode.</summary>
public bool EnforceDirectPlayOnly { get; set; } = true;
public bool EnforceOnAdminsToo { get; set; } = false;
// --- Authentik (streamer username -> Discord user id via the OAuth source connection) --
public string AuthentikUrl { get; set; } = "https://auth.example.com";
public string AuthentikApiToken { get; set; } = string.Empty;
// --- Time / seasons ---------------------------------------------------------------------
public string TimeZoneId { get; set; } = "America/New_York";
/// <summary>Hour (0-23) at which the "broadcast day" rolls over. 4 = a 01:00 clip belongs to the previous evening.</summary>
public int BroadcastDayRolloverHour { get; set; } = 4;
/// <summary>Season name overrides: "202611=Winter Scrims Block", one per line.</summary>
public string SeasonNameOverrides { get; set; } = string.Empty;
/// <summary>Prefer the overlapping Discord scheduled event's name as the episode title; fallback is the dock title (folder name).</summary>
public bool EpisodeTitleFromEvent { get; set; } = true;
/// <summary>
/// Folder name -> identity, one per line: "techy=123456789012345678" (Discord user id) or
/// "techy=authentik:someuser" (Authentik username). Folders not listed are looked up in Authentik
/// by username = folder name.
/// </summary>
public string FolderIdentityMap { get; set; } = string.Empty;
/// <summary>Hours of slack when matching a recording to a Discord scheduled event (before start / after end).</summary>
public double EventMatchSlackHours { get; set; } = 1.0;
}