Files
nextcloud-deck-tools/import.py

120 lines
3.4 KiB
Python

#!/usr/bin/env python3
from __future__ import annotations
import argparse
import csv
import json
import sys
import requests
from typing import Dict, Any
from common import (
add_common_args,
build_session,
normalize_base_url,
resolve_arg,
resolve_common,
)
def create_card(
session: requests.Session,
base_url: str,
board_id: int,
stack_id: int,
title: str,
description: str,
) -> requests.Response:
url = f"{base_url}/index.php/apps/deck/api/v1.0/boards/{board_id}/stacks/{stack_id}/cards"
headers = {"OCS-APIRequest": "true", "Content-Type": "application/json"}
payload: Dict[str, Any] = {
"title": title,
"type": "plain",
"order": 0,
"description": description,
"duedate": None,
}
return session.post(url, headers=headers, data=json.dumps(payload))
def main() -> None:
parser = argparse.ArgumentParser(
description="Import tasks from a CSV file into Nextcloud Deck."
)
# Common flags (domain, board-id, username, password)
add_common_args(parser)
# Script-specific flags
parser.add_argument(
"--stack-id",
type=int,
help="Deck Stack ID where cards will be created",
)
parser.add_argument(
"--csv-file",
help="Path to the CSV file containing tasks (expects headers: title, description)",
)
args = parser.parse_args()
# Resolve common fields (ENV -> CLI -> prompt)
try:
base_url, board_id, username, password = resolve_common(
cli_domain=args.domain,
cli_board_id=args.board_id,
cli_username=args.username,
cli_password=args.password,
)
except Exception as e:
print(f"{e}", file=sys.stderr)
sys.exit(2)
# Resolve script-specific fields
try:
stack_id = resolve_arg(
None if args.stack_id is None else str(args.stack_id),
["NEXTCLOUD_STACK_ID", "STACK_ID"],
prompt_text="Deck Stack ID: ",
cast=lambda s: int(s.strip()),
)
csv_file = resolve_arg(
args.csv_file,
["IMPORT_CSV_FILE", "CSV_FILE"],
prompt_text="CSV file path: ",
cast=str,
)
except Exception as e:
print(f"{e}", file=sys.stderr)
sys.exit(2)
session = build_session(username, password)
# Read & import
try:
with open(csv_file, newline="", encoding="utf-8") as f:
reader = csv.DictReader(f)
for row in reader:
title = (row.get("title") or "").strip()
description = (row.get("description") or "").strip()
if not title:
print(f"Skipping row with missing title: {row}")
continue
resp = create_card(
session, base_url, int(board_id), int(stack_id), title, description
)
if resp.status_code in (200, 201):
print(f"✔️ Created card: {title}")
else:
print(f"❌ Failed: {title}{resp.status_code} {resp.text}")
except FileNotFoundError:
print(f"❌ CSV file not found: {csv_file}", file=sys.stderr)
sys.exit(1)
except Exception as e:
print(f"❌ Error during import: {e}", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()