Skip to content

Update main.py - #55

Open
saidblcd-hue wants to merge 1 commit into
aeither:mainfrom
saidblcd-hue:patch-1
Open

saidblcd-hue wants to merge 1 commit into
aeither:mainfrom
saidblcd-hue:patch-1

Conversation

@saidblcd-hue

@saidblcd-hue saidblcd-hue commented May 20, 2026 •

Copy link
Copy Markdown

Summary by CodeRabbit

  • New Features

    • Added webhook endpoint for receiving trading signals with automatic message formatting
    • Implemented health check endpoint for monitoring bot status
    • Enhanced trade alerts with calculated stop-loss and take-profit values based on price and volatility data
  • Refactor

    • Transitioned from polling-based to webhook-based signal processing for improved efficiency

Review Change Stack

@coderabbitai

coderabbitai Bot commented May 20, 2026 •

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

The entire application transitions from a Telebot polling-based command handler to a Flask web server. A new message formatter computes trade signal details (stop-loss, take-profit) from price and ATR. Three HTTP endpoints handle webhook signals, connection tests, and health checks, all authenticated via a shared secret. Startup launches Flask on a configurable port instead of entering a polling loop.

Changes

Polling to webhook-based Telegram bot

Layer / File(s) Summary
Flask webhook server and message routing
main.py
Flask app replaces Telebot polling with three HTTP endpoints: POST /webhook authenticates via secret query parameter, parses signal/price/timeframe/atr, selects format_buy_message() or format_sell_message() to compute stop-loss/take-profit levels, and sends via python-telegram-bot Bot.send_message(); GET /test validates connection; GET /health returns status. Environment variables provide token, chat ID, secret, and port (default 5000) with fallback placeholders. Startup runs Flask on 0.0.0.0:PORT with debug=False.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant Flask
  participant Bot as python-telegram-bot
  participant Telegram
  
  Client->>Flask: POST /webhook with signal, price, timeframe, atr
  Flask->>Flask: validate secret parameter
  Flask->>Flask: parse JSON payload
  Flask->>Flask: select format_buy_message or format_sell_message
  Flask->>Bot: send_message(chat_id, formatted_message)
  Bot->>Telegram: API call
  Telegram->>Bot: confirmation
  Bot->>Flask: return
  Flask->>Client: 200 JSON status response
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

A polling bot once looped all day,
Now webhooks catch signals' way.
Flask and secret, buy and sell,
ATR stops at calculated bell.
🐰 One trade whispers, one reply—
Telegram receives them high! 📱

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Update main.py' is vague and generic, using a non-descriptive term that doesn't convey meaningful information about the substantial architectural change from Telebot polling to Flask webhooks. Replace with a descriptive title such as 'Replace Telebot polling with Flask webhook server' to clearly communicate the main change to reviewers.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ 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.

@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: 3

🤖 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 `@main.py`:
- Around line 56-57: The except block in main.py currently returns the raw
exception string (except Exception as e) to clients via jsonify, which leaks
internal details; change it to log the full exception server-side using
app.logger.exception(e) or logging.exception("...") and return a generic JSON
error (e.g. {"error":"Internal server error"}) with the 500 status code instead
of str(e), keeping the same handler (the except Exception as e block and jsonify
call) but replacing the returned message and adding the logging call.
- Around line 11-13: TELEGRAM_TOKEN, TELEGRAM_CHAT_ID and WEBHOOK_SECRET are
using insecure default fallbacks; change retrieval to require these env vars and
fail fast at startup by checking the values after os.environ.get (or use
os.environ[]) and raising a clear exception (RuntimeError/SystemExit) if any are
missing or empty so the process won't start with predictable or placeholder
secrets; reference the TELEGRAM_TOKEN, TELEGRAM_CHAT_ID and WEBHOOK_SECRET
symbols when adding the validation and error messages.
- Around line 39-41: Replace the naive inequality check used to validate the
webhook secret with a timing-safe comparison: import the standard library
secrets module and use secrets.compare_digest to compare the value returned by
request.args.get("secret", "") (the local variable secret) against the
WEBHOOK_SECRET constant; apply the identical change to the `/test` endpoint
where the same direct `!=` comparison is used so both checks use
secrets.compare_digest and ensure both operands are strings before comparing.
🪄 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: a5a5067f-a972-478d-a86e-5e6512177406

📥 Commits

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

📒 Files selected for processing (1)
  • main.py

Comment thread main.py
Comment on lines +11 to +13
TELEGRAM_TOKEN = os.environ.get("TELEGRAM_TOKEN", "VOTRE_TOKEN_ICI")
TELEGRAM_CHAT_ID = os.environ.get("TELEGRAM_CHAT_ID", "VOTRE_CHAT_ID_ICI")
WEBHOOK_SECRET = os.environ.get("WEBHOOK_SECRET", "eurusd_secret_2024")

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 | ⚡ Quick win

Avoid hardcoded default secrets; fail fast on missing configuration.

The fallback "eurusd_secret_2024" is predictable and could be exploited if the environment variable is unset. Similarly, placeholder tokens will cause silent failures at runtime. Require these values explicitly or fail at startup.

Proposed fix
-TELEGRAM_TOKEN   = os.environ.get("TELEGRAM_TOKEN", "VOTRE_TOKEN_ICI")
-TELEGRAM_CHAT_ID = os.environ.get("TELEGRAM_CHAT_ID", "VOTRE_CHAT_ID_ICI")
-WEBHOOK_SECRET   = os.environ.get("WEBHOOK_SECRET", "eurusd_secret_2024")
+TELEGRAM_TOKEN   = os.environ.get("TELEGRAM_TOKEN")
+TELEGRAM_CHAT_ID = os.environ.get("TELEGRAM_CHAT_ID")
+WEBHOOK_SECRET   = os.environ.get("WEBHOOK_SECRET")
+
+if not all([TELEGRAM_TOKEN, TELEGRAM_CHAT_ID, WEBHOOK_SECRET]):
+    raise RuntimeError("Missing required environment variables: TELEGRAM_TOKEN, TELEGRAM_CHAT_ID, WEBHOOK_SECRET")
🤖 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 `@main.py` around lines 11 - 13, TELEGRAM_TOKEN, TELEGRAM_CHAT_ID and
WEBHOOK_SECRET are using insecure default fallbacks; change retrieval to require
these env vars and fail fast at startup by checking the values after
os.environ.get (or use os.environ[]) and raising a clear exception
(RuntimeError/SystemExit) if any are missing or empty so the process won't start
with predictable or placeholder secrets; reference the TELEGRAM_TOKEN,
TELEGRAM_CHAT_ID and WEBHOOK_SECRET symbols when adding the validation and error
messages.

Comment thread main.py
Comment on lines +39 to +41
secret = request.args.get("secret", "")
if secret != WEBHOOK_SECRET:
return jsonify({"error": "Unauthorized"}), 401

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 | ⚡ Quick win

Use timing-safe comparison for secret validation.

String comparison with != is vulnerable to timing attacks. An attacker could potentially determine the secret character-by-character by measuring response times.

Proposed fix

Add import at the top of the file:

import secrets

Then update the comparison:

     secret = request.args.get("secret", "")
-    if secret != WEBHOOK_SECRET:
+    if not secrets.compare_digest(secret, WEBHOOK_SECRET):
         return jsonify({"error": "Unauthorized"}), 401

Apply the same fix to the /test endpoint at line 62.

🤖 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 `@main.py` around lines 39 - 41, Replace the naive inequality check used to
validate the webhook secret with a timing-safe comparison: import the standard
library secrets module and use secrets.compare_digest to compare the value
returned by request.args.get("secret", "") (the local variable secret) against
the WEBHOOK_SECRET constant; apply the identical change to the `/test` endpoint
where the same direct `!=` comparison is used so both checks use
secrets.compare_digest and ensure both operands are strings before comparing.

Comment thread main.py
Comment on lines +56 to +57
except Exception as e:
return jsonify({"error": str(e)}), 500

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 | 🟡 Minor | ⚡ Quick win

Avoid leaking exception details to clients.

Returning str(e) exposes internal error messages that could reveal implementation details to attackers. Log the exception server-side and return a generic error message.

Proposed fix
     except Exception as e:
-        return jsonify({"error": str(e)}), 500
+        app.logger.exception("Webhook processing failed")
+        return jsonify({"error": "Internal server error"}), 500
📝 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.

Suggested change
except Exception as e:
return jsonify({"error": str(e)}), 500
except Exception as e:
app.logger.exception("Webhook processing failed")
return jsonify({"error": "Internal server error"}), 500
🧰 Tools
🪛 Ruff (0.15.13)

[warning] 56-56: Do not catch blind exception: Exception

(BLE001)

🤖 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 `@main.py` around lines 56 - 57, The except block in main.py currently returns
the raw exception string (except Exception as e) to clients via jsonify, which
leaks internal details; change it to log the full exception server-side using
app.logger.exception(e) or logging.exception("...") and return a generic JSON
error (e.g. {"error":"Internal server error"}) with the 500 status code instead
of str(e), keeping the same handler (the except Exception as e block and jsonify
call) but replacing the returned message and adding the logging call.

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