getting user; mod: avatar, profileBg, profile now working

This commit is contained in:
2026-04-19 18:27:36 +02:00
parent 61936b4576
commit f24cab8fb0
9 changed files with 390 additions and 199 deletions
+196 -29
View File
@@ -34,6 +34,12 @@ shutdown_event: asyncio.Event = None
def post(path, **data):
return requests.post(f"{BASE_URL}{path}", data=data)
def post_auth(path, **data):
return requests.post(f"{BASE_URL}{path}", data={"token": token, **data})
def post_auth_header(path, files=None, **data):
return requests.post(f"{BASE_URL}{path}", headers={"token": token}, data=data, files=files)
def fmt_msg(m: dict) -> str:
sender = m.get("sender", "?")
content = m.get("content", "")
@@ -47,12 +53,19 @@ def fmt_msg(m: dict) -> str:
# ── commands ─────────────────────────────────────────────────────────────────
def cmd_login(args):
def cmd_new_user(args):
if len(args) < 2:
print("usage: /new/user <username> <password>")
return
r = post("/new/user", username=args[0], password=args[1])
print("registered" if r.ok else f"error: {r.text}")
def cmd_new_token(args):
global token, user_id
if len(args) < 2:
print("usage: /login <username> <password>")
print("usage: /new/token <username> <password>")
return
r = post("/token", username=args[0], password=args[1])
r = post("/new/token", username=args[0], password=args[1])
if r.ok:
data = r.json()
token = data["token"]
@@ -64,31 +77,31 @@ def cmd_login(args):
else:
print(f"login failed: {r.text}")
def cmd_send(args):
def cmd_msg_user(args):
if not token:
print("not logged in")
return
if len(args) < 2:
print("usage: /send <connectionid> <message…>")
print("usage: /msg/user <connectionid> <message…>")
return
conn_id = args[0]
content = " ".join(args[1:])
r = post("/message", token=token, connectionid=conn_id, msgContent=content)
r = post_auth("/msg/user", connectionid=conn_id, msgContent=content)
print("sent" if r.ok else f"error: {r.text}")
def cmd_history(args):
def cmd_get_connection_messages(args):
if not token:
print("not logged in")
return
if not args:
print("usage: /history <connectionid> [count]")
print("usage: /get/connection/messages <connectionid> [count] [before]")
return
data = {"token": token, "connectionid": args[0]}
data = {"connectionid": args[0]}
if len(args) > 1:
data["messages"] = args[1]
if len(args) > 2:
data["before"] = args[2]
r = requests.post(f"{BASE_URL}/get/connection/messages", data=data)
r = post_auth("/get/connection/messages", **data)
if r.ok:
msgs = r.json() or []
if not msgs:
@@ -98,41 +111,198 @@ def cmd_history(args):
else:
print(f"error: {r.text}")
def cmd_connections(args):
def cmd_get_connections(args):
if not token:
print("not logged in")
return
r = post("/get/connections", token=token)
r = post_auth("/get/connections")
if r.ok:
for c in (r.json() or {}).values():
for c in (r.json() or []):
print(f" {c['id']} requestor={c['requestorId']} recipient={c['recipientId']} state={c['state']}")
else:
print(f"error: {r.text}")
def cmd_delconnection(args):
def cmd_new_connection(args):
if not token:
print("not logged in")
return
if not args:
print("usage: /delconnection <connectionid>")
print("usage: /new/connection <userid>")
return
r = post("/del/connection", token=token, connectionid=args[0])
r = post_auth("/new/connection", recipient=args[0])
print("connection requested" if r.ok else f"error: {r.text}")
def cmd_mod_connection_elevate(args):
if not token:
print("not logged in")
return
if not args:
print("usage: /mod/connection/elevate <connectionid>")
return
r = post_auth("/mod/connection/elevate", connectionid=args[0])
print(f"ok: {r.text}" if r.ok else f"error: {r.text}")
def cmd_del_connection(args):
if not token:
print("not logged in")
return
if not args:
print("usage: /del/connection <connectionid>")
return
r = post_auth("/del/connection", connectionid=args[0])
print("deleted" if r.ok else f"error: {r.text}")
def cmd_del_user(args):
if not token:
print("not logged in")
return
r = post_auth("/del/user")
print("user deleted" if r.ok else f"error: {r.text}")
def cmd_get_user(args):
if not token:
print("not logged in")
return
if not args:
print("usage: /get/user <userid>")
return
r = post_auth("/get/user", targetid=args[0])
if r.ok:
print(json.dumps(r.json(), indent=2))
else:
print(f"error: {r.text}")
def cmd_mod_user_profile(args):
if not token:
print("not logged in")
return
data = {}
for arg in args:
if "=" in arg:
k, v = arg.split("=", 1)
data[k] = v
if not data:
print("usage: /mod/user/profile [pronouns=...] [description=...] [color=r,g,b,a]")
return
r = post_auth("/mod/user/profile", **data)
print("updated" if r.ok else f"error: {r.text}")
def cmd_get_file(args):
if not token:
print("not logged in")
return
if len(args) < 2:
print("usage: /get/file <connectionid> <key>")
return
r = post_auth_header("/get/file", connectionid=args[0], key=args[1])
if r.ok:
print(json.dumps(r.json(), indent=2))
else:
print(f"error: {r.text}")
def cmd_new_file(args):
if not token:
print("not logged in")
return
if len(args) < 2:
print("usage: /new/file <connectionid> <filepath>")
return
conn_id, filepath = args[0], args[1]
try:
with open(filepath, "rb") as f:
r = post_auth_header("/new/file", files={"file": f}, connectionid=conn_id)
print(f"uploaded: {r.text}" if r.ok else f"error: {r.text}")
except FileNotFoundError:
print(f"file not found: {filepath}")
def cmd_mod_user_avatar(args):
if not token:
print("not logged in")
return
if not args:
print("usage: /mod/user/avatar <filepath>")
return
filepath = args[0]
try:
with open(filepath, "rb") as f:
r = post_auth_header("/mod/user/avatar", files={"file": f})
print("avatar updated" if r.ok else f"error: {r.text}")
except FileNotFoundError:
print(f"file not found: {filepath}")
def cmd_mod_user_profilebg(args):
if not token:
print("not logged in")
return
if not args:
print("usage: /mod/user/profilebg <filepath>")
return
filepath = args[0]
try:
with open(filepath, "rb") as f:
r = post_auth_header("/mod/user/profilebg", files={"file": f})
print("profile background updated" if r.ok else f"error: {r.text}")
except FileNotFoundError:
print(f"file not found: {filepath}")
def cmd_get_user_avatar(args):
if not token:
print("not logged in")
return
if not args:
print("usage: /get/user/avatar <userid>")
return
r = post_auth_header("/get/user/avatar", userid=args[0])
print(r.text if r.ok else f"error: {r.text}")
def cmd_get_user_profilebg(args):
if not token:
print("not logged in")
return
if not args:
print("usage: /get/user/profilebg <userid>")
return
r = post_auth_header("/get/user/profilebg", userid=args[0])
print(r.text if r.ok else f"error: {r.text}")
COMMANDS = {
"/login": cmd_login,
"/send": cmd_send,
"/history": cmd_history,
"/connections": cmd_connections,
"/delconnection": cmd_delconnection,
"/new/user": cmd_new_user,
"/new/token": cmd_new_token,
"/new/connection": cmd_new_connection,
"/new/file": cmd_new_file,
"/mod/user/profile": cmd_mod_user_profile,
"/mod/user/avatar": cmd_mod_user_avatar,
"/mod/user/profilebg": cmd_mod_user_profilebg,
"/mod/connection/elevate": cmd_mod_connection_elevate,
"/get/user": cmd_get_user,
"/get/connections": cmd_get_connections,
"/get/connection/messages": cmd_get_connection_messages,
"/get/file": cmd_get_file,
"/get/user/avatar": cmd_get_user_avatar,
"/get/user/profilebg": cmd_get_user_profilebg,
"/del/user": cmd_del_user,
"/del/connection": cmd_del_connection,
"/msg/user": cmd_msg_user,
}
HELP = """
/login <user> <pass> authenticate
/connections list your connections
/send <connectionid> <message…> send a DM
/history <connectionid> [count] [before] fetch message history
/delconnection <connectionid> delete a connection
/new/user <user> <pass> create account
/new/token <user> <pass> authenticate
/new/connection <userid> send connection request
/new/file <connectionid> <filepath> upload attachment
/mod/user/profile [pronouns=...] [description=...] [color=r,g,b,a] update profile
/mod/user/avatar <filepath> set avatar image
/mod/user/profilebg <filepath> set profile background
/mod/connection/elevate <connectionid> elevate connection
/get/user <userid> get user info
/get/connections list your connections
/get/connection/messages <connectionid> [count] [before] fetch message history
/get/file <connectionid> <key> download attachment URL
/get/user/avatar <userid> get avatar download URL
/get/user/profilebg <userid> get profile background URL
/del/user delete your account
/del/connection <connectionid> delete a connection
/msg/user <connectionid> <message…> send a DM
"""
# ── websocket ─────────────────────────────────────────────────────────────────
@@ -141,7 +311,6 @@ async def receiver(ws):
async for raw in ws:
try:
data = json.loads(raw)
# pushed DM
if "content" in data and "sender" in data:
print(f"\n{fmt_msg(data)}", flush=True)
else:
@@ -171,7 +340,6 @@ async def run():
print("Alt+Enter = newline | Enter = send | /help | Ctrl+C = quit\n")
input_thread.start()
input_thread_started = True
# re-auth after reconnect
if token:
await ws.send(json.dumps({"token": token}))
@@ -219,7 +387,6 @@ def input_loop():
if cmd in COMMANDS:
COMMANDS[cmd](parts[1:])
else:
# raw JSON passthrough
asyncio.run_coroutine_threadsafe(send_queue.put(text), loop)
except (EOFError, KeyboardInterrupt):
asyncio.run_coroutine_threadsafe(shutdown_event.set(), loop)