Changeset 183875b in Klonkt for src/routes/admin-audio.js


Ignore:
Timestamp:
06/20/2026 05:23:08 AM (3 months ago)
Author:
roboburr <roboburr@…>
Branches:
main
Children:
d727e92
Parents:
459acd9
Message:

feat(audio): per-track "open in" Spotify/YouTube/SoundCloud links

New per-track fields link_spotify/link_youtube/link_soundcloud (audio_tracks),
editable in the track editor (https + correct host validated). Shown as small
brand icons per track row in standalone track embeds, albums and playlists —
click opens the track on that service (new tab). buster audio.css?v=8.

Co-Authored-By: Claude <noreply@…>

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/routes/admin-audio.js

    r459acd9 r183875b  
    7272
    7373const router = express.Router();
     74
     75// "Open in"-platformlinks per track: alleen https + de juiste host accepteren
     76// (href komt ongeescaped in de view → scheme/host-guard tegen misbruik).
     77const LINK_DOMAINS = {
     78  spotify: ['spotify.com'],
     79  youtube: ['youtube.com', 'youtu.be', 'music.youtube.com'],
     80  soundcloud: ['soundcloud.com'],
     81};
     82function platformLink(url, domains) {
     83  const u = String(url || '').trim();
     84  if (!u || !/^https:\/\//i.test(u)) return null;
     85  try {
     86    const h = new URL(u).hostname.toLowerCase();
     87    if (domains.some((d) => h === d || h.endsWith('.' + d))) return u;
     88  } catch (e) { /* ongeldige URL */ }
     89  return null;
     90}
    7491
    7592router.get('/', requireGod, (req, res) => {
     
    172189    const finalCredit  = (req.body.credit  || '').trim() || finalArtist || null;
    173190    const finalLicense = (req.body.license || '').trim() || null;
     191    const finalLinkSpotify    = platformLink(req.body.link_spotify, LINK_DOMAINS.spotify);
     192    const finalLinkYoutube    = platformLink(req.body.link_youtube, LINK_DOMAINS.youtube);
     193    const finalLinkSoundcloud = platformLink(req.body.link_soundcloud, LINK_DOMAINS.soundcloud);
    174194
    175195    console.log('[admin-audio] upload received:', {
     
    222242      console.log('[admin-audio] inserting audio_tracks row (duration=' + finalDuration + ')');
    223243      db.prepare(`
    224         INSERT INTO audio_tracks (id, site_id, title, artist, album, duration, cover_url, credit, license, media_id, position)
    225         VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, COALESCE(
     244        INSERT INTO audio_tracks (id, site_id, title, artist, album, duration, cover_url, credit, license, link_spotify, link_youtube, link_soundcloud, media_id, position)
     245        VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, COALESCE(
    226246          (SELECT MAX(position) + 1 FROM audio_tracks WHERE site_id = ?),
    227247          0
     
    233253        coverUrl,
    234254        finalCredit, finalLicense,
     255        finalLinkSpotify, finalLinkYoutube, finalLinkSoundcloud,
    235256        mediaId, site.id
    236257      );
     
    378399  const t = db.prepare(`
    379400    SELECT t.id, t.title, t.artist, t.album, t.duration, t.cover_url,
    380            t.credit, t.license, t.position, t.created_at, m.filename
     401           t.credit, t.license, t.link_spotify, t.link_youtube, t.link_soundcloud,
     402           t.position, t.created_at, m.filename
    381403    FROM audio_tracks t LEFT JOIN media m ON m.id = t.media_id
    382404    WHERE t.id = ? AND t.site_id = ?
     
    445467  if (Object.prototype.hasOwnProperty.call(body, 'license')) {
    446468    fields.push('license = ?'); values.push(String(body.license || '').trim() || null);
     469  }
     470  if (Object.prototype.hasOwnProperty.call(body, 'link_spotify')) {
     471    fields.push('link_spotify = ?'); values.push(platformLink(body.link_spotify, LINK_DOMAINS.spotify));
     472  }
     473  if (Object.prototype.hasOwnProperty.call(body, 'link_youtube')) {
     474    fields.push('link_youtube = ?'); values.push(platformLink(body.link_youtube, LINK_DOMAINS.youtube));
     475  }
     476  if (Object.prototype.hasOwnProperty.call(body, 'link_soundcloud')) {
     477    fields.push('link_soundcloud = ?'); values.push(platformLink(body.link_soundcloud, LINK_DOMAINS.soundcloud));
    447478  }
    448479
Note: See TracChangeset for help on using the changeset viewer.