import { $joinedUser, $says, $user, fromNickClaim, fromSays, NickClaim, Says, UserId } from "../gen/secureChatProtocol.js"; import { during, observe, P } from "../runtime/dataspace.js"; import { Assertion, Ref, Turn } from "../runtime/actor.js"; import { attachReadline } from './readline.js'; import { Embedded } from "@preserves/core"; export default function (t: Turn, ds_ptr: Embedded) { const ds = ds_ptr.embeddedValue; observe(t, ds, P.rec($joinedUser, P.bind(), P.bind()), during(async (t, bindings) => { let [uid, handle] = bindings as [UserId, Ref]; const facet = t.facet(t => runSession(t, uid, handle)); return t => t.stop(facet); })); } function runSession(t: Turn, uid: UserId, session: Ref) { let username: string | undefined; let cleanShutdown = false; t.activeFacet.onStop(_t => { if (!cleanShutdown) { console.log('Moderator retracted room permission.'); } }); function updateUsername(t: Turn, name: string) { const q = t.assert(session, fromNickClaim(NickClaim({ uid, name, k: t.ref({ message(t, reply0) { if (reply0 === true) { username = name; console.log(`Nick changed to ${username}`); } else { console.log(`Nick conflict: name is still ${username ?? ''}`); } t.retract(q); } })}))); } updateUsername(t, 'user' + process.pid); const users = new Map(); observe(t, session, P.rec($user, P.bind(), P.bind()), during(async (_t, bindings) => { let [uid, name] = bindings as [UserId, string]; const oldName = users.get(uid); console.log(oldName === void 0 ? `${name} arrived` : `${oldName} changed name to ${name}`); users.set(uid, name); return (_t) => { if (users.get(uid) === name) { console.log(`${name} departed`); users.delete(uid); } }; })); observe(t, session, P.rec($says, P.bind(), P.bind()), { message(_t: Turn, bindings: Assertion): void { let [who, what] = bindings as [UserId, string]; console.log(`${users.get(who) ?? ``}: ${what}`); }, }); attachReadline(t, { retract(t) { cleanShutdown = true; t.stopActor(); }, message(t, line: string) { if (line.toLowerCase().startsWith('/nick ')) { updateUsername(t, line.slice(5).trimLeft()); } else { t.message(session, fromSays(Says({ who: uid, what: line }))); } }, }); }