210 lines
14 KiB
Markdown
210 lines
14 KiB
Markdown
# Финансовый Telegram-бот
|
||
|
||
Аккуратный бот для повседневного учёта личных финансов. Расход записывается одной строкой — `467 ярче` или `3000 бензин`. Доход — через `+ 85000 зарплата` или `доход 5000 подработка`.
|
||
|
||
## Что уже работает
|
||
|
||
- автоматическое определение категорий: Продукты, Развлечения, Машина, Кредиты, Ремонт и Другое;
|
||
- доходы, расходы и точные суммы с копейками;
|
||
- изменение категории и удаление только что добавленной записи;
|
||
- итоги за текущий месяц и за всё время;
|
||
- аналитика по категориям с процентами и визуальными полосами — за месяц или всё время;
|
||
- последние 10 операций;
|
||
- ежедневный отчёт: траты и доходы за день плюс накопительный итог месяца;
|
||
- отдельные данные для каждого Telegram-пользователя;
|
||
- защищённый семейный бюджет для двух супругов с подтверждением владельца;
|
||
- мгновенные уведомления супругу и в подключённый семейный Telegram-чат;
|
||
- один общий вечерний отчёт в семейный чат;
|
||
- общий долг: доходы автоматически уменьшают его, расходы увеличивают;
|
||
- категории и подкатегории с возможностью добавлять собственные;
|
||
- SQLite в режиме WAL и защита от повторного дневного отчёта;
|
||
- готовый Docker-запуск на сервере.
|
||
|
||
## Развёртывание на сервере из GitHub
|
||
|
||
Ниже приведён готовый вариант для чистого сервера с Ubuntu 22.04/24.04 или Debian 12. Установщик сам поставит Docker и Docker Compose, запросит настройки и запустит бота с автоматическим перезапуском.
|
||
|
||
### 1. Подготовьте доступ к приватному репозиторию
|
||
|
||
Репозиторий приватный, поэтому серверу нужен SSH-ключ. На сервере выполните:
|
||
|
||
```bash
|
||
sudo apt update
|
||
sudo apt install -y git openssh-client
|
||
ssh-keygen -t ed25519 -C "finance-bot-server"
|
||
cat ~/.ssh/id_ed25519.pub
|
||
```
|
||
|
||
При создании ключа можно нажимать `Enter`, оставляя предлагаемые значения. Скопируйте строку, которую показала последняя команда. Откройте репозиторий в GitHub и добавьте ключ: **Settings → Deploy keys → Add deploy key**. Галочку **Allow write access** не включайте — серверу достаточно доступа на чтение только к этому репозиторию.
|
||
|
||
Проверьте подключение:
|
||
|
||
```bash
|
||
ssh -T git@github.com
|
||
```
|
||
|
||
При первом подключении ответьте `yes`. Сообщение GitHub об успешной аутентификации означает, что доступ настроен.
|
||
|
||
### 2. Скачайте и установите бота
|
||
|
||
```bash
|
||
cd ~
|
||
git clone git@github.com:ochenstarik-ui/finance-telegram-bot.git
|
||
cd finance-telegram-bot
|
||
sudo bash install.sh
|
||
```
|
||
|
||
Во время установки будут запрошены:
|
||
|
||
- папка установки — обычно достаточно нажать `Enter`, чтобы использовать `/opt/finance-bot`;
|
||
- токен бота, полученный у [@BotFather](https://t.me/BotFather);
|
||
- часовой пояс — по умолчанию `Asia/Novosibirsk`;
|
||
- время ежедневного отчёта — по умолчанию `21:00`;
|
||
- разрешение установить Docker, если его ещё нет.
|
||
|
||
Токен при вводе не отображается. Настройки сохраняются в `/opt/finance-bot/.env` с доступом только для root, а база данных — в постоянном Docker-томе.
|
||
|
||
### 3. Проверьте запуск
|
||
|
||
```bash
|
||
sudo docker compose -f /opt/finance-bot/compose.yaml ps
|
||
sudo docker compose -f /opt/finance-bot/compose.yaml logs --tail=100 finance-bot
|
||
```
|
||
|
||
Для просмотра журнала в реальном времени:
|
||
|
||
```bash
|
||
sudo docker compose -f /opt/finance-bot/compose.yaml logs -f finance-bot
|
||
```
|
||
|
||
Выход из просмотра журнала — `Ctrl+C`; бот при этом продолжит работать.
|
||
|
||
### Обновление до новой версии
|
||
|
||
После появления изменений в GitHub выполните:
|
||
|
||
```bash
|
||
cd ~/finance-telegram-bot
|
||
git pull --ff-only
|
||
sudo bash install.sh
|
||
```
|
||
|
||
Установщик предложит сохранить прежний токен. Повторное развёртывание пересоберёт контейнер, но не удалит `.env`, операции и настройки из базы данных.
|
||
|
||
### Управление ботом
|
||
|
||
```bash
|
||
# Перезапустить
|
||
sudo docker compose -f /opt/finance-bot/compose.yaml restart finance-bot
|
||
|
||
# Остановить
|
||
sudo docker compose -f /opt/finance-bot/compose.yaml stop finance-bot
|
||
|
||
# Запустить после остановки
|
||
sudo docker compose -f /opt/finance-bot/compose.yaml start finance-bot
|
||
```
|
||
|
||
Если `install.sh` запустить отдельно, без остальных файлов проекта рядом, он по-прежнему сможет загрузить резервную копию с Яндекс.Диска.
|
||
|
||
## Ручной запуск на сервере
|
||
|
||
Понадобятся Docker и Docker Compose.
|
||
|
||
1. Создайте бота через [@BotFather](https://t.me/BotFather) и скопируйте токен.
|
||
2. На сервере скопируйте `.env.example` в `.env`.
|
||
3. В `.env` замените `BOT_TOKEN`, при необходимости настройте таймзону и время отчёта.
|
||
4. Запустите контейнер:
|
||
|
||
```bash
|
||
docker compose up -d --build
|
||
```
|
||
|
||
Посмотреть состояние и журнал:
|
||
|
||
```bash
|
||
docker compose ps
|
||
docker compose logs -f finance-bot
|
||
```
|
||
|
||
Данные сохраняются в Docker-томе `finance-data` и не исчезают при пересборке контейнера.
|
||
|
||
## Настройки
|
||
|
||
| Переменная | Пример | Назначение |
|
||
|---|---|---|
|
||
| `BOT_TOKEN` | `123:ABC...` | токен от BotFather |
|
||
| `BOT_TIMEZONE` | `Asia/Novosibirsk` | таймзона операций и отчётов |
|
||
| `DAILY_REPORT_TIME` | `21:00` | локальное время дневного отчёта |
|
||
| `DATABASE_PATH` | `/app/data/finance.db` | путь к SQLite |
|
||
| `LOG_LEVEL` | `INFO` | уровень журналирования |
|
||
|
||
## Семейный бюджет и общий чат
|
||
|
||
1. Первый супруг открывает кнопку **«Семья»** и выбирает **«Создать общий бюджет»**.
|
||
2. Второй супруг запускает этого же бота, открывает **«Семья»**, нажимает **«Ввести код супруга»** и отправляет полученный код.
|
||
3. Код не даёт доступ автоматически: создатель бюджета получает запрос с кнопками **«Подтвердить»** и **«Отклонить»**.
|
||
4. После подтверждения итоги, аналитика и история становятся общими. Новые записи мгновенно отправляются второму супругу.
|
||
5. Для общего журнала создайте Telegram-группу, добавьте туда бота. Создатель семейного бюджета должен быть администратором этой группы и отправить в ней команду `/family_chat`.
|
||
|
||
После привязки каждая новая операция обоих супругов дублируется в группу. В заданное время туда также приходит один общий дневной отчёт. Посторонний человек не сможет подключиться только по коду: требуется ручное подтверждение владельца, семейный бюджет ограничен двумя участниками, а привязать групповой чат может только создатель бюджета, являющийся его администратором.
|
||
|
||
### Общий долг
|
||
|
||
После создания семейного бюджета откройте кнопку **«💳 Общий долг»** и укажите текущую сумму. Сделать это может только создатель бюджета, второй супруг видит результат.
|
||
|
||
Например, исходный долг составляет `530713`. После записи `+ 400000 зарплата` бот покажет долг `130713`. Следующая запись `5000 продукты` увеличит его до `135713`.
|
||
|
||
Расчёт ведётся по операциям после установки исходной суммы:
|
||
|
||
- каждый расход увеличивает долг;
|
||
- каждый доход уменьшает долг;
|
||
- удаление ошибочной операции автоматически пересчитывает сумму;
|
||
- если доходы превысят долг, бот покажет разницу как семейный резерв;
|
||
- текущий долг или резерв отображается в подтверждениях, семейном чате и дневном отчёте.
|
||
|
||
Повторная установка текущей суммы начинает новый расчёт с указанного значения, не меняя историю доходов и расходов.
|
||
|
||
### Категории и подкатегории
|
||
|
||
В семейном бюджете доступна кнопка **«🗂 Категории»**. Категории общие для обоих супругов: каждый участник может добавить новую основную категорию или подкатегорию.
|
||
|
||
При создании бюджета бот автоматически добавляет базовое дерево, например:
|
||
|
||
- Машина → Бензин, Ремонт, Запчасти, Мойка и парковка, Страховка;
|
||
- Продукты → Еда, Алкоголь, Кафе и рестораны, Бытовые товары;
|
||
- Развлечения → Кино и театр, Игры, Подписки, Хобби;
|
||
- Кредиты → Ипотека, Кредиты, Рассрочки;
|
||
- Ремонт → Материалы, Мебель, Работы, Инструменты.
|
||
|
||
Стандартные подкатегории определяются автоматически: запись `3000 бензин` попадёт в **Машина → Бензин**, а `500 пиво` — в **Продукты → Алкоголь**.
|
||
|
||
Чтобы создать свою структуру, нажмите **«🗂 Категории»**, затем **«Добавить категорию»** или **«Добавить подкатегорию»**. Новые пользовательские категории выбираются вручную при изменении записи.
|
||
|
||
После добавления расхода нажмите **«Изменить категорию»**. Можно выбрать как основную категорию, так и любую подкатегорию. Это работает и для записей, которые первоначально попали в **«Другое»**. Изменить категорию может только автор операции; супруг и семейный чат сразу получают уведомление о переносе.
|
||
|
||
## Локальная разработка
|
||
|
||
Нужен Python 3.11 или новее.
|
||
|
||
```bash
|
||
python -m venv .venv
|
||
source .venv/bin/activate # Windows: .venv\Scripts\activate
|
||
pip install -e ".[dev]"
|
||
cp .env.example .env # Windows: copy .env.example .env
|
||
```
|
||
|
||
Переменные из `.env` нужно загрузить в окружение, затем запустить:
|
||
|
||
```bash
|
||
python -m app
|
||
```
|
||
|
||
Тесты:
|
||
|
||
```bash
|
||
pytest
|
||
```
|
||
|
||
## Как расширять категории
|
||
|
||
Названия, иконки и ключевые слова находятся в `app/categories.py`. Новые ключевые слова можно добавлять без изменения базы данных. Суммы хранятся целым числом копеек, поэтому арифметика не накапливает ошибки `float`.
|