Add minimal Companion-to-Nextcloud-Health bridge (weight only, MVP)

This commit is contained in:
Matthias Jacob
2026-09-17 02:02:34 +02:00
parent d376d5ee95
commit 37f3399953
6 changed files with 609 additions and 0 deletions
+67
View File
@@ -0,0 +1,67 @@
#!/usr/bin/env python3
"""One-time setup: obtain a Nextcloud app password via Login Flow v2.
Usage:
python nc_login_flow.py https://your-nextcloud.example.com
Writes the resulting server URL, login name and app password to
credentials.json (used by server.py to authenticate against the Health API).
"""
import json
import sys
import time
import webbrowser
from pathlib import Path
import requests
CREDENTIALS_FILE = Path(__file__).parent / "credentials.json"
# Shown to the user on Nextcloud's login-flow authorization page instead of the
# default "python-requests/x.y.z".
USER_AGENT = "PrivateHealthBridge"
def run(base_url: str) -> None:
base_url = base_url.rstrip("/")
headers = {"User-Agent": USER_AGENT}
resp = requests.post(f"{base_url}/index.php/login/v2", headers=headers, timeout=10)
resp.raise_for_status()
flow = resp.json()
login_url = flow["login"]
poll_token = flow["poll"]["token"]
poll_endpoint = flow["poll"]["endpoint"]
print(f"Open this URL and confirm the login in your browser:\n{login_url}\n")
webbrowser.open(login_url)
print("Waiting for confirmation...")
while True:
time.sleep(2)
poll_resp = requests.post(poll_endpoint, data={"token": poll_token}, headers=headers, timeout=10)
if poll_resp.status_code == 404:
continue # not confirmed yet
poll_resp.raise_for_status()
result = poll_resp.json()
break
CREDENTIALS_FILE.write_text(
json.dumps(
{
"server": result["server"].rstrip("/"),
"login_name": result["loginName"],
"app_password": result["appPassword"],
},
indent=2,
)
)
CREDENTIALS_FILE.chmod(0o600)
print(f"Saved credentials to {CREDENTIALS_FILE}")
if __name__ == "__main__":
if len(sys.argv) != 2:
print(f"Usage: {sys.argv[0]} <nextcloud-base-url>")
sys.exit(1)
run(sys.argv[1])