feat: Adobe Sign template download pipeline
download_templates.py — subcommand CLI for listing and downloading library
templates from Adobe Sign.
list — print all templates with name, modified date, ID
download — download all templates (default)
download --all — explicit download all
download "Name" — download a single named template; picks the most
recently modified if duplicates exist
Each template is saved to downloads/<name>__<id8>/ containing metadata.json,
form_fields.json, documents.json, and the source PDF.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
343955241d
commit
e655d8b4f5
|
|
@ -0,0 +1,162 @@
|
|||
"""
|
||||
Download Adobe Sign library templates to the local downloads/ folder.
|
||||
|
||||
Usage:
|
||||
python3 src/download_templates.py list
|
||||
List all templates available in the account (no download).
|
||||
|
||||
python3 src/download_templates.py download
|
||||
python3 src/download_templates.py download --all
|
||||
Download all templates.
|
||||
|
||||
python3 src/download_templates.py download "Template Name"
|
||||
Download the named template. If multiple templates share the same name,
|
||||
the most recently modified one is used.
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
sys.path.insert(0, os.path.dirname(__file__))
|
||||
|
||||
from adobe_api import adobe_api_get, adobe_api_get_bytes
|
||||
|
||||
DOWNLOADS_DIR = os.path.join(os.path.dirname(__file__), "..", "downloads")
|
||||
|
||||
|
||||
def safe_dirname(name):
|
||||
return "".join(c if c.isalnum() or c in " -_" else "_" for c in name).strip()
|
||||
|
||||
|
||||
def save_json(path, data):
|
||||
with open(path, "w", encoding="utf-8") as f:
|
||||
json.dump(data, f, indent=2)
|
||||
|
||||
|
||||
def fetch_template_list():
|
||||
result = adobe_api_get("libraryDocuments")
|
||||
return result.get("libraryDocumentList", [])
|
||||
|
||||
|
||||
def cmd_list(_args):
|
||||
print("Fetching template list...")
|
||||
templates = fetch_template_list()
|
||||
if not templates:
|
||||
print("No templates found.")
|
||||
return
|
||||
print(f"{'Name':<45} {'Modified':<25} {'ID'}")
|
||||
print("-" * 100)
|
||||
for t in sorted(templates, key=lambda x: x.get("modifiedDate", ""), reverse=True):
|
||||
print(f"{t['name']:<45} {t.get('modifiedDate', 'n/a'):<25} {t['id']}")
|
||||
|
||||
|
||||
def download_one(template):
|
||||
template_id = template["id"]
|
||||
template_name = template["name"]
|
||||
dir_name = f"{safe_dirname(template_name)}__{template_id[:8]}"
|
||||
out_dir = os.path.join(DOWNLOADS_DIR, dir_name)
|
||||
os.makedirs(out_dir, exist_ok=True)
|
||||
|
||||
print(f"\n--- {template_name} ---")
|
||||
|
||||
metadata = adobe_api_get(f"libraryDocuments/{template_id}")
|
||||
save_json(os.path.join(out_dir, "metadata.json"), metadata)
|
||||
|
||||
try:
|
||||
form_fields = adobe_api_get(f"libraryDocuments/{template_id}/formFields")
|
||||
save_json(os.path.join(out_dir, "form_fields.json"), form_fields)
|
||||
print(f" {len(form_fields.get('fields', []))} form fields saved.")
|
||||
except Exception as e:
|
||||
print(f" WARNING: Could not fetch form fields: {e}")
|
||||
save_json(os.path.join(out_dir, "form_fields.json"), {"error": str(e)})
|
||||
|
||||
docs = adobe_api_get(f"libraryDocuments/{template_id}/documents")
|
||||
save_json(os.path.join(out_dir, "documents.json"), docs)
|
||||
|
||||
for doc in docs.get("documents", []):
|
||||
doc_id = doc["id"]
|
||||
doc_name = doc.get("name", doc_id)
|
||||
if not doc_name.lower().endswith(".pdf"):
|
||||
doc_name += ".pdf"
|
||||
safe_name = safe_dirname(doc_name)
|
||||
pdf_path = os.path.join(out_dir, safe_name)
|
||||
try:
|
||||
pdf_bytes = adobe_api_get_bytes(
|
||||
f"libraryDocuments/{template_id}/documents/{doc_id}"
|
||||
)
|
||||
with open(pdf_path, "wb") as f:
|
||||
f.write(pdf_bytes)
|
||||
print(f" PDF saved ({len(pdf_bytes) // 1024}KB) → {safe_name}")
|
||||
except Exception as e:
|
||||
print(f" WARNING: Could not download PDF: {e}")
|
||||
|
||||
print(f" Done → downloads/{dir_name}/")
|
||||
return out_dir
|
||||
|
||||
|
||||
def cmd_download(args):
|
||||
os.makedirs(DOWNLOADS_DIR, exist_ok=True)
|
||||
templates = fetch_template_list()
|
||||
|
||||
if not templates:
|
||||
print("No templates found in the account.")
|
||||
return
|
||||
|
||||
# Specific template name requested
|
||||
if args.template_name:
|
||||
matches = [t for t in templates if t["name"] == args.template_name]
|
||||
if not matches:
|
||||
print(f"ERROR: No template named '{args.template_name}' found.")
|
||||
print("Run 'list' to see available templates.")
|
||||
sys.exit(1)
|
||||
if len(matches) > 1:
|
||||
print(f" {len(matches)} templates named '{args.template_name}' — using most recently modified.")
|
||||
target = max(matches, key=lambda t: t.get("modifiedDate", ""))
|
||||
download_one(target)
|
||||
return
|
||||
|
||||
# --all or default (no name given)
|
||||
print(f"Downloading all {len(templates)} template(s)...")
|
||||
for t in templates:
|
||||
download_one(t)
|
||||
print(f"\nAll templates downloaded to: {os.path.abspath(DOWNLOADS_DIR)}")
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Download Adobe Sign library templates",
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
epilog=__doc__,
|
||||
)
|
||||
subparsers = parser.add_subparsers(dest="command")
|
||||
|
||||
subparsers.add_parser("list", help="List all templates in the account")
|
||||
|
||||
dl_parser = subparsers.add_parser("download", help="Download templates")
|
||||
dl_parser.add_argument(
|
||||
"template_name", nargs="?", default=None,
|
||||
metavar="TEMPLATE_NAME",
|
||||
help="Name of template to download. Omit (or use --all) to download all.",
|
||||
)
|
||||
dl_parser.add_argument(
|
||||
"--all", dest="download_all", action="store_true",
|
||||
help="Download all templates (default when no name is given)",
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.command == "list":
|
||||
cmd_list(args)
|
||||
elif args.command == "download":
|
||||
cmd_download(args)
|
||||
else:
|
||||
parser.print_help()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Loading…
Reference in New Issue