| 1 | /**
|
|---|
| 2 | * Zachte groepen (shaer-mbji): een gesprek is de SET deelnemers, niet één
|
|---|
| 3 | * tegenpartij.
|
|---|
| 4 | *
|
|---|
| 5 | * Een direct bericht aan Anna en Ben bestond al als groep op de draad --
|
|---|
| 6 | * ap_outbox.to_actors droeg de hele set -- maar elke lezing hier sleutelde op
|
|---|
| 7 | * één `other`. Een uitgaand bericht aan twee mensen viel daardoor in twee
|
|---|
| 8 | * gesprekken uiteen, en een binnenkomend bericht van Anna aan jou en Ben kwam
|
|---|
| 9 | * alleen bij Anna terecht: Ben viel eruit. Een gesprek met drie mensen bestond
|
|---|
| 10 | * zo alleen als losse één-op-één-bubbels die elk een deel ervan droegen.
|
|---|
| 11 | *
|
|---|
| 12 | * DE SLEUTEL:
|
|---|
| 13 | *
|
|---|
| 14 | * één ander -> zijn actor-URI, kaal. Precies wat het altijd was, dus elk
|
|---|
| 15 | * bestaand gesprek, elke leesmarkering en elke ?with=-URL
|
|---|
| 16 | * blijft geldig. Niets te migreren.
|
|---|
| 17 | * meer -> de URI's gesorteerd, gescheiden door één spatie. Een URI kan
|
|---|
| 18 | * geen ongecodeerde spatie bevatten, dus de scheiding is
|
|---|
| 19 | * ondubbelzinnig, en sorteren maakt {Anna, Ben} en {Ben, Anna}
|
|---|
| 20 | * hetzelfde gesprek.
|
|---|
| 21 | *
|
|---|
| 22 | * Ikzelf zit nooit in de sleutel: ik ben in elk gesprek, dus mij noemen zegt
|
|---|
| 23 | * niets en zou dezelfde groep twee sleutels geven, afhankelijk van wie hem
|
|---|
| 24 | * begon.
|
|---|
| 25 | *
|
|---|
| 26 | * ZACHT BETEKENT: WIE GEADRESSEERD IS, ZIT ERIN. Geen aanmaakstap, geen
|
|---|
| 27 | * eigenaar. Komt Carla er halverwege bij, dan is {Anna, Ben, Carla} een ander
|
|---|
| 28 | * gesprek dan {Anna, Ben} -- en dat klopt, want een antwoord daar bereikt
|
|---|
| 29 | * Carla en een antwoord in de oude bubbel niet. `context` (FEP-7888) reist mee
|
|---|
| 30 | * en wordt bewaard, maar voegt hier geen bubbels samen: een bubbel die Carla
|
|---|
| 31 | * toont terwijl je antwoord haar niet bereikt, zou liegen over wie meeleest.
|
|---|
| 32 | *
|
|---|
| 33 | * Puur, zonder afhankelijkheden: de inbox, de bezorging en de lezing gebruiken
|
|---|
| 34 | * allemaal dezelfde sleutel, en dat kan alleen als hij op één plek staat.
|
|---|
| 35 | */
|
|---|
| 36 |
|
|---|
| 37 | const PUBLIC = new Set([
|
|---|
| 38 | 'https://www.w3.org/ns/activitystreams#Public',
|
|---|
| 39 | 'as:Public',
|
|---|
| 40 | 'Public',
|
|---|
| 41 | ]);
|
|---|
| 42 |
|
|---|
| 43 | /** Is dit een persoon, en niet een publiek of een volgerslijst? */
|
|---|
| 44 | export function isPersonalAddress(uri) {
|
|---|
| 45 | if (typeof uri !== 'string' || !/^https?:\/\//i.test(uri)) return false;
|
|---|
| 46 | if (PUBLIC.has(uri)) return false;
|
|---|
| 47 | return !/\/followers\/?$/.test(uri);
|
|---|
| 48 | }
|
|---|
| 49 |
|
|---|
| 50 | const lijst = (v) => (Array.isArray(v) ? v : (v ? [v] : []))
|
|---|
| 51 | .map((x) => (typeof x === 'string' ? x : (x && typeof x === 'object' ? x.id : null)))
|
|---|
| 52 | .filter((x) => typeof x === 'string');
|
|---|
| 53 |
|
|---|
| 54 | /**
|
|---|
| 55 | * De andere deelnemers van een binnenkomende note: de afzender plus iedere
|
|---|
| 56 | * persoon in to/cc, zonder mij. Gesorteerd en ontdubbeld.
|
|---|
| 57 | */
|
|---|
| 58 | export function participantsOf(note, author, me) {
|
|---|
| 59 | const set = new Set();
|
|---|
| 60 | if (isPersonalAddress(author)) set.add(author);
|
|---|
| 61 | for (const u of [...lijst(note && note.to), ...lijst(note && note.cc)]) {
|
|---|
| 62 | if (isPersonalAddress(u)) set.add(u);
|
|---|
| 63 | }
|
|---|
| 64 | set.delete(me);
|
|---|
| 65 | return [...set].sort();
|
|---|
| 66 | }
|
|---|
| 67 |
|
|---|
| 68 | /** De gesprekssleutel van een set andere deelnemers. */
|
|---|
| 69 | export function conversationKey(others) {
|
|---|
| 70 | const set = [...new Set((others || []).filter(isPersonalAddress))].sort();
|
|---|
| 71 | return set.join(' ');
|
|---|
| 72 | }
|
|---|
| 73 |
|
|---|
| 74 | /** De deelnemers achter een sleutel. Een kale URI is een gesprek met één. */
|
|---|
| 75 | export function participantsOfKey(key) {
|
|---|
| 76 | return String(key || '').split(' ').filter(isPersonalAddress);
|
|---|
| 77 | }
|
|---|
| 78 |
|
|---|
| 79 | /** Een groep: meer dan één ander. */
|
|---|
| 80 | export function isGroupKey(key) {
|
|---|
| 81 | return participantsOfKey(key).length > 1;
|
|---|
| 82 | }
|
|---|
| 83 |
|
|---|
| 84 | /** De context van een note (FEP-7888): een string of een object met een id. */
|
|---|
| 85 | export function contextOf(note) {
|
|---|
| 86 | const c = note && note.context;
|
|---|
| 87 | const id = typeof c === 'string' ? c : (c && typeof c === 'object' ? c.id : null);
|
|---|
| 88 | return typeof id === 'string' && /^https?:\/\//i.test(id) ? id : null;
|
|---|
| 89 | }
|
|---|