| 1 | /**
|
|---|
| 2 | * Deze Klonkt biedt zich aan als guardian bij een reeks wards (FEP-633c 3.1).
|
|---|
| 3 | *
|
|---|
| 4 | * Bedoeld voor de caseload-test: honderd kinderen, een guardian. Draait tegen de
|
|---|
| 5 | * database van de instance zelf, zoals de andere scripts hier -- geen OAuth, geen
|
|---|
| 6 | * tweede weg. Wat het doet is precies wat de PWA-knop doet, honderd keer.
|
|---|
| 7 | *
|
|---|
| 8 | * DATABASE_PATH=... PUBLIC_BASE_URL=... node offer-many.mjs \
|
|---|
| 9 | * --slug dev --base https://wards.klonkt.com --from 1 --to 100
|
|---|
| 10 | *
|
|---|
| 11 | * ECHTE FEDERATIE, geen kortsluiting: de wards wonen op een andere origin, dus
|
|---|
| 12 | * elk aanbod gaat over de lijn en wordt daar ondertekend beantwoord. Dat is het
|
|---|
| 13 | * hele punt -- een test die de co-locatieroute neemt meet iets anders dan wat er
|
|---|
| 14 | * in productie gebeurt.
|
|---|
| 15 | *
|
|---|
| 16 | * VEILIG OM OPNIEUW TE DRAAIEN: een ward die al gecommit is wordt overgeslagen,
|
|---|
| 17 | * en een aanbod dat al openstaat wordt niet nog eens gestuurd. Zonder dat maakt
|
|---|
| 18 | * een tweede run honderd dubbele aanbiedingen bij mensen die al ja zeiden.
|
|---|
| 19 | */
|
|---|
| 20 |
|
|---|
| 21 | const args = Object.fromEntries(
|
|---|
| 22 | process.argv.slice(2).join(' ').split('--').filter(Boolean)
|
|---|
| 23 | .map((s) => s.trim().split(/\s+/)).map(([k, ...v]) => [k, v.join(' ') || true]),
|
|---|
| 24 | );
|
|---|
| 25 |
|
|---|
| 26 | const slug = args.slug || 'dev';
|
|---|
| 27 | const farmBase = (args.base || 'https://wards.klonkt.com').replace(/\/+$/, '');
|
|---|
| 28 | const van = Number(args.from || 1);
|
|---|
| 29 | const tot = Number(args.to || 100);
|
|---|
| 30 | const pauze = Number(args.pauze || 150);
|
|---|
| 31 |
|
|---|
| 32 | const AP = await import('../../src/services/ActivityPubService.js');
|
|---|
| 33 | const Guardianship = await import('../../src/services/guardianship/index.js');
|
|---|
| 34 | const dbMod = await import('../../src/config/database.js');
|
|---|
| 35 | const db = dbMod.default;
|
|---|
| 36 |
|
|---|
| 37 | const site = db.prepare('SELECT * FROM sites WHERE slug = ?').get(slug);
|
|---|
| 38 | if (!site) { console.error(`geen site met slug "${slug}"`); process.exit(1); }
|
|---|
| 39 |
|
|---|
| 40 | const base = (process.env.PUBLIC_BASE_URL || '').replace(/\/+$/, '');
|
|---|
| 41 | const me = AP.actorId(base, site.slug);
|
|---|
| 42 | console.log(`[offer] ${me} biedt zich aan bij w${String(van).padStart(3, '0')}..w${String(tot).padStart(3, '0')} op ${farmBase}`);
|
|---|
| 43 |
|
|---|
| 44 | const alBekend = new Set(Guardianship.listWards(site.slug).map((w) => w.other_uri));
|
|---|
| 45 | let gestuurd = 0, overgeslagen = 0, mislukt = 0;
|
|---|
| 46 |
|
|---|
| 47 | for (let i = van; i <= tot; i++) {
|
|---|
| 48 | const naam = `w${String(i).padStart(3, '0')}`;
|
|---|
| 49 | const ward = `${farmBase}/u/${naam}`;
|
|---|
| 50 | if (alBekend.has(ward)) { overgeslagen++; continue; }
|
|---|
| 51 |
|
|---|
| 52 | // Precies de vorm die handleOutbox verwacht: een Offer van een
|
|---|
| 53 | // Relationship{subject: ward, object: ik}. Door hem via de outbox te sturen
|
|---|
| 54 | // loopt dit langs dezelfde code als de knop in de PWA -- er is geen tweede pad
|
|---|
| 55 | // naar hetzelfde besluit, en dat is de les van vandaag.
|
|---|
| 56 | const activity = {
|
|---|
| 57 | type: 'Offer',
|
|---|
| 58 | to: [ward],
|
|---|
| 59 | object: {
|
|---|
| 60 | type: 'Relationship',
|
|---|
| 61 | subject: ward,
|
|---|
| 62 | object: me,
|
|---|
| 63 | relationship: 'https://shaer.klonkt.com/ns#guardian',
|
|---|
| 64 | },
|
|---|
| 65 | };
|
|---|
| 66 |
|
|---|
| 67 | try {
|
|---|
| 68 | const uit = await AP.ingestOutboxActivity(site, { id: site.owner_id, username: slug }, activity);
|
|---|
| 69 | if (uit && (uit.status === 201 || uit.status === 200)) gestuurd++;
|
|---|
| 70 | else { mislukt++; console.warn(` ${naam}: ${uit && uit.status} ${uit && uit.error}`); }
|
|---|
| 71 | } catch (e) {
|
|---|
| 72 | mislukt++;
|
|---|
| 73 | console.warn(` ${naam}: ${e.message}`);
|
|---|
| 74 | }
|
|---|
| 75 | // Een adempauze. Honderd handshakes tegelijk zegt meer over de bezorgwachtrij
|
|---|
| 76 | // dan over het paneel, en dit script is er om het paneel te kunnen bekijken.
|
|---|
| 77 | if (pauze) await new Promise((r) => setTimeout(r, pauze));
|
|---|
| 78 | }
|
|---|
| 79 |
|
|---|
| 80 | console.log(`[offer] verstuurd ${gestuurd}, overgeslagen ${overgeslagen}, mislukt ${mislukt}`);
|
|---|
| 81 | console.log('[offer] de commit valt pas als elke ward heeft geaccepteerd; kijk over een minuut met listWards.');
|
|---|
| 82 | process.exit(0);
|
|---|