Files
tt-proxy-bot/README.md
T

4.0 KiB
Raw Blame History

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<telegram_user_id> (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 <username|telegram_id> — select user for further updates and show current values.
  • /selected_user — show the currently selected user and current values.
  • /set_expire <YYYY-MM-DD or ISO datetime> — set selected user expiration (UTC).
  • /set_traffic <GB> — set selected user monthly traffic limit in GB.
  • /set_multiplier <float> — set selected user price multiplier.

Setup

python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env

Fill .env and run:

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:

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:

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:

ghcr.io/kr0sh512/tt-simple

A push to main publishes latest and sha-<commit> tags. A Git tag such as v0.1.0 publishes the matching version tag:

git tag v0.1.0
git push origin main v0.1.0

K3s deployment

Create the namespace first:

kubectl apply -f k8s/namespace.yaml

Create or update the application Secret from the local .env file. The Secret is never stored in Git:

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:

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:

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:

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.