1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
|
#!/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()
|