Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/services/ActivityPubService.js

    r09fc5fb raae5881  
    41914191}
    41924192
    4193 // ── Gesprekken: eerst wie, dan pas wat (shaer-frontend-yso) ──────────
    4194 //
    4195 // De oude lezing gaf de nieuwste 60 berichten over ALLE gesprekken samen. Dat
    4196 // knipt geschiedenis weg zonder dat iemand het merkt, en het is bij DM's veel
    4197 // erger dan bij posts: dat zijn er meer en het zijn kortere berichten, dus een
    4198 // druk gesprek kan de 60 in zijn eentje opeten en de rest uit de lezing duwen.
    4199 // Viel het laatste bericht van iemand erbuiten, dan verdween die persoon
    4200 // helemaal uit Messages -- de avatarhemel plaatst mensen op de leeftijd van hun
    4201 // laatste bericht, dus geen bericht is geen gezicht.
    4202 //
    4203 // Vandaar twee lezingen. Deze geeft EEN rij per tegenpartij, hoe druk iemand
    4204 // ook is, en conversationHistory hieronder geeft het gesprek zelf met een
    4205 // cursor. Wat de client van de hemel nodig heeft -- wie, wanneer, en waarmee --
    4206 // zit in die ene nieuwste note.
    4207 //
    4208 // Een gesprek is hier hetzelfde als in de app: incoming zijn de ap_mentions
    4209 // (die tabel IS de aan ons gerichte post), uitgaand zijn de eigen notes met
    4210 // visibility 'direct'. Een publiek antwoord is geen gesprek en hoort niet als
    4211 // gezicht in de hemel.
    4212 const GESPREK_UNIE = `
    4213   SELECT m.actor_uri AS other, COALESCE(m.published, m.created_at) AS stamp,
    4214          'in' AS richting, m.object_uri AS ref
    4215     FROM ap_mentions m
    4216    WHERE m.slug = @slug AND m.actor_uri IS NOT NULL AND m.actor_uri <> ''
    4217   UNION ALL
    4218   SELECT j.value AS other, o.created_at AS stamp,
    4219          'uit' AS richting, o.id AS ref
    4220     FROM ap_outbox o
    4221     JOIN json_each(COALESCE(NULLIF(o.to_actors, ''), json_array(o.to_actor))) j
    4222    WHERE o.site_slug = @slug AND o.visibility = 'direct'
    4223      AND j.value IS NOT NULL AND j.value <> ''`;
    4224 
    4225 /**
    4226  * Een rij per tegenpartij: zijn nieuwste bericht, nieuwste gesprek eerst.
    4227  *
    4228  * Compleet van vorm -- het aantal rijen is het aantal mensen, niet het aantal
    4229  * berichten -- dus de hemel kan niemand meer kwijtraken doordat een ander druk
    4230  * was. Zonder limiet, en dat mag: dit schaalt met je kring.
    4231  */
    4232 export function conversationHeads(slug) {
    4233   try {
    4234     return db.prepare(`
    4235       SELECT other, stamp, richting, ref FROM (
    4236         SELECT *, ROW_NUMBER() OVER (PARTITION BY other ORDER BY stamp DESC, ref DESC) AS rn
    4237           FROM (${GESPREK_UNIE})
    4238       ) WHERE rn = 1
    4239       ORDER BY stamp DESC, ref DESC`).all({ slug });
    4240   } catch { return []; }
    4241 }
    4242 
    4243 /**
    4244  * Een gesprek, nieuwste eerst, met een cursor.
    4245  *
    4246  * BEIDE KANTEN ONDER EEN LIMIET. In de oude lezing werden jouw kant
    4247  * (getSentNotes) en hun kant apart afgekapt, waardoor een gesprek eenzijdig
    4248  * kon lijken -- alsof iemand nooit geantwoord had. Hier is de limiet er een
    4249  * voor het gesprek als geheel.
    4250  *
    4251  * `before` is de cursor van het OUDSTE bericht dat je al hebt; je krijgt wat
    4252  * daarvoor ligt. Er komt er een extra op om te weten of er nog meer is: de
    4253  * client hoort dat te weten zonder te moeten gokken, en zonder dat weten kan
    4254  * 'load more' niet eerlijk verschijnen.
    4255  *
    4256  * DE CURSOR IS SAMENGESTELD -- '<stempel>|<ref>' -- en niet alleen de stempel.
    4257  * Twee berichten in dezelfde seconde is bij DM's geen randgeval maar een
    4258  * gesprek, en met 'stamp < before' zou alles wat die grensseconde deelt stil
    4259  * overgeslagen worden. Je zou het niet merken: de pagina komt gewoon, er
    4260  * ontbreekt alleen iets in het midden.
    4261  */
    4262 const cursorVan = (r) => (r ? `${r.stamp}|${r.ref}` : null);
    4263 
    4264 export function conversationHistory(slug, other, { before = null, limit = 60 } = {}) {
    4265   try {
    4266     const n = Math.min(Math.max(parseInt(limit, 10) || 60, 1), 200);
    4267     const knip = String(before || '').indexOf('|');
    4268     const bStamp = before && knip > 0 ? String(before).slice(0, knip) : null;
    4269     const bRef = before && knip > 0 ? String(before).slice(knip + 1) : null;
    4270     const rijen = db.prepare(`
    4271       SELECT other, stamp, richting, ref FROM (${GESPREK_UNIE})
    4272        WHERE other = @other
    4273          AND (@bStamp IS NULL OR stamp < @bStamp OR (stamp = @bStamp AND ref < @bRef))
    4274        ORDER BY stamp DESC, ref DESC LIMIT @n`).all({ slug, other, bStamp, bRef, n: n + 1 });
    4275     const meer = rijen.length > n;
    4276     const uit = meer ? rijen.slice(0, n) : rijen;
    4277     return { rijen: uit, meer, oudste: cursorVan(uit[uit.length - 1]) };
    4278   } catch { return { rijen: [], meer: false, oudste: null }; }
    4279 }
    4280 
    4281 // De kolommen die een bericht tot kaart maken. Een constante, want de
    4282 // gesprekslezing haalt dezelfde rijen op: twee lijsten die uiteenlopen leveren
    4283 // een kaart die op de ene plek een plaatje heeft en op de andere niet.
    4284 const BERICHT_KOLOMMEN = `
    4285       m.object_uri, m.note_url, m.actor_uri, m.actor_name, m.actor_handle, m.actor_icon, m.actor_url,
    4286       m.content, m.published, m.created_at, m.wave, m.help_request,
    4287       m.emoji_json, m.actor_emoji_json, m.media_json, m.quote_json, m.embed_json`;
    4288 
    4289 /** Dezelfde berichtrijen, maar op object-uri -- voor een gesprek. */
    4290 export function messageRowsByUri(slug, uris) {
    4291   const lijst = (uris || []).filter((u) => typeof u === 'string' && u);
    4292   if (!lijst.length) return [];
    4293   try {
    4294     const gaten = lijst.map(() => '?').join(',');
    4295     return db.prepare(`SELECT ${BERICHT_KOLOMMEN} FROM ap_mentions m
    4296                         WHERE m.slug = ? AND m.object_uri IN (${gaten})`).all(slug, ...lijst);
    4297   } catch { return []; }
    4298 }
    4299 
    43004193export function getDirectMessages(slug, limit) {
    43014194  try {
    43024195    return db.prepare(`
    4303       SELECT ${BERICHT_KOLOMMEN}
     4196      SELECT m.object_uri, m.note_url, m.actor_uri, m.actor_name, m.actor_handle, m.actor_icon, m.actor_url,
     4197             m.content, m.published, m.created_at, m.wave, m.help_request,
     4198             m.emoji_json, m.actor_emoji_json, m.media_json, m.quote_json, m.embed_json
    43044199      FROM ap_mentions m
    43054200      WHERE m.slug = ?
     
    63916286  getInteractions, getInteractionById, setInteractionBoosted, setInteractionLiked, buildReplyNote, getOutboxNote, getSentNotes, deliverReply, resolveRemoteNote, noteAudience, mayReadNote,
    63926287  listOutbox, deliverOutboxDelete, deliverOutboxUpdate, deliverDirectNote,
    6393   webfingerResolve, followActor, resolveRemoteActor, unfollowActor, handleMoveInbox, moveAccount, listFollowing, setAutoBoost, backfillFromOutbox, getTimeline, getDirectMessages, messageRowsByUri, conversationHeads, conversationHistory, isoStamp, timelineAttachments, timelineEmojis, timelineObjectLinks, timelineQuote, timelineEmbed, applyQuoteProps, deliverToActor, sendInteraction, voteOnPoll, voteOnRemotePoll,
     6288  webfingerResolve, followActor, resolveRemoteActor, unfollowActor, handleMoveInbox, moveAccount, listFollowing, setAutoBoost, backfillFromOutbox, getTimeline, getDirectMessages, isoStamp, timelineAttachments, timelineEmojis, timelineObjectLinks, timelineQuote, timelineEmbed, applyQuoteProps, deliverToActor, sendInteraction, voteOnPoll, voteOnRemotePoll,
    63946289  acceptGatedFollow, rejectGatedFollow, isWardGuardian, outboxAudience, sendFollowDecision,
    63956290  gateOutgoingFollow, performApprovedFollow, recordGuardianEvent, listGuardianEvents, GUARDIAN_EVENT_KEEP,
Note: See TracChangeset for help on using the changeset viewer.