Skip to content

Latest commit

 

History

History
136 lines (99 loc) · 3.17 KB

File metadata and controls

136 lines (99 loc) · 3.17 KB

image2url Telegram Bot

Telegram bot that accepts image/video uploads and returns a public URL from Cloudflare R2.

This is a pure vibe coding project.

Features

  • Upload photo/video and return:
    • direct URL
    • Markdown snippet
    • HTML snippet
  • Webhook secret validation (X-Telegram-Bot-Api-Secret-Token)
  • User whitelist (ALLOWED_USER_IDS)
  • Basic per-user rate limiting
  • Daily usage count (/quota)
  • History query (/history) and delete by id (/delete <id>)
  • Persistent webhook update idempotency in SQLite (safe across restarts)
  • SHA256-based upload deduplication to reduce duplicate R2 writes
  • Basic magic-number sniffing to detect mime mismatch
  • Graceful shutdown on SIGTERM/SIGINT

Constraints

  • Telegram cloud Bot API practical download limit: 20MB
  • This MVP enforces file size limit via MAX_FILE_SIZE_MB (default 20)

Quick Start

  1. Install dependencies
npm install
  1. Configure environment
cp .env.example .env
# edit .env
  1. Start server
npm run start
  1. Set webhook (after your public domain is ready)
npm run set-webhook

If you deploy with systemd and nginx on the target host, fill .env and run:

./scripts/finalize-production.sh

That helper script restarts image2url-bot, checks /healthz and /readyz, then runs npm run set-webhook.

Webhook endpoint is POST /webhook. Health endpoint is GET /healthz. Readiness endpoint is GET /readyz.

Docker Deploy

Build and run with Docker:

docker build -t image2url-bot .
docker run --rm -p 3000:3000 --env-file .env -v $(pwd)/data:/app/data image2url-bot

Or run with docker compose:

docker compose up -d --build

Tests

Run unit tests:

npm test

Run tests with coverage:

npm run test:coverage

Required Env

  • BOT_TOKEN
  • WEBHOOK_SECRET
  • R2_ACCOUNT_ID
  • R2_ACCESS_KEY_ID
  • R2_SECRET_ACCESS_KEY
  • R2_BUCKET
  • R2_PUBLIC_BASE_URL

Optional Env

  • WEBHOOK_URL
  • PORT (default 3000)
  • ALLOWED_USER_IDS (comma separated; empty means allow all)
  • MAX_FILE_SIZE_MB (default 20)
  • RATE_LIMIT_PER_MINUTE (default 20)
  • DOWNLOAD_TIMEOUT_MS (default 15000)
  • HISTORY_LIMIT (default 5)
  • LOG_LEVEL (default info)
  • MAX_WEBHOOK_BODY_MB (default 2)
  • UPDATE_DEDUPE_WINDOW_SECONDS (default 600)
  • R2_REGION (default auto)
  • SQLITE_PATH (default ./data/bot.db)

Production Checklist

  1. Keep ALLOWED_USER_IDS non-empty for private access.
  2. Use HTTPS webhook endpoint and a long random WEBHOOK_SECRET.
  3. Configure R2 bucket with least privilege access key (only required bucket).
  4. Put a CDN/custom domain in front of R2 for stable public URL.
  5. Persist SQLITE_PATH on durable volume or migrate to managed DB.
  6. Monitor GET /healthz and restart process on non-200.
  7. Run behind process manager (systemd, pm2, Docker orchestrator).
  8. Keep logs in JSON and ship stdout/stderr to your log collector.
  9. On the production host, run ./scripts/finalize-production.sh after updating .env.

CI

GitHub Actions workflow is included: ci.yml.
It runs npm ci, npm test, and npm run test:coverage on push and PR.