feat(proj): init

This commit is contained in:
vl.arkhangelskii
2026-09-21 04:06:43 +03:00
commit c956b94983
1076 changed files with 50876 additions and 0 deletions
+141
View File
@@ -0,0 +1,141 @@
# 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.