🛡️ VPN Service Platform — Telegram Bot + Web Admin Panel - #3
Open
devin-ai-integration[bot] wants to merge 3 commits into
Open
🛡️ VPN Service Platform — Telegram Bot + Web Admin Panel#3devin-ai-integration[bot] wants to merge 3 commits into
devin-ai-integration[bot] wants to merge 3 commits into
Conversation
- Telegram bot (aiogram 3.7.0) with subscription management - Web admin panel with dark theme UI - Xray VLESS auto-configuration via SSH - CryptoBot + Lolz.live payment integration - Whitelist relay support for Russian IPs - Subscription endpoint with base64-encoded VLESS links - Country auto-detection via IP geolocation - Custom Telegram emoji support - Background scheduler for subscription expiry - Deployment script with systemd service Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Author
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Author
Bot E2E Test ResultsTested: May 19, 2026 via Telegram Web All 20 tests passedMain Menu Flow (Tests 1-9)
Admin Flow (Tests 10-16)
Web Pages & Navigation (Tests 17-20)
Emoji complianceAll button labels verified emoji-free. Country flags (🇵🇱) in server names correctly preserved. No bugs found |
Author
Test Report: SSH Key Storage, Traffic Sync & DisplayDate: May 19, 2026 | Environment: Production 2.27.12.148:8080 | Bot: @Bglazbogaoboglzobot Results: 8/10 passed, 2 untested
Escalations
Shell evidenceTraffic sync logs (no errors): Subscription endpoint headers: Xray stats API response: {"stat": [{"name": "inbound>>>vless-in>>>traffic>>>downlink"}, {"name": "inbound>>>api>>>traffic>>>uplink", "value": 431}]} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a complete VPN service platform built in Python:
services/xray_manager.py): SSH into remote servers viasshpassor SSH key, install Xray, generate x25519 keys, deploy VLESS+Reality configs with stats API auto-enabled, set up iptables relay for whitelist servers/sub/{token}): serves base64-encoded VLESS links withSubscription-Userinfoheader for VPN client apps (profile title: GMBOT)deploy.shinstalls deps, creates virtualenv, sets up systemd service at/opt/vpnbot/Updates since last revision
Relay display names with country flags — Relay servers now show
WHITELIST 🇷🇺 → 🇩🇪(flag of relay country → flag of target VPN server) instead of the oldWHITELIST Россия, Москваtext. Updated in bothweb/app.py(admin panel) andhandlers/admin.py(Telegram bot). Usesemoji.flag()to convert country codes to flag emoji.Renamed subscription Profile-Title to GMBOT —
services/subscription.pynow returnsProfile-Title: GMBOTinstead ofPremium VPNin theSubscription-Userinforesponse headers. This controls what VPN client apps display as the profile name.Relay setup supports non-root SSH users —
setup_relay()inxray_manager.pynow prefixes alliptables,sysctl, andapt-getcommands withsudo. This fixes relay setup on Yandex Cloud VMs and similar providers where SSH login is a non-root user (e.g.,user) with passwordless sudo.Previous updates still included
Fixed traffic counting end-to-end — Rewrote
query_xray_stats()to usejson.loads()instead of fragile regex parsing. Added-resetflag so Xray counters reset after each read (incremental collection). Filters stats to onlyvless-ininbound anduser>>>entries, ignoring internal API traffic. Removed dead code in the old parsing loop. Tested on production — Germany and Poland both return real traffic data.Database backup every 3 hours — New
send_db_backup()job inscheduler.py. Copies SQLite database and sends it as a Telegram document to all admin users with timestamp caption. Runs via APScheduler alongside existing jobs.Geolocation API reordered — Switched primary API from
2ip.uatoip-api.com(withlang=ru). The 2ip.ua API returned Singapore for a Polish IP; ip-api.com is more reliable. Fallback chain is now:ip-api.com→2ip.ua→ipwho.is.Improved sync_traffic aggregation — Traffic from all servers is now aggregated first, then distributed evenly to active users (instead of distributing per-server). Added detailed logging: each server's contribution is logged individually, plus the final distribution.
SSH key storage in database — Added
ssh_key TEXT DEFAULT ''column toserverstable.add_server()now accepts and stores anssh_keyparameter. Both relay and VPN server creation paths inweb/app.pypassssh_keythrough.sync_traffic()fetches the storedssh_keyfrom each server record and passes it toquery_xray_stats().SSH key file upload on Add Server page — File upload button (
.zip,.pem,.key). ZIP archives are extracted client-side via JSZip — automatically finds the first file containingPRIVATE KEY. A hidden textarea still holds the key value for form submission and allows manual paste.Traffic display in Telegram bot —
fmt_bytes()helper formats bytes into human-readable strings./profileand "Мои ключи" both display total traffic, upload, and download.Removed 100GB traffic limit —
services/subscription.pyqueries real traffic stats from thetrafficDB table. TheSubscription-Userinfoheader reportstotal=0(unlimited) with realupload/downloadbyte counts.Xray stats API auto-enabled on new servers —
build_xray_config()includes"stats": {},StatsServiceAPI inbound on127.0.0.1:10085, per-user stats policy, and routing rules. Any server added through the admin panel automatically gets traffic counting.Fix Xray auto-installation — Installs
curl+unzipbefore downloading, parses both key output formats, creates systemd unit.Real-time installation console on Add Server page — SSE streaming of setup logs with color-coded levels.
Admin panel full redesign — Dark theme, Lucide SVG icons, sidebar nav, KPI cards, Chart.js. Sunrise palette for help & legal pages.
Branding: GMVPN / GMBOT — All logo references updated across help pages, legal pages,
<title>tags, and subscription profile title.Review & Testing Checklist for Human
sync_traffic()divides total VPN traffic equally among all active users. If 3 users share a server and one uses 90% of the bandwidth, all 3 get credited with 33% each. Verify this matches intended behavior or if per-UUID tracking is needed (theemailfield exists in Xray configs but is not currently used for attribution).-resetflag means lost data on failure —query_xray_stats()uses-resetso Xray zeroes counters after each read. If the sync job reads stats but crashes before writing to the DB, that traffic data is permanently lost. There is no retry or WAL mechanism.total=0in Subscription-Userinfo — Some VPN clients (v2rayNG, Clash) may interprettotal=0as "0 bytes quota" rather than "unlimited". Test with target clients. Consider using a very large value (e.g.999999999999999).serverstable storesssh_passwordandssh_keyin plain text in SQLite.deduct_balance()has a TOCTOU race. Admin panel has no CSRF protection. All pages served over HTTP. DB backup is sent as an unencrypted file via Telegram.country_codeset, the display will beWHITELIST 🇷🇺 →with a trailing arrow and no target flag. Verify all target VPN servers havecountry_codepopulated.add_server.htmlloads JSZip fromcdnjs.cloudflare.comon first ZIP upload. If CDN is blocked, ZIP extraction will silently fail._setup_logsmemory leak — Setup logs stored in global dict. If client disconnects mid-stream or never connects, logs accumulate indefinitely.127.0.0.1:10085WHITELIST 🇷🇺 → 🇩🇪(appropriate flags)/sub/{token}header → verifyupload/downloadvalues are non-zero and profile title isGMBOT/profile→ verify traffic stats displayed (Total / Upload / Download)Notes
/tmp, sent, then deleted.help/style.cssandlegal/style.cssimport Inter fromfonts.googleapis.com. If blocked in Russia, pages fall back to system fonts.ip-api.com→2ip.ua→ipwho.is.Link to Devin session: https://app.devin.ai/sessions/6d47698e17e145bcb8b015918ff3ff4e
Requested by: @promi1