# Vanguard Metadata — Jellyfin plugin Metadata provider for gameplay recordings. Each streamer/submitter folder is a show; season and episode numbers come from the recording timestamp under a rolling policy; names, avatars and episode titles come from Discord via Authentik's identity link; new recordings and clips are announced in a Discord channel. ## Layout - `Jellyfin.Plugin.Vanguard.Core/` — pure logic: `SeasonPolicy` (rolling buckets, naming, overrides), `ItemTimestamp` (sidecar → filename patterns → mtime). No Jellyfin dependency. Unit-tested. - `Jellyfin.Plugin.Vanguard/` — the plugin: providers (Series, Series images, Season, Episode), services (Discord REST, Authentik REST, event store, identity resolver, feed), scheduled tasks (Discord snapshot every 5 min; season roll nightly after the rollover hour), config page. - `Jellyfin.Plugin.Vanguard.Tests/` — xunit. ## Season scheme | age of item | season # | season name | |---|---|---| | current ISO week | `YYYYMMDD` | "Thursday, Oct 29" | | current month | `1YYYYWW` | "Week 44" | | current year | `YYYYMM` | "October 2026" | | older | `YYYY` | "2026" | Episode # = `MMDDHHMMSS` of the local timestamp — never changes when the season rolls. Broadcast day rolls at the configured hour (default 04:00). Overrides: `seasonNumber=Name`, one per line. ## Timestamp sources, in order 1. `.json` / `.clip.json` sidecar with `"timestamp"` (UTC ISO-8601) — written by the clip bot 2. filename: MediaMTX `2026-10-29_21-03-11`, Game Bar `2026-10-29 21-03-11`, ShadowPlay `2026.10.29 - 21.03.11`, Steam `20261029_210311` 3. file modification time (Syncthing preserves the gamer's mtime) ## Build / package ./package.sh # tests + Release build → dist/VanguardMetadata_.zip + manifest.json Requires .NET 10 SDK. Bump `version` in `build.yaml` for a release. ## Install on the server (manual, v0.1) scp dist/VanguardMetadata_0.1.0.0.zip debian@HOST:/tmp/ ssh debian@HOST 'sudo -u "#1000" mkdir -p "/srv/appdata/jellyfin/config/plugins/Vanguard Metadata_0.1.0.0" && sudo -u "#1000" python3 -m zipfile -e /tmp/VanguardMetadata_0.1.0.0.zip "/srv/appdata/jellyfin/config/plugins/Vanguard Metadata_0.1.0.0/" && cd ~/vanguard-stream && docker compose restart jellyfin' Later: serve `dist/` at `https://HOST/plugins/` (Caddy) and add it as a repository in Jellyfin so updates come through the Catalog. ## Runs with an empty config Seasons, episode numbers, timestamps and the nightly roll need nothing external. Without a Discord bot token the show is named after its folder, has no poster, and episode titles are the dock title; without Authentik no folder→Discord mapping is attempted; without a feed channel nothing is posted. Add the credentials later and re-run "roll seasons" / refresh the libraries to pick up names and avatars. ## Configure (Dashboard → Plugins → Vanguard Metadata) - Discord: bot token (add a **Bot** to the existing Authentik Discord application; enable the Server Members intent; invite it to the server), guild ID, feed channel ID, public Jellyfin URL. - Authentik: URL + API token of a read-only service account (used to map folder → Discord user). - Folder → identity overrides if a streamer's folder name isn't their Authentik username. - Libraries (Dashboard → Libraries → each of streams/clips): content type Shows; metadata downloaders: **only** "Vanguard Metadata" for Series, Season and Episode; image fetchers: Vanguard Metadata (Series) and **Screen Grabber** (Episode) — the grab is what the Discord embed attaches. ## Tasks (Dashboard → Scheduled Tasks → Vanguard) - "snapshot Discord events": every 5 min + startup. Run it once after configuring. - "roll seasons": daily at rollover+10 min. Run it once after the first library scan.