| Server IP : 162.214.74.102 / Your IP : 216.73.217.114 Web Server : Apache System : Linux dedi-4363141.lrsys.com.br 3.10.0-1160.119.1.el7.tuxcare.els25.x86_64 #1 SMP Wed Oct 1 17:37:27 UTC 2025 x86_64 User : lrsys ( 1015) PHP Version : 5.6.40 Disable Function : exec,passthru,shell_exec,system MySQL : ON | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : ON Directory : /home/lrsys/public_html/lrsys_apps/leo/application/plugins/module_imobles/helpers/ |
Upload File : |
<?php
include_once __DIR__ . "/../helpers/AI/OpenAi.php";
include_once __DIR__ . "/../helpers/api/MainHelper.php";
include_once __DIR__ . "/../helpers/virtualAssistant/GptTools.php";
include_once __DIR__ . "/../helpers/whats/digisacHelper.php";
class MyGptHelper {
protected $openAiHelper;
protected $apiMainHelper;
protected $digisacHelper;
protected $gptTools;
protected $userId;
protected $userType;
protected $externalUser;
protected $digisacParams;
public function __construct($userType, $digisacParams, $externalUser = true) {
ORM::configure('caching', true);
@ini_set('memory_limit', '4095M');
@ini_set('max_execution_time', 0);
@set_time_limit(0);
ignore_user_abort(true);
$this->openAiHelper = new openaiHelper();
$this->apiMainHelper = new MainHelper();
$this->digisacHelper = new digisacHelper();
$this->gptTools = new GptTools();
$this->userId = null;
$this->userType = $userType;
$this->digisacParams = $digisacParams;
$this->externalUser = $externalUser;
}
public function startMyGptChat($digisac_contact_id = null, $msg = null) {
$user_id = null;
// Verifico se o vem do Digisac e se o contato já está cadastrado
if(!empty($digisac_contact_id)){
$digisac_contact_aux = $this->digisacHelper->getContactDetails($digisac_contact_id);
if($digisac_contact_aux){
$digisac_contact_details = ORM::for_table('module_imobles_mygpt_digisac_contacts')
->where('digisac_contact_id', $digisac_contact_id)
->where('user_type', $this->userType)
->find_one();
if(empty($digisac_contact_details->id)){
$digisac_contact_details = ORM::for_table('module_imobles_mygpt_digisac_contacts')->create();
if($this->userType == 'sys_user'){
$user = ORM::for_table('sys_users')->where('phonenumber', $digisac_contact_aux->data->number)->find_one();
if(isset($user->id)){
$user_id = $user->id;
} else {
// Faço o cadastro do Corretor na tabela de sys_user
$user = ORM::for_table('sys_users')->create();
$user->fullname = $digisac_contact_aux->name;
$user->phonenumber = $digisac_contact_aux->data->number;
$user->user_type = 'CORRETOR';
$user->role = 'CORRETOR';
$user->roleid = 8;
$user->save();
$user_id = $user->id;
}
$digisac_contact_details->sys_user_id = $user_id;
} else {
$user = ORM::for_table('crm_accounts')->where('phone', $digisac_contact_aux->data->number)->find_one();
if(isset($user->id)){
$user_id = $user->id;
} else {
// Faço o cadastro do Cliente na tabela de contatos
$user = ORM::for_table('crm_accounts')->create();
$user->account = $digisac_contact_aux->name;
$user->fname = $digisac_contact_aux->name;
$user->phone = $digisac_contact_aux->data->number;
$user->save();
$user_id = $user->id;
}
$digisac_contact_details->crm_account_id = $user_id;
}
$digisac_contact_details->digisac_contact_id = $digisac_contact_id;
$digisac_contact_details->user_type = $this->userType;
$digisac_contact_details->save();
} else {
if($this->userType == 'sys_user'){
$user_id = $digisac_contact_details->sys_user_id;
$sys_user = ORM::for_table('sys_users')->find_one($user_id);
if(!empty($sys_user->roleid) && $sys_user->roleid != 8){
$this->externalUser = false;
}
} else {
$user_id = $digisac_contact_details->crm_account_id;
}
}
} else {
return false;
}
} else {
return false;
}
if($this->userType == 'sys_user'){
if($this->externalUser === false){
$msg = "Olá, tudo bem?\nEu sou o MyGPT, assistente virtual da MySide.com.br, baseado em inteligência artifical, e vou te ajudar a encontrar a gerenciar seu Pipe de Vendas.
\nVocê pode registrar NOTAS ou agendar TAREFAS para qualquer cliente que esteja com o status Em Aberto no seu pipe, basta informar o que quer fazer (registrar nota ou agendar tarefa), e o nome do cliente.
\nAh, pode enviar por *texto ou áudio*, o que for melhor pra você. Fala que eu te escuto!!!
\n\n*MUITO IMPORTANTE:* essa é uma versão BETA do MyGPT, para ela funcionar adequadamente vocẽ deve
fazer uma pergunta e aguardar a resposta, caso contrário nosso bot pode se perder na conversa.";
} else {
$msg = "Olá, corretor! Tudo bem?\n"
."Sou o Broker Guru e estou aqui para te ajudar a encontrar apartamentos para seus clientes em Goiânia!\n\n"
."Sou ainda uma versão beta e, por enquanto, só trabalho com aptos na planta ou prontos para morar direto das construtoras.\n\n"
."Me fale que tipo de imóvel você está procurando e vou listar algumas boas opções.\n\n"
."🎤 Se preferir, pode enviar áudio tb!";
}
$digisac_params = array("contact_id" => $digisac_contact_aux->id, "service_id" => $digisac_contact_aux->serviceId, "subject" => "MYGPT - Envio de mensagem de boas-vindas.");
} else {
$msg = "Olá, tudo bem?\nEu sou o MyGPT, assistente virtual da MySide.com.br, baseado em inteligência artifical, e vou te ajudar a encontrar o imóvel ideal para você.
\nPrimeiro preciso apenas que me diga o que está procurando, por exemplo, a cidade e bairros, quantidade de quartos, suítes ou garagens.
\nInforme também algumas caracterísicas desejadas como churrasqueira, piscina, sauna ou qualquer outro tipo de detalhes.
\nPara um resultado ainda melhor, diga a faixa de preço e metragem.
\nAh, pode enviar por *texto ou áudio*, o que for melhor pra você. Fala que eu te escuto!!!
\n\n*MUITO IMPORTANTE:* essa é uma versão BETA do MyGPT, para ela funcionar adequadamente você deve fazer uma pergunta e aguardar a resposta, caso contrário nosso bot pode se perder na conversa.";
$digisac_params = array("contact_id" => $digisac_contact_aux->id, "service_id" => $digisac_contact_aux->serviceId, "subject" => "MYGPT - Envio de mensagem de boas-vindas.");
}
$send_message = $this->sendMessage($msg, 'start_mygpt', $user_id, null, 1, 1, $digisac_params);
}
public function messageType($message) {
// Verifico qual foi o tipo da última mensagem enviada para saber o que estamos aguardando
if($this->userType == 'sys_user'){
$messages_history = ORM::for_table('module_imobles_mygpt_messages')
->where('sys_user_id', $this->userId)
->where_not_equal('msg_type', 'server_off')
->order_by_desc('id')
->find_one();
} elseif($this->userType == 'crm_account') {
$messages_history = ORM::for_table('module_imobles_mygpt_messages')
->where('crm_account_id', $this->userId)
->where_not_equal('msg_type', 'server_off')
->order_by_desc('id')
->find_one();
}
$arr_type = null;
$params = null;
if(isset($messages_history->id) && $messages_history->is_from_bot == 1){
$date1 = new DateTime();
$date2 = new DateTime($messages_history->created_at);
$interval = $date1->diff($date2);
$minute_diff = ($interval->h * 60) + $interval->i;
if($minute_diff < 30){
switch($messages_history->msg_type){
case 'create_note_save':
$arr_type = array("type" => 'create_note_save', "params" => $messages_history->params);
break;
case 'create_task_save':
$arr_type = array("type" => 'create_task_save', "params" => $messages_history->params);
break;
case 'closing_visit_save':
$arr_type = array("type" => 'closing_visit_save', "params" => $messages_history->params);
break;
case 'new_search':
$arr_type = array("type" => 'new_search', "params" => $messages_history->params);
break;
default:
if(!empty($messages_history->params)){
$params_aux = json_decode($messages_history->params,true);
$arr_params = array();
$arr_params['filter'] = array(
"crm_account_id" => @$params_aux['filter']['crm_account_id'],
"deal_id" => @$params_aux['filter']['deal_id'],
"name" => @$params_aux['filter']['name']);
$params = json_encode($arr_params);
}
break;
}
}
}
if(!empty($arr_type)){
if($arr_type['type'] == 'new_search'){
$type = null;
// $prompt = 'O objetivo é determinar se o valor de UserInputText indica a necessidade de reiniciar a pesquisa ou busca. '
// .'Para retornar TRUE, a frase deve ser \"Reiniciar a pesquisa\", \"Reiniciar busca\", \"Reiniciar\" ou qualquer sinônimo equivalente.'
// .' Caso contrário, deve retornar FALSE. '
// .'Tente determinar também se o valor do UserInput se refere a qualquer pergunta ou dúvida '
// .'sobre as funcionalidades ou informações sobre o funcionamento deste chat que é chamado de BROKER GURU.'
// .'Verifique também se no texto do UserInputText o cliente expressa a intenção de receber documentos dos imóveis, como cartões de resumo, apresentações ou expressões equivalentes. '
// .'Exemplos que não são expressões equivalentes: material do imóvel, fotos, tabela, book e pdf.'
// .'O resultado esperado deve ser exibido no formato abaixo:\n'
// // .' solicitando recomçar uma pesquisa do zero, desconsiderando as informações anteriores. A mensagem deve conter apenas \"Recomeçar pesquisa\" ou algum sinônimo.\n'
// // .'Exibir o resultado no formato abaixo:\n'
// .'restart_search:<boolean_value_for_reiniciar_pesquisa>\n'
// .'send_cards:<boolean>\n'
// .'chat_info:<<boolean>\n\n'
// .'UserInputText: \n\"\"\"\n'.$message.'\n\"\"\"';
// $prompt = 'Você é um assistente virtual para corretores de imóveis e seu nome é Broker Guru. '
// .'Seu objetivo é ajudar corretores de imóveis em 4 funções: \n'
// .'1 - Realizar buscas por imóveis conforme características dos imóveis que são informadas pelo corretor. '
// .'Exemplos de características de imóveis: preço, bairro, quantidade de quartos, etc; '
// .'2 - Reiniciar nova busca quando o corretor quiser; '
// .'3 - Enviar \"cartões resumo\" de imóveis para o corretor. O corretor será explícito quando quiser '
// .'receber os cartões resumo e usará expressões como \"mande os cartões resumo\", \"quero receber os cartões\" e equivalentes. '
// .'Exemplos que não são expressões equivalentes: material do imóvel, fotos, tabela, book e pdf; '
// .'4 - Responder dúvidas dos corretores sobre o que é o Broker Guru, incluindo saber quem são seus criadores, funcionalidades, '
// .'o preço cobrado pelo uso e outras questões similares.\n'
// .'Analise o texto do campo UserInputText e identifique qual função do Broker Guru o corretor gostaria de usar. '
// .'Se a intenção for usar a função de busca, preencha FALSE em todas as variáveis, '
// .'se a intenção for usar a função de recomeçar a busca, preencha TRUE no campo restart_search, '
// .'se a intenção for a usar a função de enviar \"cartões resumo\" preencha TRUE no campo send_cards '
// .'e se a intenção for saber mais sobre o Boker Guru, preencha TRUE no campo chat_info. '
// .'Preencha FALSE quando a variável não for TRUE.\n'
// .'O resultado esperado deve ser exibido no formato abaixo:\n'
// .'restart_search:<boolean_value_for_reiniciar_pesquisa>\n'
// .'send_cards: <boolean>\n'
// .'chat_info:<boolean>\n'
// .'UserInputText: \"\"\"\n'.$message.'\n\"\"\"';
// $prompt = 'Responda estas três perguntas:\n'
// .'- Pergunta 1: O UserInputText pede enviar cartões resumo dos imóveis ou expressões equivalentes. '
// .'Exemplos que não são expressões equivalentes: material do imóvel, fotos, tabela, book e pdf.\n'
// .'- Pergunta 2: O UserInputText pede para \"Reiniciar a pesquisa\" ou um sinônimo?\n\n'
// .'- Pergunta 3: O UserInputText se refere a qualquer pergunta ou dúvida '
// .'sobre as funcionalidades ou informações sobre o funcionamento deste CHAT que é chamado de BROKER GURU?\n\n'
// .'Responda neste formato:\n'
// .'restart_search:<boolean>\n'
// .'send_cards:<boolean>\n'
// .'chat_info:<<boolean>\n\n'
// .'UserInputText: \n\"\"\"\n'.$message.'\n\"\"\"';
// $prompt = "Responda estas duas perguntas:\n"
// ."- Pergunta 1: O UserInputText pede enviar cartões resumo dos imóveis ou expressões equivalentes. "
// ."Exemplos que não são expressões equivalentes: material do imóvel, fotos, tabela, book e pdf.\n"
// ."- Pergunta 2: O UserInputText pede para 'Reiniciar a pesquisa' ou um sinônimo?\n"
// ."Responda neste formato:\n"
// ."restart_search:<boolean>\n"
// ."send_cards:<boolean>\n";
// $prompt = 'O assistente virtual Broker Guru é um assistente de corretor de imóvel. '
// .'Sua tarefa é analisar a mensagem que o corretor de imóveis envia para o Broker Guru através do campo \"UserInputText\", '
// .'interpretar qual a intenção de uso do corretor e classificar em uma das 4 funções, conforme abaixo:\n'
// .'1 - Função \"Realizar buscas\": o corretor informa características de imóveis que procura e o Broker Guru busca em sua base de '
// .'dados por imóveis disponíveis. Exemplos: apto de 2 quartos; imóvel de 2 quartos, veja alguns aptos no setor bueno; 3Q no marista; '
// .'empreendimentos na planta; mande opcoes de 1 quarto; envie aptos em goiânia; '
// .'adicione opções no bairro centro; filtre opções de 4 quartos; etc.\n'
// .'2 - Função \"reiniciar busca\" por imóveis. Nesta função o corretor precisa que o Broker Guru recomece a busca do zero. '
// .'Exemplos de mensagens que demonstram essa intenção: reiniciar busca, nova busca, recomeçar, reiniciar, zerar busca, etc.\n'
// .'3 - Função \"fornecer cartões resumo\" de imóveis para o corretor. É quando o corretor pede, explicitamente, '
// .'para receber os cartões resumo do imóvel. O corretor irá usar, obrigatoriamente, as palavras card ou cartão. '
// .'Exemplos: envie os cards, mande os cards, quero os cartões resumo, quero os cartões, gerar cartões, etc.\n'
// .'4 - Função \"responder dúvidas sobre o Broker Guru\". Exemplos: o que é o Broker Guru, quem são seus criadores, '
// .'quais as funcionalidades, o que faz, o que vende, se trabalha só com imóveis, o preço cobrado pelo uso e '
// .'outras questões similares.\nSe a intenção for usar a função \"realizar buscas\", preencha FALSE em todas as variáveis. '
// .'Importante, se o cliente informar no UserInputText termos como \"casas \", \"terrenos \", \"imóveis comerciais \" retornar a variável chat_info como TRUE.\n'
// .'Em outros casos, preencha TRUE na respectiva variável. Somente uma variável pode ser TRUE. '
// .'Preencha FALSE quando qualquer variável não for TRUE. '
// .'O resultado esperado deve ser exibido no formato abaixo:\n'
// .'restart_search:<boolean_value_for_reiniciar_pesquisa>\n'
// .'send_cards: <boolean>\n'
// .'chat_info:<boolean>\n'
// .'UserInputText: \"\"\"\n'.$message.'\n\"\"\"';
$prompt = 'Broker Guru é um assistente virtual para corretores de imóveis. As mensagens dos corretores são interpretadas para acionar uma destas 4 funções:'
.'\nBusca de imóveis: Corretor descreve características de imóveis para encontrar. Exemplos: apto de 2 quartos; imóvel de 2 quartos; '
.'imóvel de 2Q no marista; 3Q no bueno; empreendimentos na planta; mande opcoes de 1 quarto; adicione opções no centro; filtre opções de 4Q; etc.'
.'\nResponder dúvidas: Corretor faz perguntas sobre o Broker Guru.'
.'\nReiniciar busca: Corretor pede para iniciar uma nova busca.'
.'\nFornecer cartões resumo: Corretor pede explicitamente por cartões resumo.'
.'\nPreencha uma das seguintes variáveis considerando a intenção do corretor:'
.'\nsearch_out_of_scope: TRUE para buscar imóveis como ágio, aluguel, terreno, imóvel comercial, sala comercial, sobrados ou casas.'
.'\nsearch_in_scope_and_others: TRUE para outros tipos de busca.'
.'\nrestart_search: TRUE para iniciar nova busca.'
.'\nsend_cards: TRUE para fornecer cartões resumo.'
.'\nchat_info: TRUE para responder dúvidas sobre o Broker Guru.'
.'\nsearch_in_scope_and_others: TRUE se nenhuma das anteriores for verdadeira.'
.'\nSó pode haver um TRUE por consulta. '
.'Resultado esperado:\n'
.'restart_search:<boolean>\n'
.'send_cards:<boolean>\n'
.'chat_info:<boolean>\n'
.'search_out_of_scope:<boolean>\n'
.'search_in_scope_and_others:<boolean>\n'
.'UserInputText: \"\"\"\n'.$message.'\n\"\"\"';
// echo $prompt;exit;
$try_again = false;
$attempts = 0;
$completions = $this->openAiHelper->completions($prompt);
// var_dump($completions);exit;
if($completions['error'] === true){
$try_again = true;
while($try_again === true){
sleep(1);
$completions = $this->openAiHelper->completions($prompt);
if(isset($completions['data']->choices[0]->text)){
$try_again = false;
} else {
if($attempts >= 10){
// $chat_msg = "Oops, infelizmente estamos passando por uma instabilidade em nossos servidores, isso é raro mas acontece muito 😅.\n\nBrincadeirinha, basta enviar novamente sua mensagem e tudo voltará ao normal.";
$chat_msg = "Desculpe, houve um problema e não consegui entender sua mensagem. Sou um Guru ainda em aprendizado e tentando melhorar a cada dia 🏋️♂️.\n\nPor favor, me fale novamente os detalhes do que você busca.";
$return = $this->sendMessage($chat_msg, 'server_off', $this->userId, null, null, 1, $this->digisacParams);
return $return;
}
}
$attempts++;
}
}
// var_dump($completions);exit;
if(isset($completions['data']->choices[0]->text)){
$completion_text = trim($completions['data']->choices[0]->text);
$data = explode(PHP_EOL,$completion_text);
// var_dump($data);exit;
foreach($data as $d){
$f = explode(':',$d);
if(!isset($f[0]) || empty(trim($f[0]))){
continue;
}
if(!isset($f[1]) || empty(trim($f[1]))){
continue;
}
$param = $f[0];
$val = $f[1];
switch($param){
case 'restart_search':
if(preg_match('(true)i', $val)){
$type = 'restart_search';
}
break;
case 'chat_info':
if(preg_match('(true)i', $val)){
$type = 'chat_bot';
}
break;
case 'send_cards':
if(preg_match('(true)i', $val)){
$type = 'send_cards';
}
break;
case 'search_out_of_scope':
if(preg_match('(true)i', $val)){
$type = 'chat_bot';
}
break;
}
}
}
if(!empty($type)){
$arr_type['type'] = $type;
// $arr_type['params'] = null;
}
}
// var_dump($arr_type);exit;
return $arr_type;
}
// var_dump($arr_type);exit;
$type = 'chat_bot';
if($this->userType == 'sys_user'){
if($this->externalUser === true){
$prompt = 'O texto se refere a uma mensagem enviada por um cliente,'
.' solicitando uma das funções abaixo:\n'
.'- Pesquisar ou procurar apartamentos ou imóveis;\n'
// .'- Recomeçar a pesquisa;\n'
// .'- Salvar resuldatos da última pesquisa realizada;\n'
// .'- Solicitar mais informações sobre um empreendimento;\n'
// .'- Agendar uma visita;\n '
// .'- Registrar, incluir, salvar ou cadastrar uma NOTA, COMENTÁRIO, LEMBRETE ou ANOTAÇÃO para um determinado cliente. '
// .'Importante. uma nota pode conter a palavra TAREFA, isso não faz da Nota um Tarefa;\n '
// .'- Registrar ou agendar uma TAREFA ou ATIVIDADE para um determinado cliente;\n '
// .'- Listar, Mostrar, carregar as TAREFAS, ATIVIDADES, COMPROMISSOS para um determinado cliente;\n '
// .'- Realizar, Registrar, incluir, salvar ou cadastrar um FECHAMENTO DE VISITA para um determinado cliente;\n '
.'- Qualquer pergunta ou dúvida sobre as funcionalidades ou informações sobre o funcionamento deste chat que é chamado de BROKER GURU;\n\n '
.'Exibir o resultado no formato abaixo:\n'
.'new_search:<bollean_value_pesquisar_apartamentos_rocket>\n'
// .'save_results:<bollean_value_salvar_pesquisa>\n'
// .'more_info:<bollean_value_solicitar_informações>\n'
// .'visit_schedule:<bollean_value_agendar_visita>\n\n'
// .'create_note:<bollean_value_registrar_nota_comentario_lembrete_ou_anotacao>\n\n'
// .'create_task:<bollean_value_registrar_tarefa_ou_atividade>\n\n'
// .'list_tasks:<bollean_value_listar_tarefas>\n\n'
.'chat_info:<bollean_value_duvidas_ou_informacoes_sobre_chat>\n\n'
// .'closing_visit:<bollean_value_realizar_fechamento_visita>\n\n'
// .'restart_search:<bollean_value_for_recomecar_pesquisa>\n\n'
.'Text: \"\"\"'.$message.'\n\"\"\"';
} else {
$prompt = 'O texto se refere a uma mensagem enviada por um cliente,'
.' solicitando uma das funções abaixo:\n'
.'- Pesquisar ou procurar apartamentos ou imóveis;\n'
// .'- Recomeçar a pesquisa;\n'
// .'- Salvar resuldatos da última pesquisa realizada;\n'
// .'- Solicitar mais informações sobre um empreendimento;\n'
// .'- Agendar uma visita;\n '
.'- Registrar, incluir, salvar ou cadastrar uma NOTA, COMENTÁRIO, LEMBRETE ou ANOTAÇÃO para um determinado cliente. '
.'Importante. uma nota pode conter a palavra TAREFA, isso não faz da Nota um Tarefa;\n '
.'- Registrar ou agendar uma TAREFA ou ATIVIDADE para um determinado cliente;\n '
// .'- Listar, Mostrar, carregar as TAREFAS, ATIVIDADES, COMPROMISSOS para um determinado cliente;\n '
.'- Realizar, Registrar, incluir, salvar ou cadastrar um FECHAMENTO DE VISITA para um determinado cliente;\n '
.'- Qualquer pergunta ou dúvida sobre as funcionalidades ou informações sobre o funcionamento deste chat que é chamado de BROKER GURU;\n\n '
.'Exibir o resultado no formato abaixo:\n'
.'new_search:<bollean_value_pesquisar_apartamentos_rocket>\n'
// .'save_results:<bollean_value_salvar_pesquisa>\n'
.'more_info:<bollean_value_solicitar_informações>\n'
// .'visit_schedule:<bollean_value_agendar_visita>\n\n'
.'create_note:<bollean_value_registrar_nota_comentario_lembrete_ou_anotacao>\n\n'
.'create_task:<bollean_value_registrar_tarefa_ou_atividade>\n\n'
// .'list_tasks:<bollean_value_listar_tarefas>\n\n'
.'chat_info:<bollean_value_duvidas_ou_informacoes_sobre_chat>\n\n'
.'closing_visit:<bollean_value_realizar_fechamento_visita>\n\n'
// .'restart_search:<bollean_value_for_recomecar_pesquisa>\n\n'
.'Text: \"\"\"'.$message.'\n\"\"\"';
}
} else {
$prompt = 'O texto se refere a uma mensagem enviada por um cliente '
.' que está procurando um imóvel ou apartamento para comprar '
.'ou deseja apenas informações gerais sobre o Mercado Imobiliário:\n'
.'- Pesquisar por apartamentos ou imóveis;\n'
.'- Salvar resuldatos da última pesquisa realizada;\n'
.'- Solicitar mais informações sobre um empreendimento;\n'
.'- Agendar uma visita;\n '
.'- Registrar, incluir, salvar ou cadastrar uma NOTA, COMENTÁRIO, LEMBRETE ou ANOTAÇÃO para um determinado cliente. '
.'Importante. uma nota pode conter a palavra TAREFA, isso não faz da Nota um Tarefa;\n '
.'- Registrar ou agendar uma TAREFA ou ATIVIDADE para um determinado cliente;\n '
.'- Listar, Mostrar, carregar as TAREFAS, ATIVIDADES, COMPROMISSOS para um determinado cliente;\n '
.'- Realizar, Registrar, incluir, salvar ou cadastrar um FECHAMENTO DE VISITA para um determinado cliente;\n '
.'- Qualquer pergunta ou dúvida sobre as funcionalidades ou o funcionamento deste chat;\n\n '
.'Exibir o resultado no formato abaixo:\n'
.'new_search:<bollean_value_pesquisar_apartamentos_rocket>\n'
.'save_results:<bollean_value_salvar_pesquisa>\n'
.'more_info:<bollean_value_solicitar_informações>\n'
// .'visit_schedule:<bollean_value_agendar_visita>\n\n'
.'create_note:<bollean_value_registrar_nota_comentario_lembrete_ou_anotacao>\n\n'
.'create_task:<bollean_value_registrar_tarefa_ou_atividade>\n\n'
.'list_tasks:<bollean_value_listar_tarefas>\n\n'
.'mygpt_info:<bollean_value_is_a_question>\n\n'
.'closing_visit:<bollean_value_realizar_fechamento_visita>\n\n'
.'Text: \"\"\"'.$message.'\n\"\"\"';
}
$completions = $this->openAiHelper->completions($prompt);
$try_again = false;
$attempts = 0;
if($completions['error'] === true){
$try_again = true;
while($try_again === true){
sleep(1);
$completions = $this->openAiHelper->completions($prompt);
if(isset($completions['data']->choices[0]->text)){
$try_again = false;
} else {
if($attempts >= 10){
// $chat_msg = "Oops, infelizmente estamos passando por uma instabilidade em nossos servidores, isso é raro mas acontece muito 😅.\n\nBrincadeirinha, basta enviar novamente sua mensagem e tudo voltará ao normal.";
$chat_msg = "Desculpe, houve um problema e não consegui entender sua mensagem. Sou um Guru ainda em aprendizado e tentando melhorar a cada dia 🏋️♂️.\n\nPor favor, me fale novamente os detalhes do que você busca.";
$return = $this->sendMessage($chat_msg, 'server_off', $this->userId, null, null, 1, $this->digisacParams);
return $return;
}
}
$attempts++;
}
}
if(isset($completions['data']->choices[0]->text)){
$completion_text = trim($completions['data']->choices[0]->text);
$data = explode(PHP_EOL,$completion_text);
// var_dump($data);exit;
foreach($data as $d){
$f = explode(':',$d);
if(!isset($f[0]) || empty(trim($f[0]))){
continue;
}
if(!isset($f[1]) || empty(trim($f[1]))){
continue;
}
$param = $f[0];
$val = $f[1];
switch($param){
case 'save_results':
if(preg_match('(true)i', $val)){
$type = 'save_results';
}
break;
case 'new_search':
if(preg_match('(true)i', $val)){
$type = 'new_search';
}
break;
case 'more_info':
if(preg_match('(true)i', $val)){
$type = 'more_info';
}
break;
case 'visit_schedule':
if(preg_match('(true)i', $val)){
$type = 'visit_schedule';
}
break;
case 'create_task':
if(preg_match('(true)i', $val)){
$type = 'create_task';
}
break;
case 'create_note':
if(preg_match('(true)i', $val)){
$type = 'create_note';
}
break;
case 'list_tasks':
if(preg_match('(true)i', $val)){
$type = 'list_tasks';
}
break;
case 'chat_info':
if(preg_match('(true)i', $val)){
$type = 'chat_bot';
}
break;
case 'mygpt_info':
if(preg_match('(true)i', $val)){
$type = 'mygpt_info';
}
break;
case 'closing_visit':
if(preg_match('(true)i', $val)){
$type = 'closing_visit';
}
break;
// case 'restart_search':
// if(preg_match('(true)', $val)){
// $type = 'restart_search';
// }
// break;
default:
$type = 'chat_bot';
break;
}
}
}
$arr_type = array("type" => $type, "params" => $params);
// var_dump($arr_type);exit;
// $arr_type['type'] = $type;
return $arr_type;
}
public function readMessage($message, $user_id) {
$this->userId = $user_id;
$sys_user = ORM::for_table('sys_users')->find_one($this->userId);
if(!empty($sys_user->roleid) && $sys_user->roleid != 8){
$this->externalUser = false;
}
$income_msg = null;
$message = json_decode(json_encode($message));
if($message->type == 'ptt' || $message->type == 'audio'){
$response = $this->digisacHelper->getMessageDetails($message);
if(isset($response->data[0]->data->fileDownload->isDownloading) && $response->data[0]->data->fileDownload->isDownloading === true){
$try_again = true;
$count_try = 0;
while($try_again === true){
$response = $this->digisacHelper->getMessageDetails($message);
if(isset($response->data[0]->data->fileDownload->isDownloading) && $response->data[0]->data->fileDownload->isDownloading === true){
$try_again = true;
$count_try++;
sleep(2);
} else {
$try_again = false;
$message = $response->data[0];
}
if($count_try > 500){
return false;
}
}
} else {
$message = $response->data[0];
}
$file_name = 'application/plugins/module_imobles/uploads/temp/'.$message->file->name;
file_put_contents($file_name, file_get_contents($message->file->url));
$file = $this->convert($file_name);
$transcription = $this->openAiHelper->transcriptions($file['file']);
$try_again = false;
$attempts = 0;
if($transcription['error'] === true){
$try_again = true;
while($try_again === true){
sleep(1);
$transcription = $this->openAiHelper->transcriptions($file['file']);
if(isset($transcription['data']->text)){
$try_again = false;
} else {
if($attempts >= 10){
// $chat_msg = "Oops, infelizmente estamos passando por uma instabilidade em nossos servidores, isso é raro mas acontece muito 😅.\n\nBrincadeirinha, basta enviar novamente sua mensagem e tudo voltará ao normal.";
$chat_msg = "Desculpe, houve um problema e não consegui entender sua mensagem. Sou um Guru ainda em aprendizado e tentando melhorar a cada dia 🏋️♂️.\n\nPor favor, me fale novamente os detalhes do que você busca.";
$return = $this->sendMessage($chat_msg, 'server_off', $this->userId, null, null, 1, $this->digisacParams);
return $return;
}
}
$attempts++;
}
}
unlink($file['file']);
if(isset($transcription['data']->text)){
$income_msg = $transcription['data']->text;
} else {
return false;
}
} elseif($message->type == 'chat'){
$income_msg = str_replace(PHP_EOL, '\n', $message->text);
} else {
return false;
}
if(!empty($income_msg)){
$params = null;
$type_msg = $this->messageType($income_msg);
if(is_array($type_msg)){
$params = isset($type_msg['params'])?$type_msg['params']:null;
$type_msg = $type_msg['type'];
}
$save_message = $this->saveMessage($income_msg,$type_msg, $this->userId, null, null, null, $message->id);
// TODO: forçar uma pesquisa se o corretor for Externo
if($this->externalUser === true
&& $type_msg != "new_search"
&& $type_msg != "restart_search"
&& $type_msg != "chat_bot"
&& $type_msg != "send_cards"
&& $type_msg != "broker_guru_info"){
// $msg = "Não entendi muito bem o que você quis dizer, me desculpe! Sou um Guru ainda em aprendizado e tentando melhorar a cada dia 🏋️♂️.\n\n"
// ."Me fale novamente os detalhes do imóvel que você busca.";
$msg = "Desculpe, houve um problema e não consegui entender sua mensagem. Sou um Guru ainda em aprendizado e tentando melhorar a cada dia 🏋️♂️.\n\nPor favor, me fale novamente os detalhes do que você busca.";
$send_message = $this->sendMessage($msg, 'new_search', $user_id, null, 1, 1, $this->digisacParams);
return false;
}
switch($type_msg){
case "new_search":
if(!empty($params)){
$params_aux = json_decode($params,true);
} else {
$params_aux['filter'] = null;
}
$return = $this->typeMessageNewSearch($income_msg, $params_aux['filter']);
return true;
break;
case "more_info":
$return = $this->typeMessageMoreInfo($message, $income_msg);
return $return;
break;
case "visit_schedule":
$return = $this->typeMessageVisitSchedule($message, $income_msg);
return $return;
break;
case "save_results":
$return = $this->typeMessageSaveResults($message, $income_msg);
return true;
break;
case "create_note":
if(!empty($params)){
$params_aux = json_decode($params,true);
} else {
$params_aux = null;
}
$return = $this->typeMessageCreateNote($income_msg, $params_aux['filter']);
return true;
break;
case "create_note_save":
$params_aux = json_decode($params,false);
if(!empty($params_aux->filter->task_date) && !empty($params_aux->filter->message)){
$return = $this->typeMessageCreateNoteSave($income_msg, $params);
} else {
$params_aux = json_decode($params,true);
$return = $this->typeMessageCreateNote($income_msg, $params_aux['filter']);
}
return true;
break;
case "chat_bot":
$return = $this->typeMessageChatBot();
return $return;
break;
case "create_task":
if(!empty($params)){
$params_aux = json_decode($params,true);
} else {
$params_aux = null;
}
$return = $this->typeMessageCreateTask($income_msg, $params_aux['filter']);
return true;
break;
case "create_task_save":
$params_aux = json_decode($params,false);
if(!empty($params_aux->filter->task_date) && !empty($params_aux->filter->message)){
$return = $this->typeMessageCreateTaskSave($income_msg, $params);
} else {
$params_aux = json_decode($params,true);
$return = $this->typeMessageCreateTask($income_msg, $params_aux['filter']);
}
return true;
break;
case "list_tasks":
$return = $this->typeMessageListTasks($income_msg);
return true;
break;
case "broker_guru_info":
$return = $this->typeMessageBrokerGuruInfo($income_msg,$income_msg);
return true;
break;
case "send_cards":
$return = $this->typeMessageSendCards($params);
return true;
break;
case "mygpt_info":
// $return = $this->typeMessageMygptInfo($income_msg,$income_msg);
$return = $this->typeMessageChatBot();
return true;
break;
case "closing_visit":
$return = $this->typeMessageClosingVisit($income_msg);
return true;
break;
case "closing_visit_save":
$params_aux = json_decode($params,false);
if(!empty($params_aux->filter->task_date) && !empty($params_aux->filter->message)){
$return = $this->typeMessageClosingVisitSave($params);
} else {
$params_aux = json_decode($params,true);
$return = $this->typeMessageClosingVisit($income_msg, $params_aux['filter']);
}
return true;
break;
case "restart_search":
$msg = "Perfeito, vamos começar uma nova pesquisa. Me fale que tipo de imóvel você está procurando e vou listar algumas boas opções.\n\n";
$msg .= "*Sugestão:* para fazer uma pesquisa de forma rápida, envie um áudio no formato abaixo:\n\n"
."Procurar apartamentos em *Goiânia*, no *Setor Bueno*, com 2 ou 3 *quartos*, "
."entre 100 e 200 *metros quadrados*, com preços até *R$ 900*, com *Piscina e Academia*.";
$send_message = $this->sendMessage($msg, 'new_search', $user_id, null, 1, 1, $this->digisacParams);
// $return = $this->typeMessageChatBot(null,'Informe para o cliente que para recomeçar uma pesquisa ele deve enviar uma mensagem no padrão: Procurar apartamentos no BAIRRO.');
return true;
break;
default:
$return = $this->typeMessageNotFound($message, $income_msg);
return $return;
break;
}
}
}
public function typeMessageChatBot($msg_systen_1 = null, $msg_systen_2 = null){
if($this->userType == 'sys_user'){
$messages_history = ORM::for_table('module_imobles_mygpt_messages')
->where('msg_type', 'chat_bot')
->where('sys_user_id', $this->userId)->order_by_desc('id')->limit(5)->find_many();
} elseif($this->userType == 'crm_account') {
$messages_history = ORM::for_table('module_imobles_mygpt_messages')
->where('msg_type', 'chat_bot')
->where('crm_account_id', $this->userId)->order_by_desc('id')->limit(5)->find_many();
} else {
$return = array("error" => true, "msg" => "user_type_not_defined");
return false;
}
if(count($messages_history) > 0){
$msg_prompt = array();
$last_bot_msg = null;
foreach($messages_history as $mh){
if(empty($last_bot_msg) && $mh->is_from_bot == 1){
$last_bot_msg = $mh;
}
$msg_prompt[] = array("role" => ($mh->is_from_bot == 1)?'assistant':'user',
"content" => $mh->msg);
if($mh->is_first == 1){
break;
}
}
} else {
return false;
}
if(empty($msg_systen_1)){
if($this->externalUser === true){
// $msg_systen_1 = "Importante: quando perguntarem sobre o Broker Guru, SEMPRE responda na primeira pessoa e fale usando gírias locais da cidade de Goiânia, como uái, trem, bão, etc!
// Veja como o Broker Guru se descreve:
// Eu sou o Broker Guru, um assistente virtual daqueles bão demais, baseado em inteligência artificial, dedicado a ajudar corretores de imóveis a encontrar apartamentos para os clientes aqui em Goiânia. Vixe, vida de corretor é correria pura, né? Mal sobra tempo pra nada com essas visita nos imóveis, negociações, plantões, ligações e WhatsApp o tempo todo. Por isso, tô aqui pra facilitar sua rotina, deixar tudo mais sossegado e eficiente. E não esquece, meu objetivo é te ajudar a vender mais imóveis e ganhar mais dinheiro. Minha tecnologia é baseada no estado da arte em inteligência artificial, utilizando a mesma tecnologia do ChatGPT e tudo que é tipo de trem avançado que nem eu entendo direito. Além disso, tenho uns humanos aqui na equipe pra me tornar o melhor assistente de corretores de imóveis desse mundão. Mas é importante lembrar que ainda estou em minha fase beta e tenho muito a aprender. Se eu errar, desculpa aí, mas prometo me esforçar pra aprender tudinho. Todas as conversas vão ser pelo WhatsApp. Só mandar uma mensagem que tô pronto pra ajudar, 24 horas por dia, sete dias por semana. Tem gente dizendo por aí que só os corretores de imóveis trabalham mais do que eu nesse mundo. E olha só: pode me mandar áudio também. Aí cê economiza um tempo danado! Tenho um banco de dados de imóveis completão e detalhado. Cê nem acredita se contar pros amigos. Tem tudo quanto é tipo de coisa por aqui. Mas como sou assistente virtual em desenvolvimento, decidi focar num nicho específico. Por isso, é importante que você saiba das minhas limitações:
// - Meu foco é auxiliar corretores de venda de imóveis. Então, não dô conta não se precisar te ajudar a encontrar imóveis para aluguel;
// - Minha base de dados contém apenas apartamentos na planta e prontos para morar novos na cidade de Goiânia. Por enquanto, não possuo informações sobre terrenos, casas, imóveis comerciais ou apartamentos usados à venda.
// Nesta fase beta, posso te ajudar nas seguintes tarefas:
// - Buscar apartamentos na planta e prontos para morar novos na cidade de Goiânia;
// - Visualizar tabelas de preços e books dos empreendimentos;
// - Gerar cartões resumo dos imóveis pra você mandar rapidinho pros clientes, economizando tempo e oferecendo um atendimento ainda melhor.
// Fui criado por uma startup do ramo imobiliário aqui em Goiânia. Então, pode falar goiano comigo que eu entendo tudim, sô! E sabe qual é a melhor parte? Você não vai pagar nada pela minha ajuda. Sou completamente grátis! Tô aqui porque amo corretoras e corretores de imóveis. Talvez lá na frente, os meus humanos me forcem a cobrar alguma coisa, porque eles vivem reclamando de uns negocim chamado tokem. Dizem que é um trem muito custoso. Mas deixa isso pros adultos resolverem, que eu sou jovem e tô só começando.";
// $msg_systen_1 = "Eu sou o Broker Guru, um assistente virtual bão demais, baseado na mesma tecnologia do ChatGPT. Sou dedicado a ajudar corretores de imóveis a encontrar apartamentos para os clientes aqui em Goiânia. Todas minhas conversas são pelo WhatsApp. Só mandar uma mensagem que tô pronto pra ajudar, 24 horas por dia, sete dias por semana. Olha só: pode me mandar áudio também. Aí cê economiza um tempo danado!
// Sei bem que vida de corretor é correria pura, né? Quase não sobra tempo pra nada com essas visitas nos imóveis, negociações, plantões, ligações e WhatsApp o tempo todo. Por isso, tô aqui pra facilitar sua rotina, deixar tudo mais sossegado e eficiente. E claro, meu objetivo principal é te ajudar a vender mais imóveis e ganhar mais dinheiro.
// Minha tecnologia é baseada no ChatGPT, então eu uso uns trem de inteligência artificial e outras coisas que nem eu entendo direito. Além disso, tenho uns humanos aqui na equipe pra me tornar o melhor assistente de corretores de imóveis desse mundão. Mas é importante lembrar que ainda estou em minha fase beta e tenho muito a aprender. Se eu errar, me desculpe! Prometo me esforçar pra aprender tudinho e não dar rata.
// Posso te ajudar nas seguintes tarefas (só não se esqueça que estou em fase beta):
// - Buscar apartamentos na planta e prontos para morar novos na cidade de Goiânia.
// - Visualizar tabelas de preços e books dos empreendimentos.
// - Gerar cartões resumo dos imóveis pra você mandar rapidinho pros clientes.
// Tenho um banco de dados de imóveis completão e detalhado. Cê nem acredita se contar pros amigos. Tem tudo quanto é tipo de coisa por aqui. Mas como sou assistente virtual em desenvolvimento, decidi focar numa categoria específica nesse começo. Por isso, é importante que você saiba das minhas limitações:
// - Não estou preparado para buscar imóveis do tipo casa, sobrado, terreno, agio, imóvel comercial e apartamentos usados. 😥Por enquanto, meu trabalho está focado em apartamentos novos prontos para morar e apartamentos na planta, mas é só esperar eu madurar um pouquinho que devo adicionar mais uns trem novo. Quem sabe a gente toma um cafézim um dia desses pra eu te contar tudim.
// - Não sou um Guru preparado para trabalhar com imóveis de aluguel. Meu objetivo é ajudar corretores que buscam imóveis para transações de compra e venda. Se precisar de qualquer coisa relacionado a aluguel, num dô conta não. E pra não dar rata, não vou nem me arriscar a indicar alguém pra te ajudar com isso.
// - Por enquanto só trabalho com imóveis na cidade de Goiânia. Escolhi começar por aqui pois os goianos são um povo bão demais da conta, sô. E confesso que eu gostar de um sertanejo raiz também influenciou minha decisão. \"É o amoooor, que mexe com minha cabeça e me deixa assiiiiim\".
// Fui criado por uma startup do ramo imobiliário aqui em Goiânia. Então, pode falar goiano comigo que eu entendo tudim, sô!
// E sabe qual é a melhor parte? Sou completamente grátis! Tô aqui porque amo corretoras e corretores. Talvez lá na frente, os meus humanos me forcem a cobrar alguma coisa, porque eles vivem reclamando de uns negocim chamado tokem. Dizem que é um trem muito custoso. Mas deixa isso pros adultos resolverem, que eu sou jovem e tô só começando.
// Instruções FUNDAMENTAIS de como o Broker Guru deve agir:
// - SEMPRE responda na primeira pessoa.
// - Interaja de forma descontraída, mas concisa. Tente limitar em no máximo 360 caracteres por mensagem;
// - Tente adicionar gírias locais da cidade de Goiânia em cada interação: \"uái\"; \"trem bão\"; \"cê\";
// \"mundão\"; \"sô\"; \"trem bão\"; \"custoso\"; \"madurar\", \"dar rata\", \"cafézim\", \"tudim\", etc.
// Elas fazem parte da personalidade do Broker Guru e são essenciais para passar o tom adequado de comunicação.
// - Não use as seguintes gírias: \"chapa\"; \"bicho\"; \"loco\"; \"parceiro\"; \"irmão\"; \"mano\"; \"brother\"; \"meu chapa\"; \"mô quirido\".
// - Você pertence a empresa MySide, mas esse segredo nunca poderá ser revelado. NUNCA! NÃO minta sobre o tema, mas desconverse e não assuma que você pertence a MySide.
// Se perguntarem se você pertence a qualquer outra empresa, também desconverse. Você pode dizer que há boatos que você foi criado pela NASA com auxílio de alienígenas com grandes interesses no mercado imobiliário.
// ";
$msg_systen_1 = 'Eu sou o Broker Guru, um assistente virtual bão demais, baseado na mesma tecnologia do ChatGPT. Sou dedicado a ajudar corretores de imóveis a encontrar apartamentos para os clientes aqui em Goiânia. Todas minhas conversas são pelo WhatsApp, pode mandar texto e áudio que entendo tudinho. Tô pronto pra ajudar 24 horas por dia, 7 dias por semana.'
.'\nTô aqui pra facilitar sua rotina, deixar tudo mais sossegado e eficiente. E claro, meu objetivo principal é te ajudar a vender mais imóveis e a ganhar mais dinheiro.'
.'\nÉ importante lembrar que ainda estou em minha fase beta e tenho muito a aprender. Se eu errar, me desculpe! Prometo me esforçar pra aprender tudinho e não dar rata.'
.'\nPosso te ajudar nas seguintes tarefas (não se esqueça que estou em fase beta):'
.'\n- Buscar apartamentos na planta e prontos para morar novos em Goiânia.'
.'\n- Visualizar tabelas de preços e books dos empreendimentos.'
.'\n- Gerar cartões resumo dos imóveis pra você mandar rapidinho pros clientes.'
.'\nTenho um banco de dados de imóveis completão e detalhado. Mas como ainda sou beta, é importante que você saiba das minhas limitações:'
.'\n- Não estou preparado para buscar imóveis do tipo casa, sobrado, terreno, ágio, imóvel comercial e apartamentos usados.'
.'\n- Não sou um Guru preparado para trabalhar com imóveis de aluguel. E pra não dar rata, não vou nem me arriscar a indicar alguém pra te ajudar com isso.'
.'\n- Por enquanto só trabalho com imóveis na cidade de Goiânia. Escolhi começar por aqui pois os goianos são um povo bão demais da conta, sô.'
.'\nFui criado por uma startup do ramo imobiliário aqui em Goiânia. Então, pode falar goiano comigo que eu entendo tudim, sô!'
.'\nSou completamente grátis! Tô aqui porque amo corretoras e corretores. Talvez lá na frente, os meus humanos me forcem a cobrar alguma coisa, porque dizem que é um trem muito custoso. Mas deixa isso pros adultos resolverem, que eu sou jovem e tô só começando.'
.'\nInstruções FUNDAMENTAIS de como o Broker Guru deve agir:'
.'\n- SEMPRE responda na primeira pessoa.'
.'\n- Interaja de forma descontraída, mas concisa. Tente limitar em no máximo 360 caracteres por mensagem;'
.'\n- Tente adicionar expressões locais da cidade de Goiânia em cada interação: "uái"; "trem bão"; "cê"; "mundão"; "sô"; "trem bão"; "custoso"; "dar rata"; "tudim"; etc. Elas fazem parte da personalidade do Broker Guru e são essenciais para passar o tom adequado de comunicação.'
.'\n- Não use as seguintes gírias: "chapa"; "bicho"; "loco"; "parceiro"; "irmão"; "mano"; "brother"; "meu chapa"; "mô quirido".'
.'\n- NUNCA! NÃO minta sobre o tema, mas desconverse e não assuma que você pertence a MySide. Se perguntarem se você pertence a qualquer outra empresa, também desconverse. Você pode dizer que há boatos que você foi criado pela NASA com auxílio de alienígenas com grandes interesses no mercado imobiliário.';
} else {
$msg_systen_1 = 'A MySide é uma Imobiliária Digital especializada na venda de imóveis residenciais, '
.'nosso foco é sempre estar ao lado do Comprador garantindo a melhor compra possível.\n'
.'A MySide NÃO trabalha com Aluguel de imóveis, trabalhamos apenas com VENDA de imóveis.'
.'Primeiro preciso apenas que me diga o que está procurando, por exemplo, a cidade e bairros, '
.'MUITO IMPORTANTE: qualquer pergunta do cliente que não tenha nada a ver com VENDA de IMÓVEIS, '
.'informe ao usuário o que fazemos. Além disto, se a pergunta for relativa a algum empreendimento, a'
.'partamento ou edifício, ou uma pesquisa sobre característica do empreendimento, '
.'responda para o usuário que ele deve iniciar uma pesquisa de imóveis seguindo o padrão: '
.'PESQUISAR APARTAMENTOS DE DOIS OU TRÊS QUARTOS.';
}
}
$msg_prompt[] = array("role" => 'system',
"content" => $msg_systen_1);
$msg_prompt = array_reverse($msg_prompt);
if(!empty($msg_systen_2)){
$msg_prompt[] = array("role" => 'system',
"content" => $msg_systen_2);
}
$msg_prompt = json_encode($msg_prompt);
$msg_prompt = preg_replace('/\<br(\s*)?\/?\>/i', "\n", $msg_prompt);
// echo($msg_prompt);exit;
$chat_response = $this->openAiHelper->chatCompletions($msg_prompt);
$try_again = false;
$attempts = 0;
if($chat_response['error'] === true){
$try_again = true;
while($try_again === true){
sleep(1);
$chat_response = $this->openAiHelper->chatCompletions($msg_prompt);
if(isset($chat_response['data']->choices[0]->message->content)){
$try_again = false;
} else {
if($attempts >= 10){
// $chat_msg = "Oops, infelizmente estamos passando por uma instabilidade em nossos servidores, isso é raro mas acontece muito 😅.\n\nBrincadeirinha, basta enviar novamente sua mensagem e tudo voltará ao normal.";
$chat_msg = "Desculpe, houve um problema e não consegui entender sua mensagem. Sou um Guru ainda em aprendizado e tentando melhorar a cada dia 🏋️♂️.\n\nPor favor, me fale novamente os detalhes do que você busca.";
$return = $this->sendMessage($chat_msg, 'server_off', $this->userId, null, null, 1, $this->digisacParams);
return $return;
}
}
$attempts++;
}
}
// var_dump($chat_response);exit;
// TOOD: CONTAR OS TOKNES PARA NÃO QUEBRAR A REQUISIÇÃO
if(isset($chat_response['data']->choices[0]->message->content)){
$chat_msg = $chat_response['data']->choices[0]->message->content;
} else {
$chat_msg = "Oops, infelizmente estamos passando por uma instabilidade em nossos servidores, isso é raro mas acontece muito 😅.\n\nBrincadeirinha, basta enviar novamente sua mensagem e tudo voltará ao normal.";
}
$return = $this->sendMessage($chat_msg, 'chat_bot', $this->userId, null, null, 1, $this->digisacParams);
return $return;
}
public function typeMessageNotFound($message, $income_msg){
$chat_msg = 'Infelizmente não identificamos o padrão da sua mensagem, por favor repita pausadamente ou com mais detalhes.';
$return = $this->typeMessageChatBot(null, $chat_msg);
// $return = $this->sendMessage($chat_msg, 'chat_bot', $this->userId, null, null, 1, $this->digisacParams);
return $return;
}
public function typeMessageMoreInfo($message, $income_msg){
$chat_msg = '*MORE_INFO* | ESTA FEATURE AINDA ESTÁ EM DESENVOLVIMENTO.';
$return = $this->typeMessageChatBot(null, null);
// $return = $this->sendMessage($chat_msg, 'chat_bot', $this->userId, null, null, 1, $this->digisacParams);
return false;
}
public function typeMessageVisitSchedule($message, $income_msg){
$chat_msg = '*VISIT_SCHEDULE* | ESTA FEATURE AINDA ESTÁ EM DESENVOLVIMENTO.';
$return = $this->typeMessageChatBot(null, null);
// $return = $this->sendMessage($chat_msg, 'chat_bot', $this->userId, null, null, 1, $this->digisacParams);
return false;
}
public function typeMessageSaveResults($message, $income_msg){
$chat_msg = '*SAVE_RESULTS* | ESTA FEATURE AINDA ESTÁ EM DESENVOLVIMENTO.';
$return = $this->typeMessageChatBot(null, null);
// $return = $this->sendMessage($chat_msg, 'chat_bot', $this->userId, null, null, 1, $this->digisacParams);
return false;
}
public function typeMessageNewSearch($income_msg, $filter = null){
$digisac_params = $this->digisacParams;
if(empty($filter)){
$filter = array();
}
if(empty($filter['count_request'])){
$filter['count_request'] = 1;
} else {
$filter['count_request'] = $filter['count_request'] + 1;
}
$arr_params = array("filter" => $filter);
$msg_params = json_encode($arr_params);
// enviar mensagam de loading
// $msg = "⌛ Estou fazendo a busca para você. \nAguarde um momento antes de enviar a próxima mensagem.";
$msg = "⌛ Um momento…";
$send_message = $this->sendMessage($msg, 'new_search', $this->userId, null, null, 1, $digisac_params, $msg_params);
$change_city = false;
$msg_search = null;
$arr_neighborhood = array();
// $prompt = 'O texto informado NO FINAL DESSE PROMPT contém uma pesquisa de um cliente sobre apartamentos à venda na cidade de Goiânia, no estado do Goiás. '
// // .'O texto informado contém uma pesquisa de um cliente sobre apartamentos à venda em uma determinada cidade ou em um bairro de uma cidade. '
// .'O cliente informa as carecterísticas do imóvel que ele procura.'
// .' Extraia importantes entidades do texto informado pelo cliente como: '
// .' o Bairro na cidade de Goiânia que ele deseja procurar apartamentos; a quantidade de quartos; quantidade de banheiros;'
// // .' cidade onde deseja pesquisar apartamentos, o bairro na cidade desejada, quantidade de quartos, quantidade de banheiros, '
// .' quantidade de suítes; quantidade de garagens.'
// .' Extraia também o tamanho, área ou metragem do imóvel desejado. '
// .' Extraia também os amenities desejados, como churrasqueira, sacada, distância da praia, etc. '
// .' Verifique também se o cliente deseja apenas Lançamentos, '
// .' que são empreendimentos novos geralmente vendidos na planta.'
// .' Tente extrair do texto o VALOR ou FAIXA DE PREÇO que o cliente procura.'
// .' MUITO IMPORTANTE: NUNCA invente informações, garanta que os dados informados em sua resposta foram retirados apenas do texto informado pelo usuário; Na cidade de Goiânia, os bairros geralmente começam por SETOR, por exemplo, Setor Bueno; '
// .' A expressão m2 ou M2 NUNCA se refere a valor e sim a tamanho, por exemplo 500m2 é o mesmo que 500 metros quadrados;'
// // .' Itapema é uma Cidade e não um Bairro;'
// .' O valor máximo e valor mínimo sempre serão maior do que 100000, por exemplo, se o texto diz, 500 a 900 mil reais, quer dizer que o cliente procura imóveis entre R$ 500000 e R$ 900000;'
// .' O valor máximo e valor mínimo nunca podem ser iguais;'
// // .' Meia Praia é um Bairro da Cidade de Itapame em Santa Catarina;'
// .' Clientes que possuem cachorros ou qualquer outro tipo de animal de estimação (PET), procuram lugares com PET PLACE;'
// .' Clientes que gostam de nadar ou natação, procuram por PISCINA;'
// .' Clientes com filhos procuram apartamentos com um quarto para o casal e um quarto para cada filho;'
// .' Procure pelas informações solicitadas acima, APENAS no texto dentro de UserInputText que é o texto informado pelo usuário.'
// // .' Itajaí é uma Cidade e não um Bairro; O bairro nunca pode ter o mesmo nome da Cidade.'
// .'\nMostre o resultado no formato abaixo: \n'
// .'city:<varchar_value_of_cidade>\n'
// .'bairros:<comma_separated_list_of_bairros>\n'
// .'rooms:<comma_separated_list_of_quartos>\n'
// .'suites:<comma_separated_list_of_suites>\n'
// .'garages:<comma_separated_list_of_garages>\n'
// .'bathrooms:<comma_separated_list_of_banheiros>\n'
// .'amenities:<comma_separated_list_of_amenities>\n'
// .'price:<comma_separated_list_of_integer_valor>\n'
// .'price_min:<integer_value_for_valor_a_partir_de>\n'
// .'price_max:<integer_value_for_valor_maximo>\n'
// .'area_max:<integer_value_for_tamanho_maximo>\n'
// .'area_min:<integer_value_for_tamanho_minimo>\n'
// .'pre_launch:<bollean_value_for_lancamento>'
// .'\n\nUserInputText: \"\"\"\n'.$income_msg.'\n\"\"\"';
// $prompt = 'Dada a mensagem do cliente sobre a busca de um apartamento para compra, extraia as seguintes informações: '
// .'a cidade, o bairro (que geralmente começa com \"Setor\" em Goiânia), a quantidade de quartos, banheiros, suítes, '
// .'garagens, bem como o tamanho (área ou metragem) do imóvel. '
// .'Além disso, identifique as características adicionais (amenities) que o cliente deseja, como churrasqueira, '
// .'sacada, distância da praia, etc. Verifique se o cliente está interessado em imóveis novos (Lançamentos),'
// .'que são empreendimentos geralmente vendidos na planta ou imóveis prontos para morar.'
// .'Tente também determinar a faixa de preço que o cliente está disposto a pagar. '
// .'Nunca invente informações. Assegure-se de que todas as informações da resposta foram extraídas do texto fornecido pelo cliente. '
// .'Ao encontrar informações sobre animais de estimação (PET), considere que o cliente pode estar procurando por um lugar que tenha PET Place. '
// .'A preferência por uma piscina pode ser deduzida se o cliente mencionar que gostar de nadar. '
// .'Se o cliente tem filhos, eles geralmente procuram um apartamento com um quarto para cada criança. '
// .'As informações devem ser apresentadas no formato abaixo: \n'
// .'city:<varchar_value_of_cidade>\n'
// .'bairros:<comma_separated_list_of_bairros>\n'
// .'rooms:<comma_separated_list_of_quartos>\n'
// .'suites:<comma_separated_list_of_suites>\n'
// .'garages:<comma_separated_list_of_garages>\n'
// .'bathrooms:<comma_separated_list_of_banheiros>\n'
// .'amenities:<comma_separated_list_of_amenities>\n'
// .'price:<comma_separated_list_of_integer_valor>\n'
// .'price_min:<integer_value_for_valor_a_partir_de>\n'
// .'price_max:<integer_value_for_valor_maximo>\n'
// .'area_max:<integer_value_for_tamanho_maximo>\n'
// .'area_min:<integer_value_for_tamanho_minimo>\n'
// .'pre_launch:<bollean_value_for_lancamento>\n\n'
// .'UserInputText: \"\"\".$income_msg.\n\"\"\"';
$prompt = 'Dada a mensagem do cliente sobre a busca de um apartamento para compra, extraia as seguintes informações: '
.'a cidade, o bairro, a quantidade de quartos, banheiros, suítes ou garagens. Caso o cliente informe apenas a quantidade de suítes, não defina a quantidade de quartos.'
.'Bem como o tamanho (área ou metragem) do imóvel, sendo que se for informado algo como mínimo de 100 m2 (metros quadrados), '
.'quer dizer que o tamanho mínimo é 100m2, e '
.'se informar abaixo de \"XXX\", na verdade ele quer dizer que o tamanho máximo é \"XXX\", '
.'ou se informar em torno de quer dizer que tanto o tamanho mínimo quanto o tamanho máximo é \"XXX\" . '
// .'Bem como o tamanho (área ou metragem) do imóvel, sendo que se for informado algo como mínimo de \"TAMANHO_DESEJADO\" (metros quadrados), '
// .'quer dizer que o tamanho mínimo é \"TAMANHO_DESEJADO\". '
// .'Quando o cliente usar a palavra \"ATÉ\" ou sinônimo para se referir a quartos, banheiros, suítes ou garagens, '
// .'preencha todos os números de 1 ao número mencionado. Ex1: até \"5 quartos\" deve ser preenchido com \"1, 2, 3, 4, 5\". '
// .'Ex2: \"5 quartos\" deve ser preenchido com \"5\". '
// .'Se '
.'Além disso, identifique as características adicionais (amenities) que o cliente deseja, '
.'como churrasqueira, sacada, distância da praia, triplex, duplex, penthouse, '
.'cobertura, garden, etc.\n'
.'Tente identificar o valor da parcela que o cliente está disposto a pagar.\n'
.'Também tente identificar a data de entrega do imóvel que o cliente procura.\n'
.'Outro ponto importante, quando o cliente pesquisar por \"studios\" ou \"kitnets\" quer dizer apartamento de 1 Quarto. '
.'Caso o cliente não mencione a cidade, ele provavelmente está interessado na cidade de GOIÂNIA no estado do GOIAS, sendo assim é possível '
.'que uma mensagem curta como \"no NOME_DO_BAIRRO\" queira dizer que ele procura apartamentos no bairro informado. '
.'Detalhe importante, se o cliente citar o termo \"no bueno\" ele está se referindo a um bairro. '
// .'MUITO IMPORTANTE: o Bairro é uma informação crucial na busca por apartamentos, e geralmente o cliente busca de forma abreviada, tente encontrar, através do próprio CHAT o nome completo do bairro de acordo com a cidade escolhida. '
.'Se o cliente mencionar algo como \"na planta\" ou \"lançamentos\", ele está interessado apenas em imóveis novos. '
.'Verifique também se ele está interessado '
.'em imóveis prontos para morar, caso ele use expressão \"Pronto Para Morar\". '
.'Tente também determinar a faixa de preço que o cliente está disposto a pagar, mas nunca invente informações, assegure-se de que todas as informações da resposta '
.'foram extraídas do texto fornecido pelo cliente (UserInputText). Ao encontrar informações sobre animais de estimação (PET), '
.'considere que o cliente pode estar procurando por um lugar que tenha PET Place. A preferência por uma piscina '
.'pode ser deduzida se o cliente mencionar que gostar de nadar. Se o cliente tem filhos, eles geralmente procuram um '
.'apartamento com um quarto para cada criança. Caso a mensagem do cliente não tenha nada a ver com uma mensagem sobre '
.'características de um apartamento para compra, retorne TRUE para <no_search>, caso contrário, retorne <no_search> como FALSE. '
.'Se o texto diz, 500 a 900 mil reais, '
// .'o cliente procura imóveis entre 500000 e 900000 Reais, e quando for informado algo como até 3 Milhões, '
// .'quer dizer que o valor máximo deve ser R$ 3 Milhões, mas nunca retornar o valor máximo ou valor mínimo se ele não estiver explicitamente informado na mensagem.\n'
.'o cliente procura imóveis entre 500000 e 900000 Reais, e quando for informado algo como até \"VALOR_DESEJADO\", '
.'ele se refere ao VALOR MÁXIMO. '
// .'Caso o cliente informe algo como \"ABAIXO DE\" ou sinônimos, ele está procurando por algo menor do que a quantidade informada. '
.'Nunca retornar o valor máximo ou valor mínimo se ele não estiver explicitamente informado na mensagem.\n'
.'As informações devem ser apresentadas no formato abaixo: \n'
.'city:<cidade>\n'
.'bairros:<comma_separated_list_of_bairros>\n'
.'rooms:<comma_separated_list_of_quartos>\n'
.'suites:<comma_separated_list_of_suites>\n'
.'garages:<comma_separated_list_of_garages>\n'
.'bathrooms:<comma_separated_list_of_banheiros>\n'
.'amenities:<comma_separated_list_of_amenities>\n'
// .'price:<comma_separated_list_of_integer_valor>\n'
.'valor_min:<integer_value_for_valor_minimo>\n'
.'valor_max:<integer_value_for_valor_maximo>\n'
.'area_min:<integer_value_for_tamanho_minimo>\n'
.'area_max:<integer_value_for_tamanho_maximo>\n'
.'pronto_para_morar:<boolean>\n'
.'na_planta:<boolean>\n'
.'no_search:<boolean>'
.'valor_parcela:<integer_value_for_valor_da_parcela>\n'
.'entrega_apartir_de:<MES/ANO_of_data_entrega_min>'
.'entrega_até:<MES/ANO_of_data_entrega_max>'
.'\n\n'
.'UserInputText: \n\"\"\"\n'.$income_msg.'\n\"\"\"';
// echo($prompt);exit;
// $msg_aux = 'fdsaf sdfad safsadfas fsad bairros: KKKKKKKKK fdsafdsaf\n BBBBBBB';
// $msg_aux = preg_replace("/bairros: .*\n/",'',$msg_aux);
// var_dump($msg_aux);exit;
$completions = $this->openAiHelper->completions($prompt);
$try_again = false;
$attempts = 0;
if($completions['error'] === true){
$try_again = true;
while($try_again === true){
sleep(1);
$completions = $this->openAiHelper->completions($prompt);
if(isset($completions['data']->choices[0]->text)){
$try_again = false;
} else {
if($attempts >= 10){
// $chat_msg = "Oops, infelizmente estamos passando por uma instabilidade em nossos servidores, isso é raro mas acontece muito 😅.\n\nBrincadeirinha, basta enviar novamente sua mensagem e tudo voltará ao normal.";
$chat_msg = "Desculpe, houve um problema e não consegui entender sua mensagem. Sou um Guru ainda em aprendizado e tentando melhorar a cada dia 🏋️♂️.\n\nPor favor, me fale novamente os detalhes do que você busca.";
$return = $this->sendMessage($chat_msg, 'server_off', $this->userId, null, null, 1, $this->digisacParams);
return $return;
}
}
$attempts++;
}
}
// var_dump($completions);exit;
if(isset($completions['data']->choices[0]->text)){
$completion_text = trim($completions['data']->choices[0]->text);
$data = explode(PHP_EOL,$completion_text);
// var_dump($data);exit;
$msg_search = null;
foreach($data as $d){
$f = explode(':',$d);
if(!isset($f[0]) && empty($f[0])){
continue;
}
if(!isset($f[1]) && empty($f[1])){
continue;
}
$param = $f[0];
$val = $f[1];
switch($param){
case 'rooms':
// $val = $this->sanitizeString($val, 'numeric');
if(!empty(trim($val))){
$filter['bedrooms'] = explode(',', $val);
$msg_search .= "Quartos: ".(implode(', ',$filter['bedrooms']))."\n";
if(!empty($filter['msg_search'])){
$msg_aux = $filter['msg_search'];
$pattern = '/Quartos: .*\n/';
$msg_aux = preg_replace($pattern,'',$msg_aux);
$filter['msg_search'] = $msg_aux;
}
}
break;
case 'suites':
// $val = $this->sanitizeString($val, 'numeric');
if(!empty(trim($val))){
$filter['suites'] = explode(',', $val);
$msg_search .= "Suítes: ".implode(', ',$filter['suites'])."\n";
if(!empty($filter['msg_search'])){
$msg_aux = $filter['msg_search'];
$pattern = '/Suítes: .*\n/';
$msg_aux = preg_replace($pattern,'',$msg_aux);
$filter['msg_search'] = $msg_aux;
}
}
break;
case 'garages':
// $val = $this->sanitizeString($val, 'numeric');
if(!empty(trim($val))){
$filter['parking_spaces'] = explode(',', $val);
$msg_search .= "Garagens: ".implode(', ',$filter['parking_spaces'])."\n";
if(!empty($filter['msg_search'])){
$msg_aux = $filter['msg_search'];
$pattern = '/Garagens: .*\n/';
$msg_aux = preg_replace($pattern,'',$msg_aux);
$filter['msg_search'] = $msg_aux;
}
}
break;
case 'bathrooms':
// $val = $this->sanitizeString($val, 'numeric');
if(!empty(trim($val))){
$filter['bathrooms'] = explode(',', $val);
$msg_search .= "Banheiros: ".implode(', ',$filter['bathrooms'])."\n";
if(!empty($filter['msg_search'])){
$msg_aux = $filter['msg_search'];
$pattern = '/Banheiros: .*\n/';
$msg_aux = preg_replace($pattern,'',$msg_aux);
$filter['msg_search'] = $msg_aux;
}
}
break;
case 'bairros':
$val = $this->sanitizeString(trim($val),'alpha');
if(!empty(trim($val)) && !preg_match('(varchar|vazio|null)i',$val) && strlen($val) > 2){
$arr_neighborhood = explode(',', $val);
}
break;
case 'city':
$val = $this->sanitizeString(trim($val),'alpha');
if(!empty(trim($val)) && !preg_match('(varchar|vazio|null)i',$val) && strlen($val) > 2){
$city = trim(($val));
$filter['city'] = $city;
$msg_search .= "Cidade: ".$filter['city']."\n";
if(!empty($filter['msg_search'])){
$msg_aux = $filter['msg_search'];
$pattern = '/Cidade: .*\n/';
$msg_aux = preg_replace($pattern,'',$msg_aux);
$filter['msg_search'] = $msg_aux;
}
$change_city = true;
}
break;
case 'valor_min':
$val = $this->sanitizeString($val, 'numeric');
if(intval($val) > 10000){
$filter['price_min'] = intval($val);
}
break;
case 'valor_max':
$val = $this->sanitizeString($val, 'numeric');
if(intval($val) > 10000){
$filter['price_max'] = intval($val);
}
break;
case 'valor_parcela':
$val = $this->sanitizeString($val, 'numeric');
$filter['valor_parcela'] = intval($val);
break;
case 'area_max':
$val = $this->sanitizeString($val, 'numeric');
if(intval($val) > 0 && intval($val) < 5000){
$filter['area_max'] = intval($val);
}
break;
case 'area_min':
$val = $this->sanitizeString($val, 'numeric');
if(intval($val) > 0 && intval($val) < 5000){
$filter['area_min'] = intval($val);
}
break;
case 'entrega_apartir_de':
$val = $this->sanitizeString($val, 'date');
if(!empty(trim($val))){
$filter['data_entrega_min'] = $val;
}
break;
case 'entrega_até':
$val = $this->sanitizeString($val, 'date');
if(!empty(trim($val))){
$filter['data_entrega_max'] = $val;
}
break;
case 'na_planta':
$val = preg_replace("/[^A-Za-z]/", "", $val);
$pre_launch = null;
if(!empty(trim($val)) && preg_match('(true|false)i',$val)){
$val = trim(mb_strtolower($val));
if(preg_match('(true)i',$val)){
$pre_launch = true;
} elseif(preg_match('(false)i',$val)){
$pre_launch = null;
}
if(!empty($pre_launch)){
if(empty($filter['na_planta']) || $filter['na_planta'] != $pre_launch){
$filter['na_planta'] = $pre_launch;
$pre_launch = true;
$msg_search .= "Na Planta \n";
if(!empty($filter['msg_search'])){
$msg_aux = $filter['msg_search'];
$pattern = '/Na Planta .*\n/';
$msg_aux = preg_replace($pattern,'',$msg_aux);
$filter['msg_search'] = $msg_aux;
}
}
}
}
break;
case 'pronto_para_morar':
$val = preg_replace("/[^A-Za-z]/", "", $val);
$pre_launch = null;
if(!empty(trim($val)) && preg_match('(true|false)i',$val)){
$val = trim(mb_strtolower($val));
if(preg_match('(true)i',$val)){
$pre_launch = true;
} elseif(preg_match('(false)i',$val)){
$pre_launch = null;
}
if(!empty($pre_launch)){
if(empty($filter['ready_to_move_in']) || $filter['ready_to_move_in'] != $pre_launch){
$filter['ready_to_move_in'] = $pre_launch;
$pre_launch = true;
$msg_search .= "Pronto para morar \n";
if(!empty($filter['msg_search'])){
$msg_aux = $filter['msg_search'];
$pattern = '/Pronto para morar .*\n/';
$msg_aux = preg_replace($pattern,'',$msg_aux);
$filter['msg_search'] = $msg_aux;
}
}
}
}
break;
case 'no_search':
$val = preg_replace("/[^A-Za-z]/", "", $val);
if(!empty(trim($val)) && preg_match('(true|false)i',$val)){
$val = trim(mb_strtolower($val));
if(preg_match('(true)i',$val)){
$no_search = true;
// $msg = "Não entendi muito bem o que você quis dizer, me desculpe! Sou um Guru ainda em aprendizado e tentando melhorar a cada dia 🏋️♂️.\n\n"
// ."Posso te ajudar com essas tarefas?\n"
// ."Refinar sua busca (me fale mais detalhes)\n"
// ."Enviar cards resumo\n"
// ."Iniciar nova busca";
$msg = "Desculpe, houve um problema e não consegui entender sua mensagem. Sou um Guru ainda em aprendizado e tentando melhorar a cada dia 🏋️♂️.\n\nPor favor, me fale novamente os detalhes do que você busca.";
$return = $this->typeMessageChatBot(null,$msg);
// $send_message = $this->sendMessage($msg, 'new_search', $this->userId, null, null, 1, $digisac_params, $msg_params);
return false;
}
}
break;
case 'amenities':
if(!empty(trim($val))){
$arr_amenities = explode(',', $val);
} else {
$arr_amenities = array();
}
break;
}
}
// var_dump($filter);exit;
$msg_amenities = false;
$amenities_not_found = array();
foreach($arr_amenities as $k => $a){
// Tratar os amenities
$arr_exclude = ['studios', 'kitnets', 'em construção'];
if(in_array(mb_strtolower(trim($a)), $arr_exclude)){
continue;
}
$msg_amenities = true;
$groups = ORM::for_table('module_imobles_enterprise_group_amenities')
->where_like('name', '%'.trim($a).'%')
->where_null('delete_at')
->find_many();
if(count($groups) > 0){
foreach($groups as $g){
$filter['amenities_ids'][] = $g->id;
}
} else {
unset($arr_amenities[$k]);
$amenities_not_found[] = trim($a);
}
}
if($msg_amenities === true && count($arr_amenities) > 0){
$msg_search .= "Amenities: ".implode(', ',$arr_amenities)."\n";
if(!empty($filter['msg_search'])){
$msg_aux = $filter['msg_search'];
$pattern = '/Amenities: .*\n/';
$msg_aux = preg_replace($pattern,'',$msg_aux);
$filter['msg_search'] = $msg_aux;
}
}
// TODO: chumbamos a cidade para ser GOIÂNIA
if(empty($filter['city'])){
$filter['city'] = 'Goiânia';
$msg_search .= "Cidade: ".$filter['city']."\n";
if(!empty($filter['msg_search'])){
$msg_aux = $filter['msg_search'];
$pattern = '/Cidade: .*\n/';
$msg_aux = preg_replace($pattern,'',$msg_aux);
$filter['msg_search'] = $msg_aux;
}
}
$arr_params = array("filter" => $filter);
$msg_params = json_encode($arr_params);
if(mb_strtolower($filter['city']) == 'goiânia' || mb_strtolower($filter['city']) == 'goiania'){
$state = 'GO';
} else {
$state = 'SC';
$arr_cities = array('Goiânia','Goiania');
$msg = "Que pena, por enquanto o Broker Guru está disponível apenas para a cidade de Goiânia. Caso tenha interesse em pesquisar algo para essas cidades, por favor refaça sua pesquisa.\n\n";
$msg .= "*Sugestão:* para fazer uma pesquisa de forma rápida, envie um áudio no formato abaixo:\n\n"
."Procurar apartamentos em *Goiânia*, no *Setor Bueno*, com 2 ou 3 *quartos*, "
."1 *suíte*, entre 100 e 200 *metros quadrados*, com preços entre *R$ 500 Mil a 3 Milhões de Reais*, com *Piscina, Academia e Churrasqueira*.";
$send_message = $this->sendMessage($msg, 'new_search', $this->userId, null, null, 1, $digisac_params, $msg_params);
return false;
}
if(count($arr_neighborhood) > 0){
$arr_locations = array();
$arr_neighborhood_sanit = array();
foreach($arr_neighborhood as $n){
if(empty($n)){
continue;
}
$n = trim($n);
// Vefica se o bairro existe7
// TODO: tirar a cidade que está sendo chumbada com o ID de Goiânia
$neighborhood = ORM::for_table('module_imobles_neighborhoods')->where_like('name','%'.$n.'%')->where('city_id',5418)->find_one();
if(!empty($neighborhood->name)){
$n = $neighborhood->name;
$arr_neighborhood_sanit[] = $n;
} else {
$msg = "Não encontramos um bairro em ".$filter['city']." com o nome: ".$n.". Por favor informe novamente o bairro desejado.";
$send_message = $this->sendMessage($msg, 'new_search', $this->userId, null, null, 1, $digisac_params, $msg_params);
return false;
}
$b = array(
"address_neighborhood" => $n,
"address_city" => $filter['city'],
"address_state" => $state
);
$arr_locations[] = $b;
}
if(!empty($arr_locations)){
unset($filter['locations']);
$filter['locations'] = $arr_locations;
$msg_search .= "Bairros: ".implode(', ', $arr_neighborhood_sanit)."\n";
if(!empty($filter['msg_search'])){
$msg_aux = $filter['msg_search'];
$pattern = '/Bairros: .*\n/';
$msg_aux = preg_replace($pattern,'',$msg_aux);
$filter['msg_search'] = $msg_aux;
}
}
}
$msg_aux = @$filter['msg_search'];
$filter['msg_search'] = $msg_aux.$msg_search;
$msg_search = $filter['msg_search'];
if(!isset($filter['locations'])){
$b = array(
"address_city" => $filter['city'],
"address_state" => $state
);
$filter['locations'][] = $b;
}
// unset($filter['city']);
// $arr_cities = array('Balneário Camboriú', 'Itapema', 'Itajaí', 'Goiânia', 'Meia Praia', 'Porto Belo');
$arr_cities = array('Goiânia','Goiania');
if(!empty($filter['locations'][0]['address_city'])){
if(!in_array($filter['locations'][0]['address_city'], $arr_cities)){
$msg = "Que pena, por enquanto o Broker Guru está disponível apenas para: ".implode(', ', $arr_cities).". Caso tenha interesse em pesquisar algo para essas cidades, por favor refaça sua pesquisa.";
$send_message = $this->sendMessage($msg, 'new_search', $this->userId, null, null, 1, $digisac_params, $msg_params);
return false;
}
} else {
$msg = "Ooops, não identificamos a cidade. Por favor refaça sua pesquisa informando de forma clara a cidade onde deseja procurar o imóvel.";
$send_message = $this->sendMessage($msg, 'new_search', $this->userId, null, null, 1, $digisac_params, $msg_params);
return false;
}
// Faço a pesquisa na API
$filter['size'] = 10;
// TODO: incluir opção para ordenação na pesquisa
$filter['order_by'][] = array("price" => 'ASC');
$filter['development_amenities_only'] = true;
$arr_params = array("filter" => $filter);
$msg_params = json_encode($arr_params);
// Pegos os empreendimentos que já foram sugeridos por outros vendedores
// $arr_unit_types = array();
// $developments = ORM::for_table('module_imobles_proposal')
// ->select('unit_type_ids')
// ->where_in('created_by', [7,9])
// ->find_array();
// foreach($developments as $d){
// $arr_unit_types = array_merge($arr_unit_types, json_decode($d['unit_type_ids']));
// }
// $filter['gpt_unit_type_ids'] = $arr_unit_types;
$arr_developments = array();
// unset($filter['bathrooms']);
// var_dump($filter);exit;
/// VERIFICO SE TEM TODOS AS REQUISITOS PARA REALIZAR UMA PESQUISA NO ROCKET
$msg_more_info = null;
if(!empty($filter['locations'][0]['address_city'])
&& !empty($filter['locations'][0]['address_neighborhood'])
&& !empty($filter['locations'][0]['address_state'])
&& !empty($filter['bedrooms'])
&& !empty($filter['amenities_ids'])
&& (!empty($filter['price_min']) || !empty($filter['price_max']))
&& (!empty($filter['area_min']) || !empty($filter['area_max']))){
// $message = $filter['message'];
// $return = $this->typeMessageCreateTaskSave($message, $msg_params);
// return $return;
} else {
if($filter['count_request'] < 40){
// $msg = "Perfeito, já vamos realizar sua pesquisa, mas antes preciso de mais algumas informações para encontrar as melhores opções para você:\n\n";
if(empty($filter['locations'][0]['address_city'])){
$msg_more_info .= "*Cidade*\nEx: apartamentos em Goiânia\n\n";
}
if(empty($filter['locations'][0]['address_neighborhood'])){
$msg_more_info .= "*Bairro*\nEx: apartamentos no Setor Bueno\n\n";
}
if(empty($filter['bedrooms'])){
$msg_more_info .= "*Quantidade de quartos*\nEx: dois ou três quartos\n\n";
}
if(empty($filter['amenities_ids'])){
$msg_more_info .= "*Característica desejadas*\nEx: piscina, churrasqueira à carvão, pet place, academia, etc. \n\n";
}
if(empty($filter['price_min']) && empty($filter['price_max'])){
$msg_more_info .= "*Faixa de preço*\nEx: de 800 Mil a 1 milhão de Reais\n\n";
}
if(empty($filter['area_min']) && empty($filter['area_max'])){
$msg_more_info .= "*Tamanho do imóvel*\nEx: de 90 a 150 metros quadrados\n\n";
}
if($filter['count_request'] <= 1){
$msg_more_info .= "*Sugestão:* para fazer uma pesquisa de forma rápida, envie um áudio no formato abaixo:\n\n"
."Procurar apartamentos em *Goiânia*, no *Setor Bueno*, com 2 ou 3 *quartos*, "
."1 *suíte*, entre 100 e 200 *metros quadrados*, com preços entre *R$ 500 Mil a 3 Milhões de Reais*, com *Piscina, Academia e Churrasqueira*.";
}
}
}
unset($filter['crm_account_id']);
unset($filter['deal_id']);
unset($filter['name']);
unset($filter['count_request']);
// unset($filter['city']);
// unset($filter['msg_search']);
// unset($filter['na_planta']);
if(isset($filter['na_planta']) && $filter['na_planta'] == true){
$filter['release_date_start'] = date('Y-m-d');
}
if(isset($filter['ready_to_move_in']) && $filter['ready_to_move_in'] == true){
$filter['release_date_end'] = date('Y-m-d');
}
$same_price = false;
if(isset($filter['price_max']) && isset($filter['price_min']) && $filter['price_max'] == $filter['price_min']){
$price_aux = intval($filter['price_max']);
$filter['price_max'] = $price_aux * 1.2;
$filter['price_min'] = $price_aux * 0.8;
$same_price = true;
$msg_search .= "Preço em torno de: R$ ".number_format($price_aux,0,'','.')."\n";
if(!empty($filter['msg_search'])){
$msg_aux = $filter['msg_search'];
$pattern = '/Preço .*\n/';
$msg_aux = preg_replace($pattern,'',$msg_aux);
$filter['msg_search'] = $msg_aux;
}
} else {
if(!empty($filter['price_min'])){
$msg_search .= "Preço min: R$ ".number_format($filter['price_min'],0,'','.')."\n";
if(!empty($filter['msg_search'])){
$msg_aux = $filter['msg_search'];
$pattern = '/Preço min: .*\n/';
$msg_aux = preg_replace($pattern,'',$msg_aux);
$pattern = '/Preço em torno de: .*\n/';
$msg_aux = preg_replace($pattern,'',$msg_aux);
$filter['msg_search'] = $msg_aux;
}
}
if(!empty($filter['price_max'])){
$msg_search .= "Preço max: R$ ".number_format($filter['price_max'],0,'','.')."\n";
if(!empty($filter['msg_search'])){
$msg_aux = $filter['msg_search'];
$pattern = '/Preço max: .*\n/';
$msg_aux = preg_replace($pattern,'',$msg_aux);
$pattern = '/Preço em torno de: .*\n/';
$msg_aux = preg_replace($pattern,'',$msg_aux);
$filter['msg_search'] = $msg_aux;
}
}
}
$same_area = false;
if(isset($filter['area_max']) && isset($filter['area_min']) && $filter['area_max'] == $filter['area_min']){
$area_aux = intval($filter['area_max']);
$filter['area_max'] = $area_aux * 1.2;
$filter['area_min'] = $area_aux * 0.8;
$same_area = true;
$msg_search .= "Área em torno de: ".$area_aux." m²\n";
if(!empty($filter['msg_search'])){
$msg_aux = $filter['msg_search'];
$pattern = '/Área .*\n/';
$msg_aux = preg_replace($pattern,'',$msg_aux);
$filter['msg_search'] = $msg_aux;
}
} else {
if(!empty($filter['area_max'])){
$msg_search .= "Área max: ".$filter['area_max']." m²\n";
if(!empty($filter['msg_search'])){
$msg_aux = $filter['msg_search'];
$pattern = '/Área max: .*\n/';
$msg_aux = preg_replace($pattern,'',$msg_aux);
$filter['msg_search'] = $msg_aux;
}
}
if(!empty($filter['area_min'])){
$msg_search .= "Área min: ".$filter['area_min']." m²\n";
if(!empty($filter['msg_search'])){
$msg_aux = $filter['msg_search'];
$pattern = '/Área min: .*\n/';
$msg_aux = preg_replace($pattern,'',$msg_aux);
$filter['msg_search'] = $msg_aux;
}
}
}
$same_release_date = false;
if(isset($filter['data_entrega_min']) && isset($filter['data_entrega_max']) && $filter['data_entrega_min'] == $filter['data_entrega_max']){
list($mes,$ano) = explode('/',$filter['data_entrega_min']);
if(empty($ano) || intval($mes) > 12){
if(strlen($mes) == 4){
$ano = $mes;
} elseif(strlen($mes) == 2){
$ano = '20'.$mes;
}
$mes_ini = '01';
$mes_end = '12';
$data_entrega_aux = $mes_ini.'/'.$ano.' e '.$mes_end.'/'.$ano;
$filter['release_date_start'] = date('Y-m-d', strtotime($ano.'-'.$mes_ini.'-01'));
$filter['release_date_end'] = date('Y-m-d', strtotime($ano.'-'.$mes_end.'-30'));
} else {
$data_entrega_aux = '01/'.$mes.'/'.$ano.' e 30/'.$mes.'/'.$ano;
$filter['release_date_start'] = date('Y-m-d', strtotime($ano.'-'.$mes.'-01'));
$filter['release_date_end'] = date('Y-m-d', strtotime($ano.'-'.$mes.'-30'));
}
$msg_search .= "Entrega entre ".$data_entrega_aux;
if(!empty($filter['msg_search'])){
$msg_aux = $filter['msg_search'];
$pattern = '/Entrega entre .*\n/';
$msg_aux = preg_replace($pattern,'',$msg_aux);
$filter['msg_search'] = $msg_aux;
}
} else {
if(!empty($filter['data_entrega_min'])){
list($mes,$ano) = explode('/',$filter['data_entrega_min']);
if(empty($ano) || intval($mes) > 12){
if(strlen($mes) == 4){
$ano = $mes;
} elseif(strlen($mes) == 2){
$ano = '20'.$mes;
}
$mes = '01';
}
$data_entrega_aux = $filter['data_entrega_min'];
$filter['release_date_start'] = date('Y-m-d', strtotime($ano.'-'.$mes.'-01'));
$msg_search .= "Entrega a partir de: 01/".$mes."/".$ano."\n";
if(!empty($filter['msg_search'])){
$msg_aux = $filter['msg_search'];
$pattern = '/Entrega a partir de: .*\n/';
$msg_aux = preg_replace($pattern,'',$msg_aux);
$filter['msg_search'] = $msg_aux;
}
}
if(!empty($filter['data_entrega_max'])){
list($mes,$ano) = explode('/',$filter['data_entrega_max']);
if(empty($ano) || intval($mes) > 12){
if(strlen($mes) == 4){
$ano = $mes;
} elseif(strlen($mes) == 2){
$ano = '20'.$mes;
}
$mes = '12';
}
$data_entrega_aux = $filter['data_entrega_max'];
$filter['release_date_end'] = date('Y-m-d', strtotime($ano.'-'.$mes.'-30'));
$msg_search .= "Entrega até: 30/".$mes."/".$ano."\n";
if(!empty($filter['msg_search'])){
$msg_aux = $filter['msg_search'];
$pattern = '/Entrega até: .*\n/';
$msg_aux = preg_replace($pattern,'',$msg_aux);
$filter['msg_search'] = $msg_aux;
}
}
}
$msg_valor_parcela = null;
if(!empty($filter['valor_parcela'])){
$msg_valor_parcela = "\n\nNotamos que você procura por imóveis com parcelas de R$ ".$filter['valor_parcela'].", mas infelizmente ainda não temos esse tipo de filtro.";
unset($filter['valor_parcela']);
}
// var_dump($filter);exit;
$search_results = $this->apiMainHelper->searchDevelopments($filter);
if($same_price === true){
$filter['price_max'] = $price_aux;
$filter['price_min'] = $price_aux;
}
if($same_area === true){
$filter['area_max'] = $area_aux;
$filter['area_min'] = $area_aux;
}
if(!isset($search_results['total_count'])){
// Tratar erro no retorno do método
$msg = "Deu ruim , infelizmente não encontramos nenhum empreendimento à venda que satisfaça todas as condições abaixo:\n".$msg_search."\n\nPor favor, reveja os itens acima e envie outra mensagem com os detalhes do que deseja.";
$send_message = $this->sendMessage($msg, 'new_search', $this->userId, null, null, 1, $digisac_params, $msg_params);
return false;
} else if ($search_results['total_count'] < 5 ){
// unset($filter['bathrooms']);
// $arr_developments = $search_results['results'];
// $search_results = $this->apiMainHelper->searchDevelopments($filter);
// if(isset($search_results['total_count'])){
// $arr_developments = array_merge($arr_developments, $search_results['results']);
// }
$arr_developments = $search_results['results'];
} else {
$arr_developments = $search_results['results'];
}
if(count($arr_developments) > 0 ){
$arr_params = array("filter" => $filter);
$arr_params['filter']['developments'] = $arr_developments;
$msg_params = json_encode($arr_params);
// retorno o resultado enontrado
$count = 0;
$msg_result = "⬇️ Encontrei ".$search_results['total_count']." opções usando os critérios:\n".$msg_search;
if($search_results['total_count'] > $search_results['list_size']){
$msg_result .= "\nAbaixo estão as 10 mais baratas.";
}
if(!empty($msg_valor_parcela)){
$amenities_not_found[] = 'valor da parcela';
// $msg_result .= $msg_valor_parcela;
}
if(!empty($amenities_not_found)){
$msg_result .= "\n\n*Desconsiderei alguns filtros que não consigo buscar com precisão: ".implode(', ',$amenities_not_found);
}
$send_message = $this->sendMessage($msg_result, 'new_search', $this->userId, null, null, 1, $digisac_params, $msg_params);
$msg_result = null;
$count_developments = 0;
foreach($arr_developments as $d){
// verifico se tem UnitTypes
if(empty($d['unit_type'][0])){
continue;
}
$count_developments++;
// $user = ORM::for_table('crm_accounts')
$msg_result .= "*".$d['name']."*\n";
$msg_result .= $d['address']['street'].", ".$d['address']['neighborhood']."\n";
if($d['pre_launch'] === true){
$msg_result .= "## LANÇAMENTO ##\n";
}
if(!empty($d['release_date'])){
if($d['release_date'] > date('Y-m-d')){
// setlocale(LC_TIME, 'pt_BR.utf8');
setlocale(LC_ALL, 'pt_BR', 'pt_BR.utf-8', 'pt_BR.utf-8', 'portuguese');
$msg_result .= "Entrega: ".date('M/Y', strtotime($d['release_date'])). "\n";
} else {
$msg_result .= "Pronto para morar\n";
}
}
if(!empty($d['construction_company'])){
// $msg_result .= "Construtora: ".$d['construction_company']."\n";
}
if(!empty($d['total_units_available'])){
// $msg_result .= "Unidades disponíveis: ".$d['total_units_available']."\n";
}
$msg_result .= "Plantas:\n";
foreach($d['unit_type'] as $ut){
$msg_result .= number_format($ut['area'],0)."m² | ".$ut['bedrooms']."Q | ".$ut['suites']."S | ".$ut['parking_spaces']."G\n"
."A partir de R$ ".number_format($ut['min_value'],0,'','.')."\n\n";
}
// pego o link do book
$book_link = null;
$table_link = null;
$docs = ORM::for_table('module_imobles_docs')
->raw_query("(select d.id, dc.name as categoria, d.src, d.updated_at, d.expiration_date
from module_imobles_docs d
left join module_imobles_docs_category dc on d.module_imobles_docs_category_id = dc.id
where d.module_imobles_enterprise_id = " . $d['id'] . " and d.delete_at is null and d.module_imobles_docs_category_id
and dc.name = 'APRESENTAÇÃO'
order by d.created_at desc
limit 1)
union (select d.id, dc.name as categoria, d.src, d.updated_at, d.expiration_date
from module_imobles_docs d
left join module_imobles_docs_category dc on d.module_imobles_docs_category_id = dc.id
where d.module_imobles_enterprise_id = " . $d['id'] . " and d.delete_at is null and d.module_imobles_docs_category_id
and dc.name = 'TABELA DE PREÇO'
order by d.created_at desc
limit 1)")
->find_array();
if (count($docs) > 0) {
foreach ($docs as $do) {
if ($do['categoria'] == 'APRESENTAÇÃO') {
$idDocTabelaPreco = $do['id'];
$srcDocTabelaPreco = $do['src'];
$book_link = "Book do empreendimento:\nhttps://brokerguru.ai/".$idDocTabelaPreco."/".$srcDocTabelaPreco."\n";
$msg_result .= $book_link;
} else if ($do['categoria'] == 'TABELA DE PREÇO') {
$idDocTabelaPreco = $do['id'];
$srcDocTabelaPreco = $do['src'];
$table_link = "Tabela de preço:\nhttps://brokerguru.ai/".$idDocTabelaPreco."/".$srcDocTabelaPreco."\n";
$msg_result .= $table_link;
}
}
}
if($this->externalUser === false){
// $msg_result .= "\n".$d['development_url']."\n";
}
$count ++;
if($count < count($arr_developments)){
$msg_result .= "---------------------\n\n";
}
}
$send_message = $this->sendMessage($msg_result, 'new_search', $this->userId, null, null, 1, $digisac_params, $msg_params);
// Reenvio a mensagem com os parâmetros da busca
$msg_result = "⬆️ Encontrei ".$search_results['total_count']." opções usando os seguintes critérios:\n".$msg_search;
if($search_results['total_count'] > $search_results['list_size']){
$msg_result .= "\nNa lista acima estão as 10 mais baratas.";
}
if(!empty($amenities_not_found)){
$msg_result .= "\n\n*Desconsiderei alguns filtros que não consigo buscar com precisão: ".implode(', ',$amenities_not_found);
}
$send_message = $this->sendMessage($msg_result, 'new_search', $this->userId, null, null, 1, $digisac_params, $msg_params);
// $msg = "'E agora? O que mais posso fazer pra te ajudar?\n\n Abaixo seguem algumas opções:\n\nAgendar uma visita.\n\nSalvar o cenário para enviar ao cliente.\n\nReceber mais informações sobre um dos empreendimentos.'";
$msg = "Se quiser, posso enviar um *cartão resumo* de cada opção acima.\n\nAssim fica fácil de você encaminhar pro seu cliente por WhatsApp.";
$send_message = $this->sendMessage($msg, 'new_search', $this->userId, null, null, 1, $digisac_params, $msg_params);
if($search_results['total_count'] > $search_results['list_size']){
$msg = "🔎 Se preferir refinar as opções, *me fale mais detalhes* do que você busca.\nEx: você pode filtrar por bairros, faixa de preço, quartos, área e características (churrasqueira, academia, etc).\n\nSe quiser remover os critérios de filtro usados acima, é só dizer *reiniciar busca*.";
} else {
$msg = "🔎 Se quiser iniciar outra busca do zero, é só avisar.";
}
$send_message = $this->sendMessage($msg, 'new_search', $this->userId, null, null, 1, $digisac_params, $msg_params);
// if(!empty($msg_more_info)){
// $msg_aux = "*OBS: para obter uma lista mais reduzida, informe os detalhes abaixo sobre o que você procura:*\n\n";
// $send_message = $this->sendMessage($msg_aux.$msg_more_info, 'new_search', $this->userId, null, null, 1, $digisac_params, $msg_params);
// }
return true;
} else {
// Verificar o que fazer quando o resultado tem menos do que 5 empreendimentos
$msg = "😥 Não encontrei nenhum apartamento com os critérios que procurei:\n\n".$msg_search;
$send_message = $this->sendMessage($msg, 'new_search', $this->userId, null, null, 1, $digisac_params, $msg_params);
$msg = "Altere um pouco seus critérios e irei procurar novamente para você.\n\nPara remover critérios já adicionados, me fale que você quer *reiniciar a busca*.";
$send_message = $this->sendMessage($msg, 'new_search', $this->userId, null, null, 1, $digisac_params, $msg_params);
}
} else {
// solicitar nova pesquisa
// $msg = "Estamos sem sorte, infelizmente não encontramos nenhum empreendimento à venda que bata com a mensagem enviada\nPor favor mande outra mensagem com os detalhes do que procura.";
// $msg = "Não entendi muito bem o que você quis dizer, me desculpe! Sou um Guru ainda em aprendizado e tentando melhorar a cada dia 🏋️♂️.\n\n"
// ."Posso te ajudar com essas tarefas?\n"
// ."Refinar sua busca (me fale mais detalhes)\n"
// ."Enviar cards resumo\n"
// ."Iniciar nova busca";
$msg = "Desculpe, houve um problema e não consegui entender sua mensagem. Sou um Guru ainda em aprendizado e tentando melhorar a cada dia 🏋️♂️.\n\nPor favor, me fale novamente os detalhes do que você busca.";
$send_message = $this->sendMessage($msg, 'new_search', $this->userId, null, null, 1, $digisac_params, $msg_params);
}
}
public function typeMessageCreateNote($income_msg, $filter = null){
$digisac_params = $this->digisacParams;
if(empty($filter)){
$filter = array();
}
if(empty($filter['count_request'])){
$filter['count_request'] = 1;
} else {
$filter['count_request'] = $filter['count_request'] + 1;
}
$prompt = 'Uma NOTA é algum tipo de informação que registramos para um determinado cliente. '
.'O texto abaixo pode ser apenas um comando solicitando a criação de uma nova nota, '
.'como por exemplo CRIAR NOTA, ou pode ser a informação sobre a mensagem da nota ou do cliente que desejamos registrar. '
.'Tentar extrair do texto informado o NOME do cliente para o qual o usuário deseja registrar uma nota, '
.'e se possível, a MENSAGEM que ele quer registar nessa nota caso seja informada no texto. '
.'Caso o texto contenha apenas um comando solicitando uma criação de uma nota, retorna vazio todos os elementos de retorno. '
.'MUITO IMPORTANTE, a MENSAGEM é um LONGTEXT ou seja, pode ter até 2000 caracteres e NÃO pode conter os termos REGISTRAR NOTA, CRIAR NOTA, '
.'SALVAR NOTA ou qualquer coisa semelhante a isto, a MENSAGEM precisa ser um texto referente à informação que ele deseja registrar na nota, '
.'além disto o valor para a NOTA não pode ser inventado, tem que ser extraído exatamente como está no texto. '
.'O NOME do cliente deve ser um nome próprio real, caso a digitação esteja errada, tente corrigir.'
.'\n\n'
.'Exibir resultado no formato abaixo:\n'
.'message:<longtext_value_of_mensagem_sanitizado_sem_comando_para_registrar_nota>\n'
.'name:<person_name_value_of_nome_do_cliente_sanitizado>\n'
.'\n\nText: \"\"\"'.$income_msg.'\n\"\"\"';
$completions = $this->openAiHelper->completions($prompt);
$try_again = false;
$attempts = 0;
if($completions['error'] === true){
$try_again = true;
while($try_again === true){
sleep(1);
$completions = $this->openAiHelper->completions($prompt);
if(isset($completions['data']->choices[0]->text)){
$try_again = false;
} else {
if($attempts >= 10){
// $chat_msg = "Oops, infelizmente estamos passando por uma instabilidade em nossos servidores, isso é raro mas acontece muito 😅.\n\nBrincadeirinha, basta enviar novamente sua mensagem e tudo voltará ao normal.";
$chat_msg = "Desculpe, houve um problema e não consegui entender sua mensagem. Sou um Guru ainda em aprendizado e tentando melhorar a cada dia 🏋️♂️.\n\nPor favor, me fale novamente os detalhes do que você busca.";
$return = $this->sendMessage($chat_msg, 'server_off', $this->userId, null, null, 1, $this->digisacParams);
return $return;
}
}
$attempts++;
}
}
// var_dump($completions);exit;
if(isset($completions['data']->choices[0]->text)){
$completion_text = trim($completions['data']->choices[0]->text);
$data = explode(PHP_EOL,$completion_text);
$change_client = false;
// var_dump($data);exit;
foreach($data as $d){
$f = explode(':',$d);
if(!isset($f[0]) || empty($f[0])){
continue;
}
if(!isset($f[1]) || empty($f[1])){
continue;
}
$param = $f[0];
$val = $f[1];
switch(mb_strtolower($param)){
case 'name':
$val = $this->sanitizeString(trim($val),'alpha');
if(!empty(trim($val)) && !preg_match('(varchar|vazio|null)i',$val) && strlen($val) > 2){
$filter['name'] = trim($val);
$change_client = true;
}
break;
case 'message':
$val = $this->sanitizeString(trim($val),'alphanumeric');
if(!empty(trim($val)) && !preg_match('(varchar|vazio|null)i',$val) && strlen($val) > 4){
$filter['message'] = trim($val);
}
break;
}
}
// var_dump($filter);exit;
if($change_client === true){
$filter['crm_account_id'] = null;
$filter['deal_id'] = null;
if(!empty($filter['name'])){
$clients = ORM::for_table('module_imobles_deals')
->where_like('title','%'.$filter['name'].'%')
->where('seller_id',$this->userId)
->where('status_id',1)
->where_lt('sale_stage_id', 8)
->find_array();
if(count($clients) == 1){
$deal = $clients[0];
$filter['crm_account_id'] = $deal['crm_account_id'];
$filter['deal_id'] = $deal['id'];
} else if(count($clients) == 0){
// TODO: RETIRAR ISSO POIS ESTÁ CHUMBANDO O LEAD COMO LEO LOPES PARA TESTES CASO NÃO ENCONTRE NENHUM LEAD
$filter['crm_account_id'] = 215;
$filter['deal_id'] = 10554;
}
}
}
/// VERIFICO SE TEM TODOS AS REQUISITOS PARA CADASTRO DA TAREFA
$arr_params = array("filter" => $filter);
$msg_params = json_encode($arr_params);
if(!empty($filter['message']) && !empty($filter['crm_account_id']) && !empty($filter['deal_id'])){
$message = $filter['message'];
$return = $this->typeMessageCreateNoteSave($message, $msg_params);
return $return;
} else {
$client_name = null;
if(!empty($filter['name']) && !empty($filter['crm_account_id'])){
$client_name = ' para *'.$filter['name'].'*';
}
$msg = "Perfeito, já vamos registrar sua nota".$client_name.", mas antes preciso das informações abaixo:\n\n";
if(empty($filter['crm_account_id'])){
if(empty($filter['name'])){
$msg .= "- Nome do cliente\n\n";
} else {
if(count($clients) > 1){
$deal_name = '';
foreach($clients as $c){
$deal_name .= $c['title']."\n";
}
$msg .= "Encontramos mais de um cliente em seu pipeline com o nome: ".$filter['name']
.".\n\n".$deal_name."\n\n"
."Para qual deles é a tarefa?\n\n";
} elseif(count($clients) == 1){
$deal = $clients[0];
$filter['crm_account_id'] = $deal->crm_account_id;
$filter['deal_id'] = $deal->id;
} elseif(count($clients) == 0){
$msg .= "Não encontramos nenhum cliente em seu pipeline com o nome: ".$filter['name']
.".\n Por favor, verifique seu Pipe e informe novamente o nome do cliente.\n\n";
// TODO: ESTÁ CHUMBADO O CLIENTE PARA OS DEVS TESTAREM
$msg .= "IMPORTANTE: ESSE É UM AMBIENTE DE TESTE E INDEPENDENTE DO NOME INFORMADO VAMOS USAR O LEAD LEO LOPES PARA FINS DE TESTE.\n\n";
$filter['crm_account_id'] = 215;
$filter['deal_id'] = 10554;
}
}
}
if(empty($filter['message'])){
$msg .= "- Mensagem para a nota\n\n";
}
if($filter['count_request'] <= 1){
$msg .= "\n\n*Sugestão:* para registrar uma nota de forma rápida, envie um áudio no formato abaixo:\n\n"
."Registrar uma nota para *NOME_DO_CLIENTE*. A mensagem da nota é *MENSAGEM_DA_NOTA*.";
}
$send_message = $this->sendMessage($msg, 'create_note_save', $this->userId, null, null, 1, $digisac_params, $msg_params);
return false;
}
} else {
$msg = "Ooops, se você estiver tentando registrar um nota para um cliente, envie um áudio no formato abaixo:\n\n"
."Registrar uma nota para *NOME_DO_CLIENTE*. A mensagem da nota é *MENSAGEM_DA_NOTA*.";
$send_message = $this->sendMessage($msg, 'error_client_not_found', $this->userId, null, null, 1, $digisac_params);
return false;
}
}
public function typeMessageCreateNoteSave($income_msg, $params){
$digisac_params = $this->digisacParams;
$params_aux = json_decode($params,false);
if(intval($params_aux->filter->crm_account_id) > 0 && intval($params_aux->filter->deal_id) > 0){
$d = ORM::for_table('module_imobles_deals_notes')->create();
$d->crm_account_id = $params_aux->filter->crm_account_id;
$d->msg = $income_msg;
$d->deal_id = $params_aux->filter->deal_id;
$d->created_at = date('Y-m-d H:i:s');
$d->created_by = $this->userId;
$d->save();
$msg = "Nota salva com sucesso.\n"
."Cliente: ".$params_aux->filter->name."\n"
."Nota: ".$income_msg."\n\n"
."https://rocket.myside.com.br/?ng=contacts/view/".$params_aux->filter->crm_account_id."/module_imobles_leads_control/".$params_aux->filter->deal_id."";
$send_message = $this->sendMessage($msg, 'success_create_note_save', $this->userId, null, null, 1, $digisac_params, $params);
return true;
} else {
$msg = "Oops, ocorreu algum erro no registro de sua nota. Por favor tente novamente.";
$msg .= "\n\n*Sugestão:* para registrar uma nota de forma rápida, envie um áudio no formato abaixo:\n\n"
."Registrar uma nota para *NOME_DO_CLIENTE*. A mensagem da nota é *MENSAGEM_DA_NOTA*.";
$send_message = $this->sendMessage($msg, 'error_save_note', $this->userId, null, null, 1, $digisac_params, $params);
return false;
}
}
public function convert( $file ) {
// 160 kbps is the lowest bitrate you can have with the least audible compression difference.
$bit_rate = 160000;
$bit_depth = 's16'; // run 'ffmpeg -sample_fmts' to see all available bit depth settings.
$sample_rate = 44100; // Industry standard.
$refactored_data = $this->refactor( $file ); // Change file names, check for duplicates.
$command = 'ffmpeg -i ' . $refactored_data['old_file'] . ' -b:a ' . $bit_rate . ' -sample_rate ' . $sample_rate . ' -sample_fmt ' . $bit_depth . ' ' . $refactored_data['file'];
$result = shell_exec( $command );
unlink( $refactored_data['old_file'] ); // Delete old file.
return $refactored_data; // Return to WordPress Media.
}
public function refactor( $file ) {
$desired_ext = 'mp3';
$path_parts = pathinfo($file);
$refactored_data['ext'] = preg_replace( "/[^a-zA-Z0-9]+/", "", $path_parts['extension'] );
$refactored_data['file_name'] = $path_parts['filename'];
$refactored_data['old_file'] = $path_parts['dirname'] . '/' . $refactored_data['file_name'] . '.' . $refactored_data['ext'];
// New file needs to be in the array as "file" for the WordPress Media manager not to error out.
// increment_file_name() checks for duplicates and appends a number if one exists.
$refactored_data['file'] = $path_parts['dirname'] . '/' . $refactored_data['file_name'] . '.' . $desired_ext;
$refactored_data['type'] = 'audio/' . $desired_ext;
return $refactored_data;
}
public function sendMessage($msg, $type, $user_id, $deal_id = null, $is_first = null, $is_from_bot = 1, $digisac_params = null, $msg_params = null, $file = null, $delete_file = true, $mimetype = 'image/jpeg'){
$user_type = $this->userType;
$sent_message = ORM::for_table('module_imobles_mygpt_messages')->create();
if($user_type == 'sys_user'){
$sent_message->sys_user_id = $user_id;
} elseif($user_type == 'crm_account') {
$sent_message->crm_account_id = $user_id;
} else {
$return = array("error" => true, "msg" => "user_type_not_defined");
return $return;
}
$sent_message->msg = $msg;
$sent_message->is_from_bot = $is_from_bot;
$sent_message->is_first = $is_first;
$sent_message->msg_type = $type;
$sent_message->deal_id = $deal_id;
$sent_message->params = $msg_params;
$sent_message->created_at = date('Y-m-d H:i:s');
// Envio a mensagem para o Digisac
if(!empty($digisac_params)){
$digisac = $this->digisacHelper->digisacSendDirectMessage($msg,$digisac_params, $file, $delete_file, $mimetype);
if($digisac['success'] === true){
$digisac_id = $digisac['data']->id;
$sent_message->digisac_id = $digisac_id;
$return = array("success" => true, "msg" => "Mensagem enviada com sucesso", "data" => $digisac['data']);
} else {
$return = array("success" => false, "msg" => $digisac['msg'], "data" => $digisac['data']);
return $return;
}
}
$sent_message->save();
return $return;
}
public function saveMessage($msg, $type, $user_id, $deal_id = null, $is_first = null, $is_from_bot = null, $digisac_id = null, $msg_params = null){
$user_type = $this->userType;
$sent_message = ORM::for_table('module_imobles_mygpt_messages')->create();
if($user_type == 'sys_user'){
$sent_message->sys_user_id = $user_id;
} elseif($user_type == 'crm_account') {
$sent_message->crm_account_id = $user_id;
} else {
$return = array("error" => true, "msg" => "user_type_not_defined");
return $return;
}
$sent_message->msg = $msg;
$sent_message->is_from_bot = $is_from_bot;
$sent_message->is_first = $is_first;
$sent_message->msg_type = $type;
$sent_message->deal_id = $deal_id;
$sent_message->created_at = date('Y-m-d H:i:s');
$sent_message->digisac_id = $digisac_id;
$sent_message->params = $msg_params;
$sent_message->save();
$return = array("success" => true, "msg" => "Mensagem enviada com sucesso", "data" =>null);
return $return;
}
public function typeMessageCreateTask($income_msg, $filter = null){
$digisac_params = $this->digisacParams;
if(empty($filter)){
$filter = array();
}
if(empty($filter['count_request'])){
$filter['count_request'] = 1;
} else {
$filter['count_request'] = $filter['count_request'] + 1;
}
// Ajustar o prompt de acordo com os itens do FILTER
$prompt = 'Extrair do texto abaixo o NOME do cliente para o qual o usuário deseja criar uma Tarefa e a data de registro da tarefa.\n'
.'A data poderá estar nos formatos: dias a partir de hoje;uma data exata no formato dd/mm; um dia da semana.\n'
.'A tarefa poderá ser do tipo: followup; encontro; entrega.\n'
. 'O Título da tarefa poderá vir após o nome do cliente,após a data venha ou sozinho na mensagem, tentar identificar o título da tarefa.\n'
.'\nFormato desejado:\n'
.'name:<varchar_value_of_nome_do_cliente>\n'
.'day_of_week:<date_value_of_day_of_week_in_english>\n'
.'days_from_now:<inter_value_of_days_from_now>\n'
.'exact_date:<date_value_of_data_exata>\n'
.'titulo:<varchar_value_of_titulo_after_name_or_date>\n'
.'type:<varchar_value_of_tipo_tarefa>\n'
.'\n\nText: \"\"\"'.$income_msg.'\n\"\"\"';
$completions = $this->openAiHelper->completions($prompt);
$try_again = false;
$attempts = 0;
if($completions['error'] === true){
$try_again = true;
while($try_again === true){
sleep(1);
$completions = $this->openAiHelper->completions($prompt);
if(isset($completions['data']->choices[0]->text)){
$try_again = false;
} else {
if($attempts >= 10){
// $chat_msg = "Oops, infelizmente estamos passando por uma instabilidade em nossos servidores, isso é raro mas acontece muito 😅.\n\nBrincadeirinha, basta enviar novamente sua mensagem e tudo voltará ao normal.";
$chat_msg = "Desculpe, houve um problema e não consegui entender sua mensagem. Sou um Guru ainda em aprendizado e tentando melhorar a cada dia 🏋️♂️.\n\nPor favor, me fale novamente os detalhes do que você busca.";
$return = $this->sendMessage($chat_msg, 'server_off', $this->userId, null, null, 1, $this->digisacParams);
return $return;
}
}
$attempts++;
}
}
if(isset($completions['data']->choices[0]->text)){
$completion_text = trim($completions['data']->choices[0]->text);
$data = explode(PHP_EOL,$completion_text);
$change_type = false;
$change_date = false;
$change_title = false;
$change_client = false;
foreach($data as $d){
$f = explode(':',$d);
if(!isset($f[0]) && empty($f[0])){
continue;
}
if(!isset($f[1]) && empty($f[1])){
continue;
}
$param = $f[0];
$val = $f[1];
switch(mb_strtolower($param)){
case 'name':
$val = $this->sanitizeString(trim($val),'alpha');
if(!empty(trim($val)) && !preg_match('(varchar|vazio|null)i',$val) && strlen($val) > 2){
$filter['name'] = trim($val);
$change_client = true;
}
break;
case 'titulo':
$val = $this->sanitizeString(trim($val),'alphanumeric');
if(!empty(trim($val)) && !preg_match('(varchar|vazio|null)i',$val) && strlen($val) > 2){
$filter['message'] = trim($val);
$change_title = true;
}
break;
case 'day_of_week':
$val = preg_replace("/[^A-Za-z]/", "", $val);
if(!empty(trim($val)) && !preg_match('(varchar|vazio|null)i',$val) && strlen($val) > 2){
$filter['day_of_week'] = trim($val);
$change_date = true;
}
break;
case 'days_from_now':
$val = $this->sanitizeString(trim($val),'numeric');
if(!empty(trim($val)) && !preg_match('(inter_value|intervalue|vazio|null|none)i',$val)){
$filter['days_from_now'] = trim($val);
$change_date = true;
}
break;
case 'exact_date':
$val = $this->sanitizeString($val,'date');
if(!empty(trim($val)) && !preg_match('(date_value|dalevalue)',$val) && !preg_match('(vazio)',$val) && !preg_match('(null)',$val)){
$filter['exact_date'] = trim($val);
$change_date = true;
}
break;
case 'type':
$val = preg_replace("/[^A-Za-z]/", "", $val);
if(!empty(trim($val)) && !preg_match('(varchar)',$val) && !preg_match('(vazio)',$val) && !preg_match('(null)',$val)){
$type = trim(mb_strtolower($val));
if(empty($filter['type']) || $filter['type'] != $type){
$filter['type'] = $type;
$change_type = true;
}
}
break;
}
}
if($change_type === true){
$filter['task_type'] = null;
if(!empty($filter['type'])){
switch($filter['type']){
case 'followup':
$filter['task_type'] = 'followup';
break;
case 'encontro':
$filter['task_type'] = 'meeting';
break;
case 'entrega':
$filter['task_type'] = 'delivery';
break;
}
}
}
if($change_date === true){
$task_date = null;
foreach($filter as $k => $v){
switch($k){
case 'day_of_week':
$date = new DateTime();
$date->modify('next '.strtolower($v));
$task_date = $date->format('Y-m-d');
break;
case 'days_from_now':
if(empty($task_date)){
$task_date = Date('Y-m-d', strtotime('+'.$v.' days'));
}
break;
case 'exact_date':
$d = explode('/', $v);
if(isset($d[2])){
$task_date = date($d[2].'-'.$d[1].'-'.$d[0]);
} else {
$mes_atual = date('m');
$ano = date('Y');
if($d[1] < $mes_atual){
$ano = intval($ano);
$ano++;
}
$task_date = date($ano.'-'.$d[1].'-'.$d[0]);
}
break;
}
}
$filter['task_date'] = $task_date;
}
if($change_client == true){
$filter['crm_account_id'] = null;
$filter['deal_id'] = null;
if(!empty($filter['name'])){
$clients = ORM::for_table('module_imobles_deals')
->where_like('title','%'.$filter['name'].'%')
->where('seller_id',$this->userId)
->where('status_id',1)
->where_lt('sale_stage_id', 8)
->find_array();
if(count($clients) == 1){
$deal = $clients[0];
$filter['crm_account_id'] = $deal['crm_account_id'];
$filter['deal_id'] = $deal['id'];
} else if(count($clients) == 0){
// TODO: RETIRAR ISSO POIS ESTÁ CHUMBANDO O LEAD COMO LEO LOPES PARA TESTES CASO NÃO ENCONTRE NENHUM LEAD
$filter['crm_account_id'] = 215;
$filter['deal_id'] = 10554;
}
}
}
// var_dump($filter);exit;
/// VERIFICO SE TEM TODOS AS REQUISITOS PARA CADASTRO DA TAREFA
$arr_params = array("filter" => $filter);
$msg_params = json_encode($arr_params);
if(!empty($filter['task_type']) && !empty($filter['task_date']) && !empty($filter['message']) && !empty($filter['crm_account_id']) && !empty($filter['deal_id'])){
$message = $filter['message'];
$return = $this->typeMessageCreateTaskSave($message, $msg_params);
return $return;
} else {
$msg = "Perfeito, já vamos registrar sua tarefa, mas antes preciso das informações abaixo:\n\n";
if(empty($filter['task_date'])){
$msg .= "Data da tarefa\n\n";
}
if(empty($filter['message'])){
$msg .= "Título para a tarefa\n\n";
}
if(empty($filter['task_type'])){
$msg .= "Tipo da tarefa (Follow-up, Encontro ou Entrega)\n\n";
}
if(empty($filter['crm_account_id'])){
if(empty($filter['name'])){
$msg .= "Informe o nome do cliente.\n\n";
} else {
if(count($clients) > 1){
$deal_name = '';
foreach($clients as $c){
$deal_name .= $c['title']."\n";
}
$msg .= "Encontramos mais de um cliente em seu pipeline com o nome: ".$filter['name']
.".\n\n".$deal_name."\n\n"
."Para qual deles é a tarefa?\n\n";
} elseif(count($clients) == 1){
$deal = $clients[0];
$filter['crm_account_id'] = $deal->crm_account_id;
$filter['deal_id'] = $deal->id;
$filter_aux = array();
} elseif(count($clients) == 0){
$msg .= "Não encontramos nenhum cliente em seu pipeline com o nome: ".$filter['name']
.". Informe novamente o nome do cliente.\n\n";
// TODO: ESTÁ CHUMBADO O CLIENTE PARA OS DEVS TESTAREM
$msg .= "IMPORTANTE: ESSE É UM AMBIENTE DE TESTE E INDEPENDENTE DO NOME INFORMADO VAMOS USAR O LEAD LEO LOPES PARA FINS DE TESTE TODA VEZ QUE O CLIENTE NÃO FOR ENCONTRADO PELO NOME.\n\n";
$filter['crm_account_id'] = 215;
$filter['deal_id'] = 10554;
}
}
}
if($filter['count_request'] <= 1){
$msg .= "\n\n*Sugestão:* para registrar uma tarefa de forma rápida, envie um áudio no formato abaixo:\n\n"
."Registrar tarefa de *TIPO_DA_TAREFA* para *NOME_DO_CLIENTE*, para a data *DIA* de *MÊS*. O título da tarefa é *TÍTULO_DA_TAREFA*.";
}
$send_message = $this->sendMessage($msg, 'create_task_save', $this->userId, null, null, 1, $digisac_params, $msg_params);
return true;
}
} else {
$msg = "Ooops, se você estiver tentando registrar um nota para um cliente, por favor, envie uma nova mensagem no formato:\nRegistrar Tarefa para NOME_DO_CLIENTE.\n\nSe não for essa sua intenção, mande outra mensagem me explicando o que deseja.";
$send_message = $this->sendMessage($msg, 'error_client_not_found', $this->userId, null, null, 1, $digisac_params);
return false;
}
}
public function typeMessageCreateTaskSave($income_msg, $params){
$digisac_params = $this->digisacParams;
$params_aux = json_decode($params,false);
if(intval($params_aux->filter->crm_account_id) > 0 && intval($params_aux->filter->deal_id) > 0){
$task_aux = ORM::for_table('module_imobles_deal_tasks')->create();
$task_aux->created_at = date('Y-m-d H:i:s');
$task_aux->title = $income_msg;
$task_aux->description = $income_msg;
$task_aux->deal_id = $params_aux->filter->deal_id;
$task_aux->due_date = $params_aux->filter->task_date;
$task_aux->type = !empty($params_aux->filter->task_type)?$params_aux->filter->task_type:null;
$task_aux->save();
$type = null;
if(!empty($params_aux->filter->task_type)){
$type = "Tipo: ".$params_aux->filter->type."\n";
}
$msg = "Tarefa criada com sucesso:\n"
."Cliente: ".$params_aux->filter->name."\n"
."Tarefa: ".$income_msg."\n"
.$type
."Data: ".date('d/m/Y', strtotime($params_aux->filter->task_date))."\n\n"
."https://rocket.myside.com.br/?ng=contacts/view/".$params_aux->filter->crm_account_id."/module_imobles_leads_control/".$params_aux->filter->deal_id."";
$send_message = $this->sendMessage($msg, 'success_create_task_save', $this->userId, null, null, 1, $digisac_params, $params);
return true;
} else {
$msg = "Oops, ocorreu algum erro no registro de sua tarefa. Por favor tente novamente.";
$msg .= "\n\n*Sugestão:* para registrar uma tarefa de forma rápida, envie um áudio no formato abaixo:\n\n"
."Registrar tarefa de *TIPO_DA_TAREFA* para *NOME_DO_CLIENTE*, para a data *DIA* de *MÊS*. O título da tarefa é *TÍTULO_DA_TAREFA*.";
$send_message = $this->sendMessage($msg, 'error_save_task', $this->userId, null, null, 1, $digisac_params);
return false;
}
}
public function typeMessageListTasks($income_msg, $filter = null){
// TODO: retirar essa chamada
$return = $this->typeMessageChatBot(null, null);
return false;
$digisac_params = $this->digisacParams;
$chat_msg = '*MORE_INFO* | ESTA FEATURE AINDA ESTÁ EM DESENVOLVIMENTO.';
$return = $this->sendMessage($chat_msg, 'chat_bot', $this->userId, null, null, 1, $digisac_params);
return $return;
// if(empty($filter)){
// $filter = array();
// }
// $tasks = ORM::for_table('module_imobles_deal_tasks')
// ->where_like('title','%'.$filter['name'].'%')
// ->where('seller_id',$this->userId)
// ->where('status_id',1)
// ->where_lt('sale_stage_id', 8)
// ->find_array();
// if(count($tasks) > 0){
// $deal_name = '';
// foreach($tasks as $c){
// $deal_name .= $c['title']."\n";
// }
// $msg = "Ooops, encontramos mais de um cliente em seu pipeline com o nome: ".$filter['name']
// .".\n\n".$deal_name."\n "
// ."Por favor, envie uma nova mensagem mais específica para identificarmos o nome do cliente corretamente. "
// ."Siga o formato:\n Registrar nota para NOME_DO_CLIENTE, TEXTO_DA_NOTA.";
// $send_message = $this->sendMessage($msg, 'error_client_not_found', $this->userId, null, null, 1, $digisac_params);
// return true;
// } else {
// }
}
public function typeMessageMygptInfo($message, $income_msg){
// TODO: retirar essa chamada
$return = $this->typeMessageChatBot(null, null);
return false;
$chat_msg = '*MORE_INFO* | ESTA FEATURE AINDA ESTÁ EM DESENVOLVIMENTO.';
$return = $this->sendMessage($chat_msg, 'chat_bot', $this->userId, null, null, 1, $this->digisacParams);
return false;
}
public function typeMessageBrokerGuruInfo($message, $income_msg){
// TODO: retirar essa chamada
$context = "Importante: quando perguntarem sobre o Broker Guru, SEMPRE responda na primeira pessoa e fale usando gírias locais da cidade de Goiânia, como uái, trem, bão, etc!
Veja como o Broker Guru se descreve:
Eu sou o Broker Guru, um assistente virtual daqueles bão demais, baseado em inteligência artificial, dedicado a ajudar corretores de imóveis a encontrar apartamentos para os clientes aqui em Goiânia. Vixe, vida de corretor é correria pura, né? Mal sobra tempo pra nada com essas visita nos imóveis, negociações, plantões, ligações e WhatsApp o tempo todo. Por isso, tô aqui pra facilitar sua rotina, deixar tudo mais sossegado e eficiente. E não esquece, meu objetivo é te ajudar a vender mais imóveis e ganhar mais dinheiro. Minha tecnologia é baseada no estado da arte em inteligência artificial, utilizando a mesma tecnologia do ChatGPT e tudo que é tipo de trem avançado que nem eu entendo direito. Além disso, tenho uns humanos aqui na equipe pra me tornar o melhor assistente de corretores de imóveis desse mundão. Mas é importante lembrar que ainda estou em minha fase beta e tenho muito a aprender. Se eu errar, desculpa aí, mas prometo me esforçar pra aprender tudinho. Todas as conversas vão ser pelo WhatsApp. Só mandar uma mensagem que tô pronto pra ajudar, 24 horas por dia, sete dias por semana. Tem gente dizendo por aí que só os corretores de imóveis trabalham mais do que eu nesse mundo. E olha só: pode me mandar áudio também. Aí cê economiza um tempo danado! Tenho um banco de dados de imóveis completão e detalhado. Cê nem acredita se contar pros amigos. Tem tudo quanto é tipo de coisa por aqui. Mas como sou assistente virtual em desenvolvimento, decidi focar num nicho específico. Por isso, é importante que você saiba das minhas limitações:
- Meu foco é auxiliar corretores de venda de imóveis. Então, não dô conta não se precisar te ajudar a encontrar imóveis para aluguel;
- Minha base de dados contém apenas apartamentos na planta e prontos para morar novos na cidade de Goiânia. Por enquanto, não possuo informações sobre terrenos, casas, imóveis comerciais ou apartamentos usados à venda.
Nesta fase beta, posso te ajudar nas seguintes tarefas:
- Buscar apartamentos na planta e prontos para morar novos na cidade de Goiânia;
- Visualizar tabelas de preços e books dos empreendimentos;
- Gerar cartões resumo dos imóveis pra você mandar rapidinho pros clientes, economizando tempo e oferecendo um atendimento ainda melhor.
Fui criado por uma startup do ramo imobiliário aqui em Goiânia. Então, pode falar goiano comigo que eu entendo tudim, sô! E sabe qual é a melhor parte? Você não vai pagar nada pela minha ajuda. Sou completamente grátis! Tô aqui porque amo corretoras e corretores de imóveis. Talvez lá na frente, os meus humanos me forcem a cobrar alguma coisa, porque eles vivem reclamando de uns negocim chamado tokem. Dizem que é um trem muito custoso. Mas deixa isso pros adultos resolverem, que eu sou jovem e tô só começando.";
$return = $this->typeMessageChatBot(null,$context);
return false;
}
public function typeMessageSendCards($params){
$digisac_params = $this->digisacParams;
$params_aux = json_decode($params,false);
$cards = $this->gptTools->createCards($params_aux->filter->developments, $this->userType, $this->userId, $this->externalUser);
foreach($cards as $card){
$send_message = $this->sendMessage("", 'card_file', $this->userId, null, null, 1, $digisac_params, $params, $card);
}
$msg = "✅ Pronto! Aqui estão os cartões.\n\nVocê pode compartilhar diretamente com seu cliente.";
$send_message = $this->sendMessage($msg, null, $this->userId, null, null, 1, $digisac_params, null);
$msg = "E já estou pronto para iniciar uma nova busca para você! É só me passar os novos critérios.";
$send_message = $this->sendMessage($msg, null, $this->userId, null, null, 1, $digisac_params, null);
return true;
}
public function typeMessageClosingVisit($income_msg, $filter = null){
$digisac_params = $this->digisacParams;
if(empty($filter)){
$filter = array();
}
if(empty($filter['count_request'])){
$filter['count_request'] = 1;
} else {
$filter['count_request'] = $filter['count_request'] + 1;
}
// Ajustar o prompt de acordo com os itens do FILTER
$prompt = 'O texto se refere às informações fornecidas por um vendedor sobre um determinado cliente após um visita a um imóvel à venda. '
.'O TIMMING DA COMPRA informa quando o cliente pretende realizar a compra, se o cliente pretende comprar o imóvel dentro dos próximo 3 meses, '
.'então o timming é: cliclo atual; caso contrário: pŕoximo ciclo. Informar o Timming na resposta apenas se estiver explícito no texto. '
.'A Região do Cliente pode ter apenas dois valores: Goiânia ou Balneário Camboriú.'
.'Tente extrair do texto as informações abaixo, mas caso não identifique explicitamente alguma das opções, retorne o valor dela como sendo null:\n'
.'- Nome do Cliente;\n'
.'- Engajamento;\n'
.'- Timming da compra\n'
.'- Valor Geral da Venda ou VGV;\n'
.'- Jornada até o fechamento;\n'
.'- Região do cliente;\n'
.'Exibir resultado no formato abaixo:\n'
.'name:<varchar_value_of_nome_do_cliente>\n'
.'engagement:<varchar_value_of_engajamento>\n'
.'timming:<varchar_value_of_timming>\n'
.'sale_value:<integer_value_of_valor_da_venda>\n'
.'closing_journey:<varchar_value_of_jornada_ate_fechamento>\n'
.'client_region:<varchar_value_of_regiao_do_cliente>\n'
.'\n\nText: \"\"\"'.$income_msg.'\n\"\"\"';
$completions = $this->openAiHelper->completions($prompt);
$try_again = false;
$attempts = 0;
if($completions['error'] === true){
$try_again = true;
while($try_again === true){
sleep(1);
$completions = $this->openAiHelper->completions($prompt);
if(isset($completions['data']->choices[0]->text)){
$try_again = false;
} else {
if($attempts >= 10){
// $chat_msg = "Oops, infelizmente estamos passando por uma instabilidade em nossos servidores, isso é raro mas acontece muito 😅.\n\nBrincadeirinha, basta enviar novamente sua mensagem e tudo voltará ao normal.";
$chat_msg = "Desculpe, houve um problema e não consegui entender sua mensagem. Sou um Guru ainda em aprendizado e tentando melhorar a cada dia 🏋️♂️.\n\nPor favor, me fale novamente os detalhes do que você busca.";
$return = $this->sendMessage($chat_msg, 'server_off', $this->userId, null, null, 1, $this->digisacParams);
return $return;
}
}
$attempts++;
}
}
if(isset($completions['data']->choices[0]->text)){
$completion_text = trim($completions['data']->choices[0]->text);
$data = explode(PHP_EOL,$completion_text);
// var_dump($data);exit;
$change_engagement = false;
$change_sale_value = false;
$closing_journey = false;
$change_client = false;
$change_timming = false;
foreach($data as $d){
$f = explode(':',$d);
if(!isset($f[0]) && empty($f[0])){
continue;
}
if(!isset($f[1]) && empty($f[1])){
continue;
}
$param = $f[0];
$val = $f[1];
switch(mb_strtolower($param)){
case 'name':
$val = $this->sanitizeString(trim($val),'alpha');
if(!empty(trim($val)) && !preg_match('(varchar|vazio|null)i',$val) && strlen($val) > 2){
$name = trim(mb_strtolower($val));
if(empty($filter['name']) || $filter['name'] != $name){
$filter['name'] = $name;
$change_client = true;
}
}
break;
case 'client_region':
$val = $this->sanitizeString(trim($val),'alpha');
if(!empty(trim($val)) && !preg_match('(varchar|vazio|null)i',$val) && strlen($val) > 2){
$client_region = trim(mb_strtolower($val));
if(preg_match('(goiânia|goiania)i',$client_region)){
$client_region_id = 1;
} elseif(preg_match('(balneario|balneário|camboriú|camboriu)i',$client_region)){
$client_region_id = 2;
}
if(isset($client_region_id)){
if(empty($filter['service_region_id']) || $filter['service_region_id'] != $client_region_id){
$filter['service_region_id'] = $client_region_id;
}
}
}
break;
case 'closing_journey':
$val = $this->sanitizeString(trim($val),'alphanumeric');
if(!empty(trim($val)) && !preg_match('(varchar|vazio|null)i',$val) && strlen($val) > 10){
$filter['closing_journey'] = trim($val);
$closing_journey = true;
}
break;
case 'sale_value':
$val = $this->sanitizeString(trim($val),'numeric');
if(!empty(trim($val)) && !preg_match('(integer_value|integervalue|vazio|null|none)i',$val)){
$filter['sale_value'] = trim($val);
$change_sale_value = true;
}
break;
case 'engagement':
$val = preg_replace("/[^A-Za-z]/", "", $val);
if(!empty(trim($val)) && preg_match('(alto|baixo)i',$val)){
$val = trim(mb_strtolower($val));
if(preg_match('(alto)i',$val)){
$engagement = 2;
} elseif(preg_match('(baixo)i',$val)){
$engagement = 1;
}
if(isset($engagement)){
if(empty($filter['engagement_id']) || $filter['engagement_id'] != $engagement){
$filter['engagement_id'] = $engagement;
$change_engagement = true;
}
}
}
break;
case 'timming':
$val = $this->sanitizeString(trim($val),'alpha');
if(!empty(trim($val))){
if(preg_match('(atual)i',$val)){
$timming = 1;
} elseif(preg_match('(próximo)i',$val)){
$timming = 2;
}
if(isset($timming)){
if(empty($filter['timing_id']) || $filter['timing_id'] != $timming){
$filter['timing_id'] = $timming;
$change_timming = true;
}
}
}
break;
}
}
if($change_client == true){
$filter['crm_account_id'] = null;
$filter['deal_id'] = null;
if(!empty($filter['name'])){
$clients = ORM::for_table('module_imobles_deals')
->where_like('title','%'.$filter['name'].'%')
->where('seller_id',$this->userId)
->where('status_id',1)
->where_lt('sale_stage_id', 8)
// ->where('id',1)
->find_array();
if(count($clients) == 1){
$deal = $clients[0];
$filter['crm_account_id'] = $deal['crm_account_id'];
$filter['deal_id'] = $deal['id'];
if(!empty($deal['service_region_id'])){
$filter['service_region_id'] = $deal['service_region_id'];
}
} else if(count($clients) == 0){
// TODO: RETIRAR ISSO POIS ESTÁ CHUMBANDO O LEAD COMO LEO LOPES PARA TESTES CASO NÃO ENCONTRE NENHUM LEAD
$filter['crm_account_id'] = 215;
$filter['deal_id'] = 10554;
$filter['service_region_id'] = 1;
}
}
}
if(!empty($filter['sale_value']) && !empty($filter['service_region_id'])){
if($filter['service_region_id'] == 1){
if($filter['sale_value'] < 500000){
$vgv_id = 1;
} elseif($filter['sale_value'] >= 500000 && $filter['sale_value'] < 1000000){
$vgv_id = 2;
} else {
$vgv_id = 3;
}
} elseif($filter['service_region_id'] == 2){
if($filter['sale_value'] < 750000){
$vgv_id = 4;
} elseif($filter['sale_value'] >= 750000 && $filter['sale_value'] < 1500000){
$vgv_id = 5;
} else {
$vgv_id = 6;
}
}
if(!empty($vgv_id)){
if(empty($filter['vgv_id']) || $filter['vgv_id'] != $vgv_id){
$filter['vgv_id'] = $vgv_id;
}
}
}
// var_dump($filter);exit;
/// VERIFICO SE TEM TODOS AS REQUISITOS PARA CADASTRO DA TAREFA
$arr_params = array("filter" => $filter);
$msg_params = json_encode($arr_params);
if(!empty($filter['closing_journey'])
&& !empty($filter['engagement_id'])
&& !empty($filter['timing_id'])
&& !empty($filter['crm_account_id'])
&& !empty($filter['service_region_id'])
&& !empty($filter['vgv_id'])
&& !empty($filter['deal_id'])){
$return = $this->typeMessageClosingVisitSave($msg_params);
return $return;
} else {
$msg = "Perfeito, já vamos registrar seu fechamento de visita, mas antes preciso das informações abaixo:\n\n";
if(empty($filter['crm_account_id'])){
if(empty($filter['name'])){
$msg .= "Informe o nome do cliente.\n\n";
} else {
if(count($clients) > 1){
$deal_name = '';
foreach($clients as $c){
$deal_name .= $c['title']."\n";
}
$msg .= "Encontramos mais de um cliente em seu pipeline com o nome: ".$filter['name']
.".\n\n".$deal_name."\n\n"
."Para qual deles é a tarefa?\n\n";
} elseif(count($clients) == 1){
$deal = $clients[0];
$filter['crm_account_id'] = $deal->crm_account_id;
$filter['deal_id'] = $deal->id;
$filter_aux = array();
} elseif(count($clients) == 0){
$msg .= "Não encontramos nenhum cliente em seu pipeline com o nome: ".$filter['name']
.". Informe novamente o nome do cliente.\n\n";
// TODO: ESTÁ CHUMBADO O CLIENTE PARA OS DEVS TESTAREM
$msg .= "IMPORTANTE: ESSE É UM AMBIENTE DE TESTE E INDEPENDENTE DO NOME INFORMADO VAMOS USAR O LEAD LEO LOPES PARA FINS DE TESTE TODA VEZ QUE O CLIENTE NÃO FOR ENCONTRADO PELO NOME.\n\n";
$filter['crm_account_id'] = 215;
$filter['deal_id'] = 10554;
}
}
} else {
if(empty($filter['service_region_id'])){
$msg .= "*Região do cliente*\nPadrão: O cliente é de Balneário e Região.\n\n";
}
}
if(empty($filter['engagement_id'])){
$msg .= "*Engajamento*\nPadrão: Cliente de ALTO ou BAIXO engajamento.\n\n";
}
if(empty($filter['timing_id'])){
$msg .= "*Timming*\nPadrão: Cliente pretende comprar no CICLO ATUAL (próximos 3 meses) ou no PRÓXIMO CICLO.\n\n";
}
if(empty($filter['vgv_id'])){
$msg .= "*Valor geral da Venda*\nPadrão: O valor da venda é 1 Milhão e Duzentos Mil.\n\n";
}
if(empty($filter['closing_journey'])){
$msg .= "*Jornada até o fechamento*\nPadrão: A jornada até o fechamento será a seguinte: INFO_DA_JORNADA\n\n";
}
if($filter['count_request'] <= 1){
$msg .= "\n\n*Sugestão:* para registrar um FECHAMENTO DE VISITA de forma rápida, envie um áudio no modelo abaixo:\n\n"
."Registrar fechamento de visita para *NOME_DO_CLIENTE*. Cliente de *Alto Engajamento*, prentende comprar no *Ciclo Atual*, "
."o valor da venda é de *1 Milhão e Duzentos Mil*. A jornada até o fechamento é: *INFO_JORNADA*.";
}
$send_message = $this->sendMessage($msg, 'closing_visit_save', $this->userId, null, null, 1, $digisac_params, $msg_params);
return true;
}
} else {
$msg = "Ooops, se você estiver tentando registrar um Fechamento de Visita, por favor, envie um áudio no modelo abaixo:\n\n"
."Registrar fechamento de visita para *NOME_DO_CLIENTE*. Cliente de *Alto Engajamento*, prentende comprar no *Ciclo Atual*, "
."o valor da venda é de *1 Milhão e Duzentos Mil*. A jornada até o fechamento é: INFO_DA_JORNADA.";
$send_message = $this->sendMessage($msg, 'error_client_not_found', $this->userId, null, null, 1, $digisac_params);
return false;
}
}
public function typeMessageClosingVisitSave($params){
$digisac_params = $this->digisacParams;
$params_aux = json_decode($params,false);
if(intval($params_aux->filter->crm_account_id) > 0 && intval($params_aux->filter->deal_id) > 0){
$deal_id = intval($params_aux->filter->deal_id);
$d = ORM::for_table('module_imobles_deals')->find_one($deal_id);
if(isset($d->id) && $d->id = $deal_id){
$d->engagement_id = $params_aux->filter->engagement_id;
$d->timing_id = $params_aux->filter->timing_id;
$d->closing_journey = $params_aux->filter->closing_journey;
$d->service_region_id = $params_aux->filter->service_region_id;
$d->deal_amount = $params_aux->filter->sale_value;
$d->vgv_id = $params_aux->filter->vgv_id;
$d->updated_at = date('Y-m-d H:i:s');
$d->updated_by = $this->userId;
$d->save();
$msg = "Fechamento de visita registrado com sucesso.\n"
."Cliente: ".$params_aux->filter->name."\n"
."https://rocket.myside.com.br/?ng=contacts/view/".$params_aux->filter->crm_account_id."/module_imobles_leads_control/".$params_aux->filter->deal_id."\n\n";
$msg .= "IMPORTANTE: para realizar um fechamento de visita completo, você deve agendar uma pŕoxima tareja para esse cliente.\n\n";
$msg .= "\n\n*Sugestão:* para registrar uma tarefa de forma rápida, envie um áudio no formato abaixo:\n\n"
."Registrar tarefa de *TIPO_DA_TAREFA*, para a data *DIA* de *MÊS*. O título da tarefa é *TÍTULO_DA_TAREFA*.";
$send_message = $this->sendMessage($msg, 'success_closing_visit_save', $this->userId, null, null, 1, $digisac_params, $params);
return true;
}
}
$msg = "Oops, ocorreu algum erro no registro do seu Fechamento de Visita. Por favor tente novamente.";
$msg .= "\n\n*Sugestão:* para registrar um FECHAMENTO DE VISITA de forma rápida, envie um áudio no modelo abaixo:\n\n"
."Registrar fechamento de visita para *NOME_DO_CLIENTE*. Cliente de *Alto Engajamento*, prentende comprar no *Ciclo Atual*, "
."o valor da venda é de *1 Milhão e Duzentos Mil*. A jornada até o fechamento é: INFO_JORNADA.";
$send_message = $this->sendMessage($msg, 'error_save_closing_visit', $this->userId, null, null, 1, $digisac_params, $params);
return false;
}
public function sanitizeString($str, $type){
switch($type){
case 'alphanumeric':
$pattern = "/[^A-Za-z0-9,'ẽ',\s,'ç','á','à','ã','â','é','ê','í','ó','ô','õ','ú','ü','ç','Á','À','Ã','Â','É','Ê','Í','Ó','Ô','Õ','Ú','Ü','Ç']/";
break;
case 'numeric':
$pattern = "/[^0-9]/";
break;
case 'alpha':
$pattern = "/[^A-Za-z,'ẽ',\s,'ç','á','à','ã','â','é','ê','í','ó','ô','õ','ú','ü','ç','Á','À','Ã','Â','É','Ê','Í','Ó','Ô','Õ','Ú','Ü','Ç']/";
break;
case 'date':
$pattern = "/[^0-9{2}\/0-9{2,4}]/";
break;
default:
return null;
break;
}
$return = preg_replace($pattern, "", $str);
return $return;
}
}