feat: optional direct Bandcamp/Apple/YouTube links via Odesli (flag-gated) (closes task/odesli-direct-cross-platform-links)
Source: task/odesli-direct-cross-platform-links (plan/improvement-backlog) — bandcamp was only a Google search; Odesli gives direct cross-platform links for Spotify-resolved names.
- service/odesli.js: makeOdesli({fetch,baseUrl}) -> getLinks(spotifyUrl); pure parseOdesli core; bounded AbortSignal.timeout; non-200/timeout/garbage -> {} (graceful).
- resolver.js: opt-in ODESLI / ODESLI_URL flag (default OFF). When ON, enrich each Spotify-resolved result with additive bandcamp/appleMusic/youtube fields (isHttpUrl-validated), cached per Spotify url. OFF -> no call, byte-identical behavior. /health + startup log surface the flag.
- extension: a tiny additive "bc" link to a direct Bandcamp page when result.bandcamp is present (reuses isSafeHttpUrl); primary artist/album/spotify/google rendering unchanged. styles.css: bandcamp-teal secondary link.
- odesli.test.js + odesli.fixture.json: parseOdesli unit-tested against a real captured Odesli response (Blood Incantation album -> direct bandcamp; absent apple/youtube omitted; junk -> {}); getLinks 200/non-200/throw/parse-error paths.
- docs: .env.example, README, AGENTS.md note the opt-in flag.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -117,6 +117,31 @@ With both gates, the LLM decides which names are artists and Spotify supplies th
|
||||
direct links; with the LLM alone, confirmed names get a Spotify direct link if one
|
||||
exists, else the Google fallback.
|
||||
|
||||
## Direct Bandcamp / Apple / YouTube links via Odesli (optional)
|
||||
|
||||
By default a name that isn't on Spotify links to a Google "<name> bandcamp" search — one click
|
||||
from the real Bandcamp page. With **Odesli** (the free, no-auth [song.link](https://odesli.co)
|
||||
API) enabled, an **album** result that resolved to a direct Spotify page is also enriched with the
|
||||
album's **direct** Bandcamp (and, when Odesli has them, Apple Music / YouTube) links, so the
|
||||
extension shows a small `bc` link straight to Bandcamp beside the Spotify link.
|
||||
|
||||
- **Opt-in, default OFF** — set `ODESLI=1` in `service/.env` (or `ODESLI_URL=<base>` to override the
|
||||
endpoint). With it off, no Odesli call is made and behavior is unchanged.
|
||||
- **Album results only** — Odesli resolves album/track *entity* urls, not artist urls (an artist
|
||||
url 405s), so only **album** results are enriched; artist results are skipped (no wasted call).
|
||||
- **Needs the Spotify gate** — an album result only carries a direct Spotify url when Spotify
|
||||
confirmed it, so set the Spotify credentials above to have a url to enrich. The no-creds Google
|
||||
fallback path is untouched.
|
||||
- **Bounded + graceful** — one cached Odesli call per Spotify url, with a timeout; if Odesli is
|
||||
down/slow/garbled the current result is kept and nothing breaks.
|
||||
|
||||
```sh
|
||||
ODESLI=1 SPOTIFY_CLIENT_ID=… SPOTIFY_CLIENT_SECRET=… node resolver.js
|
||||
# resolver listening on http://localhost:8787 (spotify: on, llm: off, odesli: on)
|
||||
```
|
||||
|
||||
`curl localhost:8787/health` then shows `"odesli":true`.
|
||||
|
||||
## 2. Install the extension in Firefox
|
||||
|
||||
The extension is unpacked / unsigned, so load it as a **temporary add-on**:
|
||||
|
||||
Reference in New Issue
Block a user