← back to Rentv Sheet Enrich Refine

export_top.py

75 lines

#!/usr/bin/env python3
"""
Export the top-N warmest RENTV leads as a ready-to-work CSV.

Reads the local snapshot (data/snapshot.json — the same source the live console
serves) so it never burns a Sheets read, scores every unique contact with the
shared warmth.py scorer, sorts hottest-first, and writes a lean outreach sheet
with a 'Why Warm' reason column.

Usage:  python3 export_top.py [N] [outfile.csv]
        (defaults: N=200, outfile=rentv_top<N>_to_work.csv)
"""
import csv, json, os, sys
import warmth

HERE = os.path.dirname(os.path.abspath(__file__))
UNIQUE_GID = 3823360  # "Unique Contacts (all tabs)" — the deduped master

N = int(sys.argv[1]) if len(sys.argv) > 1 else 200
OUT = sys.argv[2] if len(sys.argv) > 2 else os.path.join(HERE, f"rentv_top{N}_to_work.csv")

snap = json.load(open(os.path.join(HERE, "data", "snapshot.json")))
tab = next(t for t in snap["tabs"] if t["gid"] == UNIQUE_GID)
H, rows = tab["headers"], tab["rows"]
idx = {h: i for i, h in enumerate(H)}


def cell(r, name):
    i = idx.get(name)
    return (str(r[i]).strip() if i is not None and i < len(r) and r[i] is not None else "")


def best_email(r):
    for f in ("Email", "Updated Email (found)", "Likely Email (inferred)"):
        v = cell(r, f)
        if v:
            return v
    return ""


def best_linkedin(r):
    return cell(r, "LinkedIn (Contact)") or cell(r, "LinkedIn (Company)")


scored = sorted(rows, key=lambda r: warmth.score(r, idx), reverse=True)

COLS = ["Rank", "Warmth", "Why Warm", "Contact Name", "Company/Venue", "Position",
        "Best Email", "Phone 1", "Phone 2", "Status", "Marketing/VP Name",
        "Marketing/VP Position", "LinkedIn", "Website", "Source Tabs", "# Appearances"]

written = 0
with open(OUT, "w", newline="") as f:
    w = csv.writer(f)
    w.writerow(COLS)
    for r in scored:
        sc = warmth.score(r, idx)
        # skip section/divider rows and anything with no real identity
        if cell(r, "Status (color)") == "Section / Category":
            continue
        if not (cell(r, "Contact Name") or cell(r, "Company/Venue")):
            continue
        written += 1
        w.writerow([
            written, sc, warmth.reason(r, idx),
            cell(r, "Contact Name"), cell(r, "Company/Venue"), cell(r, "Position"),
            best_email(r), cell(r, "Phone 1"), cell(r, "Phone 2"),
            cell(r, "Status (color)"), cell(r, "Marketing/VP Name"),
            cell(r, "Marketing/VP Position"), best_linkedin(r),
            cell(r, "Website"), cell(r, "Source Tabs"), cell(r, "# Appearances"),
        ])
        if written >= N:
            break

print(f"Wrote {written} leads -> {OUT}")