#!/usr/bin/env python3 import argparse import json import sys import requests from urllib.parse import urlparse import getpass def normalize_base_url(domain_or_url: str) -> str: parsed = urlparse(domain_or_url) if parsed.scheme in ("http", "https"): return domain_or_url.rstrip("/") return f"https://{domain_or_url.strip().strip('/')}" def list_stacks(session: requests.Session, base_url: str, board_id: int): url = f"{base_url}/index.php/apps/deck/api/v1.0/boards/{board_id}/stacks" headers = {"OCS-APIRequest": "true", "Accept": "application/json"} resp = session.get(url, headers=headers) if resp.status_code != 200: raise RuntimeError(f"Deck API error: {resp.status_code} {resp.text}") return resp.json() def main(): parser = argparse.ArgumentParser( description="List stacks (id + name) for a Nextcloud Deck board." ) parser.add_argument( "--domain", required=True, help="Nextcloud instance (e.g., example.com or https://example.com)", ) parser.add_argument( "--board-id", required=True, type=int, help="Deck Board ID to list stacks from" ) parser.add_argument( "--username", help="Nextcloud username (if not provided, will be prompted)" ) parser.add_argument( "--password", help="Nextcloud password or app password (if not provided, will be prompted)", ) parser.add_argument( "--json", action="store_true", help="Output raw JSON instead of a table" ) args = parser.parse_args() # Prompt for missing creds username = args.username or input("Nextcloud username: ") password = args.password or getpass.getpass( "Nextcloud password (or app password): " ) base_url = normalize_base_url(args.domain) session = requests.Session() session.auth = (username, password) try: stacks = list_stacks(session, base_url, args.board_id) except Exception as e: print(f"❌ Failed to fetch stacks: {e}", file=sys.stderr) sys.exit(1) if args.json: print(json.dumps(stacks, ensure_ascii=False, indent=2)) return if not stacks: print("No stacks found.") return print(f"Stacks for board {args.board_id} at {base_url}:") print("-" * 60) print(f"{'ID':<8} {'NAME'}") print("-" * 60) for s in stacks: sid = s.get("id") title = s.get("title", "") print(f"{str(sid):<8} {title}") print("-" * 60) print("Tip: use the ID in your importer script's --stack-id.") if __name__ == "__main__": main()