Changes in / [fbda20e:e9ec5e4] in Klonkt
- Files:
-
- 1 deleted
- 1 edited
-
src/services/ActivityPubService.js (modified) (11 diffs)
-
test/summary-not-a-warning.test.js (deleted)
Legend:
- Unmodified
- Added
- Removed
-
src/services/ActivityPubService.js
rfbda20e re9ec5e4 280 280 * Funkwhale hoeft te weten. 281 281 */ 282 /**283 * De waarschuwingstekst van een object, of niets.284 *285 * `summary` IS in AS2 een SAMENVATTING -- "a natural language summarization of286 * the object". Dat Mastodon dat veld hergebruikt als waarschuwing is Mastodons287 * conventie, en die zet er `sensitive` bij. Zonder `sensitive` is een summary288 * dus gewoon een samenvatting.289 *290 * WordPress + ActivityPub stuurt daar de EXCERPT van een artikel in, netjes291 * afgekapt voor Mastodon. Wij lazen dat als waarschuwing en verborgen de post292 * daarmee achter zijn eigen eerste alinea (Barts melding, 13-8:293 * europeanpirates.eu). Niemand krijgt dan te zien wat er staat, en de294 * waarschuwing waarschuwt nergens voor.295 */296 export function contentWarning(o) {297 if (!o || !o.sensitive) return null;298 const s = typeof o.summary === 'string' ? o.summary.trim() : '';299 return s || null;300 }301 302 282 export function timelineFields(o) { 303 283 // De hoes: een `image` op het object. Bij een Note alleen als terugval (daar … … 328 308 } 329 309 330 // Een ARTIKEL heeft een titel, en die is het eerste wat je wilt zien. Zonder 331 // dit kwam een WordPress-post binnen als kale body: de titel zit in `name` en 332 // die gooiden we weg, terwijl de excerpt in `summary` ten onrechte als 333 // waarschuwing dienstdeed. Nu allebei goed -- en dit is dezelfde greep die 334 // resolveRemoteNote al doet voor niet-Note-objecten, dus de tijdlijn en het 335 // antwoordpad zeggen eindelijk hetzelfde. 336 if (o.type && o.type !== 'Note' && typeof o.name === 'string' && o.name.trim()) { 337 const kop = `<p><strong>${HtmlSanitizerService.escape ? HtmlSanitizerService.escape(o.name) : o.name}</strong></p>`; 338 const atts = mediaFromNote(o); 339 const pagina = pickLink(o.url, (mt) => !mt || /html/i.test(mt)); 340 return { 341 html: HtmlSanitizerService.sanitize(kop + (o.content || '')), 342 atts, 343 url: pagina ? pagina.href : null, 344 }; 345 } 346 347 // Note / Question -- ongewijzigd gedrag. 310 // Note / Article / Question -- ongewijzigd gedrag. 348 311 const atts = (Array.isArray(o.attachment) ? o.attachment : []) 349 312 .map((a) => ({ url: safeUrl(a && a.url), type: (a && a.mediaType) || '' })) … … 2500 2463 // the timeline). 2501 2464 for (const s of subs) { 2502 tlStmts().ins.run(o.id, s.slug, actorUri, ai.name, ai.handle, ai.icon, ai.url, html, _url, o.published || null, media, o.sensitive ? 1 : 0, contentWarning(o));2465 tlStmts().ins.run(o.id, s.slug, actorUri, ai.name, ai.handle, ai.icon, ai.url, html, _url, o.published || null, media, o.sensitive ? 1 : 0, o.summary || null); 2503 2466 // FEP-633c ยง2.2: register the ward hint on the stored object (no action yet). 2504 2467 if (Guardianship.objectHasGuardians(o)) { try { db.prepare('UPDATE ap_timeline SET has_guardians = 1 WHERE id = ? AND slug = ?').run(o.id, s.slug); } catch { /* ignore */ } } … … 2652 2615 // post would keep linking to the old, now-dead URL. 2653 2616 const r = db.prepare('UPDATE ap_timeline SET content = ?, media_json = ?, nsfw = ?, cw = ?, url = COALESCE(?, url) WHERE id = ? AND author_uri = ?') 2654 .run(html, media, o.sensitive ? 1 : 0, contentWarning(o), o.url || null, o.id, claimedActor);2617 .run(html, media, o.sensitive ? 1 : 0, o.summary || null, o.url || null, o.id, claimedActor); 2655 2618 if (r.changes) console.log('[AP] timeline update', claimedActor, 'โ', o.id); 2656 2619 // A poll's Update carries the fresh vote counts / closed state. Refresh per-row so each … … 2716 2679 // have the note (e.g. we also follow the author), keep it and DON'T relabel it. 2717 2680 let inserted = false; 2718 try { const r = tlStmts().ins.run(bn.id, s.slug, origUri || '', oai.name, oai.handle, oai.icon, oai.url, html, bn.url || null, new Date().toISOString(), media, bn.sensitive ? 1 : 0, contentWarning(bn)); inserted = r.changes > 0; } catch { /* ignore */ }2681 try { const r = tlStmts().ins.run(bn.id, s.slug, origUri || '', oai.name, oai.handle, oai.icon, oai.url, html, bn.url || null, new Date().toISOString(), media, bn.sensitive ? 1 : 0, bn.summary || null); inserted = r.changes > 0; } catch { /* ignore */ } 2719 2682 if (inserted) { try { db.prepare('UPDATE ap_timeline SET reblog_name = ?, reblog_handle = ?, reblog_icon = ?, reblog_emoji_json = ? WHERE slug = ? AND id = ?').run(booster.name, booster.handle, booster.icon, (booster.emojis && Object.keys(booster.emojis).length) ? JSON.stringify(booster.emojis) : null, s.slug, bn.id); } catch { /* ignore */ } } 2720 2683 storeAuthorEmoji(bn.id, s.slug, oai); // custom-emoji display name for the byline … … 3879 3842 published: typeof o.published === 'string' ? o.published : undefined, 3880 3843 sensitive: !!o.sensitive, 3881 summary: (contentWarning(o) || '').slice(0, 500) ||undefined,3844 summary: typeof o.summary === 'string' ? o.summary.slice(0, 500) : undefined, 3882 3845 attachment: (() => { 3883 3846 const arr = Array.isArray(o.attachment) ? o.attachment : (o.attachment ? [o.attachment] : []); … … 3995 3958 content: HtmlSanitizerService.sanitize(rawHtml), // full, sanitized 3996 3959 sensitive: !!note.sensitive, // remote CW โ blur in the Cirkel 3997 cw: contentWarning(note)|| '',3960 cw: note.summary || '', 3998 3961 images, 3999 3962 // Full typed media (incl. video/mp4) for the timeline cache. `images` above is … … 5025 4988 // during a flux window, e.g. a fleet-wide update), and drops notes that are gone 5026 4989 // (404/410). Bump SELFHEAL_VERSION only on a release that warrants a re-sync. 5027 const SELFHEAL_VERSION = 2 2; // v22: summary is pas een waarschuwing MET sensitive, en een artikel houdt zijn titel4990 const SELFHEAL_VERSION = 21; // v21: drop direct notes (๐ help requests, waves) that were cached as timeline posts 5028 4991 async function fetchNoteAP(url) { 5029 4992 try { … … 5412 5375 const poll = parsePoll(o); // a Question (poll) โ carry its options/counts on backfill too 5413 5376 try { 5414 const r = tlStmts().ins.run(o.id, slug, actorUri, ai.name, ai.handle, ai.icon, ai.url, html, o.url || null, o.published || null, mediaFromNote(o), o.sensitive ? 1 : 0, contentWarning(o));5377 const r = tlStmts().ins.run(o.id, slug, actorUri, ai.name, ai.handle, ai.icon, ai.url, html, o.url || null, o.published || null, mediaFromNote(o), o.sensitive ? 1 : 0, o.summary || null); 5415 5378 if (r && r.changes > 0) added++; 5416 5379 // FEP-9098: keep custom-emoji tags from backfilled posts too. … … 5571 5534 if (note === 404) { db.prepare('DELETE FROM ap_timeline WHERE id = ?').run(r.id); healed++; continue; } 5572 5535 if (!note || typeof note !== 'object') { failed++; continue; } // origin unreachable right now 5573 // Door DEZELFDE bouwer als de innamekant (v22). Hij bouwde de inhoud 5574 // hier zelf op, en daardoor miste een gerepareerde rij precies wat de 5575 // inname wel doet -- de titel van een artikel bijvoorbeeld. Een 5576 // zelfherstel dat een andere vorm oplevert dan de inname repareert naar 5577 // een derde toestand. 5578 const velden = timelineFields(note); 5579 const html = velden.html; 5580 const media = velden.atts.length ? JSON.stringify(velden.atts) : mediaFromNote(note); 5536 const html = HtmlSanitizerService.sanitize(note.content || ''); 5537 const media = mediaFromNote(note); 5581 5538 const nsfw = note.sensitive ? 1 : 0; // re-sync NSFW/sensitive + CW onto already-cached posts 5582 const cw = contentWarning(note);5539 const cw = note.summary || null; 5583 5540 const url = note.url || null; // re-sync the human url (catches a remote slug rename) 5584 5541 const emoji = extractEmojiTags(note.tag); // FEP-9098: re-capture custom-emoji tags (v8) … … 6633 6590 getInteractions, getInteractionById, setInteractionBoosted, setInteractionLiked, buildReplyNote, getOutboxNote, getSentNotes, deliverReply, resolveRemoteNote, noteAudience, mayReadNote, 6634 6591 listOutbox, deliverOutboxDelete, deliverOutboxUpdate, deliverDirectNote, 6635 webfingerResolve, followActor, resolveRemoteActor, unfollowActor, handleMoveInbox, moveAccount, listFollowing, setAutoBoost, backfillFromOutbox, getTimeline, timelineRowsByIds, contentWarning,getDirectMessages, readMarkers, markRead, unreadPerConversation, messageRowsByUri, replyRowsByUri, conversationHeads, conversationHistory, isoStamp, timelineAttachments, timelineEmojis, timelineObjectLinks, timelineQuote, timelineEmbed, applyQuoteProps, deliverToActor, sendInteraction, voteOnPoll, voteOnRemotePoll,6592 webfingerResolve, followActor, resolveRemoteActor, unfollowActor, handleMoveInbox, moveAccount, listFollowing, setAutoBoost, backfillFromOutbox, getTimeline, timelineRowsByIds, getDirectMessages, readMarkers, markRead, unreadPerConversation, messageRowsByUri, replyRowsByUri, conversationHeads, conversationHistory, isoStamp, timelineAttachments, timelineEmojis, timelineObjectLinks, timelineQuote, timelineEmbed, applyQuoteProps, deliverToActor, sendInteraction, voteOnPoll, voteOnRemotePoll, 6636 6593 acceptGatedFollow, rejectGatedFollow, isWardGuardian, outboxAudience, sendFollowDecision, 6637 6594 gateOutgoingFollow, performApprovedFollow, recordGuardianEvent, listGuardianEvents, GUARDIAN_EVENT_KEEP,
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)