Skip to content

Refactor: Modular Telegram Bot v4.0 — async DB, proxy service, speed test, analytics - #3

Open
devin-ai-integration[bot] wants to merge 2 commits into
mainfrom
devin/1780210935-telegram-bot-restructure
Open

Refactor: Modular Telegram Bot v4.0 — async DB, proxy service, speed test, analytics#3
devin-ai-integration[bot] wants to merge 2 commits into
mainfrom
devin/1780210935-telegram-bot-restructure

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented May 31, 2026

Copy link
Copy Markdown

Summary

Rewrites 2775-line monolithic bot (unzjxjxj.py) into 12 focused modules with async database, new features, and bug fixes.

Architecture:

  • bot/database.py — async SQLite via aiosqlite, persistent connection, WAL mode, 8MB cache
  • bot/handlers/ — 6 handler modules separated by domain (start, menu, youtube, file, proxy, admin)
  • bot/server.py — aiohttp web server for file streaming + proxy REST API
  • bot/decorators.py@guard(perm=...) for centralized auth/rate-limit/ban checks

New features:

  • Proxy service: aggregates 7 public APIs, auto-refreshes, REST endpoint at /api/proxies
  • Proxy checker: user sends ip:port, bot validates liveness + measures latency
  • Speed test: one-click download speed test (Cloudflare + Hetzner)
  • Admin wallet charge: user_id amount reason to manually credit any user
  • Weekly analytics dashboard: 7-day user chart, revenue/download/claim breakdown, top actions

Bug fixes (Devin Review):

  • Referral balance display was double-counting REFERRAL_BONUS
  • Discount code used_count was incremented before payment (now on receipt submit)
  • ValueError crash in proxy API on non-numeric limit param
  • aiohttp.ClientSession leak — added on_cleanup handler
  • download_count was incremented even for expired files — split into get_file() + increment_file_downloads()

All original features preserved: VPN configs, YouTube/Instagram/TikTok downloads, file-to-link, VIP tiers, wallet, referral, admin panel.

Link to Devin session: https://app.devin.ai/sessions/451ad0922c2a4d229212dc5e8d49eea4
Requested by: @mohammad1390555


Open in Devin Review

… separated concerns

- Extract database layer to bot/database.py (async via aiosqlite)
- Split monolithic script into 12 focused modules
- Add proxy service: HTTP/HTTPS/SOCKS4/SOCKS5 aggregation from 7+ sources
- Add proxy REST API endpoint at /api/proxies
- Persistent DB connection with WAL mode and 8MB cache
- Guard decorator for centralized auth, rate limiting, ban checking
- Queue-based media download system with progress tracking
- Periodic proxy refresh and daily report jobs
- Admin proxy management panel
- .gitignore, requirements.txt, .env.example, README.md

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@devin-ai-integration

Copy link
Copy Markdown
Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 5 potential issues.

View 6 additional findings in Devin Review.

Open in Devin Review

Comment thread bot/handlers/start.py Outdated
f"*Referral success!*\n\n"
f"*{user.full_name or user.username or 'New user'}* joined via your link!\n"
f"*{REFERRAL_BONUS:,}* added to your wallet\n"
f"Balance: *{(referrer['balance'] + REFERRAL_BONUS):,}*",

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 Referral balance display double-counts the bonus

In cmd_start, after create_user returns, the referrer's balance is fetched via db.get_user(referred_by) at line 30. The create_user method (bot/database.py:277-279) already incremented the referrer's balance in the DB before committing at line 293. So referrer['balance'] already includes the REFERRAL_BONUS. However, line 37 displays referrer['balance'] + REFERRAL_BONUS, effectively double-counting the bonus and showing the referrer a balance that is REFERRAL_BONUS higher than their actual wallet balance.

Suggested change
f"Balance: *{(referrer['balance'] + REFERRAL_BONUS):,}*",
f"Balance: *{referrer['balance']:,}*",
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment thread bot/handlers/main_menu.py Outdated
new_price = int(original * (100 - disc["percent"]) / 100)
context.user_data["vip_price"] = new_price
context.user_data["discount_code"] = code
await db.use_discount(code)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 Discount code usage count incremented before payment is made

In handle_discount_code, db.use_discount(code) is called at line 268, which increments the discount code's used_count in the database. However, at this point the user has only applied the discount — they haven't submitted a payment receipt yet (the next state is STATE_WAITING_RECEIPT). If the user cancels the conversation, the discount code's usage count was already permanently incremented. This can exhaust a code's max_uses limit without any actual purchases, effectively making the discount code unavailable to legitimate users.

Prompt for agents
The discount code's used_count is incremented in handle_discount_code (bot/handlers/main_menu.py:268) when the user applies the code, but the payment hasn't been submitted yet. If the user cancels, the code is wasted.

The fix should move the db.use_discount(code) call to handle_receipt (bot/handlers/main_menu.py:222) after the payment is successfully created. The discount code is already stored in context.user_data['discount_code'] at line 267, so it can be consumed in handle_receipt. Additionally, consider calling use_discount in confirm_payment (database.py) when the payment is actually confirmed by an admin, to be truly safe against receipt rejections.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment thread bot/server.py Outdated
"""REST API endpoint for proxy list."""
db = request.app["db"]
protocol = request.query.get("protocol")
limit = min(int(request.query.get("limit", "50")), 200)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Unhandled ValueError in proxy API when limit parameter is non-numeric

The proxy_api_handler at line 61 calls int(request.query.get("limit", "50")) without any exception handling. If a client sends a request like /api/proxies?limit=abc, this raises a ValueError which propagates as an unhandled 500 error. This is a public-facing REST API endpoint.

Suggested change
limit = min(int(request.query.get("limit", "50")), 200)
try:
limit = min(int(request.query.get("limit", "50")), 200)
except (ValueError, TypeError):
limit = 50
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment thread bot/server.py
app = web.Application()
app["bot"] = bot
app["db"] = db
app["http_client"] = aiohttp.ClientSession()

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 aiohttp ClientSession created in web server is never closed

In start_web_server at line 71, an aiohttp.ClientSession() is created and stored in app["http_client"], but no cleanup handler is registered to close it on shutdown. This causes resource leaks (unclosed connector/session) and will emit ResourceWarning messages. The session should be closed via app.on_cleanup or app.on_shutdown signal.

Suggested change
app["http_client"] = aiohttp.ClientSession()
app["http_client"] = aiohttp.ClientSession()
async def close_session(app):
await app["http_client"].close()
app.on_cleanup.append(close_session)
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment thread bot/database.py Outdated
Comment on lines +531 to +535
if row:
await self._execute(
"UPDATE file_links SET download_count=download_count+1 WHERE file_unique_id=?",
(unique_id,),
)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 File download_count incremented even when file is expired

The db.get_file() method (bot/database.py:527-536) unconditionally increments download_count whenever a file record is found. Both stream_handler (bot/server.py:23) and cmd_start (bot/handlers/start.py:45) call db.get_file() and only check expiry afterwards. This means every access to an expired file link still inflates the download counter, producing inaccurate download statistics.

Prompt for agents
The get_file method in bot/database.py:527-536 increments download_count as a side effect before the caller can verify the file hasn't expired. The callers (bot/server.py stream_handler and bot/handlers/start.py cmd_start) check expiry after calling get_file.

Two approaches to fix:
1. Split get_file into a read-only lookup method and a separate increment_download_count method. Let callers call the increment only after verifying the file is valid and not expired.
2. Move the expiry check into get_file itself, returning None for expired files without incrementing the count.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

…tics

Bug fixes (Devin Review):
- Fix referral balance double-count in start handler
- Fix discount code usage before payment (moved to receipt submit)
- Fix unhandled ValueError in proxy API limit param
- Fix aiohttp ClientSession leak in web server
- Fix file download_count increment on expired files

New features:
- Proxy checker: user sends ip:port, bot validates live
- Speed test: download speed test via Cloudflare/Hetzner
- Admin wallet charge: manually add balance to any user
- Enhanced analytics: weekly breakdown, top actions, chart in full stats
- New conversation states for proxy check and wallet charge

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@devin-ai-integration devin-ai-integration Bot changed the title Refactor: Modular Telegram Bot v4.0 — async DB, proxy service, separated concerns Refactor: Modular Telegram Bot v4.0 — async DB, proxy service, speed test, analytics May 31, 2026
@devin-ai-integration

Copy link
Copy Markdown
Author

Test Results — Integration Testing

Ran shell-based integration tests against the refactored bot (no BOT_TOKEN available, so Telegram-specific flows untested).

Result: 44/44 assertions passed across 8 test areas.

Bug Fix Verification (5/5 verified)
Bug Method Result
Referral balance double-count Code inspection (start.py:37) Correct — shows referrer['balance'] (already includes bonus)
Discount code consumed before payment Automated test PASSEDvalidate_discount leaves used_count=0; only use_discount increments
Proxy API ValueError on bad limit Automated test PASSED?limit=abc returns HTTP 200, defaults to 50
aiohttp ClientSession leak Code inspection (server.py:76-78) Correct — on_cleanup handler registered
download_count on expired files Automated test PASSEDget_file() is read-only; separate increment_file_downloads() required
New Feature Verification (4/4 verified)
Feature Method Result
Proxy Checker Code analysis + fetch_all_proxies() test PASSED — 10,354 proxies fetched, deduplicated
Speed Test Code analysis Correct structure (Cloudflare + Hetzner endpoints)
Admin Wallet Charge Automated test PASSEDadd_balance credits user, logs transaction correctly
Weekly Analytics Automated test PASSED — 7-day breakdown, revenue/downloads/claims aggregated
Infrastructure Tests
  • All 11 DB tables created with correct schema
  • All 5 performance indexes created
  • Super admin user auto-seeded on first run
  • All 12 modules import without errors
  • 19 conversation states correctly defined
  • ApplicationBuilder constructs successfully
  • Web server health endpoint returns OK
Untested (requires BOT_TOKEN)
  • Live Telegram bot polling
  • Conversation handler flows (multi-step interactions)
  • File streaming via /stream/{f_uid}
  • Broadcast messaging
  • VIP payment confirmation flow

Devin session

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant