# Telegram VPN bot (Marzban + Telegram Stars) Async Telegram bot for selling and extending Marzban VPN subscriptions. ## Features - Plans: - 1 month = ⭐️100 - 3 months = ⭐️270 - 6 months = ⭐️500 - Marzban username format: `tg` (example: `tg12345678`). - New users are created with: - `data_limit = 50 GB` - `data_limit_reset_strategy = month` - `proxies = {"vless": {"flow": "xtls-rprx-vision"}}` - `inbounds = {"vless": ["VLESS TCP REALITY"]}` - `note` containing Telegram first name, last name, and phone (if available) - If user has active subscription, a new purchase extends from current expiration. - Bot sends **subscription URL** after successful purchase. - Admin notifications for every creation/extension. - Per-user price multiplier support (`price_multiplier`) that affects invoice stars (final amount is always integer). - `/stats` command for admins: - payments count - stars earned - sold months - marzban users - traffic usage/total quota ## Admin user management - `/select_user ` — select user for further updates and show current values. - `/selected_user` — show the currently selected user and current values. - `/set_expire ` — set selected user expiration (UTC). - `/set_traffic ` — set selected user monthly traffic limit in GB. - `/set_multiplier ` — set selected user price multiplier. ## Setup ```bash python -m venv .venv source .venv/bin/activate pip install -r requirements.txt cp .env.example .env ``` Fill `.env` and run: ```bash set -a source .env set +a python bot.py ``` ## Container image The image contains only the application and Python dependencies. Runtime secrets and the SQLite database are deliberately excluded. Build and verify it locally: ```bash docker build --pull -t tt-simple:dev . docker run --rm --entrypoint sh tt-simple:dev -c \ 'test ! -e /app/.env && test ! -e /app/stats.db && test -e /app/bot.py' ``` Run it with environment variables and persistent SQLite storage: ```bash docker volume create tt-simple-data docker run --rm \ --env-file .env \ --env DB_PATH=/data/stats.db \ --volume tt-simple-data:/data \ tt-simple:dev ``` ### Publishing to GHCR `.github/workflows/container.yml` publishes a multi-architecture image to: ```text ghcr.io/kr0sh512/tt-simple ``` A push to `main` publishes `latest` and `sha-` tags. A Git tag such as `v0.1.0` publishes the matching version tag: ```bash git tag v0.1.0 git push origin main v0.1.0 ``` ### K3s deployment Create the namespace first: ```bash kubectl apply -f k8s/namespace.yaml ``` Create or update the application Secret from the local `.env` file. The Secret is never stored in Git: ```bash kubectl -n tt-simple create secret generic tt-simple-env \ --from-env-file=.env \ --dry-run=client -o yaml | kubectl apply -f - ``` For a private GHCR package, create a classic GitHub token with `read:packages` and create the registry pull secret: ```bash read -rsp "GHCR token: " GHCR_TOKEN echo kubectl -n tt-simple create secret docker-registry ghcr-creds \ --docker-server=ghcr.io \ --docker-username=kr0sh512 \ --docker-password="$GHCR_TOKEN" \ --dry-run=client -o yaml | kubectl apply -f - unset GHCR_TOKEN ``` If the package is public, remove `imagePullSecrets` from `k8s/tt-simple.yaml`. Deploy the PVC and bot after publishing the `v0.1.0` image: ```bash kubectl apply -f k8s/tt-simple.yaml kubectl -n tt-simple rollout status deployment/tt-simple kubectl -n tt-simple logs -f deployment/tt-simple ``` The manifest injects the Secret, mounts persistent storage at `/data`, and sets `DB_PATH=/data/stats.db`. To use the shared non-Russian proxy, add this to the local `.env` before updating `tt-simple-env`: ```dotenv HTTP_PROXY=http://shared-http-proxy.proxy.svc.cluster.local:3128 ``` The included namespace and pod labels satisfy the proxy `NetworkPolicy`. ## Notes - Telegram Stars invoices use `currency="XTR"` and empty `provider_token`. - Local SQLite database stores only payment statistics. User state is read from Marzban API.