Repository navigation
HiUpdate railway.toml - #48
hichamrouazi827-max wants to merge 1 commit into
Conversation
📝 WalkthroughWalkthroughThe Changes
Sequence Diagram(s)sequenceDiagram
participant User as User/Telegram
participant Handler as Message Handler
participant Analysis as Match Analysis
participant Bot as Bot Application
User->>Bot: Send three odds (home, draw, away)
Bot->>Handler: Receive text message
Handler->>Handler: Parse odds values
Handler->>Analysis: Call match_analysis(home, draw, away)
Analysis->>Analysis: Convert odds to probabilities
Analysis->>Analysis: Calculate lambda values (home/away)
Analysis->>Analysis: Generate score probability matrix
Analysis->>Analysis: Compute Over 2.5 & BTTS probabilities
Analysis-->>Handler: Return probability results
Handler->>Handler: Format recommendation based on thresholds
Handler->>User: Send analysis and recommendation
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~22 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ 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 |
|
Yes |
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@railway.toml`:
- Around line 68-92: The handler function handle currently parses any floats and
uses a bare except which swallows real errors; validate the three odds parsed
from update.message.text (e.g., ensure h, d, a are >1.0 and within sensible
bounds) and raise/respond with a usage error if validation fails, catch only
parsing/validation errors (ValueError or a custom ValidationError) to send the
usage hint, and replace the bare except with a broad except Exception block that
logs unexpected exceptions (use your logger or logger.exception) and returns an
internal error message; update references: handle, match_analysis,
update.message.reply_text to implement these checks and proper logging.
- Around line 95-97: The railway config currently reads TOKEN =
os.getenv("BOT_TOKEN") which is inconsistent with the rest of the app that
expects TELEGRAM_BOT_TOKEN (see main.py and .env.example); change the
environment key used in the config to TOKEN = os.getenv("TELEGRAM_BOT_TOKEN")
(or alternatively rename TELEGRAM_BOT_TOKEN to BOT_TOKEN everywhere) so all
references (TOKEN, BOT_TOKEN, TELEGRAM_BOT_TOKEN) match across the codebase and
deployment config.
- Around line 36-57: The score truncation using max_goals = 5 undercounts
probabilities for outcomes with 5+ goals; update the logic that builds
prob_matrix and aggregates over25 and btts to account for the tail beyond
max_goals. Either increase max_goals to a sufficiently large number (e.g., 10 or
more) or compute the tail mass using the Poisson CDF (use 1 -
sum_{k=0}^{max_goals-1} poisson(lambda,k)) and add aggregated
rows/columns/overlap when computing over25 and btts (reference prob_matrix,
max_goals, the nested loops over i/j, and the poisson(home_l, i)/poisson(away_l,
j) calls) so that probabilities for i>=max_goals or j>=max_goals are included in
over25 and btts.
- Around line 1-103: The file currently embeds a full Python bot instead of
TOML; move the Python code (functions like start, handle, match_analysis,
calculate_lambda and the ApplicationBuilder/app.run_polling block that
references TOKEN) into a proper Python entrypoint (e.g., main.py), ensure the
environment variable name matches what your app expects (use TELEGRAM_BOT_TOKEN
or change main.py to read BOT_TOKEN consistently), remove all Python from
railway.toml and replace it with valid TOML including a [deploy] table and a
startCommand that runs your new entrypoint (e.g., "startCommand = \"uv run
python main.py\""), and ensure you keep only one bot implementation (pick either
the python-telegram-bot code or the telebot code) so handlers are not dead code.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
| import logging | ||
| import math | ||
| import os | ||
| from telegram import Update | ||
| from telegram.ext import ApplicationBuilder, CommandHandler, MessageHandler, filters, ContextTypes | ||
|
|
||
| logging.basicConfig(level=logging.INFO) | ||
|
|
||
| # 🔢 تحويل odds → احتمالات | ||
| def odds_to_prob(odd): | ||
| return 1 / odd | ||
|
|
||
| # 📊 حساب λ (Poisson) | ||
| def calculate_lambda(home, draw, away): | ||
| p_home = odds_to_prob(home) | ||
| p_draw = odds_to_prob(draw) | ||
| p_away = odds_to_prob(away) | ||
|
|
||
| total = p_home + p_draw + p_away | ||
| p_home /= total | ||
| p_away /= total | ||
|
|
||
| home_lambda = 1.5 * p_home * 2 | ||
| away_lambda = 1.5 * p_away * 2 | ||
|
|
||
| return home_lambda, away_lambda | ||
|
|
||
| # 📈 دالة Poisson | ||
| def poisson(lmbda, k): | ||
| return (lmbda ** k * math.exp(-lmbda)) / math.factorial(k) | ||
|
|
||
| # 📊 حساب النتائج | ||
| def match_analysis(home, draw, away): | ||
| home_l, away_l = calculate_lambda(home, draw, away) | ||
|
|
||
| max_goals = 5 | ||
| prob_matrix = [] | ||
|
|
||
| for i in range(max_goals): | ||
| row = [] | ||
| for j in range(max_goals): | ||
| prob = poisson(home_l, i) * poisson(away_l, j) | ||
| row.append(prob) | ||
| prob_matrix.append(row) | ||
|
|
||
| # 🎯 حساب Over 2.5 | ||
| over25 = 0 | ||
| btts = 0 | ||
|
|
||
| for i in range(max_goals): | ||
| for j in range(max_goals): | ||
| if i + j > 2: | ||
| over25 += prob_matrix[i][j] | ||
| if i > 0 and j > 0: | ||
| btts += prob_matrix[i][j] | ||
|
|
||
| return home_l, away_l, over25, btts | ||
|
|
||
| # 📩 start | ||
| async def start(update: Update, context: ContextTypes.DEFAULT_TYPE): | ||
| await update.message.reply_text( | ||
| "📊 Bot Pro 🔥\n" | ||
| "دخل odds هكا:\n" | ||
| "1.80 3.50 4.20" | ||
| ) | ||
|
|
||
| # 📊 تحليل | ||
| async def handle(update: Update, context: ContextTypes.DEFAULT_TYPE): | ||
| try: | ||
| h, d, a = map(float, update.message.text.split()) | ||
|
|
||
| hl, al, over25, btts = match_analysis(h, d, a) | ||
|
|
||
| total = hl + al | ||
|
|
||
| bet = "🔥 Over 2.5" if over25 > 0.55 else "❄️ Under 2.5" | ||
| btts_res = "✅ BTTS Yes" if btts > 0.55 else "❌ BTTS No" | ||
|
|
||
| msg = ( | ||
| f"📊 تحليل متقدم:\n\n" | ||
| f"⚽ λ Home: {hl:.2f}\n" | ||
| f"⚽ λ Away: {al:.2f}\n" | ||
| f"🎯 Expected Goals: {total:.2f}\n\n" | ||
| f"📈 Over 2.5: {over25:.2%}\n" | ||
| f"📈 BTTS: {btts:.2%}\n\n" | ||
| f"💡 الرهان:\n{bet}\n{btts_res}" | ||
| ) | ||
|
|
||
| await update.message.reply_text(msg) | ||
|
|
||
| except: | ||
| await update.message.reply_text("❌ دخل odds: 1.80 3.50 4.20") | ||
|
|
||
| # 🚀 تشغيل | ||
| TOKEN = os.getenv("BOT_TOKEN") | ||
|
|
||
| app = ApplicationBuilder().token(TOKEN).build() | ||
|
|
||
| app.add_handler(CommandHandler("start", start)) | ||
| app.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, handle)) | ||
|
|
||
| app.run_polling()[deploy] | ||
| startCommand = "uv run python main.py" |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, let's explore the repository structure
git ls-files | head -20Repository: aeither/telegram-bot-python
Length of output: 171
🏁 Script executed:
# Look for the key files mentioned in the review
fd -t f "(railway\.toml|main\.py|\.env\.example)" .Repository: aeither/telegram-bot-python
Length of output: 95
🏁 Script executed:
# Get file sizes to understand what we're working with
wc -l railway.toml main.py .env.example 2>/dev/null || echo "Files not found or issue reading"Repository: aeither/telegram-bot-python
Length of output: 130
🏁 Script executed:
cat -n railway.tomlRepository: aeither/telegram-bot-python
Length of output: 3458
🏁 Script executed:
cat -n main.pyRepository: aeither/telegram-bot-python
Length of output: 1691
🏁 Script executed:
cat -n .env.exampleRepository: aeither/telegram-bot-python
Length of output: 245
🌐 Web query:
Railway.app railway.toml configuration format syntax
💡 Result:
The railway.toml file uses standard TOML syntax to define build and deploy configurations for Railway.app services as part of their "Config as Code" feature. Railway looks for railway.toml (or railway.json) in the repository root by default, or a custom path specified in service settings. Config in the file overrides dashboard settings. TOML structure features top-level tables [build] and [deploy], with keys corresponding to service settings. Arrays use [] syntax, e.g., preDeployCommand = ["npm run db:migrate"]. Values can be strings, numbers, booleans, arrays, or null. Example from official docs: [build] builder = "railpack" buildCommand = "echo building!" [deploy] preDeployCommand = ["npm run db:migrate"] startCommand = "echo starting!" healthcheckPath = "/" healthcheckTimeout = 100 restartPolicyType = "never" Additional examples: [build] builder = "DOCKERFILE" dockerfilePath = "Dockerfile.custom" [deploy] healthcheckPath = "/healthz" healthcheckTimeout = 300 restartPolicyType = "on_failure" For environment-specific overrides: [environments.production] deploy.startCommand = "node dist/index.js" Full list of configurable fields (build and deploy settings like watchPatterns, railpackVersion, multiRegionConfig, cronSchedule, etc.) is in the official reference: https://docs.railway.com/config-as-code/reference. Equivalent to JSON schema at https://railway.com/railway.schema.json (use for editor autocomplete in JSON, TOML follows same structure). Config source shown on deployment details page with file icons. TOML follows standard spec (toml.io): case-sensitive, # comments, bare/quoted/dotted keys, strings in "" or '', multi-line """", arrays [], inline tables not typically used here.
Citations:
- 1: https://docs.railway.com/config-as-code
- 2: https://docs.railway.com/config-as-code/reference
- 3: https://github.com/vignesh07/clawdbot-railway-template/blob/main/railway.toml
- 4: https://github.com/pglombardo/PasswordPusher/blob/master/railway.toml
Move this bot implementation into a Python entrypoint and restore railway.toml as proper TOML configuration.
railway.toml should contain only TOML configuration (e.g., [deploy] table with startCommand), not Python code. Lines 1–101 contain a complete bot implementation using python-telegram-bot, but line 102's syntax app.run_polling()[deploy] is invalid (indexing None), and line 103 attempts TOML syntax within a Python context. More critically, line 103 launches main.py, which contains a separate bot implementation using telebot instead. The handlers defined in railway.toml are dead code and never execute. Additionally, the embedded code reads BOT_TOKEN, but main.py expects TELEGRAM_BOT_TOKEN per .env.example; this mismatch will cause the embedded implementation to fail. Choose one bot implementation, move it to a proper Python file (main.py or similar), fix the environment variable name to match, and replace railway.toml with valid TOML configuration.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@railway.toml` around lines 1 - 103, The file currently embeds a full Python
bot instead of TOML; move the Python code (functions like start, handle,
match_analysis, calculate_lambda and the ApplicationBuilder/app.run_polling
block that references TOKEN) into a proper Python entrypoint (e.g., main.py),
ensure the environment variable name matches what your app expects (use
TELEGRAM_BOT_TOKEN or change main.py to read BOT_TOKEN consistently), remove all
Python from railway.toml and replace it with valid TOML including a [deploy]
table and a startCommand that runs your new entrypoint (e.g., "startCommand =
\"uv run python main.py\""), and ensure you keep only one bot implementation
(pick either the python-telegram-bot code or the telebot code) so handlers are
not dead code.
| max_goals = 5 | ||
| prob_matrix = [] | ||
|
|
||
| for i in range(max_goals): | ||
| row = [] | ||
| for j in range(max_goals): | ||
| prob = poisson(home_l, i) * poisson(away_l, j) | ||
| row.append(prob) | ||
| prob_matrix.append(row) | ||
|
|
||
| # 🎯 حساب Over 2.5 | ||
| over25 = 0 | ||
| btts = 0 | ||
|
|
||
| for i in range(max_goals): | ||
| for j in range(max_goals): | ||
| if i + j > 2: | ||
| over25 += prob_matrix[i][j] | ||
| if i > 0 and j > 0: | ||
| btts += prob_matrix[i][j] | ||
|
|
||
| return home_l, away_l, over25, btts |
There was a problem hiding this comment.
The truncated score matrix undercounts Over 2.5 and BTTS.
range(5) only models 0-4 goals per side. Any result with 5+ home goals or 5+ away goals disappears from the total mass, so both returned probabilities are systematically biased low and can cross the 0.55 cutoff the wrong way.
Suggested direction
- max_goals = 5
+ max_goals = 10 # or grow until the omitted tail is negligible
- for i in range(max_goals):
+ for i in range(max_goals + 1):
row = []
- for j in range(max_goals):
+ for j in range(max_goals + 1):
prob = poisson(home_l, i) * poisson(away_l, j)
row.append(prob)
prob_matrix.append(row)
+ total_mass = sum(sum(row) for row in prob_matrix)
+ over25 /= total_mass
+ btts /= total_mass🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@railway.toml` around lines 36 - 57, The score truncation using max_goals = 5
undercounts probabilities for outcomes with 5+ goals; update the logic that
builds prob_matrix and aggregates over25 and btts to account for the tail beyond
max_goals. Either increase max_goals to a sufficiently large number (e.g., 10 or
more) or compute the tail mass using the Poisson CDF (use 1 -
sum_{k=0}^{max_goals-1} poisson(lambda,k)) and add aggregated
rows/columns/overlap when computing over25 and btts (reference prob_matrix,
max_goals, the nested loops over i/j, and the poisson(home_l, i)/poisson(away_l,
j) calls) so that probabilities for i>=max_goals or j>=max_goals are included in
over25 and btts.
| async def handle(update: Update, context: ContextTypes.DEFAULT_TYPE): | ||
| try: | ||
| h, d, a = map(float, update.message.text.split()) | ||
|
|
||
| hl, al, over25, btts = match_analysis(h, d, a) | ||
|
|
||
| total = hl + al | ||
|
|
||
| bet = "🔥 Over 2.5" if over25 > 0.55 else "❄️ Under 2.5" | ||
| btts_res = "✅ BTTS Yes" if btts > 0.55 else "❌ BTTS No" | ||
|
|
||
| msg = ( | ||
| f"📊 تحليل متقدم:\n\n" | ||
| f"⚽ λ Home: {hl:.2f}\n" | ||
| f"⚽ λ Away: {al:.2f}\n" | ||
| f"🎯 Expected Goals: {total:.2f}\n\n" | ||
| f"📈 Over 2.5: {over25:.2%}\n" | ||
| f"📈 BTTS: {btts:.2%}\n\n" | ||
| f"💡 الرهان:\n{bet}\n{btts_res}" | ||
| ) | ||
|
|
||
| await update.message.reply_text(msg) | ||
|
|
||
| except: | ||
| await update.message.reply_text("❌ دخل odds: 1.80 3.50 4.20") |
There was a problem hiding this comment.
Validate odds explicitly and stop swallowing every runtime error.
Line 70 accepts any float values, so 0, 1, or negative odds either produce impossible probabilities or fall into the generic fallback. Line 91 then catches everything, including real code bugs, and replies with the same usage prompt. Catch only parse/validation errors here, and log unexpected exceptions separately.
Suggested direction
async def handle(update: Update, context: ContextTypes.DEFAULT_TYPE):
try:
h, d, a = map(float, update.message.text.split())
+ if min(h, d, a) <= 1:
+ raise ValueError("Decimal odds must be greater than 1")
hl, al, over25, btts = match_analysis(h, d, a)
@@
- except:
+ except ValueError:
await update.message.reply_text("❌ دخل odds: 1.80 3.50 4.20")
+ except Exception:
+ logging.exception("Failed to analyze odds")
+ await update.message.reply_text("❌ صار خطأ داخلي، حاول مرة أخرى.")🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@railway.toml` around lines 68 - 92, The handler function handle currently
parses any floats and uses a bare except which swallows real errors; validate
the three odds parsed from update.message.text (e.g., ensure h, d, a are >1.0
and within sensible bounds) and raise/respond with a usage error if validation
fails, catch only parsing/validation errors (ValueError or a custom
ValidationError) to send the usage hint, and replace the bare except with a
broad except Exception block that logs unexpected exceptions (use your logger or
logger.exception) and returns an internal error message; update references:
handle, match_analysis, update.message.reply_text to implement these checks and
proper logging.
| TOKEN = os.getenv("BOT_TOKEN") | ||
|
|
||
| app = ApplicationBuilder().token(TOKEN).build() |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
git ls-files | grep -E '(railway\.toml|main\.py|\.env)' | head -20Repository: aeither/telegram-bot-python
Length of output: 104
🏁 Script executed:
# Check if railway.toml exists and read the relevant lines
if [ -f railway.toml ]; then
echo "=== railway.toml (lines 90-100) ==="
sed -n '90,100p' railway.toml
fiRepository: aeither/telegram-bot-python
Length of output: 403
🏁 Script executed:
# Check main.py
if [ -f main.py ]; then
echo "=== main.py (lines 1-15) ==="
sed -n '1,15p' main.py
fiRepository: aeither/telegram-bot-python
Length of output: 431
🏁 Script executed:
# Check .env.example
if [ -f .env.example ]; then
echo "=== .env.example (lines 1-10) ==="
sed -n '1,10p' .env.example
fiRepository: aeither/telegram-bot-python
Length of output: 265
Use consistent environment variable naming.
railway.toml line 95 reads BOT_TOKEN, but main.py (line 10) and .env.example (line 2) use TELEGRAM_BOT_TOKEN. If this code becomes the startup path, deployments will fail to initialize without the correct env var unless these names are synchronized.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@railway.toml` around lines 95 - 97, The railway config currently reads TOKEN
= os.getenv("BOT_TOKEN") which is inconsistent with the rest of the app that
expects TELEGRAM_BOT_TOKEN (see main.py and .env.example); change the
environment key used in the config to TOKEN = os.getenv("TELEGRAM_BOT_TOKEN")
(or alternatively rename TELEGRAM_BOT_TOKEN to BOT_TOKEN everywhere) so all
references (TOKEN, BOT_TOKEN, TELEGRAM_BOT_TOKEN) match across the codebase and
deployment config.
Hi
Summary by CodeRabbit
/startcommand and text-based input processing