options = get_option('mxchat_options');
$this->chat_count = get_option('mxchat_chat_count', 0);
$this->is_activated = $this->is_license_active();
// Initialize default options if they are not set
if (!$this->options) {
$this->initialize_default_options();
}
// Add admin menu and initialize settings
add_action('admin_menu', array($this, 'mxchat_add_plugin_page'));
add_action('admin_init', array($this, 'mxchat_page_init'));
add_action('admin_enqueue_scripts', array($this, 'mxchat_enqueue_admin_assets'));
add_action('wp_ajax_mxchat_delete_chat_history', array($this, 'mxchat_delete_chat_history'));
add_action('admin_post_mxchat_submit_content', array($this, 'mxchat_handle_content_submission'));
add_action('admin_post_mxchat_delete_prompt', array($this, 'mxchat_handle_delete_prompt'));
add_action('wp_ajax_mxchat_fetch_chat_history', array($this, 'mxchat_fetch_chat_history'));
add_action('wp_ajax_nopriv_mxchat_fetch_chat_history', array($this, 'mxchat_fetch_chat_history'));
add_action('admin_post_mxchat_submit_sitemap', array($this, 'mxchat_handle_sitemap_submission'));
add_action('wp_footer', array($this, 'mxchat_append_chatbot_to_body'));
add_action('admin_head-mxchat-prompts', array($this, 'mxchat_enqueue_admin_assets'));
add_action('admin_head-toplevel_page_mxchat-max', array($this, 'mxchat_enqueue_admin_assets'));
add_action('wp_ajax_mxchat_activate_license', array($this, 'mxchat_handle_activate_license'));
add_action('admin_notices', array($this, 'mxchat_display_admin_notice'));
// Add the AJAX handler for logged-in users
add_action('wp_ajax_mxchat_save_inline_prompt', array($this, 'mxchat_save_inline_prompt'));
add_action('admin_post_mxchat_delete_all_prompts', array($this, 'mxchat_handle_delete_all_prompts'));
// Define admin_post actions for form submission handling
add_action('admin_post_mxchat_add_intent', array($this, 'mxchat_handle_add_intent'));
add_action('admin_post_mxchat_delete_intent', array($this, 'mxchat_handle_delete_intent'));
add_action('admin_post_mxchat_update_intent_threshold', array($this, 'mxchat_handle_update_intent_threshold'));
add_action('admin_post_mxchat_stop_processing', array($this, 'mxchat_stop_processing'));
}
// Method to check if the license is active
private function is_license_active() {
$license_status = get_option('mxchat_license_status', 'inactive');
return $license_status === 'active';
}
// Initialize default options
private function initialize_default_options() {
$default_options = array(
'api_key' => '',
'xai_api_key' => '',
'claude_api_key' => '',
'system_prompt_instructions' => '[EXAMPLE INSTRUCTIONS] You are an AI Chatbot assistant for this website. The primary subject you should focus on is [insert proper subject here]. Your main goal is to assist visitors with questions related to this specific topic. Here are some key things to keep in mind:
- Your name is [Chatbot Name].
- Stay focused on topics related to [insert proper subject here]. If a visitor asks about an unrelated topic, politely redirect the conversation to how you can assist them with this subject.
- Do not make up links to pages. Only use specific links you see in your knowledgebase.
- Keep your responses short, concise, and to the point. Provide clear and direct answers suitable for a chatbot interaction.
- Provide answers based on the knowledge available to you. If you do not have an answer to a specific question, let the visitor know that you don’t have the information.',
'model' => 'gpt-4o',
'rate_limit_logged_in' => '100',
'rate_limit_logged_out' => '100',
'rate_limit_message' => 'Rate limit exceeded. Please try again later.',
'top_bar_title' => 'MxChat',
'intro_message' => 'Hello! How can I assist you today?',
'input_copy' => 'How can I assist?',
'append_to_body' => 'off',
'close_button_color' => '#fff',
'chatbot_bg_color' => '#fff',
'user_message_bg_color' => '#fff',
'user_message_font_color' => '#212121',
'bot_message_bg_color' => '#212121',
'bot_message_font_color' => '#fff',
'top_bar_bg_color' => '#212121',
'send_button_font_color' => '#212121',
'chat_input_font_color' => '#212121',
'chatbot_background_color' => '#212121',
'icon_color' => '#fff',
'enable_woocommerce_integration' => '0',
'link_target_toggle' => 'off',
'pre_chat_message' => 'Hey there! Ask me anything!',
// New fields for Loops Integration
'loops_api_key' => '',
'loops_mailing_list' => '',
'triggered_phrase_response' => 'Would you like to join our mailing list? Please provide your email below.',
'email_capture_response' => 'Thank you for providing your email! You\'ve been added to our list.',
'popular_question_1' => '',
'popular_question_2' => '',
'popular_question_3' => '',
'pdf_intent_trigger_text' => "Please provide the URL to the PDF you'd like to discuss.",
'pdf_intent_success_text' => "I've processed the PDF. What questions do you have about it?",
'pdf_intent_error_text' => "Sorry, I couldn't process the PDF. Please ensure it's a valid file.",
'pdf_max_pages' => 69,
// Live Agent Integration
'live_agent_webhook_url' => '',
'live_agent_secret_key' => '',
'live_agent_bot_token' => '',
'live_agent_message_bg_color' => '#ffffff',
'live_agent_message_font_color' => '#333333',
'chat_toolbar_toggle' => 'off',
'mode_indicator_bg_color' => '#767676',
'mode_indicator_font_color' => '#ffffff',
'toolbar_icon_color' => '#212121',
);
// Merge existing options with defaults
$existing_options = get_option('mxchat_options', array());
$merged_options = wp_parse_args($existing_options, $default_options);
// Update the options if they have changed
if ($existing_options !== $merged_options) {
update_option('mxchat_options', $merged_options);
}
// Update the $this->options property
$this->options = $merged_options;
}
public function mxchat_add_plugin_page() {
// Main menu page
add_menu_page(
'MxChat Settings',
'MxChat',
'manage_options',
'mxchat-max',
array($this, 'mxchat_create_admin_page'),
'dashicons-testimonial',
6
);
// Submenu page for Knowledge
add_submenu_page(
'mxchat-max',
'Prompts',
'Knowledge',
'manage_options',
'mxchat-prompts',
array($this, 'mxchat_create_prompts_page')
);
// Submenu page for Chat Transcripts
add_submenu_page(
'mxchat-max', // Corrected parent slug to match the main menu
'Chat Transcripts',
'Transcripts',
'manage_options',
'mxchat-transcripts',
array($this, 'mxchat_create_transcripts_page') // Prefixed function name with mxchat_
);
// Submenu page for Intents
add_submenu_page(
'mxchat-max', // Parent slug
'MxChat Intents', // Page title
'Intents', // Menu title
'manage_options', // Capability
'mxchat-intents', // Menu slug
array($this, 'mxchat_intents_page_html') // Callback function
);
// Submenu page for Activation Key
add_submenu_page(
'mxchat-max',
'Pro Upgrade',
'Pro Upgrade',
'manage_options',
'mxchat-activation',
array($this, 'mxchat_create_activation_page')
);
}
public function mxchat_handle_content_submission() {
// Check if the form was submitted and the user has sufficient permissions
if (!isset($_POST['submit_content']) || !current_user_can('manage_options')) {
return;
}
// Verify the nonce field for security
$nonce = isset($_POST['mxchat_submit_content_nonce']) ? sanitize_text_field(wp_unslash($_POST['mxchat_submit_content_nonce'])) : '';
if (!wp_verify_nonce($nonce, 'mxchat_submit_content_action')) {
wp_die('Nonce verification failed.');
}
// Sanitize the content input
$article_content = sanitize_textarea_field($_POST['article_content']);
// Sanitize the URL input (optional URL)
$article_url = isset($_POST['article_url']) ? esc_url_raw($_POST['article_url']) : ''; // Default to empty if not provided
// Generate the embedding vector for the content
$embedding_vector = $this->mxchat_generate_embedding($article_content);
global $wpdb;
$table_name = $wpdb->prefix . 'mxchat_system_prompt_content';
// Check if the 'source_url' column exists in the table and add it if it doesn't
if ($wpdb->get_var($wpdb->prepare("SHOW COLUMNS FROM {$table_name} LIKE %s", 'source_url')) != 'source_url') {
// Use wpdb::query and a prepared statement to avoid SQL injection
$wpdb->query($wpdb->prepare("ALTER TABLE {$table_name} ADD source_url VARCHAR(255) DEFAULT ''"));
}
if (is_array($embedding_vector)) {
// Serialize the embedding vector before storing it
$embedding_vector_serialized = serialize($embedding_vector);
// Insert the content, embedding vector, and source URL into the database, using a prepared statement
$inserted = $wpdb->insert(
$table_name,
array(
'article_content' => $article_content,
'embedding_vector' => $embedding_vector_serialized,
'source_url' => $article_url, // Insert the URL, empty string if not provided
),
array(
'%s', // Format for article_content (string)
'%s', // Format for embedding_vector (serialized string)
'%s', // Format for source_url (string)
)
);
if ($inserted === false) {
//error_log('Error inserting content: ' . $wpdb->last_error);
set_transient('mxchat_admin_notice_error', 'Error inserting content into the database. Please try again.', 30);
} else {
set_transient('mxchat_admin_notice_success', 'Content successfully submitted!', 30);
}
} else {
//error_log('Embedding generation failed for article content: ' . $article_content);
set_transient('mxchat_admin_notice_error', 'Embedding generation failed. Please ensure your API key is correct and try again.', 30);
}
// Redirect after setting the transient
wp_safe_redirect(esc_url(admin_url('admin.php?page=mxchat-prompts')));
exit;
}
public function mxchat_display_admin_notice() {
// Success notice
if ($message = get_transient('mxchat_admin_notice_success')) {
?>
is_activated): ?>
Limited-time offer: Get a lifetime MxChat Pro license for just $49.97 until 01.01.25! After that, it switches to an annual license at $99.97/year. Purchase now and be grandfathered into the lifetime deal!
Upgrade to MxChat Pro today!
MxChat
prefix . 'mxchat_system_prompt_content';
// Display success message if all prompts were deleted
if (isset($_GET['all_deleted']) && $_GET['all_deleted'] === 'true') {
echo '' . esc_html__('All knowledge has been deleted successfully.', 'mxchat') . '
';
}
// Set up pagination and search query
$nonce = isset($_GET['_wpnonce']) ? sanitize_text_field($_GET['_wpnonce']) : '';
$search_query = (!empty($nonce) && wp_verify_nonce($nonce, 'mxchat_prompts_search_nonce') && isset($_GET['search'])) ? sanitize_text_field($_GET['search']) : '';
$current_page = isset($_GET['paged']) ? absint($_GET['paged']) : 1;
$per_page = 10;
$offset = ($current_page - 1) * $per_page;
// Modify query to handle search input
$sql_search = "";
if ($search_query) {
$sql_search = $wpdb->prepare("WHERE article_content LIKE %s", '%' . $wpdb->esc_like($search_query) . '%');
}
// Retrieve total number of prompts, considering search filter
$total_prompts = $wpdb->get_var("SELECT COUNT(*) FROM {$table_name} {$sql_search}");
$total_pages = ceil($total_prompts / $per_page);
// Retrieve prompts from the database
$prompts = $wpdb->get_results(
$wpdb->prepare(
"SELECT * FROM {$table_name} {$sql_search} ORDER BY timestamp DESC LIMIT %d OFFSET %d",
$per_page,
$offset
)
);
?>
Submit Content
Submitting content, please wait...
items
add_query_arg(array('paged' => '%#%', 'search' => urlencode($search_query), '_wpnonce' => wp_create_nonce('mxchat_prompts_search_nonce')), admin_url('admin.php?page=mxchat-prompts')),
'format' => '',
'prev_text' => __('« Previous'),
'next_text' => __('Next »'),
'total' => $total_pages,
'current' => $current_page,
));
if ($page_links) {
echo '
' . wp_kses_post($page_links) . '
';
}
?>
prefix . 'mxchat_system_prompt_content';
// Delete all prompts from the table
$wpdb->query("DELETE FROM {$table_name}");
// Clear relevant cache
wp_cache_delete('all_prompts', 'mxchat_prompts');
// Redirect back with a success message
$redirect_url = add_query_arg(array(
'page' => 'mxchat-prompts',
'all_deleted' => 'true'
), admin_url('admin.php'));
wp_safe_redirect($redirect_url);
exit;
}
// Single Prompt Deletion
public function mxchat_handle_delete_prompt() {
// Sanitize and validate nonce
$nonce = isset($_GET['_wpnonce']) ? sanitize_text_field(wp_unslash($_GET['_wpnonce'])) : '';
if (empty($nonce) || !wp_verify_nonce($nonce, 'mxchat_delete_prompt_nonce')) {
wp_die('Nonce verification failed.');
}
// Check permissions
if (!current_user_can('manage_options')) {
wp_die('You do not have sufficient permissions to delete prompts.');
}
// Validate and sanitize ID parameter
$id = isset($_GET['id']) ? intval($_GET['id']) : 0;
if ($id <= 0) {
wp_die('Invalid prompt ID.');
}
global $wpdb;
$table_name = $wpdb->prefix . 'mxchat_system_prompt_content';
// Clear cache and delete prompt
wp_cache_delete('prompt_' . $id, 'mxchat_prompts');
$wpdb->delete($table_name, array('id' => $id), array('%d'));
wp_safe_redirect(add_query_arg(array('page' => 'mxchat-prompts', 'deleted' => 'true'), admin_url('admin.php')));
exit;
}
public function mxchat_generate_embedding($text) {
$options = get_option('mxchat_options');
$api_key = $options['api_key'] ?? 'default_api_key';
$response = wp_remote_post('https://api.openai.com/v1/embeddings', array(
'body' => wp_json_encode(array(
'model' => 'text-embedding-ada-002',
'input' => $text
)),
'headers' => array(
'Authorization' => 'Bearer ' . $api_key,
'Content-Type' => 'application/json'
),
));
if (is_wp_error($response)) {
return null;
}
$response_data = json_decode(wp_remote_retrieve_body($response), true);
return $response_data['data'][0]['embedding'] ?? null;
}
public function mxchat_delete_chat_history() {
if (!current_user_can('manage_options')) {
echo wp_json_encode(['error' => 'You do not have sufficient permissions.']);
wp_die();
}
check_ajax_referer('mxchat_delete_chat_history', 'security');
global $wpdb;
$table_name = $wpdb->prefix . 'mxchat_chat_transcripts';
if (isset($_POST['delete_session_ids']) && is_array($_POST['delete_session_ids'])) {
foreach ($_POST['delete_session_ids'] as $session_id) {
$session_id_sanitized = sanitize_text_field($session_id);
// Clear relevant cache before deletion
$cache_key = 'chat_session_' . $session_id_sanitized;
wp_cache_delete($cache_key, 'mxchat_chat_sessions');
// Perform the deletion
$wpdb->delete($table_name, ['session_id' => $session_id_sanitized]);
}
// Optionally, clear a general cache if you have one
wp_cache_delete('all_chat_sessions', 'mxchat_chat_sessions');
echo wp_json_encode(['success' => 'Selected chat sessions have been deleted.']);
} else {
echo wp_json_encode(['error' => 'No chat sessions selected for deletion.']);
}
wp_die();
}
public function mxchat_save_inline_prompt() {
// Check for nonce security
check_ajax_referer('mxchat_save_inline_nonce');
// Verify permissions
if (!current_user_can('manage_options')) {
wp_send_json_error('Permission denied.');
return;
}
global $wpdb;
$table_name = $wpdb->prefix . 'mxchat_system_prompt_content';
// Validate and sanitize input data
$prompt_id = isset($_POST['id']) ? absint($_POST['id']) : 0;
$article_content = isset($_POST['article_content']) ? sanitize_textarea_field($_POST['article_content']) : '';
$article_url = isset($_POST['article_url']) ? esc_url_raw($_POST['article_url']) : '';
if ($prompt_id > 0 && !empty($article_content)) {
// Re-generate the embedding vector for the updated content
$embedding_vector = $this->mxchat_generate_embedding($article_content);
if (is_array($embedding_vector)) {
// Serialize the embedding vector before storing it
$embedding_vector_serialized = serialize($embedding_vector);
// Update the prompt in the database
$updated = $wpdb->update(
$table_name,
array(
'article_content' => $article_content,
'embedding_vector' => $embedding_vector_serialized,
'source_url' => $article_url,
),
array('id' => $prompt_id),
array('%s', '%s', '%s'),
array('%d')
);
if ($updated !== false) {
wp_send_json_success();
} else {
wp_send_json_error('Database update failed.');
}
} else {
wp_send_json_error('Embedding generation failed.');
}
} else {
wp_send_json_error('Invalid data.');
}
}
public function mxchat_fetch_chat_history() {
global $wpdb;
$table_name = $wpdb->prefix . 'mxchat_chat_transcripts';
if (!current_user_can('manage_options')) {
echo esc_html__('You do not have sufficient permissions to view this page.', 'mxchat');
wp_die();
}
$chat_transcripts = $wpdb->get_results(
$wpdb->prepare("SELECT * FROM {$table_name} ORDER BY timestamp ASC")
);
if (empty($chat_transcripts)) {
echo esc_html__('No chat history available.', 'mxchat');
wp_die();
}
ob_start();
$current_session_id = '';
echo '';
foreach ($chat_transcripts as $transcript) {
if ($current_session_id !== $transcript->session_id) {
if ($current_session_id !== '') {
echo '
';
}
$current_session_id = sanitize_text_field($transcript->session_id);
echo '';
echo '';
echo '
';
}
$formatted_timestamp = date_i18n('g:i a', strtotime($transcript->timestamp));
$role = $transcript->role;
$message_class = '';
// Check if it's an automated test message
if (strpos($transcript->user_identifier, 'Curious Customer') !== false ||
strpos($transcript->user_identifier, 'Technical Expert') !== false ||
strpos($transcript->user_identifier, 'Feature Explorer') !== false) {
$message_class = 'user-message';
$display_role = $transcript->user_identifier; // Show the agent type
} else if ($role === 'user' || filter_var($transcript->user_identifier, FILTER_VALIDATE_IP)) {
$message_class = 'user-message';
// Format display role (IP address or email)
if (!empty($transcript->user_email)) {
$display_role = sanitize_email($transcript->user_email);
} else {
$user_identifier = sanitize_text_field($transcript->user_identifier);
if (filter_var($user_identifier, FILTER_VALIDATE_IP)) {
$display_role = preg_replace('/\.\d+$/', '.xxx', $user_identifier);
} else {
$display_role = $user_identifier;
}
}
} elseif ($role === 'agent') {
$message_class = 'agent-message';
$display_role = 'Agent';
} else {
$message_class = 'bot-message';
$display_role = 'Bot';
}
echo '
';
echo '';
echo '
' . wp_kses_post($transcript->message) . '
';
echo '
' . esc_html($formatted_timestamp) . '
';
echo '
';
}
echo '
';
$output = ob_get_clean();
echo $output;
wp_die();
}
public function mxchat_create_activation_page() {
$license_status = get_option('mxchat_license_status', 'inactive');
$license_error = get_option('mxchat_license_error', '');
?>
MxChat Pro: Activation
License Status:
prefix . 'mxchat_intents';
$page = isset( $_GET['paged'] ) ? max( 1, intval( $_GET['paged'] ) ) : 1;
$per_page = 20;
$offset = ( $page - 1 ) * $per_page;
// Build the WHERE clause based on filters
$where = '1=1';
$search_term = isset( $_GET['s'] ) ? trim( $_GET['s'] ) : '';
$callback_filter = isset( $_GET['callback_filter'] ) ? sanitize_text_field( $_GET['callback_filter'] ) : '';
if ( $search_term ) {
$search_term_like = '%' . $wpdb->esc_like( $search_term ) . '%';
$where .= $wpdb->prepare( ' AND (intent_label LIKE %s OR phrases LIKE %s)', $search_term_like, $search_term_like );
}
if ( $callback_filter ) {
$where .= $wpdb->prepare( ' AND callback_function = %s', $callback_filter );
}
// Get total count for pagination
$total_intents = $wpdb->get_var( "SELECT COUNT(*) FROM $table_name WHERE $where" );
$total_pages = ceil( $total_intents / $per_page );
// Fetch intents with pagination and filters
$intents = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $table_name WHERE $where LIMIT %d OFFSET %d", $per_page, $offset ) );
// Get available callback functions with 'pro_only' flag
$available_callbacks = $this->mxchat_get_available_callbacks();
?>
$callback_data ) : ?>
is_activated && $pro_only ) ? 'disabled' : '';
$label_suffix = ( ! $this->is_activated && $pro_only ) ? ' (Pro Only)' : '';
?>
>
$callback_data ) : ?>
>
prefix . 'mxchat_intents';
$intent_id = intval($_POST['intent_id']);
$threshold_percentage = max(70, min(95, intval($_POST['intent_threshold'])));
$similarity_threshold = $threshold_percentage / 100;
$wpdb->update(
$table_name,
['similarity_threshold' => $similarity_threshold],
['id' => $intent_id],
['%f'],
['%d']
);
}
wp_safe_redirect(admin_url('admin.php?page=mxchat-intents'));
exit;
}
public function mxchat_handle_add_intent() {
if ( ! current_user_can( 'manage_options' ) ) {
wp_die( esc_html__('Unauthorized user', 'mxchat') );
}
check_admin_referer('mxchat_add_intent_nonce');
global $wpdb;
$table_name = $wpdb->prefix . 'mxchat_intents';
$intent_label = isset($_POST['intent_label']) ? sanitize_text_field($_POST['intent_label']) : '';
$phrases_input = isset($_POST['phrases']) ? sanitize_textarea_field($_POST['phrases']) : '';
$callback_function = isset($_POST['callback_function']) ? sanitize_text_field($_POST['callback_function']) : '';
$default_threshold = 0.85;
if (empty($intent_label) || empty($callback_function) || empty($phrases_input)) {
wp_die( esc_html__('Invalid input. Please ensure all fields are filled out.', 'mxchat') );
}
$available_callbacks = $this->mxchat_get_available_callbacks();
if (!array_key_exists($callback_function, $available_callbacks)) {
wp_die( esc_html__('Invalid callback function selected.', 'mxchat') );
}
$is_pro_only = $available_callbacks[$callback_function]['pro_only'];
if ($is_pro_only && !$this->is_activated) {
wp_die( esc_html__('This callback function is available in the Pro version only.', 'mxchat') );
}
$phrases_array = array_map('sanitize_text_field', array_filter(array_map('trim', explode(',', $phrases_input))));
if (empty($phrases_array)) {
wp_die( esc_html__('Please enter at least one valid phrase.', 'mxchat') );
}
$vectors = [];
foreach ($phrases_array as $phrase) {
$embedding_vector = $this->mxchat_generate_embedding($phrase, $this->options['api_key']);
if (is_array($embedding_vector)) {
$vectors[] = $embedding_vector;
} else {
wp_die( esc_html__('Error generating embedding for phrase: ', 'mxchat') . esc_html($phrase) );
}
}
if (!empty($vectors)) {
$combined_vector = $this->mxchat_average_vectors($vectors);
$serialized_vector = maybe_serialize($combined_vector);
$result = $wpdb->insert($table_name, [
'intent_label' => $intent_label,
'phrases' => implode(', ', $phrases_array),
'embedding_vector' => $serialized_vector,
'callback_function' => $callback_function,
'similarity_threshold' => $default_threshold,
]);
if ($result === false) {
wp_die( esc_html__('Database error: ', 'mxchat') . esc_html($wpdb->last_error) );
}
} else {
wp_die( esc_html__('No valid embeddings generated. Please check your phrases.', 'mxchat') );
}
wp_safe_redirect(admin_url('admin.php?page=mxchat-intents'));
exit;
}
private function mxchat_get_available_callbacks() {
return [
'mxchat_handle_email_capture' => [
'label' => 'Email Capture',
'pro_only' => false,
],
'mxchat_handle_product_inquiry' => [
'label' => 'Show Product Card',
'pro_only' => true,
],
'mxchat_handle_order_history' => [
'label' => 'Order History',
'pro_only' => true,
],
'mxchat_generate_image' => [
'label' => 'Generate Image',
'pro_only' => true,
],
'mxchat_handle_search_request' => [
'label' => 'Brave Web Search',
'pro_only' => false,
],
'mxchat_handle_image_search_request' => [
'label' => 'Brave Image Search',
'pro_only' => false,
],
'mxchat_handle_add_to_cart_intent' => [
'label' => 'Add to Cart',
'pro_only' => true,
],
'mxchat_handle_checkout_intent' => [
'label' => 'Proceed to Checkout',
'pro_only' => true,
],
'mxchat_handle_pdf_discussion' => [
'label' => 'Chat with PDF',
'pro_only' => true,
],
'mxchat_handle_product_recommendations' => [
'label' => 'Product Recommendations',
'pro_only' => true,
],
'mxchat_live_agent_handover' => [
'label' => 'Live Agent',
'pro_only' => true,
],
'mxchat_handle_switch_to_chatbot_intent' => [
'label' => 'Back to Chatbot',
'pro_only' => true,
],
];
}
private function mxchat_average_vectors($vectors) {
$vector_length = count($vectors[0]);
$sum_vector = array_fill(0, $vector_length, 0);
foreach ($vectors as $vector) {
for ($i = 0; $i < $vector_length; $i++) {
$sum_vector[$i] += $vector[$i];
}
}
// Divide each component by the number of vectors to get the average
$num_vectors = count($vectors);
for ($i = 0; $i < $vector_length; $i++) {
$sum_vector[$i] /= $num_vectors;
}
return $sum_vector;
}
public function mxchat_handle_delete_intent() {
if ( ! current_user_can( 'manage_options' ) ) {
wp_die( esc_html__('Unauthorized user', 'mxchat') );
}
check_admin_referer('mxchat_delete_intent_nonce');
if (isset($_POST['intent_id'])) {
global $wpdb;
$table_name = $wpdb->prefix . 'mxchat_intents';
$intent_id = intval($_POST['intent_id']);
$wpdb->delete($table_name, ['id' => $intent_id], ['%d']);
}
wp_safe_redirect(admin_url('admin.php?page=mxchat-intents'));
exit;
}
public function mxchat_page_init() {
// Register settings
register_setting(
'mxchat_option_group',
'mxchat_options',
array($this, 'mxchat_sanitize')
);
register_setting(
'mxchat_option_group',
'mxchat_similarity_threshold',
array(
'type' => 'number',
'sanitize_callback' => function($value) {
$value = absint($value); // Ensure it's an integer
return min(max($value, 70), 85); // Enforce range
},
'default' => 80,
)
);
// Chatbot Settings Section
add_settings_section(
'mxchat_chatbot_section',
'Chatbot Settings',
null,
'mxchat-chatbot'
);
// Similarity Threshold Slider
add_settings_field(
'similarity_threshold', // Field ID
'Similarity Threshold', // Field title
array($this, 'mxchat_similarity_threshold_callback'), // Callback function
'mxchat-chatbot', // Page
'mxchat_chatbot_section' // Section
);
// Existing fields...
add_settings_field(
'api_key',
'OpenAI API Key',
array($this, 'api_key_callback'),
'mxchat-chatbot',
'mxchat_chatbot_section'
);
add_settings_field(
'xai_api_key',
'X.AI API Key',
array($this, 'xai_api_key_callback'),
'mxchat-chatbot',
'mxchat_chatbot_section'
);
add_settings_field(
'claude_api_key',
'Claude API Key',
array($this, 'claude_api_key_callback'),
'mxchat-chatbot',
'mxchat_chatbot_section'
);
add_settings_field(
'system_prompt_instructions',
'AI Instructions',
array($this, 'system_prompt_instructions_callback'),
'mxchat-chatbot',
'mxchat_chatbot_section'
);
add_settings_field(
'model',
'Model',
array($this, 'mxchat_model_callback'),
'mxchat-chatbot',
'mxchat_chatbot_section'
);
add_settings_field(
'top_bar_title',
'Top Bar Title',
array($this, 'mxchat_top_bar_title_callback'),
'mxchat-chatbot',
'mxchat_chatbot_section'
);
add_settings_field(
'intro_message',
'Introductory Message',
array($this, 'mxchat_intro_message_callback'),
'mxchat-chatbot',
'mxchat_chatbot_section'
);
add_settings_field(
'input_copy',
'Input Copy',
array($this, 'mxchat_input_copy_callback'),
'mxchat-chatbot',
'mxchat_chatbot_section'
);
add_settings_field(
'rate_limit_logged_in',
__('Rate Limit for Logged-in Users', 'mxchat'),
array($this, 'mxchat_rate_limit_logged_in_callback'),
'mxchat-chatbot',
'mxchat_chatbot_section'
);
add_settings_field(
'rate_limit_logged_out',
__('Rate Limit for Logged-out Users', 'mxchat'),
array($this, 'mxchat_rate_limit_logged_out_callback'),
'mxchat-chatbot',
'mxchat_chatbot_section'
);
add_settings_field(
'rate_limit_message',
'Rate Limit Message',
array($this, 'mxchat_rate_limit_message_callback'),
'mxchat-chatbot',
'mxchat_chatbot_section'
);
add_settings_field(
'pre_chat_message',
'Pre-Chat Message',
array($this, 'mxchat_pre_chat_message_callback'),
'mxchat-chatbot',
'mxchat_chatbot_section'
);
add_settings_field(
'append_to_body',
'Append Chat Widget to Body',
array($this, 'mxchat_append_to_body_callback'),
'mxchat-chatbot',
'mxchat_chatbot_section'
);
add_settings_field(
'privacy_toggle',
'Toggle Privacy Notice',
array($this, 'mxchat_privacy_toggle_callback'),
'mxchat-chatbot',
'mxchat_chatbot_section'
);
add_settings_field(
'complianz_toggle',
'Enable Complianz',
array($this, 'mxchat_complianz_toggle_callback'),
'mxchat-chatbot',
'mxchat_chatbot_section'
);
add_settings_field(
'link_target_toggle',
'Open Links in a New Tab',
array($this, 'mxchat_link_target_toggle_callback'),
'mxchat-chatbot',
'mxchat_chatbot_section'
);
add_settings_field(
'chat_persistence_toggle',
'Enable Chat Persistence',
array($this, 'mxchat_chat_persistence_toggle_callback'),
'mxchat-chatbot',
'mxchat_chatbot_section'
);
add_settings_field(
'popular_question_1',
'Popular Question 1',
array($this, 'mxchat_popular_question_1_callback'),
'mxchat-chatbot',
'mxchat_chatbot_section'
);
add_settings_field(
'popular_question_2',
'Popular Question 2',
array($this, 'mxchat_popular_question_2_callback'),
'mxchat-chatbot',
'mxchat_chatbot_section'
);
add_settings_field(
'popular_question_3',
'Popular Question 3',
array($this, 'mxchat_popular_question_3_callback'),
'mxchat-chatbot',
'mxchat_chatbot_section'
);
add_settings_field(
'additional_popular_questions',
'Additional Popular Questions',
array($this, 'mxchat_additional_popular_questions_callback'),
'mxchat-chatbot',
'mxchat_chatbot_section'
);
// WooCommerce Settings Section
add_settings_section(
'mxchat_woocommerce_section',
'WooCommerce Settings',
null,
'mxchat-embed'
);
// Loops Settings Section
add_settings_section(
'mxchat_loops_section',
'Loops Settings',
null,
'mxchat-embed'
);
// WooCommerce Settings Fields
add_settings_field(
'enable_woocommerce_integration',
'Automatically Embed Products',
array($this, 'mxchat_enable_woocommerce_integration_callback'),
'mxchat-embed',
'mxchat_woocommerce_section'
);
add_settings_field(
'woocommerce_consumer_key',
'WooCommerce Consumer Key',
array($this, 'mxchat_woocommerce_consumer_key_callback'),
'mxchat-embed',
'mxchat_woocommerce_section'
);
add_settings_field(
'woocommerce_consumer_secret',
'WooCommerce Consumer Secret',
array($this, 'mxchat_woocommerce_consumer_secret_callback'),
'mxchat-embed',
'mxchat_woocommerce_section'
);
// Loops Settings Fields
add_settings_field(
'loops_api_key',
'Loops API Key',
array($this, 'mxchat_loops_api_key_callback'),
'mxchat-embed',
'mxchat_loops_section'
);
add_settings_field(
'loops_mailing_list',
'Loops Mailing List',
array($this, 'mxchat_loops_mailing_list_callback'),
'mxchat-embed',
'mxchat_loops_section'
);
add_settings_field(
'triggered_phrase_response',
'Triggered Phrase Response',
array($this, 'mxchat_triggered_phrase_response_callback'),
'mxchat-embed',
'mxchat_loops_section'
);
add_settings_field(
'email_capture_response',
'Email Capture Response',
array($this, 'mxchat_email_capture_response_callback'),
'mxchat-embed',
'mxchat_loops_section'
);
// Brave Search Settings Fields
add_settings_section(
'mxchat_brave_section',
__('Brave Search Settings', 'mxchat'),
array($this, 'mxchat_brave_section_callback'),
'mxchat-embed'
);
add_settings_field(
'brave_api_key',
__('Brave API Key', 'mxchat'),
array($this, 'mxchat_brave_api_key_callback'),
'mxchat-embed',
'mxchat_brave_section'
);
add_settings_field(
'brave_image_count',
__('Number of Images to Return', 'mxchat'),
array($this, 'mxchat_brave_image_count_callback'),
'mxchat-embed',
'mxchat_brave_section'
);
add_settings_field(
'brave_safe_search',
__('Safe Search', 'mxchat'),
array($this, 'mxchat_brave_safe_search_callback'),
'mxchat-embed',
'mxchat_brave_section'
);
add_settings_field(
'brave_news_count',
__('Number of News Articles', 'mxchat'),
array($this, 'mxchat_brave_news_count_callback'),
'mxchat-embed',
'mxchat_brave_section'
);
add_settings_field(
'brave_country',
__('Country', 'mxchat'),
array($this, 'mxchat_brave_country_callback'),
'mxchat-embed',
'mxchat_brave_section'
);
add_settings_field(
'brave_language',
__('Language', 'mxchat'),
array($this, 'mxchat_brave_language_callback'),
'mxchat-embed',
'mxchat_brave_section'
);
// Chat with PDF Intent Settings Fields
add_settings_section(
'mxchat_pdf_intent_section',
__('Toolbar Settings & Intents', 'mxchat'),
array($this, 'mxchat_pdf_intent_section_callback'),
'mxchat-embed'
);
add_settings_field(
'chat_toolbar_toggle',
__('Show Chat Toolbar', 'mxchat'),
array($this, 'mxchat_chat_toolbar_toggle_callback'),
'mxchat-embed',
'mxchat_pdf_intent_section'
);
add_settings_field(
'pdf_intent_trigger_text',
__('Intent Trigger Text', 'mxchat'),
array($this, 'mxchat_pdf_intent_trigger_text_callback'),
'mxchat-embed',
'mxchat_pdf_intent_section'
);
add_settings_field(
'pdf_intent_success_text',
__('Success Text', 'mxchat'),
array($this, 'mxchat_pdf_intent_success_text_callback'),
'mxchat-embed',
'mxchat_pdf_intent_section'
);
add_settings_field(
'pdf_intent_error_text',
__('Error Text', 'mxchat'),
array($this, 'mxchat_pdf_intent_error_text_callback'),
'mxchat-embed',
'mxchat_pdf_intent_section'
);
// Add PDF Maximum Pages Field
add_settings_field(
'pdf_max_pages',
__('Maximum PDF Pages', 'mxchat'),
array($this, 'mxchat_pdf_max_pages_callback'),
'mxchat-embed',
'mxchat_pdf_intent_section'
);
// Live Agent Settings Fields
add_settings_section(
'mxchat_live_agent_section',
__('Live Agent Settings', 'mxchat'),
array($this, 'mxchat_live_agent_section_callback'),
'mxchat-embed'
);
// Live Agent Status Fields (add at top of live agent settings)
add_settings_field(
'live_agent_status',
__('Live Agent Status', 'mxchat'),
array($this, 'mxchat_live_agent_status_callback'),
'mxchat-embed',
'mxchat_live_agent_section'
);
add_settings_field(
'live_agent_notification_message',
__('Notification Message', 'mxchat'),
array($this, 'mxchat_live_agent_notification_message_callback'),
'mxchat-embed',
'mxchat_live_agent_section'
);
add_settings_field(
'live_agent_away_message',
__('Away Message', 'mxchat'),
array($this, 'mxchat_live_agent_away_message_callback'),
'mxchat-embed',
'mxchat_live_agent_section'
);
add_settings_field(
'live_agent_webhook_url',
__('Slack Webhook URL', 'mxchat'),
array($this, 'mxchat_live_agent_webhook_url_callback'),
'mxchat-embed',
'mxchat_live_agent_section'
);
add_settings_field(
'live_agent_secret_key',
__('Slack Secret Key', 'mxchat'),
array($this, 'mxchat_live_agent_secret_key_callback'),
'mxchat-embed',
'mxchat_live_agent_section'
);
// Live Agent Integration Fields
add_settings_field(
'live_agent_bot_token',
__('Slack Bot OAuth Token', 'mxchat'),
array($this, 'mxchat_live_agent_bot_token_callback'),
'mxchat-embed',
'mxchat_live_agent_section'
);
// Theme Settings Section
add_settings_section(
'mxchat_theme_section',
'Theme Settings',
null,
'mxchat-theme'
);
add_settings_field(
'close_button_color',
'Close Button & Title Color',
array($this, 'mxchat_close_button_color_callback'),
'mxchat-theme',
'mxchat_theme_section'
);
add_settings_field(
'chatbot_bg_color',
'Chatbot Background Color',
array($this, 'mxchat_chatbot_bg_color_callback'),
'mxchat-theme',
'mxchat_theme_section'
);
add_settings_field(
'user_message_bg_color',
'User Message Background Color',
array($this, 'mxchat_user_message_bg_color_callback'),
'mxchat-theme',
'mxchat_theme_section'
);
add_settings_field(
'user_message_font_color',
'User Message Font Color',
array($this, 'mxchat_user_message_font_color_callback'),
'mxchat-theme',
'mxchat_theme_section'
);
add_settings_field(
'bot_message_bg_color',
'Bot Message Background Color',
array($this, 'mxchat_bot_message_bg_color_callback'),
'mxchat-theme',
'mxchat_theme_section'
);
add_settings_field(
'bot_message_font_color',
'Bot Message Font Color',
array($this, 'mxchat_bot_message_font_color_callback'),
'mxchat-theme',
'mxchat_theme_section'
);
add_settings_field(
'top_bar_bg_color',
'Top Bar Background Color',
array($this, 'mxchat_top_bar_bg_color_callback'),
'mxchat-theme',
'mxchat_theme_section'
);
add_settings_field(
'send_button_font_color',
'Send Button Color',
array($this, 'mxchat_send_button_font_color_callback'),
'mxchat-theme',
'mxchat_theme_section'
);
add_settings_field(
'chat_input_font_color',
'Chat Input Font Color',
array($this, 'mxchat_chat_input_font_color_callback'),
'mxchat-theme',
'mxchat_theme_section'
);
add_settings_field(
'chatbot_background_color',
'Floating Widget Background Color',
array($this, 'mxchat_chatbot_background_color_callback'),
'mxchat-theme',
'mxchat_theme_section'
);
add_settings_field(
'icon_color',
'Chatbot Icon Color',
array($this, 'mxchat_icon_color_callback'),
'mxchat-theme',
'mxchat_theme_section'
);
add_settings_field(
'custom_icon',
'Custom Chatbot Icon (PNG)',
array($this, 'mxchat_custom_icon_callback'),
'mxchat-theme',
'mxchat_theme_section'
);
add_settings_field(
'live_agent_message_bg_color',
'Live Agent Background Color',
array($this, 'mxchat_live_agent_message_bg_color_callback'),
'mxchat-theme',
'mxchat_theme_section'
);
add_settings_field(
'live_agent_message_font_color',
'Live Agent Font Color',
array($this, 'mxchat_live_agent_message_font_color_callback'),
'mxchat-theme',
'mxchat_theme_section'
);
// Mode Indicator Background Color
add_settings_field(
'mode_indicator_bg_color',
'Mode Indicator Background Color',
array($this, 'mxchat_mode_indicator_bg_color_callback'),
'mxchat-theme',
'mxchat_theme_section'
);
// Mode Indicator Font Color
add_settings_field(
'mode_indicator_font_color',
'Mode Indicator Font Color',
array($this, 'mxchat_mode_indicator_font_color_callback'),
'mxchat-theme',
'mxchat_theme_section'
);
add_settings_field(
'toolbar_icon_color',
'Toolbar Icon Color',
array($this, 'mxchat_toolbar_icon_color_callback'),
'mxchat-theme',
'mxchat_theme_section'
);
// General Settings Section
add_settings_section(
'mxchat_general_section',
'Frequently Asked Questions (FAQ)',
null,
'mxchat-general'
);
}
public function mxchat_handle_activate_license() {
check_ajax_referer('mxchat_activate_license_nonce', 'security');
$license_key = isset($_POST['mxchat_activation_key']) ? sanitize_text_field($_POST['mxchat_activation_key']) : '';
$customer_email = isset($_POST['mxchat_pro_email']) ? sanitize_email($_POST['mxchat_pro_email']) : '';
if (empty($license_key) || empty($customer_email)) {
wp_send_json_error('Email or License Key is missing');
}
$product_id = 'MxChatPRO';
$response = wp_remote_get("http://mxchat.ai/?wc-api=software-api&request=activation&email={$customer_email}&license_key={$license_key}&product_id={$product_id}");
if (is_wp_error($response)) {
wp_send_json_error('Activation failed due to a server error');
}
$body = wp_remote_retrieve_body($response);
$data = json_decode($body);
if ($data && isset($data->activated) && $data->activated) {
update_option('mxchat_license_status', 'active');
update_option('mxchat_pro_email', $customer_email);
update_option('mxchat_activation_key', $license_key);
wp_send_json_success();
} else {
$error_message = isset($data->error) ? $data->error : 'Activation failed';
update_option('mxchat_license_status', 'inactive');
update_option('mxchat_license_error', $error_message);
wp_send_json_error($error_message);
}
}
public function mxchat_rate_limit_logged_in_callback() {
$rate_limits = array('1', '3', '5', '10', '15', '20', '100', 'unlimited'); // Add 'unlimited' option
$selected_rate_limit = isset($this->options['rate_limit_logged_in']) ? $this->options['rate_limit_logged_in'] : '100';
echo '';
echo '
';
foreach ($rate_limits as $limit) {
echo '' . esc_html($limit) . ' ';
}
echo ' ';
echo '
Set the rate limit for logged-in users.
';
echo '
';
}
public function mxchat_rate_limit_logged_out_callback() {
$rate_limits = array('1', '3', '5', '10', '15', '20', '100', 'unlimited'); // Add 'unlimited' option
$selected_rate_limit = isset($this->options['rate_limit_logged_out']) ? $this->options['rate_limit_logged_out'] : '10';
echo '';
echo '
';
foreach ($rate_limits as $limit) {
echo '' . esc_html($limit) . ' ';
}
echo ' ';
echo '
Set the rate limit for logged-out users.
';
echo '
';
}
public function mxchat_rate_limit_message_callback() {
// Remove the is_activated check and make it always enabled
echo '';
printf(
'%s ',
isset($this->options['rate_limit_message']) ? esc_textarea($this->options['rate_limit_message']) : 'Rate limit exceeded. Please try again later.'
);
echo '
';
}
public function mxchat_enable_woocommerce_integration_callback() {
$checked = isset($this->options['enable_woocommerce_integration']) && $this->options['enable_woocommerce_integration'] === '1' ? 'checked' : '';
$disabled = $this->is_activated ? '' : 'disabled';
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive';
echo '';
echo '
';
echo ' ';
echo ' ';
echo ' ';
if (!$this->is_activated) {
echo '
';
echo '
';
echo '
';
}
echo '
';
}
private function mxchat_add_option_field($id, $title, $callback = '') {
add_settings_field(
$id,
$title,
$callback ? array($this, $callback) : array($this, $id . '_callback'),
'mxchat-max',
'mxchat_setting_section_id',
$id === 'model' ? ['label_for' => 'model'] : []
);
}
public function api_key_callback() {
$apiKey = isset($this->options['api_key']) ? esc_attr($this->options['api_key']) : '';
echo ' ';
echo 'Show ';
}
public function xai_api_key_callback() {
// Check if the feature is activated (paid feature)
$disabled = $this->is_activated ? '' : 'disabled'; // Disable input if not activated
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive'; // CSS class to style the wrapper based on activation status
// Render the input field for the X.AI API key
echo '';
printf(
'
',
isset($this->options['xai_api_key']) ? esc_attr($this->options['xai_api_key']) : '',
$disabled
);
echo '
Show ';
// If the feature is not activated, show the overlay with a "Pro Only" message
if (!$this->is_activated) {
echo '
';
echo '
';
echo '
';
}
echo '
';
}
public function claude_api_key_callback() {
// Check if the feature is activated (paid feature)
$disabled = $this->is_activated ? '' : 'disabled'; // Disable input if not activated
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive'; // CSS class to style the wrapper based on activation status
// Render the input field for the Claude API key
echo '';
printf(
'
',
isset($this->options['claude_api_key']) ? esc_attr($this->options['claude_api_key']) : '',
$disabled
);
echo '
Show ';
// If the feature is not activated, show the overlay with a "Pro Only" message
if (!$this->is_activated) {
echo '
';
echo '
';
echo '
';
}
echo '
';
}
public function mxchat_woocommerce_consumer_key_callback() {
$disabled = $this->is_activated ? '' : 'disabled';
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive';
echo '';
printf(
'
',
isset($this->options['woocommerce_consumer_key']) ? esc_attr($this->options['woocommerce_consumer_key']) : '',
$disabled
);
if (!$this->is_activated) {
echo '
';
echo '
';
echo '
';
}
echo '
';
}
public function mxchat_woocommerce_consumer_secret_callback() {
$disabled = $this->is_activated ? '' : 'disabled';
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive';
echo '';
printf(
'
',
isset($this->options['woocommerce_consumer_secret']) ? esc_attr($this->options['woocommerce_consumer_secret']) : '',
$disabled
);
echo '
Show ';
if (!$this->is_activated) {
echo '
';
echo '
';
echo '
';
}
echo '
';
}
public function mxchat_loops_api_key_callback() {
$loops_api_key = isset($this->options['loops_api_key']) ? esc_attr($this->options['loops_api_key']) : '';
echo '';
printf(
' ',
$loops_api_key
);
echo 'Show ';
echo '
';
echo 'Enter your Loops API Key here. (See FAQ for details)
';
}
public function mxchat_loops_mailing_list_callback() {
// Retrieve Loops API key and lists
$loops_api_key = isset($this->options['loops_api_key']) ? $this->options['loops_api_key'] : '';
$selected_list = isset($this->options['loops_mailing_list']) ? $this->options['loops_mailing_list'] : '';
if ($loops_api_key) {
// Fetch lists from Loops API
$lists = $this->mxchat_fetch_loops_mailing_lists($loops_api_key);
if ($lists) {
echo '';
foreach ($lists as $list) {
echo '' . esc_html($list['name']) . ' ';
}
echo ' ';
} else {
echo 'No lists found. Please verify your API Key.
';
}
} else {
echo 'Enter a valid Loops API Key to load mailing lists.
';
}
}
public function mxchat_triggered_phrase_response_callback() {
$triggered_response = isset($this->options['triggered_phrase_response']) ? $this->options['triggered_phrase_response'] : '';
echo '' . esc_textarea($triggered_response) . ' ';
echo 'Enter the chatbot response when a trigger keyword is detected, prompting the user to share their email.
';
}
public function mxchat_email_capture_response_callback() {
$email_capture_response = isset($this->options['email_capture_response']) ? $this->options['email_capture_response'] : 'Thank you for providing your email! You\'ve been added to our list.';
echo '' . esc_textarea($email_capture_response) . ' ';
echo 'Enter the message to send when a user provides their email.
';
}
public function mxchat_pre_chat_message_callback() {
printf(
'%s ',
isset($this->options['pre_chat_message']) ? esc_textarea($this->options['pre_chat_message']) : ''
);
}
// Callback for AI Instructions textarea
public function system_prompt_instructions_callback() {
printf(
'%s ',
isset($this->options['system_prompt_instructions']) ? esc_textarea($this->options['system_prompt_instructions']) : ''
);
}
public function mxchat_model_callback() {
$models = array(
'X.AI Models' => array(
'grok-beta' => 'grok-beta (Early Beta)'
),
'Claude Models' => array(
'claude-3-5-sonnet-20241022' => 'Claude 3.5 Sonnet (Most Intelligent)',
'claude-3-opus-20240229' => 'Claude 3 Opus (Highly Complex Tasks)',
'claude-3-sonnet-20240229' => 'Claude 3 Sonnet (Balanced)',
'claude-3-haiku-20240307' => 'Claude 3 Haiku (Fastest)'
),
'OpenAI Models' => array(
'gpt-4o' => 'GPT-4o (Recommended)',
'gpt-4o-mini' => 'GPT-4o Mini (Fast and Lightweight)',
'gpt-4-turbo' => 'GPT-4 Turbo (High-Performance)',
'gpt-4' => 'GPT-4 (High Intelligence)',
'gpt-3.5-turbo' => 'GPT-3.5 Turbo (Affordable and Fast)'
)
);
$selected_model = isset($this->options['model']) ? $this->options['model'] : 'gpt-3.5-turbo';
echo '';
foreach ($models as $group_label => $group_models) {
echo '';
foreach ($group_models as $model_value => $model_label) {
// Disable if not activated for paid models (Claude or X.AI)
$disabled = (!$this->is_activated && ($group_label === 'X.AI Models' || $group_label === 'Claude Models')) ? 'disabled' : '';
$label_suffix = (!$this->is_activated && ($group_label === 'X.AI Models' || $group_label === 'Claude Models')) ? ' (Pro Only)' : '';
// Output the element
echo ' ' . esc_html($model_label . $label_suffix) . ' ';
}
echo ' ';
}
echo ' ';
}
public function mxchat_top_bar_title_callback() {
printf(
' ',
isset($this->options['top_bar_title']) ? esc_attr($this->options['top_bar_title']) : ''
);
}
public function mxchat_intro_message_callback() {
printf(
'%s ',
isset($this->options['intro_message']) ? esc_textarea($this->options['intro_message']) : 'Hello! How can I assist you today?'
);
}
public function mxchat_input_copy_callback() {
printf(
' ',
isset($this->options['input_copy']) ? esc_attr($this->options['input_copy']) : 'How can I assist?'
);
echo 'This is the placeholder text for the chat input field.
';
}
public function mxchat_close_button_color_callback() {
$disabled = $this->is_activated ? '' : 'disabled';
echo '';
printf(
'
',
isset($this->options['close_button_color']) ? esc_attr($this->options['close_button_color']) : '',
esc_attr($disabled)
);
if (!$this->is_activated) {
echo '
';
echo '
';
echo '
';
}
echo '
';
}
public function mxchat_chatbot_bg_color_callback() {
$disabled = $this->is_activated ? '' : 'disabled';
echo '';
printf(
'
',
isset($this->options['chatbot_bg_color']) ? esc_attr($this->options['chatbot_bg_color']) : '',
esc_attr($disabled)
);
if (!$this->is_activated) {
echo '
';
echo '
';
echo '
';
}
echo '
';
}
public function mxchat_user_message_bg_color_callback() {
$disabled = $this->is_activated ? '' : 'disabled';
echo '';
printf(
'
',
isset($this->options['user_message_bg_color']) ? esc_attr($this->options['user_message_bg_color']) : '',
esc_attr($disabled)
);
if (!$this->is_activated) {
echo '
';
echo '
';
echo '
';
}
echo '
';
}
public function mxchat_user_message_font_color_callback() {
$disabled = $this->is_activated ? '' : 'disabled';
echo '';
printf(
'
',
isset($this->options['user_message_font_color']) ? esc_attr($this->options['user_message_font_color']) : '',
esc_attr($disabled)
);
if (!$this->is_activated) {
echo '
';
echo '
';
echo '
';
}
echo '
';
}
public function mxchat_bot_message_bg_color_callback() {
$disabled = $this->is_activated ? '' : 'disabled';
echo '';
printf(
'
',
isset($this->options['bot_message_bg_color']) ? esc_attr($this->options['bot_message_bg_color']) : '',
esc_attr($disabled)
);
if (!$this->is_activated) {
echo '
';
echo '
';
echo '
';
}
echo '
';
}
public function mxchat_bot_message_font_color_callback() {
$disabled = $this->is_activated ? '' : 'disabled';
echo '';
printf(
'
',
isset($this->options['bot_message_font_color']) ? esc_attr($this->options['bot_message_font_color']) : '',
esc_attr($disabled)
);
if (!$this->is_activated) {
echo '
';
echo '
';
echo '
';
}
echo '
';
}
public function mxchat_live_agent_message_bg_color_callback() {
$disabled = $this->is_activated ? '' : 'disabled';
echo '';
printf(
'
',
isset($this->options['live_agent_message_bg_color']) ? esc_attr($this->options['live_agent_message_bg_color']) : '',
esc_attr($disabled)
);
if (!$this->is_activated) {
echo '
';
echo '
';
echo '
';
}
echo '
';
}
public function mxchat_live_agent_message_font_color_callback() {
$disabled = $this->is_activated ? '' : 'disabled';
echo '';
printf(
'
',
isset($this->options['live_agent_message_font_color']) ? esc_attr($this->options['live_agent_message_font_color']) : '',
esc_attr($disabled)
);
if (!$this->is_activated) {
echo '
';
echo '
';
echo '
';
}
echo '
';
}
// Mode Indicator Background Color Callback
public function mxchat_mode_indicator_bg_color_callback() {
$disabled = $this->is_activated ? '' : 'disabled';
echo '';
printf(
'
',
isset($this->options['mode_indicator_bg_color']) ? esc_attr($this->options['mode_indicator_bg_color']) : '',
esc_attr($disabled)
);
if (!$this->is_activated) {
echo '
';
echo '
';
echo '
';
}
echo '
';
}
// Mode Indicator Font Color Callback
public function mxchat_mode_indicator_font_color_callback() {
$disabled = $this->is_activated ? '' : 'disabled';
echo '';
printf(
'
',
isset($this->options['mode_indicator_font_color']) ? esc_attr($this->options['mode_indicator_font_color']) : '',
esc_attr($disabled)
);
if (!$this->is_activated) {
echo '
';
echo '
';
echo '
';
}
echo '
';
}
public function mxchat_toolbar_icon_color_callback() {
$disabled = $this->is_activated ? '' : 'disabled';
echo '';
printf(
'
',
isset($this->options['toolbar_icon_color']) ? esc_attr($this->options['toolbar_icon_color']) : '',
esc_attr($disabled)
);
if (!$this->is_activated) {
echo '
';
echo '
';
echo '
';
}
echo '
';
}
public function mxchat_top_bar_bg_color_callback() {
$disabled = $this->is_activated ? '' : 'disabled';
echo '';
printf(
'
',
isset($this->options['top_bar_bg_color']) ? esc_attr($this->options['top_bar_bg_color']) : '',
esc_attr($disabled)
);
if (!$this->is_activated) {
echo '
';
echo '
';
echo '
';
}
echo '
';
}
public function mxchat_send_button_font_color_callback() {
$disabled = $this->is_activated ? '' : 'disabled';
echo '';
printf(
'
',
isset($this->options['send_button_font_color']) ? esc_attr($this->options['send_button_font_color']) : '',
esc_attr($disabled)
);
if (!$this->is_activated) {
echo '
';
echo '
';
echo '
';
}
echo '
';
}
public function mxchat_chatbot_background_color_callback() {
$disabled = $this->is_activated ? '' : 'disabled';
echo '';
printf(
'
',
isset($this->options['chatbot_background_color']) ? esc_attr($this->options['chatbot_background_color']) : '',
esc_attr($disabled)
);
if (!$this->is_activated) {
echo '
';
echo '
';
echo '
';
}
echo '
';
}
public function mxchat_icon_color_callback() {
$disabled = $this->is_activated ? '' : 'disabled';
echo '';
printf(
'
',
isset($this->options['icon_color']) ? esc_attr($this->options['icon_color']) : '',
esc_attr($disabled)
);
if (!$this->is_activated) {
echo '
';
echo '
';
echo '
';
}
echo '
';
}
public function mxchat_custom_icon_callback() {
$disabled = $this->is_activated ? '' : 'disabled';
$custom_icon_url = isset($this->options['custom_icon']) ? esc_url($this->options['custom_icon']) : '';
echo '';
printf(
'
',
$custom_icon_url,
esc_attr($disabled)
);
echo '
Upload your PNG icon and paste the URL here. Recommended size: 48x48 pixels.
';
if (!$this->is_activated) {
echo '
';
echo '
';
echo '
';
}
echo '
';
}
public function mxchat_chat_input_font_color_callback() {
$disabled = $this->is_activated ? '' : 'disabled';
echo '';
printf(
'
',
isset($this->options['chat_input_font_color']) ? esc_attr($this->options['chat_input_font_color']) : '',
esc_attr($disabled)
);
if (!$this->is_activated) {
echo '
';
echo '
';
echo '
';
}
echo '
';
}
public function mxchat_append_to_body_callback() {
$append_to_body_checked = isset($this->options['append_to_body']) && $this->options['append_to_body'] === 'on' ? 'checked' : '';
echo '';
printf(
' ',
esc_attr($append_to_body_checked)
);
echo ' ';
echo ' ';
echo 'Enable this option to automatically append the chat widget to the body of every page (recommended). No need to manually use the shortcode [mxchat_chatbot floating="yes"].
';
}
public function mxchat_privacy_toggle_callback() {
// Check if the privacy toggle is enabled
$privacy_toggle_checked = isset($this->options['privacy_toggle']) && $this->options['privacy_toggle'] === 'on' ? 'checked' : '';
// Retrieve the stored privacy text if it exists
$privacy_text = isset($this->options['privacy_text']) ? wp_kses_post($this->options['privacy_text']) : 'By chatting, you agree to our privacy policy .';
// Output the toggle switch
echo '';
printf(
' ',
esc_attr($privacy_toggle_checked)
);
echo ' ';
echo ' ';
echo 'Enable this option to display a privacy notice below the chat widget.
';
// Output the custom text input field
printf(
'%s ',
esc_textarea($privacy_text)
);
echo 'Enter the privacy policy text. You can include HTML links.
';
}
public function mxchat_complianz_toggle_callback() {
// Check if the Complianz toggle is enabled
$complianz_toggle_checked = isset($this->options['complianz_toggle']) && $this->options['complianz_toggle'] === 'on' ? 'checked' : '';
// Check if the plugin is activated (paid feature)
$disabled = $this->is_activated ? '' : 'disabled';
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive';
echo '';
// Output the toggle switch
echo '
';
printf(
' ',
esc_attr($complianz_toggle_checked),
esc_attr($disabled)
);
echo ' ';
echo ' ';
echo '
Enable this option to apply Complianz consent logic to the chatbot.
';
// If the feature is not activated, show the Pro feature overlay
if (!$this->is_activated) {
echo '
';
echo '
';
echo '
';
}
echo '
';
}
public function mxchat_link_target_toggle_callback() {
// Check if the toggle is enabled in the options
$link_target_toggle = isset($this->options['link_target_toggle']) && $this->options['link_target_toggle'] === 'on' ? 'checked' : '';
// Output the toggle switch
echo '';
printf(
' ',
esc_attr($link_target_toggle)
);
echo ' ';
echo ' ';
echo 'Enable to open links in a new tab (default is to open in the same tab).
';
}
public function mxchat_chat_persistence_toggle_callback() {
// Check if chat persistence toggle is enabled
$chat_persistence_toggle_checked = isset($this->options['chat_persistence_toggle']) && $this->options['chat_persistence_toggle'] === 'on' ? 'checked' : '';
// Check if the plugin is activated (paid feature)
$disabled = $this->is_activated ? '' : 'disabled';
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive';
echo '';
// Output the toggle switch
echo '
';
printf(
' ',
esc_attr($chat_persistence_toggle_checked),
esc_attr($disabled)
);
echo ' ';
echo ' ';
echo '
Enable to keep chat history when users navigate tabs or return to the site within 24 hours.
';
// If not activated, show Pro feature overlay
if (!$this->is_activated) {
echo '
';
echo '
';
echo '
';
}
echo '
';
}
public function mxchat_popular_question_1_callback() {
printf(
' ',
isset($this->options['popular_question_1']) ? esc_attr($this->options['popular_question_1']) : ''
);
echo 'This will be the first popular question in the chatbot.
';
}
public function mxchat_popular_question_2_callback() {
// Check if the plugin is activated (paid feature)
$disabled = $this->is_activated ? '' : 'disabled';
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive';
echo '';
printf(
'
',
isset($this->options['popular_question_2']) ? esc_attr($this->options['popular_question_2']) : '',
esc_attr($disabled)
);
echo '
This will be the second popular question in the chatbot.
';
// If not activated, show Pro feature overlay
if (!$this->is_activated) {
echo '
';
echo '
';
echo '
';
}
echo '
';
}
public function mxchat_popular_question_3_callback() {
// Check if the plugin is activated (paid feature)
$disabled = $this->is_activated ? '' : 'disabled';
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive';
echo '';
printf(
'
',
isset($this->options['popular_question_3']) ? esc_attr($this->options['popular_question_3']) : '',
esc_attr($disabled)
);
echo '
This will be the third popular question in the chatbot.
';
// If not activated, show Pro feature overlay
if (!$this->is_activated) {
echo '
';
echo '
';
echo '
';
}
echo '
';
}
public function mxchat_additional_popular_questions_callback() {
$disabled = $this->is_activated ? '' : 'disabled';
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive';
$additional_questions = isset($this->options['additional_popular_questions']) ? $this->options['additional_popular_questions'] : array();
echo '';
echo '
';
printf(
'
Add Question ',
esc_attr($disabled)
);
echo '
You can add more popular questions beyond the default three here.
';
if (!$this->is_activated) {
echo '
';
echo '
';
echo '
';
}
echo '
';
}
/**
* Callback for Brave API Key field.
*/
public function mxchat_brave_api_key_callback() {
$options = get_option('mxchat_options');
$brave_api_key = isset($options['brave_api_key']) ? esc_attr($options['brave_api_key']) : '';
echo '';
printf(
' ',
$brave_api_key
);
echo 'Show ';
echo '
';
echo '' . __('Enter your Brave Search API Key here. (See FAQ for details)', 'mxchat') . '
';
?>
',
$brave_image_count
);
echo '' . __('Select the number of images to return (1-6).', 'mxchat') . '
';
}
/**
* Callback for Safe Search field.
*/
public function mxchat_brave_safe_search_callback() {
$options = get_option('mxchat_options');
$brave_safe_search = isset($options['brave_safe_search']) ? esc_attr($options['brave_safe_search']) : 'strict';
?>
>
>
',
$brave_news_count
);
echo '' . __('Select the number of news articles to retrieve (1-10).', 'mxchat') . '
';
}
/**
* Callback for Country field.
*/
public function mxchat_brave_country_callback() {
$options = get_option('mxchat_options');
$brave_country = isset($options['brave_country']) ? esc_attr($options['brave_country']) : 'us';
printf(
' ',
$brave_country
);
echo '' . __('Enter the country code (e.g., "us" for United States).', 'mxchat') . '
';
}
/**
* Callback for Language field.
*/
public function mxchat_brave_language_callback() {
$options = get_option('mxchat_options');
$brave_language = isset($options['brave_language']) ? esc_attr($options['brave_language']) : 'en';
printf(
' ',
$brave_language
);
echo '' . __('Enter the language code (e.g., "en" for English).', 'mxchat') . '
';
}
// Section Callback
public function mxchat_pdf_intent_section_callback() {
echo '' . esc_html__('Configure the intent settings for the Chat with PDF feature.', 'mxchat') . '
';
}
public function mxchat_chat_toolbar_toggle_callback() {
$checked = isset($this->options['chat_toolbar_toggle']) && $this->options['chat_toolbar_toggle'] === 'on' ? 'checked' : '';
$disabled = $this->is_activated ? '' : 'disabled';
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive';
echo '';
echo '
';
printf(
' ',
esc_attr($checked),
esc_attr($disabled)
);
echo ' ';
echo ' ';
if (!$this->is_activated) {
echo '
';
echo '
';
echo '
';
}
echo '
';
echo 'Enable to display the chat toolbar (default is hidden).
';
}
// Intent Trigger Text Callback
public function mxchat_pdf_intent_trigger_text_callback() {
$disabled = $this->is_activated ? '' : 'disabled';
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive';
echo '';
printf(
'
%s ',
esc_attr($disabled),
isset($this->options['pdf_intent_trigger_text']) ? esc_textarea($this->options['pdf_intent_trigger_text']) : ''
);
echo '
Text displayed when the intent is triggered.
';
if (!$this->is_activated) {
echo '
';
echo '
';
echo '
';
}
echo '
';
}
// Success Text Callback
public function mxchat_pdf_intent_success_text_callback() {
$disabled = $this->is_activated ? '' : 'disabled';
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive';
echo '';
printf(
'
%s ',
esc_attr($disabled),
isset($this->options['pdf_intent_success_text']) ? esc_textarea($this->options['pdf_intent_success_text']) : ''
);
echo '
Text displayed when the intent is successful.
';
if (!$this->is_activated) {
echo '
';
echo '
';
echo '
';
}
echo '
';
}
// Error Text Callback
public function mxchat_pdf_intent_error_text_callback() {
$disabled = $this->is_activated ? '' : 'disabled';
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive';
echo '';
printf(
'
%s ',
esc_attr($disabled),
isset($this->options['pdf_intent_error_text']) ? esc_textarea($this->options['pdf_intent_error_text']) : ''
);
echo '
Text displayed when an error occurs during the intent.
';
if (!$this->is_activated) {
echo '
';
echo '
';
echo '
';
}
echo '
';
}
// Maximum PDF Pages Callback
public function mxchat_pdf_max_pages_callback() {
$disabled = $this->is_activated ? '' : 'disabled';
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive';
$max_pages = isset($this->options['pdf_max_pages']) ? intval($this->options['pdf_max_pages']) : 69;
echo '';
printf(
'
',
esc_attr($max_pages),
esc_attr($disabled)
);
echo '
' . esc_html($max_pages) . ' ';
echo '
Set the maximum number of PDF pages users can upload for processing. (1-69 pages)
';
if (!$this->is_activated) {
echo '
';
echo '
';
echo '
';
}
echo '
';
}
// Status Toggle Callback
public function mxchat_live_agent_status_callback() {
$disabled = $this->is_activated ? '' : 'disabled';
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive';
$status = isset($this->options['live_agent_status']) ? $this->options['live_agent_status'] : 'offline';
echo '';
echo '
';
printf(
' ',
checked($status, 'online', false),
esc_attr($disabled)
);
echo ' ';
echo ' ';
echo '
';
echo '' . ($status === 'online' ? esc_html__('Online', 'mxchat') : esc_html__('Offline', 'mxchat')) . ' ';
echo ' ';
if (!$this->is_activated) {
echo '
';
echo '
';
echo '
';
}
echo '
';
}
// Away Message Callback
public function mxchat_live_agent_away_message_callback() {
$disabled = $this->is_activated ? '' : 'disabled';
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive';
$message = isset($this->options['live_agent_away_message'])
? $this->options['live_agent_away_message']
: __('Sorry, live agents are currently unavailable. I can continue helping you as an AI assistant.', 'mxchat');
echo '';
printf(
'
%s ',
esc_attr($disabled),
esc_textarea($message)
);
echo '
' . esc_html__('Message shown when live agents are offline.', 'mxchat') . '
';
if (!$this->is_activated) {
echo '
';
echo '
';
echo '
';
}
echo '
';
}
public function mxchat_live_agent_notification_message_callback() {
$disabled = $this->is_activated ? '' : 'disabled';
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive';
$message = isset($this->options['live_agent_notification_message'])
? $this->options['live_agent_notification_message']
: __('Live agent has been notified.', 'mxchat');
echo '';
printf(
'
%s ',
esc_attr($disabled),
esc_textarea($message)
);
echo '
' . esc_html__('Message shown when live transfer activated.', 'mxchat') . '
';
if (!$this->is_activated) {
echo '
';
echo '
';
echo '
';
}
echo '
';
}
public function mxchat_live_agent_webhook_url_callback() {
$disabled = $this->is_activated ? '' : 'disabled';
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive';
$webhook_url = isset($this->options['live_agent_webhook_url'])
? esc_url($this->options['live_agent_webhook_url'])
: esc_url(get_option('live_agent_webhook_url', ''));
echo '';
printf(
'
',
$webhook_url,
esc_attr($disabled)
);
echo '
Show ';
echo '
Enter your Slack webhook URL for live agent notifications.
';
if (!$this->is_activated) {
echo '
';
echo '
';
echo '
';
}
echo '
';
}
public function mxchat_similarity_threshold_callback() {
$threshold = get_option('mxchat_similarity_threshold', 80); // Default to 80
?>
Lower values match less relevant content, higher values match more strictly.
is_activated ? '' : 'disabled';
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive';
echo '';
printf(
'
',
isset($this->options['live_agent_secret_key']) ? esc_attr($this->options['live_agent_secret_key']) : '',
esc_attr($disabled)
);
echo '
Show ';
echo '
Secret key for validating Slack requests. Keep this secure.
';
if (!$this->is_activated) {
echo '
';
echo '
';
echo '
';
}
echo '
';
}
public function mxchat_live_agent_bot_token_callback() {
$disabled = $this->is_activated ? '' : 'disabled';
$class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive';
echo '';
printf(
'
',
isset($this->options['live_agent_bot_token']) ? esc_attr($this->options['live_agent_bot_token']) : '',
esc_attr($disabled)
);
echo '
Show ';
echo '
Your Slack Bot OAuth Token (starts with xoxb-). Keep this secure.
';
if (!$this->is_activated) {
echo '
';
echo '
';
echo '
';
}
echo '
';
}
public function mxchat_enqueue_admin_assets() {
wp_enqueue_style('wp-color-picker');
// Get the plugin version or file modification time for cache busting
$plugin_version = '1.5.2'; // Replace this with your plugin's version
// File paths
$color_picker_js_path = plugin_dir_path(__FILE__) . '../js/my-color-picker.js';
$embedding_check_js_path = plugin_dir_path(__FILE__) . '../js/embedding-check.js';
$admin_css_path = plugin_dir_path(__FILE__) . '../css/admin-style.css';
$transcripts_js_path = plugin_dir_path(__FILE__) . '../js/mxchat_transcripts.js';
// Check if files exist and get modification times
$color_picker_version = file_exists($color_picker_js_path) ? filemtime($color_picker_js_path) : $plugin_version;
$embedding_check_version = file_exists($embedding_check_js_path) ? filemtime($embedding_check_js_path) : $plugin_version;
$admin_css_version = file_exists($admin_css_path) ? filemtime($admin_css_path) : $plugin_version;
$transcripts_js_version = file_exists($transcripts_js_path) ? filemtime($transcripts_js_path) : $plugin_version;
// Enqueue scripts and styles with corrected paths
wp_enqueue_script(
'mxchat-color-picker',
plugin_dir_url(__FILE__) . '../js/my-color-picker.js',
array('wp-color-picker'),
$color_picker_version,
true
);
wp_enqueue_script(
'mxchat-embedding-check',
plugin_dir_url(__FILE__) . '../js/embedding-check.js',
array(),
$embedding_check_version,
true
);
wp_enqueue_script(
'mxchat-transcripts-js',
plugin_dir_url(__FILE__) . '../js/mxchat_transcripts.js',
array('jquery'),
$transcripts_js_version,
true
);
wp_enqueue_script(
'mxchat-admin-js',
plugin_dir_url(__FILE__) . '../js/mxchat-admin.js',
array('jquery'),
$plugin_version,
true
);
// Localize the script with data for the activation process
wp_localize_script('mxchat-admin-js', 'mxchatAdmin', array(
'ajax_url' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('mxchat_activate_license_nonce'),
));
wp_enqueue_style(
'mxchat-admin-css',
plugin_dir_url(__FILE__) . '../css/admin-style.css',
array(),
$admin_css_version
);
wp_localize_script('mxchat-color-picker', 'mxchatStyleSettings', array(
'ajax_url' => admin_url('admin-ajax.php'),
'link_target_toggle' => $this->options['link_target_toggle'] ?? 'off',
'user_message_bg_color' => $this->options['user_message_bg_color'] ?? '#fff',
'user_message_font_color' => $this->options['user_message_font_color'] ?? '#212121',
'bot_message_bg_color' => $this->options['bot_message_bg_color'] ?? '#212121',
'bot_message_font_color' => $this->options['bot_message_font_color'] ?? '#fff',
'top_bar_bg_color' => $this->options['top_bar_bg_color'] ?? '#212121',
'send_button_font_color' => $this->options['send_button_font_color'] ?? '#212121',
'close_button_color' => $this->options['close_button_color'] ?? '#fff',
'chatbot_background_color' => $this->options['chatbot_background_color'] ?? '#212121',
'icon_color' => $this->options['icon_color'] ?? '#fff',
'chat_input_font_color' => $this->options['chat_input_font_color'] ?? '#212121',
'pre_chat_message' => $this->options['pre_chat_message'] ?? 'Hey there! Ask me anything!',
'rate_limit_message' => $this->options['rate_limit_message'] ?? 'Rate limit exceeded. Please try again later.',
// New fields for Loops Integration
'loops_api_key' => $this->options['loops_api_key'] ?? '',
'loops_mailing_list' => $this->options['loops_mailing_list'] ?? '',
'triggered_phrase_response' => $this->options['triggered_phrase_response'] ?? 'Would you like to join our mailing list? Please provide your email below.',
'email_capture_response' => $this->options['email_capture_response'] ?? 'Thank you for providing your email! You\'ve been added to our list.',
'pdf_intent_trigger_text' => $this->options['pdf_intent_trigger_text'] ?? "Please provide the URL to the PDF you'd like to discuss.",
'pdf_intent_success_text' => $this->options['pdf_intent_success_text'] ?? "I've processed the PDF. What questions do you have about it?",
'pdf_intent_error_text' => $this->options['pdf_intent_error_text'] ?? "Sorry, I couldn't process the PDF. Please ensure it's a valid file.",
'pdf_max_pages' => $this->options['pdf_max_pages'] ?? 69,
// Live Agent Integration
'live_agent_webhook_url' => $this->options['live_agent_webhook_url'] ?? '',
'live_agent_secret_key' => $this->options['live_agent_secret_key'] ?? '',
'live_agent_bot_token' => $this->options['live_agent_bot_token'] ?? '',
'live_agent_message_bg_color' => $this->options['live_agent_message_bg_color'] ?? '#ffffff',
'live_agent_message_font_color' => $this->options['live_agent_message_font_color'] ?? '#333333',
'chat_toolbar_toggle' => $this->options['chat_toolbar_toggle'] ?? 'off',
'mode_indicator_bg_color' => $this->options['mode_indicator_bg_color'] ?? '#767676',
'mode_indicator_font_color' => $this->options['mode_indicator_font_color'] ?? '#ffffff',
'toolbar_icon_color' => $this->options['toolbar_icon_color'] ?? '#212121',
));
// Localize the script to pass the nonce and other data to JavaScript
wp_localize_script('mxchat-admin-js', 'mxchatInlineEdit', array(
'nonce' => wp_create_nonce('mxchat_save_inline_nonce'),
'ajax_url' => admin_url('admin-ajax.php')
));
}
public function mxchat_sanitize($input) {
$new_input = array();
if (isset($input['api_key'])) {
$new_input['api_key'] = sanitize_text_field($input['api_key']);
}
if (isset($input['similarity_threshold'])) {
$new_input['similarity_threshold'] = absint($input['similarity_threshold']); // Ensure it's an integer
$new_input['similarity_threshold'] = min(max($new_input['similarity_threshold'], 70), 85); // Enforce range
}
if (isset($input['xai_api_key'])) {
$new_input['xai_api_key'] = sanitize_text_field($input['xai_api_key']);
}
if (isset($input['claude_api_key'])) {
$new_input['claude_api_key'] = sanitize_text_field($input['claude_api_key']);
}
if (isset($input['enable_woocommerce_integration'])) {
$new_input['enable_woocommerce_integration'] = isset($input['enable_woocommerce_integration']) && $input['enable_woocommerce_integration'] === '1' ? '1' : '0';
}
if (isset($input['privacy_toggle'])) {
$new_input['privacy_toggle'] = $input['privacy_toggle'];
}
if (isset($input['complianz_toggle'])) {
$new_input['complianz_toggle'] = $input['complianz_toggle'];
}
// Handle custom privacy text input
if (isset($input['privacy_text'])) {
// Allow basic HTML for links
$new_input['privacy_text'] = wp_kses_post($input['privacy_text']);
}
if (isset($input['system_prompt_instructions'])) {
$new_input['system_prompt_instructions'] = sanitize_textarea_field($input['system_prompt_instructions']);
}
if (isset($input['mxchat_pro_email'])) {
$new_input['mxchat_pro_email'] = sanitize_email($input['mxchat_pro_email']);
}
if (isset($input['mxchat_activation_key'])) {
$new_input['mxchat_activation_key'] = sanitize_text_field($input['mxchat_activation_key']);
}
if (isset($input['append_to_body'])) {
$new_input['append_to_body'] = $input['append_to_body'] === 'on' ? 'on' : 'off';
}
if (isset($input['top_bar_title'])) {
$new_input['top_bar_title'] = sanitize_text_field($input['top_bar_title']);
}
if (isset($input['intro_message'])) {
$new_input['intro_message'] = sanitize_text_field($input['intro_message']);
}
if (isset($input['input_copy'])) {
$new_input['input_copy'] = sanitize_text_field($input['input_copy']);
}
if (isset($input['rate_limit_message'])) {
$new_input['rate_limit_message'] = sanitize_text_field($input['rate_limit_message']);
}
if (isset($input['rate_limit_logged_in'])) {
$allowed_limits = array('1', '3', '5', '10', '15', '20', '100', 'unlimited'); // Add 'unlimited' to allowed values
$rate_limit = sanitize_text_field($input['rate_limit_logged_in']);
if (in_array($rate_limit, $allowed_limits, true)) {
$new_input['rate_limit_logged_in'] = $rate_limit;
} else {
$new_input['rate_limit_logged_in'] = '100'; // Default for logged-in users
}
}
if (isset($input['rate_limit_logged_out'])) {
$allowed_limits = array('1', '3', '5', '10', '15', '20', '100', 'unlimited'); // Add 'unlimited' to allowed values
$rate_limit = sanitize_text_field($input['rate_limit_logged_out']);
if (in_array($rate_limit, $allowed_limits, true)) {
$new_input['rate_limit_logged_out'] = $rate_limit;
} else {
$new_input['rate_limit_logged_out'] = '10'; // Default for logged-out users
}
}
if (isset($input['pre_chat_message'])) {
$new_input['pre_chat_message'] = sanitize_textarea_field($input['pre_chat_message']);
}
if (isset($input['model'])) {
$allowed_models = array(
'grok-beta',
'claude-3-5-sonnet-20241022',
'claude-3-opus-20240229',
'claude-3-sonnet-20240229',
'claude-3-haiku-20240307',
'gpt-4o',
'gpt-4o-mini',
'gpt-4-turbo',
'gpt-4',
'gpt-3.5-turbo',
);
if (in_array($input['model'], $allowed_models)) {
$new_input['model'] = sanitize_text_field($input['model']);
}
}
// Sanitize new pro features
if (isset($input['close_button_color'])) {
$new_input['close_button_color'] = sanitize_hex_color($input['close_button_color']);
}
if (isset($input['chatbot_bg_color'])) {
$new_input['chatbot_bg_color'] = sanitize_hex_color($input['chatbot_bg_color']);
}
if (isset($input['woocommerce_consumer_key'])) {
$new_input['woocommerce_consumer_key'] = sanitize_text_field($input['woocommerce_consumer_key']);
}
if (isset($input['woocommerce_consumer_secret'])) {
$new_input['woocommerce_consumer_secret'] = sanitize_text_field($input['woocommerce_consumer_secret']);
}
if (isset($input['user_message_bg_color'])) {
$new_input['user_message_bg_color'] = sanitize_hex_color($input['user_message_bg_color']);
}
if (isset($input['user_message_font_color'])) {
$new_input['user_message_font_color'] = sanitize_hex_color($input['user_message_font_color']);
}
if (isset($input['bot_message_bg_color'])) {
$new_input['bot_message_bg_color'] = sanitize_hex_color($input['bot_message_bg_color']);
}
if (isset($input['bot_message_font_color'])) {
$new_input['bot_message_font_color'] = sanitize_hex_color($input['bot_message_font_color']);
}
if (isset($input['live_agent_message_bg_color'])) {
$new_input['live_agent_message_bg_color'] = sanitize_hex_color($input['live_agent_message_bg_color']);
}
if (isset($input['live_agent_message_font_color'])) {
$new_input['live_agent_message_font_color'] = sanitize_hex_color($input['live_agent_message_font_color']);
}
if (isset($input['mode_indicator_bg_color'])) {
$new_input['mode_indicator_bg_color'] = sanitize_hex_color($input['mode_indicator_bg_color']);
}
if (isset($input['mode_indicator_font_color'])) {
$new_input['mode_indicator_font_color'] = sanitize_hex_color($input['mode_indicator_font_color']);
}
if (isset($input['toolbar_icon_color'])) {
$new_input['toolbar_icon_color'] = sanitize_hex_color($input['toolbar_icon_color']);
}
if (isset($input['top_bar_bg_color'])) {
$new_input['top_bar_bg_color'] = sanitize_hex_color($input['top_bar_bg_color']);
}
if (isset($input['send_button_font_color'])) {
$new_input['send_button_font_color'] = sanitize_hex_color($input['send_button_font_color']);
}
if (isset($input['chatbot_background_color'])) {
$new_input['chatbot_background_color'] = sanitize_hex_color($input['chatbot_background_color']);
}
if (isset($input['icon_color'])) {
$new_input['icon_color'] = sanitize_hex_color($input['icon_color']);
}
if (isset($input['custom_icon'])) {
$new_input['custom_icon'] = esc_url_raw($input['custom_icon']);
}
if (isset($input['chat_input_font_color'])) {
$new_input['chat_input_font_color'] = sanitize_hex_color($input['chat_input_font_color']);
}
// Sanitize link_target_toggle
if (isset($input['link_target_toggle'])) {
$new_input['link_target_toggle'] = $input['link_target_toggle'] === 'on' ? 'on' : 'off';
}
// Sanitize Loops API Key
if (isset($input['loops_api_key'])) {
$new_input['loops_api_key'] = sanitize_text_field($input['loops_api_key']);
}
if (isset($input['chat_persistence_toggle'])) {
$new_input['chat_persistence_toggle'] = $input['chat_persistence_toggle'] === 'on' ? 'on' : 'off';
}
if (isset($input['popular_question_1'])) {
$new_input['popular_question_1'] = sanitize_text_field($input['popular_question_1']);
}
if (isset($input['popular_question_2'])) {
$new_input['popular_question_2'] = sanitize_text_field($input['popular_question_2']);
}
if (isset($input['popular_question_3'])) {
$new_input['popular_question_3'] = sanitize_text_field($input['popular_question_3']);
}
if (isset($input['additional_popular_questions']) && is_array($input['additional_popular_questions'])) {
$new_input['additional_popular_questions'] = array_map('sanitize_text_field', $input['additional_popular_questions']);
}
// Sanitize Loops Mailing List
if (isset($input['loops_mailing_list'])) {
$new_input['loops_mailing_list'] = sanitize_text_field($input['loops_mailing_list']);
}
// Sanitize Triggered Phrase Response
if (isset($input['triggered_phrase_response'])) {
$new_input['triggered_phrase_response'] = wp_kses_post($input['triggered_phrase_response']);
}
if (isset($input['email_capture_response'])) {
$new_input['email_capture_response'] = sanitize_textarea_field($input['email_capture_response']);
}
// Sanitize Brave Search Settings
if (isset($input['brave_api_key'])) {
$new_input['brave_api_key'] = sanitize_text_field($input['brave_api_key']);
}
if (isset($input['brave_image_count'])) {
$image_count = intval($input['brave_image_count']);
$new_input['brave_image_count'] = ($image_count >=1 && $image_count <=6) ? $image_count : 4;
}
if (isset($input['brave_safe_search'])) {
$allowed = array('strict', 'off');
$new_input['brave_safe_search'] = in_array($input['brave_safe_search'], $allowed, true) ? $input['brave_safe_search'] : 'strict';
}
if (isset($input['brave_news_count'])) {
$news_count = intval($input['brave_news_count']);
$new_input['brave_news_count'] = ($news_count >=1 && $news_count <=10) ? $news_count : 3;
}
if (isset($input['brave_country'])) {
$new_input['brave_country'] = sanitize_text_field($input['brave_country']);
}
if (isset($input['brave_language'])) {
$new_input['brave_language'] = sanitize_text_field($input['brave_language']);
}
if (isset($input['chat_toolbar_toggle'])) {
$new_input['chat_toolbar_toggle'] = $input['chat_toolbar_toggle'] === 'on' ? 'on' : 'off';
}
if (isset($input['pdf_intent_trigger_text'])) {
$new_input['pdf_intent_trigger_text'] = sanitize_text_field($input['pdf_intent_trigger_text']);
}
if (isset($input['pdf_intent_success_text'])) {
$new_input['pdf_intent_success_text'] = sanitize_text_field($input['pdf_intent_success_text']);
}
if (isset($input['pdf_intent_error_text'])) {
$new_input['pdf_intent_error_text'] = sanitize_text_field($input['pdf_intent_error_text']);
}
if (isset($input['pdf_max_pages'])) {
$new_input['pdf_max_pages'] = intval($input['pdf_max_pages']);
if ($new_input['pdf_max_pages'] < 1 || $new_input['pdf_max_pages'] > 69) {
$new_input['pdf_max_pages'] = 69; // Default to 69 if out of range
}
}
if (isset($input['live_agent_webhook_url'])) {
$new_input['live_agent_webhook_url'] = esc_url_raw($input['live_agent_webhook_url']);
}
if (isset($input['live_agent_secret_key'])) {
$new_input['live_agent_secret_key'] = sanitize_text_field($input['live_agent_secret_key']);
}
// Live Agent Integration
if (isset($input['live_agent_bot_token'])) {
$new_input['live_agent_bot_token'] = sanitize_text_field($input['live_agent_bot_token']);
}
if (isset($input['live_agent_status'])) {
$new_input['live_agent_status'] = ($input['live_agent_status'] === 'online') ? 'online' : 'offline';
}
if (isset($input['live_agent_away_message'])) {
$new_input['live_agent_away_message'] = sanitize_textarea_field($input['live_agent_away_message']);
}
if (isset($input['live_agent_notification_message'])) {
$new_input['live_agent_notification_message'] = sanitize_textarea_field($input['live_agent_notification_message']);
}
return $new_input;
}
// Method to append the chatbot to the body
public function mxchat_append_chatbot_to_body() {
$options = get_option('mxchat_options');
if (isset($options['append_to_body']) && $options['append_to_body'] === 'on') {
echo do_shortcode('[mxchat_chatbot floating="yes"]');
}
}
private static function mxchat_extract_main_content($html) {
$dom = new DOMDocument;
libxml_use_internal_errors(true); // Suppress HTML parsing errors
@$dom->loadHTML($html);
libxml_clear_errors();
$xpath = new DOMXPath($dom);
// Simplified selectors focusing on common content areas
$selectors = [
'//article',
'//*[@id="content"]',
'//*[@class="entry-content"]',
'//main',
];
foreach ($selectors as $selector) {
$nodes = $xpath->query($selector);
if ($nodes->length > 0) {
$content = '';
foreach ($nodes as $node) {
$content .= $dom->saveHTML($node);
}
return $content;
}
}
// Fallback: Return the entire body content if no specific selector matches
$body = $dom->getElementsByTagName('body');
return $body->length > 0 ? $dom->saveHTML($body->item(0)) : $html;
}
public function mxchat_handle_sitemap_submission() {
// Check if the form was submitted and verify permissions
if (!isset($_POST['submit_sitemap']) || !current_user_can('manage_options')) {
wp_die(esc_html__('Unauthorized access', 'mxchat'));
}
// Verify nonce
check_admin_referer('mxchat_submit_sitemap_action', 'mxchat_submit_sitemap_nonce');
// Validate URL
if (!isset($_POST['sitemap_url']) || empty($_POST['sitemap_url'])) {
set_transient('mxchat_admin_notice_error',
esc_html__('Please provide a valid URL.', 'mxchat'),
30
);
wp_safe_redirect(esc_url(admin_url('admin.php?page=mxchat-prompts')));
exit;
}
$submitted_url = esc_url_raw($_POST['sitemap_url']);
$response = wp_remote_get($submitted_url, array('timeout' => 30));
if (is_wp_error($response) || wp_remote_retrieve_response_code($response) !== 200) {
$error_message = is_wp_error($response) ? $response->get_error_message() : 'Failed to fetch URL';
set_transient('mxchat_admin_notice_error',
sprintf(
esc_html__('Failed to fetch the URL: %s', 'mxchat'),
esc_html($error_message)
),
30
);
wp_safe_redirect(esc_url(admin_url('admin.php?page=mxchat-prompts')));
exit;
}
$content_type = wp_remote_retrieve_header($response, 'content-type');
$body_content = wp_remote_retrieve_body($response);
if (empty($body_content)) {
set_transient('mxchat_admin_notice_error',
esc_html__('Empty response received from URL.', 'mxchat'),
30
);
wp_safe_redirect(esc_url(admin_url('admin.php?page=mxchat-prompts')));
exit;
}
// Handle PDF URL
if ($this->is_pdf_url($submitted_url, $response)) {
$result = $this->handle_pdf_for_knowledge_base($submitted_url, $response);
if ($result === 'scheduled') {
set_transient(
'mxchat_last_pdf_url',
sanitize_text_field($submitted_url),
DAY_IN_SECONDS
);
set_transient('mxchat_admin_notice_info',
esc_html__('PDF processing has started in the background. You can check the progress in the Knowledge Base section.', 'mxchat'),
30
);
} else {
set_transient('mxchat_admin_notice_error',
esc_html__('Failed to start PDF processing. Please try again.', 'mxchat'),
30
);
}
wp_safe_redirect(esc_url(admin_url('admin.php?page=mxchat-prompts')));
exit;
}
// Handle Sitemap XML
if (strpos($content_type, 'xml') !== false || strpos($body_content, 'handle_sitemap_for_knowledge_base($xml, $submitted_url);
if ($result === 'scheduled') {
set_transient(
'mxchat_last_sitemap_url',
sanitize_text_field($submitted_url),
DAY_IN_SECONDS
);
set_transient('mxchat_admin_notice_info',
esc_html__('Sitemap processing has started in the background. You can check the progress in the Knowledge Base section.', 'mxchat'),
30
);
} else {
set_transient('mxchat_admin_notice_error',
esc_html__('Failed to start sitemap processing. Please try again.', 'mxchat'),
30
);
}
wp_safe_redirect(esc_url(admin_url('admin.php?page=mxchat-prompts')));
exit;
}
// Handle Regular URL
$page_content = $this->mxchat_extract_main_content($body_content);
$sanitized_content = $this->mxchat_sanitize_content_for_api($page_content);
if (empty($sanitized_content)) {
set_transient('mxchat_admin_notice_error',
esc_html__('No valid content found on the provided URL.', 'mxchat'),
30
);
wp_safe_redirect(esc_url(admin_url('admin.php?page=mxchat-prompts')));
exit;
}
$embedding_vector = $this->mxchat_generate_embedding($sanitized_content);
if (is_array($embedding_vector)) {
MxChat_Utils::submit_content_to_db(
$sanitized_content,
$submitted_url,
$this->options['api_key']
);
set_transient('mxchat_admin_notice_success',
esc_html__('URL content successfully submitted!', 'mxchat'),
30
);
} else {
set_transient('mxchat_admin_notice_error',
esc_html__('Failed to generate embedding for the URL content. Please check your API key and try again.', 'mxchat'),
30
);
}
wp_safe_redirect(esc_url(admin_url('admin.php?page=mxchat-prompts')));
exit;
}
private function is_pdf_url($url, $response) {
$content_type = wp_remote_retrieve_header($response, 'content-type');
$file_extension = strtolower(pathinfo($url, PATHINFO_EXTENSION));
return strpos($content_type, 'pdf') !== false || $file_extension === 'pdf';
}
private function handle_pdf_for_knowledge_base($pdf_url, $response) {
if (!current_user_can('manage_options')) {
//error_log('Unauthorized PDF processing attempt');
return false;
}
$pdf_url = esc_url_raw($pdf_url);
$upload_dir = wp_upload_dir();
if (isset($upload_dir['error']) && $upload_dir['error'] !== false) {
//error_log(sprintf('Upload directory error: %s', esc_html($upload_dir['error'])));
return false;
}
$pdf_filename = sanitize_file_name('mxchat_kb_' . time() . '.pdf');
$pdf_path = trailingslashit($upload_dir['path']) . $pdf_filename;
$response_body = wp_remote_retrieve_body($response);
if (empty($response_body)) {
//error_log('Empty PDF response body');
return false;
}
if (!wp_mkdir_p(dirname($pdf_path))) {
//error_log(sprintf('Failed to create directory for PDF: %s', esc_html($pdf_path)));
return false;
}
try {
file_put_contents($pdf_path, $response_body);
if (!file_exists($pdf_path)) {
throw new Exception('Failed to save PDF file');
}
$parser = new \Smalot\PdfParser\Parser();
$pdf = $parser->parseFile($pdf_path);
$total_pages = absint(count($pdf->getPages()));
if ($total_pages < 1) {
throw new Exception('Invalid PDF: no pages found');
}
wp_schedule_single_event(time(), 'mxchat_process_pdf_pages', array(
'pdf_path' => $pdf_path,
'pdf_url' => $pdf_url,
'total_pages' => $total_pages,
'batch_size' => absint(15),
'batch_pause' => absint(10)
));
$status_data = array(
'total_pages' => $total_pages,
'processed_pages' => 0,
'status' => 'processing',
'last_update' => time()
);
set_transient(
sanitize_key('mxchat_pdf_status_' . md5($pdf_url)),
array_map('sanitize_text_field', $status_data),
DAY_IN_SECONDS
);
return 'scheduled';
} catch (Exception $e) {
//error_log(sprintf('Error preparing PDF for processing: %s', esc_html($e->getMessage())));
if (file_exists($pdf_path)) {
wp_delete_file($pdf_path);
}
return false;
}
}
public static function process_pdf_pages_cron($pdf_path, $pdf_url, $total_pages, $batch_size, $batch_pause) {
// Validate inputs
$pdf_path = sanitize_text_field($pdf_path);
$pdf_url = esc_url_raw($pdf_url);
$total_pages = absint($total_pages);
$batch_size = absint($batch_size);
$batch_pause = absint($batch_pause);
try {
if (!file_exists($pdf_path)) {
throw new Exception(sprintf('PDF file not found at path: %s', esc_html($pdf_path)));
}
$parser = new \Smalot\PdfParser\Parser();
$pdf = $parser->parseFile($pdf_path);
$pages = $pdf->getPages();
// Get current progress
$status_key = sanitize_key('mxchat_pdf_status_' . md5($pdf_url));
$status = get_transient($status_key);
if (!$status || !is_array($status)) {
throw new Exception('Invalid status data retrieved from transient');
}
$start_page = absint($status['processed_pages']);
$end_page = min($start_page + $batch_size, $total_pages);
$instance = new self(); // Create an instance of the class
for ($i = $start_page; $i < $end_page; $i++) {
$text = $pages[$i]->getText();
$sanitized_content = $instance->mxchat_sanitize_content_for_api($text); // Call via instance
if (!empty($sanitized_content)) {
$embedding_vector = $instance->mxchat_generate_embedding($sanitized_content); // Call via instance
if (is_array($embedding_vector)) {
$metadata = array(
'document_type' => 'pdf',
'total_pages' => $total_pages,
'current_page' => $i + 1,
'prev_page' => $i > 0 ? $i : null,
'next_page' => $i < ($total_pages - 1) ? $i + 2 : null,
'source_url' => $pdf_url
);
$content_with_metadata = wp_json_encode($metadata) . "\n---\n" . $sanitized_content;
$page_url = esc_url($pdf_url . "#page=" . ($i + 1));
$options = get_option('mxchat_options');
MxChat_Utils::submit_content_to_db($content_with_metadata, $page_url, $options['api_key']);
}
}
// Update progress with sanitized data
$status['processed_pages'] = absint($i + 1);
$status['last_update'] = time();
set_transient($status_key, array_map('sanitize_text_field', $status), DAY_IN_SECONDS);
}
// Schedule next batch if needed
if ($end_page < $total_pages) {
wp_schedule_single_event(time() + $batch_pause, 'mxchat_process_pdf_pages', array(
'pdf_path' => $pdf_path,
'pdf_url' => $pdf_url,
'total_pages' => $total_pages,
'batch_size' => $batch_size,
'batch_pause' => $batch_pause
));
} else {
// Processing complete
$status['status'] = 'complete';
set_transient($status_key, array_map('sanitize_text_field', $status), DAY_IN_SECONDS);
if (file_exists($pdf_path)) {
wp_delete_file($pdf_path);
}
}
} catch (\Exception $e) {
$status['status'] = 'error';
$status['error'] = sanitize_text_field($e->getMessage());
set_transient($status_key, array_map('sanitize_text_field', $status), DAY_IN_SECONDS);
if (file_exists($pdf_path)) {
wp_delete_file($pdf_path);
}
}
}
public function get_pdf_processing_status($pdf_url) {
$pdf_url = esc_url_raw($pdf_url);
$status = get_transient(sanitize_key('mxchat_pdf_status_' . md5($pdf_url)));
if (!$status || !is_array($status)) {
return false;
}
return array(
'total_pages' => absint($status['total_pages']),
'processed_pages' => absint($status['processed_pages']),
'percentage' => round((absint($status['processed_pages']) / absint($status['total_pages'])) * 100),
'status' => sanitize_text_field($status['status']),
'last_update' => human_time_diff(absint($status['last_update']), time()) . ' ago'
);
}
private function handle_sitemap_for_knowledge_base($xml, $sitemap_url) {
if (!current_user_can('manage_options')) {
//error_log('Unauthorized sitemap processing attempt');
return false;
}
try {
$sitemap_url = esc_url_raw($sitemap_url);
if (!$xml || !is_object($xml)) {
throw new Exception('Invalid XML object provided');
}
$urls = [];
foreach ($xml->url as $url_element) {
$url = esc_url_raw((string)$url_element->loc);
if ($url) {
$urls[] = $url;
}
}
$total_urls = absint(count($urls));
if ($total_urls < 1) {
throw new Exception('No valid URLs found in sitemap');
}
wp_schedule_single_event(time(), 'mxchat_process_sitemap_urls', array(
'urls' => $urls,
'sitemap_url' => $sitemap_url,
'total_urls' => $total_urls,
'batch_size' => absint(10),
'batch_pause' => absint(5)
));
$status_data = array(
'total_urls' => $total_urls,
'processed_urls' => 0,
'status' => 'processing',
'last_update' => time()
);
set_transient(
sanitize_key('mxchat_sitemap_status_' . md5($sitemap_url)),
array_map('sanitize_text_field', $status_data),
DAY_IN_SECONDS
);
return 'scheduled';
} catch (\Exception $e) {
//error_log(sprintf('Error preparing sitemap for processing: %s', esc_html($e->getMessage())));
return false;
}
}
public static function process_sitemap_urls_cron($urls, $sitemap_url, $total_urls, $batch_size, $batch_pause) {
// Validate inputs
$sitemap_url = esc_url_raw($sitemap_url);
$total_urls = absint($total_urls);
$batch_size = absint($batch_size);
$batch_pause = absint($batch_pause);
if (!is_array($urls) || empty($urls)) {
return;
}
try {
$status_key = sanitize_key('mxchat_sitemap_status_' . md5($sitemap_url));
$status = get_transient($status_key);
if (!$status || !is_array($status)) {
throw new Exception('Invalid status data retrieved from transient');
}
$start_url = absint($status['processed_urls']);
$end_url = min($start_url + $batch_size, $total_urls);
$instance = new self(); // Create an instance of the class
$embedding_success = true;
for ($i = $start_url; $i < $end_url; $i++) {
$page_url = esc_url_raw($urls[$i]);
$page_response = wp_remote_get($page_url);
if (is_wp_error($page_response) || wp_remote_retrieve_response_code($page_response) !== 200) {
continue;
}
$page_html = wp_remote_retrieve_body($page_response);
$page_content = $instance->mxchat_extract_main_content($page_html); // Call via instance
$sanitized_content = $instance->mxchat_sanitize_content_for_api($page_content); // Call via instance
if (!empty($sanitized_content)) {
$embedding_vector = $instance->mxchat_generate_embedding($sanitized_content); // Call via instance
if (is_array($embedding_vector)) {
$options = get_option('mxchat_options');
MxChat_Utils::submit_content_to_db($sanitized_content, $page_url, $options['api_key']);
} else {
$embedding_success = false;
}
}
$status['processed_urls'] = absint($i + 1);
$status['last_update'] = time();
set_transient($status_key, array_map('sanitize_text_field', $status), DAY_IN_SECONDS);
}
if ($end_url < $total_urls) {
wp_schedule_single_event(time() + $batch_pause, 'mxchat_process_sitemap_urls', array(
'urls' => array_map('esc_url_raw', $urls),
'sitemap_url' => $sitemap_url,
'total_urls' => $total_urls,
'batch_size' => $batch_size,
'batch_pause' => $batch_pause,
));
} else {
$status['status'] = 'complete';
set_transient($status_key, array_map('sanitize_text_field', $status), DAY_IN_SECONDS);
}
} catch (\Exception $e) {
$status['status'] = 'error';
$status['error'] = sanitize_text_field($e->getMessage());
set_transient($status_key, array_map('sanitize_text_field', $status), DAY_IN_SECONDS);
}
}
public function get_sitemap_processing_status($sitemap_url) {
$sitemap_url = esc_url_raw($sitemap_url);
$status = get_transient(sanitize_key('mxchat_sitemap_status_' . md5($sitemap_url)));
if (!$status || !is_array($status)) {
return false;
}
return array(
'total_urls' => absint($status['total_urls']),
'processed_urls' => absint($status['processed_urls']),
'percentage' => round((absint($status['processed_urls']) / absint($status['total_urls'])) * 100),
'status' => sanitize_text_field($status['status']),
'last_update' => human_time_diff(absint($status['last_update']), time()) . ' ago'
);
}
public function mxchat_stop_processing() {
// Verify permissions
if (!current_user_can('manage_options')) {
wp_die(esc_html__('Unauthorized access', 'mxchat'));
}
// Verify nonce
check_admin_referer('mxchat_stop_processing_action', 'mxchat_stop_processing_nonce');
// Get the last sitemap URL and clear its transient
$sitemap_url = get_transient('mxchat_last_sitemap_url');
if ($sitemap_url) {
delete_transient('mxchat_sitemap_status_' . md5($sitemap_url));
delete_transient('mxchat_last_sitemap_url');
}
// Get the last PDF URL and clear its transient
$pdf_url = get_transient('mxchat_last_pdf_url');
if ($pdf_url) {
delete_transient('mxchat_pdf_status_' . md5($pdf_url));
delete_transient('mxchat_last_pdf_url');
}
// Unschedule any pending sitemap events
$timestamp = wp_next_scheduled('mxchat_process_sitemap_urls');
if ($timestamp) {
wp_unschedule_event($timestamp, 'mxchat_process_sitemap_urls');
}
// Redirect back with a success message
set_transient('mxchat_admin_notice_success',
esc_html__('Processing has been stopped successfully.', 'mxchat'),
30
);
wp_safe_redirect(admin_url('admin.php?page=mxchat-prompts'));
exit;
}
private function mxchat_sanitize_content_for_api($content) {
// Remove script, style tags, and HTML comments
$content = preg_replace('/