Browse Source

проект Bot_Polimed

master
Ilya_Chis 2 days ago
commit
1909a9b75f
  1. 1
      .gitignore
  2. 3
      .idea/.gitignore
  3. 6
      .idea/inspectionProfiles/profiles_settings.xml
  4. 7
      .idea/misc.xml
  5. 8
      .idea/modules.xml
  6. 10
      .idea/pythonProject.iml
  7. 676
      BotPM.py
  8. 564
      PM.py
  9. BIN
      __pycache__/BotPM.cpython-38.pyc
  10. 13
      botforclinic-436512-0c117dd103a8.json
  11. 122
      doctors.json
  12. 461
      proba1PM.py
  13. BIN
      requirements.txt
  14. BIN
      s-blob-v1-IMAGE-tdNCrEv8Ldo.png

1
.gitignore vendored

@ -0,0 +1 @@
.venv/

3
.idea/.gitignore vendored

@ -0,0 +1,3 @@
# Default ignored files
/shelf/
/workspace.xml

6
.idea/inspectionProfiles/profiles_settings.xml

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>

7
.idea/misc.xml

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Black">
<option name="sdkName" value="Python 3.8 (Bot_for_clinic)" />
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.8 (Bot_for_clinic)" project-jdk-type="Python SDK" />
</project>

8
.idea/modules.xml

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/pythonProject.iml" filepath="$PROJECT_DIR$/.idea/pythonProject.iml" />
</modules>
</component>
</project>

10
.idea/pythonProject.iml

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.venv" />
</content>
<orderEntry type="jdk" jdkName="Python 3.8 (Bot_for_clinic)" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

676
BotPM.py

@ -0,0 +1,676 @@
import requests
import aiohttp
from aiogram import Bot, Dispatcher, types
from aiogram.contrib.fsm_storage.memory import MemoryStorage
from aiogram.dispatcher.filters.state import State, StatesGroup
from aiogram.utils import executor
import re
from aiogram.types import ReplyKeyboardMarkup, KeyboardButton
import asyncio
from aiogram.dispatcher import FSMContext
from aiogram import types
from aiogram.dispatcher.filters import Command
from datetime import datetime, timedelta
import gspread
from oauth2client.service_account import ServiceAccountCredentials
import re
from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton, WebAppInfo
import logging
from aiogram.types import ReplyKeyboardRemove
TOKEN = '7907319434:AAEEM55xbWHhp5uPAlJ5AS2vNoleES_z_Kk'
bot = Bot(token=TOKEN)
storage = MemoryStorage()
dp = Dispatcher(bot, storage=storage)
# Кнопка для перезапуска
restart_button = ReplyKeyboardMarkup(resize_keyboard=True)
restart_button.add(KeyboardButton("Перезапустить бота"))
MAX_ATTEMPTS = 3 # Максимальное количество попыток ввода кода
TIMEOUT = 30 # Время в секундах
# Словарь для хранения данных о пользователях
user_data = {}
last_bot_message_id = {}
# Авторизация и доступ к таблице
scope = ["https://spreadsheets.google.com/feeds", "https://www.googleapis.com/auth/drive"]
credentials = ServiceAccountCredentials.from_json_keyfile_name("botforclinic-436512-0c117dd103a8.json", scope)
client = gspread.authorize(credentials)
sheet = client.open("Пациенты клиники").sheet1 # Открытие таблицы, используйте название вашей таблицы
# Словарь для хранения данных о сообщениях пользователей
user_messages = {}
# История состояний для каждого пользователя
user_states = {}
class Form(StatesGroup):
telegram_id = State()
existing_patient = State()
phone_number = State()
fio = State()
birthday = State()
verification_code = State()
confirm_fio = State()
confirm_phone_number = State()
# Создаем состояния
class QuestionForm(StatesGroup):
waiting_for_question = State()
from aiogram import types
# Настройка логирования
logging.basicConfig(level=logging.INFO)
# Главное меню
main_menu = InlineKeyboardMarkup(row_width=2).add(
InlineKeyboardButton("🌍 Контакты", callback_data="menu_contacts"),
InlineKeyboardButton("📞 Связь", callback_data="menu_contact")
)
# Подменю "контакты"
contacts_menu = InlineKeyboardMarkup(row_width=1).add(
InlineKeyboardButton(" Назад", callback_data="main_menu")
)
# Меню связь
contact_menu = InlineKeyboardMarkup(row_width=1).add(
InlineKeyboardButton("💬 Отправить сообщение администратору Клиники", callback_data="contact_administrator"),
InlineKeyboardButton("🛎 Заказать звонок от администратора Клиники", callback_data="order_call"),
InlineKeyboardButton(" Назад", callback_data="main_menu"),
)
administrator_contact = InlineKeyboardMarkup(row_width=1).add(
InlineKeyboardButton("✍🏼 Написать сообщение", callback_data="message_admin"),
InlineKeyboardButton(" Назад", callback_data="menu_contact"),
InlineKeyboardButton("🔘 Главное меню", callback_data="main_menu")
)
message_ad = InlineKeyboardMarkup(row_width=1).add(
InlineKeyboardButton(" Назад", callback_data="contact_administrator"),
InlineKeyboardButton("🔘 Главное меню", callback_data="main_menu")
)
call_order = InlineKeyboardMarkup(row_width=1).add(
InlineKeyboardButton("📞 Позвонить мне", callback_data="call_me"),
InlineKeyboardButton(" Назад", callback_data="menu_contact"),
InlineKeyboardButton("🔘 Главное меню", callback_data="main_menu")
)
return_call_me = InlineKeyboardMarkup(row_width=1).add(
InlineKeyboardButton(" Назад", callback_data="order_call"),
InlineKeyboardButton("🔘 Главное меню", callback_data="main_menu")
)
whatsapp = InlineKeyboardMarkup(row_width=1).add(
InlineKeyboardButton("🔘 Главное меню", callback_data="main_menu")
)
# Обработка нажатий на инлайн-кнопки
@dp.callback_query_handler(lambda c: c.data.startswith("menu_") or c.data == "main_menu")
async def handle_main_menu(call: types.CallbackQuery):
if call.data == "main_menu":
await call.message.edit_text("В настоящее время я, как Ваш виртуальный помощник, активно развиваюсь."
" В ближайшее время у меня появятся новые функции и возможности."
" А пока Вы можете ознакомиться с текущим меню.", reply_markup=main_menu)
elif call.data == "menu_contacts":
await call.message.edit_text("Клиники им. проф. Е.Н.Оленевой\n\n"
"Клиника УХО•ГОРЛО•НОС\n"
"Записаться на приём, задать вопрос:\n"
"📞 +7 (342) 207-03-03\n\n"
"Больше информации о клинике и врачах на нашем <a href='https://perm.oclinica.ru/lor'>🔗САЙТЕ</a>\n"
"📍г. Пермь, ул. К. Цеткин, 9\n"
"(ост. Строительный факультет)\n"
"<a href='https://tinyurl.com/286a8tv7'>Построить маршрут</a>\n\n"
"--------------\n\n"
"Клиника лечения КАШЛЯ•АЛЛЕРГИИ\n"
"Записаться на приём, задать вопрос:\n"
"📞 +7 (342) 200-02-03\n\n"
"Больше информации о клинике и врачах на нашем <a href='https://perm.oclinica.ru/allergo'>🔗САЙТЕ</a>\n\n"
"📍г. Пермь, ул. Пермь, ул. Г. Звезда, 31А\n"
"(ост. Г. Звезда)\n"
"<a href='https://tinyurl.com/9a9w5pdu'>Построить маршрут</a>\n\n"
"--------------\n\n"
"Центр ДИАГНОСТИКИ И РЕАБИЛИТАЦИИ \n"
"📞 +7 (342) 287-16-94\n\n"
"Больше информации о клинике и врачах на нашем <a href='https://cdr.oclinica.ru/'>🔗САЙТЕ</a>\n\n"
"📍 г. Пермь, ул. Пермь, ул. Г. Звезда, 31А\n"
" (ост. Г. Звезда)\n"
"<a href='https://tinyurl.com/9a9w5pdu'>Построить маршрут</a>\n\n"
"Присоединяйтесь к нашему каналу новостей в <a href='https://t.me/permlor'>Telegram</a>.", reply_markup=contacts_menu, parse_mode="HTML")
elif call.data == "menu_contact":
await call.message.edit_text("Выберите способ связи", reply_markup=contact_menu)
# Обработка нажатия на "Запись на исследование"
@dp.callback_query_handler(lambda c: c.data == "contact_administrator")
async def handle_call_menu(call: types.CallbackQuery):
await call.message.edit_text("💬 Для отправки сообщения администратору Клиники нажмите кнопку ниже 'Написать сообщение'.", reply_markup=administrator_contact)
# Обработка нажатия на "Запись на исследование"
@dp.callback_query_handler(lambda c: c.data == "order_call")
async def handle_admin_call_menu(call: types.CallbackQuery):
await call.message.edit_text("Для получения обратного звонка от администратора Клиники нажмите кнопку ниже 'Позвонить мне'.", reply_markup=call_order)
@dp.callback_query_handler(lambda c: c.data == "call_me")
async def handle_ad_call_menu(call: types.CallbackQuery):
try:
user_id = call.from_user.id # ID пользователя
records = sheet.get_all_records()
# Получаем данные пользователя из таблицы
user_data = next((entry for entry in records if str(entry['Telegram ID']) == str(user_id)), None)
if not user_data:
await call.message.answer("Ваши данные не найдены.", reply_markup=return_call_me)
return
phone_number = user_data['Номер телефона']
text = "Позвонить мне"
message_id = call.message.message_id
date = call.message.date.isoformat() # Конвертация даты
reply_to_message_id = call.message.reply_to_message.message_id if call.message.reply_to_message else None
# Передаём данные на сервер
await send_message_server(phone_number, text, message_id, user_id, date, reply_to_message_id)
await call.message.edit_text(
"Администратор Клиники свяжется с Вами в ближайшее время в рабочие часы и проконсультирует по всем вопросам.",
reply_markup=return_call_me
)
except Exception as e:
logging.error(f"Ошибка при обработке запроса: {e}")
await call.message.edit_text("Произошла ошибка. Попробуйте снова позже.", reply_markup=return_call_me)
# Обработчик кнопки "message_admin"
@dp.callback_query_handler(lambda c: c.data == "message_admin")
async def handle_ad_message(call: types.CallbackQuery, state: FSMContext):
user_id = str(call.from_user.id) # Преобразуем в строку для сравнения
try:
# Получение всех записей из таблицы
records = sheet.get_all_records()
# Поиск пользователя по Telegram ID
user_data = next((entry for entry in records if str(entry['Telegram ID']) == user_id), None)
if not user_data:
await call.message.answer("Ваши данные не найдены.", reply_markup=message_ad)
return
# Переход в состояние ожидания вопроса
prompt_message = await call.message.edit_text(
"Пожалуйста, отправьте Ваш вопрос администратору одним сообщением.",
reply_markup=message_ad
)
# Сохраняем ID сообщения
async with state.proxy() as data:
data["prompt_message_id"] = prompt_message.message_id
await QuestionForm.waiting_for_question.set() # Устанавливаем состояние ожидания=
except Exception as e:
logging.error(f"Ошибка при доступе к таблице: {e}")
await call.message.edit_text("Произошла ошибка. Попробуйте снова позже.", reply_markup=message_ad)
# Обработчик ввода вопроса
@dp.message_handler(state=QuestionForm.waiting_for_question, content_types=types.ContentTypes.TEXT)
async def handle_user_question(message: types.Message, state: FSMContext):
user_id = str(message.from_user.id) # ID пользователя
text = message.text # Сообщение пользователя
try:
# Удаление предыдущего сообщения
async with state.proxy() as data:
if "prompt_message_id" in data:
await bot.delete_message(chat_id=message.chat.id, message_id=data["prompt_message_id"])
# Отправка сообщения пользователя на сервер
await send_message_server2(user_id, text, message.message_id, user_id, message.date.isoformat(), None)
# Ответ пользователю
await message.answer(
"Ваше сообщение успешно отправлено! Администратор Клиники ответит Вам в ближайшее время в рабочие часы. Спасибо за Ваше обращение!",
reply_markup=message_ad
)
except Exception as e:
logging.error(f"Ошибка при обработке вопроса: {e}")
await message.answer(
"Произошла ошибка при отправке вопроса. Попробуйте позже.",
reply_markup=message_ad
)
# Завершаем состояние
await state.finish()
# Хранилище для уже обработанных пользователей
processed_users = set()
# Обработка нажатия на кнопку "Проверить данные"
@dp.callback_query_handler(lambda c: c.data == 'check_verification')
async def process_check_verification(callback_query: types.CallbackQuery, state: FSMContext):
user_id = callback_query.from_user.id
try:
# Чтение всех строк таблицы
records = sheet.get_all_records()
user_data_verified = False
for row in records:
fio = str(row.get("ФИО", "")).strip()
phone = str(row.get("Номер телефона", "")).strip()
telegram_id = str(row.get("Telegram ID", "")).strip()
# Проверяем, если в таблице есть данные для этого пользователя
if telegram_id == str(user_id):
user_data_verified = True
break
if user_data_verified:
await send_success_message(user_id) # Отправляем сообщение о успешной регистрации
else:
await bot.send_message(
user_id,
"Мы не нашли ваших данных в системе. Пожалуйста, проверьте, что вы правильно заполнили форму и попробуйте снова.",
reply_markup=InlineKeyboardMarkup().add(
InlineKeyboardButton("Попробовать снова", callback_data="check_verification")
)
)
except Exception as e:
print(f"Ошибка при проверке верификации: {e}")
await bot.send_message(user_id, "Произошла ошибка при проверке данных. Попробуйте позже.")
# Функция отправки сообщения об успешной регистрации
async def send_success_message(user_id):
try:
await bot.send_message(
chat_id=user_id,
text=("Ура! Ваша регистрация прошла успешно! 🥳\n\n"
"Теперь все уведомления о записи на приём будут приходить сюда, в чат-бот. "
"Если Вы также получаете рассылку в WhatsApp, то сообщения будут дублироваться. "
"Для получения рассылки только в чат-бот Telegram, нажмите кнопку ниже 'Не дублировать сообщения в WhatsApp'."),
reply_markup=InlineKeyboardMarkup().add(
InlineKeyboardButton("Не дублировать сообщения в WhatsApp", callback_data="stop_replying"),
InlineKeyboardButton("🔘 Главное меню", callback_data="main_menu")
)
)
except Exception as e:
print(f"Ошибка при отправке сообщения пользователю {user_id}: {e}")
@dp.callback_query_handler(lambda c: c.data == "stop_replying")
async def stop_replying_handler(call: types.CallbackQuery):
user_id = str(call.from_user.id) # Преобразуем в строку для сравнения
try:
# Получение всех записей из таблицы
records = sheet.get_all_records()
# Поиск пользователя по Telegram ID
user_data = next((entry for entry in records if str(entry['Telegram ID']) == user_id), None)
if not user_data:
await call.message.answer("Ваши данные не найдены.", reply_markup=whatsapp)
return
phone_number = user_data['Номер телефона'] # Измените на название вашего столбца
text = "Отключить дублирование в WhatsApp"
message_id = call.message.message_id
date = call.message.date.isoformat()
reply_to_message_id = call.message.reply_to_message.message_id if call.message.reply_to_message else None
# Отправка данных на сервер
await send_message_server(phone_number, text, message_id, call.from_user.id, date, reply_to_message_id)
# Ответ пользователю
await call.message.edit_text("Рассылка уведомлений в WhatsApp отключена.", reply_markup=whatsapp)
except Exception as e:
logging.error(f"Ошибка при доступе к таблице: {e}")
await call.message.edit_text("Произошла ошибка. Попробуйте снова позже.", reply_markup=whatsapp)
@dp.message_handler(commands=['help'])
async def handle_help(message: types.Message):
#await save_message_data(message)
user_id = message.from_user.id
help_message = "Список доступных команд:\n"
help_message += "/start - начать взаимодействие с ботом\n"
help_message += "/registration - регистрация\n"
help_message += "/help - показать список команд и их описания\n"
sent_message = await bot.send_message(user_id, help_message)
last_bot_message_id[user_id] = sent_message.message_id
@dp.message_handler(Command("start"), state="*")
async def handle_start(message: types.Message, state: FSMContext):
# Завершаем текущее состояние и очищаем данные пользователя
await state.finish() # Завершает текущее состояние
await state.storage.reset_data(user=message.from_user.id) # Удаляет все данные пользователя в FSM хранилище
# Отправляем фото
with open("s-blob-v1-IMAGE-tdNCrEv8Ldo.png", "rb") as photo:
await bot.send_photo(
chat_id=message.from_user.id,
photo=photo,
caption=("Добро пожаловать!\nЯ чат-бот Клиники и Ваш надежный виртуальный помощник.\nЧтобы узнать, что я могу для Вас сделать, просто введите /help\nДля начала работы нажмите кнопку /registration внизу."),
reply_markup=generate_markup_registration() # Кнопка для продолжения
)
@dp.message_handler(commands=['registration'], chat_type=types.ChatType.PRIVATE)
async def handle_registration(message: types.Message):
user_id = message.from_user.id
sent_message = await bot.send_message(user_id, "Вы уже являетесь пациентом нашей Клиники?\nЕсли Вы хотите начать общение с ботом заново, нажмите /start.",
reply_markup=yes_no_markup())
last_bot_message_id[user_id] = sent_message.message_id
await Form.existing_patient.set()
def generate_markup_telegram_id():
markup = types.ReplyKeyboardMarkup(row_width=2, resize_keyboard=True)
item3 = types.KeyboardButton("Отправить Telegram ID")
markup.add(item3)
return markup
def generate_markup_registration():
markup = types.ReplyKeyboardMarkup(row_width=1, resize_keyboard=True)
item_registration = types.KeyboardButton("/registration")
markup.add(item_registration)
return markup
def generate_back_button():
"""Создает клавиатуру с кнопкой 'Назад'."""
markup = ReplyKeyboardMarkup(row_width=1, resize_keyboard=True)
back_button = KeyboardButton("Назад") # Текст кнопки "Назад"
markup.add(back_button)
return markup
@dp.message_handler(state=Form.existing_patient)
async def handle_existing_patient(message: types.Message, state: FSMContext):
user_id = message.from_user.id
form_url = f"https://tgbotpolimed.pirogov.ai/?user_id={user_id}"
if not message.text.strip():
await message.answer(
"Пожалуйста, выберите 'Да' или 'Нет' с помощью кнопок.",
reply_markup=ReplyKeyboardRemove()
)
return
if message.text.lower() == "да":
await message.answer(
"В соответствии с Федеральным законом № 152-ФЗ «О персональных данных», для идентификации Вас как пациента нашей Клиники, просим заполнить форму, нажав на кнопку ниже.",
reply_markup=ReplyKeyboardRemove()
)
await message.answer(
"Ввод персональных данных",
reply_markup=InlineKeyboardMarkup().add(
InlineKeyboardButton(
text="Заполнить форму",
web_app=WebAppInfo(url=form_url)
)
)
)
# Отправляем кнопку для проверки данных
await message.answer(
"После того как Вы заполните форму, нажмите на кнопку ниже для проверки данных.\n"
"Если Вы хотите начать общение с ботом заново, нажмите /start.",
reply_markup=InlineKeyboardMarkup().add(
InlineKeyboardButton(
text="Проверить данные",
callback_data="check_verification"
)
)
)
await state.finish()
elif message.text.lower() == "нет":
await bot.send_message(
user_id,
"Полный доступ к функциям сервиса предоставляется только пациентам нашей Клиники.\n\n"
"Вы можете связаться с нами по тел.: +7 (342) 207-03-03 или посетить Клинику лично для заключения договора по следующим адресам:\n"
"г. Пермь, ул. Клары Цеткин, д. 9; ул. Газеты Звезда, д. 31-а.\n\n"
"Будьте здоровы!\n"
"Если Вы хотите начать общение с ботом заново, нажмите /start.",
reply_markup=generate_back_button() # Клавиатура с кнопкой "Назад"
)
await state.finish()
else:
await bot.send_message(
user_id,
"Пожалуйста, выберите 'Да' или 'Нет' с помощью кнопок.",
reply_markup=ReplyKeyboardRemove()
)
await state.finish()
# Обработчик кнопки "Назад"
@dp.message_handler(lambda message: message.text == "Назад")
async def handle_back_button(message: types.Message):
await handle_registration(message) # Вызываем функцию обработки команды /registration
def find_patients_by_id(telegram_id):
records = sheet.get_all_records() # Получаем все строки таблицы
patients = []
for record in records:
if str(record["Telegram ID"]) == str(telegram_id):
patients.append(record)
return patients
async def prompt_patient_selection(user_id, patient_records):
# Создаем кнопки с ФИО пациентов
markup = ReplyKeyboardMarkup(row_width=1, resize_keyboard=True)
for record in patient_records:
markup.add(KeyboardButton(record["ФИО"]))
# Сохраняем данные пациентов временно
user_data[user_id]["patients"] = patient_records
await bot.send_message(
user_id,
"Найдено несколько записей с вашим Telegram ID. Пожалуйста, выберите пациента:",
reply_markup=markup,
)
await Form.fio.set()
async def save_message_data(message: types.Message, reply_to_message_id=None):
user_id = message.from_user.id
reply_to_message_id = last_bot_message_id.get(user_id, None)
user_messages[message.message_id] = {
"message_id": message.message_id,
"text": message.text,
"date": message.date.isoformat(), # Исправлено
"user_id": message.from_user.id,
"reply_to_message_id": reply_to_message_id
}
print(f"Сообщение пользователя {user_id} сохранено: {user_messages[message.message_id]}")
await send_message_to_server(user_messages[message.message_id])
async def send_message_to_server(message_data):
url = "http://192.168.1.10:8080/AppSaveMessage"
headers = {"Content-Type": "application/json"}
async with aiohttp.ClientSession() as session:
async with session.post(url, headers=headers, json=message_data) as response:
if response.status == 200:
print(f"Сообщение {message_data['message_id']} успешно отправлено на сервер.")
else:
print(f"Ошибка при отправке сообщения {message_data['message_id']} на сервер. Статус-код: {response.status}")
# Функция для выполнения POST-запроса и получения списка врачей
def get_doctors():
url = "http://192.168.1.10:8080/AppZaprSpecDoc"
# Данные для отправки в запросе
data = {"spec_id": 1}
# Выполняем POST-запрос
response = requests.post(url, json=data)
# Проверяем статус ответа
if response.status_code == 200:
# Если запрос успешен, возвращаем данные
return response.json()
else:
# Если запрос не удался, выводим ошибку
print(f"Ошибка: {response.status_code}")
return []
def yes_no_markup():
markup = types.ReplyKeyboardMarkup(row_width=2, resize_keyboard=True)
item_no = types.KeyboardButton("Нет")
item_yes = types.KeyboardButton("Да")
markup.add(item_yes, item_no)
return markup
def markup2():
markup = types.ReplyKeyboardMarkup(row_width=2, resize_keyboard=True)
item_good = types.KeyboardButton("Всё верно")
item_no_good = types.KeyboardButton("Указать ФИО ещё раз")
markup.add(item_good, item_no_good)
return markup
def generate_start_markup():
markup = types.ReplyKeyboardMarkup(row_width=1, resize_keyboard=True)
start_button = types.KeyboardButton("/start")
markup.add(start_button)
return markup
async def send_message_server(phone_number, text, message_id, user_id, date, reply_to_message_id=None):
url = "http://192.168.1.10:8080/AppSaveMessage"
headers = {"Content-Type": "application/json"}
message_data = {
"message_id": message_id,
"text": text,
"date": date,
"user_id": user_id, # Передача ID пользователя
"reply_to_message_id": reply_to_message_id, # Если нужно указать reply_to_message_id
"phone_number": phone_number
}
async with aiohttp.ClientSession() as session:
async with session.post(url, json=message_data, headers=headers) as response:
if response.status == 200:
print(message_data)
logging.info("Сообщение успешно отправлено на сервер")
else:
logging.error(f"Ошибка при отправке сообщения: {response.status}")
async def send_message_server2(user_id, text, message_id, from_user_id, date, reply_to_message_id):
url = "http://192.168.1.10:8080/AppSaveMessage"
headers = {"Content-Type": "application/json"}
message_data = {
"user_id": user_id,
"text": text,
"message_id": message_id,
"from_user_id": from_user_id,
"date": date,
"reply_to_message_id": reply_to_message_id,
}
async with aiohttp.ClientSession() as session:
async with session.post(url, json=message_data, headers=headers) as response:
if response.status == 200:
logging.info("Сообщение успешно отправлено на сервер")
else:
logging.error(f"Ошибка при отправке сообщения: {response.status}")
def find_patient_by_id(telegram_id):
records = sheet.get_all_records() # Получаем все строки таблицы
for record in records:
if str(record["Telegram ID"]) == str(telegram_id): # Сравнение с Telegram ID
phone_raw = record["Номер телефона"]
# Удаляем все нецифровые символы
phone_formatted = re.sub(r"\D", "", phone_raw)
# Проверка на правильную длину номера и корректировка, если необходимо
if len(phone_formatted) == 11:
if phone_formatted.startswith("8"): # Если номер начинается с 8, заменяем на 7
phone_formatted = "7" + phone_formatted[1:]
return phone_formatted
else:
return None # Возвращаем None, если номер неправильной длины
return None
def authorize_google():
# google_json = {}
# for key in config["GOOGLE"].keys():
# google_json[key] = config["GOOGLE"][key]
scope = ["https://spreadsheets.google.com/feeds", "https://www.googleapis.com/auth/drive"]
creds = ServiceAccountCredentials.from_json_keyfile_name("botforclinic-436512-0c117dd103a8.json", scope)
# creds = ServiceAccountCredentials.from_json_keyfile_dict(google_json, scope)
client = gspread.authorize(creds)
return client
@dp.message_handler(content_types=types.ContentType.TEXT)
async def handle_message(message: types.Message):
await save_message_data(message)
if __name__ == '__main__':
executor.start_polling(dp, skip_updates=True)

564
PM.py

@ -0,0 +1,564 @@
import requests
import aiohttp
from aiogram import Bot, Dispatcher, types
from aiogram.contrib.fsm_storage.memory import MemoryStorage
from aiogram.dispatcher.filters.state import State, StatesGroup
from aiogram.utils import executor
import re
from aiogram.types import ReplyKeyboardMarkup, KeyboardButton
import asyncio
from aiogram.dispatcher import FSMContext
from aiogram import types
from aiogram.dispatcher.filters import Command
from datetime import datetime, timedelta
import gspread
from oauth2client.service_account import ServiceAccountCredentials
import re
from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton, WebAppInfo
import logging
from aiogram.types import ReplyKeyboardRemove
TOKEN = '6476840022:AAFlOlYHCH4UKbGlOfILw8xcIUG0AD354X8'
bot = Bot(token=TOKEN)
storage = MemoryStorage()
dp = Dispatcher(bot, storage=storage)
# Кнопка для перезапуска
restart_button = ReplyKeyboardMarkup(resize_keyboard=True)
restart_button.add(KeyboardButton("Перезапустить бота"))
MAX_ATTEMPTS = 3 # Максимальное количество попыток ввода кода
TIMEOUT = 30 # Время в секундах
# Словарь для хранения данных о пользователях
user_data = {}
last_bot_message_id = {}
# Авторизация и доступ к таблице
scope = ["https://spreadsheets.google.com/feeds", "https://www.googleapis.com/auth/drive"]
credentials = ServiceAccountCredentials.from_json_keyfile_name("botforclinic-436512-0c117dd103a8.json", scope)
client = gspread.authorize(credentials)
sheet = client.open("Пациенты клиники").sheet1 # Открытие таблицы, используйте название вашей таблицы
# Словарь для хранения данных о сообщениях пользователей
user_messages = {}
# История состояний для каждого пользователя
user_states = {}
class Form(StatesGroup):
telegram_id = State()
existing_patient = State()
phone_number = State()
fio = State()
birthday = State()
verification_code = State()
confirm_fio = State()
confirm_phone_number = State()
from aiogram import types
# Настройка логирования
logging.basicConfig(level=logging.INFO)
# Главное меню
main_menu = InlineKeyboardMarkup(row_width=2).add(
InlineKeyboardButton("📝 Запись", callback_data="menu_record"),
InlineKeyboardButton("🧰 Услуги", callback_data="menu_services"),
InlineKeyboardButton(" Специалисты", callback_data="menu_specialists"),
InlineKeyboardButton("🌍 Контакты", callback_data="menu_contacts"),
InlineKeyboardButton("📞 Связь", callback_data="menu_contact")
)
# Подменю "Запись"
record_menu = InlineKeyboardMarkup(row_width=1).add(
InlineKeyboardButton("Запись на приём", callback_data="record_appointment"),
InlineKeyboardButton("Запись на исследование", callback_data="record_research"),
InlineKeyboardButton("Запись на терапию", callback_data="record_therapy"),
InlineKeyboardButton("Назад", callback_data="main_menu")
)
# Меню исследований
research_menu = InlineKeyboardMarkup(row_width=1).add(
InlineKeyboardButton("УЗИ", callback_data="research_uzi"),
InlineKeyboardButton("КТ", callback_data="research_kt"),
InlineKeyboardButton("ЭКГ", callback_data="research_ekg"),
InlineKeyboardButton("КСП (скарификационные пробы)", callback_data="research_ksp"),
InlineKeyboardButton("Назад", callback_data="menu_record"),
InlineKeyboardButton("Главное меню", callback_data="main_menu")
)
# Меню терапии
therapy_menu = InlineKeyboardMarkup(row_width=1).add(
InlineKeyboardButton("Слухопротезирование", callback_data="therapy_hearing"),
InlineKeyboardButton("АСИТ-терапия", callback_data="therapy_asit"),
InlineKeyboardButton("ФДТ (фотодинамическая терапия)", callback_data="therapy_fdt"),
InlineKeyboardButton("Галотерапия (соляная комната)", callback_data="therapy_halo"),
InlineKeyboardButton("Назад", callback_data="menu_record"),
InlineKeyboardButton("Главное меню", callback_data="main_menu")
)
# Обработка нажатий на инлайн-кнопки
@dp.callback_query_handler(lambda c: c.data.startswith("menu_") or c.data == "main_menu")
async def handle_main_menu(call: types.CallbackQuery):
if call.data == "main_menu":
await call.message.edit_text("Главное меню:", reply_markup=main_menu)
elif call.data == "menu_record":
await call.message.edit_text("Выберите тип записи:", reply_markup=record_menu)
# Обработка нажатия на "Запись на исследование"
@dp.callback_query_handler(lambda c: c.data == "record_research")
async def handle_research_menu(call: types.CallbackQuery):
await call.message.edit_text("Выберите тип исследования:", reply_markup=research_menu)
# Обработка нажатия на "Запись на терапию"
@dp.callback_query_handler(lambda c: c.data == "record_therapy")
async def handle_therapy_menu(call: types.CallbackQuery):
await call.message.edit_text("Выберите тип терапии:", reply_markup=therapy_menu)
# Обработка нажатий на инлайн-кнопки
@dp.callback_query_handler(lambda c: c.data.startswith("menu_") or c.data == "main_menu")
async def handle_main_menu(call: types.CallbackQuery):
if call.data == "main_menu":
await call.message.edit_text("Главное меню:", reply_markup=main_menu)
elif call.data == "menu_record":
await call.message.edit_text("Выберите тип записи:", reply_markup=record_menu)
# Обработка нажатия на "Запись на приём"
@dp.callback_query_handler(lambda c: c.data == "record_appointment")
async def show_specialties(call: types.CallbackQuery):
spec_url = "http://46.146.229.242:1980/AppZaprSpec"
try:
response = requests.post(spec_url)
logging.info(f"Ответ от сервера специальностей: {response.text}")
if response.status_code == 200:
specialties = response.json()
specialties_menu = InlineKeyboardMarkup(row_width=1)
for spec in specialties:
if 'MSP_ID' in spec and 'MSP_NAME' in spec:
specialties_menu.add(
InlineKeyboardButton(
spec['MSP_NAME'], callback_data=f"spec_{spec['MSP_ID']}"
)
)
specialties_menu.add(
InlineKeyboardButton("Назад", callback_data="menu_record"),
InlineKeyboardButton("Главное меню", callback_data="main_menu")
)
await call.message.edit_text("Выберите специальность:", reply_markup=specialties_menu)
else:
await call.message.answer(f"Ошибка сервера. Код ответа: {response.status_code}")
except Exception as e:
logging.error(f"Ошибка получения специальностей: {e}")
await call.message.answer("Произошла ошибка при получении специальностей.")
# Обработка выбора специальности
@dp.callback_query_handler(lambda c: c.data.startswith("spec_"))
async def show_doctors(call: types.CallbackQuery):
spec_id = call.data.split('_')[1]
doc_url = "http://46.146.229.242:1980/AppZaprSpecDoc"
try:
doc_response = requests.post(doc_url, json={"spec_id": int(spec_id)})
logging.info(f"Ответ от сервера врачей: {doc_response.text}")
if doc_response.status_code == 200:
doctors = doc_response.json()
if not doctors:
await call.message.answer("Врачи по этой специальности не найдены.")
return
doctors_menu = InlineKeyboardMarkup(row_width=1)
for doc in doctors:
if 'DOC_FIO' in doc and 'DOC_ID' in doc:
doctors_menu.add(
InlineKeyboardButton(
f"{doc['DOC_FIO']}", callback_data=f"doc_{doc['DOC_ID']}"
)
)
doctors_menu.add(
InlineKeyboardButton("Назад", callback_data="record_appointment"),
InlineKeyboardButton("Главное меню", callback_data="main_menu")
)
await call.message.edit_text("Выберите врача:", reply_markup=doctors_menu)
else:
await call.message.answer(f"Ошибка сервера. Код ответа: {doc_response.status_code}")
except Exception as e:
logging.error(f"Ошибка получения врачей: {e}")
await call.message.answer("Произошла ошибка при получении списка врачей.")
@dp.message_handler(commands=['test'])
async def handle_help(message: types.Message):
user_id = message.from_user.id
await bot.send_message(user_id,"тестирование кнопок меню", reply_markup=main_menu)
@dp.message_handler(commands=['help'])
async def handle_help(message: types.Message):
#await save_message_data(message)
user_id = message.from_user.id
help_message = "Список доступных команд:\n"
help_message += "/start - начать взаимодействие с ботом\n"
help_message += "/registration - регистрация\n"
help_message += "/help - показать список команд и их описания\n"
sent_message = await bot.send_message(user_id, help_message)
last_bot_message_id[user_id] = sent_message.message_id
@dp.message_handler(Command("start"), state="*")
async def handle_start(message: types.Message, state: FSMContext):
# Завершаем текущее состояние и очищаем данные пользователя
await state.finish() # Завершает текущее состояние
await state.storage.reset_data(user=message.from_user.id) # Удаляет все данные пользователя в FSM хранилище
# Отправляем фото
with open("s-blob-v1-IMAGE-tdNCrEv8Ldo.png", "rb") as photo:
await bot.send_photo(
chat_id=message.from_user.id,
photo=photo,
caption=("Добро пожаловать!\nЯ чат-бот Клиники и Ваш надежный виртуальный помощник.\nЧтобы узнать, что я могу для Вас сделать, просто введите /help\nДля начала работы нажмите кнопку /registration внизу."),
reply_markup=generate_markup_registration() # Кнопка для продолжения
)
@dp.message_handler(commands=['registration'], chat_type=types.ChatType.PRIVATE)
async def handle_registration(message: types.Message):
user_id = message.from_user.id
sent_message = await bot.send_message(user_id, "Вы уже являетесь пациентом нашей Клиники?\nЕсли Вы хотите начать общение с ботом заново, нажмите /start.",
reply_markup=yes_no_markup())
last_bot_message_id[user_id] = sent_message.message_id
await Form.existing_patient.set()
def generate_markup_telegram_id():
markup = types.ReplyKeyboardMarkup(row_width=2, resize_keyboard=True)
item3 = types.KeyboardButton("Отправить Telegram ID")
markup.add(item3)
return markup
def generate_markup_registration():
markup = types.ReplyKeyboardMarkup(row_width=1, resize_keyboard=True)
item_registration = types.KeyboardButton("/registration")
markup.add(item_registration)
return markup
@dp.message_handler(state=Form.existing_patient)
async def handle_existing_patient(message: types.Message, state: FSMContext):
user_id = message.from_user.id
form_url = f"https://tgbotpolimed.pirogov.ai/?user_id={user_id}"
if message.text.lower() == "да":
# Удаляем кнопки и отправляем ссылку на форму
await message.answer(
"В соответствии с Федеральным законом № 152-ФЗ «О персональных данных», для идентификации Вас как пациента нашей Клиники, просим заполнить форму, нажав на кнопку ниже.",
reply_markup=ReplyKeyboardRemove()
)
await message.answer(
"Заполнить форму:",
reply_markup=InlineKeyboardMarkup().add(
InlineKeyboardButton(
text="Заполнить форму",
web_app=WebAppInfo(url=form_url)
)
)
)
elif message.text.lower() == "нет":
await bot.send_message(
user_id,
"Полный доступ к функциям сервиса доступен только пациентам нашей Клиники.\n"
"Вы можете связаться с нами по тел.+7 (342) 207-03-03 или посетить Клинику лично по адресам:\n"
"г. Пермь, ул. Клары Цеткин, д. 9; ул. Газеты Звезда, д. 31- а.\n\n"
"Будьте здоровы!",
reply_markup=ReplyKeyboardRemove()
)
await state.finish()
else:
await bot.send_message(
user_id,
"Пожалуйста, выберите 'Да' или 'Нет' с помощью кнопок.",
reply_markup=ReplyKeyboardRemove()
)
@dp.message_handler(state=Form.verification_code)
async def handle_verification_code(message: types.Message, state: FSMContext):
user_id = message.from_user.id
code_entered = message.text.strip()
expected_code = user_data.get(user_id, {}).get("verification_code")
if expected_code and str(code_entered) == str(expected_code):
await bot.send_message(user_id, "Верификация прошла успешно! Пожалуйста, подождите...")
# Поиск данных пациента по Telegram ID
patient_records = find_patients_by_id(user_id)
if len(patient_records) == 0:
await bot.send_message(user_id, "Пациенты с данным Telegram ID не найдены в базе данных.")
await state.finish()
elif len(patient_records) == 1:
# Если только одна запись, сразу берём данные
await process_patient_data(user_id, patient_records[0], state)
else:
# Если несколько записей, предлагаем выбрать пациента
await prompt_patient_selection(user_id, patient_records)
else:
await bot.send_message(user_id, "Неверный код. Попробуйте снова.")
def find_patients_by_id(telegram_id):
records = sheet.get_all_records() # Получаем все строки таблицы
patients = []
for record in records:
if str(record["Telegram ID"]) == str(telegram_id):
patients.append(record)
return patients
async def prompt_patient_selection(user_id, patient_records):
# Создаем кнопки с ФИО пациентов
markup = ReplyKeyboardMarkup(row_width=1, resize_keyboard=True)
for record in patient_records:
markup.add(KeyboardButton(record["ФИО"]))
# Сохраняем данные пациентов временно
user_data[user_id]["patients"] = patient_records
await bot.send_message(
user_id,
"Найдено несколько записей с вашим Telegram ID. Пожалуйста, выберите пациента:",
reply_markup=markup,
)
await Form.fio.set()
@dp.message_handler(state=Form.fio)
async def handle_patient_selection(message: types.Message, state: FSMContext):
user_id = message.from_user.id
selected_fio = message.text.strip()
# Поиск выбранного пациента
patients = user_data[user_id].get("patients", [])
selected_patient = next((p for p in patients if p["ФИО"] == selected_fio), None)
if selected_patient:
await process_patient_data(user_id, selected_patient, state)
else:
await bot.send_message(user_id, "Ошибка: выбранный пациент не найден. Попробуйте ещё раз.")
async def process_patient_data(user_id, patient_record, state: FSMContext):
# Форматирование данных
fio_parts = patient_record["ФИО"].split()[:3] # Берем первые три слова из ФИО
formatted_phone = find_patient_by_id(user_id) # Используем функцию для получения номера телефона
if formatted_phone:
# Сохранение в словарь
user_data[user_id] = {
"telegram_id": user_id,
"first_name": fio_parts[0],
"middle_name": fio_parts[1] if len(fio_parts) > 1 else "",
"last_name": fio_parts[2] if len(fio_parts) > 2 else "",
"phone_number": formatted_phone,
"birthday": patient_record["Дата рождения"],
}
# Отправка на сервер
result = send_registration_request(user_data[user_id])
if result == "success":
await bot.send_message(user_id, "Регистрация успешно завершена!")
else:
await bot.send_message(user_id, "Произошла ошибка при регистрации. Пожалуйста, попробуйте позже.")
else:
await bot.send_message(user_id, "Не удалось найти номер телефона для вашего аккаунта.")
await state.finish()
def send_verification_call(user_id, phone_number):
url = "https://sms.ru/code/call"
data = {
"phone": phone_number,
"api_id": "2ED72E61-76C8-5637-3587-2792D47B698C"
}
response = requests.post(url, data=data)
json_data = response.json()
verification_code = None
# Проверяем статус запроса
if json_data and json_data.get("status") == "OK":
verification_code = json_data.get("code") # Получаем код
if not verification_code:
print("Ошибка: Код отсутствует в ответе API.")
return None
# Сохраняем код для пользователя
if user_id not in user_data:
user_data[user_id] = {}
user_data[user_id]["verification_code"] = verification_code
# Логируем код для отладки
print(f"Код верификации, отправленный пользователю {user_id}: {verification_code}")
else:
print("Звонок не может быть выполнен.")
print("Текст ошибки:", json_data.get("status_text"))
return verification_code
async def save_message_data(message: types.Message, reply_to_message_id=None):
user_id = message.from_user.id
reply_to_message_id = last_bot_message_id.get(user_id, None)
user_messages[message.message_id] = {
"message_id": message.message_id,
"text": message.text,
"date": message.date.isoformat(), # Исправлено
"user_id": message.from_user.id,
"reply_to_message_id": reply_to_message_id
}
print(f"Сообщение пользователя {user_id} сохранено: {user_messages[message.message_id]}")
await send_message_to_server(user_messages[message.message_id])
def send_registration_request(user_data):
HEADER = {
"Content-Type": "application/json"
}
data = {
"telegram_id": user_data.get("telegram_id"),
"first_name": user_data["first_name"],
"second_name": user_data["middle_name"],
"last_name": user_data["last_name"],
"mobile_phone": user_data["phone_number"],
"birthday": user_data["birthday"]
}
print("Отправляемые данные на сервер:", data)
response = requests.post("http://46.146.229.242:1980/AppFindPac", headers=HEADER, json=data)
if response.status_code == 200:
result = response.json()
print("Результат JSON:", result)
return result.get('result')
else:
print(f"Ошибка при отправке данных. Статус-код: {response.status_code}")
return "error"
async def send_message_to_server(message_data):
url = "http://46.146.229.242:1980/AppSaveMessage"
headers = {"Content-Type": "application/json"}
async with aiohttp.ClientSession() as session:
async with session.post(url, headers=headers, json=message_data) as response:
if response.status == 200:
print(f"Сообщение {message_data['message_id']} успешно отправлено на сервер.")
else:
print(f"Ошибка при отправке сообщения {message_data['message_id']} на сервер. Статус-код: {response.status}")
# Функция для выполнения POST-запроса и получения списка врачей
def get_doctors():
url = "http://46.146.229.242:1980/AppZaprSpecDoc"
# Данные для отправки в запросе
data = {"spec_id": 1}
# Выполняем POST-запрос
response = requests.post(url, json=data)
# Проверяем статус ответа
if response.status_code == 200:
# Если запрос успешен, возвращаем данные
return response.json()
else:
# Если запрос не удался, выводим ошибку
print(f"Ошибка: {response.status_code}")
return []
def yes_no_markup():
markup = types.ReplyKeyboardMarkup(row_width=2, resize_keyboard=True)
item_no = types.KeyboardButton("Нет")
item_yes = types.KeyboardButton("Да")
markup.add(item_yes, item_no)
return markup
def markup2():
markup = types.ReplyKeyboardMarkup(row_width=2, resize_keyboard=True)
item_good = types.KeyboardButton("Всё верно")
item_no_good = types.KeyboardButton("Указать ФИО ещё раз")
markup.add(item_good, item_no_good)
return markup
def generate_start_markup():
markup = types.ReplyKeyboardMarkup(row_width=1, resize_keyboard=True)
start_button = types.KeyboardButton("/start")
markup.add(start_button)
return markup
def find_patient_by_id(telegram_id):
records = sheet.get_all_records() # Получаем все строки таблицы
for record in records:
if str(record["Telegram ID"]) == str(telegram_id): # Сравнение с Telegram ID
phone_raw = record["Номер телефона"]
# Удаляем все нецифровые символы
phone_formatted = re.sub(r"\D", "", phone_raw)
# Проверка на правильную длину номера и корректировка, если необходимо
if len(phone_formatted) == 11:
if phone_formatted.startswith("8"): # Если номер начинается с 8, заменяем на 7
phone_formatted = "7" + phone_formatted[1:]
return phone_formatted
else:
return None # Возвращаем None, если номер неправильной длины
return None
def generate_markup_menu():
# Создаем клавиши
buttons = [
KeyboardButton("📝 Запись"),
KeyboardButton("🧰 Услуги"),
KeyboardButton(" Специалисты"),
KeyboardButton("🌍 Контакты"),
KeyboardButton("📞 Связь"),
]
# Создаем и настраиваем клавиатуру
markup = ReplyKeyboardMarkup(resize_keyboard=True, one_time_keyboard=False)
# Добавляем кнопки в столбик (по одной в строке)
markup.add(*buttons)
return markup
@dp.message_handler(content_types=types.ContentType.TEXT)
async def handle_message(message: types.Message):
await save_message_data(message)
if __name__ == '__main__':
executor.start_polling(dp, skip_updates=True)

BIN
__pycache__/BotPM.cpython-38.pyc

Binary file not shown.

13
botforclinic-436512-0c117dd103a8.json

@ -0,0 +1,13 @@
{
"type": "service_account",
"project_id": "botforclinic-436512",
"private_key_id": "0c117dd103a890d20705d9e66bbfde56f9d65a05",
"private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC4XOtHBzxPR4lb\nqiX8grd2XBfBxXZLgLKTkz4WRcncgBpACXKms5AtKF707uKCvgUD8SwTpzvfY3oz\nvzLQs0uZoM9RALw5ui9dlimdoYQGsuH5LAUX68w0oPyour36XeBqacxNoEeO5C2F\nbb4+ql4gC2qJT86aBt2kwKpTxnTPZxvYoKZ0TwsmN8gj9vNckONbSSZteMKpQA50\nRqpoLM0EpsB64HRSiu8mH+bkdLK9ZMEZGmOG7pNDijctGkgAy9rK9vurH4PRgIMt\n7j+q/EeBQDuZX2SSVIaMkiFkDhHVGd84CFzcodBIYOSiCDer7aIcv8SrcYGZ0QJD\nnIzTqZMrAgMBAAECggEAW3HHR2dI3D/s2xkVl15U1nHOXM/vIXsX2EgH2y9JdUPb\nAVlOU24sPKHSG6YjltrejPqCNMtV0LM8SU90Sn0sKerP+esl8XIujTpusN+Mp2/x\n0tApRJiyJIaXW6+ojHck2VNZwUUXSUJXa9+npdiGMFnJQYtivBZcuJvRwBTnGnm/\ntuwQUcQREPy8IaaX5j+xPf390KeXqNOopULW7FtItkHthM18fr6706X1GQ77ua23\nzz1DT2PfIxOu2e3uPJ1O1CsQ8UiTIAm3J0nNgbpau1nP2+ea62vCrjmuqcyn5dfb\nhpgGD7Qe8uRvU+EICr67sOW47ikjAqkM38lZFgufuQKBgQDmypfFTYke7oDTZ8GE\nZFHZKn+ri5s94pDzjeeb8HxmeEC85cA6+jOr6f1QncwHON+tD2FRO7HHp/yVVyZY\nU2RSxaLaFleRL4CwlQkiMoqynLFWbqQthqdeJx2onNyGoO8uBDqfMJVBhOjwb8jI\n3SZt1Z6BJ076CMMOiLI7moZsWQKBgQDMgBdWND+uTR0SHXWqF1hj/+UgwHBqQKio\nyWbnIO28uFyMscfBAgh7JJbqcJIh6A+M9NdD4TveqZWoYBaUHkMBg5VGcmWrCH+L\nJOlAVJmhy4GgpE2nkYE0ZgDd0qlViYeTOKaLSKchPrLxRKNI9eeWkKqrk/a7wBHh\nsGJbt8p7IwKBgQCvFYaqAbZCpwFIX/ApNcn6DAmq5FAzVIxOmJrabEiTnCrQoyOA\nGovUocCwxeUgnX7i1UYo0DaAlupBiUnnu+vh91kiRczMsdLZI1c4gEtEUScfwPQA\nLaUPAnG3lrid0b1hlYe7eKnieKgWr1cNOuiKboK+zElX2gnQHtfH6+SKkQKBgDYW\nsxVz4FwDvWqrLBH+9rwMVNgizhjsXS+3hWYgiYDe6mu0IfdkyEV52gjMGXqqXGKV\n59HmYuVzyUetkos+rc5atULawxVHvCRbcO448iGfJ/wLORbXH2tyh0wkifE73QYN\nd89jOgFLCh1SYDXOBKEIRnv3OM1T8ebVtk44AHAtAoGAfOprlkWEDyVnfHQjGxxx\nTrxhEAjw3+ikM+wQJj7vumnpg91eAFNcwRUa/ykbVOmj6z/fBnStAbsG7mMQwa1M\nyIVPTvUogrsTHvf9GaG0IaAVJn/Su2DVNqQeL/ZpDmu2+wC959g8z665BKLzm3S8\nFc0eV1a7FN4GOpKNvXuDMBc=\n-----END PRIVATE KEY-----\n",
"client_email": "clinic-chats-bot@botforclinic-436512.iam.gserviceaccount.com",
"client_id": "105253150604049743778",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/clinic-chats-bot%40botforclinic-436512.iam.gserviceaccount.com",
"universe_domain": "googleapis.com"
}

122
doctors.json

@ -0,0 +1,122 @@
[
{
"DOC_ID": 228,
"DOC_FIO": "Акутина Алёна Владимировна"
},
{
"DOC_ID": 50,
"DOC_FIO": "Анфилатов Андрей Викторович"
},
{
"DOC_ID": 40,
"DOC_FIO": "Верещагина Лидия Владимировна"
},
{
"DOC_ID": 127,
"DOC_FIO": "Волкова Надежда Геннадьевна"
},
{
"DOC_ID": 81,
"DOC_FIO": "Ворончихина Наталия Валерьевна"
},
{
"DOC_ID": 72,
"DOC_FIO": "Гашеева Ирина Валерьевна"
},
{
"DOC_ID": 121,
"DOC_FIO": "Генеральчук Людмила Владимировна"
},
{
"DOC_ID": 193,
"DOC_FIO": "Гилязова Лариса Левоновна"
},
{
"DOC_ID": 91,
"DOC_FIO": "Головач Светлана Вячеславовна"
},
{
"DOC_ID": 140,
"DOC_FIO": "Давлятшина Олеся Алексеевна"
},
{
"DOC_ID": 17,
"DOC_FIO": "Долгих Елена Павловна"
},
{
"DOC_ID": 44,
"DOC_FIO": "Зыкин Олег Владимирович"
},
{
"DOC_ID": 223,
"DOC_FIO": "Иванова Анастасия Александровна"
},
{
"DOC_ID": 269,
"DOC_FIO": "Козенкова Юлия Александровна"
},
{
"DOC_ID": 171,
"DOC_FIO": "Коротаева Владлена Александровна"
},
{
"DOC_ID": 2,
"DOC_FIO": "Лебединская Елена Александровна"
},
{
"DOC_ID": 272,
"DOC_FIO": "Лобанова Ирина Юрьевна"
},
{
"DOC_ID": 5,
"DOC_FIO": "Макарова Людмила Германовна"
},
{
"DOC_ID": 75,
"DOC_FIO": "Операционная "
},
{
"DOC_ID": 119,
"DOC_FIO": "Осадчий Антон Павлович"
},
{
"DOC_ID": 47,
"DOC_FIO": "Семерикова Наталия Александровна"
},
{
"DOC_ID": 19,
"DOC_FIO": "Синдяев Алексей Викторович"
},
{
"DOC_ID": 267,
"DOC_FIO": "Суднева Анна Руслановна"
},
{
"DOC_ID": 41,
"DOC_FIO": "Сушков Михаил Германович"
},
{
"DOC_ID": 3,
"DOC_FIO": "Терво Светлана Олеговна"
},
{
"DOC_ID": 4,
"DOC_FIO": "Уткина Наталия Павловна"
},
{
"DOC_ID": 253,
"DOC_FIO": "Хмелёва Марина Александровна"
},
{
"DOC_ID": 38,
"DOC_FIO": "Шайдурова Валентина Николаевна"
},
{
"DOC_ID": 224,
"DOC_FIO": "Шевырина Наталья Григорьевна"
},
{
"DOC_ID": 139,
"DOC_FIO": "Юрков Владислав Сергеевич"
}
]

461
proba1PM.py

@ -0,0 +1,461 @@
import requests
import aiohttp
from aiogram import Bot, Dispatcher, types
from aiogram.contrib.fsm_storage.memory import MemoryStorage
from aiogram.dispatcher.filters.state import State, StatesGroup
from aiogram.utils import executor
import re
from aiogram.types import ReplyKeyboardMarkup, KeyboardButton
import asyncio
from aiogram.dispatcher import FSMContext
from aiogram import types
from aiogram.dispatcher.filters import Command
from datetime import datetime, timedelta
TOKEN = '6476840022:AAFlOlYHCH4UKbGlOfILw8xcIUG0AD354X8'
bot = Bot(token=TOKEN)
storage = MemoryStorage()
dp = Dispatcher(bot, storage=storage)
# Кнопка для перезапуска
restart_button = ReplyKeyboardMarkup(resize_keyboard=True)
restart_button.add(KeyboardButton("Перезапустить бота"))
MAX_ATTEMPTS = 3 # Максимальное количество попыток ввода кода
TIMEOUT = 30 # Время в секундах
# Словарь для хранения данных о пользователях
user_data = {}
last_bot_message_id = {}
# Словарь для хранения данных о сообщениях пользователей
user_messages = {}
class Form(StatesGroup):
telegram_id = State()
existing_patient = State()
phone_number = State()
fio = State()
birthday = State()
verification_code = State()
confirm_fio = State()
confirm_phone_number = State()
@dp.message_handler(lambda message: message.text in ["📝 Запись", "🧰 Услуги", " Специалисты", "🌍 Контакты", "📞 Связь"])
async def handle_menu_selection(message: types.Message):
user_id = message.from_user.id
if message.text == "📝 Запись":
await bot.send_message(user_id,"Вы выбрали 'Запись'. Здесь можно записаться на прием.")
elif message.text == "🧰 Услуги":
await bot.send_message(user_id,"Вы выбрали 'Услуги'. Здесь можно ознакомиться с нашими услугами.")
elif message.text == " Специалисты":
await bot.send_message(user_id,"Вы выбрали 'Специалисты'. Здесь можно узнать о наших специалистах.")
elif message.text == "🌍 Контакты":
await bot.send_message(user_id,"Вы выбрали 'Контакты'. Здесь указаны контактные данные.")
elif message.text == "📞 Связь":
await bot.send_message(user_id,"Вы выбрали 'Связь'. Здесь можно связаться с нами.")
@dp.message_handler(commands=['test'])
async def handle_help(message: types.Message):
user_id = message.from_user.id
await bot.send_message(user_id,"тестирование кнопок меню", reply_markup=generate_markup_menu())
@dp.message_handler(commands=['help'])
async def handle_help(message: types.Message):
#await save_message_data(message)
user_id = message.from_user.id
help_message = "Список доступных команд:\n"
help_message += "/start - начать взаимодействие с ботом\n"
help_message += "/registration - регистрация\n"
help_message += "/help - показать список команд и их описания\n"
sent_message = await bot.send_message(user_id, help_message)
last_bot_message_id[user_id] = sent_message.message_id
@dp.message_handler(Command("start"), state="*")
async def handle_start(message: types.Message, state: FSMContext):
# Завершаем текущее состояние и очищаем данные пользователя
await state.finish() # Завершает текущее состояние
await state.storage.reset_data(user=message.from_user.id) # Удаляет все данные пользователя в FSM хранилище
# Отправляем фото
with open("s-blob-v1-IMAGE-tdNCrEv8Ldo.png", "rb") as photo:
await bot.send_photo(
chat_id=message.from_user.id,
photo=photo,
caption=("Добро пожаловать!\nЯ чат-бот Клиники и Ваш надежный виртуальный помощник.\nЧтобы узнать, что я могу для Вас сделать, просто введите /help\nДля начала работы нажмите кнопку /registration внизу."),
reply_markup=generate_markup_registration() # Кнопка для продолжения
)
@dp.message_handler(commands=['registration'])
async def handle_registration1(message: types.Message):
#await save_message_data(message)
user_id = message.from_user.id
user_data[user_id] = {"step": "telegram_id"}
sent_message = await bot.send_message(user_id, "Для продолжения регистрации отправьте, пожалуйста, свой Telegram ID, нажав на кнопку ниже.\nЕсли Вы хотите начать общение с ботом заново, нажмите /start.", reply_markup=generate_markup_telegram_id())
last_bot_message_id[user_id] = sent_message.message_id
await Form.telegram_id.set()
def generate_markup_telegram_id():
markup = types.ReplyKeyboardMarkup(row_width=2, resize_keyboard=True)
item3 = types.KeyboardButton("Отправить Telegram ID")
markup.add(item3)
return markup
def generate_markup_registration():
markup = types.ReplyKeyboardMarkup(row_width=1, resize_keyboard=True)
item_registration = types.KeyboardButton("/registration")
markup.add(item_registration)
return markup
@dp.message_handler(lambda message: message.text == "Отправить Telegram ID", state=Form.telegram_id)
async def handle_telegram_id(message: types.Message):
#await save_message_data(message)
user_id = message.from_user.id
telegram_id = message.from_user.id
user_data[user_id]["telegram_id"] = telegram_id
sent_message = await bot.send_message(user_id, f"Ваш Telegram ID: {telegram_id}. Вы уже являетесь пациентом нашей Клиники?\nЕсли Вы хотите начать общение с ботом заново, нажмите /start.", reply_markup=yes_no_markup())
last_bot_message_id[user_id] = sent_message.message_id
await Form.existing_patient.set()
@dp.message_handler(state=Form.existing_patient)
async def handle_existing_patient(message: types.Message, state: FSMContext):
#await save_message_data(message)
user_id = message.from_user.id
print(message.text.lower())
if message.text.lower() == "да":
sent_message = await bot.send_message(user_id, "Введите ваш контактный номер телефона в формате 7XXXXXXXXX\nЕсли Вы хотите начать общение с ботом заново, нажмите /start.")
last_bot_message_id[user_id] = sent_message.message_id
await Form.phone_number.set()
elif message.text.lower() == "нет":
sent_message = await bot.send_message(user_id, "Затычка")
last_bot_message_id[user_id] = sent_message.message_id
await state.finish() # Завершаем состояние
# Дополнительно добавляем условие для завершения работы состояния
else:
await bot.send_message(user_id, "Пожалуйста, выберите 'Да' или 'Нет' с помощью кнопок.")
@dp.message_handler(state=Form.phone_number)
async def process_phone_number(message: types.Message):
#await save_message_data(message)
user_id = message.from_user.id
phone_number = message.text.strip() # Удаляем лишние пробелы
user_data[user_id]["phone_number"] = phone_number
# Регулярное выражение для проверки номера телефона
if not re.match(r'^7\d{10}$', phone_number):
sent_message = await bot.send_message(user_id, "Номер телефона должен начинаться с '7' и содержать 11 цифр. Пожалуйста, введите номер ещё раз\nЕсли Вы хотите начать общение с ботом заново, нажмите /start.")
last_bot_message_id[user_id] = sent_message.message_id
return
# Отправляем номер телефона для подтверждения
markup = types.ReplyKeyboardMarkup(resize_keyboard=True)
item_good = types.KeyboardButton("Всё верно")
item_no_good = types.KeyboardButton("Указать номер ещё раз")
markup.row(item_good, item_no_good)
sent_message = await bot.send_message(user_id, f"Проверьте, пожалуйста, свой номер телефона: {phone_number}.\nНажмите кнопку ниже\nЕсли Вы хотите начать общение с ботом заново, нажмите /start.", reply_markup=markup)
last_bot_message_id[user_id] = sent_message.message_id
await Form.confirm_phone_number.set() # Переход к состоянию подтверждения номера телефона
@dp.message_handler(state=Form.confirm_phone_number)
async def confirm_phone_number(message: types.Message):
user_id = message.from_user.id
if message.text.lower() == "всё верно":
# Если номер телефона подтвержден, переходим к следующему шагу
sent_message = await bot.send_message(user_id, "Укажите ФИО пациента строго в формате “Фамилия Имя Отчество”.\nЕсли пациентом является Ваш ребенок, введите только ФИО ребенка.\nПример: Иванов Иван Иванович\nЕсли Вы хотите начать общение с ботом заново, нажмите /start.")
last_bot_message_id[user_id] = sent_message.message_id
await Form.fio.set() # Переход к состоянию ввода ФИО
elif message.text.lower() == "указать номер ещё раз":
# Если номер телефона нужно указать снова, возвращаемся к вводу номера телефона
sent_message = await bot.send_message(user_id, "Пожалуйста, введите номер телефона снова:\nЕсли Вы хотите начать общение с ботом заново, нажмите /start.")
last_bot_message_id[user_id] = sent_message.message_id
await Form.phone_number.set() # Возвращаемся к состоянию ввода номера телефона
@dp.message_handler(state=Form.fio)
async def handle_fio_process(message: types.Message):
#await save_message_data(message)
user_id = message.from_user.id
fio_parts = message.text.strip().split()
if len(fio_parts) == 3:
last_name, first_name, middle_name = fio_parts
user_data[user_id]["last_name"] = last_name
user_data[user_id]["first_name"] = first_name
user_data[user_id]["middle_name"] = middle_name
sent_message = await bot.send_message(user_id, f"Проверьте, пожалуйста, в правильном ли формате вы ввели ФИО пациента:\nФамилия - {last_name}, Имя - {first_name}, Отчество - {middle_name}.\nНажмите кнопку ниже\nЕсли Вы хотите начать общение с ботом заново, нажмите /start.", reply_markup=markup2())
last_bot_message_id[user_id] = sent_message.message_id
await Form.confirm_fio.set() # Переход к состоянию подтверждения ФИО
else:
sent_message = await bot.send_message(user_id, "Пожалуйста, введите ФИО в формате 'Фамилия Имя Отчество'.\nЕсли Вы хотите начать общение с ботом заново, нажмите /start.")
last_bot_message_id[user_id] = sent_message.message_id
@dp.message_handler(state=Form.confirm_fio)
async def handle_fio_confirmation(message: types.Message):
user_id = message.from_user.id
if message.text.lower() == "всё верно":
sent_message = await bot.send_message(user_id,"Укажите год рождения пациента в формате YYYY.\nЕсли пациентом является Ваш ребенок, введите только год рождения ребенка в формате YYYY.\nПример: 2003\nЕсли Вы хотите начать общение с ботом заново, нажмите /start.")
last_bot_message_id[user_id] = sent_message.message_id
await Form.birthday.set() # Переход к запросу года рождения
elif message.text.lower() == "указать фио ещё раз":
user_data[user_id].pop("last_name", None)
user_data[user_id].pop("first_name", None)
user_data[user_id].pop("middle_name", None)
sent_message = await bot.send_message(user_id, "Укажите ФИО пациента строго в формате 'Фамилия Имя Отчество'.\nЕсли Вы хотите начать общение с ботом заново, нажмите /start.")
last_bot_message_id[user_id] = sent_message.message_id
await Form.fio.set() # Возвращаемся к запросу ФИО
else:
await bot.send_message(user_id, "Пожалуйста, выберите 'Всё верно' или 'Указать ФИО ещё раз' с помощью кнопок.\nЕсли Вы хотите начать общение с ботом заново, нажмите /start.")
@dp.message_handler(state=Form.birthday)
async def handle_birthday(message: types.Message):
#await save_message_data(message)
user_id = message.from_user.id
birthday = message.text
# Проверяем, что введённый год состоит из 4 цифр и является числом
if len(birthday) != 4 or not birthday.isdigit():
sent_message = await bot.send_message(user_id, "Укажите год рождения пациента в формате YYYY.\nПример: 2003.\nЕсли Вы хотите начать общение с ботом заново, нажмите /start.")
last_bot_message_id[user_id] = sent_message.message_id
return
# Преобразуем введённый год в целое число
birth_year = int(birthday)
current_year = datetime.now().year
# Проверка возраста на не более 100 лет
if birth_year < current_year - 100 or birth_year > current_year:
sent_message = await bot.send_message(user_id, f"Укажите корректный год рождения. Пациенту не может быть больше 100 лет. Пример: 2003.\nЕсли Вы хотите начать общение с ботом заново, нажмите /start.")
last_bot_message_id[user_id] = sent_message.message_id
return
# Сохранение года рождения
user_data[user_id]["birthday"] = birthday
# Отправка данных на сервер для проверки
server_response = send_registration_request(user_data[user_id])
# Проверяем ответ от сервера
if server_response != "OK":
# Если пользователь не найден в базе, отправляем сообщение
sent_message = await bot.send_message(
user_id,
"К сожалению, мы не смогли найти Вас в нашей базе. Возможно, у нас указаны другие данные, или Вы ни разу не были в нашей Клинике.\n\n"
"Попробуйте пройти регистрацию еще раз. Если не получится, обратитесь в регистратуру Клиники или свяжитесь с нами по тел. (342) 207-03-03.\n\nБудьте здоровы!\n\n/start", reply_markup=generate_start_markup()
)
last_bot_message_id[user_id] = sent_message.message_id
return
# Если пользователь найден, продолжаем процесс регистрации
phone_number = user_data[user_id]["phone_number"]
verification_code = send_verification_call(user_id, phone_number)
if verification_code:
# Показываем последние 4 цифры номера для верификации
print(f"Последние 4 цифры номера телефона: {str(verification_code)[-4:]}")
# Переход к состоянию ввода кода верификации
sent_message = await bot.send_message(
user_id,
"В течение нескольких секунд на указанный номер телефона поступит звонок-сброс с уникального номера. Введите последние 4 цифры этого номера.\nПример: 3487\nЕсли звонок не поступил, пожалуйста, пройдите регистрацию заново, введя команду /start."
)
last_bot_message_id[user_id] = sent_message.message_id
await Form.verification_code.set()
else:
sent_message = await bot.send_message(user_id, "Произошла ошибка при отправке звонка. Пожалуйста, пройдите регистрацию заново, введя команду /start.", reply_markup=generate_markup_registration())
last_bot_message_id[user_id] = sent_message.message_id
@dp.message_handler(state=Form.verification_code)
async def handle_verification_code(message: types.Message, state: FSMContext):
user_id = message.from_user.id
code_entered = message.text.strip() # Удаляем пробелы на случай ошибки
markup = generate_markup_menu()
# Если это первая попытка, инициализируем счетчик попыток
if "attempts" not in user_data[user_id]:
user_data[user_id]["attempts"] = 0
if "verification_code" not in user_data[user_id]:
await bot.send_message(user_id, "Процесс верификации не был инициализирован. Пожалуйста, начните регистрацию заново, введя команду /start.")
await state.finish()
return
# Функция для проверки тайм-аута (будет вызвана автоматически через 30 секунд)
async def verification_timeout():
await asyncio.sleep(TIMEOUT) # Ждем 30 секунд
# Проверяем, если процесс регистрации всё еще не завершён
if user_id in user_data and "verification_code" in user_data[user_id]:
await bot.send_message(user_id, "Время на верификацию истекло. Пожалуйста, начните регистрацию заново, введя команду /start.")
await state.finish() # Завершаем состояние
del user_data[user_id]["verification_code"] # Удаляем код из данных пользователя
del user_data[user_id]["attempts"] # Сбрасываем счетчик попыток
# Запускаем тайм-аут в фоновом режиме
asyncio.create_task(verification_timeout())
# Проверка на корректность кода
expected_code = str(user_data[user_id]["verification_code"])
print(f"Ожидаемый код: {expected_code}, Введенный код: {code_entered}")
# Если введенный код совпадает с ожидаемым
if expected_code == code_entered:
sent_message = await bot.send_message(user_id, "Верификация прошла успешно! Вы успешно зарегистрированы.\nЧем могу быть Вам полезен?", reply_markup=markup)
last_bot_message_id[user_id] = sent_message.message_id
# Удаление кода из данных и завершение состояния
del user_data[user_id]["verification_code"]
await state.finish() # Завершаем состояние
# Отправка данных на сервер (если нужно)
server_response = send_registration_request(user_data[user_id])
else:
# Увеличиваем счетчик попыток
user_data[user_id]["attempts"] += 1
# Если количество попыток больше максимального, завершаем процесс
if user_data[user_id]["attempts"] >= MAX_ATTEMPTS:
await bot.send_message(user_id, f"Вы превысили максимальное количество попыток ({MAX_ATTEMPTS}). Пожалуйста, начните регистрацию заново, введя команду /start.")
await state.finish() # Завершаем состояние
del user_data[user_id]["verification_code"] # Удаляем код из данных
del user_data[user_id]["attempts"] # Сбрасываем счетчик попыток
return
sent_message = await bot.send_message(user_id, f"Неверный код верификации. Попытка {user_data[user_id]['attempts']} из {MAX_ATTEMPTS}. Пожалуйста, попробуйте еще раз.\nЕсли Вы хотите начать общение с ботом заново, нажмите /start.")
last_bot_message_id[user_id] = sent_message.message_id
print("Ошибка верификации: код не совпадает.")
def send_verification_call(user_id, phone_number):
url = "https://sms.ru/code/call"
data = {
"phone": phone_number,
"api_id": "2ED72E61-76C8-5637-3587-2792D47B698C"
}
response = requests.post(url, data=data)
json_data = response.json()
verification_code = None
if json_data and json_data["status"] == "OK":
verification_code = json_data["code"]
# Сохраняем код в user_data
user_data[user_id]["verification_code"] = verification_code
print(f"Код верификации, отправленный пользователю: {verification_code}")
else:
print("Звонок не может быть выполнен.")
print("Текст ошибки:", json_data.get("status_text"))
return verification_code
async def save_message_data(message: types.Message, reply_to_message_id=None):
user_id = message.from_user.id
reply_to_message_id = last_bot_message_id.get(user_id, None)
user_messages[message.message_id] = {
"message_id": message.message_id,
"text": message.text,
"date": message.date.isoformat(), # Исправлено
"user_id": message.from_user.id,
"reply_to_message_id": reply_to_message_id
}
print(f"Сообщение пользователя {user_id} сохранено: {user_messages[message.message_id]}")
await send_message_to_server(user_messages[message.message_id])
def send_registration_request(user_data):
HEADER = {
"Content-Type": "application/json"
}
data = {
"telegram_id": user_data.get("telegram_id"),
"first_name": user_data["first_name"],
"second_name": user_data["middle_name"],
"last_name": user_data["last_name"],
"mobile_phone": user_data["phone_number"],
"birthday": user_data["birthday"]
}
print("Отправляемые данные на сервер:", data)
response = requests.post("http://46.146.229.242:1980/AppFindPac", headers=HEADER, json=data)
if response.status_code == 200:
result = response.json()
print("Результат JSON:", result)
return result.get('result')
else:
print(f"Ошибка при отправке данных. Статус-код: {response.status_code}")
return "error"
async def send_message_to_server(message_data):
url = "http://46.146.229.242:1980/AppSaveMessage"
headers = {"Content-Type": "application/json"}
async with aiohttp.ClientSession() as session:
async with session.post(url, headers=headers, json=message_data) as response:
if response.status == 200:
print(f"Сообщение {message_data['message_id']} успешно отправлено на сервер.")
else:
print(f"Ошибка при отправке сообщения {message_data['message_id']} на сервер. Статус-код: {response.status}")
def yes_no_markup():
markup = types.ReplyKeyboardMarkup(row_width=2, resize_keyboard=True)
item_yes = types.KeyboardButton("Да")
item_no = types.KeyboardButton("Нет")
markup.add(item_yes, item_no)
return markup
def markup2():
markup = types.ReplyKeyboardMarkup(row_width=2, resize_keyboard=True)
item_good = types.KeyboardButton("Всё верно")
item_no_good = types.KeyboardButton("Указать ФИО ещё раз")
markup.add(item_good, item_no_good)
return markup
def generate_start_markup():
markup = types.ReplyKeyboardMarkup(row_width=1, resize_keyboard=True)
start_button = types.KeyboardButton("/start")
markup.add(start_button)
return markup
def generate_markup_menu():
# Создаем клавиши
buttons = [
KeyboardButton("📝 Запись"),
KeyboardButton("🧰 Услуги"),
KeyboardButton(" Специалисты"),
KeyboardButton("🌍 Контакты"),
KeyboardButton("📞 Связь"),
]
# Создаем и настраиваем клавиатуру
markup = ReplyKeyboardMarkup(resize_keyboard=True, one_time_keyboard=False)
# Добавляем кнопки в столбик (по одной в строке)
markup.add(*buttons)
return markup
@dp.message_handler(content_types=types.ContentType.TEXT)
async def handle_message(message: types.Message):
await save_message_data(message)
if __name__ == '__main__':
executor.start_polling(dp, skip_updates=True)

BIN
requirements.txt

Binary file not shown.

BIN
s-blob-v1-IMAGE-tdNCrEv8Ldo.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 246 KiB

Loading…
Cancel
Save