428th-website-2026/api/README.md
Artemii Peretiachenko 793d093c86 Add Telegram contact API with JSONL backup and real form errors.
Wire the anonymous form to a VPS Python endpoint that notifies Telegram, persists submissions locally, and stops faking success on failure.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-26 18:43:43 +02:00

2.8 KiB

Contact API → Telegram

Small Python 3 (stdlib only) service that accepts POST /api/contact and forwards the message to Telegram.

Setup (once)

  1. Create a bot with @BotFather → copy the token.
  2. Open a chat with the bot and press Start.
  3. Get your numeric chat id (@userinfobot, or call getUpdates after messaging the bot).
  4. On the VPS:
cd /path/to/site/api
cp .env.example .env
# edit .env — set TELEGRAM_BOT_TOKEN and TELEGRAM_CHAT_ID

Local smoke test

cd api
cp .env.example .env   # fill tokens
python3 contact_server.py
curl -sS -X POST http://127.0.0.1:8787/api/contact \
  -H 'Content-Type: application/json' \
  -d '{"name":"Test","contact":"@you","message":"hello"}'

Health check: GET /api/health{"ok":true,"configured":true}.

systemd

/etc/systemd/system/428th-contact.service:

[Unit]
Description=428th contact form → Telegram
After=network.target

[Service]
Type=simple
WorkingDirectory=/var/www/428th.com/api
EnvironmentFile=/var/www/428th.com/api/.env
ExecStart=/usr/bin/python3 /var/www/428th.com/api/contact_server.py
Restart=always
RestartSec=3
User=www-data
Group=www-data

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now 428th-contact
sudo systemctl status 428th-contact

Adjust WorkingDirectory, EnvironmentFile, User, and paths to match your VPS layout.

nginx

Inside the HTTPS server block for 428th.com:

location /api/contact {
    proxy_pass http://127.0.0.1:8787/api/contact;
    proxy_http_version 1.1;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    client_max_body_size 16k;
}

# optional
location /api/health {
    proxy_pass http://127.0.0.1:8787/api/health;
    proxy_set_header Host $host;
}

Then:

sudo nginx -t && sudo systemctl reload nginx

Deploy updated static files (common.js, built HTML) as usual so the form shows real errors and includes the honeypot field.

Message backup

Every valid submission is appended to messages.jsonl (override with MESSAGES_FILE in .env), one JSON object per line:

{"ts":"2026-07-26T16:40:00Z","name":"…","contact":"…","message":"…","ip":"1.2.3.4","telegram_ok":true,"telegram_error":null}

Backup is written even if Telegram fails (telegram_ok: false), so you still have the text on disk. Honeypot hits are not stored. Keep this file private (same permissions as .env); it is gitignored.

Behaviour notes

  • Honeypot field website: if filled, returns 200 without notifying Telegram or writing a backup.
  • In-memory rate limit: 5 POSTs per IP per 60 seconds → 429.
  • Field limits: name/contact ≤ 200 chars, message ≤ 4000.