// nextcloud's events. The tool runtime imports this once the broker is bound. It watches the user // list and the share list and announces new arrivals. // // Emits (novox/hq ADR 0041/0042): // module.nextcloud.user.created — a user account appeared (occ user:list) // module.nextcloud.share.created — a share appeared (OCS shares) // // Both are diffed and primed silently on the first look, so a restart does not re-announce every // existing user and share as freshly created. import { emit } from "@novox/mesh-sdk/events"; import { NextcloudClient } from "./client.js"; // Constructed lazily so an unconfigured node (no admin password) loads this entrypoint without // crashing the events host — it simply watches nothing. let nextcloud: NextcloudClient | undefined; try { nextcloud = NextcloudClient.fromEnv(); } catch (err) { console.log(`[nextcloud] not configured, not watching: ${err}`); } const knownUsers = new Set(); let usersPrimed = false; async function pollUsers(client: NextcloudClient): Promise { const users = client.listUsers(); for (const u of users) { if (knownUsers.has(u.uid)) continue; if (usersPrimed) await emit("user.created", { uid: u.uid, displayName: u.displayName }); knownUsers.add(u.uid); } usersPrimed = true; } const knownShares = new Set(); let sharesPrimed = false; async function pollShares(client: NextcloudClient): Promise { const shares = await client.listShares(); for (const s of shares) { if (knownShares.has(s.id)) continue; if (sharesPrimed) await emit("share.created", { id: s.id, path: s.path, shareType: s.shareType, shareWith: s.shareWith, owner: s.owner }); knownShares.add(s.id); } sharesPrimed = true; } if (nextcloud) { const client = nextcloud; const tick = (fn: (c: NextcloudClient) => Promise): void => { const run = (): void => void fn(client).catch((err) => console.error(`[nextcloud] ${err}`)); setInterval(run, 60_000); run(); }; tick(pollUsers); tick(pollShares); console.log("[nextcloud] watching users and shares"); }