|
|
|
|
@ -1,8 +1,9 @@
|
|
|
|
|
# bot_message.py
|
|
|
|
|
import re
|
|
|
|
|
|
|
|
|
|
from ai_agent.api_deepseek_ai import get_system_prompt, deepseek_chat_structured
|
|
|
|
|
from max_bot.max_api import *
|
|
|
|
|
import json
|
|
|
|
|
import qrcode
|
|
|
|
|
from ai_agent.api_common import get_system_prompt, get_ai_agent, call_ai_agent
|
|
|
|
|
from max_bot.max_api import *
|
|
|
|
|
from restoran_max_bot.bot_started import check_registration
|
|
|
|
|
from restoran_max_bot.common import *
|
|
|
|
|
from restoran_max_bot.iiko_api import customer_info, customer_create, customer_wallet
|
|
|
|
|
@ -11,24 +12,24 @@ from restoran_max_bot.settings import STATICFILES_DIRS
|
|
|
|
|
from restoran_max_bot.utils import has_key, is_json
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# отправка сообщения в группу администраторв по бронированию
|
|
|
|
|
def send_booking_to_crm(chat_id, date, time, people, contact):
|
|
|
|
|
# ---------- вспомогательные функции ----------
|
|
|
|
|
def send_booking_to_crm(chat_id, date, time, people, phone):
|
|
|
|
|
# TODO: реализовать отправку в CRM
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def send_contact_to_admin(chat_id, phone, contact_method, question, preferred_time, contact):
|
|
|
|
|
# TODO: реализовать отправку администратору
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# получение информации по интеграции с терминалом ikko, rkeeper
|
|
|
|
|
# ---------- получение бонусов ----------
|
|
|
|
|
def get_bonus(client: Client, phone: str, default_bonus: float, contact: Contact):
|
|
|
|
|
integration = common_get_integration(client=client)
|
|
|
|
|
bonus = 0
|
|
|
|
|
date = contact.field1
|
|
|
|
|
|
|
|
|
|
if len(date) < 2:
|
|
|
|
|
date = '0' + date
|
|
|
|
|
|
|
|
|
|
month = contact.field2
|
|
|
|
|
if len(month) < 2:
|
|
|
|
|
month = '0' + month
|
|
|
|
|
@ -39,23 +40,16 @@ def get_bonus(client: Client, phone: str, default_bonus: float, contact: Contact
|
|
|
|
|
customerinfo = customer_info(config['token'], phone, config['id_org'])
|
|
|
|
|
if not customerinfo:
|
|
|
|
|
birthday = f"1990-{month}-{date} 00:00:00.000"
|
|
|
|
|
|
|
|
|
|
dt = customer_create(api_key=config['token'], phone=phone, name=contact.name,
|
|
|
|
|
organization_id=config['id_org'], birthday=birthday)
|
|
|
|
|
|
|
|
|
|
dt = customer_info(config['token'], phone, config['id_org'])
|
|
|
|
|
|
|
|
|
|
customer_wallet(api_key=config['token'], iiko_wallet_id=dt['walletBalances'][0]['id'],
|
|
|
|
|
customer_id=dt['id'], organization_id=config['id_org'],
|
|
|
|
|
bonus=default_bonus)
|
|
|
|
|
|
|
|
|
|
bonus = default_bonus
|
|
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
bonus = customerinfo['walletBalances']
|
|
|
|
|
bonus = bonus[0]['balance']
|
|
|
|
|
bonus = customerinfo['walletBalances'][0]['balance']
|
|
|
|
|
|
|
|
|
|
# http://192.168.9.186:8890/docs
|
|
|
|
|
if integration.partner.slug == 'rkeeper':
|
|
|
|
|
config = json.loads(integration.setting)
|
|
|
|
|
rs = rkiper_customer_info(rkiper_server=config['url'], rkiper_token=config['token'], phone=phone)
|
|
|
|
|
@ -72,26 +66,24 @@ def get_bonus(client: Client, phone: str, default_bonus: float, contact: Contact
|
|
|
|
|
return bonus
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# получение вложения в сообщениях для их обработки (регистрация по номеру)
|
|
|
|
|
# ---------- получение вложений ----------
|
|
|
|
|
def get_attachments(message: dict):
|
|
|
|
|
chat_id = message['message']['recipient']['chat_id']
|
|
|
|
|
if 'attachments' in message['message']['body']:
|
|
|
|
|
if 'vcf_info' in message['message']['body']['attachments'][0]['payload']:
|
|
|
|
|
# Регулярное выражение: ищем всё после 'TEL;TYPE=cell:' до \r или конца строки
|
|
|
|
|
match = re.search(r'TEL;TYPE=cell:(\d+)',
|
|
|
|
|
message['message']['body']['attachments'][0]['payload']['vcf_info'])
|
|
|
|
|
if match:
|
|
|
|
|
phone_number = match.group(1)
|
|
|
|
|
return {'attachments_type': 'vcf_info', 'data': phone_number}
|
|
|
|
|
|
|
|
|
|
return {'attachments_type': False, 'data': ''}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def bot_message(client: Client, message: dict, settings_max: dict, settings_deepseek: dict, message_type):
|
|
|
|
|
# ---------- основной обработчик ----------
|
|
|
|
|
def bot_message(client: Client, message: dict, settings_max: dict, message_type):
|
|
|
|
|
chat_id = message['message']['recipient']['chat_id']
|
|
|
|
|
attachments = get_attachments(message=message)
|
|
|
|
|
|
|
|
|
|
# регистрируем по номеру телефона выдаем соответствующий контент
|
|
|
|
|
# регистрация по vcf
|
|
|
|
|
if attachments['attachments_type'] == 'vcf_info':
|
|
|
|
|
common_set_contact(client=client, uid_client=chat_id, name=message['message']['sender']['name'],
|
|
|
|
|
phone=attachments['data'])
|
|
|
|
|
@ -104,10 +96,11 @@ def bot_message(client: Client, message: dict, settings_max: dict, settings_deep
|
|
|
|
|
data = None
|
|
|
|
|
if message_type == 'message_created':
|
|
|
|
|
data = common_get_data(client=client, key=str(message['message']['body']['text']).lower())
|
|
|
|
|
|
|
|
|
|
if message_type == 'message_callback':
|
|
|
|
|
elif message_type == 'message_callback':
|
|
|
|
|
payload = json.loads(message['callback']['payload'])
|
|
|
|
|
data = common_get_data(client=client, key=str(payload['data']).lower())
|
|
|
|
|
|
|
|
|
|
# ---------- обработка стандартных команд (меню, бонусы и т.п.) ----------
|
|
|
|
|
if data:
|
|
|
|
|
for dt in data:
|
|
|
|
|
if dt.title == '##bonus##':
|
|
|
|
|
@ -116,28 +109,26 @@ def bot_message(client: Client, message: dict, settings_max: dict, settings_deep
|
|
|
|
|
url = f"https://maxbot.telefon-ip.ru/static/client_qr/{contact.phone}.png"
|
|
|
|
|
maxbot_send_img_message(chat_id=chat_id, max_token=settings_max['token'], img=url,
|
|
|
|
|
message='QR-код для начисления, списания бонусов.')
|
|
|
|
|
|
|
|
|
|
bonus = get_bonus(client=client, phone=contact.phone, default_bonus=float(dt.price), contact=contact)
|
|
|
|
|
maxbot_send_text_message(chat_id=chat_id, max_token=settings_max['token'],
|
|
|
|
|
message=f"💰 Ваш бонусный баланс: {bonus} руб")
|
|
|
|
|
|
|
|
|
|
if dt.title == '##feedback##':
|
|
|
|
|
maxbot_send_feedback_button(client=client, message='👇', chat_id=chat_id, max_token=settings_max['token'])
|
|
|
|
|
elif dt.title == '##feedback##':
|
|
|
|
|
maxbot_send_feedback_button(client=client, message='👇', chat_id=chat_id,
|
|
|
|
|
max_token=settings_max['token'])
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
if dt.title == '##booking##':
|
|
|
|
|
elif dt.title == '##booking##':
|
|
|
|
|
maxbot_send_booking_count_people_button(client=client, message='👇',
|
|
|
|
|
chat_id=chat_id, max_token=settings_max['token'])
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
# для более сложных функций
|
|
|
|
|
# сложные кнопки
|
|
|
|
|
if is_json(dt.title):
|
|
|
|
|
data = json.loads(dt.title)
|
|
|
|
|
if 'type' in dt.title:
|
|
|
|
|
if data['type'] == 'linkbutton':
|
|
|
|
|
maxbot_send_link_button(text=dt.descr, title_button=data['button'], link=dt.url,
|
|
|
|
|
chat_id=chat_id,
|
|
|
|
|
max_token=settings_max['token'])
|
|
|
|
|
data_json = json.loads(dt.title)
|
|
|
|
|
if 'type' in dt.title and data_json.get('type') == 'linkbutton':
|
|
|
|
|
maxbot_send_link_button(text=dt.descr, title_button=data_json['button'], link=dt.url,
|
|
|
|
|
chat_id=chat_id, max_token=settings_max['token'])
|
|
|
|
|
|
|
|
|
|
if dt.img:
|
|
|
|
|
url = f"https://cdn.telefon-ip.ru/{dt.img}?thumb=600"
|
|
|
|
|
@ -149,51 +140,46 @@ def bot_message(client: Client, message: dict, settings_max: dict, settings_deep
|
|
|
|
|
if dt.url and not is_json(dt.title):
|
|
|
|
|
maxbot_send_text_message(chat_id=chat_id, max_token=settings_max['token'], message=dt.url)
|
|
|
|
|
|
|
|
|
|
# отправка меню
|
|
|
|
|
maxbot_send_menu_button(chat_id=chat_id, max_token=settings_max['token'], message='👇 Выберите раздел',
|
|
|
|
|
client=client)
|
|
|
|
|
else:
|
|
|
|
|
# =========================== обработка сообщения через ИИ ===========================
|
|
|
|
|
if settings_deepseek.get('token', False):
|
|
|
|
|
text = message['message']['body']['text']
|
|
|
|
|
# Получаем системный промт из настроек
|
|
|
|
|
system_prompt = get_system_prompt(client)
|
|
|
|
|
if settings_deepseek.get('deepseek_system_prompt', False):
|
|
|
|
|
system_prompt = (system_prompt + "\n Дополнительная информация:\n" +
|
|
|
|
|
settings_deepseek.get('deepseek_system_prompt'))
|
|
|
|
|
|
|
|
|
|
# Отправляем запрос в DeepSeek
|
|
|
|
|
response = deepseek_chat_structured(
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
# ---------- обработка через AI ----------
|
|
|
|
|
# Проверяем, есть ли AI-агент у клиента
|
|
|
|
|
ai_agent = get_ai_agent(client)
|
|
|
|
|
if not ai_agent.get('ai_agent'):
|
|
|
|
|
maxbot_send_menu_button(chat_id=chat_id, max_token=settings_max['token'],
|
|
|
|
|
message='👇 Выберите раздел', client=client)
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
# Вызываем AI-агента через универсальную функцию
|
|
|
|
|
response = call_ai_agent(
|
|
|
|
|
client=client,
|
|
|
|
|
session_id=str(chat_id),
|
|
|
|
|
api_token=settings_deepseek.get('token'),
|
|
|
|
|
system_prompt=system_prompt,
|
|
|
|
|
user_query=text
|
|
|
|
|
user_query=message['message']['body']['text']
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# ---------- обработка ответа AI ----------
|
|
|
|
|
intent = response.get('intent')
|
|
|
|
|
message_text = response.get('message', '')
|
|
|
|
|
entities = response.get('entities', {})
|
|
|
|
|
status = response.get('status', 'complete')
|
|
|
|
|
|
|
|
|
|
# Если общий вопрос — просто отвечаем
|
|
|
|
|
if intent == 'general':
|
|
|
|
|
maxbot_send_text_message(chat_id, settings_max['token'], message_text)
|
|
|
|
|
|
|
|
|
|
elif intent == 'booking':
|
|
|
|
|
if status == 'need_more_info':
|
|
|
|
|
# Отправляем уточняющий вопрос
|
|
|
|
|
maxbot_send_text_message(chat_id, settings_max['token'], message_text)
|
|
|
|
|
elif status == 'complete':
|
|
|
|
|
# Все данные собраны — передаём в CRM
|
|
|
|
|
date = entities.get('date')
|
|
|
|
|
time = entities.get('time')
|
|
|
|
|
people = entities.get('people')
|
|
|
|
|
phone = entities.get('phone')
|
|
|
|
|
if date and time and people:
|
|
|
|
|
# Вызываем функцию для отправки в CRM
|
|
|
|
|
success = send_booking_to_crm(chat_id, date, time, people, phone)
|
|
|
|
|
if success:
|
|
|
|
|
confirm_msg = f"✅ Бронирование на {date} в {time} на {people} чел. принято! " \
|
|
|
|
|
f"Администратор свяжется с вами для уточнения вопросов"
|
|
|
|
|
confirm_msg = f"✅ Бронирование на {date} в {time} на {people} чел. принято! Администратор свяжется с вами."
|
|
|
|
|
else:
|
|
|
|
|
confirm_msg = "❌ Не удалось забронировать. Попробуйте позже."
|
|
|
|
|
maxbot_send_text_message(chat_id, settings_max['token'], confirm_msg)
|
|
|
|
|
@ -201,18 +187,16 @@ def bot_message(client: Client, message: dict, settings_max: dict, settings_deep
|
|
|
|
|
maxbot_send_text_message(chat_id, settings_max['token'], "⚠️ Не хватает данных для бронирования.")
|
|
|
|
|
else:
|
|
|
|
|
maxbot_send_text_message(chat_id, settings_max['token'], message_text)
|
|
|
|
|
|
|
|
|
|
elif intent == 'contact_admin':
|
|
|
|
|
if status == 'need_more_info':
|
|
|
|
|
# Отправляем уточняющий вопрос
|
|
|
|
|
maxbot_send_text_message(chat_id, settings_max['token'], message_text)
|
|
|
|
|
elif status == 'complete':
|
|
|
|
|
# Все данные собраны — передаём администратору
|
|
|
|
|
phone = entities.get('phone')
|
|
|
|
|
contact_method = entities.get('contact_method')
|
|
|
|
|
question = entities.get('question', '')
|
|
|
|
|
preferred_time = entities.get('preferred_time', '')
|
|
|
|
|
if phone and contact_method:
|
|
|
|
|
# Вызываем функцию отправки уведомления администратору
|
|
|
|
|
success = send_contact_to_admin(chat_id, phone, contact_method, question, preferred_time, contact)
|
|
|
|
|
if success:
|
|
|
|
|
confirm_msg = f"✅ Ваш запрос передан администратору. Способ связи: {contact_method}. Скоро с вами свяжутся."
|
|
|
|
|
@ -224,11 +208,11 @@ def bot_message(client: Client, message: dict, settings_max: dict, settings_deep
|
|
|
|
|
"⚠️ Не хватает данных для связи с администратором.")
|
|
|
|
|
else:
|
|
|
|
|
maxbot_send_text_message(chat_id, settings_max['token'], message_text)
|
|
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
maxbot_send_text_message(chat_id, settings_max['token'], message_text)
|
|
|
|
|
|
|
|
|
|
# После ответа отправляем меню (если нужно)
|
|
|
|
|
# всегда отправляем меню после ответа
|
|
|
|
|
maxbot_send_menu_button(chat_id=chat_id, max_token=settings_max['token'],
|
|
|
|
|
message='👇 Выберите раздел', client=client)
|
|
|
|
|
|
|
|
|
|
return True
|
|
|
|
|
|