import { $joinedUser, $says, $user, asJoin, asSays, asUserInfo, fromNickClaim, fromSays, NickClaim, Says, UserId } from "./gen/secure-chat-protocol.js"; import { during, observe } from "./dataspace.js"; import { Assertion, Ref, Turn } from "./actor.js"; import readline from 'readline'; export default function (t: Turn, ds: Ref) { observe(t, ds, $joinedUser, { assert(t, j0) { const j = asJoin(j0); runSession(t, j.uid, j.handle); } }); } function runSession(t: Turn, uid: UserId, session: Ref) { let username: string | undefined; 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, $user, during((_t, ui0) => { const ui = asUserInfo(ui0); const oldName = users.get(ui.uid); console.log(oldName === void 0 ? `${ui.name} arrived` : `${oldName} changed name to ${ui.name}`); users.set(ui.uid, ui.name); return (_t) => { if (users.get(ui.uid) === ui.name) { console.log(`${ui.name} departed`); } }; })); observe(t, session, $says, { message(_t: Turn, u0: Assertion): void { const u = asSays(u0); console.log(`${users.get(u.who) ?? ``}: ${u.what}`); }, }); const rl = readline.createInterface({ input: process.stdin, output: process.stdout }); rl.on('line', (line: string) => t.freshen(t => { if (line.toLowerCase().startsWith('/nick ')) { updateUsername(t, line.slice(5).trimLeft()); } else { t.message(session, fromSays(Says({ who: uid, what: line }))); } })); rl.on('close', () => t.freshen(t => t.stopActor())); }