finance-telegram-bot/README.md

212 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Финансовый Telegram-бот
Аккуратный бот для повседневного учёта личных финансов. Расход записывается одной строкой — `467 ярче` или `3000 бензин`. Зарплата распознаётся по словам `зп` и `зарплата`, например `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`. Запись `-5000 рабочий закуп` уменьшит долг на `5000`, хотя останется расходом в финансовой аналитике.
Расчёт ведётся по операциям после установки исходной суммы:
- каждый расход увеличивает долг;
- каждый доход уменьшает долг;
- сумма со знаком `-` уменьшает долг независимо от категории; сама сумма хранится положительной;
- удаление ошибочной операции автоматически пересчитывает сумму;
- если доходы превысят долг, бот покажет разницу как семейный резерв;
- текущий долг или резерв отображается в подтверждениях, семейном чате и дневном отчёте.
Повторная установка текущей суммы начинает новый расчёт с указанного значения, не меняя историю доходов и расходов.
### Категории и подкатегории
В семейном бюджете доступна кнопка **«🗂 Категории»**. Категории общие для обоих супругов: каждый участник может добавить новую основную категорию или подкатегорию. При создании основной категории выбирается тип **«Расход»** или **«Доход»**; подкатегория наследует тип родителя. Перенос операции в категорию другого типа меняет её тип и влияние на долг.
При создании бюджета бот автоматически добавляет базовое дерево, например:
- Машина → Бензин, Ремонт, Запчасти, Мойка и парковка, Страховка;
- Продукты → Еда, Алкоголь, Кафе и рестораны, Бытовые товары;
- Развлечения → Кино и театр, Игры, Подписки, Хобби;
- Кредиты → Ипотека, Кредиты, Рассрочки;
- Ремонт → Материалы, Мебель, Работы, Инструменты.
Стандартные подкатегории определяются автоматически: запись `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`.