Ryanhub - file viewer
filename: scripts/new_contact.py
branch: main
back to repo
#!/usr/bin/env python3
"""Create a contact markdown file with the next available ID."""

from __future__ import annotations

import argparse
import sys
from pathlib import Path

sys.path.insert(0, str(Path(__file__).resolve().parent))

from common import (  # noqa: E402
    CONTACTS_DIR,
    CONTACT_STATUSES,
    CONFIDENCE_VALUES,
    load_entities,
    next_id,
    normalize_name,
    run_sync_indexes,
    slugify,
    today_str,
    write_markdown,
    find_company_by_name,
    parse_frontmatter,
    REPO_ROOT,
    die,
)


def build_body(name: str) -> str:
    return "\n".join(
        [
            f"# {name}",
            "",
            "# Context",
            "",
            "# Message ideas",
            "",
            "# History",
            "",
        ]
    )


def ensure_company(company_name: str) -> str:
    existing = find_company_by_name(company_name)
    if existing:
        _, meta, _ = existing
        return str(meta["id"])

    from new_company import main as new_company_main

    argv = ["new_company.py", "--name", company_name]
    old_argv = sys.argv
    try:
        sys.argv = argv
        new_company_main()
    finally:
        sys.argv = old_argv

    created = find_company_by_name(company_name)
    if not created:
        die(f"Failed to create company: {company_name}")
    _, meta, _ = created
    return str(meta["id"])


def add_contact_to_company(company_id: str, contact_id: str) -> None:
    for path in CONTACTS_DIR.parent.joinpath("companies").glob("*.md"):
        meta, body = parse_frontmatter(path)
        if meta.get("id") != company_id:
            continue
        contacts = list(meta.get("contacts") or [])
        if contact_id not in contacts:
            contacts.append(contact_id)
            meta["contacts"] = contacts
            meta["date_updated"] = today_str()
            write_markdown(path, meta, body)
        return


def duplicate_contact(name: str, company: str) -> bool:
    target_name = normalize_name(name)
    target_company = normalize_name(company)
    for path in CONTACTS_DIR.glob("*.md"):
        if path.name.startswith("_"):
            continue
        meta, _ = parse_frontmatter(path)
        if (
            normalize_name(str(meta.get("name", ""))) == target_name
            and normalize_name(str(meta.get("company", ""))) == target_company
        ):
            return True
    return False


def main() -> None:
    parser = argparse.ArgumentParser(description="Create a new contact file.")
    parser.add_argument("--name", required=True, help="Contact name")
    parser.add_argument("--company", required=True, help="Company name")
    parser.add_argument("--role", default="", help="Contact role")
    parser.add_argument("--linkedin-url", default="", help="LinkedIn profile URL")
    parser.add_argument("--x-url", default="", help="X/Twitter profile URL")
    parser.add_argument("--github-url", default="", help="GitHub profile URL")
    parser.add_argument("--website", default="", help="Personal website")
    parser.add_argument("--email", default="", help="Email address")
    parser.add_argument("--source", default="", help="Where contact was found")
    parser.add_argument(
        "--status",
        default="found",
        choices=sorted(CONTACT_STATUSES),
        help="Contact status",
    )
    parser.add_argument(
        "--confidence",
        default="unknown",
        choices=sorted(CONFIDENCE_VALUES),
        help="Contact confidence",
    )
    parser.add_argument(
        "--force",
        action="store_true",
        help="Allow duplicate name + company pairs",
    )
    args = parser.parse_args()

    if duplicate_contact(args.name, args.company) and not args.force:
        die(
            f"Likely duplicate contact: {args.name} at {args.company}. "
            "Use --force to create anyway."
        )

    company_id = ensure_company(args.company)
    contacts = load_entities(CONTACTS_DIR)
    contact_id = next_id("C", 4, contacts)
    slug = slugify(args.name)
    path = CONTACTS_DIR / f"{contact_id}-{slug}.md"
    if path.exists():
        die(f"File already exists: {path}")

    today = today_str()
    meta = {
        "id": contact_id,
        "name": args.name,
        "company": args.company,
        "company_id": company_id,
        "role": args.role,
        "linkedin_url": args.linkedin_url,
        "x_url": args.x_url,
        "github_url": args.github_url,
        "website": args.website,
        "email": args.email,
        "source": args.source,
        "confidence": args.confidence,
        "status": args.status,
        "date_found": today,
        "date_updated": today,
        "related_leads": [],
        "last_contacted": "",
        "next_followup": "",
        "notes": "",
    }
    write_markdown(path, meta, build_body(args.name))
    add_contact_to_company(company_id, contact_id)
    print(f"Created {path.relative_to(REPO_ROOT)}")
    run_sync_indexes()


if __name__ == "__main__":
    main()