Files
please-pay-me/README.md
T
2026-09-21 04:06:43 +03:00

142 lines
5.2 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.
# Please Pay Me Bot
Telegram-бот + web-кабинет для жизни «от зарплаты до зарплаты».
**Стек сейчас:** Telegram bot (Python) · **API ASP.NET Core + PostgreSQL** (`src/PleasePayMe.*`) · React web.
Python-папка `api/` устарела; HTTP-контракт `/api/...` для бота и web сохранён.
## Возможности
- Задать бюджет: сумма + дата до зарплаты
- Пересчёт дневного лимита по остатку и числу дней
- Быстрый ввод трат: `250`, `250 кофе`, `кофе 250`
- Статус / траты за сегодня / отмена последней траты
- Кнопки внизу чата для частых действий
## Логика лимита
```
остаток = бюджет − все траты периода
дней_осталось = (дата_конца − сегодня) + 1 # включая сегодня
остаток_на_утро = остаток + траты_сегодня
лимит_на_день = остаток_на_утро / дней_осталось
можно_сегодня = лимит_на_день − траты_сегодня
```
Лимит дня не сжимается от каждой траты внутри дня (модель «утреннего конверта»). Если сегодня вылез из лимита — завтра лимит пересчитается по новому остатку.
## Быстрый старт
1. Создай бота у [@BotFather](https://t.me/BotFather), скопируй токен.
2. Установи зависимости:
```bash
python -m venv .venv
# Windows Git Bash / Linux:
source .venv/Scripts/activate # или .venv/bin/activate
pip install -r requirements.txt
```
3. Создай `.env` из примера:
```bash
cp .env.example .env
# пропиши BOT_TOKEN=...
```
4. Запуск:
```bash
python -m bot.main
```
## Команды
| Команда / кнопка | Действие |
|---|---|
| `/budget` | Новый бюджет (сумма → дата) |
| `/status` | Лимит и остаток |
| `/today` | Список трат за сегодня |
| `/history` | Траты за период бюджета (постранично) |
| `/day 12.09` | Список трат за дату |
| `/spend` | Диалог: трата за другую дату |
| `/undo` | Удалить последнюю трату |
| `/help` | Справка |
Трата за дату одним сообщением: `за 12.09 250 кофе`, `12.09 250`, `250 кофе 12.09`.
Данные хранятся локально в SQLite: `data/budget.db`.
## Web-кабинет (личный, через Telegram)
Вход через [Telegram Login Widget](https://core.telegram.org/widgets/login). После входа пользователь видит **только свой** бюджет и траты (`/api/me/...`).
### Настройка BotFather
1. `/setdomain` → укажи домен, с которого открывается кабинет (нужен публичный HTTPS; чистый `localhost` обычно не работает).
2. Username бота без `@` положи в `.env` как `TELEGRAM_BOT_USERNAME`.
### API
| Метод | Путь | Auth | Описание |
|---|---|---|---|
| POST | `/api/auth/telegram` | — | обмен данных Login Widget на JWT |
| GET | `/api/me` | Bearer JWT | профиль |
| GET | `/api/me/budget` | Bearer JWT | свой бюджет |
| GET | `/api/me/expenses` | Bearer JWT | свои траты |
| GET | `/api/budgets`… | `API_TOKEN` | админский список (опционально) |
### Docker
```env
BOT_TOKEN=...
TELEGRAM_BOT_USERNAME=MyPayBot
PROXY_URL=socks5://127.0.0.1:10808
```
```bash
docker compose up -d --build
```
- кабинет: http://HOST:51290
- API: http://HOST:51291
## Docker
```bash
docker build -t please-pay-me-bot .
docker run --rm -e BOT_TOKEN=your_token -v "$(pwd)/data:/app/data" please-pay-me-bot
```
На Windows (PowerShell):
```powershell
docker build -t please-pay-me-bot .
docker run --rm -e BOT_TOKEN=your_token -v ${PWD}/data:/app/data please-pay-me-bot
```
Том `data` сохраняет SQLite между перезапусками.
### Прокси (Xray на хосте + бот в Docker)
**Рекомендуемый способ:** `network_mode: host` — контейнер видит `127.0.0.1` хоста, Xray можно оставить на loopback.
В `.env` (токен только здесь, не в compose):
```env
BOT_TOKEN=...
PROXY_URL=socks5://127.0.0.1:10808
```
```bash
docker compose up -d --build
```
Проверка на хосте:
```bash
curl -x socks5h://127.0.0.1:10808 https://api.telegram.org
```
Если без `host` сети (bridge): Xray должен слушать `0.0.0.0`, а в `PROXY_URL` — gateway хоста (`172.17.0.1` или `host.docker.internal`). Скрипт: `./scripts/open_xray_listen.sh`. У Portainer custom-сеть часто **не** имеет маршрута к `172.17.0.1`, из‑за этого был timeout.