diff --git a/src/core/config.py b/src/core/config.py
index f5f78fd..1998685 100644
--- a/src/core/config.py
+++ b/src/core/config.py
@@ -7,6 +7,7 @@ class Settings(BaseSettings):
BOT_TOKEN: str
DATABASE_URL: str
ADMIN_API_KEY: str
+ LOGGING_LEVEL: str
settings = Settings()
diff --git a/src/core/logging.py b/src/core/logging.py
index 13c513c..7304dae 100644
--- a/src/core/logging.py
+++ b/src/core/logging.py
@@ -11,9 +11,10 @@ def setup_logging():
Конфигурирует консольный и файловый логгеры с ротацией.
"""
# Получаем уровень логирования из настроек, по умолчанию INFO
- level_name = settings.log_level.upper() if hasattr(settings, 'log_level') else 'INFO'
+ level_name = settings.LOGGING_LEVEL if hasattr(settings, 'LOGGING_LEVEL') else 'INFO'
log_level = getattr(logging, level_name, logging.INFO)
+
# Форматтер для всех хэндлеров
formatter = logging.Formatter(
fmt="%(asctime)s %(levelname)s [%(name)s] %(message)s",
@@ -53,4 +54,4 @@ def setup_logging():
setup_logging()
# Получаем logger для текущего модуля
-logger = logging.getLogger(__name__)
\ No newline at end of file
+logger = logging.getLogger(__name__)
diff --git a/src/docbot/handlers/admins/verify_handler.py b/src/docbot/handlers/admins/verify_handler.py
index 49c90e5..3f9c5a8 100644
--- a/src/docbot/handlers/admins/verify_handler.py
+++ b/src/docbot/handlers/admins/verify_handler.py
@@ -174,4 +174,5 @@ def get_verify_handler():
],
},
fallbacks=[],
+ allow_reentry=True,
)
diff --git a/src/docbot/handlers/doctors/add_payments_method.py b/src/docbot/handlers/doctors/add_payments_method.py
index d422caf..851038c 100644
--- a/src/docbot/handlers/doctors/add_payments_method.py
+++ b/src/docbot/handlers/doctors/add_payments_method.py
@@ -5,11 +5,11 @@ from telegram.ext import (
CommandHandler,
MessageHandler,
filters,
+ CallbackQueryHandler
)
from docbot.handlers.utils.cancel_handler import get_cancel_handler
from docbot.services.doctors_service import add_payment_link
-from docbot.handlers.utils.utils import cleanup_session
from core.enums.dialog_helpers import ConfirmationMessage
from core.logging import logger
from core.utils import is_valid_url
@@ -28,11 +28,11 @@ async def send_info(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
[
InlineKeyboardButton(
ConfirmationMessage.PROCEED.value,
- callback_data="accepted"
+ callback_data="pay:accepted"
),
InlineKeyboardButton(
ConfirmationMessage.DECLINE.value,
- callback_data="declined"
+ callback_data="pay:declined"
),
]
]
@@ -51,7 +51,7 @@ async def send_info(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
async def ask_payment_link(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
user_id = context.user_data['user_id']
- await update.message.reply_text(
+ await update.callback_query.message.reply_text(
text="Введите адрес вашей платёжной ссылки, пожалуйста."
)
logger.info(f"Ask user {user_id} to enter their payment link.")
@@ -67,7 +67,7 @@ async def ask_payment_system_api(update: Update, context: ContextTypes.DEFAULT_T
if is_valid_url(payment_link):
logger.info(f"Payment link {payment_link} provided by user {user_id} is valid.")
await update.message.reply_text(
- text="Введите API ключ, который указан у вас личном кабинете плтёжной системы, пожалуйста."
+ text="Введите API ключ, который указан у вас личном кабинете платёжной системы, пожалуйста."
)
return ASK_PAYMENT_SYSTEM_API
else:
@@ -106,8 +106,7 @@ def get_add_payment_method_handler() -> ConversationHandler:
entry_points=[add_payment_method()],
states={
ASK_PAYMENT_LINK: [
- MessageHandler(filters.TEXT & ~filters.COMMAND,
- ask_payment_link)
+ CallbackQueryHandler(ask_payment_link, pattern="^(pay:accepted)$")
],
ASK_PAYMENT_SYSTEM_API: [
MessageHandler(filters.TEXT & ~filters.COMMAND,
@@ -121,4 +120,5 @@ def get_add_payment_method_handler() -> ConversationHandler:
fallbacks=[get_cancel_handler()],
name="add_payment_method",
persistent=True,
+ allow_reentry=True,
)
diff --git a/src/docbot/handlers/doctors/register_handler.py b/src/docbot/handlers/doctors/register_handler.py
index 906a5f6..243d72d 100644
--- a/src/docbot/handlers/doctors/register_handler.py
+++ b/src/docbot/handlers/doctors/register_handler.py
@@ -212,5 +212,6 @@ def get_register_doctor_first_stage_handler() -> ConversationHandler:
},
fallbacks=[get_cancel_handler()],
name="register_doctor_conversation_first_stage", # для тестов/логирования
- persistent=True, # если используете хранение состояний
+ persistent=True,
+ allow_reentry=True, # если используете хранение состояний
)
diff --git a/src/docbot/handlers/patients/consultation_handler.py b/src/docbot/handlers/patients/consultation_handler.py
index df6c2a3..14c99cc 100644
--- a/src/docbot/handlers/patients/consultation_handler.py
+++ b/src/docbot/handlers/patients/consultation_handler.py
@@ -43,11 +43,11 @@ keyboard = [
[
InlineKeyboardButton(
"Записаться на консультацию",
- callback_data="proceed_with_consultation"
+ callback_data="consult:proceed_with_consultation"
),
InlineKeyboardButton(
"Частые вопросы",
- callback_data="frequent_questions"
+ callback_data="consult:frequent_questions"
),
]
]
@@ -58,11 +58,11 @@ async def accept_personal_data_agreement(update: Update, context: ContextTypes.D
[
InlineKeyboardButton(
ConfirmationMessage.PROCEED.value,
- callback_data="accepted"
+ callback_data="consult:accepted"
),
InlineKeyboardButton(
ConfirmationMessage.DECLINE.value,
- callback_data="declined"
+ callback_data="consult:declined"
),
]
]
@@ -94,7 +94,7 @@ async def receive_patient_aceptance(update: Update, context: ContextTypes.DEFAUL
user_data = context.user_data
await update.callback_query.answer()
- if update.callback_query.data == "accepted":
+ if update.callback_query.data == "consult:accepted":
user_data['accepted'] = True
user_id = user_data['telegram_id']
await create_patient(telegram_id=user_id, terms_acceptance=True) # Создаем пациента в БД
@@ -118,11 +118,11 @@ async def choose_consultation_type(update: Update, context: ContextTypes.DEFAULT
[
InlineKeyboardButton(
"Первичная консультация",
- callback_data="initial_reception"
+ callback_data="consult:initial_reception"
),
InlineKeyboardButton(
"Повторная консультация",
- callback_data="readmission"
+ callback_data="consult:readmission"
),
]
]
@@ -181,7 +181,7 @@ async def receive_patient_phone(update: Update, context: ContextTypes.DEFAULT_TY
[
InlineKeyboardButton(
"Изменить",
- callback_data="back"
+ callback_data="consult:back"
),
]
]
@@ -199,7 +199,7 @@ async def receive_patient_phone(update: Update, context: ContextTypes.DEFAULT_TY
[
InlineKeyboardButton(
"Изменить",
- callback_data="back"
+ callback_data="consult:back"
),
]
]
@@ -251,11 +251,11 @@ async def receive_consultation_date(update: Update, context: ContextTypes.DEFAUL
[
InlineKeyboardButton(
"Изменить",
- callback_data="back"
+ callback_data="consult:back"
),
InlineKeyboardButton(
"Продолжить",
- callback_data="proceed"
+ callback_data="consult:proceed"
),
]
]
@@ -304,23 +304,24 @@ def get_consultation_handler() -> ConversationHandler:
return ConversationHandler(
entry_points=[consultation_handler()],
states={
- SEND_ACKNOWLEDGEMENT_INFO: [CallbackQueryHandler(receive_patient_aceptance)],
- PROCEED_WITH_CONSULTATION: [CallbackQueryHandler(choose_consultation_type)],
- SELECT_CONSULTATION_TYPE: [CallbackQueryHandler(enter_patient_phone)],
+ SEND_ACKNOWLEDGEMENT_INFO: [CallbackQueryHandler(receive_patient_aceptance, pattern=r"^consult:(accepted|declined)$")],
+ PROCEED_WITH_CONSULTATION: [CallbackQueryHandler(choose_consultation_type, pattern=r"^consult:proceed$")],
+ SELECT_CONSULTATION_TYPE: [CallbackQueryHandler(enter_patient_phone, pattern=r"^consult:(initial_reception|readmission)$")],
ENTER_PATIENT_PHONE: [MessageHandler(filters=filters.TEXT & ~filters.COMMAND, callback=receive_patient_phone)],
ENTER_DOCTOR_NUMBER: [
MessageHandler(filters.TEXT & ~filters.COMMAND, receive_doctor_number),
- CallbackQueryHandler(enter_patient_phone, pattern="^" + "back" + "$")
+ CallbackQueryHandler(enter_patient_phone, pattern="^consult:back$")
],
ENTER_CONSULTATION_DATE: [MessageHandler(filters=filters.TEXT & ~filters.COMMAND, callback=receive_consultation_date)],
PAY_CONSULTATION: [
- CallbackQueryHandler(pay_consultation, pattern="^" + "proceed" + "$"),
- CallbackQueryHandler(receive_doctor_number, pattern="^" + "back" + "$")
+ CallbackQueryHandler(pay_consultation, pattern="^consult:proceed$"),
+ CallbackQueryHandler(receive_doctor_number, pattern="^consult:back$")
],
- ERROR_PHONE_NUMBER: [CallbackQueryHandler(enter_patient_phone, pattern="^" + "back" + "$")],
+ ERROR_PHONE_NUMBER: [CallbackQueryHandler(enter_patient_phone, pattern="^consult:back$")],
STOPPING: [get_start_handler()],
},
fallbacks=[get_cancel_handler()],
name="consultation_dialog",
persistent=True,
+ allow_reentry=True,
)
diff --git a/src/docbot/handlers/patients/send_form_handler.py b/src/docbot/handlers/patients/send_form_handler.py
index f2c6599..98c2e10 100644
--- a/src/docbot/handlers/patients/send_form_handler.py
+++ b/src/docbot/handlers/patients/send_form_handler.py
@@ -64,6 +64,7 @@ def get_send_form_handler() -> ConversationHandler:
],
},
fallbacks=[get_cancel_handler()],
- name="send_form_conversation", # для тестов/логирования
- persistent=True, # если используете хранение состояний
- )
\ No newline at end of file
+ name="send_form_conversation",
+ persistent=True,
+ allow_reentry=True,
+ )
diff --git a/src/docbot/handlers/start_handler.py b/src/docbot/handlers/start_handler.py
index 4a0b2d7..6d869e0 100644
--- a/src/docbot/handlers/start_handler.py
+++ b/src/docbot/handlers/start_handler.py
@@ -1,6 +1,6 @@
from telegram import Update
+from telegram.constants import ParseMode
from telegram.ext import ContextTypes, CommandHandler
-from core.logging import logger
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
@@ -8,12 +8,13 @@ async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
Отправляет приветствие и краткую инструкцию по работе с ботом.
"""
text = (
- "👋 Добро пожаловать в DocBot!\n\n"
- "Используйте команду /consultation, чтобы произвести запись на консультацию, если вы пациент.\n"
- "Используйте команду /register, если вы врач и у вас есть реферальный код."
+ "👋 Добро пожаловать в DocBot!\n"
+ "Используйте команду /consultation, чтобы произвести запись на консультацию, если вы пациент.\n\n"
+ "Используйте команду /register, если вы врач и у вас есть реферальный код.\n\n"
+ "Используйте команду /help, чтобы увидеть список доступных вам команд."
)
- await context.bot.send_message(chat_id=update.effective_chat.id, text=text)
+ await context.bot.send_message(chat_id=update.effective_chat.id, text=text, parse_mode=ParseMode.HTML)
def get_start_handler() -> CommandHandler:
diff --git a/src/docbot/handlers/utils/cancel_handler.py b/src/docbot/handlers/utils/cancel_handler.py
index d733d3f..5b2078c 100644
--- a/src/docbot/handlers/utils/cancel_handler.py
+++ b/src/docbot/handlers/utils/cancel_handler.py
@@ -1,4 +1,4 @@
-from telegram import Update
+from telegram import Update, ReplyKeyboardRemove
from telegram.ext import (
ContextTypes,
ConversationHandler,
@@ -7,7 +7,10 @@ from telegram.ext import (
async def cancel(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
- await update.message.reply_text("❌ Отменено.")
+ await update.message.reply_text(
+ "❌ Отменено.",
+ reply_markup=ReplyKeyboardRemove()
+ )
return ConversationHandler.END
diff --git a/src/docbot/handlers/utils/help.py b/src/docbot/handlers/utils/help.py
index bd51843..d8dab50 100644
--- a/src/docbot/handlers/utils/help.py
+++ b/src/docbot/handlers/utils/help.py
@@ -1,5 +1,8 @@
-from telegram import Update, ReplyKeyboardMarkup, ReplyKeyboardRemove
-from telegram.ext import ContextTypes, CommandHandler
+from telegram import Update
+from telegram.ext import (
+ ContextTypes, CommandHandler, ConversationHandler
+)
+from telegram.constants import ParseMode
from docbot.services.admins_service import get_admin_info
from docbot.services.doctors_service import get_doctor
@@ -25,30 +28,30 @@ async def help_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> No
)
# (При необходимости в будущем можно добавить другие admin-команды)
await update.message.reply_text(text, parse_mode="Markdown")
- return
# 2) Проверим, зарегистрирован ли врач
- if await get_doctor(user_id):
+ elif await get_doctor(user_id):
text = (
- "👨⚕️ *Меню доктора*:\n\n"
+ "👨⚕️ Меню доктора:\n"
+ "/start Запустить бота\n"
+ "/payment_methods Настроить платёжные способы\n"
+ "/help Показать это меню\n"
+ )
+
+ await update.message.reply_text(text, parse_mode=ParseMode.HTML)
+
+ # 3) Иначе — это пациент (незарегистрированный/обычный пользователь)
+ else:
+ text = (
+ "👤 *Меню пациента*:\n\n"
"/start ‒ Запустить бота\n"
- "/sessions ‒ Посмотреть список пациентов (или текущих сессий)\n"
+ "/get_form ‒ Получить ссылку на форму анкеты для заполнения"
+ "/send_form ‒ Отправить ссылку на заполненную анкету\n"
"/help ‒ Показать это меню\n"
)
await update.message.reply_text(text, parse_mode="Markdown")
- return
-
- # 3) Иначе — это пациент (незарегистрированный/обычный пользователь)
- text = (
- "👤 *Меню пациента*:\n\n"
- "/start ‒ Запустить бота\n"
- "/get_form ‒ Получить ссылку на форму анкеты для заполнения"
- "/send_form ‒ Отправить ссылку на заполненную анкету\n"
- "/help ‒ Показать это меню\n"
- )
-
- await update.message.reply_text(text, parse_mode="Markdown")
+ return ConversationHandler.END
def get_help_handler() -> CommandHandler:
diff --git a/src/docbot/handlers/utils/unknown.py b/src/docbot/handlers/utils/unknown.py
index 753817f..6f1bc77 100644
--- a/src/docbot/handlers/utils/unknown.py
+++ b/src/docbot/handlers/utils/unknown.py
@@ -15,4 +15,4 @@ async def unknown_command(update: Update, context: ContextTypes.DEFAULT_TYPE) ->
def get_unknown_handler() -> MessageHandler:
"""Фабрика для регистрации в Application."""
- return MessageHandler(filters.COMMAND, unknown_command)
\ No newline at end of file
+ return MessageHandler(filters.COMMAND, unknown_command)
diff --git a/src/docbot/main.py b/src/docbot/main.py
index d544fc1..dfd41cc 100644
--- a/src/docbot/main.py
+++ b/src/docbot/main.py
@@ -26,21 +26,21 @@ def main():
.concurrent_updates(concurrent_updates=False)
.build()
)
- app.add_handler(get_start_handler(), group=0)
- app.add_handler(get_cancel_handler(), group=0)
- app.add_handler(get_help_handler(), group=0)
- app.add_handler(get_consultation_handler(), group=1)
- app.add_handler(get_send_form_handler(), group=2)
- app.add_handler(get_doctors_handler(), group=3)
- app.add_handler(get_register_doctor_first_stage_handler(), group=1)
- app.add_handler(get_referral_handlers(), group=3)
- app.add_handler(get_verify_handler(), group=3)
- app.add_handler(get_unknown_handler(), group=0)
- app.add_handler(get_add_payment_method_handler(), group=1)
- app.add_error_handler(get_start_handler())
- app.add_handlers
- logger.debug("Все хэндлеры зарегистрированы, запускаем polling")
+ app.add_handler(get_start_handler())
+ app.add_handler(get_cancel_handler())
+ app.add_handler(get_help_handler())
+ app.add_handler(get_consultation_handler())
+ app.add_handler(get_send_form_handler())
+ app.add_handler(get_doctors_handler())
+ app.add_handler(get_register_doctor_first_stage_handler())
+ app.add_handler(get_referral_handlers())
+ app.add_handler(get_verify_handler())
+ app.add_handler(get_add_payment_method_handler())
+
+ app.add_handler(get_unknown_handler())
+
+ logger.info("Все хэндлеры зарегистрированы, запускаем polling")
app.run_polling()