Oracle / finbot /features /core.py
spacedout-bits's picture
Run a local model on ZeroGPU instead of paid inference
ad4bf51 verified
Raw History Blame Contribute Delete
3.89 kB
"""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 = """<b>Hello πŸ‘‹</b>
Just tell me what you spent and I'll keep track.
<b>Log it</b>
<code>250 coffee</code>
<code>β‚Ή1,240 groceries at bigbasket</code>
<code>45.50 lunch yesterday</code>
<code>320 uber #transport</code>
<b>Send me things</b>
πŸ“· a receipt photo β€” I'll read the total
πŸ“„ a bank statement (PDF, CSV, XLSX) β€” I'll pull out the transactions and ask before saving
<b>See it back</b>
/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\n<i>Plain text with a number is logged as an expense. "
"Add #category to override the guess.</i>"
)
return Reply(body + tail)
def cmd_whoami(self, ctx: BotContext) -> Reply:
return Reply(f"Your Telegram user ID is <code>{ctx.user_id}</code>.")
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 = [
"<b>Status</b>",
f"Transactions logged: {store.count(ctx.user_id)} ({month_count} this month)",
f"Today (in {render.escape(settings.timezone)}): {ctx.today.isoformat()}",
"",
"<b>Inference</b>",
]
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("<b>Access</b>")
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("<b>Storage</b>")
if settings.sync_enabled:
lines.append(f"βœ… {render.escape(store.sync_status)}")
else:
lines.append(
"πŸ”΄ <b>Local only β€” Space disk is ephemeral.</b>\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("<b>Not configured</b>")
lines.extend(f"β€’ {render.escape(gap)}" for gap in gaps)
return Reply("\n".join(lines))