Changeset 0db3c72 in Klonkt for src/services/ActivityPubService.js
- Timestamp:
- 08/10/2026 06:54:54 AM (4 weeks ago)
- Branches:
- main
- Children:
- 75f2897
- Parents:
- 7e53594
- File:
-
- 1 edited
-
src/services/ActivityPubService.js (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/services/ActivityPubService.js
r7e53594 r0db3c72 4808 4808 4809 4809 /** The stored external-embed card, for the C2S read. */ 4810 // ── Standaardvormen in plaats van eigen dialect (shaer-nmw) ─────── 4811 // 4812 // Robins waarschuwing: geen Klonkt/Shaer-dialect schrijven waar AS2 of een FEP 4813 // het al regelt. Vier eigen properties hadden een standaard naast zich staan, 4814 // en deze helpers zijn die standaard -- een definitie per vorm, zodat de tien 4815 // plekken die ze emitten niet elk hun eigen variant krijgen. 4816 // 4817 // De oude shaer:-velden blijven er voorlopig NAAST staan. Een app in het veld 4818 // leest ze nog, en een leeg scherm is een duurdere fout dan een dubbel veld; 4819 // ze gaan eruit als de clients om zijn (tweede helft van shaer-nmw). 4820 4821 /** FEP-9098 Emoji-tags uit een {shortcode: url}-kaart. */ 4822 function emojiTagsFromMap(emojis) { 4823 const uit = Object.entries(emojis || {}) 4824 .filter(([naam, url]) => naam && url) 4825 .map(([naam, url]) => ({ type: 'Emoji', name: naam, icon: { type: 'Image', url } })); 4826 return uit.length ? uit : undefined; 4827 } 4828 4829 /** 4830 * Een actor als INGESLOTEN OBJECT voor `attributedTo` / `actor`. 4831 * 4832 * AS2 staat toe dat attributedTo een object is in plaats van een URI, en dan 4833 * heeft ELKE client er wat aan -- niet alleen de onze, die er shaer:author 4834 * naast kreeg. `preferredUsername` is de lokale naam; een lezer leidt de handle 4835 * af uit die naam plus de host van de id, precies zoals wij serverkant ook 4836 * doen. Weten we niets van de persoon, dan blijft het de kale URI: een leeg 4837 * object zou beweren dat we hem kennen. 4838 */ 4839 export function actorObject(uri, info) { 4840 if (!uri) return undefined; 4841 const iets = info && (info.name || info.handle || info.icon || info.url); 4842 if (!iets) return uri; 4843 const o = { id: uri, type: 'Person' }; 4844 if (info.name) o.name = info.name; 4845 const lokaal = String(info.handle || '').replace(/^@/, '').split('@')[0]; 4846 if (lokaal) o.preferredUsername = lokaal; 4847 if (info.icon) o.icon = { type: 'Image', url: info.icon }; 4848 if (info.url) o.url = info.url; 4849 const tags = emojiTagsFromMap(info.emojis); 4850 if (tags) o.tag = tags; 4851 return o; 4852 } 4853 4854 /** 4855 * De linkkaart als AS2 `preview` (core: "identifies an entity that provides a 4856 * preview of this object"). Een Page met url, name en image IS een kaart; daar 4857 * hoefde shaer:embed nooit voor te bestaan. 4858 * 4859 * Wat WEL van ons blijft is de spelerpagina: dat die alleen meegaat als de 4860 * guardians de poort openden is FEP-633c-gedrag en heeft geen AS2-tegenhanger. 4861 */ 4862 export function previewObject(embedJson, { playback = false } = {}) { 4863 const e = timelineEmbed(embedJson, { playback }); 4864 if (!e) return undefined; 4865 const thumb = (e.media || []).find((m) => m && m.url); 4866 const p = { type: 'Page', url: e.url }; 4867 if (e.title) p.name = e.title; 4868 if (thumb) p.image = { type: 'Image', url: thumb.url }; 4869 if (e.author && (e.author.name || e.author.handle)) { 4870 p.attributedTo = { type: 'Person', name: e.author.name || e.author.handle }; 4871 } 4872 if (e['shaer:playerUrl']) p['shaer:playerUrl'] = e['shaer:playerUrl']; 4873 if (e['shaer:playable']) p['shaer:playable'] = e['shaer:playable']; 4874 return p; 4875 } 4876 4877 /** 4878 * De geciteerde post als OBJECT in `quote` (FEP-044f staat toe dat quote het 4879 * object zelf is, niet alleen een URI). De opgeslagen momentopname wordt hier 4880 * een echte Note, met de auteur als ingesloten actor -- dus geen tweede eigen 4881 * property voor iets dat de FEP al kan. 4882 */ 4883 export function quoteObject(quoteJson) { 4884 const q = timelineQuote(quoteJson); 4885 if (!q) return undefined; 4886 const note = { type: 'Note', id: q.url, url: q.url }; 4887 if (q.content) note.content = q.content; 4888 if (q.published) note.published = q.published; 4889 if (q.author) { 4890 note.attributedTo = actorObject(q.author.url || q.url, { 4891 name: q.author.name, handle: q.author.handle, icon: q.author.icon, 4892 }); 4893 } 4894 const media = (q.media || []).filter((m) => m && m.url) 4895 .map((m) => ({ type: 'Document', mediaType: m.type || undefined, url: m.url })); 4896 if (media.length) note.attachment = media; 4897 const tags = emojiTagsFromMap(q.emojis); 4898 if (tags) note.tag = tags; 4899 return note; 4900 } 4901 4810 4902 export function timelineEmbed(embedJson, { playback = false } = {}) { 4811 4903 try { … … 6188 6280 getNotifications, listBlocks, isBlockedAny, blockTarget, unblock, 6189 6281 deliverWithRetry, enqueueDelivery, processDeliveryQueue, startDeliveryWorker, 6190 sendMaybe304, etagFor, onGuardian, wakeGuardian, onGuardianshipEvent, proposeGate, getReplyUris, getThread, filterThreadToCircle, gateAttachments, stripEmojiTags, markNotificationsSeen, countUnseenNotifications, hasPlayableAudio,6282 sendMaybe304, etagFor, onGuardian, wakeGuardian, onGuardianshipEvent, proposeGate, getReplyUris, getThread, filterThreadToCircle, gateAttachments, stripEmojiTags, actorObject, previewObject, quoteObject, markNotificationsSeen, countUnseenNotifications, hasPlayableAudio, 6191 6283 linkifyBody, bakePostContent, bakePostContentWithMentions, listFollowers, removeFollower, listConnections, 6192 6284 noteVisibility, belongsInTimeline, playerUrlFor, isRejectedObject, rejectInteraction, interactionReportTarget,
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)