Ignore:
Timestamp:
08/06/2026 02:20:19 PM (5 weeks ago)
Author:
roboburr <roboburr@…>
Branches:
main
Children:
7aa3140
Parents:
58cfe5f
git-author:
Robin <roboburr@…> (08/06/2026 02:20:09 PM)
git-committer:
roboburr <roboburr@…> (08/06/2026 02:20:19 PM)
Message:

Elke bijlage zegt waar hij voor was (shaer-pmr, vervolg)

Gevonden bij een oefenherstel: ik vergeleek dertien kolommen, noemde het een
schone rondgang, en vergeleek daarna ALLE kolommen. Toen bleken er drie dingen
weg te vallen.

COVER de bytes zaten in het archief, maar nergens stond dat ze de

cover waren. cover_image_url kwam als null terug, dus de post
stond zonder cover.

C2S-BIJLAGE idem: het audiobestand en zijn poster zaten erin, maar

c2s_attachments werd niet hersteld, dus de speler verdween.

SUB-SECONDE de import zette tijdstempels om naar SQL-notatie en verloor de

milliseconden. Twee posts in dezelfde seconde staan dan in
willekeurige volgorde.

Elke bijlage draagt nu een shaer:role -- cover, coverVideo, inline, c2s, poster,
track -- en een poster wijst met shaer:posterFor naar de bijlage waar hij bij
hoort. De importer bouwt cover_image_url, cover_video_url en c2s_attachments
daaruit terug. Een rol is geen versiering: zonder rol heeft het archief wel de
bytes maar niet het feit dat ze de cover WAREN, en dat zie je pas als je alle
kolommen vergelijkt.

Tijdstempels gaan nu ongewijzigd de database in. Klonkt schrijft zelf in twee
spellingen; het archief normaliseert naar ISO. Het MOMENT overleeft de rondgang,
de spelling niet -- nu ook zo gedocumenteerd in plaats van stilzwijgend.

Rondgang op echte beta-data: geen verschil meer over 29 kolommen, met de tijden
op moment vergeleken in plaats van op tekst. 21 tests. Suite 514/514.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/services/ArchiveImportService.js

    r58cfe5f r812fea9  
    2828
    2929const sha256 = (buf) => crypto.createHash('sha256').update(buf).digest('hex');
    30 const sqlTijd = (iso) => { const t = Date.parse(iso); return isNaN(t) ? null : new Date(t).toISOString().replace('T', ' ').replace(/\.\d+Z$/, ''); };
     30// De tijdstempel gaat er ONGEWIJZIGD in. Omzetten naar SQL-notatie kostte de
     31// sub-seconde, en twee posts in dezelfde seconde staan dan in willekeurige
     32// volgorde. Klonkt schrijft zelf ook ISO in deze kolommen.
     33const tijd = (iso) => (iso && !isNaN(Date.parse(iso)) ? String(iso) : null);
    3134
    3235// ── Inlezen ───────────────────────────────────────────────────────
     
    220223    (id, site_id, slug, author_id, title, content, excerpt, status, cover_image_url, cover_alt, cover_video_url,
    221224     pinned, type, tags, published_at, created_at, updated_at, noindex, publish_at, fan_only, nsfw, language,
    222      content_warning, poll_json, quote_uri, quote_actor, ap_visibility, paid, paid_min_cents, view_count, origin_server)
     225     content_warning, poll_json, quote_uri, quote_actor, ap_visibility, paid, paid_min_cents, view_count, c2s_attachments, origin_server)
    223226    VALUES (@id, @site_id, @slug, @author_id, @title, @content, @excerpt, @status, @cover_image_url, @cover_alt, @cover_video_url,
    224227     @pinned, @type, @tags, @published_at, @created_at, @updated_at, @noindex, @publish_at, @fan_only, @nsfw, @language,
    225      @content_warning, @poll_json, @quote_uri, @quote_actor, @ap_visibility, @paid, @paid_min_cents, @view_count, 'import')`);
     228     @content_warning, @poll_json, @quote_uri, @quote_actor, @ap_visibility, @paid, @paid_min_cents, @view_count, @c2s_attachments, 'import')`);
    226229  const insReply = db.prepare(`INSERT OR IGNORE INTO ap_interactions
    227230    (kind, post_id, object_uri, actor_uri, actor_name, actor_handle, content, published, parent_uri, created_at)
     
    242245      const o = s.obj;
    243246      const opties = (Array.isArray(o.oneOf) ? o.oneOf : (Array.isArray(o.anyOf) ? o.anyOf : null));
     247      // De rollen uit het archief terug naar de kolommen. Zonder dit staat het
     248      // bestand er wel, maar komt de post zonder cover en zonder speler terug --
     249      // en dat zie je pas als je alle kolommen vergelijkt.
     250      const bijlagen = Array.isArray(o.attachment) ? o.attachment : [];
     251      const padVan = (a) => (a ? padVanOrigineel(a['shaer:originalUrl']) : null);
     252      const metRol = (r) => bijlagen.find((a) => a['shaer:role'] === r);
     253      const c2s = bijlagen.filter((a) => a['shaer:role'] === 'c2s').map((a) => {
     254        const poster = bijlagen.find((x) => x['shaer:role'] === 'poster' && x['shaer:posterFor'] === padVan(a));
     255        return {
     256          url: padVan(a), mediaType: a.mediaType, name: a.name || undefined,
     257          poster: poster ? padVan(poster) : undefined,
     258        };
     259      }).filter((a) => a.url);
    244260      insPost.run({
    245261        id: s.id, site_id: site.id, slug: o['shaer:slug'] || s.id, author_id: site.owner_id,
    246262        title: o.name || null, content: o.content || '', excerpt: o['shaer:excerpt'] || null,
    247263        status: o['shaer:status'] || 'draft',
    248         cover_image_url: null, cover_alt: o['shaer:coverAlt'] || null, cover_video_url: null,
     264        cover_image_url: padVan(metRol('cover')), cover_alt: o['shaer:coverAlt'] || null,
     265        cover_video_url: padVan(metRol('coverVideo')),
     266        c2s_attachments: c2s.length ? JSON.stringify(c2s) : null,
    249267        pinned: o['shaer:pinned'] ? 1 : 0, type: o['shaer:type'] || 'post',
    250268        tags: Array.isArray(o.tag) ? o.tag.filter((t) => t && t.type === 'Hashtag').map((t) => String(t.name).replace(/^#/, '')).join(', ') : null,
    251         published_at: sqlTijd(o.published), created_at: sqlTijd(o.published), updated_at: sqlTijd(o.updated || o.published),
    252         noindex: o['shaer:noindex'] ? 1 : 0, publish_at: sqlTijd(o['shaer:publishAt']),
     269        published_at: tijd(o.published), created_at: tijd(o.published), updated_at: tijd(o.updated || o.published),
     270        noindex: o['shaer:noindex'] ? 1 : 0, publish_at: tijd(o['shaer:publishAt']),
    253271        fan_only: o['shaer:fanOnly'] ? 1 : 0, nsfw: o.sensitive ? 1 : 0,
    254272        language: (o.contentMap && Object.keys(o.contentMap)[0]) || null,
Note: See TracChangeset for help on using the changeset viewer.