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

75 lines
2.5 KiB
TypeScript

import { $joinedUser, $says, $user, asJoin, asSays, asUserInfo, fromNickClaim, fromSays, NickClaim, Says, UserId } from "../gen/secure-chat-protocol.js";
import { during, observe } from "../runtime/dataspace.js";
import { Assertion, Ref, Turn } from "../runtime/actor.js";
import { attachReadline } from './readline.js';
export default function (t: Turn, ds: Ref) {
observe(t, ds, $joinedUser, during(async (t, j0) => {
const j = asJoin(j0);
const facet = t.facet(t => runSession(t, j.uid, j.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 ?? '<not set>'}`);
}
t.retract(q);
}
})})));
}
updateUsername(t, 'user' + process.pid);
const users = new Map<UserId, string>();
observe(t, session, $user, during(async (_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}`);
},
});
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 })));
}
},
});
}