Skip to content

Refactor Telegram bot to fetch hot Solana pairs - #37

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

drzhivago123 wants to merge 1 commit into
aeither:mainfrom
drzhivago123:patch-1

Conversation

@drzhivago123

@drzhivago123 drzhivago123 commented Mar 23, 2026 •

Copy link
Copy Markdown

Make better roi

Summary by CodeRabbit

  • New Features

    • Added an interactive menu system for easier navigation
    • Introduced "Hot Solana Picks" feature to discover trending tokens with scoring and filtering
    • Added "Market Summary" option
    • Added "Help" section with guidance
  • Improvements

    • Enhanced error handling with clearer messaging to users

@coderabbitai

coderabbitai Bot commented Mar 23, 2026 •

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

The bot implementation has been completely rewritten. It now fetches Solana token data from Dexscreener API, filters by liquidity and trading metrics, ranks by a computed score, and presents the top 5 tokens via a menu-driven interface. Error handling has shifted from startup-time blocking to runtime responses.

Changes

Cohort / File(s) Summary
Bot Initialization & Polling
main.py
Replaced .env loading and external command registration with direct TELEGRAM_BOT_TOKEN environment variable reading and bot.infinity_polling() for continuous operation.
Dexscreener API Integration & Token Filtering
main.py
Added HTTP fetching from Dexscreener (DEX_URL) with 20s timeout. Extracts pairs, filters by liquidity thresholds, 5m volume, and 5m price change, computes score, sorts descending, returns top 5.
Message Handlers & Menu System
main.py
Introduced reply keyboard main menu with /start handler and three routes: "🔥 Hot Solana Picks" (displays ranked tokens), "📈 Market Summary", and "ℹ️ Help"; added fallback handler for unrecognized input.
Error Handling
main.py
Changed from startup try/except with infinite sleep on failure to runtime error responses. API errors returned as {"error": ...} and surfaced in chat; per-pair parsing errors silently skipped.

Sequence Diagram

sequenceDiagram
    actor User
    participant Bot as Telegram Bot
    participant API as Dexscreener API
    participant Filter as Token Filter & Score

    User->>Bot: Click "🔥 Hot Solana Picks"
    activate Bot
    Bot->>API: GET /dexscreener/latest/pairs/solana?skip=0
    activate API
    API-->>Bot: pairs[] (all Solana tokens)
    deactivate API
    
    Bot->>Filter: Filter by liquidity, 5m volume, price change
    activate Filter
    Filter->>Filter: Compute score for each pair
    Filter->>Filter: Sort by score (descending)
    Filter-->>Bot: Top 5 tokens
    deactivate Filter
    
    Bot-->>User: Display ranked list + main menu
    deactivate Bot
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Poem

🐰 Hops excitedly
A bot that leaps through Solana's glow,
Sifting tokens high and low!
With filters sharp and scores so fine,
Finding hottest picks online—
Menu-driven, swift, and keen! 🚀✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

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.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately describes the main change: refactoring the Telegram bot to fetch and display hot Solana pairs from the Dexscreener API.

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

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

🧹 Nitpick comments (3)
main.py (3)

119-119: Wrap polling in __main__ guard for testability.

Calling bot.infinity_polling() at module level means the bot starts immediately on import, preventing unit testing or reuse of the module's functions.

♻️ Proposed fix
-bot.infinity_polling()
+if __name__ == "__main__":
+    bot.infinity_polling()
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@main.py` at line 119, The module currently calls bot.infinity_polling() at
import time which prevents importing for tests; move that call into a guarded
entrypoint: create a main() function that calls bot.infinity_polling() and wrap
its invocation in if __name__ == "__main__": main(). Update any startup logic
tied to bot.infinity_polling() accordingly so tests can import functions/classes
without starting the bot automatically.

82-91: Consider batching messages to avoid potential rate limits.

Sending up to 5 individual messages in rapid succession could trigger Telegram's rate limiting. Consider combining results into a single formatted message.

♻️ Proposed batched message approach
-    for idx, token in enumerate(results, start=1):
-        msg = (
-            f"#{idx} {token['name']} ({token['symbol']})\n"
-            f"Price: ${token['price']}\n"
-            f"Liquidity: ${token['liquidity']:,.0f}\n"
-            f"5m Volume: ${token['volume_5m']:,.0f}\n"
-            f"5m Change: {token['price_change_5m']:.2f}%\n"
-            f"Chart: {token['url']}"
-        )
-        bot.send_message(message.chat.id, msg)
+    lines = []
+    for idx, token in enumerate(results, start=1):
+        lines.append(
+            f"#{idx} {token['name']} ({token['symbol']})\n"
+            f"💰 Price: ${token['price']}\n"
+            f"💧 Liquidity: ${token['liquidity']:,.0f}\n"
+            f"📊 5m Volume: ${token['volume_5m']:,.0f}\n"
+            f"📈 5m Change: {token['price_change_5m']:.2f}%\n"
+            f"🔗 {token['url']}"
+        )
+    bot.send_message(message.chat.id, "\n\n".join(lines))
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@main.py` around lines 82 - 91, The loop sending individual messages (for idx,
token in enumerate(results, start=1): ... bot.send_message(message.chat.id,
msg)) can hit Telegram rate limits; instead build a single formatted string by
iterating over results and appending each token's formatted block (include idx,
token['name'], token['symbol'], price, liquidity, volume_5m, price_change_5m,
url) into one message body, then call bot.send_message once to message.chat.id;
ensure you respect Telegram max message length (chunk into multiple batched
messages if the combined string exceeds the API limit) and reuse the same send
operation rather than multiple sends in the loop.

42-43: Silent exception swallowing hinders debugging.

Catching all exceptions and continuing without any logging makes it difficult to diagnose issues with malformed pair data. Consider logging the exception or at least the pair identifier that failed parsing.

♻️ Proposed fix to add logging
+import logging
+
+logger = logging.getLogger(__name__)

Then in the exception handler:

             except Exception:
-                continue
+                logger.debug("Skipping malformed pair data: %s", p.get("pairAddress", "unknown"))
+                continue
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@main.py` around lines 42 - 43, Replace the silent catch-all "except
Exception:" in main.py with "except Exception as e:" and log the error and the
related pair identifier before continuing; e.g., call an existing logger
(logger.exception or logger.error) with a message that includes the pair
variable name used in the parsing loop (e.g., pair or pair_id) and the exception
(or stack trace); if no logger exists, write the same information to stderr so
malformed pair data failures are visible while still continuing.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@main.py`:
- Around line 5-6: Validate the TELEGRAM_BOT_TOKEN before constructing TeleBot:
check the TOKEN returned from os.getenv("TELEGRAM_BOT_TOKEN") is non-empty, and
if not, log an explicit error or raise SystemExit (e.g., use logging.error(...)
and sys.exit(1) or raise RuntimeError) so TeleBot(TOKEN) is never called with
None; update the initialization around TOKEN and TeleBot(TOKEN) to perform this
check and provide a clear failure message including that the TELEGRAM_BOT_TOKEN
environment variable is missing or invalid.

---

Nitpick comments:
In `@main.py`:
- Line 119: The module currently calls bot.infinity_polling() at import time
which prevents importing for tests; move that call into a guarded entrypoint:
create a main() function that calls bot.infinity_polling() and wrap its
invocation in if __name__ == "__main__": main(). Update any startup logic tied
to bot.infinity_polling() accordingly so tests can import functions/classes
without starting the bot automatically.
- Around line 82-91: The loop sending individual messages (for idx, token in
enumerate(results, start=1): ... bot.send_message(message.chat.id, msg)) can hit
Telegram rate limits; instead build a single formatted string by iterating over
results and appending each token's formatted block (include idx, token['name'],
token['symbol'], price, liquidity, volume_5m, price_change_5m, url) into one
message body, then call bot.send_message once to message.chat.id; ensure you
respect Telegram max message length (chunk into multiple batched messages if the
combined string exceeds the API limit) and reuse the same send operation rather
than multiple sends in the loop.
- Around line 42-43: Replace the silent catch-all "except Exception:" in main.py
with "except Exception as e:" and log the error and the related pair identifier
before continuing; e.g., call an existing logger (logger.exception or
logger.error) with a message that includes the pair variable name used in the
parsing loop (e.g., pair or pair_id) and the exception (or stack trace); if no
logger exists, write the same information to stderr so malformed pair data
failures are visible while still continuing.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 80c1d1cd-fa01-4042-b79e-511557277677

📥 Commits

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

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

Comment thread main.py
Comment on lines +5 to +6
TOKEN = os.getenv("TELEGRAM_BOT_TOKEN")
bot = TeleBot(TOKEN)

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

Missing validation for TELEGRAM_BOT_TOKEN environment variable.

If TELEGRAM_BOT_TOKEN is not set, TOKEN will be None, and TeleBot(None) will fail with a cryptic error during polling or when sending messages. Validate the token at startup for a clear failure mode.

🛡️ Proposed fix to add validation
 TOKEN = os.getenv("TELEGRAM_BOT_TOKEN")
+if not TOKEN:
+    raise RuntimeError("TELEGRAM_BOT_TOKEN environment variable is not set")
 bot = TeleBot(TOKEN)
📝 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
TOKEN = os.getenv("TELEGRAM_BOT_TOKEN")
bot = TeleBot(TOKEN)
TOKEN = os.getenv("TELEGRAM_BOT_TOKEN")
if not TOKEN:
raise RuntimeError("TELEGRAM_BOT_TOKEN environment variable is not set")
bot = TeleBot(TOKEN)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@main.py` around lines 5 - 6, Validate the TELEGRAM_BOT_TOKEN before
constructing TeleBot: check the TOKEN returned from
os.getenv("TELEGRAM_BOT_TOKEN") is non-empty, and if not, log an explicit error
or raise SystemExit (e.g., use logging.error(...) and sys.exit(1) or raise
RuntimeError) so TeleBot(TOKEN) is never called with None; update the
initialization around TOKEN and TeleBot(TOKEN) to perform this check and provide
a clear failure message including that the TELEGRAM_BOT_TOKEN environment
variable is missing or invalid.

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