# 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.