"""Onboarding, help and diagnostics. Registered last so /help sees everything."""
from __future__ import annotations
from typing import Sequence
from .. import render
from ..analytics import month_bounds
from .base import BotContext, CommandSpec, Reply, SimpleFeature
_WELCOME = """Hello ๐
Just tell me what you spent and I'll keep track.
Log it
250 coffee
โน1,240 groceries at bigbasket
45.50 lunch yesterday
320 uber #transport
Send me things
๐ท a receipt photo โ I'll read the total
๐ a bank statement (PDF, CSV, XLSX) โ I'll pull out the transactions and ask before saving
See it back
/today ยท /week ยท /month ยท /recurring ยท /advice
/help for everything."""
class CoreFeature(SimpleFeature):
name = "core"
description = "โ๏ธ General"
priority = 90
def commands(self) -> Sequence[CommandSpec]:
return (
CommandSpec("start", "What this bot does"),
CommandSpec("help", "All commands"),
CommandSpec("status", "Configuration and storage health"),
CommandSpec("whoami", "Your Telegram user ID", hidden=True),
)
def cmd_start(self, ctx: BotContext) -> Reply:
return Reply(_WELCOME)
def cmd_help(self, ctx: BotContext) -> Reply:
body = ctx.services.registry.help_text()
tail = (
"\n\nPlain text with a number is logged as an expense. "
"Add #category to override the guess."
)
return Reply(body + tail)
def cmd_whoami(self, ctx: BotContext) -> Reply:
return Reply(f"Your Telegram user ID is {ctx.user_id}.")
def cmd_status(self, ctx: BotContext) -> Reply:
settings = ctx.settings
store = ctx.store
start, _ = month_bounds(ctx.today)
month_count = len(ctx.store.list_expenses(ctx.user_id, start, ctx.today))
lines = [
"Status",
f"Transactions logged: {store.count(ctx.user_id)} ({month_count} this month)",
f"Today (in {render.escape(settings.timezone)}): {ctx.today.isoformat()}",
"",
"Inference",
]
llm = ctx.services.llm
if llm.enabled:
lines.append(f"โ
{render.escape(llm.describe())}")
else:
lines.append(f"โ ๏ธ {render.escape(llm.describe())}")
lines.append(" Receipts, statements and written advice are off.")
lines.append(" Typed expenses, summaries and budgets still work.")
lines.append("")
lines.append("Access")
if settings.open_access:
cap = settings.uploads_per_user_per_day
lines.append("๐ Open โ anyone on Telegram can use this bot.")
lines.append(" Each person's ledger is separate; nobody sees yours.")
lines.append(
f" Uploads capped at {cap}/user/day."
if cap > 0
else " โ ๏ธ Uploads uncapped โ strangers can spend your inference credits."
)
else:
lines.append(f"๐ Allowlist โ {len(settings.allowed_user_ids)} user(s).")
lines.append("")
lines.append("Storage")
if settings.sync_enabled:
lines.append(f"โ
{render.escape(store.sync_status)}")
else:
lines.append(
"๐ด Local only โ Space disk is ephemeral.\n"
" Your data will be lost on the next restart or sleep.\n"
" Set HF_DATASET_REPO to fix this."
)
if gaps := settings.missing_required():
lines.append("")
lines.append("Not configured")
lines.extend(f"โข {render.escape(gap)}" for gap in gaps)
return Reply("\n".join(lines))