Files
2026-10-19 09:41:32 +03:00

96 lines
3.7 KiB
Python

"""`kadence` — run the server, or poke it from a terminal/cron."""
from __future__ import annotations
import argparse
import getpass
import json
from datetime import date
from app.db import init_db, session_scope
from app.services import report, settings_service, stats, tasks_service
from app.timeutil import local_date
def main() -> int:
parser = argparse.ArgumentParser(prog="kadence")
sub = parser.add_subparsers(dest="command", required=True)
serve = sub.add_parser("serve", help="run the API (and the web UI)")
serve.add_argument("--host", default="0.0.0.0")
serve.add_argument("--port", type=int, default=8000)
serve.add_argument("--reload", action="store_true")
sub.add_parser("refresh", help="pull every todo source once")
sub.add_parser("briefing", help="send the morning briefing now")
report_cmd = sub.add_parser("report", help="build and send today's report")
report_cmd.add_argument("--date", type=date.fromisoformat, default=None)
report_cmd.add_argument("--print", action="store_true", help="print, do not send")
sub.add_parser("stats", help="print a summary as JSON")
setpw = sub.add_parser("set-password", help="set or replace the web login password")
setpw.add_argument("--username", default=None, help="defaults to the current one")
args = parser.parse_args()
if args.command == "serve":
import uvicorn
uvicorn.run("app.main:app", host=args.host, port=args.port, reload=args.reload)
return 0
init_db()
with session_scope() as session:
settings = settings_service.load_settings(session)
if args.command == "refresh":
print(json.dumps(tasks_service.refresh_tasks(session, settings), indent=2))
elif args.command == "briefing":
from app.services.notify import notify
text = report.render_morning_briefing(session, settings)
print(text)
print([d.as_dict() for d in notify(settings, text, urgent=True)])
elif args.command == "report":
day = args.date or local_date(settings.timezone)
if args.print:
_, payload = report.get_or_build_daily(session, settings, day, rebuild=True)
print(report.render_daily_telegram(payload, settings))
else:
result = report.send_daily(session, settings, day, force=True)
print(result.get("text", ""))
print([d for d in result.get("deliveries", [])])
elif args.command == "stats":
today = local_date(settings.timezone)
print(
json.dumps(
{
"today": stats.day_metrics(session, settings, today),
"streak": stats.streak(session, settings),
"lifetime": stats.lifetime(session, settings),
},
indent=2,
ensure_ascii=False,
)
)
elif args.command == "set-password":
from app.services import auth_service
password = getpass.getpass("New web login password: ")
if password != getpass.getpass("Confirm: "):
print("Passwords did not match.")
return 1
if len(password) < 8:
print("Use at least 8 characters.")
return 1
if args.username:
settings.auth.username = args.username
settings.auth.password_hash = auth_service.hash_password(password)
settings_service.save_settings(session, settings)
print(f"Password set for {settings.auth.username!r}.")
return 0
if __name__ == "__main__": # pragma: no cover
raise SystemExit(main())