#!/usr/bin/env python3 """ Create a group and host it on the node running on this machine. Run it on the node's machine, as the user the node runs as: the node's control API only answers on 127.0.0.1, with a token the node writes to its data folder. USERNAME must be the hub account the node is linked to. """ import sys import time from pathlib import Path import httpx from meshbay_session import auth_key HUB = "https://meshbay.org" USERNAME = "alice" PASSPHRASE = "your passphrase" GROUP_NAME = "Family Photos" DESCRIPTION = "" FOLDER = "~/Pictures/shared" # the folder to share, created if missing WRITABLE = True # whether members may upload into it NODE_API = "http://127.0.0.1:18000" # ui_port in node.toml TOKEN_FILE = "~/.local/share/meshbay/ui-token" def call(client: httpx.Client, method: str, path: str, **kwargs) -> dict: r = client.request(method, path, **kwargs) if r.status_code >= 400: sys.exit(f"{method} {path} refused: {r.text}") return r.json() def main() -> None: # 1. Create the group on the hub. It is only a name and a member list there. with httpx.Client(base_url=HUB, timeout=30) as hub: login = call(hub, "POST", "/v1/users/login", json={ "username": USERNAME, "auth_key": auth_key(USERNAME, PASSPHRASE)}) auth = {"Authorization": f"Bearer {login['access_token']}"} body = {"name": GROUP_NAME, "visibility": "private", "join_policy": "invite"} if DESCRIPTION: body["description"] = DESCRIPTION group_id = call(hub, "POST", "/v1/groups", headers=auth, json=body)["group_id"] print(f"Created {GROUP_NAME!r} on the hub ({group_id})") # The node changes its token at every start: read it now. token = Path(TOKEN_FILE).expanduser().read_text().strip() with httpx.Client(base_url=NODE_API, timeout=30, headers={"X-MeshBay-Token": token}) as node: # 2. Ask the node to host it. The node writes the group into node.toml, # then indexes the folder. call(node, "POST", "/api/groups/attach", json={ "name": group_id, "shared_dir": FOLDER, "writable": WRITABLE, "join_policy": "invite"}) while True: hosted = call(node, "GET", "/api/groups") group = next((g for g in hosted["groups"] if g["id"] == group_id), None) if group: break print("Waiting for the node to index the folder...") time.sleep(2) # 3. The group key. It never leaves the node, except wrapped for a member. call(node, "POST", f"/api/groups/{group_id}/gek") # 4. First group on this node: a one-time code makes your application # its operator. pair = None if hosted["operator_paired"] else call(node, "POST", "/api/operator/pair") print(f"Hosted on this node: {group['file_count']} files indexed") if pair: print(f"Operator code, to enter when the application asks: {pair['code']} " f"(valid until {pair['expires_at']})") if __name__ == "__main__": main()