I recently built a personal finance tool that lets me log expenses via Telegram, automatically categorizes them, and records everything in Google Sheets.
The goal? Make budgeting fast, private, and mobile-friendly — even from a Raspberry Pi.
This post explains how to reproduce it, what I learned, and where it got interesting.
What I Built
A Telegram bot that lets me send messages like:
groceries 12.50
uber 8.90
coffee -4.00
The bot:
- Parses the text and categorizes the expense
- Applies budget tracking with alerts if I’m close to my monthly limit
- Logs the expense into a Google Sheet using a service account
- Runs on a Raspberry Pi using Docker
Technologies Used
- Python + python-telegram-bot (v20)
- Google Sheets API via service accounts
- Docker (with ARM build for Raspberry Pi)
- Poetry for Python dependency management
- YAML configs for budgets, users, and categories
- Makefile for workflow automation
How to Reproduce It
- Create a Telegram bot with @BotFather
- Generate a Google service account and share a Sheet with it
- Configure your categories and budget limits in
budgets.yaml
- Whitelist Telegram user IDs in
users.yaml
- Mount the secrets into Docker using bind volumes
- Run it on a Raspberry Pi (with a lightweight ARM-compatible image)
Interesting Challenges
Dynamic Configuration Reloading
I wanted to update users.yaml
without restarting the bot. To do that:
- I implemented an in-memory cache with a TTL
- It reloads configs every few seconds if the file changes
- Updates deployable via
make deploy-users
over SSH
Smart Expense Parsing
- Messages like
"food -3.50"
are parsed with regex - I used word-boundary matching to avoid false positives (e.g., “car” in “carbonara”)
- Negative values allow for reimbursements
Secret Management in Docker
- Rather than baking credentials into the image, I mounted them at runtime
- Paths are resolved dynamically based on the
users.yaml
file location - This made it secure and flexible across environments
Custom Budgets Per User
- Each user can define their own monthly budgets per category
- If none is defined, the app falls back to the shared config
- Budget overages trigger alerts at 25%, 50%, and 75%
Local vs. Docker Consistency
I ensured:
- All paths in
users.yaml
are relative and resolved based on file location - The same
users.yaml
works in local dev and in Docker on the Pi - Deployment is as easy as:
make build-arm && make deploy && make run-on-pi
Ideas for the Future
- Zero-shot category classification using AI instead of static keywords
- Multi-user dashboards with shared budgets
- Voice input or receipt photo parsing
TL;DR
I built a Telegram bot that logs categorized expenses into Google Sheets, tracks budgets, and runs on a Raspberry Pi — using clean Python, YAML configs, and Docker. It was a great blend of DevOps, API integration, and practical problem-solving.