Skip to content

HiUpdate railway.toml - #48

Open
hichamrouazi827-max wants to merge 1 commit into
aeither:mainfrom
hichamrouazi827-max:patch-1
Open

hichamrouazi827-max wants to merge 1 commit into
aeither:mainfrom
hichamrouazi827-max:patch-1

Conversation

@hichamrouazi827-max

@hichamrouazi827-max hichamrouazi827-max commented Apr 3, 2026 •

Copy link
Copy Markdown

Hi

Summary by CodeRabbit

  • New Features
    • Added Telegram bot application for odds analysis
    • Converts betting odds to implied probabilities
    • Generates match probability matrices and scoring predictions
    • Calculates expected goals using statistical analysis
    • Provides recommendations based on probability thresholds
    • Supports /start command and text-based input processing

@coderabbitai

coderabbitai Bot commented Apr 3, 2026 •

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

The railway.toml file was replaced to contain Telegram bot application code. Added utility functions for converting betting odds to probabilities and computing Poisson-based expected goals, along with async message handlers for processing odds and generating betting recommendations. Runtime setup reads bot token from environment variables and initiates polling.

Changes

Cohort / File(s) Summary
Telegram Bot Application
railway.toml
File converted from deployment configuration to Python bot application. Added utility functions: odds_to_prob(), calculate_lambda(), poisson(), and match_analysis() for odds-to-probability conversions and Poisson-based expected goals calculations. Implemented async handlers for /start command and text message processing. Added runtime initialization to read BOT_TOKEN from environment, build Telegram Application, register handlers, and start polling.

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
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Poem

🐰 A bot hops in to calculate odds with flair,
Converting decimals through Poisson's air,
Goals and probabilities dance in its code,
Recommendations bloom down the telegram road! 🎲✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'HiUpdate railway.toml' is vague and non-descriptive; it uses informal language ('Hi') and only names the file being changed without conveying the actual purpose or main change (converting file to Telegram bot Python application). Revise the title to clearly describe the main change, such as 'Convert railway.toml to Telegram bot polling setup with odds analysis' or 'Add Telegram bot handlers and odds probability calculations'.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Warning

⚠️ This pull request might be slop. It has been flagged by CodeRabbit slop detection and should be reviewed carefully.

@hichamrouazi827-max

Copy link
Copy Markdown
Author

Yes

@hichamrouazi827-max

Copy link
Copy Markdown
Author

Uploading Screenshot_20260401_223117_Telegram.jpg…

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 522c05d8-1685-4253-8ef2-3a3e0d991008

📥 Commits

Reviewing files that changed from the base of the PR and between 5cfd740 and b8d298d.

📒 Files selected for processing (1)
  • railway.toml

Comment thread railway.toml
Comment on lines +1 to 103
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"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# First, let's explore the repository structure
git ls-files | head -20

Repository: 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.toml

Repository: aeither/telegram-bot-python

Length of output: 3458


🏁 Script executed:

cat -n main.py

Repository: aeither/telegram-bot-python

Length of output: 1691


🏁 Script executed:

cat -n .env.example

Repository: 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:


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.

Comment thread railway.toml
Comment on lines +36 to +57
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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

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.

Comment thread railway.toml
Comment on lines +68 to +92
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")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

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.

Comment thread railway.toml
Comment on lines +95 to +97
TOKEN = os.getenv("BOT_TOKEN")

app = ApplicationBuilder().token(TOKEN).build()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

git ls-files | grep -E '(railway\.toml|main\.py|\.env)' | head -20

Repository: 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
fi

Repository: 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
fi

Repository: 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
fi

Repository: 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.

This branch has not been deployed

No deployments
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