81 lines
2.6 KiB
Python
81 lines
2.6 KiB
Python
# 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()
|