Repository navigation
BOt SHop - #63
BOt SHop#63CyberTAck-afks wants to merge 1 commit into
Conversation
📝 WalkthroughWalkthroughThe Railway deployment configuration was replaced by a Python Telegram bot. The bot persists JSON data and supports channel checks, menus, purchases, receipt approval, inventory, subscriptions, administrator management, and configuration delivery. ChangesST VPN Telegram Bot
Estimated code review effort: 5 (Critical) | ~90+ minutes Sequence Diagram(s)sequenceDiagram
participant TelegramUser
participant handle_all_messages
participant handle_receipt_photo
participant callback_handler
participant JSONDatabase
TelegramUser->>handle_all_messages: Send payment receipt photo
handle_all_messages->>handle_receipt_photo: Process receipt
handle_receipt_photo->>JSONDatabase: Save receipt and purchase data
callback_handler->>JSONDatabase: Load purchase and subscription data
callback_handler->>JSONDatabase: Save approved payment and subscription
callback_handler->>TelegramUser: Deliver configuration with expiration date
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment Warning |
There was a problem hiding this comment.
Actionable comments posted: 7
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@railway.toml`:
- Around line 188-191: Add a reject_ branch in callback_handler matching the
callback_data generated by the “رد پرداخت” button. In this branch, answer the
callback query, notify the buyer that payment was refused, and update the
administrator message caption to reflect the rejection.
- Around line 1-9: Restore railway.toml as valid TOML, including the previous
startCommand = "uv run python main.py" configuration. Move the Python bot
implementation beginning with the telebot imports and bot initialization into
the Python entry module launched by the Dockerfile, such as main.py, and ensure
the deployment continues to start that module.
- Around line 7-9: Remove the hardcoded TOKEN value, revoke the exposed Telegram
token via BotFather, and update the bot initialization to read TOKEN from an
environment variable. Confirm the token is absent from the working tree and
repository history using the provided search pattern, without adding another
secret fallback.
- Around line 583-595: The approval read-modify-write flow around the
`delivered_config` and `save_db` calls is not thread-safe, and `save_db` must
not overwrite the database directly. Add a shared `threading.Lock` and guard all
database read-modify-write sections, including the approval path, then update
`save_db` to write JSON to a temporary file and atomically replace the database
with `os.replace`.
- Around line 193-205: Update the admin_msg construction to escape
message.from_user.first_name for the selected Markdown parse mode before
embedding it in the Telegram link, and replace the silent exception handling in
the administrator send loop with exception logging. Preserve successful delivery
and ensure failures remain visible while the buyer notification flow continues
as intended.
- Around line 118-125: Remove the pasted Telegram advertisement text from the
markup.add argument list and restore the indentation of the following
KeyboardButton call. Repair the copy/paste damage throughout the file by
reindenting the statements at db["card_holder"] = parts[1], the line around 370,
elif text == "📊 حساب کاربری":, and if prod_key in db["products"]: to their
enclosing blocks; remove the duplicated lines identified around 201, 282, 328,
542, 544, and 562 while preserving the intended surrounding logic.
- Around line 540-542: Update the callback-handler branches for buy_ data and
the matching product lookups around the referenced branches to use the existing
safe .get access pattern, including the lookup near the current prod_key
assignment and those at the other reported locations. Handle a missing product
consistently with the established behavior near line 581 so unknown or deleted
tariffs do not raise KeyError or leave the user without a response.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
| import telebot | ||
| from telebot import types | ||
| import json | ||
| import os | ||
| from datetime import datetime, timedelta | ||
|
|
||
| # توکن اختصاصی ربات شما | ||
| TOKEN = '8857262027:AAGUB9VgDiTZhoKCBLNSmnXY9c-yxCN9_Qw' | ||
| bot = telebot.TeleBot(TOKEN) |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🔴 Critical | 🏗️ Heavy lift
Python source was committed into railway.toml. This breaks the deployment configuration.
railway.toml must be valid TOML. This file now contains Python code, so Railway cannot parse it, and the previous startCommand = "uv run python main.py" is gone. Move this bot code into a Python module (for example main.py, which Dockerfile already launches) and restore the TOML configuration.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@railway.toml` around lines 1 - 9, Restore railway.toml as valid TOML,
including the previous startCommand = "uv run python main.py" configuration.
Move the Python bot implementation beginning with the telebot imports and bot
initialization into the Python entry module launched by the Dockerfile, such as
main.py, and ensure the deployment continues to start that module.
| # توکن اختصاصی ربات شما | ||
| TOKEN = '8857262027:AAGUB9VgDiTZhoKCBLNSmnXY9c-yxCN9_Qw' | ||
| bot = telebot.TeleBot(TOKEN) |
There was a problem hiding this comment.
🔒 Security & Privacy | 🔴 Critical | ⚡ Quick win
Sensitive Data Exposure (CWE-798): Use of Hard-coded Credentials
Reachability: External
Remove the hardcoded bot token and revoke it now.
Line 8 commits a live Telegram bot token to the repository. Anyone who reads this pull request can control the bot, read user messages, and send messages to all users. Revoke this token with @BotFather immediately, then load it from an environment variable.
🔒 Proposed fix
-# توکن اختصاصی ربات شما
-TOKEN = '8857262027:AAGUB9VgDiTZhoKCBLNSmnXY9c-yxCN9_Qw'
+TOKEN = os.environ["BOT_TOKEN"]
bot = telebot.TeleBot(TOKEN)Confirm the token is not still present elsewhere in the repository or in its history:
#!/bin/bash
# Description: Find committed Telegram bot tokens.
rg -nP '\b\d{8,12}:[A-Za-z0-9_-]{35}\b' || echo "no token pattern in working tree"
git log --oneline -20🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@railway.toml` around lines 7 - 9, Remove the hardcoded TOKEN value, revoke
the exposed Telegram token via BotFather, and update the bot initialization to
read TOKEN from an environment variable. Confirm the token is absent from the
working tree and repository history using the provided search pattern, without
adding another secret fallback.
| Telegram | ||
| ST VPN ⚡️ | اینترنت بدون مرز | ||
| 🚀 ST VPN | تجربه سرعت و امنیت واقعی | ||
| 🌐 مخصوص یوتیوب، اینستاگرام، وبگردی و گیمینگ | ||
| 🔒 سرورهای اختصاصی با پینگ پایین | ||
| 🛡 ضمانت کامل و پشتیبانی تا آخرین... | ||
| VIEW CHANNEL | ||
| types.KeyboardButton("📦 مشاهده موجودی انبار"), |
There was a problem hiding this comment.
🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win
The pasted channel advertisement makes the file invalid Python.
Lines 118 through 124 contain Telegram channel promotional text inside the markup.add(...) call. Line 125 also loses its indentation. Delete the advertisement text and restore the argument list.
The same copy/paste damage appears at other places: line 295 (db["card_holder"] = parts[1]), line 370, line 444 (elif text == "📊 حساب کاربری":), and line 517 (if prod_key in db["products"]:) all start at column 0 and break their enclosing blocks. Several lines are also duplicated (201, 282, 328, 542, 544, 562). Fix all of them before merge.
🐛 Proposed fix for lines 117-125
types.KeyboardButton("➕ افزودن کانفیگ به انبار"),
-Telegram
-ST VPN ⚡️ | اینترنت بدون مرز
-🚀 ST VPN | تجربه سرعت و امنیت واقعی
-🌐 مخصوص یوتیوب، اینستاگرام، وبگردی و گیمینگ
-🔒 سرورهای اختصاصی با پینگ پایین
-🛡 ضمانت کامل و پشتیبانی تا آخرین...
-VIEW CHANNEL
-types.KeyboardButton("📦 مشاهده موجودی انبار"),
+ types.KeyboardButton("📦 مشاهده موجودی انبار"),📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| Telegram | |
| ST VPN ⚡️ | اینترنت بدون مرز | |
| 🚀 ST VPN | تجربه سرعت و امنیت واقعی | |
| 🌐 مخصوص یوتیوب، اینستاگرام، وبگردی و گیمینگ | |
| 🔒 سرورهای اختصاصی با پینگ پایین | |
| 🛡 ضمانت کامل و پشتیبانی تا آخرین... | |
| VIEW CHANNEL | |
| types.KeyboardButton("📦 مشاهده موجودی انبار"), | |
| types.KeyboardButton("➕ افزودن کانفیگ به انبار"), | |
| types.KeyboardButton("📦 مشاهده موجودی انبار"), |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@railway.toml` around lines 118 - 125, Remove the pasted Telegram
advertisement text from the markup.add argument list and restore the indentation
of the following KeyboardButton call. Repair the copy/paste damage throughout
the file by reindenting the statements at db["card_holder"] = parts[1], the line
around 370, elif text == "📊 حساب کاربری":, and if prod_key in db["products"]:
to their enclosing blocks; remove the duplicated lines identified around 201,
282, 328, 542, 544, and 562 while preserving the intended surrounding logic.
| markup.add( | ||
| types.InlineKeyboardButton("✅ تایید و تحویل سرویس", callback_data=f"approve_{user_id}_{prod_key}"), | ||
| types.InlineKeyboardButton("❌ رد پرداخت", callback_data=f"reject_{user_id}") | ||
| ) |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
The reject_ callback has no handler.
Line 190 creates a button with callback_data=f"reject_{user_id}", but callback_handler contains no reject_ branch. The administrator gets no response, the callback query stays unanswered, and the buyer is never told the payment was refused. Add a reject_ branch that answers the query, notifies the buyer, and updates the caption.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@railway.toml` around lines 188 - 191, Add a reject_ branch in
callback_handler matching the callback_data generated by the “رد پرداخت” button.
In this branch, answer the callback query, notify the buyer that payment was
refused, and update the administrator message caption to reflect the rejection.
| admin_msg = ( | ||
| f"📥 فیش واریزی جدید دریافت شد!\n\n" | ||
| f"👤 خریدار: [{message.from_user.first_name}](tg://user?id={user_id})\n" | ||
| f"🆔 شناسه کاربری: {user_id}\n" | ||
| f"📦 سرویس درخواستی: {prod['name']}\n" | ||
| f"💰 مبلغ: {prod['price']}" | ||
| ) | ||
|
|
||
| for adm in db.get("admins", [db["admin_id"]]): | ||
| try: | ||
| bot.send_photo(adm, photo_id, caption=admin_msg, reply_markup=markup, parse_mode="Markdown") | ||
| except Exception: | ||
| pass |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
An unescaped first_name can silently stop receipt delivery to administrators.
Line 195 places message.from_user.first_name inside a Markdown link and line 203 sends it with parse_mode="Markdown". A name that contains _, *, [, or ] makes Telegram reject the request with a 400 error. The bare except: pass at lines 204 and 205 hides the failure, and line 207 still tells the buyer the receipt was sent. No administrator ever sees the payment.
Escape the name, or use parse_mode="MarkdownV2" with proper escaping, and log the exception instead of discarding it.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@railway.toml` around lines 193 - 205, Update the admin_msg construction to
escape message.from_user.first_name for the selected Markdown parse mode before
embedding it in the Telegram link, and replace the silent exception handling in
the administrator send loop with exception logging. Preserve successful delivery
and ensure failures remain visible while the buyer notification flow continues
as intended.
| elif data.startswith("buy_"): | ||
| prod_key = data.split("_")[-1] | ||
| prod = db["products"][prod_key] |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
Unvalidated prod_key raises KeyError in the callback handler.
prod_key comes from call.data. If an administrator deleted the tariff after the keyboard was sent, or the client sends unknown data, db["products"][prod_key] raises KeyError. The user then sees no response. The same pattern exists at lines 502, 510, and 562. Line 581 already uses .get; use the same approach here.
🐛 Proposed fix
elif data.startswith("buy_"):
prod_key = data.split("_")[-1]
- prod = db["products"][prod_key]
+ prod = db["products"].get(prod_key)
+ if not prod:
+ bot.answer_callback_query(call.id, "❌ این تعرفه دیگر موجود نیست.", show_alert=True)
+ return📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| elif data.startswith("buy_"): | |
| prod_key = data.split("_")[-1] | |
| prod = db["products"][prod_key] | |
| elif data.startswith("buy_"): | |
| prod_key = data.split("_")[-1] | |
| prod = db["products"].get(prod_key) | |
| if not prod: | |
| bot.answer_callback_query(call.id, "❌ این تعرفه دیگر موجود نیست.", show_alert=True) | |
| return |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@railway.toml` around lines 540 - 542, Update the callback-handler branches
for buy_ data and the matching product lookups around the referenced branches to
use the existing safe .get access pattern, including the lookup near the current
prod_key assignment and those at the other reported locations. Handle a missing
product consistently with the established behavior near line 581 so unknown or
deleted tariffs do not raise KeyError or leave the user without a response.
| if not prod or len(prod["configs"]) == 0: | ||
| bot.answer_callback_query(call.id, "❌ انبار خالی است! کانفیگ موجود نیست.", show_alert=True) | ||
| return | ||
|
|
||
| delivered_config = prod["configs"].pop(0) | ||
| expire_time = datetime.now() + timedelta(days=prod["days"]) | ||
|
|
||
| db["user_services"][str(target_user_id)] = { | ||
| "plan": prod["name"], | ||
| "expire_date": expire_time.strftime("%Y-%m-%d %H:%M:%S"), | ||
| "config": delivered_config | ||
| } | ||
| save_db(db) |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift
The approval path is not atomic and save_db can truncate the database.
pyTelegramBotAPI dispatches updates in worker threads by default. Two concurrent approve_ callbacks can both pass the stock check at line 583 and both pop a config, and the last save_db wins. save_db also opens the file with 'w', so a crash during the write leaves a truncated bot_database.json with no backup.
Guard all read-modify-write sections with a threading.Lock, and write the JSON to a temporary file, then use os.replace for an atomic swap.
#!/bin/bash
# Description: Confirm the polling mode and whether any locking exists.
rg -n 'infinity_polling|polling\(|num_threads|threaded|threading' || echo "no polling/threading setup found"🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@railway.toml` around lines 583 - 595, The approval read-modify-write flow
around the `delivered_config` and `save_db` calls is not thread-safe, and
`save_db` must not overwrite the database directly. Add a shared
`threading.Lock` and guard all database read-modify-write sections, including
the approval path, then update `save_db` to write JSON to a temporary file and
atomically replace the database with `os.replace`.
Summary by CodeRabbit