loading core in a worker…
Browsers can't open raw TCP, so IMAP/SMTP/DNS tunnel through a tiny WebSocket→TCP bridge. TLS terminates inside the wasm core — the bridge only ever relays ciphertext. Without it the core runs fine, but networking errors.
npx @slothfulchat/ws-tcp-proxy (listens on
ws://localhost:8641, override with PORT)?proxy=ws://localhost:8641
ws://localhost works even from an https deployment (localhost is
exempt from mixed-content blocking); a remote bridge needs wss://.
Other params: ?persist=0 for a fresh in-memory core — persistence
holds an exclusive OPFS lock per origin, so on the deployed site this page and
the main app can't both run a persistent core at once.
Open the browser console and poke at core directly:
await rpc.request('get_system_info') — raw JSON-RPC, any method nameawait dc.rpc.getAllAccountIds() — generated typed clientawait dc.rpc.addAccount() then await dc.rpc.getAccountInfo(1)// === DC account bot (paste after page loads with ?proxy=...) ===
const aid = (await dc.rpc.getAllAccountIds())[0] || await dc.rpc.addAccount()
await dc.rpc.setConfig(aid, 'bot', '1')
// Check if already configured
if (!(await dc.rpc.isConfigured(aid))) {
await dc.rpc.addTransportFromQr(aid, 'dcaccount:nine.testrun.org')
console.log('Account configured via dcaccount QR')
} else {
await dc.rpc.startIo(aid)
}
dc.getContextEvents(aid).on('IncomingMsg', async (ev) => {
const msg = await dc.rpc.getMessage(aid, ev.msgId)
const chat = await dc.rpc.getBasicChatInfo(aid, ev.chatId)
console.log(`[${chat.name}] ${msg.text}`)
// echo
await dc.rpc.sendMsg(aid, ev.chatId, {
text: `🤖 echo: ${msg.text ?? '(non-text)'} !`,
viewtype: 'Text', file: null, filename: null,
location: null, html: null, overrideSenderName: null,
quotedMessageId: null, quotedText: null,
})
})
await dc.rpc.getChatSecurejoinQrCode(aid)