Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/services/PlaylistService.js

    r834bcc3 r7090fd2  
    1515import { v4 as uuid } from 'uuid';
    1616
     17/**
     18 * Een volledige datum of niets (shaer-756s).
     19 *
     20 * STRIKT, en dat is de hele functie. `year` bestaat al en blijft; dit veld
     21 * bestaat juist omdat een jaartal geen uitgavedatum is. Zou hij "2024"
     22 * doorlaten en er 2024-01-01 van maken, dan stond er straks een dag op de
     23 * federatie die niemand ooit heeft ingevoerd -- en dan hadden we het veld net
     24 * zo goed niet kunnen toevoegen.
     25 *
     26 * Ook 2024-02-31 valt af: dat is geen strengheid om de strengheid, Date rolt
     27 * hem stilletjes door naar 2 maart en dan slaan we iets anders op dan er
     28 * ingetypt is.
     29 */
     30function normDatum(v) {
     31  const s = String(v == null ? '' : v).trim();
     32  if (!s) return null;
     33  if (!/^\d{4}-\d{2}-\d{2}$/.test(s)) return null;
     34  const d = new Date(`${s}T00:00:00Z`);
     35  return Number.isNaN(d.getTime()) || d.toISOString().slice(0, 10) !== s ? null : s;
     36}
     37
     38/** Een MusicBrainz-id of niets. Zelfde vorm als sites.mb_artist_id. */
     39function normMbid(v) {
     40  const s = String(v == null ? '' : v).trim().toLowerCase();
     41  return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/.test(s) ? s : null;
     42}
     43
    1744class PlaylistService {
    1845
     
    5279    const rows = db.prepare(`
    5380      SELECT p.id, p.title, p.artist, p.year, p.cover_url, p.kind,
     81             p.release_date, p.mb_release_id,
    5482             p.created_at, p.updated_at,
    5583             (SELECT COUNT(*) FROM playlist_tracks WHERE playlist_id = p.id) AS track_count
     
    6593      cover: r.cover_url || '',
    6694      kind: r.kind || 'album',
     95      release_date: r.release_date || '',
     96      mb_release_id: r.mb_release_id || '',
    6797      track_count: r.track_count,
    6898      created_at: r.created_at,
     
    86116    if (!id) return null;
    87117    const p = db.prepare(`
    88       SELECT id, title, artist, year, cover_url, kind, created_at, updated_at
     118      SELECT id, title, artist, year, cover_url, kind, release_date, mb_release_id, created_at, updated_at
    89119      FROM playlists WHERE site_id = ? AND id = ?
    90120    `).get(siteId, id);
     
    125155      cover: p.cover_url || fallbackCover,
    126156      kind: (p.kind === 'playlist') ? 'playlist' : 'album',
     157      // created_at hoort erbij omdat de AP-kant er `published` van maakt. Zonder
     158      // dit veld viel buildAlbumObject terug op 1970, en dat stond op 16-8
     159      // gewoon op de federatie.
     160      created_at: p.created_at,
     161      // Leeg als het een afspeellijst is -- de opslag houdt ze daar al leeg,
     162      // maar dit is de plek waar de editor leest en die mag niet afhangen van
     163      // wat er toevallig in de kolom stond.
     164      release_date: p.kind === 'playlist' ? '' : (p.release_date || ''),
     165      mb_release_id: p.kind === 'playlist' ? '' : (p.mb_release_id || ''),
    127166      tracks: mappedTracks,
    128167    };
     
    141180    const kind = data.kind === 'playlist' ? 'playlist' : 'album';
    142181
     182    // Alleen een UITGAVE draagt deze twee. Een afspeellijst heeft geen
     183    // uitgavedatum en geen release-id, en dat onderscheid is precies wat de
     184    // keuze album/playlist betekent (shaer-cyg). Het afdwingen gebeurt HIER en
     185    // niet alleen in het scherm: een scherm kun je omzeilen -- de API ligt open
     186    // voor de post-editor -- en dan staat er stille rommel op een mixtape die
     187    // later als Album de deur uit gaat.
     188    const uitgave = kind === 'album';
     189    const releaseDate = uitgave ? normDatum(data.release_date) : null;
     190    const mbRelease = uitgave ? normMbid(data.mb_release_id) : null;
     191
    143192    const tx = db.transaction(() => {
    144193      db.prepare(`
    145         INSERT INTO playlists (id, site_id, title, artist, year, cover_url, kind, created_at, updated_at)
    146         VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
     194        INSERT INTO playlists (id, site_id, title, artist, year, cover_url, kind, release_date, mb_release_id, created_at, updated_at)
     195        VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
    147196      `).run(
    148197        id, siteId, title,
     
    150199        Number.isFinite(+data.year) && +data.year > 0 ? +data.year : null,
    151200        String(data.cover || '').trim() || null,
    152         kind, now, now,
     201        kind, releaseDate, mbRelease, now, now,
    153202      );
    154203      this._writeTracks(id, siteId, data.tracks);
     
    171220    if (!id) return false;
    172221    const existing = db.prepare(
    173       'SELECT id FROM playlists WHERE site_id = ? AND id = ?'
     222      'SELECT id, kind FROM playlists WHERE site_id = ? AND id = ?'
    174223    ).get(siteId, id);
    175224    if (!existing) return false;
     
    177226    const fields = [];
    178227    const values = [];
     228    // Wat wordt het NA deze wijziging? `kind` hoeft niet in data te staan, dus
     229    // val terug op wat er ligt.
     230    const nieuwKind = Object.prototype.hasOwnProperty.call(data, 'kind')
     231      ? (data.kind === 'playlist' ? 'playlist' : 'album')
     232      : (existing.kind || 'album');
    179233    if (Object.prototype.hasOwnProperty.call(data, 'title')) {
    180234      const v = String(data.title || '').trim();
     
    193247    }
    194248    if (Object.prototype.hasOwnProperty.call(data, 'kind')) {
    195       fields.push('kind = ?'); values.push(data.kind === 'playlist' ? 'playlist' : 'album');
     249      fields.push('kind = ?'); values.push(nieuwKind);
     250    }
     251    // De uitgavevelden. Wordt dit een afspeellijst, dan gaan ze ALTIJD leeg --
     252    // ook als de aanroeper er niets over zei. Anders houdt een album dat je tot
     253    // mixtape ombouwt zijn uitgavedatum en zijn release-id, en die duiken dan
     254    // weer op zodra iemand hem terugzet. Een veld dat niet meer mag bestaan
     255    // hoort weg te zijn, niet te wachten.
     256    if (nieuwKind !== 'album') {
     257      fields.push('release_date = ?'); values.push(null);
     258      fields.push('mb_release_id = ?'); values.push(null);
     259    } else {
     260      if (Object.prototype.hasOwnProperty.call(data, 'release_date')) {
     261        fields.push('release_date = ?'); values.push(normDatum(data.release_date));
     262      }
     263      if (Object.prototype.hasOwnProperty.call(data, 'mb_release_id')) {
     264        fields.push('mb_release_id = ?'); values.push(normMbid(data.mb_release_id));
     265      }
    196266    }
    197267    fields.push('updated_at = ?'); values.push(new Date().toISOString());
Note: See TracChangeset for help on using the changeset viewer.