ingest: give every track a source link

The player's "source" link only worked for direct yt-dlp URLs. Two other
cases had no linkable page: ListenBrainz picks resolved via ytsearch1: (the
locator is a search query) and Subsonic library tracks (an opaque song id).

Centralise the rule in Track.page_url and cover both: the yt-dlp fetcher now
records the concrete video URL it resolved into source_url, and a Subsonic
track links to the stream's new /share endpoint, which asks ingest to mint a
public share (createShare) on demand and redirects to it — so a share is only
created when a listener actually clicks, never per played track.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
nemunaire 2026-07-04 11:42:29 +08:00
commit efd7307cc6
9 changed files with 154 additions and 18 deletions

View file

@ -372,3 +372,33 @@ harbor.http.register(
serve_attachment(resp, name)
end
)
# Partage Subsonic à la demande. Un morceau de la bibliothèque Subsonic n'a pas
# d'URL publique : son lien « source » pointe ici avec l'id du morceau. On
# demande alors à l'ingest (qui détient les identifiants Subsonic) de créer un
# partage public via createShare, puis on redirige l'auditeur vers l'URL
# renvoyée. Le partage n'est donc créé que si quelqu'un clique réellement sur le
# lien — jamais à chaque morceau joué. 404 si l'id manque, 502 si l'ingest ne
# peut pas partager (partage désactivé côté serveur, injoignable…).
ingest_share_url = "http://ingest:8080/share"
harbor.http.register(
port=8000, method="GET", "/share",
fun(req, resp) -> begin
song = list.assoc(default="", "song", req.query)
if song == "" then
resp.status_code(404)
resp.data("missing song id")
else
body = http.post(data="", timeout=10.0, "#{ingest_share_url}?id=#{url.encode(song)}")
share = json.parse(default={url=""}, string.trim(body))
if body.status_code == 200 and share.url != "" then
resp.status_code(302)
resp.header("Location", share.url)
resp.data("")
else
resp.status_code(502)
resp.data("share unavailable")
end
end
end
)