mirror of
https://github.com/chenasraf/nextcloud-deck-tools.git
synced 2026-05-17 17:28:07 +00:00
167 lines
4.8 KiB
Python
167 lines
4.8 KiB
Python
#!/usr/bin/env python3
|
|
from __future__ import annotations
|
|
import argparse
|
|
import json
|
|
import os
|
|
import sys
|
|
from typing import Iterable
|
|
|
|
import requests
|
|
|
|
from common import (
|
|
add_domain_and_auth_args,
|
|
build_session,
|
|
resolve_arg,
|
|
resolve_domain_and_auth,
|
|
)
|
|
|
|
DEFAULT_STACKS: list[str] = [
|
|
"🐞 Bugs",
|
|
"📋 To Do",
|
|
"🚧 In Progress",
|
|
"✅ Done",
|
|
"📄 Backlog",
|
|
]
|
|
|
|
|
|
def get_stack_names() -> list[str]:
|
|
"""
|
|
Get stack names from NEW_BOARD_COLUMNS env var (comma-separated),
|
|
or fall back to DEFAULT_STACKS if not set.
|
|
"""
|
|
columns_env = os.getenv("NEW_BOARD_COLUMNS")
|
|
if columns_env:
|
|
# Split by comma and strip whitespace from each column name
|
|
return [col.strip() for col in columns_env.split(",") if col.strip()]
|
|
return DEFAULT_STACKS
|
|
|
|
|
|
def create_board(session: requests.Session, base_url: str, title: str) -> dict:
|
|
"""
|
|
POST /boards -> { id, title, ... }
|
|
"""
|
|
url = f"{base_url}/index.php/apps/deck/api/v1.0/boards"
|
|
headers = {"OCS-APIRequest": "true", "Content-Type": "application/json"}
|
|
payload = {"title": title}
|
|
resp = session.post(url, headers=headers, data=json.dumps(payload))
|
|
if resp.status_code not in (200, 201):
|
|
raise RuntimeError(
|
|
f"Deck API error creating board: {resp.status_code} {resp.text}"
|
|
)
|
|
return resp.json()
|
|
|
|
|
|
def create_stack(
|
|
session: requests.Session, base_url: str, board_id: int, title: str, order: int
|
|
) -> dict:
|
|
"""
|
|
POST /boards/{board_id}/stacks -> { id, title, order, ... }
|
|
"""
|
|
url = f"{base_url}/index.php/apps/deck/api/v1.0/boards/{board_id}/stacks"
|
|
headers = {"OCS-APIRequest": "true", "Content-Type": "application/json"}
|
|
payload = {"title": title, "order": order}
|
|
resp = session.post(url, headers=headers, data=json.dumps(payload))
|
|
if resp.status_code not in (200, 201):
|
|
raise RuntimeError(
|
|
f"Deck API error creating stack '{title}': {resp.status_code} {resp.text}"
|
|
)
|
|
return resp.json()
|
|
|
|
|
|
def create_stacks_in_order(
|
|
session: requests.Session,
|
|
base_url: str,
|
|
board_id: int,
|
|
stacks: Iterable[str],
|
|
) -> list[dict]:
|
|
created = []
|
|
for idx, title in enumerate(stacks):
|
|
created.append(create_stack(session, base_url, board_id, title, idx))
|
|
print(f" ✔️ Created stack [{idx}]: {title}")
|
|
return created
|
|
|
|
|
|
def main() -> None:
|
|
parser = argparse.ArgumentParser(
|
|
description="Create a Nextcloud Deck board and pre-populate it with standard stacks."
|
|
)
|
|
|
|
# Only domain/username/password (no board-id since we are creating it)
|
|
add_domain_and_auth_args(parser)
|
|
|
|
# Script-specific
|
|
parser.add_argument(
|
|
"--board-name",
|
|
help="New board name/title (e.g., 'Team Kanban')",
|
|
)
|
|
parser.add_argument(
|
|
"--no-default-stacks",
|
|
action="store_true",
|
|
help="Create the board without the default stacks.",
|
|
)
|
|
|
|
args = parser.parse_args()
|
|
|
|
# Resolve domain + auth (ENV -> CLI -> prompt)
|
|
try:
|
|
base_url, username, password = resolve_domain_and_auth(
|
|
cli_domain=args.domain,
|
|
cli_username=args.username,
|
|
cli_password=args.password,
|
|
)
|
|
except Exception as e:
|
|
print(f"❌ {e}", file=sys.stderr)
|
|
sys.exit(2)
|
|
|
|
# Resolve board name
|
|
try:
|
|
board_name = resolve_arg(
|
|
args.board_name,
|
|
["NEXTCLOUD_BOARD_NAME", "BOARD_NAME"],
|
|
prompt_text="New board name: ",
|
|
cast=str,
|
|
)
|
|
except Exception as e:
|
|
print(f"❌ {e}", file=sys.stderr)
|
|
sys.exit(2)
|
|
|
|
session = build_session(username, password)
|
|
|
|
# Create board
|
|
try:
|
|
board = create_board(session, base_url, board_name)
|
|
board_id = board.get("id")
|
|
if board_id is None:
|
|
raise RuntimeError(f"Board created but no id returned: {board}")
|
|
print(f"✔️ Created board '{board_name}' (id: {board_id}) at {base_url}")
|
|
except Exception as e:
|
|
print(f"❌ Failed to create board: {e}", file=sys.stderr)
|
|
sys.exit(1)
|
|
|
|
# Create default stacks (unless suppressed)
|
|
created_stacks = []
|
|
if not args.no_default_stacks:
|
|
try:
|
|
stack_names = get_stack_names()
|
|
print("→ Creating stacks in order:")
|
|
created_stacks = create_stacks_in_order(
|
|
session, base_url, int(board_id), stack_names
|
|
)
|
|
except Exception as e:
|
|
print(f"❌ Failed to create stacks: {e}", file=sys.stderr)
|
|
sys.exit(1)
|
|
|
|
# Summary
|
|
print("\nSummary")
|
|
print("-------")
|
|
print(f"Board ID: {board_id}")
|
|
if created_stacks:
|
|
print("Stacks (in order):")
|
|
for s in created_stacks:
|
|
print(f" - [{s.get('id')}] {s.get('title')}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|
|
|