# Setlist A small Beat Saber (PC, BSIPA) plugin that syncs in-game playlist edits back to [BeatLeader](https://beatleader.com) so your playlists stay current outside the game — on the website, on your phone, or shared with friends. ## What it does When you add a map to a playlist in-game (via the standard [PlaylistManager](https://github.com/rithik-b/PlaylistManager) "Add to playlist" flow), Setlist: 1. Watches `PlaylistManager.Utilities.Events.playlistSongAdded`. 2. Checks whether the playlist is a **BeatLeader-synced playlist owned by you** — i.e. its `customData.syncURL` is an `api.beatleader.com/playlist/guid/…` URL and its `customData.owner` matches your platform user id. 3. Serializes the updated playlist and **POSTs it back to BeatLeader** (`POST /user/playlist?id=…&shared=…`). The POST reuses the [BeatLeader mod](https://github.com/BeatLeader/beatleader-mod)'s authenticated session — no extra login, no API token in your config, nothing to copy/paste. If BeatLeader is signed in, Setlist is signed in. The result: edit playlists in VR; see them updated on the website and any device that consumes them, without alt-tabbing or running a sync script. ## Requirements - Beat Saber `1.40.8` (PC), via BSIPA. - [BeatLeader](https://github.com/BeatLeader/beatleader-mod) `^0.9.0` — must be installed **and signed in** for the sync to authenticate. - [PlaylistManager](https://github.com/rithik-b/PlaylistManager) `^1.7.0`. - [BeatSaberPlaylistsLib](https://github.com/Zingabopp/BeatSaberPlaylistsLib) `^1.7.0` (transitive via PlaylistManager). See `Setlist/manifest.json` for the authoritative list. ## Install Drop `Setlist.dll` into `Beat Saber/Plugins/` alongside BeatLeader and PlaylistManager (BSManager works fine). Confirm in `Logs/_latest.log`: ``` [INFO @ ...] [Setlist|...] platformUserId=... [INFO @ ...] [Setlist|...] Playlist "...": hasSyncUrl=True, owner=..., ownerMatchesPlatform=true (...) ``` When you add a map to one of those playlists in-game you should then see: ``` [INFO @ ...] [Setlist|...] Setlist BeatLeader sync: OK HTTP 200 playlist="..." body=... ``` ## Build (Linux / NixOS, no Visual Studio / Rider) This whole plugin is built from the `dotnet` CLI on Linux — including NixOS — no BSMT IDE extension required. The Linux + Cursor toolchain (.NET SDK 9, BSMT MSBuild tasks, the missing-`net472`-reference-assemblies workaround, and the "copy DLL into `Plugins/` on a Unix host" target) is documented in: - [`docs/pc-modding.md`](docs/pc-modding.md) — full guide, adapted from the BSMG wiki for Linux + Cursor + LLM-assisted dev. - [`docs/bootstrap.md`](docs/bootstrap.md) — exactly how this project was scaffolded (template, NuGet pins, `BeatSaberDir`, etc.). Quick start once `Setlist.csproj.user` points at your install: ```bash cd Setlist dotnet restore dotnet build -c Debug ``` Output: `Setlist/bin/Debug/Setlist.dll`, also copied into `$BeatSaberDir/Plugins/Setlist.dll` by the Unix-host post-build target. ## How it integrates with the two host plugins Both integrations are deliberately thin and live in a single project so they can be read end-to-end: - **PlaylistManager** — Setlist subscribes to its public `Events.playlistSongAdded` hook (same one used by the in-game UI flow). Notes on that flow live in [`docs/playlistmanager-add-map.md`](docs/playlistmanager-add-map.md). - **BeatLeader** — Setlist references the shipped `BeatLeader.dll`, waits on BeatLeader's own `Authentication._signedIn` flag, and POSTs through Unity's `UnityWebRequest` so the cookies BeatLeader's `HttpClient` already has on the shared `CookieContainer` are reused. Background and the alternative "go through `WebRequestFactory` directly" approach are in [`docs/beatleader-playlist-api.md`](docs/beatleader-playlist-api.md) and [`docs/beatleader-api-samples.md`](docs/beatleader-api-samples.md). ## Status Early / personal-use. Currently scoped to: - Adds (one new song → one POST). Removes, reorders, renames, and bulk edits are not yet wired. - BeatLeader as the sync target. The same model would extend to other backends that accept a full-playlist upload. See [`AGENTS.md`](AGENTS.md) for repo conventions (version-bump-on-build, smoketest, etc.) if you're contributing or letting an agent work in this repo.