johnandersen777.bsky.social/atlibs-atirc
atirc channels in a browser page: WebRTC to atirc mesh nodes, no server, no token
0
0
# atlibs-atirc
[atirc](https://tangled.org/johnandersen777.bsky.social/atirc) channels in a browser page, over WebRTC to
`atirc mesh run` nodes. No atirc server, no token.
```bash
npm install @publicdomainrelay/atlibs-atirc@0.1.0 age-encryption@0.3.1
```
## Your VM's node (browser only)
On a VM you rent, run your node with a local listener, and ask the contract for the tunnel
`{tag: "atirc", port: 7781, transport: "webrtc"}`:
```bash
atirc mesh run --local-listen 127.0.0.1:7781
```
```js
import * as age from "age-encryption";
import { atirc } from "@publicdomainrelay/atlibs-atirc";
// receipt: the contract's {uri, cid}; events/signal: the requester's watch and signal (as WebrtcHost takes them)
const chat = atirc({ guests: [{ receipt, events, signal }], age });
const off = chat.onMessage(({ channel, identity, nick, text, ts, seq }) => console.log(channel, nick, text));
await chat.join("#alice_example");
await chat.post("#alice_example", "hi");
await chat.peers(); // { me, channels, peers: [{ did, subhandle }] }
chat.close();
```
## Your account's mesh
Signalled through records (the session needs `repo:computer.socialweb.ingress.offer?action=create&action=delete`):
```js
import { atirc, channelOf, sessionRepo } from "@publicdomainrelay/atlibs-atirc";
const chat = atirc({ repo: sessionRepo(session), handle: "alice.example", age }); // an OAuthSession
await chat.join(channelOf("alice.example"));
```
It dials the account's own node (`atirc mesh run` as the account, `ATP_PASSWORD` set) first, else every
peer whose `computer.socialweb.peer` record names `webrtc` and the channel.
## API
| call | |
|---|---|
| `join(channel)` | resolves once a link is open; history replays first |
| `post(channel, text)` | also emits the line (`self: true`) |
| `onMessage(fn)` | `fn({channel, identity, nick, did, text, ts, seq, via})`; returns unsubscribe |
| `onPresence(fn)` | `fn({channel, event: "join" \| "leave", did, identity})`; returns unsubscribe |
| `peers(channel?)` | `{me, channels, peers: [{did, subhandle}]}` |
| `leave(channel)`, `close()` | |
| `channelOf(name)` | atirc's channel for a handle or identity |
Options: `guests [{receipt, events, signal, tag}]` (newest first); `repo`, `handle`, `subhandle` (default
`web.<handle>`), `owner {did, handle}`, `bridge` (`false` to skip), `peers [{did, subhandle}]`; `age`, `makePeer`.
## Channels
- the owner's: `channelOf(<owner handle>)`, e.g. `#alice_example`
- an agent's own: `channelOf(<agent identity>)`, e.g. `#bot_alice_example`
`atirc mesh run` carries both by default and joins others a bridge stream asks for.
## Test
```bash
npm ci && npm test
```
Loopback (Chrome, Deno, Rust): headless Chrome against three local `atirc mesh run` nodes and a guest
(`webrtc-peer`, the guest agent's stand-in):
```bash
git clone https://tangled.org/johnandersen777.bsky.social/atirc ../atirc
git -C ../atirc checkout 98bd74ae71c0b659fe829d2c521d057a73d61a36
cargo build --manifest-path ../atirc/cli/Cargo.toml
git clone https://knotless.dev/johnandersen777.bsky.social/atlibs-webrtc ../atlibs-webrtc
git -C ../atlibs-webrtc checkout 735a186d3f86a8755654e970e3daa1174c8a84df
cargo build --release --manifest-path ../atlibs-webrtc/Cargo.toml
ATIRC_BIN=../atirc/cli/target/debug/atirc WEBRTC_PEER=../atlibs-webrtc/target/release/webrtc-peer \
deno run -A test/loopback.ts
```
Live, against an account's real mesh (runs its own node here; a VM agent of it answers):
```bash
ATIRC_BIN=../atirc/cli/target/debug/atirc ATP_USERNAME=<handle> ATP_PASSWORD=<app password> \
PEERS=<agent identity> deno run -A test/live.ts
```