Repository navigation
Expand file tree
/
Copy pathmain.py
More file actions
89 lines (67 loc) · 2.6 KB
/
Copy pathmain.py
File metadata and controls
89 lines (67 loc) · 2.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#!/usr/bin/env python3
"""
Substack Engagement Agent — headless CLI.
Fetches your live Notes feed, scores each note for relevance, drafts reply
angles, and writes scored_notes.json (the same file the UI reads).
Usage:
python main.py # fetch + score, write scored_notes.json
python main.py --check # just verify the session cookie is still valid
For the interactive UI (meter, digest, refresh button) run serve.py instead.
"""
import os
import sys
import json
import argparse
from dotenv import load_dotenv
load_dotenv()
def check_env():
if not os.environ.get("SUBSTACK_SESSION_COOKIE"):
print("Missing SUBSTACK_SESSION_COOKIE in .env")
print("Copy .env.example to .env and fill in the values.")
sys.exit(1)
from scorer import is_llm_available, BASE_URL
if not is_llm_available():
print(f"Local LLM not reachable at {BASE_URL}")
print("Start the LM Studio server and load a model, then retry.")
sys.exit(1)
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--check", action="store_true", help="Verify the session cookie")
args = parser.parse_args()
from scraper import fetch_notes_feed, is_session_valid
cookie = os.environ.get("SUBSTACK_SESSION_COOKIE", "")
if args.check:
if not cookie:
print("✗ SUBSTACK_SESSION_COOKIE not set in .env")
sys.exit(1)
if is_session_valid(cookie):
print("✓ Session cookie is valid")
else:
print("✗ Session expired — grab a fresh substack.sid from DevTools")
sys.exit(1)
return
check_env()
if not is_session_valid(cookie):
print("✗ Session expired — grab a fresh substack.sid from DevTools and update .env")
sys.exit(1)
from scorer import score_and_draft
print("Fetching Notes feed…")
notes = fetch_notes_feed(cookie, limit=80)
print(f"Fetched {len(notes)} notes. Scoring…")
scored = score_and_draft(notes)
hv = [n for n in scored if n.get("opportunity_type") == "high_visibility"]
peers = [n for n in scored if n.get("opportunity_type") == "peer"]
import datetime
from profile import TOPIC_TAGS
out = {
"high_visibility": hv[:8],
"peers": peers[:8],
"all": scored,
"topic_vocab": TOPIC_TAGS,
"generated_at": datetime.datetime.now().isoformat(timespec="seconds"),
}
with open("scored_notes.json", "w") as f:
json.dump(out, f, indent=2)
print(f"Wrote scored_notes.json — {len(hv)} high-visibility, {len(peers)} peers")
if __name__ == "__main__":
main()