array( 'label' => __( 'Chat Sessions', 'wpbot-chat-history' ), 'icon' => 'dashicons-format-chat', ), 'not-answered' => array( 'label' => __( 'Questions Not Answered', 'wpbot-chat-history' ), 'icon' => 'dashicons-editor-help', ), 'ai-insight' => array( 'label' => __( 'AI Insight', 'wpbot-chat-history' ), 'icon' => 'dashicons-lightbulb', ), ); if ( function_exists( 'qcpdcs_is_woowbot_active' ) && qcpdcs_is_woowbot_active() ) { $tabs['woowbot-sessions'] = array( 'label' => __( 'ChatBot Sessions', 'wpbot-chat-history' ), 'icon' => 'dashicons-cart', ); } ?>

admin_url( 'admin-ajax.php' ), 'ajax_nonce' => wp_create_nonce( 'wpbot_session_ajax_nonce' ) ) ); wp_register_script( 'qcld-wp-dataTables-cs', QCLD_CHATBOT_FREE_SESSION_PLUGIN_URL . 'js/qcld-dataTables.min.js', array( 'jquery' ), QCLD_wpCHATBOT_VERSION, true ); wp_enqueue_script( 'qcld-wp-dataTables-cs' ); } // ─── AI Insight Page Callback ───────────────────────────────────────────────── function qcld_wpbot_schedule_session_reporting() { wp_register_style( 'qcld-wp-chatbot-history-style', QCLD_CHATBOT_FREE_SESSION_PLUGIN_URL . 'css/history-style.css', array(), QCLD_wpCHATBOT_VERSION, 'screen' ); wp_enqueue_style( 'qcld-wp-chatbot-history-style' ); ?>

show_errors = true; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, PluginCheck.Security.DirectDB.UnescapedDBParameter $table = $wpdb->prefix . 'wpbot_failed_response'; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, PluginCheck.Security.DirectDB.UnescapedDBParameter if ( isset( $_GET['msg'] ) && $_GET['msg'] == 'success' ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended echo '

Record has been Deleted Successfully!

'; } if ( isset( $_GET['action'] ) && $_GET['action'] == 'deleteall' ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended $wpdb->query( "TRUNCATE TABLE `$table`" ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter echo '

All Records have been deleted successfully!

'; } $sql = "SELECT * FROM $table WHERE 1 ORDER BY `id` DESC"; // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared $sql1 = "SELECT count(*) FROM $table WHERE 1 ORDER BY `id` DESC"; // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared $total = $wpdb->get_var( $sql1 ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter $items_per_page = 30; $page = isset( $_GET['cpage'] ) ? abs( (int) $_GET['cpage'] ) : 1; // phpcs:ignore WordPress.Security.NonceVerification.Recommended $offset = ( $page * $items_per_page ) - $items_per_page; $sql .= " LIMIT {$offset}, {$items_per_page}"; $result = $wpdb->get_results( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter $totalPage = ceil( $total / $items_per_page ); $customPagHTML = ''; if ( $totalPage > 1 ) { $customPagHTML = '
Page ' . esc_html( $page ) . ' of ' . esc_html( $totalPage ) . '' . paginate_links( array( 'base' => add_query_arg( 'cpage', '%#%' ), 'format' => '', 'prev_text' => __( '« prev' ), // phpcs:ignore WordPress.WP.I18n.MissingArgDomain 'next_text' => __( 'next »' ), // phpcs:ignore WordPress.WP.I18n.MissingArgDomain 'total' => esc_html( $totalPage ), 'current' => esc_html( $page ), ) ) . '
'; } wp_register_style( 'qcld-wp-chatbot-history-style', QCLD_CHATBOT_FREE_SESSION_PLUGIN_URL . 'css/history-style.css', array(), QCLD_wpCHATBOT_VERSION, 'screen' ); wp_enqueue_style( 'qcld-wp-chatbot-history-style' ); ?>

show_errors = true; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, PluginCheck.Security.DirectDB.UnescapedDBParameter $tableuser = $wpdb->prefix . 'wpbot_user'; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, PluginCheck.Security.DirectDB.UnescapedDBParameter $tableconversation = $wpdb->prefix . 'wpbot_conversation'; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, PluginCheck.Security.DirectDB.UnescapedDBParameter $mainurl = admin_url( 'admin.php?page=wbcs-botsessions-page' ); if ( isset( $_GET['min_interaction'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended $mainurl .= '&min_interaction=' . intval( $_GET['min_interaction'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended } if ( isset( $_GET['wp_user'] ) && $_GET['wp_user'] != '' ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended $mainurl .= '&wp_user=' . intval( $_GET['wp_user'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended } $msg = ''; if ( isset( $_GET['action'] ) && $_GET['action'] == 'deleteall' ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended $wpdb->query( "TRUNCATE TABLE `$tableuser`" ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter $wpdb->query( "TRUNCATE TABLE `$tableconversation`" ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter $msg = esc_html( 'All Sessions have been deleted successfully!' ); } if ( isset( $_GET['msg'] ) && $_GET['msg'] == 'success' ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended echo '

Record has been Deleted Successfully!

'; } if ( isset( $_GET['userid'] ) && $_GET['userid'] != '' ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended require_once QCLD_CHATBOT_FREE_SESSION_DIR_PATH . 'reports/view/partials/view-single-chat.php'; } else { wp_register_style( 'qcld-wp-chatbot-history-style', QCLD_CHATBOT_FREE_SESSION_PLUGIN_URL . 'css/history-style.css', array(), QCLD_wpCHATBOT_VERSION, 'screen' ); wp_enqueue_style( 'qcld-wp-chatbot-history-style' ); wp_register_style( 'qcld-wp-chatbot-jquery-ui', QCLD_CHATBOT_FREE_SESSION_PLUGIN_URL . 'css/jqueryui.css', array(), '', 'screen' ); wp_enqueue_style( 'qcld-wp-chatbot-jquery-ui' ); wp_register_script( 'qcld-wp-chatsession-admin-js', QCLD_CHATBOT_FREE_SESSION_PLUGIN_URL . 'js/chatsession.js', array( 'jquery' ), QCLD_wpCHATBOT_VERSION, true ); wp_enqueue_script( 'qcld-wp-chatsession-admin-js' ); wp_localize_script( 'qcld-wp-chatsession-admin-js', 'ajax_object', array( 'ajax_url' => admin_url( 'admin-ajax.php' ), 'ajax_nonce' => wp_create_nonce( 'wpbot_session_ajax_nonce' ) ) ); wp_register_script( 'qcld-wp-jqueryui-js', QCLD_CHATBOT_FREE_SESSION_PLUGIN_URL . 'js/jqueryui.js', array( 'jquery' ), QCLD_wpCHATBOT_VERSION, true ); wp_enqueue_script( 'qcld-wp-jqueryui-js' ); $where = ''; if ( isset( $_GET['min_interaction'] ) && $_GET['min_interaction'] != 'all' ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended if ( isset( $_GET['min_interaction'] ) && $_GET['min_interaction'] > 0 ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended $where = ' and `interaction` >= ' . intval( $_GET['min_interaction'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended } if ( isset( $_GET['min_interaction'] ) && $_GET['min_interaction'] == 0 ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended $where = ' and `interaction` = 0'; } } $wwhere = ''; if ( isset( $_GET['wp_user'] ) && $_GET['wp_user'] != 'all' && $_GET['wp_user'] != 0 && $_GET['wp_user'] != '' ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended $wwhere = ' and `user_id` = ' . intval( $_GET['wp_user'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended } $sql = "SELECT * FROM $tableuser WHERE 1 $where $wwhere ORDER BY `date` DESC"; // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared $sql1 = "SELECT count(*) FROM $tableuser WHERE 1 $where $wwhere"; // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared $dateFilter = ''; if ( isset( $_GET['FilterDate'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended if ( $_GET['FilterDate'] === 'LastWeek' ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended $dateFilter = " WHERE `date` >= CURDATE() - INTERVAL 7 DAY"; } if ( $_GET['FilterDate'] === 'LastMonth' ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended $dateFilter = " WHERE `date` >= CURDATE() - INTERVAL 30 DAY"; } if ( $_GET['FilterDate'] === 'Last3Months' ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended $dateFilter = " WHERE `date` >= CURDATE() - INTERVAL 90 DAY"; } $sql = "SELECT * FROM $tableuser $dateFilter $wwhere ORDER BY `date` DESC"; // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared $sql1 = "SELECT count(*) FROM $tableuser $dateFilter"; // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared } $total = $wpdb->get_var( $sql1 ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter $items_per_page = 30; $page = isset( $_GET['cpage'] ) ? abs( (int) $_GET['cpage'] ) : 1; // phpcs:ignore WordPress.Security.NonceVerification.Recommended $offset = ( $page * $items_per_page ) - $items_per_page; $sql .= " LIMIT {$offset}, {$items_per_page}"; $result = $wpdb->get_results( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter $totalPage = ceil( $total / $items_per_page ); $customPagHTML = ''; if ( $totalPage > 1 ) { $customPagHTML = '
Page ' . esc_html( $page ) . ' of ' . esc_html( $totalPage ) . '' . paginate_links( array( 'base' => add_query_arg( 'cpage', '%#%' ), 'format' => '', 'prev_text' => __( '« prev' ), // phpcs:ignore WordPress.WP.I18n.MissingArgDomain 'next_text' => __( 'next »' ), // phpcs:ignore WordPress.WP.I18n.MissingArgDomain 'total' => esc_html( $totalPage ), 'current' => esc_html( $page ), ) ) . '
'; } $deleteurl = admin_url( 'admin.php?page=wbcs-botsessions-page&action=deleteall' ); ?>

Filtering Records by: ' . esc_html( $filterText ) . '
'; } ?>

No result found.

show_errors = true; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, PluginCheck.Security.DirectDB.UnescapedDBParameter $tableuser1 = $wpdb->prefix . 'wpbot_user'; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, PluginCheck.Security.DirectDB.UnescapedDBParameter $tableconversation1 = $wpdb->prefix . 'wpbot_conversation'; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, PluginCheck.Security.DirectDB.UnescapedDBParameter $table = $wpdb->prefix . 'wpbot_failed_response'; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, PluginCheck.Security.DirectDB.UnescapedDBParameter // Delete single "not answered" record. if ( isset( $_GET['page'] ) && $_GET['page'] == 'wbcs-botsessions-notansweredpage' && isset( $_GET['act'] ) && $_GET['act'] == 'delete' ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended $userid = intval( $_GET['id'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended check_admin_referer( 'wpcs_delete_session_' . $userid ); $wpdb->delete( $table, array( 'id' => $userid ), array( '%d' ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching wp_safe_redirect( admin_url( 'admin.php?page=wbcs-botsessions-notansweredpage&msg=success' ) ); exit; } // Delete single chat session. if ( isset( $_GET['page'] ) && $_GET['page'] == 'wbcs-botsessions-page' && isset( $_GET['act'] ) && $_GET['act'] == 'delete' ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended $userid = intval( $_GET['userid'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended check_admin_referer( 'wpcs_delete_session_' . $userid ); $wpdb->delete( $tableuser1, array( 'id' => $userid ), array( '%d' ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching $wpdb->delete( $tableconversation1, array( 'user_id' => $userid ), array( '%d' ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching wp_safe_redirect( admin_url( 'admin.php?page=wbcs-botsessions-page&msg=success' ) ); exit; } // Export all sessions as CSV. if ( isset( $_POST['wpbot_session_export_all'] ) && isset( $_POST['wpbot_session_remove'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing check_admin_referer( 'wpcs_bulk_action' ); $users = $wpdb->get_results( "SELECT wu.`id`, wu.`session_id`, wu.`name`, wu.`email`, wu.`date`, wu.`phone`, wu.`interaction`, wc.`conversation` FROM $tableuser1 as wu, $tableconversation1 as wc WHERE 1 AND wu.id = wc.user_id LIMIT 5000" ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter $sessions = array(); if ( ! empty( $users ) ) { foreach ( $users as $user ) { $sessions[] = wpbot_conversations_export( $user ); } } qcld_wpbot_chatsession_download_send_headers( 'wpbot_chatsession_' . gmdate( 'Y-m-d' ) . '.csv' ); print wpbot_chatsession_array2csv( $sessions ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- raw CSV download, escaping would corrupt the file. exit; } // Export selected sessions or delete selected sessions. if ( isset( $_POST['wpbot_session_remove'] ) && ! empty( $_POST['sessions'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing check_admin_referer( 'wpcs_bulk_action' ); $userids = array_map( 'intval', $_POST['sessions'] ); // phpcs:ignore WordPress.Security.NonceVerification.Missing if ( isset( $_POST['wpbot_session_export'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing $sessions = array(); foreach ( $userids as $userid ) { $user = $wpdb->get_row( $wpdb->prepare( "SELECT wu.`id`, wu.`session_id`, wu.`name`, wu.`email`, wu.`date`, wu.`phone`, wu.`interaction`, wc.`conversation` FROM $tableuser1 as wu, $tableconversation1 as wc WHERE 1 AND wu.id = wc.user_id AND wu.id = %d", $userid ) ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter $sessions[] = wpbot_conversations_export( $user ); } qcld_wpbot_chatsession_download_send_headers( 'wpbot_chatsession_' . gmdate( 'Y-m-d' ) . '.csv' ); print wpbot_chatsession_array2csv( $sessions ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- raw CSV download, escaping would corrupt the file. exit; } if ( isset( $_POST['wpbot_session_delete'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing foreach ( $userids as $userid ) { $wpdb->delete( $tableuser1, array( 'id' => $userid ), array( '%d' ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching $wpdb->delete( $tableconversation1, array( 'user_id' => $userid ), array( '%d' ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching } wp_safe_redirect( admin_url( 'admin.php?page=wbcs-botsessions-page&msg=success' ) ); exit; } } } // ─── Admin Footer: Email Modal ──────────────────────────────────────────────── add_action( 'admin_footer', 'wpcs_admin_footer_content_free' ); function wpcs_admin_footer_content_free() { if ( isset( $_GET['page'] ) && $_GET['page'] == 'wbcs-botsessions-page' ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended ?>
×

prefix . 'wpbot_user'; $table_sql = esc_sql( $tableuser ); $cache_key = 'wpbot_user_email_' . md5( $to ); $user_exists = wp_cache_get( $cache_key, 'wpbot' ); if ( false === $user_exists ) { $user_exists = $wpdb->get_var( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery $wpdb->prepare( 'SELECT id FROM `' . $table_sql . '` WHERE email = %s LIMIT 1', // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared $to ) ); wp_cache_set( $cache_key, $user_exists, 'wpbot', 60 ); } $admin_email = get_option('admin_email'); if ( ! $user_exists && $to !== $admin_email ) { wp_send_json( array( 'status' => 'fail', 'message' => 'Invalid recipient address. Email must be a stored session email or admin email.' ) ); } $url = get_site_url(); $url = wp_parse_url( $url ); $domain = $url['host']; $fromEmail = 'wordpress@' . $domain; $headers = array( 'Content-Type: text/html; charset=UTF-8', 'From: ' . esc_html( $domain ) . ' <' . esc_html( $fromEmail ) . '>', ); $result = wp_mail( $to, $subject, $message, $headers ); if ( $result ) { $response = array( 'status' => 'success', 'message' => 'Email has been sent successfully!' ); } else { $response = array( 'status' => 'fail', 'message' => 'Unable to send email. Please contact your server administrator.' ); } ob_clean(); echo wp_json_encode( $response ); die(); } // ─── AJAX: Save Email Notification Preference ───────────────────────────────── add_action( 'wp_ajax_session_email_notification_update', 'session_email_notification_update_free' ); function session_email_notification_update_free() { if ( ! current_user_can( 'manage_options' ) ) { wp_die(); } $email_notification = sanitize_text_field( $_POST['email_notification'] ); // phpcs:ignore WordPress.Security.NonceVerification.Missing update_option( 'session_email_notification_update', $email_notification ); wp_send_json( array( 'success' => true ) ); } // ─── AJAX: Conversation Save (Frontend) ────────────────────────────────────── // This is the main conversation-save handler. Guarded with function_exists // so the Pro addon's definition wins if it's active. if ( ! function_exists( 'qcld_wb_chatbot_conversation_save' ) ) { function qcld_wb_chatbot_conversation_save() { check_ajax_referer( 'qcsecretbotnonceval123qc', 'security' ); global $wpdb; $tableuser = $wpdb->prefix . 'wpbot_user'; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, PluginCheck.Security.DirectDB.UnescapedDBParameter $tableconversation = $wpdb->prefix . 'wpbot_conversation'; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, PluginCheck.Security.DirectDB.UnescapedDBParameter // SECURITY FIX: Pass raw (decoded) input to qcld_wpbot_input_validation(), which now // correctly runs html_entity_decode() BEFORE wp_kses(). Previously, wp_kses() ran first // on entity-encoded input (<img onerror=...>), saw inert text, and passed it through. // html_entity_decode() then revived the executable markup after sanitization had already run. $raw_conversation = isset( $_POST['conversation'] ) ? wp_unslash( $_POST['conversation'] ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing $conversation = qcld_wpbot_input_validation( $raw_conversation ); // phpcs:ignore WordPress.Security.NonceVerification.Missing $email = isset( $_POST['email'] ) ? sanitize_email( $_POST['email'] ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing $phone = isset( $_POST['phone'] ) ? sanitize_text_field( $_POST['phone'] ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing $name = isset( $_POST['name'] ) ? sanitize_text_field( $_POST['name'] ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing $session_id = isset( $_POST['session_id'] ) ? sanitize_text_field( $_POST['session_id'] ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing $wpuser_id = isset( $_POST['user_id'] ) ? sanitize_text_field( $_POST['user_id'] ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing $source_url = isset( $_POST['source_url'] ) && ! empty( $_POST['source_url'] ) ? sanitize_url( wp_unslash( $_POST['source_url'] ) ) : ( isset( $_SERVER['HTTP_REFERER'] ) ? sanitize_url( wp_unslash( $_SERVER['HTTP_REFERER'] ) ) : '' ); // phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized $user_agent = isset( $_POST['user_agent'] ) && ! empty( $_POST['user_agent'] ) ? sanitize_text_field( wp_unslash( $_POST['user_agent'] ) ) : ( isset( $_SERVER['HTTP_USER_AGENT'] ) ? sanitize_text_field( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) ) : '' ); // phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized $session_mailed = isset( $_POST['session_mailed'] ) ? sanitize_text_field( $_POST['session_mailed'] ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing // Prepend source URL to conversation. $conversation = '<ul><li class="session_start_url"><span>Source URL: </span><a href="' . $source_url . '">' . $source_url . '</a></li></ul>' . $conversation; $response = array(); $response['status'] = 'success'; $user_exists = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $tableuser WHERE 1 AND session_id = %s", $session_id ) ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter $is_new_insert = false; if ( empty( $user_exists ) ) { $lock_key = 'wpcs_lock_' . md5( $session_id ); if ( add_option( $lock_key, '1', '', 'no' ) ) { $interaction = (int) substr_count( $conversation, 'wp-chat-user-msg' ); if ( $interaction == 0 ) { $interaction = (int) substr_count( $conversation, 'woo-chat-user-msg' ); } if ( $interaction != 0 ) { $wpdb->insert( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, PluginCheck.Security.DirectDB.UnescapedDBParameter $tableuser, array( 'date' => current_time( 'mysql' ), 'name' => $name, 'email' => $email, 'phone' => $phone, 'session_id' => $session_id, 'interaction' => $interaction, 'user_id' => $wpuser_id, ) ); $user_id = $wpdb->insert_id; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, PluginCheck.Security.DirectDB.UnescapedDBParameter $wpdb->insert( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, PluginCheck.Security.DirectDB.UnescapedDBParameter $tableconversation, array( 'user_id' => $user_id, 'conversation' => $conversation, 'interaction' => $interaction, 'environment_info' => $user_agent, ) ); $is_new_insert = true; } delete_option( $lock_key ); } else { $retries = 3; while ( $retries > 0 ) { usleep( 500000 ); $user_exists = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $tableuser WHERE 1 AND session_id = %s", $session_id ) ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter if ( ! empty( $user_exists ) ) { break; } $retries--; } } } if ( ! $is_new_insert && ! empty( $user_exists ) ) { $interaction = (int) substr_count( $conversation, 'wp-chat-user-msg' ); if ( $interaction == 0 ) { $interaction = (int) substr_count( $conversation, 'woo-chat-user-msg' ); } $user_id = isset( $user_exists->id ) ? $user_exists->id : get_current_user_id(); $wpdb->update( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, PluginCheck.Security.DirectDB.UnescapedDBParameter $tableuser, array( 'date' => current_time( 'mysql' ), 'name' => $name, 'email' => $email, 'phone' => $phone, 'interaction' => $interaction, 'user_id' => $wpuser_id, ), array( 'id' => $user_id ), array( '%s', '%s', '%s', '%s', '%d', '%d' ), array( '%d' ) ); $wpdb->update( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, PluginCheck.Security.DirectDB.UnescapedDBParameter $tableconversation, array( 'conversation' => $conversation, 'interaction' => $interaction, ), array( 'user_id' => $user_id ), array( '%s', '%d' ), array( '%d' ) ); } // Email notification for new session. if ( $is_new_insert && ( get_option( 'session_email_notification_update' ) == 'checked' ) ) { $admin_email = get_option( 'admin_email' ); $subject = esc_html__( 'Someone has started a new chat session with ChatBot.', 'chatbot' ); $bodyContent = '

' . esc_html__( 'Hi,', 'chatbot' ) . '

'; $bodyContent .= '

' . esc_html__( 'Someone has started a new chat session with ChatBot. Please go to ', 'chatbot' ) . '' . esc_html__( 'Bot Sessions Dashboard', 'chatbot' ) . '' . esc_html__( ' and find him/her.', 'chatbot' ) . '

'; $bodyContent .= ''; $bodyContent .= '

' . esc_html__( 'Thanks', 'chatbot' ) . '

'; $bodyContent .= '

' . esc_html__( '(You can disable email notifications from ', 'chatbot' ) . '' . esc_html__( 'Bot - Sessions)', 'chatbot' ) . '

'; $to = get_option( 'qlcd_wp_chatbot_admin_email' ) != '' ? get_option( 'qlcd_wp_chatbot_admin_email' ) : $admin_email; $headers = array( 'Content-Type: text/html; charset=UTF-8' ); wp_mail( $to, $subject, $bodyContent, $headers ); } // WPBot Automator Trigger - Debounced by 3 minutes $cron_args = array( $session_id ); if ( wp_next_scheduled( 'wpbot_automator_delayed_trigger', $cron_args ) ) { wp_clear_scheduled_hook( 'wpbot_automator_delayed_trigger', $cron_args ); } wp_schedule_single_event( time() + 60, 'wpbot_automator_delayed_trigger', $cron_args ); echo wp_json_encode( $response ); die(); } } add_action( 'wp_ajax_qcld_wb_chatbot_conversation_save', 'qcld_wb_chatbot_conversation_save' ); add_action( 'wp_ajax_nopriv_qcld_wb_chatbot_conversation_save', 'qcld_wb_chatbot_conversation_save' ); // ─── AJAX: Date Filter ──────────────────────────────────────────────────────── add_action( 'wp_ajax_qcld_chatbot_session_date_filter', 'qcld_chatbot_session_date_filter_free' ); function qcld_chatbot_session_date_filter_free() { if ( ! current_user_can( 'manage_options' ) ) { wp_die(); } check_ajax_referer( 'wpbot_session_ajax_nonce', 'security' ); global $wpdb; $tableuser = $wpdb->prefix . 'wpbot_user'; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, PluginCheck.Security.DirectDB.UnescapedDBParameter $start_date = sanitize_text_field( $_POST['start_date'] ); // phpcs:ignore WordPress.Security.NonceVerification.Missing $end_date = sanitize_text_field( $_POST['end_date'] ); // phpcs:ignore WordPress.Security.NonceVerification.Missing $result = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $tableuser WHERE date BETWEEN %s AND %s", $start_date, $end_date ) ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter echo wp_json_encode( $result ); wp_die(); } // ─── AJAX: Email Transcript ─────────────────────────────────────────────────── add_action( 'wp_ajax_wpbot_send_email_transcript', 'wpbot_send_email_transcript_free' ); function wpbot_send_email_transcript_free() { if ( ! current_user_can( 'manage_options' ) ) { wp_send_json( array( 'status' => 'fail', 'message' => 'Unauthorized' ) ); } check_ajax_referer( 'wpbot_session_ajax_nonce', 'security' ); global $wpdb; $session = trim( sanitize_text_field( $_POST['session'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing $url = wp_parse_url( get_site_url() ); $domain = $url['host']; $admin_email = get_option( 'admin_email' ); $fromEmail = get_option( 'qlcd_wp_chatbot_from_email' ) ? get_option( 'qlcd_wp_chatbot_from_email' ) : 'wordpress@' . $domain; $subject = 'Chat transcript by ' . get_bloginfo( 'name' ); $tableuser = $wpdb->prefix . 'wpbot_user'; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, PluginCheck.Security.DirectDB.UnescapedDBParameter $tableconversation = $wpdb->prefix . 'wpbot_conversation'; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, PluginCheck.Security.DirectDB.UnescapedDBParameter $user = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $tableuser WHERE 1 AND session_id = %s", $session ) ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter $response = array( 'status' => 'fail', 'message' => 'Session not found.' ); if ( ! empty( $user ) ) { $email = sanitize_email( $user->email ); // Use email from user record if ( empty( $email ) ) { wp_send_json( array( 'status' => 'fail', 'message' => 'User has no email.' ) ); } $result = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $tableconversation WHERE 1 AND user_id = %d", $user->id ) ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter $bodyContent = ''; $bodyContent .= '

' . esc_html__( 'User Details', 'chatbot' ) . ':


'; $bodyContent .= '

' . esc_html__( 'Name', 'chatbot' ) . ' : ' . esc_html( $user->name ) . '

'; $bodyContent .= '

' . esc_html__( 'Email', 'chatbot' ) . ' : ' . esc_html( $email ) . '

'; $bodyContent .= '

Conversations

-----------------------

'; $messages = qcld_wpch_conversation_extract( htmlspecialchars_decode( $result->conversation ) ); foreach ( $messages as $message ) { if ( isset( $message['bot'] ) && trim( $message['bot'] ) != '' ) { $bodyContent .= '

Chatbot : ' . esc_html( trim( $message['bot'] ) ) . '

'; } if ( isset( $message['user'] ) && trim( $message['user'] ) != '' ) { $bodyContent .= '

' . esc_html( $user->name ) . ' : ' . esc_html( trim( $message['user'] ) ) . '

'; } } $bodyContent .= '

-----------------------

'; $bodyContent .= '

Mail Generated on: ' . current_time( 'F j, Y, g:i a' ) . '

'; $headers = array( 'Content-Type: text/html; charset=UTF-8', 'From: ' . esc_html( $user->name ) . ' <' . esc_html( $fromEmail ) . '>', 'Reply-To: ' . esc_html( $user->name ) . ' <' . esc_html( $email ) . '>', ); $result_mail = wp_mail( $email, $subject, $bodyContent, $headers ); if ( $result_mail ) { $response = array( 'status' => 'success', 'message' => 'Email transcript sent successfully.' ); } } echo wp_json_encode( $response ); die(); } // ─── AJAX: Forward Session to Email ────────────────────────────────────────── add_action( 'wp_ajax_forward_session_to_email', 'forward_session_to_email_free' ); function forward_session_to_email_free() { if ( ! current_user_can( 'manage_options' ) ) { wp_send_json( array( 'success' => false, 'msg' => esc_html__( 'Insufficient permissions', 'chatbot' ) ) ); wp_die(); } check_ajax_referer( 'wpbot_session_ajax_nonce', 'security' ); global $wpdb; $session_id = sanitize_text_field( $_POST['session_id'] ); // phpcs:ignore WordPress.Security.NonceVerification.Missing $to = sanitize_email( $_POST['email'] ); // phpcs:ignore WordPress.Security.NonceVerification.Missing $tableuser = $wpdb->prefix . 'wpbot_user'; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, PluginCheck.Security.DirectDB.UnescapedDBParameter $tableconversation = $wpdb->prefix . 'wpbot_conversation'; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, PluginCheck.Security.DirectDB.UnescapedDBParameter $userinfo = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $tableuser WHERE 1 AND session_id = %s", $session_id ) ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter $result = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $tableconversation WHERE 1 AND user_id = %d", $userinfo->id ) ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter if ( ! empty( $result ) ) { $raw_html = isset( $result->conversation ) ? (string) $result->conversation : ''; $decoded_content = html_entity_decode( $raw_html ); $doc = new DOMDocument(); libxml_use_internal_errors( true ); $doc->loadHTML( '' . $decoded_content ); libxml_clear_errors(); $decoded_content = ''; $body_nodes = $doc->getElementsByTagName( 'body' ); if ( $body_nodes->length > 0 ) { foreach ( $body_nodes->item( 0 )->childNodes as $child_node ) { $decoded_content .= $doc->saveHTML( $child_node ); } } $email_body = '' . $decoded_content . ''; $subject = isset( $_POST['subject'] ) ? sanitize_text_field( wp_unslash( $_POST['subject'] ) ) : 'Chat Session Transcript'; // phpcs:ignore WordPress.Security.NonceVerification.Missing if ( empty( $subject ) ) { $subject = 'Chat Session Transcript'; } $headers = array( 'Content-Type: text/html; charset=UTF-8' ); wp_mail( $to, $subject, $email_body, $headers ); wp_send_json( array( 'success' => true, 'msg' => esc_html__( 'Session has been forwarded to email successfully', 'chatbot' ) ) ); wp_die(); } else { wp_send_json( array( 'success' => false, 'msg' => esc_html__( 'No conversation found for this session', 'chatbot' ) ) ); wp_die(); } } // ─── AJAX: Session Hover Details ───────────────────────────────────────────── add_action( 'wp_ajax_wpbot_session_hover_details', 'wpbot_session_hover_details_free' ); function wpbot_session_hover_details_free() { if ( ! current_user_can( 'manage_options' ) ) { wp_send_json( array( 'success' => false, 'msg' => esc_html__( 'Insufficient permissions', 'chatbot' ) ) ); wp_die(); } check_ajax_referer( 'wpbot_session_ajax_nonce', 'security' ); global $wpdb; $session_id = sanitize_text_field( $_POST['session_id'] ); // phpcs:ignore WordPress.Security.NonceVerification.Missing $tableconversation = $wpdb->prefix . 'wpbot_conversation'; $tableuser = $wpdb->prefix . 'wpbot_user'; $email_from = get_option( 'qlcd_wp_chatbot_from_email' ); $result = $wpdb->get_row( $wpdb->prepare( "SELECT c.*, u.email, u.name, u.session_id as user_session_id FROM $tableconversation AS c LEFT JOIN $tableuser AS u ON c.user_id = u.id WHERE c.user_id = %d", $session_id ) ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter if ( ! empty( $result ) ) { $result->email_from = $email_from; $result->status = 'success'; // SECURITY FIX: The stored conversation is entity-encoded (htmlspecialchars output). // Decode it and re-sanitize with wp_kses before returning to the admin UI. // This guarantees admin.js always receives clean, safe HTML — no onerror/onclick can survive. if ( isset( $result->conversation ) ) { $decoded = html_entity_decode( (string) $result->conversation, ENT_QUOTES | ENT_HTML5, 'UTF-8' ); $result->conversation = wp_kses( $decoded, wpbot_get_safe_conversation_tags() ); } } echo wp_json_encode( $result ); wp_die(); } // ─── AJAX: Send Reply Email ─────────────────────────────────────────────────── add_action( 'wp_ajax_wpbot_send_reply_email', 'wpbot_send_reply_email_free' ); function wpbot_send_reply_email_free() { if ( ! current_user_can( 'manage_options' ) ) { wp_send_json( array( 'success' => false, 'msg' => esc_html__( 'Insufficient permissions', 'chatbot' ) ) ); wp_die(); } check_ajax_referer( 'wpbot_session_ajax_nonce', 'security' ); $to = isset( $_POST['email'] ) ? sanitize_email( $_POST['email'] ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing $from_raw = isset( $_POST['from_email'] ) ? trim( wp_unslash( $_POST['from_email'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing $from = sanitize_email( $from_raw ); $subject = isset( $_POST['subject'] ) ? sanitize_text_field( wp_unslash( $_POST['subject'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing $message = isset( $_POST['message'] ) ? wp_kses_post( wp_unslash( $_POST['message'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing if ( empty( $to ) || empty( $message ) ) { wp_send_json( array( 'success' => false, 'msg' => esc_html__( 'Email and Message are required', 'chatbot' ) ) ); wp_die(); } // if ( ! empty( $from_raw ) && ( $from_raw !== $from || ! is_email( $from ) ) ) { // wp_send_json( array( 'success' => false, 'msg' => esc_html__( 'Please enter a valid From email address', 'chatbot' ) ) ); // wp_die(); // } $headers = array( 'Content-Type: text/html; charset=UTF-8' ); if ( ! empty( $from ) && is_email( $from ) ) { $headers[] = 'From: ' . $from; } // Convert newlines to HTML line breaks $email_body = nl2br( $message ); $sent = wp_mail( $to, $subject, $email_body, $headers ); if ( $sent ) { wp_send_json( array( 'success' => true, 'msg' => esc_html__( 'Email replied successfully', 'chatbot' ) ) ); } else { wp_send_json( array( 'success' => false, 'msg' => esc_html__( 'Failed to send email', 'chatbot' ) ) ); } wp_die(); } // ─── AJAX: Save Cron Settings ───────────────────────────────────────────────── add_action( 'wp_ajax_wpbot_seesion_corn_save', 'wpbot_seesion_corn_save_free' ); function wpbot_seesion_corn_save_free() { if ( ! current_user_can( 'manage_options' ) ) { wp_send_json( array( 'success' => false, 'msg' => esc_html__( 'Insufficient permissions', 'chatbot' ) ) ); wp_die(); } $wbsession_ai_enabled = isset( $_POST['ai_enabled'] ) ? sanitize_text_field( $_POST['ai_enabled'] ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing $wbsession_corn_schedule_interval = isset( $_POST['corn_schedule_interval'] ) ? sanitize_text_field( $_POST['corn_schedule_interval'] ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing $qcld_wpsession_corn_promt = isset( $_POST['qcld_wpsession_corn_promt'] ) ? sanitize_text_field( $_POST['qcld_wpsession_corn_promt'] ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing $qcld_wbsession_corn_starttime = isset( $_POST['qcld_wbsession_corn_starttime'] ) ? sanitize_text_field( $_POST['qcld_wbsession_corn_starttime'] ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing $openai_enabled = get_option( 'ai_enabled' ); $apiKey = get_option( 'open_ai_api_key' ); if ( $openai_enabled != '1' ) { wp_send_json( array( 'success' => false, 'icon' => 'error', 'response' => esc_html__( 'OpenAI is Not Enabled', 'chatbot' ) ) ); wp_die(); } if ( $apiKey == '' ) { wp_send_json( array( 'success' => false, 'icon' => 'error', 'response' => esc_html__( 'OpenAI API key is not set', 'chatbot' ) ) ); wp_die(); } update_option( 'qcld_wbsession_ai_enable', $wbsession_ai_enabled ); update_option( 'qcld_wbsession_corn_interval', $wbsession_corn_schedule_interval ); update_option( 'qcld_wbsession_corn_starttime', $qcld_wbsession_corn_starttime ); update_option( 'qcld_wpsession_corn_promt', $qcld_wpsession_corn_promt ); wp_clear_scheduled_hook( 'qcld_wpsession_mysql_scraper_event' ); wp_send_json( array( 'success' => true, 'icon' => 'success', 'response' => esc_html__( 'Settings Saved Successfully', 'chatbot' ) ) ); wp_die(); } // ─── AJAX: Manual AI Scraper ────────────────────────────────────────────────── add_action( 'wp_ajax_qcld_chatbot_session_mannual_scraper', 'qcld_chatbot_session_mannual_scraper_free' ); if ( ! function_exists( 'qcld_chatbot_session_mannual_scraper_free' ) ) { function qcld_chatbot_session_mannual_scraper_free() { if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error( array( 'msg' => 'Insufficient permissions.' ) ); wp_die(); } if ( get_option( 'qcld_wbsession_ai_enable' ) != '1' ) { wp_send_json( array( 'success' => false, 'icon' => 'error', 'response' => esc_html__( 'AI Insight is not enabled.', 'chatbot' ) ) ); wp_die(); } global $wpdb; $num = isset( $_POST['wpchatbot_session_mannual_number'] ) ? intval( $_POST['wpchatbot_session_mannual_number'] ) : 20; // phpcs:ignore WordPress.Security.NonceVerification.Missing if ( ! is_numeric( $num ) || $num <= 0 ) { wp_send_json( array( 'success' => false, 'icon' => 'error', 'response' => esc_html__( 'Invalid number of sessions.', 'chatbot' ) ) ); wp_die(); } $tableuser = $wpdb->prefix . 'wpbot_user'; $tableconversation = $wpdb->prefix . 'wpbot_conversation'; $results = $wpdb->get_results( $wpdb->prepare( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter "SELECT u.id, c.user_id, u.date, u.session_id, c.id AS conversation_id, c.conversation FROM $tableuser AS u LEFT JOIN $tableconversation AS c ON u.id = c.user_id ORDER BY u.date DESC LIMIT %d", $num ) // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared ); $remarkable_session = array(); foreach ( $results as $row ) { $trimmed = wpsession_message_html_filter_free( htmlspecialchars_decode( $row->conversation ) ); $remarkable_session[] = array( 'id' => $row->session_id, 'conversation' => $trimmed ); } $keyword = get_option( 'qcld_wpsession_corn_promt' ) ?: 'Below is Chat conversation session data from our users on our website. Each conversation starts with an ID. Can you analyze each conversation and summarize each of them? Note down the total number of conversations you analyzed. Create a condensed summary at the end of your report for all the conversations. Point out the important questions asked by the users below the summary and include the IDs for the important points.'; $gptkeyword = array( array( 'role' => 'system', 'content' => array( array( 'type' => 'input_text', 'text' => $keyword ) ) ), array( 'role' => 'user', 'content' => array( array( 'type' => 'input_text', 'text' => wp_json_encode( $remarkable_session ) ) ) ), ); $api_key = get_option( 'open_ai_api_key' ); $engines = get_option( 'openai_engines' ); $post_fields = array( 'model' => $engines, 'input' => $gptkeyword ); $api_response = wp_remote_post( 'https://api.openai.com/v1/responses', array( 'headers' => array( 'Content-Type' => 'application/json', 'Authorization' => 'Bearer ' . $api_key, ), 'body' => wp_json_encode( $post_fields ), 'timeout' => 60, ) ); $result = is_wp_error( $api_response ) ? '' : wp_remote_retrieve_body( $api_response ); $mess = json_decode( $result ); if ( ! empty( $mess->error ) ) { wp_send_json( array( 'status' => 'error', 'icon' => 'error', 'msg' => esc_html( $mess->error->code ), 'response' => esc_html( $mess->error->message ) ) ); wp_die(); } $msg = isset( $mess->output[0]->content ) ? $mess->output[0]->content[0]->text : ( $mess->output[1]->content[0]->text ?? '' ); $msg = preg_replace( "/\r\n|\r|\n/", '
', $msg ); $to = get_option( 'qlcd_wp_chatbot_admin_email' ) ?: get_option( 'admin_email' ); $headers = array( 'Content-Type: text/html; charset=UTF-8', 'From: ' . esc_html( get_bloginfo( 'name' ) ) . ' ', ); wp_mail( $to, 'ChatBot Sessions Analysis', $msg, $headers ); wp_send_json( array( 'status' => 'success', 'icon' => 'success', 'response' => 'Please Check Email for Report' ) ); wp_die(); } } // ─── Helper: HTML filter for AI scraper ────────────────────────────────────── if ( ! function_exists( 'wpsession_message_html_filter_free' ) ) { function wpsession_message_html_filter_free( $html ) { $dom = new DOMDocument(); libxml_use_internal_errors( true ); $dom->loadHTML( '' . $html ); $lis = $dom->getElementsByTagName( 'li' ); $full_conversation = array(); foreach ( $lis as $li ) { $agentDiv = $li->getElementsByTagName( 'div' )->item( 1 ); $paragraphDiv = $li->getElementsByTagName( 'div' )->item( 2 ); if ( $paragraphDiv ) { $full_conversation[] = array( 'id' => trim( $agentDiv->textContent ), 'conversation' => trim( $paragraphDiv->textContent ), ); } } return wp_json_encode( $full_conversation ); } } // ─── Helper: Conversation Extract ──────────────────────────────────────────── if ( ! function_exists( 'qcld_wpch_conversation_extract' ) ) { function qcld_wpch_conversation_extract( $html ) { $doc = new DOMDocument(); libxml_use_internal_errors( true ); $doc->loadHTML( '' . $html ); $lis = iterator_to_array( $doc->getElementsByTagName( 'li' ) ); $messages = array(); foreach ( $lis as $li ) { if ( strpos( $li->getAttribute( 'class' ), 'wp-chatbot-msg' ) !== false ) { $messages[]['bot'] = trim( $li->textContent ); } if ( strpos( $li->getAttribute( 'class' ), 'wp-chat-user-msg' ) !== false ) { $messages[]['user'] = trim( $li->textContent ); } } $messages = array_filter( $messages, function( $val ) { if ( isset( $val['bot'] ) && empty( $val['bot'] ) ) { return false; } return true; } ); return $messages; } } // ─── CSV Export Helpers ─────────────────────────────────────────────────────── add_action( 'admin_post_wpbot_conversations.csv', 'wpbot_conversations_csv_export_free' ); function wpbot_conversations_csv_export_free() { if ( ! current_user_can( 'manage_options' ) ) { wp_die( esc_html__( 'Unauthorized', 'chatbot' ) ); } if ( ! isset( $_GET['_wpnonce'] ) || ! wp_verify_nonce( sanitize_key( $_GET['_wpnonce'] ), 'wpbot_conversations_csv' ) ) { wp_die( esc_html__( 'Security check failed.', 'chatbot' ) ); } global $wpdb; $tableuser = $wpdb->prefix . 'wpbot_user'; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, PluginCheck.Security.DirectDB.UnescapedDBParameter $tableconversation = $wpdb->prefix . 'wpbot_conversation'; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, PluginCheck.Security.DirectDB.UnescapedDBParameter $userid = sanitize_text_field( $_GET['user_id'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended $userinfo = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $tableuser WHERE 1 AND id = %d", $userid ) ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter $result = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $tableconversation WHERE 1 AND user_id = %d", $userid ) ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter $data = array(); if ( ! empty( $result ) ) { $data[] = array( 'User Name', $userinfo->name ); $data[] = array( 'User Email', $userinfo->email ); $data[] = array( 'Session ID', $userinfo->session_id ); $data[] = array( 'Date', gmdate( 'M,d,Y h:i:s A', strtotime( $userinfo->date ) ) ); $data[] = array( 'Bot Message', 'User Message' ); $messages = qcld_wpch_conversation_extract( htmlspecialchars_decode( $result->conversation ) ); foreach ( $messages as $message ) { if ( isset( $message['bot'] ) && trim( $message['bot'] ) != '' ) { $data[] = array( str_replace( ' ', ' ', trim( $message['bot'] ) ), '' ); } if ( isset( $message['user'] ) && trim( $message['user'] ) != '' ) { $data[] = array( '', str_replace( ' ', ' ', trim( $message['user'] ) ) ); } } } qcld_wpbot_chatsession_download_send_headers( $userinfo->name . '_wpbot_chatsession_' . gmdate( 'Y-m-d' ) . '.csv' ); print wpbot_chatsession_array2csv( $data ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- raw CSV download, escaping would corrupt the file. } if ( ! function_exists( 'wpbot_conversations_export' ) ) { function wpbot_conversations_export( $user ) { $user_id = isset( $user->id ) ? $user->id : $user; $dataArray = array(); if ( ! empty( $user ) ) { $messages = qcld_wpch_conversation_extract( htmlspecialchars_decode( $user->conversation ) ); $dataArray = array( 'Session ID' => $user->session_id, 'Date' => gmdate( 'M,d,Y h:i:s A', strtotime( $user->date ) ), 'User Name' => $user->name, 'User Email' => $user->email, ); $conversations = ''; foreach ( $messages as $message ) { if ( isset( $message['bot'] ) && trim( $message['bot'] ) != '' ) { $conversations .= 'Bot Message: ' . str_replace( ' ', ' ', trim( $message['bot'] ) ) . "\n"; } if ( isset( $message['user'] ) && trim( $message['user'] ) != '' ) { $conversations .= 'User Message: ' . str_replace( ' ', ' ', trim( $message['user'] ) ) . "\n"; } } $dataArray['Conversations'] = $conversations; } $dataArray['Interaction'] = $user->interaction; return $dataArray; } } if ( ! function_exists( 'qcld_wpbot_chatsession_download_send_headers' ) ) { function qcld_wpbot_chatsession_download_send_headers( $filename ) { $now = gmdate( 'D, d M Y H:i:s' ); header( 'Expires: Tue, 03 Jul 2001 06:00:00 GMT' ); header( 'Cache-Control: max-age=0, no-cache, must-revalidate, proxy-revalidate' ); header( "Last-Modified: {$now} GMT" ); header( 'Content-Encoding: UTF-8' ); header( 'Content-type: text/csv; charset=UTF-8' ); header( "Content-Disposition: attachment;filename={$filename}" ); header( 'Content-Transfer-Encoding: binary' ); } } if ( ! function_exists( 'wpbot_chatsession_array2csv' ) ) { function wpbot_chatsession_array2csv( array &$array ) { if ( count( $array ) == 0 ) { return null; } ob_start(); // phpcs:disable WordPress.WP.AlternativeFunctions.file_system_operations_fopen, WordPress.WP.AlternativeFunctions.file_system_operations_fputs, WordPress.WP.AlternativeFunctions.file_system_operations_fclose -- php://output memory stream for CSV export. $df = fopen( 'php://output', 'w' ); fputs( $df, chr( 0xEF ) . chr( 0xBB ) . chr( 0xBF ) ); // UTF-8 BOM foreach ( $array as $data ) { fputcsv( $df, array_keys( $data ), ',', '"', '\\' ); break; } foreach ( $array as $row ) { fputcsv( $df, $row, ',', '"', '\\' ); } fclose( $df ); // phpcs:enable WordPress.WP.AlternativeFunctions.file_system_operations_fopen, WordPress.WP.AlternativeFunctions.file_system_operations_fputs, WordPress.WP.AlternativeFunctions.file_system_operations_fclose return ob_get_clean(); } } // ─── Shortcode: User Session History ───────────────────────────────────────── if ( ! function_exists( 'qc_current_user_session' ) ) { function qc_current_user_session() { $user = wp_get_current_user(); global $wpdb; $tableuser = $wpdb->prefix . 'wpbot_user'; $conversatios_table = $wpdb->prefix . 'wpbot_conversation'; $result = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $tableuser AS u LEFT JOIN $conversatios_table AS c ON u.user_id = c.user_id WHERE u.user_id = %d", $user->ID ) ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter if ( ! $user->exists() ) { return '

No user logged in.

'; } ob_start(); ?> $value ) : ?>
date ); ?> session_id ); ?> name ); ?>
( get_option( 'qcld_wbsession_corn_interval' ) != null ) ? get_option( 'qcld_wbsession_corn_interval' ) : 86400, 'display' => esc_attr__( 'Session min', 'chatbot' ), ); return $schedules; } } $wpsession_corn_start_times = wp_date( 'Y-m-d' ) . ' ' . get_option( 'qcld_wbsession_corn_starttime' ); $wpsession_corn_start_time = strtotime( $wpsession_corn_start_times ); if ( ! wp_next_scheduled( 'qcld_wpsession_mysql_scraper_event' ) && ( get_option( 'qcld_wbsession_ai_enable' ) == '1' ) ) { wp_schedule_event( $wpsession_corn_start_time, 'session_schedules', 'qcld_wpsession_mysql_scraper_event' ); } add_action( 'qcld_wpsession_mysql_scraper_event', 'qcld_wpsession_mysql_scraper_function_free' ); if ( ! function_exists( 'qcld_wpsession_mysql_scraper_function_free' ) ) { function qcld_wpsession_mysql_scraper_function_free() { if ( get_option( 'qcld_wbsession_ai_enable' ) != '1' ) { return; } global $wpdb; $interval_hours = ( (int) get_option( 'qcld_wbsession_corn_interval' ) ?: 86400 ) / 3600; $tableuser = $wpdb->prefix . 'wpbot_user'; $tableconversation = $wpdb->prefix . 'wpbot_conversation'; $results = $wpdb->get_results( $wpdb->prepare( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter "SELECT u.id, c.user_id, u.date, u.session_id, c.id, c.conversation FROM $tableuser AS u LEFT JOIN $tableconversation AS c ON u.id = c.user_id WHERE u.date >= (NOW() - INTERVAL %d HOUR) ORDER BY u.date DESC", $interval_hours ) // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared ); $remarkable_session = array(); foreach ( $results as $row ) { $remarkable_session[] = array( 'id' => $row->session_id, 'conversation' => wpsession_message_html_filter_free( htmlspecialchars_decode( $row->conversation ) ) ); } $keyword = get_option( 'qcld_wpsession_corn_promt' ) ?: 'Below is Chat conversation session data from our users on our website. Each conversation starts with an ID. Can you analyze each conversation and summarize each of them?'; $gptkeyword = array( array( 'role' => 'system', 'content' => array( array( 'type' => 'input_text', 'text' => $keyword ) ) ), array( 'role' => 'user', 'content' => array( array( 'type' => 'input_text', 'text' => wp_json_encode( $remarkable_session ) ) ) ), ); $api_key = get_option( 'open_ai_api_key' ); $engines = get_option( 'openai_engines' ); $post_fields = array( 'model' => $engines, 'input' => $gptkeyword ); $api_response = wp_remote_post( 'https://api.openai.com/v1/responses', array( 'headers' => array( 'Content-Type' => 'application/json', 'Authorization' => 'Bearer ' . $api_key, ), 'body' => wp_json_encode( $post_fields ), 'timeout' => 60, ) ); $result = is_wp_error( $api_response ) ? '' : wp_remote_retrieve_body( $api_response ); $mess = json_decode( $result ); $msg = isset( $mess->output[0]->content[0]->text ) ? $mess->output[0]->content[0]->text : ( isset( $mess->output[1]->content[0]->text ) ? $mess->output[1]->content[0]->text : 'No response from OpenAI.' ); $msg = preg_replace( "/\r\n|\r|\n/", '
', $msg ); $to = get_option( 'qlcd_wp_chatbot_admin_email' ) ?: get_option( 'admin_email' ); $headers = array( 'Content-Type: text/html; charset=UTF-8', 'From: ' . esc_html( get_bloginfo( 'name' ) ) . ' ', ); wp_mail( $to, 'ChatBot Sessions Analysis', $msg, $headers ); } } // ─── Reports (Bot - Reports submenu) ───────────────────────────────────────── require_once QCLD_CHATBOT_FREE_SESSION_DIR_PATH . 'reports/chatbot-history-reporting.php';