Snapshot: full project state
This commit is contained in:
80
autopilot.py
Normal file
80
autopilot.py
Normal file
@@ -0,0 +1,80 @@
|
||||
# Procyon — autopilot. Scheduled discover -> enrich -> score -> auto-prepare top N.
|
||||
# Everything up to the human approval/send gate. Never sends without approval.
|
||||
|
||||
import os
|
||||
|
||||
import db
|
||||
import scraper
|
||||
import tailor
|
||||
import pipeline
|
||||
import emailer
|
||||
|
||||
BASE = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
|
||||
def run():
|
||||
db.init_db()
|
||||
if db.get_setting('autopilot_enabled', '1') != '1':
|
||||
print('autopilot disabled')
|
||||
return
|
||||
|
||||
# 1. discover
|
||||
try:
|
||||
added = scraper.discover()
|
||||
except Exception as e:
|
||||
added = 0
|
||||
print(f'discover error: {e}')
|
||||
print(f'discovered {added} new job(s)')
|
||||
|
||||
# 2. enrich thin descriptions (firecrawl scrape / http fetch)
|
||||
new_jobs = db.list_jobs(status='new', limit=200)
|
||||
enriched = 0
|
||||
for j in new_jobs:
|
||||
desc = j.get('description') or ''
|
||||
if len(desc) < 200 and j.get('url'):
|
||||
try:
|
||||
full = scraper.enrich_description(j['url'])
|
||||
if full and len(full) > len(desc):
|
||||
conn = db.get_conn()
|
||||
try:
|
||||
conn.execute('UPDATE jobs SET description = ? WHERE id = ?',
|
||||
(full[:5000], j['id']))
|
||||
conn.commit()
|
||||
finally:
|
||||
conn.close()
|
||||
enriched += 1
|
||||
except Exception:
|
||||
pass
|
||||
print(f'enriched {enriched} job description(s)')
|
||||
|
||||
# 3. score all 'new' jobs
|
||||
new_jobs = db.list_jobs(status='new', limit=200)
|
||||
scored = []
|
||||
for j in new_jobs:
|
||||
s, o = tailor.score_job(j)
|
||||
db.update_job_score(j['id'], s, o)
|
||||
scored.append((j['id'], s))
|
||||
print(f'scored {len(scored)} job(s)')
|
||||
|
||||
# 4. auto-prepare the top N (tailor + audit + PDF) — queued for your approval
|
||||
max_prepare = int(db.get_setting('autopilot_max_prepare', '3'))
|
||||
top = sorted(scored, key=lambda x: -x[1])[:max_prepare]
|
||||
prepared = 0
|
||||
for jid, s in top:
|
||||
job = db.get_job(jid)
|
||||
if not job:
|
||||
continue
|
||||
try:
|
||||
aid = pipeline.prepare(job)
|
||||
print(f'prepared app #{aid} for "{job["title"]}" (fit {s})')
|
||||
prepared += 1
|
||||
if db.get_setting('auto_send', '0') == '1':
|
||||
sent, msg = emailer.auto_send(aid)
|
||||
print(f' auto-send: {msg}' if sent else f' auto-send skipped: {msg}')
|
||||
except Exception as e:
|
||||
print(f'prepare failed for {job["title"]}: {e}')
|
||||
print(f'AUTOPILOT_DONE: {added} discovered, {len(scored)} scored, {prepared} prepared')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
run()
|
||||
Reference in New Issue
Block a user