source: Klonkt/scripts/migrate-circles.mjs@ cbe4f4e

main
Last change on this file since cbe4f4e was 355364c, checked in by Robin Genis <roboburr@…>, 2 months ago

fix(cirkel): migrate ALL circle links, not just status='active'

Old pull-protocol health statuses ('error'/'outdated') are irrelevant now: a
peer that removed /.klonkt/* shows as 'error' but still has a working AP actor.
The active-only filter dropped such links (e.g. sound-fabrics: 5 links -> only 2
migrated). Migrate every non-removed link; bump the run flag to v2 so instances
re-migrate and pick up the previously-skipped ones.

Co-Authored-By: Claude <noreply@…>

  • Property mode set to 100644
File size: 1.8 KB
Line 
1// One-time migration: convert the old Cirkels (pull-protocol circle_links) into
2// ActivityPub follows with auto-boost ("feature an artist"). Run per instance:
3// cd ~/apps/<instance> && node scripts/migrate-circles.mjs
4// Idempotent: followActor upserts ap_following, so re-running is safe.
5
6import 'dotenv/config';
7import db from '../src/config/database.js';
8import ActivityPubService from '../src/services/ActivityPubService.js';
9
10// A Klonkt site's AP actor is reachable from its root via content negotiation:
11// an AP-Accept GET on the root 302s to /ap/users/<slug>.
12async function resolveActor(siteUrl) {
13 try {
14 const r = await fetch(siteUrl, { headers: { Accept: 'application/activity+json' }, redirect: 'manual' });
15 if (r.status >= 300 && r.status < 400) { const loc = r.headers.get('location'); if (loc) return new URL(loc, siteUrl).href; }
16 if (r.ok) return siteUrl; // root already serves the actor
17 } catch (e) { /* unreachable */ }
18 return null;
19}
20
21let links = [];
22try {
23 links = db.prepare(`
24 SELECT cl.remote_url AS url, s.id AS sid, s.slug AS slug
25 FROM circle_links cl JOIN sites s ON s.id = cl.local_site_id
26 WHERE cl.status != 'removed'
27 `).all();
28} catch (e) { console.log('no circle_links table — nothing to migrate'); process.exit(0); }
29
30if (!links.length) { console.log('no active circle_links — nothing to migrate'); process.exit(0); }
31
32for (const l of links) {
33 const actor = await resolveActor(l.url);
34 if (!actor) { console.log(`SKIP ${l.slug} -> ${l.url} (actor unresolvable)`); continue; }
35 try {
36 const r = await ActivityPubService.followActor({ id: l.sid, slug: l.slug }, actor, true);
37 console.log(`${l.slug} -> ${actor} : ${r && r.error ? 'ERR ' + r.error : 'OK (auto-boost)'}`);
38 } catch (e) {
39 console.log(`${l.slug} -> ${actor} : EXC ${e.message}`);
40 }
41}
42process.exit(0);
Note: See TracBrowser for help on using the repository browser.