setlist/README.md
2026-04-19 09:09:17 -07:00

105 lines
4.2 KiB
Markdown

# 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.