2021-10-11 10:55:45 +00:00
|
|
|
import { $joinedUser, $says, $user, fromNickClaim, fromSays, NickClaim, Says, UserId } from "../gen/secureChatProtocol.js";
|
|
|
|
import { during, observe, P } from "../runtime/dataspace.js";
|
2021-04-21 19:22:30 +00:00
|
|
|
import { Assertion, Ref, Turn } from "../runtime/actor.js";
|
2021-04-16 18:58:22 +00:00
|
|
|
import { attachReadline } from './readline.js';
|
2021-05-17 13:13:55 +00:00
|
|
|
import { Embedded } from "@preserves/core";
|
2021-04-16 12:38:08 +00:00
|
|
|
|
2021-05-17 13:13:55 +00:00
|
|
|
export default function (t: Turn, ds_ptr: Embedded<Ref>) {
|
2021-04-24 22:15:15 +00:00
|
|
|
const ds = ds_ptr.embeddedValue;
|
2021-10-11 11:06:57 +00:00
|
|
|
observe(t, ds, P.rec($joinedUser, P.bind(), P.bind()),
|
2021-10-11 10:55:45 +00:00
|
|
|
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);
|
|
|
|
}));
|
2021-04-16 12:38:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function runSession(t: Turn, uid: UserId, session: Ref) {
|
|
|
|
let username: string | undefined;
|
2021-04-16 20:56:10 +00:00
|
|
|
let cleanShutdown = false;
|
|
|
|
|
|
|
|
t.activeFacet.onStop(_t => {
|
|
|
|
if (!cleanShutdown) {
|
|
|
|
console.log('Moderator retracted room permission.');
|
|
|
|
}
|
|
|
|
});
|
2021-04-16 12:38:08 +00:00
|
|
|
|
|
|
|
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>();
|
2021-10-11 11:06:57 +00:00
|
|
|
observe(t, session, P.rec($user, P.bind(), P.bind()),
|
2021-10-11 10:55:45 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}));
|
2021-04-16 12:38:08 +00:00
|
|
|
|
2021-10-11 11:06:57 +00:00
|
|
|
observe(t, session, P.rec($says, P.bind(), P.bind()), {
|
2021-10-11 10:55:45 +00:00
|
|
|
message(_t: Turn, bindings: Assertion): void {
|
|
|
|
let [who, what] = bindings as [UserId, string];
|
|
|
|
console.log(`${users.get(who) ?? `<unknown ${who}>`}: ${what}`);
|
2021-04-16 12:38:08 +00:00
|
|
|
},
|
|
|
|
});
|
|
|
|
|
2021-04-16 18:58:22 +00:00
|
|
|
attachReadline(t, {
|
2021-04-16 20:56:10 +00:00
|
|
|
retract(t) {
|
|
|
|
cleanShutdown = true;
|
|
|
|
t.stopActor();
|
|
|
|
},
|
2021-04-16 18:58:22 +00:00
|
|
|
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 })));
|
|
|
|
}
|
|
|
|
},
|
|
|
|
});
|
2021-04-16 12:38:08 +00:00
|
|
|
}
|