Changeset 6c4ff7e in Klonkt for src/services/MigrationService.js
- Timestamp:
- 08/13/2026 11:39:57 PM (4 weeks ago)
- Branches:
- main
- Children:
- 9529d7b
- Parents:
- fbfd7a1
- File:
-
- 1 edited
-
src/services/MigrationService.js (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/services/MigrationService.js
rfbfd7a1 r6c4ff7e 248 248 * moet stranden, ook als die bron "van onszelf" is. 249 249 */ 250 async function haalBijlage(url, { safeFetch, mediaRoot, fs, path, maxBytes }) { 251 const r = await safeFetch(url, { headers: { accept: '*/*' } }).catch(() => null); 250 async function haalBijlage(url, { safeFetch, mediaRoot, fs, path, maxBytes, submap = 'migrated', headers = null }) { 251 // Ondertekend als het moet. Gehoste audio zit achter dezelfde poort als de 252 // rest van de bron, en een kale fetch krijgt daar een 403: de bron kan dan 253 // niet zien dat wij de doel-actor van zijn Move zijn. 254 const r = await safeFetch(url, { headers: headers || { accept: '*/*' } }).catch(() => null); 252 255 if (!r || !r.ok) return null; 253 256 const buf = Buffer.from(await r.arrayBuffer()); … … 261 264 })(); 262 265 const naam = `${crypto.randomUUID()}.${ext}`; 263 const rel = `migrated/${naam}`; 264 const abs = path.join(mediaRoot, 'migrated', naam); 266 // Zonder submap komt het bestand in de root zelf: dat is wat gehoste audio 267 // nodig heeft, want de speler zoekt AUDIO_ROOT + bestandsnaam en kijkt niet 268 // in mappen eronder. 269 const rel = submap ? `${submap}/${naam}` : naam; 270 const abs = submap ? path.join(mediaRoot, submap, naam) : path.join(mediaRoot, naam); 265 271 fs.mkdirSync(path.dirname(abs), { recursive: true }); 266 272 fs.writeFileSync(abs, buf); … … 294 300 // privacygrens en niet een weergavedetail. 295 301 noteVisibility = () => 'followers', 302 audioRoot = null, signHeaders = null, 296 303 } = deps; 297 304 const zichtbaarheid = noteVisibility; … … 329 336 const rapport = { 330 337 bron: bronActor.id, posts: 0, overgeslagen: 0, media: 0, mediaMislukt: 0, 331 blocks: 0, waarschuwingen: [],338 blocks: 0, tracksBinnen: 0, tracksMislukt: 0, overgeslagenTracks: 0, waarschuwingen: [], 332 339 }; 333 340 … … 441 448 } 442 449 if (gezien >= max) rapport.waarschuwingen.push(`gestopt bij ${max} berichten, draai het nog eens voor de rest`); 450 451 // ── De muziekbibliotheek ────────────────────────────────────── 452 // 453 // Losse nummers staan niet in de outbox: die hangen aan de tracks-collectie 454 // waar de actor via AS2 `streams` naar wijst. Zonder deze lus verhuist een 455 // muzieksite zijn berichten en laat hij zijn bibliotheek achter. 456 // 457 // De bron geeft ons hier alles, niet alleen de fedi_open-nummers, omdat we 458 // de doel-actor van zijn Move zijn (siteOpenTracks({alles})). Hetzelfde 459 // geldt voor de bestanden zelf, die anders achter de gated audio-route 460 // blijven. 461 const streams = [].concat(bronActor.streams || []).filter((u) => typeof u === 'string'); 462 const tracksUrl = streams.find((u) => /\/tracks\/?$/.test(u)); 463 if (tracksUrl && safeFetch && fs && path && audioRoot) { 464 const coll = await getJson(site.slug, tracksUrl); 465 const lijst = (coll && (coll.orderedItems || coll.items)) || []; 466 for (const it of (Array.isArray(lijst) ? lijst : []).slice(0, max)) { 467 const a = (it && typeof it.object === 'object' && it.object) ? it.object : it; 468 if (!a || !a.id) continue; 469 if (a.type && a.type !== 'Audio') continue; 470 if (alGemigreerd(site.slug, a.id)) { rapport.overgeslagenTracks++; continue; } 471 const bron = a.url && (typeof a.url === 'string' ? a.url : (Array.isArray(a.url) ? (a.url[0] && (a.url[0].href || a.url[0])) : a.url.href)); 472 if (!bron || !/^https?:\/\//i.test(String(bron))) { rapport.tracksMislukt++; continue; } 473 const g = await haalBijlage(String(bron), { 474 safeFetch, mediaRoot: audioRoot, fs, path, maxBytes, submap: '', 475 headers: signHeaders ? signHeaders(site.slug, String(bron), '*/*') : null, 476 }).catch(() => null); 477 if (!g) { 478 rapport.tracksMislukt++; 479 rapport.waarschuwingen.push(`nummer niet opgehaald: ${a.name || bron}`); 480 continue; // dezelfde regel als bij de zip: geen bestand, geen track 481 } 482 const trackId = crypto.randomUUID(); 483 const mediaId = crypto.randomUUID(); 484 try { 485 db.prepare('INSERT INTO media (id, site_id, filename, mime_type, size, storage_path) VALUES (?,?,?,?,?,?)') 486 .run(mediaId, site.id, g.filename, g.mediaType, g.size, g.storage_path); 487 db.prepare(`INSERT INTO audio_tracks (id, site_id, title, artist, album, duration, media_id, fedi_open) 488 VALUES (?,?,?,?,?,?,?,0)`) 489 .run(trackId, site.id, a.name || 'zonder titel', a.artist || null, a.album || null, 490 Number(a.duration) || null, mediaId); 491 recordMigrated(site.slug, { origin: a.id, target: `${me}/ap/tracks/${trackId}`, sourceActor: bronActor.id, isPublic: false }); 492 rapport.tracksBinnen++; 493 } catch (e) { 494 rapport.tracksMislukt++; 495 rapport.waarschuwingen.push(`nummer niet opgeslagen: ${a.name || a.id} (${e && e.message})`); 496 } 497 } 498 } else if (tracksUrl) { 499 rapport.waarschuwingen.push('muziekbibliotheek overgeslagen: geen audiomap meegegeven'); 500 } 443 501 } catch (e) { 444 502 // 9-bij-mislukking: de vlag blijft OPEN staan. Derden blijven dan kijken,
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)