#!/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()