novy-syndicate/src/secure-chat-client.ts

67 lines
2.2 KiB
TypeScript

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 ?? '<not set>'}`);
}
t.retract(q);
}
})})));
}
updateUsername(t, 'user' + process.pid);
const users = new Map<UserId, string>();
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) ?? `<unknown ${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()));
}