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

75 lines
2.7 KiB
TypeScript

import {
$claimNick,
$joinedUser,
$says,
$user,
Join,
NickConflict,
UserId,
UserInfo,
asNickClaim,
fromJoin,
fromNickConflict,
fromUserInfo,
} from "../gen/secure-chat-protocol.js";
import { Assertion, Handle, Ref, Turn } from "../runtime/actor.js";
import { observe, during, $Observe, asObserve, Dataspace } from "../runtime/dataspace.js";
import { attenuate, rfilter, pRec, pEmbedded, pString, pLit } from "../runtime/rewrite.js";
import { attenuate as sturdyAttenuate, KEY_LENGTH, sturdyEncode, fromSturdyRef, mint } from "../transport/sturdy.js";
import { Bind, fromBind } from "../gen/gatekeeper.js";
import { Bytes, Embedded } from "@preserves/core";
export default function (t: Turn, gatekeeperDs_ptr: Embedded<Ref>) {
const gatekeeperDs = gatekeeperDs_ptr.embeddedValue;
const ds = t.ref(new Dataspace());
const chatOid = 'chat';
const chatKey = new Bytes(KEY_LENGTH);
t.assert(gatekeeperDs, fromBind(Bind({ oid: chatOid, key: chatKey, target: ds })));
mint(chatOid, chatKey).then(async r => {
r = await sturdyAttenuate(r, rfilter(pRec($Observe, pLit($joinedUser), pEmbedded())));
console.log(fromSturdyRef(r).asPreservesText());
console.log(sturdyEncode(fromSturdyRef(r)).toHex());
});
const nicks = new Map<string, UserId>();
let nextUserId: UserId = 0;
observe(t, ds, $Observe, during(async (t, o0) => {
const o = asObserve(o0);
if (o.label !== $joinedUser) return null;
const uid: UserId = nextUserId++;
const f = t.facet(t => {
t.assert(o.observer, fromJoin(Join({
uid,
handle: attenuate(ds, rfilter(
pRec($Observe, pLit($user), pEmbedded()),
pRec($Observe, pLit($says), pEmbedded()),
pRec($claimNick, pLit(uid), pString(), pEmbedded()),
pRec($says, pLit(uid), pString()))),
})));
let infoHandle: Handle | undefined;
let nick: string | undefined;
observe(t, ds, $claimNick, {
assert(t: Turn, c0: Assertion): void {
const c = asNickClaim(c0);
if (c.uid !== uid) return;
if (nicks.has(c.name)) {
t.message(c.k, fromNickConflict(NickConflict()));
} else {
t.message(c.k, true);
if (nick !== void 0) nicks.delete(nick);
infoHandle = t.replace(ds, infoHandle, fromUserInfo(UserInfo(c)));
nick = c.name;
nicks.set(nick, uid);
}
}
});
});
return t => t.stop(f);
}));
}