Repository navigation
Update main.py - #36
googlanubis-create wants to merge 1 commit into
Conversation
📝 WalkthroughWalkthroughMigrated from synchronous Changes
Sequence DiagramsequenceDiagram
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
Estimated Code Review Effort🎯 4 (Complex) | ⏱️ ~40 minutes Poem
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
📝 Coding Plan
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 |
There was a problem hiding this comment.
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.
| """Обработчик всех текстовых сообщений""" | ||
| try: | ||
| user_message = update.message.text | ||
| user_name = update.message.from_user.first_name |
There was a problem hiding this comment.
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.
| "max_tokens": 2000 | ||
| } | ||
|
|
||
| response = requests.post(DEEPSEEK_API_URL, headers=headers, json=payload, timeout=30) |
There was a problem hiding this comment.
🧩 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 -20Repository: aeither/telegram-bot-python
Length of output: 171
🏁 Script executed:
find . -name "main.py" -type f 2>/dev/nullRepository: aeither/telegram-bot-python
Length of output: 80
🏁 Script executed:
head -60 main.pyRepository: 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.
| except Exception as e: | ||
| logger.error(f"Error: {e}") | ||
| await update.message.reply_text(f"Ошибка: {e}") |
There was a problem hiding this comment.
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.
| 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.
| if not TELEGRAM_TOKEN or not DEEPSEEK_API_KEY: | ||
| logger.error("Отсутствуют токены!") | ||
| return |
There was a problem hiding this comment.
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.
| 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.
| application = Application.builder().token(TELEGRAM_TOKEN).build() | ||
| application.add_handler(CommandHandler("start", start)) | ||
| application.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, handle_message)) |
There was a problem hiding this comment.
/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.
Summary by CodeRabbit
New Features
/startcommand.Bug Fixes