Source of file InteractQueryManager.php
Size: 37,469 Bytes - Last Modified: 2020-10-24T02:46:31+00:00
/home/travis/build/NextDom/nextdom-core/src/Managers/InteractQueryManager.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902 | <?php /* * This file is part of the NextDom software (https://github.com/NextDom or http://nextdom.github.io). * Copyright (c) 2018 NextDom. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, version 2. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ /* This file is part of Jeedom. * * Jeedom is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Jeedom is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Jeedom. If not, see <http://www.gnu.org/licenses/>. */ namespace NextDom\Managers; use NextDom\Enums\CmdSubType; use NextDom\Enums\CmdType; use NextDom\Enums\Common; use NextDom\Enums\ConfigKey; use NextDom\Enums\LogTarget; use NextDom\Enums\NextDomObj; use NextDom\Helpers\DBHelper; use NextDom\Helpers\LogHelper; use NextDom\Helpers\NextDomHelper; use NextDom\Helpers\Utils; use NextDom\Managers\Parents\BaseManager; use NextDom\Managers\Parents\CommonManager; use NextDom\Model\Entity\EqLogic; use NextDom\Model\Entity\InteractQuery; use NextDom\Model\Entity\JeeObject; use NextDom\Model\Entity\Listener; /** * Class InteractQueryManager * @package NextDom\Managers */ class InteractQueryManager extends BaseManager { use CommonManager; const CLASS_NAME = InteractQuery::class; const DB_CLASS_NAME = '`interactQuery`'; /** * @param $_interactDef_id * @return array|mixed|null * @throws \NextDom\Exceptions\CoreException * @throws \ReflectionException */ public static function byInteractDefId($_interactDef_id) { $values = [ 'interactDef_id' => $_interactDef_id, ]; $sql = static::getBaseSQL() . ' WHERE `interactDef_id` = :interactDef_id ORDER BY `query`'; return DBHelper::getAllObjects($sql, $values, self::CLASS_NAME); } /** * @param $_action * @return InteractQuery[] * @throws \Exception */ public static function searchActions($_action) { if (!is_array($_action)) { $values = [ 'actions' => '%' . $_action . '%', ]; $sql = static::getBaseSQL() . ' WHERE `actions` LIKE :actions'; } else { $values = [ 'actions' => '%' . $_action[0] . '%', ]; $sql = static::getBaseSQL() . ' WHERE `actions` LIKE :actions'; for ($i = 1; $i < count($_action); $i++) { $values['actions' . $i] = '%' . $_action[$i] . '%'; $sql .= ' OR `actions` LIKE :actions' . $i; } } return DBHelper::getAllObjects($sql, $values, self::CLASS_NAME); } /** * @param $interactDefId * @return array|mixed|null * @throws \NextDom\Exceptions\CoreException */ public static function removeByInteractDefId($interactDefId) { $values = [ 'interactDef_id' => $interactDefId, ]; $sql = 'DELETE FROM ' . self::DB_CLASS_NAME . ' WHERE `interactDef_id` = :interactDef_id'; return DBHelper::getAllObjects($sql, $values, self::CLASS_NAME); } /** * @param JeeObject $a * @param JeeObject $b * @return int */ public static function cmp_objectName($a, $b) { return (strlen($a->getName()) < strlen($b->getName())) ? +1 : -1; } /** * @param $_options * @throws \NextDom\Exceptions\CoreException */ public static function warnMeExecute($_options) { $warnMeCmd = (isset($_options[Common::REPLY_CMD])) ? $_options[Common::REPLY_CMD] : ConfigManager::byKey('interact::warnme::defaultreturncmd'); if (!isset($_options['test']) || $_options['test'] == '' || $warnMeCmd == '') { ListenerManager::byId($_options['listener_id'])->remove(); return; } $result = NextDomHelper::evaluateExpression(str_replace('#value#', $_options['value'], $_options['test'])); if ($result) { ListenerManager::byId($_options['listener_id'])->remove(); $cmd = CmdManager::byId(str_replace('#', '', $warnMeCmd)); if (!is_object($cmd)) { return; } $cmd->execCmd([ 'title' => __('Alerte : ') . str_replace('#value#', $_options['name'], $_options['test']) . __(' valeur : ') . $_options['value'], 'message' => __('Alerte : ') . str_replace('#value#', $_options['name'], $_options['test']) . __(' valeur : ') . $_options['value'], ]); } } /** * @param $_query * @param array $_parameters * @return array|bool|null|string * @throws \NextDom\Exceptions\CoreException * @throws \ReflectionException */ public static function tryToReply($_query, $_parameters = []) { if (trim($_query) == '') { return ['reply' => '']; } $_parameters['identifier'] = ''; if (isset($_parameters['plugin'])) { $_parameters['identifier'] = $_parameters['plugin']; } else { $_parameters['identifier'] = 'unknown'; } if (isset($_parameters[Common::PROFILE])) { $_parameters['identifier'] .= '::' . $_parameters[Common::PROFILE]; } $_parameters['dictation'] = $_query; if (isset($_parameters[Common::PROFILE])) { $_parameters[Common::PROFILE] = strtolower($_parameters[Common::PROFILE]); } $reply = ''; $words = str_word_count($_query, 1); $startContextual = explode(';', ConfigManager::byKey('interact::contextual::startpriority')); if (is_array($startContextual) && count($startContextual) > 0 && ConfigManager::byKey('interact::contextual::enable') == 1 && isset($words[0]) && in_array(strtolower($words[0]), $startContextual)) { $reply = self::contextualReply($_query, $_parameters); LogHelper::addDebug(LogTarget::INTERACT, 'Je cherche interaction contextuel (prioritaire) : ' . print_r($reply, true)); } $startWarnMe = explode(';', ConfigManager::byKey('interact::warnme::start')); if (is_array($startWarnMe) && count($startWarnMe) > 0 && ConfigManager::byKey('interact::warnme::enable') == 1 && Utils::strContainsOneOf(strtolower(Utils::sanitizeAccent($_query)), $startWarnMe)) { $reply = self::warnMe($_query, $_parameters); LogHelper::addDebug(LogTarget::INTERACT, 'Je cherche interaction "previens-moi" : ' . print_r($reply, true)); } if (ConfigManager::byKey('interact::contextual::splitword') != '') { $splitWords = explode(';', ConfigManager::byKey('interact::contextual::splitword')); $queries = []; foreach ($splitWords as $split) { if (in_array($split, $words)) { $queries = array_merge($queries, explode(' ' . $split . ' ', $_query)); } } if (count($queries) > 1) { $reply = self::tryToReply($queries[0], $_parameters); if ($reply != '') { array_shift($queries); foreach ($queries as $query) { $tmp = self::contextualReply($query, $_parameters); if (is_array($tmp)) { foreach ($tmp as $key => $value) { if (!isset($reply[$key])) { $reply[$key] = $value; continue; } if (is_string($value) && $reply[$key] != $value) { $reply[$key] .= "\n" . $value; } if (is_array($value)) { $reply[$key] = array_merge($reply[$key], $value); } } } else { $reply['reply'] .= "\n" . $tmp; } } return $reply; } } } if ($reply == '') { $reply = self::pluginReply($_query, $_parameters); if ($reply !== null) { LogHelper::addInfo(LogTarget::INTERACT, 'J\'ai reçu : ' . $_query . '. Un plugin a répondu : ' . print_r($reply, true)); return $reply; } $interactQuery = self::recognize($_query); if (is_object($interactQuery)) { $reply = $interactQuery->executeAndReply($_parameters); $cmds = $interactQuery->getActions(NextDomObj::CMD); if (isset($cmds[0]) && isset($cmds[0][NextDomObj::CMD])) { self::addLastInteract(str_replace('#', '', $cmds[0][NextDomObj::CMD]), $_parameters['identifier']); } LogHelper::addInfo(LogTarget::INTERACT, 'J\'ai reçu : ' . $_query . ". J'ai compris : " . $interactQuery->getQuery() . ". J'ai répondu : " . $reply); return ['reply' => ucfirst($reply)]; } } if ($reply == '' && ConfigManager::byKey('interact::autoreply::enable') == 1) { $reply = self::autoInteract($_query, $_parameters); LogHelper::addDebug(LogTarget::INTERACT, 'Je cherche dans les interactions automatiques, résultat : ' . $reply); } if ($reply == '' && ConfigManager::byKey('interact::noResponseIfEmpty', 'core', 0) == 0 && (!isset($_parameters['emptyReply']) || $_parameters['emptyReply'] == 0)) { $reply = self::dontUnderstand($_parameters); LogHelper::addInfo(LogTarget::INTERACT, 'J\'ai reçu : ' . $_query . ". Je n'ai rien compris. J'ai répondu : " . $reply); } if (!is_array($reply)) { $reply = ['reply' => ucfirst($reply)]; } LogHelper::addInfo(LogTarget::INTERACT, 'J\'ai reçu : ' . $_query . ". Je réponds : " . print_r($reply, true)); if (isset($_parameters[Common::REPLY_CMD]) && is_object($_parameters[Common::REPLY_CMD]) && isset($_parameters['force_reply_cmd'])) { $_parameters[Common::REPLY_CMD]->execCmd(['message' => $reply['reply']]); return true; } return $reply; } /** * @param $_query * @param array $_parameters * @param null $_lastCmd * @return array|null|string * @throws \Exception */ public static function contextualReply($_query, $_parameters = [], $_lastCmd = null) { $return = ''; if (!isset($_parameters['identifier'])) { $_parameters['identifier'] = ''; } if ($_lastCmd === null) { $last = CacheManager::byKey('interact::lastCmd::' . $_parameters['identifier']); if ($last->getValue() == '') { return $return; } $lastCmd = $last->getValue(); } else { $lastCmd = $_lastCmd; } $current = []; $current[NextDomObj::CMD] = CmdManager::byId($lastCmd); if (is_object($current[NextDomObj::CMD])) { $current[NextDomObj::EQLOGIC] = $current[NextDomObj::CMD]->getEqLogicId(); if (!is_object($current[NextDomObj::EQLOGIC])) { return $return; } $current[NextDomObj::OBJECT] = $current[NextDomObj::EQLOGIC]->getObject(); $humanName = $current[NextDomObj::CMD]->getHumanName(); } else { $humanName = strtolower(Utils::sanitizeAccent($lastCmd)); $current = self::findInQuery(NextDomObj::OBJECT, $humanName); $current = array_merge($current, self::findInQuery(Common::SUMMARY, $current[Common::QUERY], $current)); } $data = self::mergeData($_query); if (isset($data[NextDomObj::OBJECT]) && is_object($current[NextDomObj::OBJECT])) { $humanName = self::replaceForContextual($current[NextDomObj::OBJECT]->getName(), $data[NextDomObj::OBJECT]->getName(), $humanName); } if (isset($data[NextDomObj::CMD]) && is_object($current[NextDomObj::CMD])) { $humanName = self::replaceForContextual($current[NextDomObj::CMD]->getName(), $data[NextDomObj::CMD]->getName(), $humanName); } if (isset($data[NextDomObj::EQLOGIC]) && is_object($current[NextDomObj::EQLOGIC])) { $humanName = self::replaceForContextual($current[NextDomObj::EQLOGIC]->getName(), $data[NextDomObj::EQLOGIC]->getName(), $humanName); } $reply = self::pluginReply($humanName, $_parameters); if ($reply !== null) { return $reply; } $return = self::autoInteract(str_replace(['][', '[', ']'], [' ', '', ''], $humanName), $_parameters); if ($return == '' && $_lastCmd === null) { $last = CacheManager::byKey('interact::lastCmd2::' . $_parameters['identifier']); if ($last->getValue() != '') { $return = self::contextualReply($_query, $_parameters, $last->getValue()); } } return $return; } /** * @param $_type * @param $_query * @param null $_data * @return array * @throws \Exception */ public static function findInQuery($_type, $_query, $_data = null) { $return = []; $return[Common::QUERY] = strtolower(Utils::sanitizeAccent($_query)); $return[$_type] = null; $synonyms = self::getQuerySynonym($return[Common::QUERY], $_type); if ($_type == NextDomObj::OBJECT) { $jeeObjects = JeeObjectManager::all(); } elseif ($_type == NextDomObj::EQLOGIC) { if ($_data !== null && is_object($_data[NextDomObj::OBJECT])) { $jeeObjects = $_data[NextDomObj::OBJECT]->getEqLogic(); } else { $jeeObjects = EqLogicManager::all(true); } } elseif ($_type == NextDomObj::CMD) { if ($_data !== null && is_object($_data[NextDomObj::EQLOGIC])) { $jeeObjects = $_data[NextDomObj::EQLOGIC]->getCmd(); } elseif ($_data !== null && is_object($_data[NextDomObj::OBJECT])) { $jeeObjects = []; foreach ($_data[NextDomObj::OBJECT]->getEqLogic() as $eqLogic) { if ($eqLogic->getIsEnable() == 0) { continue; } foreach ($eqLogic->getCmd() as $cmd) { $jeeObjects[] = $cmd; } } } else { $jeeObjects = CmdManager::all(); } } elseif ($_type == Common::SUMMARY) { foreach (ConfigManager::byKey(ConfigKey::OBJECT_SUMMARY) as $summary) { if (count($synonyms) > 0 && in_array(strtolower($summary['name']), $synonyms)) { $return[$_type] = $summary; break; } if (self::autoInteractWordFind($return[Common::QUERY], $summary['name'])) { $return[$_type] = $summary; $return[Common::QUERY] = str_replace(strtolower(Utils::sanitizeAccent($summary['name'])), '', $return[Common::QUERY]); break; } } if (count($synonyms) > 0) { foreach ($synonyms as $summary) { $return[Common::QUERY] = str_replace(strtolower(Utils::sanitizeAccent($summary)), '', $return[Common::QUERY]); } } return $return; } usort($jeeObjects, ["interactQuery", "cmp_objectName"]); foreach ($jeeObjects as $jeeObject) { if ($jeeObject->getConfiguration('interact::auto::disable', 0) == 1) { continue; } if (count($synonyms) > 0 && in_array(strtolower($jeeObject->getName()), $synonyms)) { $return[$_type] = $jeeObject; break; } if (self::autoInteractWordFind($return[Common::QUERY], $jeeObject->getName())) { $return[$_type] = $jeeObject; break; } } if ($_type != NextDomObj::EQLOGIC && is_object($return[$_type])) { $return[Common::QUERY] = str_replace(strtolower(Utils::sanitizeAccent($return[$_type]->getName())), '', $return[Common::QUERY]); if (count($synonyms) > 0) { foreach ($synonyms as $summary) { $return[Common::QUERY] = str_replace(strtolower(Utils::sanitizeAccent($summary)), '', $return[Common::QUERY]); } } } return $return; } /** * @param $_query * @param $_for * @return array * @throws \Exception */ public static function getQuerySynonym($_query, $_for) { $return = []; $base_synonyms = explode(';', ConfigManager::byKey('interact::autoreply::' . $_for . '::synonym')); if (count($base_synonyms) == 0) { return $return; } foreach ($base_synonyms as $synonyms) { if (trim($synonyms) == '') { continue; } $synonyms = explode('|', $synonyms); foreach ($synonyms as $synonym) { if (self::autoInteractWordFind($_query, $synonym)) { $return = array_merge($return, $synonyms); } } } return $return; } /** * @param $_string * @param $_word * @return false|int */ public static function autoInteractWordFind($_string, $_word) { return preg_match( '/( |^)' . preg_quote(strtolower(Utils::sanitizeAccent($_word)), '/') . '( |$)/', str_replace("'", ' ', strtolower(Utils::sanitizeAccent($_string))) ); } /** * @param $_replace * @param $_by * @param $_in * @return mixed */ public static function replaceForContextual($_replace, $_by, $_in) { return str_replace(strtolower(Utils::sanitizeAccent($_replace)), strtolower(Utils::sanitizeAccent($_by)), str_replace($_replace, $_by, $_in)); } /** * @param $_query * @param array $_parameters * @return array|null * @throws \Exception */ public static function pluginReply($_query, $_parameters = []) { try { foreach (PluginManager::listPlugin(true) as $plugin) { if (ConfigManager::byKey('functionality::interact::enable', $plugin->getId(), 1) == 0) { continue; } if (method_exists($plugin->getId(), NextDomObj::INTERACT)) { $plugin_id = $plugin->getId(); $reply = $plugin_id::interact($_query, $_parameters); if ($reply !== null || is_array($reply)) { $reply['reply'] = '[' . $plugin_id . '] ' . $reply['reply']; self::addLastInteract($_query, $_parameters['identifier']); LogHelper::addDebug(LogTarget::INTERACT, 'Le plugin ' . $plugin_id . ' a répondu'); return $reply; } } } } catch (\Exception $e) { return ['reply' => __('Erreur : ') . $e->getMessage()]; } return null; } /** * @param $_lastCmd * @param string $_identifier * @throws \Exception */ public static function addLastInteract($_lastCmd, $_identifier = 'unknown') { $last = CacheManager::byKey('interact::lastCmd::' . $_identifier); if ($last->getValue() == '') { CacheManager::set('interact::lastCmd2::' . $_identifier, $last->getValue(), 300); } CacheManager::set('interact::lastCmd::' . $_identifier, str_replace('#', '', $_lastCmd), 300); } /** * @param $_query * @param array $_parameters * @return string * @throws \Exception */ public static function autoInteract($_query, $_parameters = []) { if (!isset($_parameters['identifier'])) { $_parameters['identifier'] = ''; } $data = self::findInQuery(NextDomObj::OBJECT, $_query); $data[Common::CMD_PARAMETERS] = []; /** @var EqLogic[] $data */ $data = array_merge($data, self::findInQuery(NextDomObj::EQLOGIC, $data[Common::QUERY], $data)); $data = array_merge($data, self::findInQuery(NextDomObj::CMD, $data[Common::QUERY], $data)); if (isset($data[NextDomObj::EQLOGIC]) && is_object($data[NextDomObj::EQLOGIC]) && (!isset($data[NextDomObj::CMD]) || !is_object($data[NextDomObj::CMD]))) { foreach ($data[NextDomObj::EQLOGIC]->getCmd(CmdType::ACTION) as $cmd) { if ($cmd->isSubType(CmdSubType::SLIDER)) { break; } } if (is_object($cmd)) { if (preg_match_all('/' . ConfigManager::byKey('interact::autoreply::cmd::slider::max') . '/i', $data[Common::QUERY])) { $data[NextDomObj::CMD] = $cmd; $data[Common::CMD_PARAMETERS][CmdSubType::SLIDER] = $cmd->getConfiguration('maxValue', 100); } if (preg_match_all('/' . ConfigManager::byKey('interact::autoreply::cmd::slider::min') . '/i', $data[Common::QUERY])) { $data[NextDomObj::CMD] = $cmd; $data[Common::CMD_PARAMETERS][CmdSubType::SLIDER] = $cmd->getConfiguration('minValue', 0); } } } if (!isset($data[NextDomObj::CMD]) || !is_object($data[NextDomObj::CMD])) { $data = array_merge($data, self::findInQuery(Common::SUMMARY, $data[Common::QUERY], $data)); LogHelper::addDebug(LogTarget::INTERACT, print_r($data, true)); if (!isset($data[Common::SUMMARY])) { return ''; } $return = $data[Common::SUMMARY][Common::NAME]; $value = ''; if (is_object($data[NextDomObj::OBJECT])) { $return .= ' ' . $data[NextDomObj::OBJECT]->getName(); $value = $data[NextDomObj::OBJECT]->getSummary($data[Common::SUMMARY][Common::KEY]); } if (trim($value) === '') { $value = JeeObjectManager::getGlobalSummary($data[Common::SUMMARY][Common::KEY]); } if (trim($value) === '') { return ''; } self::addLastInteract($_query, $_parameters['identifier']); return $return . ' ' . $value . ' ' . $data[Common::SUMMARY]['unit']; } self::addLastInteract($data[NextDomObj::CMD]->getId(), $_parameters['identifier']); if ($data[NextDomObj::CMD]->isType(CmdType::INFO)) { return trim($data[NextDomObj::CMD]->getHumanName() . ' ' . $data[NextDomObj::CMD]->execCmd() . ' ' . $data[NextDomObj::CMD]->getUnite()); } else { if ($data[NextDomObj::CMD]->getSubtype() == CmdSubType::SLIDER) { preg_match_all('/(\d+)/', strtolower(Utils::sanitizeAccent($data[Common::QUERY])), $matches); if (isset($matches[0]) && isset($matches[0][0])) { $data[Common::CMD_PARAMETERS][CmdSubType::SLIDER] = $matches[0][0]; } } if ($data[NextDomObj::CMD]->getSubtype() == CmdSubType::COLOR) { $colors = array_change_key_case(ConfigManager::byKey('convertColor')); foreach ($colors as $name => $value) { if (strpos($data[Common::QUERY], $name) !== false) { $data[Common::CMD_PARAMETERS]['color'] = $value; break; } } } $data[NextDomObj::CMD]->execCmd($data[Common::CMD_PARAMETERS]); $return = __('C\'est fait') . ' ('; $eqLogic = $data[NextDomObj::CMD]->getEqLogic(); if (is_object($eqLogic)) { $linkedObject = $eqLogic->getObject(); if (is_object($linkedObject)) { $return .= $linkedObject->getName(); } $return .= ' ' . $data[NextDomObj::CMD]->getEqLogic()->getName(); } $return .= ' ' . $data[NextDomObj::CMD]->getName(); if (isset($data[Common::CMD_PARAMETERS][CmdSubType::SLIDER])) { $return .= ' => ' . $data[Common::CMD_PARAMETERS][CmdSubType::SLIDER] . '%'; } return $return . ')'; } } /** * @param $_query * @param array $_parameters * @return array|null * @throws \NextDom\Exceptions\CoreException * @throws \ReflectionException */ public static function warnMe($_query, $_parameters = []) { global $NEXTDOM_INTERNAL_CONFIG; $operator = null; $operand = null; foreach ($NEXTDOM_INTERNAL_CONFIG[NextDomObj::INTERACT]['test'] as $key => $value) { if (Utils::strContainsOneOf(strtolower(Utils::sanitizeAccent($_query)), $value)) { $operator .= $key; break; } } preg_match_all('!\d+!', strtolower(Utils::sanitizeAccent($_query)), $matches); if (isset($matches[0]) && isset($matches[0][0])) { $operand = $matches[0][0]; } if ($operand === null || $operator === null) { return null; } $test = '#value# ' . $operator . ' ' . $operand; $options = ['test' => $test]; if (is_object($_parameters[Common::REPLY_CMD])) { $options[Common::REPLY_CMD] = $_parameters[Common::REPLY_CMD]->getId(); } $listener = new Listener(); $listener->setClass(NextDomObj::INTERACT_QUERY); $listener->setFunction('warnMeExecute'); $data = self::mergeData($_query); if (!isset($data[NextDomObj::CMD]) || !is_object($data[NextDomObj::CMD])) { return null; } else { if ($data[NextDomObj::CMD]->isType(CmdType::ACTION)) { return null; } $options['type'] = NextDomObj::CMD; $options['cmd_id'] = $data[NextDomObj::CMD]->getId(); $options['name'] = $data[NextDomObj::CMD]->getHumanName(); $listener->addEvent($data[NextDomObj::CMD]->getId()); $listener->setOption($options); $listener->save(true); return ['reply' => __('C\'est noté : ') . str_replace('#value#', $data[NextDomObj::CMD]->getHumanName(), $test)]; } } /** * @param $_query * @return null * @throws \NextDom\Exceptions\CoreException * @throws \ReflectionException */ public static function recognize($_query) { $_query = InteractDefManager::sanitizeQuery($_query); if (trim($_query) == '') { return null; } $query = self::byQuery($_query, null, false); if (is_object($query)) { if (self::searchCorrespondence($_query, $query)) { LogHelper::addDebug(LogTarget::INTERACT, 'Je prends : ' . $query->getQuery()); return $query; } return null; } $sql = 'SELECT ' . DBHelper::buildField(self::CLASS_NAME) . ', MATCH query AGAINST (:query IN NATURAL LANGUAGE MODE) as score FROM ' . self::DB_CLASS_NAME . ' GROUP BY id HAVING score > 1'; $queries = DBHelper::getAllObjects($sql, [Common::QUERY => $_query], self::CLASS_NAME); if (count($queries) == 0) { $query = self::byQuery($_query); if (is_object($query)) { if (self::searchCorrespondence($_query, $query)) { return $queries; } return null; } $queries = self::all(); } $shortest = 999; foreach ($queries as $query) { $input = InteractDefManager::sanitizeQuery($query->getQuery()); $tags = InteractDefManager::getTagFromQuery($query->getQuery(), $_query); if (count($tags) > 0) { foreach ($tags as $value) { if ($value == "") { continue (2); } } $input = str_replace(array_keys($tags), $tags, $input); } $lev = levenshtein($input, $_query); LogHelper::addDebug(LogTarget::INTERACT, 'Je compare : ' . $_query . ' avec ' . $input . ' => ' . $lev); if (trim($_query) == trim($input)) { $shortest = 0; $closest = $query; break; } if ($lev == 0) { $shortest = 0; $closest = $query; break; } if ($lev <= $shortest || $shortest < 0) { $closest = $query; $shortest = $lev; } } if ($shortest < 0) { LogHelper::addDebug(LogTarget::INTERACT, __('Aucune correspondance trouvée')); return null; } $weigh = [ 1 => ConfigManager::byKey('interact::weigh1'), 2 => ConfigManager::byKey('interact::weigh2'), 3 => ConfigManager::byKey('interact::weigh3'), 4 => ConfigManager::byKey('interact::weigh4')]; foreach (str_word_count($_query, 1) as $word) { if (isset($weigh[strlen($word)])) { $value = intval($weigh[strlen($word)]); $shortest += $value; } } if (str_word_count($_query) == 1 && ConfigManager::byKey('interact::confidence1') > 0 && $shortest > ConfigManager::byKey('interact::confidence1')) { LogHelper::addDebug(LogTarget::INTERACT, __('Correspondance trop éloigné : ') . $shortest); return null; } else if (str_word_count($_query) == 2 && ConfigManager::byKey('interact::confidence2') > 0 && $shortest > ConfigManager::byKey('interact::confidence2')) { LogHelper::addDebug(LogTarget::INTERACT, __('Correspondance trop éloigné : ') . $shortest); return null; } else if (str_word_count($_query) == 3 && ConfigManager::byKey('interact::confidence3') > 0 && $shortest > ConfigManager::byKey('interact::confidence3')) { LogHelper::addDebug(LogTarget::INTERACT, __('Correspondance trop éloigné : ') . $shortest); return null; } else if (str_word_count($_query) > 3 && ConfigManager::byKey('interact::confidence') > 0 && $shortest > ConfigManager::byKey('interact::confidence')) { LogHelper::addDebug(LogTarget::INTERACT, __('Correspondance trop éloigné : ') . $shortest); return null; } if (!is_object($closest)) { LogHelper::addDebug(LogTarget::INTERACT, __('Aucune phrase trouvée')); return null; } $interactDef = $closest->getInteractDef(); if ($interactDef->getOptions('mustcontain') != '' && !preg_match($interactDef->getOptions('mustcontain'), $_query)) { LogHelper::addDebug(LogTarget::INTERACT, __('Correspondance trouvée : ') . $closest->getQuery() . __(' mais ne contient pas : ') . InteractDefManager::sanitizeQuery($interactDef->getOptions('mustcontain'))); return null; } LogHelper::addDebug(LogTarget::INTERACT, __('J\'ai une correspondance : ') . $closest->getQuery() . __(' avec ') . $shortest); return $closest; } /** * @param $_query * @param null $_interactDef_id * @param bool $caseSensitive Set to false for insensitive case comparaison * @return InteractQuery * @throws \NextDom\Exceptions\CoreException * @throws \ReflectionException */ public static function byQuery($_query, $_interactDef_id = null, $caseSensitive = true) { $values = [ Common::QUERY => $_query, ]; $sql = static::getBaseSQL(); if ($caseSensitive) { $sql .= ' WHERE `query` = :query'; } else { $sql .= ' WHERE LOWER(query)=LOWER(:query)'; } if ($_interactDef_id !== null) { $values['interactDef_id'] = $_interactDef_id; $sql .= ' AND `interactDef_id` = :interactDef_id'; } return DBHelper::getOneObject($sql, $values, self::CLASS_NAME); } /** * @param string $baseQuery * @param InteractQuery $interactQuery * @return bool * @throws \Exception */ private static function searchCorrespondence($baseQuery, $interactQuery) { $interactDef = $interactQuery->getInteractDef(); if ($interactDef->getOptions('mustcontain') != '' && !preg_match($interactDef->getOptions('mustcontain'), $baseQuery)) { LogHelper::addDebug(LogTarget::INTERACT, __('Correspondance trouvée : ') . $interactQuery->getQuery() . __(' mais ne contient pas : ') . InteractDefManager::sanitizeQuery($interactDef->getOptions('mustcontain'))); return false; } return true; } /** * @return InteractQuery|null * @throws \Exception */ public static function all() { return static::getAllOrdered('id'); } /** * @param $_parameters * @return mixed * @throws \Exception */ public static function dontUnderstand($_parameters) { $notUnderstood = [ __('Désolé je n\'ai pas compris'), __('Désolé je n\'ai pas compris la demande'), __('Désolé je ne comprends pas la demande'), __('Je ne comprends pas'), ]; if (isset($_parameters[Common::PROFILE])) { $notUnderstood[] = __('Désolé ') . $_parameters[Common::PROFILE] . __(' je n\'ai pas compris'); $notUnderstood[] = __('Désolé ') . $_parameters[Common::PROFILE] . __(' je n\'ai pas compris ta demande'); } $random = rand(0, count($notUnderstood) - 1); return $notUnderstood[$random]; } /** * @param $_query * @param $_parameters * @return string */ public static function brainReply($_query, $_parameters) { global $PROFILE; $PROFILE = ''; if (isset($_parameters[Common::PROFILE])) { $PROFILE = $_parameters[Common::PROFILE]; } require_once NEXTDOM_DATA . '/config/bot.config.php'; global $BRAINREPLY; $shortest = 999; foreach ($BRAINREPLY as $word => $response) { $lev = levenshtein(strtolower($_query), strtolower($word)); if ($lev == 0) { $closest = $word; $shortest = 0; break; } if ($lev <= $shortest || $shortest < 0) { $closest = $word; $shortest = $lev; } } if (isset($closest) && is_array($BRAINREPLY[$closest])) { $random = rand(0, count($BRAINREPLY[$closest]) - 1); return $BRAINREPLY[$closest][$random]; } return ''; } /** * @return mixed * @throws \Exception */ public static function replyOk() { $reply = [ __('C\'est fait'), __('Ok'), __('Voila, c\'est fait'), __('Bien compris'), ]; $random = rand(0, count($reply) - 1); return $reply[$random]; } /** * @param $_params * @throws \NextDom\Exceptions\CoreException * @throws \ReflectionException */ public static function doIn($_params) { $interactQuery = self::byId($_params['interactQuery_id']); if (!is_object($interactQuery)) { return; } $_params['execNow'] = 1; $interactQuery->executeAndReply($_params); } /** * @param $query * @return array * @throws \Exception */ private static function mergeData($query): array { $data = self::findInQuery(NextDomObj::OBJECT, $query); $data = array_merge($data, self::findInQuery(NextDomObj::EQLOGIC, $data[Common::QUERY], $data)); $data = array_merge($data, self::findInQuery(NextDomObj::CMD, $data[Common::QUERY], $data)); return $data; } } |