Files
troupe-standup/wizard-work/sol/classify-messages.py
T

96 lines
2.6 KiB
Python

#!/usr/bin/env python3
"""Classify a directory of raw message files into triage lanes.
Usage:
classify-messages.py INBOX_DIR OUT_JSON OUT_TSV
Rule (deterministic, checked in priority order, case-insensitive against
subject + body):
ops -> cron, deploy, disk, backup, server, fail, uptime
finance-> invoice, payment, expense, salary, bitcoin, fee
person -> alexander, sol, wizard, troupe, meeting, alex
other -> default
Exit code IS the verdict: 0 = every message classified and counts written,
nonzero = anything malformed.
"""
import json
import sys
from pathlib import Path
LANES = [
("ops", ["cron", "deploy", "disk", "backup", "server", "fail", "uptime"]),
("finance", ["invoice", "payment", "expense", "salary", "bitcoin", "fee"]),
("person", ["alexander", "sol", "wizard", "troupe", "meeting", "alex"]),
]
ORDER = ["ops", "finance", "person", "other"]
def classify(subject: str, body: str) -> str:
text = f"{subject} {body}".lower()
for lane, kws in LANES:
if any(kw in text for kw in kws):
return lane
return "other"
def read_messages(inbox: Path):
items = []
for path in sorted(inbox.glob("*.txt")):
subject, body = "", ""
for raw in path.read_text(encoding="utf-8").splitlines():
if raw.startswith("subject:"):
subject = raw.split(":", 1)[1].strip()
elif raw.startswith("body:"):
body = raw.split(":", 1)[1].strip()
elif raw == "":
continue
else:
body += " " + raw
items.append({"file": path.name, "subject": subject, "body": body})
return items
def main(argv):
inbox = Path(argv[1])
out_json = Path(argv[2])
out_tsv = Path(argv[3])
items = read_messages(inbox)
for it in items:
it["lane"] = classify(it["subject"], it["body"])
counts = {lane: 0 for lane in ORDER}
for it in items:
counts[it["lane"]] += 1
out_json.write_text(
json.dumps(
{
"tool": "classify-messages.py",
"inbox": str(inbox),
"total": len(items),
"counts": counts,
"lanes": ORDER,
"items": [
{"file": i["file"], "lane": i["lane"]} for i in items
],
},
indent=2,
),
encoding="utf-8",
)
with out_tsv.open("w", encoding="utf-8") as fh:
fh.write("file\tlane\n")
for it in items:
fh.write(f"{it['file']}\t{it['lane']}\n")
return 0
if __name__ == "__main__":
sys.exit(main(sys.argv))