aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-cli/src/meshbay_cli/client/hub.py
diff options
context:
space:
mode:
Diffstat (limited to 'packages/meshbay-cli/src/meshbay_cli/client/hub.py')
-rw-r--r--packages/meshbay-cli/src/meshbay_cli/client/hub.py41
1 files changed, 38 insertions, 3 deletions
diff --git a/packages/meshbay-cli/src/meshbay_cli/client/hub.py b/packages/meshbay-cli/src/meshbay_cli/client/hub.py
index c8ce0c1..94d22da 100644
--- a/packages/meshbay-cli/src/meshbay_cli/client/hub.py
+++ b/packages/meshbay-cli/src/meshbay_cli/client/hub.py
@@ -1,9 +1,10 @@
"""
The hub's API, as a member's client uses it.
-The hub signs in, lists groups and the nodes serving them, mints the token a
-node is shown, and relays the WebRTC offer. Nothing else: no listing, no file
-and no byte of content passes through it (docs/MESHBAY_DESIGN.md §1.3, §8.4).
+The hub signs in, lists groups and the nodes serving them, keeps memberships
+(invitations, links, leaving) and preferences, mints the token a node is shown,
+and relays the WebRTC offer. Nothing else: no listing, no file and no byte of
+content passes through it (docs/MESHBAY_DESIGN.md §1.3, §8.4).
"""
import logging
@@ -147,6 +148,40 @@ class Hub:
raise CliError(NODE, f"The node did not answer the offer: {e.detail}") from e
return r["sdp"]
+ # ── Joining and leaving ──────────────────────────────────────────────────
+
+ async def invitations(self, token: str) -> list[dict]:
+ return (await self._call("GET", "/v1/groups/invitations",
+ token=token))["invitations"]
+
+ async def accept_invitation(self, token: str, group_id: str) -> dict:
+ return await self._call("POST", f"/v1/groups/{group_id}/invitation/accept",
+ token=token)
+
+ async def decline_invitation(self, token: str, group_id: str) -> dict:
+ return await self._call("POST", f"/v1/groups/{group_id}/invitation/decline",
+ token=token)
+
+ async def preview_link(self, token: str, ticket: str) -> dict:
+ return await self._call("POST", "/v1/invite-links/preview", token=token,
+ json={"ticket": ticket})
+
+ async def redeem_link(self, token: str, ticket: str) -> dict:
+ return await self._call("POST", "/v1/invite-links/redeem", token=token,
+ json={"ticket": ticket})
+
+ async def leave_group(self, token: str, group_id: str) -> dict:
+ return await self._call("POST", f"/v1/groups/{group_id}/leave", token=token)
+
+ # ── Preferences ──────────────────────────────────────────────────────────
+
+ async def preferences(self, token: str) -> dict:
+ return await self._call("GET", "/v1/users/me/preferences", token=token)
+
+ async def set_preference(self, token: str, key: str, value: str) -> dict:
+ return await self._call("PUT", f"/v1/users/me/preferences/{key}", token=token,
+ json={"value": value})
+
def _sign_in_refusal(e: HubError) -> CliError:
if e.status == 401: