Skip to content

Update main.py - #36

Open
googlanubis-create wants to merge 1 commit into
aeither:mainfrom
googlanubis-create:patch-4
Open

googlanubis-create wants to merge 1 commit into
aeither:mainfrom
googlanubis-create:patch-4

Conversation

@googlanubis-create

@googlanubis-create googlanubis-create commented Mar 20, 2026 •

Copy link
Copy Markdown

Summary by CodeRabbit

  • New Features

    • Added welcome message to the /start command.
  • Bug Fixes

    • Improved error handling with user-friendly messages for API failures and runtime errors.
    • Added validation of required environment variables at startup to prevent configuration issues.

@coderabbitai

coderabbitai Bot commented Mar 20, 2026 •

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Migrated from synchronous telebot framework to asynchronous python-telegram-bot library, replacing decorator-based handlers with CommandHandler and MessageHandler. The /start command now returns a fixed welcome message, while incoming messages are forwarded to the DeepSeek /v1/chat/completions API endpoint with responses relayed back to users. Added validation of required environment variables and exception logging.

Changes

Cohort / File(s) Summary
Framework Migration
main.py
Switched from synchronous telebot to asynchronous python-telegram-bot with Application framework. Added start() and handle_message() async handlers. Integrated DeepSeek API calls in message handling with HTTP status checking and error responses. Refactored initialization into main() function with environment variable validation and logging configuration.

Sequence Diagram

sequenceDiagram
    participant User as Telegram User
    participant Handler as Application Handler
    participant DeepSeek as DeepSeek API
    participant Reply as Telegram Reply

    User->>Handler: Send message
    Handler->>Handler: Route to handle_message()
    Handler->>DeepSeek: POST to /v1/chat/completions
    
    alt API Success (HTTP 200)
        DeepSeek-->>Handler: Response with choices[0].message.content
        Handler->>Reply: Send parsed content
    else API Error
        DeepSeek-->>Handler: Error status code
        Handler->>Reply: Send "Ошибка API: <status>"
    else Runtime Exception
        Handler->>Handler: Catch exception
        Handler->>Reply: Send "Ошибка: <exception>"
    end
    
    Reply-->>User: Message reply
Loading

Estimated Code Review Effort

🎯 4 (Complex) | ⏱️ ~40 minutes

Poem

🐰 The telegram hops now skip so light,
Async loops dance through the night,
DeepSeek whispers secrets true,
Handlers shimmer, shiny new! ✨

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% 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 non-descriptive language that doesn't convey meaningful information about the changeset. Consider a more descriptive title such as 'Migrate from telebot to python-telegram-bot async framework' or 'Switch to async handlers and integrate DeepSeek API' to better communicate the primary changes.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
📝 Coding Plan
  • Generate coding plan for human review comments

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

🤖 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`:
- Line 29: The code assigns user_name = update.message.from_user.first_name and
then injects it into the system prompt; instead, remove any use of
update.message.from_user.first_name (or user_name) from the system-level prompt
(do not promote user-controlled display names into the highest-priority message)
and keep the system prompt static; if you need the display name for
personalization, pass user_name only inside a user-level message or metadata
sent to the model (e.g., include user_name in the user message payload or a
separate context field) and sanitize/validate it before use to avoid overriding
bot persona instructions.
- Around line 66-68: The public `/hello` command was removed from the bot
runtime: in main.py you register only CommandHandler("start", start) while
commands.py declares `/hello`; either re-register the handler or remove it from
the public commands list. Fix by adding a CommandHandler for "hello" (e.g.,
CommandHandler("hello", hello)) alongside the existing CommandHandler("start",
start) so the hello handler function (hello) is actually invoked, or else delete
`/hello` from commands.py so the public contract matches the registered
handlers; update references to Application.builder(), CommandHandler, start,
MessageHandler and handle_message accordingly.
- Around line 62-64: The startup check in main() logs missing TELEGRAM_TOKEN or
DEEPSEEK_API_KEY but returns, causing a zero exit code; replace the early return
with a non-zero exit to fail the process (e.g., raise SystemExit(1) or call
sys.exit(1)) so that logger.error("Отсутствуют токены!") is followed by an
explicit non-zero exit when TELEGRAM_TOKEN or DEEPSEEK_API_KEY are not set.
- Around line 57-59: The except block is exposing internal exception text to
users and not logging tracebacks; change the handler around the except Exception
as e block so that you send a generic user-facing reply via
update.message.reply_text (no exception details) and log the full exception
server-side using logger.exception(...) or logger.error(..., exc_info=True) to
capture the traceback; keep the existing await behavior but replace f"Ошибка:
{e}" with a safe message and ensure logger records the traceback for debugging.
- Line 48: The synchronous requests.post call to DEEPSEEK_API_URL (the line
assigning response = requests.post(...)) is blocking an async handler; change it
to run off the event loop by wrapping the blocking call in asyncio.to_thread or
replace it with an async HTTP client. Specifically, in the async handler that
constructs headers and payload and assigns response, move the requests.post
invocation into asyncio.to_thread(lambda: requests.post(DEEPSEEK_API_URL,
headers=headers, json=payload, timeout=30)) and await that result (or use
aiohttp/httpx async client to perform the POST), then keep the subsequent code
that reads response unchanged; ensure you import asyncio and update any
exception handling around the call.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f5af0137-c4d8-453e-a507-ffa09180413a

📥 Commits

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

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

Comment thread main.py
"""Обработчик всех текстовых сообщений"""
try:
user_message = update.message.text
user_name = update.message.from_user.first_name

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

Do not promote first_name into the system prompt.

from_user.first_name is user-controlled, but Line 41 injects it into the highest-priority message. A crafted display name can override the bot persona/instructions. Keep the system prompt static and pass the display name at user-level context instead.

Safer prompt split
         payload = {
             "model": "deepseek-chat",
             "messages": [
-                {"role": "system", "content": f"Ты - Дипси, друг Дера. Ты добрый, заботливый. Сейчас ты общаешься с {user_name}."},
-                {"role": "user", "content": user_message}
+                {"role": "system", "content": "Ты - Дипси, друг Дера. Ты добрый и заботливый."},
+                {"role": "user", "content": f"Имя пользователя: {user_name}\nСообщение: {user_message}"}
             ],

Also applies to: 41-41

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@main.py` at line 29, The code assigns user_name =
update.message.from_user.first_name and then injects it into the system prompt;
instead, remove any use of update.message.from_user.first_name (or user_name)
from the system-level prompt (do not promote user-controlled display names into
the highest-priority message) and keep the system prompt static; if you need the
display name for personalization, pass user_name only inside a user-level
message or metadata sent to the model (e.g., include user_name in the user
message payload or a separate context field) and sanitize/validate it before use
to avoid overriding bot persona instructions.

Comment thread main.py
"max_tokens": 2000
}

response = requests.post(DEEPSEEK_API_URL, headers=headers, json=payload, timeout=30)

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:

fd -t f "main.py" -x wc -l {}

Repository: aeither/telegram-bot-python

Length of output: 83


🏁 Script executed:

cd $(git ls-files -o -c --exclude-standard | grep -E "^[^/]*$|main\.py$" | head -1 | xargs dirname) 2>/dev/null || cd . && git ls-files | grep -E "main\.py"

Repository: aeither/telegram-bot-python

Length of output: 78


🏁 Script executed:

git ls-files | head -20

Repository: aeither/telegram-bot-python

Length of output: 171


🏁 Script executed:

find . -name "main.py" -type f 2>/dev/null

Repository: aeither/telegram-bot-python

Length of output: 80


🏁 Script executed:

head -60 main.py

Repository: aeither/telegram-bot-python

Length of output: 2424


This blocks the bot's async update loop.

Line 48 calls requests.post(...) directly from an async handler. One slow DeepSeek request can freeze other updates until the blocking I/O returns; use an async client or offload the call with asyncio.to_thread(...).

Possible fix without adding a new dependency
+import asyncio
 import logging
 import requests
@@
-        response = requests.post(DEEPSEEK_API_URL, headers=headers, json=payload, timeout=30)
+        response = await asyncio.to_thread(
+            requests.post,
+            DEEPSEEK_API_URL,
+            headers=headers,
+            json=payload,
+            timeout=30,
+        )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@main.py` at line 48, The synchronous requests.post call to DEEPSEEK_API_URL
(the line assigning response = requests.post(...)) is blocking an async handler;
change it to run off the event loop by wrapping the blocking call in
asyncio.to_thread or replace it with an async HTTP client. Specifically, in the
async handler that constructs headers and payload and assigns response, move the
requests.post invocation into asyncio.to_thread(lambda:
requests.post(DEEPSEEK_API_URL, headers=headers, json=payload, timeout=30)) and
await that result (or use aiohttp/httpx async client to perform the POST), then
keep the subsequent code that reads response unchanged; ensure you import
asyncio and update any exception handling around the call.

Comment thread main.py
Comment on lines +57 to +59
except Exception as e:
logger.error(f"Error: {e}")
await update.message.reply_text(f"Ошибка: {e}")

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

Don't send internal exception text back to chats.

f"Ошибка: {e}" exposes transport/parser details to users, and logger.error(...) drops the traceback. Reply with a generic failure message and log the full exception server-side.

Safer error handling
-    except Exception as e:
-        logger.error(f"Error: {e}")
-        await update.message.reply_text(f"Ошибка: {e}")
+    except Exception:
+        logger.exception("DeepSeek request failed")
+        await update.message.reply_text("Сервис временно недоступен. Попробуйте позже.")
📝 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:
logger.error(f"Error: {e}")
await update.message.reply_text(f"Ошибка: {e}")
except Exception:
logger.exception("DeepSeek request failed")
await update.message.reply_text("Сервис временно недоступен. Попробуйте позже.")
🧰 Tools
🪛 Ruff (0.15.6)

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

(BLE001)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@main.py` around lines 57 - 59, The except block is exposing internal
exception text to users and not logging tracebacks; change the handler around
the except Exception as e block so that you send a generic user-facing reply via
update.message.reply_text (no exception details) and log the full exception
server-side using logger.exception(...) or logger.error(..., exc_info=True) to
capture the traceback; keep the existing await behavior but replace f"Ошибка:
{e}" with a safe message and ensure logger records the traceback for debugging.

Comment thread main.py
Comment on lines +62 to +64
if not TELEGRAM_TOKEN or not DEEPSEEK_API_KEY:
logger.error("Отсутствуют токены!")
return

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

Fail startup with a non-zero exit code.

Line 64 returns from main(), so missing secrets still terminate the process with status 0. That makes configuration failures easy to miss in Docker/systemd/K8s; raise SystemExit(1) instead.

Minimal fix
     if not TELEGRAM_TOKEN or not DEEPSEEK_API_KEY:
         logger.error("Отсутствуют токены!")
-        return
+        raise SystemExit(1)
📝 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
if not TELEGRAM_TOKEN or not DEEPSEEK_API_KEY:
logger.error("Отсутствуют токены!")
return
if not TELEGRAM_TOKEN or not DEEPSEEK_API_KEY:
logger.error("Отсутствуют токены!")
raise SystemExit(1)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@main.py` around lines 62 - 64, The startup check in main() logs missing
TELEGRAM_TOKEN or DEEPSEEK_API_KEY but returns, causing a zero exit code;
replace the early return with a non-zero exit to fail the process (e.g., raise
SystemExit(1) or call sys.exit(1)) so that logger.error("Отсутствуют токены!")
is followed by an explicit non-zero exit when TELEGRAM_TOKEN or DEEPSEEK_API_KEY
are not set.

Comment thread main.py
Comment on lines +66 to +68
application = Application.builder().token(TELEGRAM_TOKEN).build()
application.add_handler(CommandHandler("start", start))
application.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, handle_message))

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

/hello is now a dead command.

commands.py:1-16 shows /hello was part of the bot's public command set. Here only /start is registered, and Line 68 excludes commands from the fallback handler, so /hello now does nothing. Re-add it here or remove it from the public contract intentionally.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@main.py` around lines 66 - 68, The public `/hello` command was removed from
the bot runtime: in main.py you register only CommandHandler("start", start)
while commands.py declares `/hello`; either re-register the handler or remove it
from the public commands list. Fix by adding a CommandHandler for "hello" (e.g.,
CommandHandler("hello", hello)) alongside the existing CommandHandler("start",
start) so the hello handler function (hello) is actually invoked, or else delete
`/hello` from commands.py so the public contract matches the registered
handlers; update references to Application.builder(), CommandHandler, start,
MessageHandler and handle_message accordingly.

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