Changeset cc3cf7d in Klonkt for src/services
- Timestamp:
- 07/26/2026 08:08:15 AM (6 weeks ago)
- Branches:
- main
- Children:
- 6fd0e20
- Parents:
- eb36688
- File:
-
- 1 edited
-
src/services/ActivityPubService.js (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/services/ActivityPubService.js
reb36688 rcc3cf7d 1539 1539 // FEP-9098: keep the note's custom-emoji tags so the C2S inbox read can serve them. 1540 1540 { const ej = extractEmojiTags(o.tag); if (ej) { try { db.prepare('UPDATE ap_timeline SET emoji_json = ? WHERE id = ? AND slug = ?').run(ej, o.id, s.slug); } catch { /* ignore */ } } } 1541 // FEP-e232 : keep the note's object-link (quote/ref)tags for the same read.1542 { const lj = extract ObjectLinkTags(o.tag); if (lj) { try { db.prepare('UPDATE ap_timeline SET link_json = ? WHERE id = ? AND slug = ?').run(lj, o.id, s.slug); } catch { /* ignore */ } } }1541 // FEP-e232 + FEP-044f: keep the note's object-link/quote tags for the same read. 1542 { const lj = extractLinkJson(o); if (lj) { try { db.prepare('UPDATE ap_timeline SET link_json = ? WHERE id = ? AND slug = ?').run(lj, o.id, s.slug); } catch { /* ignore */ } } } 1543 1543 if (poll) { try { db.prepare('UPDATE ap_timeline SET poll_json = ? WHERE id = ? AND slug = ?').run(JSON.stringify(poll), o.id, s.slug); } catch { /* ignore */ } } 1544 1544 } … … 2605 2605 } 2606 2606 2607 // FEP-044f quote posts: a quote is usually NOT an FEP-e232 tag but an 2608 // object-level property. FEP-044f §"how to recognise" lists them all: 2609 // `quote` (the FEP property, a string or an embedded Link/object), and the 2610 // de-facto `quoteUrl` (as:), `quoteUri` (fedibird), `_misskey_quote` (misskey). 2611 // This returns the quoted object's URL from whichever is present. 2612 export function extractQuoteUrl(note) { 2613 if (!note || typeof note !== 'object') return null; 2614 const q = note.quote ?? note.quoteUrl ?? note.quoteUri ?? note['_misskey_quote']; 2615 if (!q) return null; 2616 if (typeof q === 'string') return q || null; 2617 if (typeof q === 'object') return (typeof q.id === 'string' && q.id) || (typeof q.href === 'string' && q.href) || null; 2618 return null; 2619 } 2620 2621 // The note's object-link tags for storage: real FEP-e232 Link tags PLUS any 2622 // FEP-044f object-level quote, normalised to one FEP-e232-shaped Link (rel 2623 // _misskey_quote) so the client's single object-link path renders them all. 2624 // Deduped by href. Returns the JSON to store (or null if the note has neither). 2625 export function extractLinkJson(note) { 2626 const links = []; 2627 const fromTag = extractObjectLinkTags(note && note.tag); 2628 if (fromTag) { try { links.push(...JSON.parse(fromTag)); } catch { /* ignore */ } } 2629 const qUrl = extractQuoteUrl(note); 2630 if (qUrl && !links.some((l) => l && l.href === qUrl)) { 2631 links.push({ type: 'Link', mediaType: 'application/activity+json', href: qUrl, 2632 rel: ['https://misskey-hub.net/ns#_misskey_quote'], name: qUrl }); 2633 } 2634 return links.length ? JSON.stringify(links) : null; 2635 } 2636 2607 2637 // ── Cirkel = posts from the accounts you auto-boost ("feature an artist") ── 2608 2638 let _abCount, _cirkelPosts, _cirkelMembers; … … 2701 2731 // during a flux window, e.g. a fleet-wide update), and drops notes that are gone 2702 2732 // (404/410). Bump SELFHEAL_VERSION only on a release that warrants a re-sync. 2703 const SELFHEAL_VERSION = 9; // v9: also re-capture FEP-e232 object-link tags (link_json) onto already-cached posts2733 const SELFHEAL_VERSION = 10; // v10: also capture FEP-044f object-level quotes (quote/quoteUrl/quoteUri/_misskey_quote) into link_json 2704 2734 async function fetchNoteAP(url) { 2705 2735 try { … … 2762 2792 // FEP-9098: keep custom-emoji tags from backfilled posts too. 2763 2793 { const ej = extractEmojiTags(o.tag); if (ej) { try { db.prepare('UPDATE ap_timeline SET emoji_json = ? WHERE id = ? AND slug = ?').run(ej, o.id, slug); } catch { /* ignore */ } } } 2764 // FEP-e232 : keep object-link (quote/ref)tags from backfilled posts too.2765 { const lj = extract ObjectLinkTags(o.tag); if (lj) { try { db.prepare('UPDATE ap_timeline SET link_json = ? WHERE id = ? AND slug = ?').run(lj, o.id, slug); } catch { /* ignore */ } } }2794 // FEP-e232 + FEP-044f: keep object-link/quote tags from backfilled posts too. 2795 { const lj = extractLinkJson(o); if (lj) { try { db.prepare('UPDATE ap_timeline SET link_json = ? WHERE id = ? AND slug = ?').run(lj, o.id, slug); } catch { /* ignore */ } } } 2766 2796 // Set poll_json if this is a poll and we don't already have it (COALESCE preserves a vote). 2767 2797 if (poll) { try { db.prepare('UPDATE ap_timeline SET poll_json = COALESCE(poll_json, ?) WHERE id = ? AND slug = ?').run(JSON.stringify(poll), o.id, slug); } catch { /* ignore */ } } … … 2897 2927 const url = note.url || null; // re-sync the human url (catches a remote slug rename) 2898 2928 const emoji = extractEmojiTags(note.tag); // FEP-9098: re-capture custom-emoji tags (v8) 2899 const link = extract ObjectLinkTags(note.tag); // FEP-e232: re-capture object-linktags (v9)2929 const link = extractLinkJson(note); // FEP-e232 + FEP-044f: re-capture object-link/quote tags (v9) 2900 2930 if ((html && html !== r.content) || media !== (r.media_json || '[]') || nsfw !== (r.nsfw || 0) || (cw || '') !== (r.cw || '') || (url && url !== r.url) || (emoji || '') !== (r.emoji_json || '') || (link || '') !== (r.link_json || '')) { 2901 2931 db.prepare('UPDATE ap_timeline SET content = ?, media_json = ?, nsfw = ?, cw = ?, url = COALESCE(?, url), emoji_json = ?, link_json = ? WHERE id = ?').run(html || r.content, media, nsfw, cw, url, emoji, link, r.id);
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)