Skip to content

Commit 79833f0

Browse files
committed
Refactor error handling in bot and LLM modules; improve logging format and add state management in planner
1 parent 8ba6e7d commit 79833f0

File tree

4 files changed

+41
-11
lines changed

4 files changed

+41
-11
lines changed

bot.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,10 @@ async def main():
3030
try:
3131
logger.info("Starting bot...")
3232
await dp.start_polling(bot)
33-
except Exception as e:
34-
logger.error(f"Error starting bot: {e}")
33+
except (KeyboardInterrupt, SystemExit):
34+
logger.info("Bot stopped!")
35+
except Exception as e: # pylint: disable=broad-exception-caught
36+
logger.error("Error starting bot: %s", e)
3537

3638

3739
asyncio.run(main())

handlers/planner.py

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,13 @@ class PlanFormat(StatesGroup):
1515
"""State machine for selecting the format of the study plan."""
1616
waiting_for_format = State()
1717
waiting_for_topic = State()
18+
waiting_for_next_action = State()
1819

1920
def __str__(self):
2021
return "PlanFormat FSM"
2122

2223

23-
@router.message(Command("plan")) # Changed from /start to /plan
24+
@router.message(Command("plan"))
2425
async def cmd_plan(message: types.Message, state: FSMContext):
2526
await state.set_state(PlanFormat.waiting_for_format)
2627
await message.answer(
@@ -63,4 +64,29 @@ async def handle_topic(message: types.Message, state: FSMContext):
6364
document=types.FSInputFile(txt_path),
6465
caption="📄 Твой учебный план в TXT")
6566

67+
await state.set_state(PlanFormat.waiting_for_next_action)
68+
await message.answer(
69+
"Что ещё ты хотел бы сделать?",
70+
reply_markup=types.InlineKeyboardMarkup(
71+
inline_keyboard=[
72+
[types.InlineKeyboardButton(text="🔄 Создать новый план",
73+
callback_data="new_plan")],
74+
[types.InlineKeyboardButton(text="👋 Ничего, хорошего дня!",
75+
callback_data="goodbye")]
76+
]
77+
)
78+
)
79+
80+
81+
@router.callback_query(PlanFormat.waiting_for_next_action, F.data == "new_plan")
82+
async def handle_new_plan(callback: types.CallbackQuery, state: FSMContext):
83+
await callback.answer()
84+
await callback.message.edit_text("Создаем новый план!")
85+
await cmd_plan(callback.message, state)
86+
87+
88+
@router.callback_query(PlanFormat.waiting_for_next_action, F.data == "goodbye")
89+
async def handle_goodbye(callback: types.CallbackQuery, state: FSMContext):
90+
await callback.answer()
91+
await callback.message.edit_text("Хорошего дня! 👋 Буду рад помочь снова, когда понадобится.")
6692
await state.clear()

services/llm.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
# Локальный генератор
1818
def generate_local_plan(topic: str) -> list:
1919
"""Generate a basic study plan without using API"""
20-
logger.info(f"Using local plan generator for topic: {topic}")
20+
logger.info("Using local plan generator for topic: %s", topic)
2121

2222
plan = [
2323
f"Учебный план по теме: {topic}",
@@ -45,7 +45,8 @@ async def generate_study_plan(topic: str) -> list:
4545
for attempt in range(MAX_RETRIES):
4646
try:
4747
logger.info(
48-
f"Generating study plan for topic: {topic} (attempt {attempt + 1}/{MAX_RETRIES})")
48+
"Generating study plan for topic: %s (attempt %s/%s)",
49+
topic, attempt + 1, MAX_RETRIES)
4950

5051
response = client.chat.completions.create(
5152
model="gpt-3.5-turbo",
@@ -58,16 +59,17 @@ async def generate_study_plan(topic: str) -> list:
5859
return text.strip().split("\n")
5960

6061
except RateLimitError as e:
61-
logger.warning(f"Rate limit error: {str(e)}. Retrying in {RETRY_DELAY} seconds...")
62+
logger.warning("Rate limit error: %s. Retrying in %s seconds...",
63+
str(e), RETRY_DELAY * (attempt + 1))
6264
await asyncio.sleep(RETRY_DELAY * (attempt + 1)) # Экспоненциальная задержка
6365

6466
except (APIError, OpenAIError) as e:
65-
logger.error(f"OpenAI API error: {str(e)}")
67+
logger.error("OpenAI API error: %s", str(e))
6668
logger.info("Falling back to local plan generator")
6769
return generate_local_plan(topic)
6870

69-
except Exception as e:
70-
logger.error(f"Unexpected error: {str(e)}")
71+
except Exception as e: # pylint: disable=broad-exception-caught
72+
logger.error("Unexpected error: %s", str(e))
7173
return generate_local_plan(topic)
7274

7375
# Если все попытки исчерпаны, используем локальный генератор

services/pdf.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,15 @@ def save_plan_to_pdf(plan_lines: list[str], user_id: int) -> str:
2222
else:
2323
# Fallback to standard font
2424
pdf.set_font("Arial", size=12)
25-
except Exception:
25+
except (IOError, RuntimeError): # Specify expected exceptions
2626
# If error with custom font, use standard
2727
pdf.set_font("Arial", size=12)
2828

2929
# Convert non-Latin characters to ensure compatibility
3030
for line in plan_lines:
3131
try:
3232
pdf.multi_cell(0, 10, txt=line)
33-
except Exception:
33+
except (UnicodeEncodeError, RuntimeError): # Specify expected exceptions
3434
# Handle encoding issues
3535
pdf.multi_cell(0, 10, txt="[Text encoding error]")
3636

0 commit comments

Comments
 (0)