getActionKeys(); foreach ($keys as $key) { $list[$key . '_enable'] = 0; $list[$key] = []; // Will hold per-language configuration (keywords + response) } return $list; } /** * List of items to navigate (sidebar) * * @return array[] */ public function listItems() { // He dejado por ahora solo una accion para hacerlo mas simple return [ [ 'label' => __eva('Default Reply'), 'slug' => 'action_fallback', 'is_enabled' => (bool) $this->action_fallback_enable, 'is_fallback' => true, 'description' => __eva('Response sent to the customer when sending a message.'), ], ]; return [ [ 'label' => __eva('Reserve'), 'slug' => 'action_reserve', 'is_enabled' => (bool) $this->action_reserve_enable, 'description' => __eva('Automatic response when a customer wants to make a reservation.'), ], [ 'label' => __eva('Menu'), 'slug' => 'action_menu', 'is_enabled' => (bool) $this->action_menu_enable, 'description' => __eva('Automatic response when a customer asks for the menu.'), ], [ 'label' => __eva('Schedule'), 'slug' => 'action_schedule', 'is_enabled' => (bool) $this->action_schedule_enable, 'description' => __eva('Automatic response when a customer asks about opening hours.'), ], [ 'label' => __eva('Human'), 'slug' => 'action_human', 'is_enabled' => (bool) $this->action_human_enable, 'description' => __eva('Automatic response when a customer wants to speak with a person.'), ], [ 'label' => __eva('Fallback'), 'slug' => 'action_fallback', 'is_enabled' => (bool) $this->action_fallback_enable, 'is_fallback' => true, 'description' => __eva('Response sent when no other action matches the customer message.'), ], ]; } /** * Fields for the admin editor * * @return array */ public function fields() { $keys = [ 'action_reserve' => [ __eva('Reserve'), __eva('Configure keywords and response for reservation requests.'), ], 'action_menu' => [ __eva('Menu'), __eva('Configure keywords and response for menu requests.'), ], 'action_schedule' => [ __eva('Schedule'), __eva('Configure keywords and response for opening hours requests.'), ], 'action_human' => [ __eva('Human'), __eva('Configure keywords and response when a customer wants to talk to a person.'), ], 'action_fallback' => [ __eva('Fallback'), __eva('Configure keywords for language detection.'), //__eva('Configure keywords for language detection and a response for when no other action matches. This action is evaluated last.'), ], ]; $list = []; foreach ($keys as $key => $labels) { $isFallback = ($key === 'action_fallback'); $fields = [ [ 'attribute' => $key . '_enable', 'stacked' => true, 'name' => __eva('Active'), 'helpText' => __eva('Activate this action.'), 'component' => 'boolean-field', 'type' => 'switch', 'value' => $this->{$key . '_enable'}, ], ]; // Action configuration field (keywords + response per language) $actionField = [ 'attribute' => $key, 'stacked' => true, 'name' => $labels[0], 'component' => 'group-whatsapp-action-field', 'value' => $this->valueWithLanguagesFor($key), 'helpText' => $labels[1], 'bookingFields' => self::getBookingFields(), 'restaurantTags' => self::getRestaurantTags(), 'isAdmin' => false, ]; // Fallback does not need keywords //if ($isFallback) { // $actionField['hideKeywords'] = true; //} $fields[] = $actionField; $list[$key] = $fields; } return $list; } /** * Get value with languages for a specific action * * @param string $key * @return array */ public function valueWithLanguagesFor($key) { $languages = evavel_languages_allowed(); $value = $this->{$key}; if (!is_array($value)) { $value = []; } // Ensure all languages have a configuration foreach ($languages as $lang => $label) { if (!isset($value[$lang])) { $value[$lang] = [ 'keywords' => '', 'response_type' => 'template', // 'template' or 'custom' 'template_sid' => '', 'template_name' => '', 'field_mapping' => [], 'custom_message' => '', ]; } } return $value; } // --------------------------------------------------------------- // Helpers for processing incoming messages // --------------------------------------------------------------- /** * Check if an action is enabled * * @param string $actionKey e.g. 'action_reserve' * @return bool */ public function isActionEnabled($actionKey) { return (bool) $this->{$actionKey . '_enable'}; } /** * Get the action configuration for a specific language * * @param string $actionKey e.g. 'action_reserve' * @param string $language * @return array|null */ public function getActionConfig($actionKey, $language) { $config = $this->{$actionKey}; if (!is_array($config) || !isset($config[$language])) { return null; } return $config[$language]; } /** * Get keywords for a specific action and language * * @param string $actionKey * @param string $language * @return array */ public function getKeywords($actionKey, $language) { $config = $this->getActionConfig($actionKey, $language); if (!$config || empty($config['keywords'])) { return []; } return array_map('trim', array_filter(explode(',', $config['keywords']))); } /** * Check if a message matches any keywords for a specific action and language * * @param string $actionKey * @param string $message * @param string $language * @return bool */ public function matchesKeywords($actionKey, $message, $language) { $keywords = $this->getKeywords($actionKey, $language); if (empty($keywords)) { return false; } $messageLower = mb_strtolower(trim($message)); foreach ($keywords as $keyword) { $keywordLower = mb_strtolower(trim($keyword)); if (!empty($keywordLower) && mb_strpos($messageLower, $keywordLower) !== false) { return true; } } return false; } /** * Find the matching default action for an incoming message. * Returns the action key (e.g. 'action_reserve') or null. * * Does NOT check custom actions — those are in WhatsappCustomAction. * * @param string $message * @param string $language * @return string|null The matching action key, or null */ public function findMatchingDefaultAction($message, $language) { $keys = $this->getActionKeys(); // Check all actions except fallback foreach ($keys as $key) { if ($key === 'action_fallback') { continue; } if (!$this->isActionEnabled($key)) { continue; } if ($this->matchesKeywords($key, $message, $language)) { return $key; } } return null; } /** * Get the fallback action key if enabled * * @return string|null */ public function getFallbackActionKey() { if ($this->isActionEnabled('action_fallback')) { return 'action_fallback'; } return null; } /** * Get the response type for a given action and language * * @param string $actionKey * @param string $language * @return string 'template' or 'custom' */ public function getResponseType($actionKey, $language) { $config = $this->getActionConfig($actionKey, $language); if (!$config || empty($config['response_type'])) { return 'template'; } return $config['response_type']; } /** * Get the custom message for a given action and language * * @param string $actionKey * @param string $language * @return string */ public function getCustomMessage($actionKey, $language) { $config = $this->getActionConfig($actionKey, $language); if (!$config || empty($config['custom_message'])) { return ''; } return $config['custom_message']; } /** * Get the template config for a given action and language * * @param string $actionKey * @param string $language * @return array|null */ public function getTemplateConfig($actionKey, $language) { $config = $this->getActionConfig($actionKey, $language); if (!$config || empty($config['template_sid'])) { return null; } return [ 'template_sid' => $config['template_sid'], 'template_name' => $config['template_name'] ?? '', 'field_mapping' => $config['field_mapping'] ?? [], 'static_values' => $config['static_values'] ?? [], 'book_now_widget_id' => $config['book_now_widget_id'] ?? null, ]; } }