Files
linker/README.md
T
paulandClaude Opus 4.8 607a4ab45e fix: background-script fetch (CSP/mixed-content), prefer-Spotify links, toolbar icon (task/fix-extension-and-linkui)
The extension linked nothing and the resolver saw no requests: the content script
fetched http://localhost:8787 directly from the HTTPS reddit page, which reddit's CSP /
mixed-content blocks. Move the network call to a background script (extension origin,
exempt) and add stage logging so failures are visible.

- extension/background.js (new): does the resolver fetch on message; sets the toolbar badge.
- extension/content.js: talks to background via runtime messaging (no page-context fetch);
  [rsl] console logs at boot/root/candidates/resolve/scan; single primary link.
- extension/manifest.json: background.scripts + browser_action (icon.svg, title).
- extension/{styles.css,icon.svg}: platform-coloured link (green=spotify, teal=bandcamp) + toolbar icon.
- service/lib.js: primaryOf()/isSearchUrl() — link Spotify when the artist is on Spotify,
  else Bandcamp, else Spotify search; spotifyResult/mbResult attach `primary` (unit-tested).
- README: link behaviour, toolbar, Troubleshooting.

Verified: scripts/check.sh green (10 tests); resolver returns `primary` end-to-end. The
in-browser fix is logic-verified only (no headless Firefox here) — reload the temp add-on
and watch the page console `[rsl]` logs to confirm.

Source: project human-feedback 2026-06-16 (notes 01KV8VC58QMYBDY6VVVJHR8YNY + 01KV91AMJCN2C4GFCKMKQRGNXE).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 00:36:55 +00:00

142 lines
5.7 KiB
Markdown

# Reddit → Spotify / Bandcamp linker
A Firefox extension that, while you browse a Reddit thread, finds **artist / band
names** in the comments (and the post body) and turns them into inline links to
**Spotify** and **Bandcamp** — so a recommendation thread like
[this one](https://www.reddit.com/r/SlamDeathMetal/comments/1txh2r1/) becomes a
list of clickable artists instead of names you have to copy-paste into search.
The hard part is *"which words are artists and which aren't?"*. Rather than guess
with client-side rules, the extension hands candidate names to a tiny local
**resolver service** that checks each one against a real music database and only
links the names that actually match an artist.
```
reddit page content script resolver service
─────────── ────────────── ────────────────
comment text ──extract──> candidate names ──POST /resolve──> Spotify API (direct links)
or
<a> links <──rewrite── confirmed links <───────────────── MusicBrainz (zero-setup)
```
## Layout
```
service/ tiny Node.js resolver (one file, zero npm deps)
resolver.js
package.json
.env.example
extension/ Firefox MV2 extension
manifest.json
background.js (does the resolver fetch; talks to the content script)
content.js
styles.css
icon.svg
```
## 1. Run the resolver service
Requirements: **Node 18+** (uses the built-in `fetch`). No `npm install` needed —
there are no dependencies.
```sh
cd service
node resolver.js
# resolver listening on http://localhost:8787 (provider: musicbrainz)
```
That's it. With no configuration the resolver validates names against
**MusicBrainz** (no account required). When MusicBrainz knows an artist's official
links (its `url-relations`), you get **direct** Spotify and Bandcamp artist pages;
otherwise it falls back to Spotify/Bandcamp **search** URLs.
### Optional: direct Spotify links
For **direct artist links** (instead of Spotify search), give the service Spotify
API credentials:
1. Create a free app at <https://developer.spotify.com/dashboard> and copy its
**Client ID** and **Client Secret**.
2. `cp .env.example .env` and fill them in (the `.env` file is gitignored):
```
SPOTIFY_CLIENT_ID=your_id
SPOTIFY_CLIENT_SECRET=your_secret
```
3. Restart the service. It will report `provider: spotify` on startup.
(Bandcamp has no public API; direct Bandcamp links come from MusicBrainz
`url-relations` when present, else a Bandcamp search URL.)
Quick check that it works:
```sh
curl -s localhost:8787/resolve \
-H 'content-type: application/json' \
-d '{"candidates":["Cerebral Bore","Devourment","Notarealband Xyzzy"]}'
# {"Cerebral Bore":{...},"Devourment":{...},"Notarealband Xyzzy":null}
```
## 2. Install the extension in Firefox
The extension is unpacked / unsigned, so load it as a **temporary add-on**:
1. Open `about:debugging#/runtime/this-firefox`.
2. **Load Temporary Add-on…**
3. Select `extension/manifest.json`.
It's now active until you restart Firefox. (To keep it permanently you'd sign it
via [AMO](https://addons.mozilla.org/developers/) or use Firefox Developer/ESR
with `xpinstall.signatures.required = false`.)
## 3. Use it
1. Make sure the resolver service is running.
2. Open any Reddit comments thread (a URL with `/comments/` in it).
3. Artist names become a single link — to **Spotify** if the artist is on Spotify,
otherwise to **Bandcamp** — colour-coded (green = Spotify, teal = Bandcamp). New
comments loaded as you scroll are linked automatically.
4. The toolbar icon shows the extension is active; its badge shows how many links were
added on the current page.
## Troubleshooting
If nothing gets linked:
1. Confirm the resolver is running — `curl localhost:8787/health` should return
`{"ok":true,...}`.
2. On the reddit thread, open the browser console (F12) and look for `[rsl]` logs: they
report the root element, candidate count, and resolver responses on each scan. A
`resolve failed` line means the background script can't reach the resolver (is it on
`:8787`?); `candidates found: 0` means the comment text wasn't matched (please report
the thread).
3. The content script reaches the resolver **through the extension's background script**
— a page-context fetch to `http://localhost` is blocked by reddit's CSP — so make sure
the add-on loaded without errors in `about:debugging`.
## Configuration
The resolver URL is the constant `RESOLVER_URL` at the top of
`extension/content.js` (default `http://localhost:8787`). If you change the host
or port, update **both** that constant **and** the matching entry in
`extension/manifest.json` → `permissions` (Firefox needs the host listed there to
let the content script reach it).
## Limitations (MVP)
- **Detection is capitalization-based.** Names written in lowercase, or split
across formatting (e.g. **bold** in the middle of a name), can be missed. The
resolver's exact-name match keeps false *positives* low; the trade-off is some
false *negatives*.
- **Links are direct when MusicBrainz has the artist's `url-relations`** (official
Bandcamp / Spotify pages); otherwise they fall back to a search URL. (Each
confirmed artist costs one extra throttled MusicBrainz lookup, cached after.)
- The resolver caches results in memory; it resets when you restart it.
- Without Spotify credentials the MusicBrainz path is rate-limited to ~1 lookup/
second, so the first scan of a large thread fills in gradually (cached after).
- Built and tested as a Firefox MV2 extension.
## License
Personal project — do as you like.