PluginProbe
WPBot – AI ChatBot for Live Support, Lead Generation, WordPress Automation, AI Services / 8.4.9
WPBot – AI ChatBot for Live Support, Lead Generation, WordPress Automation, AI Services v8.4.9
8.7.7 8.7.6 8.7.5 8.7.4 8.7.3 8.7.2 8.7.1 8.7.0 8.6.9 8.6.8 8.6.7 8.6.6 8.6.5 8.6.4 8.6.2 8.6.1 8.6.0 8.5.9 8.5.8 8.5.7 8.5.6 8.5.5 8.5.4 8.5.3 8.5.2 All 533 releases
chatbot / includes / chat-sessions / wpbot-chat-sessions.php

wpbot-chat-sessions.php in WPBot – AI ChatBot for Live Support, Lead Generation, WordPress Automation, AI Services 8.4.9, at includes/chat-sessions/wpbot-chat-sessions.php

1,159 lines 62.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * WPBot Sessions & Analytics — Built-in Chat Session Module
4 *
5 * Provides full chat session recording, analytics, AI Insight, and
6 * "Questions Not Answered" reporting natively in the free chatbot plugin.
7 *
8 * This module is a port of the Pro plugin's chat-session-addon.
9 * It uses the SAME database table names (wpbot_user, wpbot_conversation,
10 * wpbot_failed_response) so data is shared if the Pro addon is later activated.
11 *
12 * Everything is guarded with function_exists() checks so that when the Pro
13 * addon IS active it takes full precedence and this code is skipped entirely.
14 */
15
16 if ( ! defined( 'ABSPATH' ) ) {
17 exit;
18 }
19
20 // ─── Guard: Do not run if the Pro addon is active ────────────────────────────
21 // The Pro addon defines qcwp_chat_session_menu_fnc(); if that function already
22 // exists we skip everything here to avoid duplicate menus / conflicts.
23 if ( function_exists( 'qcwp_chat_session_menu_fnc' ) ) {
24 return;
25 }
26
27 // ─── Constants ────────────────────────────────────────────────────────────────
28 // Define our own URL / path constants for assets.
29 // Also define the legacy constant names that all copied report partials reference,
30 // so those files work without modification.
31
32 if ( ! defined( 'QCLD_CHATBOT_FREE_SESSION_PLUGIN_URL' ) ) {
33 define( 'QCLD_CHATBOT_FREE_SESSION_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
34 }
35 if ( ! defined( 'QCLD_CHATBOT_FREE_SESSION_DIR_PATH' ) ) {
36 define( 'QCLD_CHATBOT_FREE_SESSION_DIR_PATH', plugin_dir_path( __FILE__ ) );
37 }
38
39 // Legacy alias constants — used by all copied partials / report files.
40 if ( ! defined( 'QCLD_wpCHATBOT_HISTORY_PLUGIN_URL' ) ) {
41 define( 'QCLD_wpCHATBOT_HISTORY_PLUGIN_URL', QCLD_CHATBOT_FREE_SESSION_PLUGIN_URL );
42 }
43 if ( ! defined( 'QCLD_WPCHATBOT_HISTORY_DIR_PATH' ) ) {
44 define( 'QCLD_WPCHATBOT_HISTORY_DIR_PATH', QCLD_CHATBOT_FREE_SESSION_DIR_PATH );
45 }
46
47 // ─── Database Structure ───────────────────────────────────────────────────────
48 require_once QCLD_CHATBOT_FREE_SESSION_DIR_PATH . 'inc/chatsession-db-structure.php';
49
50 // ─── Admin Menu ───────────────────────────────────────────────────────────────
51 add_action( 'admin_menu', 'qcwp_chat_session_menu_fnc_free' );
52
53 function qcwp_chat_session_menu_fnc_free() {
54
55 $capability = function_exists( 'qcld_wpbot_get_menu_capability' ) ? qcld_wpbot_get_menu_capability( 'sessions' ) : 'manage_options';
56
57 if ( current_user_can( $capability ) ) {
58
59 add_menu_page(
60 'WPBot Sessions & Analytics',
61 'WPBot Sessions & Analytics',
62 $capability,
63 'wbcs-botsessions-page',
64 'qc_wpbot_cs_menu_page_callback_func',
65 'dashicons-chart-bar',
66 '9'
67 );
68
69 add_submenu_page(
70 'wbcs-botsessions-page',
71 'Questions Not Answered',
72 'Questions Not Answered',
73 $capability,
74 'wbcs-botsessions-notansweredpage',
75 'qcld_wpbot_not_answered_question'
76 );
77
78 add_submenu_page(
79 'wbcs-botsessions-page',
80 'AI Insight',
81 'AI Insight',
82 $capability,
83 'wbcs-schedule-session-reporting',
84 'qcld_wpbot_schedule_session_reporting'
85 );
86 }
87 }
88
89 // ─── Admin Scripts & Styles ───────────────────────────────────────────────────
90 add_action( 'admin_enqueue_scripts', 'qcld_wb_chatbot_session_admin_scripts_free' );
91
92 function qcld_wb_chatbot_session_admin_scripts_free( $hook ) {
93 // WordPress generates hook suffixes as follows:
94 // top-level page → toplevel_page_{slug}
95 // sub-pages → {parent-menu-title}_page_{slug} (title, lowercased, spaces→hyphens)
96 // Our parent title is "WPBot Sessions & Analytics" → "wpbot-sessions-analytics"
97 $session_hooks = array(
98 'toplevel_page_wbcs-botsessions-page',
99 'wpbot-sessions-analytics_page_wbcs-botsessions-notansweredpage',
100 'wpbot-sessions-analytics_page_wbcs-botsessions-reports',
101 'wpbot-sessions-analytics_page_wbcs-schedule-session-reporting',
102 );
103 if ( ! in_array( $hook, $session_hooks, true ) ) {
104 return;
105 }
106
107 wp_register_style( 'qlcd-wp-bootstrap-cs', QCLD_CHATBOT_FREE_SESSION_PLUGIN_URL . 'css/qlcd-wp-bootstrap.css', array(), QCLD_wpCHATBOT_VERSION, 'screen' );
108 wp_enqueue_style( 'qlcd-wp-bootstrap-cs' );
109
110 wp_register_style( 'qlcd-wp-bootstrap-icons-cs', QCLD_CHATBOT_FREE_SESSION_PLUGIN_URL . 'css/qlcd-wp-bootstrap-icons.css', array(), QCLD_wpCHATBOT_VERSION, 'screen' );
111 wp_enqueue_style( 'qlcd-wp-bootstrap-icons-cs' );
112
113 wp_register_style( 'qlcd-wp-dataTables-cs', QCLD_CHATBOT_FREE_SESSION_PLUGIN_URL . 'css/qlcd-wp-dataTables.css', array(), QCLD_wpCHATBOT_VERSION, 'screen' );
114 wp_enqueue_style( 'qlcd-wp-dataTables-cs' );
115
116 wp_register_style( 'qlcd-wp-session-style-cs', QCLD_CHATBOT_FREE_SESSION_PLUGIN_URL . 'reports/view/assets/style.css', array(), QCLD_wpCHATBOT_VERSION, 'screen' );
117 wp_enqueue_style( 'qlcd-wp-session-style-cs' );
118
119 // SweetAlert2 — used by admin.js for Swal.fire() and Swal.showLoading()
120 wp_register_script( 'qcld-wp-chatbot-sweetalrt-cs', QCLD_wpCHATBOT_PLUGIN_URL . 'js/sweetalrt.js', array( 'jquery' ), QCLD_wpCHATBOT_VERSION, true );
121 wp_enqueue_script( 'qcld-wp-chatbot-sweetalrt-cs' );
122
123 // admin.js depends on SweetAlert2 being loaded first
124 wp_register_script( 'qcld-wp-session-admin-cs', QCLD_CHATBOT_FREE_SESSION_PLUGIN_URL . 'js/admin.js', array( 'jquery', 'qcld-wp-chatbot-sweetalrt-cs' ), QCLD_wpCHATBOT_VERSION, true );
125 wp_enqueue_script( 'qcld-wp-session-admin-cs' );
126 wp_localize_script(
127 'qcld-wp-session-admin-cs',
128 'ajax_object',
129 array( 'ajax_url' => admin_url( 'admin-ajax.php' ) )
130 );
131
132 wp_register_script( 'qcld-wp-dataTables-cs', QCLD_CHATBOT_FREE_SESSION_PLUGIN_URL . 'js/qcld-dataTables.min.js', array( 'jquery' ), QCLD_wpCHATBOT_VERSION, true );
133 wp_enqueue_script( 'qcld-wp-dataTables-cs' );
134 }
135
136
137 // ─── AI Insight Page Callback ─────────────────────────────────────────────────
138 function qcld_wpbot_schedule_session_reporting() {
139 ?>
140 <div class="wrap">
141 <h2><?php echo esc_html( 'AI Insight' ); ?></h2>
142 <div class="notice notice-warning inline" style="margin-top: 20px; padding: 20px;">
143 <h3><span class="dashicons dashicons-lock"></span> <?php echo esc_html( 'Feature Locked' ); ?></h3>
144 <p>
145 <?php echo esc_html( 'The AI Insight feature allows you to receive an AI-based summary of all chat conversations emailed directly to you on a schedule.' ); ?>
146 </p>
147 <p>
148 <strong><?php echo esc_html( 'Please upgrade to WPBot Pro to unlock this feature!' ); ?></strong>
149 </p>
150 <p>
151 <a href="https://www.wpbot.pro/" target="_blank" class="button button-primary button-large"><?php echo esc_html( 'Upgrade to Pro' ); ?></a>
152 </p>
153 </div>
154 </div>
155 <?php
156 }
157
158
159 // ─── Questions Not Answered Page Callback ─────────────────────────────────────
160 function qcld_wpbot_not_answered_question() {
161 global $wpdb;
162 $wpdb->show_errors = true;
163 $table = $wpdb->prefix . 'wpbot_failed_response';
164
165 if ( isset( $_GET['msg'] ) && $_GET['msg'] == 'success' ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
166 echo '<div class="notice notice-success"><p>Record has been Deleted Successfully!</p></div>';
167 }
168
169 if ( isset( $_GET['action'] ) && $_GET['action'] == 'deleteall' ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
170 $wpdb->query( "TRUNCATE TABLE `$table`" ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
171 echo '<div class="notice notice-success"><p>All Records have been deleted successfully!</p></div>';
172 }
173
174 $sql = "SELECT * FROM $table WHERE 1 ORDER BY `id` DESC"; // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
175 $sql1 = "SELECT count(*) FROM $table WHERE 1 ORDER BY `id` DESC"; // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
176
177 $total = $wpdb->get_var( $sql1 ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
178 $items_per_page = 30;
179 $page = isset( $_GET['cpage'] ) ? abs( (int) $_GET['cpage'] ) : 1; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
180 $offset = ( $page * $items_per_page ) - $items_per_page;
181 $sql .= " LIMIT {$offset}, {$items_per_page}";
182 $result = $wpdb->get_results( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
183 $totalPage = ceil( $total / $items_per_page );
184 $customPagHTML = '';
185 if ( $totalPage > 1 ) {
186 $customPagHTML = '<div><span class="wpbot_pagination">Page ' . esc_html( $page ) . ' of ' . esc_html( $totalPage ) . '</span>' . paginate_links(
187 array(
188 'base' => add_query_arg( 'cpage', '%#%' ),
189 'format' => '',
190 'prev_text' => __( '« prev' ), // phpcs:ignore WordPress.WP.I18n.MissingArgDomain
191 'next_text' => __( 'next »' ), // phpcs:ignore WordPress.WP.I18n.MissingArgDomain
192 'total' => esc_html( $totalPage ),
193 'current' => esc_html( $page ),
194 )
195 ) . '</div>';
196 }
197
198 wp_register_style( 'qcld-wp-chatbot-history-style', QCLD_CHATBOT_FREE_SESSION_PLUGIN_URL . 'css/history-style.css', array(), QCLD_wpCHATBOT_VERSION, 'screen' );
199 wp_enqueue_style( 'qcld-wp-chatbot-history-style' );
200 ?>
201
202 <div class="sld_menu_title qcld_session_chat_menu_title">
203 <h2><?php echo esc_html__( 'Questions Not Answered', 'wpchatbot' ) . ' (' . $total . ')'; ?></h2>
204 </div>
205
206 <?php if ( $customPagHTML != '' ) : ?>
207 <div class="sld_menu_title sld_menu_title_align"><?php echo $customPagHTML; ?></div>
208 <?php endif; ?>
209
210 <?php
211 require_once QCLD_CHATBOT_FREE_SESSION_DIR_PATH . 'reports/view/partials/questions-not-answered.php';
212 }
213
214 // ─── Main Chat Sessions Page Callback ────────────────────────────────────────
215 function qc_wpbot_cs_menu_page_callback_func() {
216
217 global $wpdb;
218 $wpdb->show_errors = true;
219
220 $tableuser = $wpdb->prefix . 'wpbot_user';
221 $tableconversation = $wpdb->prefix . 'wpbot_conversation';
222 $mainurl = admin_url( 'admin.php?page=wbcs-botsessions-page' );
223
224 if ( isset( $_GET['min_interaction'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
225 $mainurl .= '&min_interaction=' . intval( $_GET['min_interaction'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
226 }
227 if ( isset( $_GET['wp_user'] ) && $_GET['wp_user'] != '' ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
228 $mainurl .= '&wp_user=' . intval( $_GET['wp_user'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
229 }
230
231 $msg = '';
232
233 if ( isset( $_GET['action'] ) && $_GET['action'] == 'deleteall' ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
234 $wpdb->query( "TRUNCATE TABLE `$tableuser`" ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
235 $wpdb->query( "TRUNCATE TABLE `$tableconversation`" ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
236 $msg = esc_html( 'All Sessions have been deleted successfully!' );
237 }
238
239 if ( isset( $_GET['msg'] ) && $_GET['msg'] == 'success' ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
240 echo '<div class="notice notice-success"><p>Record has been Deleted Successfully!</p></div>';
241 }
242
243 if ( isset( $_GET['userid'] ) && $_GET['userid'] != '' ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
244 require_once QCLD_CHATBOT_FREE_SESSION_DIR_PATH . 'reports/view/partials/view-single-chat.php';
245 } else {
246
247 wp_register_style( 'qcld-wp-chatbot-history-style', QCLD_CHATBOT_FREE_SESSION_PLUGIN_URL . 'css/history-style.css', array(), QCLD_wpCHATBOT_VERSION, 'screen' );
248 wp_enqueue_style( 'qcld-wp-chatbot-history-style' );
249 wp_register_style( 'qcld-wp-chatbot-jquery-ui', QCLD_CHATBOT_FREE_SESSION_PLUGIN_URL . 'css/jqueryui.css', array(), '', 'screen' );
250 wp_enqueue_style( 'qcld-wp-chatbot-jquery-ui' );
251 wp_register_script( 'qcld-wp-chatsession-admin-js', QCLD_CHATBOT_FREE_SESSION_PLUGIN_URL . 'js/chatsession.js', array( 'jquery' ), QCLD_wpCHATBOT_VERSION, true );
252 wp_enqueue_script( 'qcld-wp-chatsession-admin-js' );
253 wp_localize_script(
254 'qcld-wp-chatsession-admin-js',
255 'ajax_object',
256 array( 'ajax_url' => admin_url( 'admin-ajax.php' ) )
257 );
258 wp_register_script( 'qcld-wp-jqueryui-js', QCLD_CHATBOT_FREE_SESSION_PLUGIN_URL . 'js/jqueryui.js', array( 'jquery' ), QCLD_wpCHATBOT_VERSION, true );
259 wp_enqueue_script( 'qcld-wp-jqueryui-js' );
260
261 $where = '';
262 if ( isset( $_GET['min_interaction'] ) && $_GET['min_interaction'] != 'all' ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
263 if ( isset( $_GET['min_interaction'] ) && $_GET['min_interaction'] > 0 ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
264 $where = ' and `interaction` >= ' . intval( $_GET['min_interaction'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
265 }
266 if ( isset( $_GET['min_interaction'] ) && $_GET['min_interaction'] == 0 ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
267 $where = ' and `interaction` = 0';
268 }
269 }
270
271 $wwhere = '';
272 if ( isset( $_GET['wp_user'] ) && $_GET['wp_user'] != 'all' && $_GET['wp_user'] != 0 && $_GET['wp_user'] != '' ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
273 $wwhere = ' and `user_id` = ' . intval( $_GET['wp_user'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
274 }
275
276 $sql = "SELECT * FROM $tableuser WHERE 1 $where $wwhere ORDER BY `date` DESC"; // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
277 $sql1 = "SELECT count(*) FROM $tableuser WHERE 1 $where $wwhere"; // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
278
279 $dateFilter = '';
280 if ( isset( $_GET['FilterDate'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
281 if ( $_GET['FilterDate'] === 'LastWeek' ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
282 $dateFilter = " WHERE `date` >= CURDATE() - INTERVAL 7 DAY";
283 }
284 if ( $_GET['FilterDate'] === 'LastMonth' ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
285 $dateFilter = " WHERE `date` >= CURDATE() - INTERVAL 30 DAY";
286 }
287 if ( $_GET['FilterDate'] === 'Last3Months' ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
288 $dateFilter = " WHERE `date` >= CURDATE() - INTERVAL 90 DAY";
289 }
290 $sql = "SELECT * FROM $tableuser $dateFilter $wwhere ORDER BY `date` DESC"; // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
291 $sql1 = "SELECT count(*) FROM $tableuser $dateFilter"; // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
292 }
293
294 $total = $wpdb->get_var( $sql1 ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
295 $items_per_page = 30;
296 $page = isset( $_GET['cpage'] ) ? abs( (int) $_GET['cpage'] ) : 1; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
297 $offset = ( $page * $items_per_page ) - $items_per_page;
298 $sql .= " LIMIT {$offset}, {$items_per_page}";
299 $result = $wpdb->get_results( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
300 $totalPage = ceil( $total / $items_per_page );
301 $customPagHTML = '';
302 if ( $totalPage > 1 ) {
303 $customPagHTML = '<div><span class="wpbot_pagination">Page ' . esc_html( $page ) . ' of ' . esc_html( $totalPage ) . '</span>' . paginate_links(
304 array(
305 'base' => add_query_arg( 'cpage', '%#%' ),
306 'format' => '',
307 'prev_text' => __( '« prev' ), // phpcs:ignore WordPress.WP.I18n.MissingArgDomain
308 'next_text' => __( 'next »' ), // phpcs:ignore WordPress.WP.I18n.MissingArgDomain
309 'total' => esc_html( $totalPage ),
310 'current' => esc_html( $page ),
311 )
312 ) . '</div>';
313 }
314
315 $deleteurl = admin_url( 'admin.php?page=wbcs-botsessions-page&action=deleteall' );
316 ?>
317
318 <div class="qchero_sliders_list_wrapper qcld-session-history_menu_box">
319 <?php if ( $msg != '' ) : ?>
320 <div class="notice notice-success is-dismissible">
321 <p><?php echo esc_html( $msg ); ?></p>
322 </div>
323 <?php endif; ?>
324
325 <div class="sld_menu_title qcld-session-history_menu_title">
326 <h2><?php echo esc_html__( 'Chat Sessions', 'wpchatbot' ) . ' (' . $total . ')'; ?></h2>
327 </div>
328
329 <div>
330 <?php
331 if ( isset( $_GET['FilterDate'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
332 $filterText = '';
333 if ( $_GET['FilterDate'] === 'LastWeek' ) { $filterText = 'LAST WEEK'; } // phpcs:ignore WordPress.Security.NonceVerification.Recommended
334 if ( $_GET['FilterDate'] === 'LastMonth' ) { $filterText = 'LAST MONTH'; } // phpcs:ignore WordPress.Security.NonceVerification.Recommended
335 if ( $_GET['FilterDate'] === 'Last3Months' ) { $filterText = 'LAST 3 MONTHS'; } // phpcs:ignore WordPress.Security.NonceVerification.Recommended
336 echo '<div class="sld_menu_title"><em>Filtering Records by: <strong>' . esc_html( $filterText ) . '</strong></em></div>';
337 }
338 ?>
339 </div>
340
341 <?php if ( $customPagHTML != '' ) : ?>
342 <div class="sld_menu_title sld_menu_title_align"><?php echo $customPagHTML; ?></div>
343 <?php endif; ?>
344
345 <form id="wpcs_form_sessions" action="<?php echo esc_url( $mainurl ); ?>" method="POST" style="width:100%">
346 <input type="hidden" name="wpbot_session_remove" />
347
348 <?php if ( ! empty( $result ) ) : ?>
349 <?php require_once QCLD_CHATBOT_FREE_SESSION_DIR_PATH . 'reports/view/partials/chatsession-table.php'; ?>
350 <?php else : ?>
351 <div class="sld_menu_title"><h2>No result found.</h2></div>
352 <?php endif; ?>
353 </form>
354 </div>
355 <?php
356 }
357 }
358
359 // ─── Request Handler (delete, export, redirect) ───────────────────────────────
360 add_action( 'init', 'qc_wp_cs_request_handle_free' );
361
362 function qc_wp_cs_request_handle_free() {
363 global $wpdb;
364 $wpdb->show_errors = true;
365
366 $tableuser1 = $wpdb->prefix . 'wpbot_user';
367 $tableconversation1 = $wpdb->prefix . 'wpbot_conversation';
368 $table = $wpdb->prefix . 'wpbot_failed_response';
369
370 // Delete single "not answered" record.
371 if ( isset( $_GET['page'] ) && $_GET['page'] == 'wbcs-botsessions-notansweredpage' && isset( $_GET['act'] ) && $_GET['act'] == 'delete' ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
372 $userid = intval( $_GET['id'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
373 $wpdb->delete( $table, array( 'id' => $userid ), array( '%d' ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
374 wp_redirect( admin_url( 'admin.php?page=wbcs-botsessions-notansweredpage&msg=success' ) );
375 exit;
376 }
377
378 // Delete single chat session.
379 if ( isset( $_GET['page'] ) && $_GET['page'] == 'wbcs-botsessions-page' && isset( $_GET['act'] ) && $_GET['act'] == 'delete' ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
380 $userid = intval( $_GET['userid'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
381 $wpdb->delete( $tableuser1, array( 'id' => $userid ), array( '%d' ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
382 $wpdb->delete( $tableconversation1, array( 'user_id' => $userid ), array( '%d' ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
383 wp_redirect( admin_url( 'admin.php?page=wbcs-botsessions-page&msg=success' ) );
384 exit;
385 }
386
387 // Export all sessions as CSV.
388 if ( isset( $_POST['wpbot_session_export_all'] ) && isset( $_POST['wpbot_session_remove'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
389 $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
390 $sessions = array();
391 if ( ! empty( $users ) ) {
392 foreach ( $users as $user ) {
393 $sessions[] = wpbot_conversations_export( $user );
394 }
395 }
396 qcld_wpbot_chatsession_download_send_headers( 'wpbot_chatsession_' . date( 'Y-m-d' ) . '.csv' );
397 print wpbot_chatsession_array2csv( $sessions );
398 exit;
399 }
400
401 // Export selected sessions or delete selected sessions.
402 if ( isset( $_POST['wpbot_session_remove'] ) && ! empty( $_POST['sessions'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
403 $userids = array_map( 'intval', $_POST['sessions'] ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
404
405 if ( isset( $_POST['wpbot_session_export'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
406 $sessions = array();
407 foreach ( $userids as $userid ) {
408 $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
409 $sessions[] = wpbot_conversations_export( $user );
410 }
411 qcld_wpbot_chatsession_download_send_headers( 'wpbot_chatsession_' . date( 'Y-m-d' ) . '.csv' );
412 print wpbot_chatsession_array2csv( $sessions );
413 exit;
414 }
415
416 if ( isset( $_POST['wpbot_session_delete'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
417 foreach ( $userids as $userid ) {
418 $wpdb->delete( $tableuser1, array( 'id' => $userid ), array( '%d' ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
419 $wpdb->delete( $tableconversation1, array( 'user_id' => $userid ), array( '%d' ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
420 }
421 wp_redirect( admin_url( 'admin.php?page=wbcs-botsessions-page&msg=success' ) );
422 exit;
423 }
424 }
425 }
426
427 // ─── Admin Footer: Email Modal ────────────────────────────────────────────────
428 add_action( 'admin_footer', 'wpcs_admin_footer_content_free' );
429
430 function wpcs_admin_footer_content_free() {
431 if ( isset( $_GET['page'] ) && $_GET['page'] == 'wbcs-botsessions-page' ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
432 ?>
433 <div id="wpcsmyModal" class="wpcsmodal">
434 <div class="wpcsmodal-content">
435 <span class="wpcsclose">&times;</span>
436 <h2><?php echo esc_html( 'Send an Email to' ); ?> <span id="wpcs_show_email"></span></h2>
437 <div class="wpcs_form_container">
438 <form id="wpcs_email_form" action="">
439 <label for="fname"><?php echo esc_html( 'Subject' ); ?></label>
440 <input type="text" class="wpcs_text_field" id="wpcs_email_subject" name="wpcs_email_subject" placeholder="Subject.." required>
441 <label for="lname"><?php echo esc_html( 'Your Message' ); ?></label>
442 <textarea id="wpcs_email_message" class="wpcs_text_field" name="wpcs_email_message" placeholder="" style="height:200px" required></textarea>
443 <input type="hidden" id="wpcs_to_email_address" value="" />
444 <input type="submit" class="wpcs_submit_field" id="wpcs_email_submit" value="Submit">
445 <span id="wpcs_email_loading" style="display:none;"><img style="width:20px;" src="<?php echo esc_url( QCLD_CHATBOT_FREE_SESSION_PLUGIN_URL . 'images/ajax-loader.gif' ); ?>"></span>
446 <span id="wpcs_email_status"></span>
447 </form>
448 </div>
449 </div>
450 </div>
451 <?php
452 }
453 }
454
455 // ─── AJAX: Send Email to User ─────────────────────────────────────────────────
456 add_action( 'wp_ajax_wpcs_send_email', 'wpcs_send_email' );
457 add_action( 'wp_ajax_nopriv_wpcs_send_email', 'wpcs_send_email' );
458
459 function wpcs_send_email() {
460 $subject = sanitize_text_field( $_POST['data']['subject'] ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
461 $message = sanitize_text_field( $_POST['data']['message'] ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
462 $to = sanitize_email( $_POST['data']['to'] ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
463
464 $url = get_site_url();
465 $url = wp_parse_url( $url );
466 $domain = $url['host'];
467 $fromEmail = 'wordpress@' . $domain;
468 $headers = array(
469 'Content-Type: text/html; charset=UTF-8',
470 'From: ' . esc_html( $domain ) . ' <' . esc_html( $fromEmail ) . '>',
471 );
472
473 $result = wp_mail( $to, $subject, $message, $headers );
474 if ( $result ) {
475 $response = array( 'status' => 'success', 'message' => 'Email has been sent successfully!' );
476 } else {
477 $response = array( 'status' => 'fail', 'message' => 'Unable to send email. Please contact your server administrator.' );
478 }
479 ob_clean();
480 echo wp_json_encode( $response );
481 die();
482 }
483
484 // ─── AJAX: Save Email Notification Preference ─────────────────────────────────
485 add_action( 'wp_ajax_session_email_notification_update', 'session_email_notification_update_free' );
486
487 function session_email_notification_update_free() {
488 if ( ! current_user_can( 'manage_options' ) ) {
489 wp_die();
490 }
491 $email_notification = sanitize_text_field( $_POST['email_notification'] ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
492 update_option( 'session_email_notification_update', $email_notification );
493 wp_send_json( array( 'success' => true ) );
494 }
495
496 // ─── AJAX: Conversation Save (Frontend) ──────────────────────────────────────
497 // This is the main conversation-save handler. Guarded with function_exists
498 // so the Pro addon's definition wins if it's active.
499 if ( ! function_exists( 'qcld_wb_chatbot_conversation_save' ) ) {
500
501 function qcld_wb_chatbot_conversation_save() {
502
503 check_ajax_referer( 'qcsecretbotnonceval123qc', 'security' );
504 global $wpdb;
505
506 $tableuser = $wpdb->prefix . 'wpbot_user';
507 $tableconversation = $wpdb->prefix . 'wpbot_conversation';
508
509 $conversation = qcld_wpbot_input_validation( $_POST['conversation'] ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
510 $email = isset( $_POST['email'] ) ? sanitize_email( $_POST['email'] ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing
511 $phone = isset( $_POST['phone'] ) ? sanitize_text_field( $_POST['phone'] ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing
512 $name = isset( $_POST['name'] ) ? sanitize_text_field( $_POST['name'] ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing
513 $session_id = isset( $_POST['session_id'] ) ? sanitize_text_field( $_POST['session_id'] ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing
514 $wpuser_id = isset( $_POST['user_id'] ) ? sanitize_text_field( $_POST['user_id'] ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing
515 $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
516 $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
517 $session_mailed = isset( $_POST['session_mailed'] ) ? sanitize_text_field( $_POST['session_mailed'] ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing
518
519 // Prepend source URL to conversation.
520 $conversation = '&#x3C;ul&#x3E;&#x3C;li class=&#x22;session_start_url&#x22;&#x3E;&#x3C;span&#x3E;Source URL: &#x3C;/span&#x3E;&#x3C;a href=&#x22;' . $source_url . '&#x22;&#x3E;' . $source_url . '&#x3C;/a&#x3E;&#x3C;/li&#x3E;&#x3C;/ul&#x3E;' . $conversation;
521
522 $response = array();
523 $response['status'] = 'success';
524
525 $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
526 $is_new_insert = false;
527
528 if ( empty( $user_exists ) ) {
529 $lock_key = 'wpcs_lock_' . md5( $session_id );
530 if ( add_option( $lock_key, '1', '', 'no' ) ) {
531 $interaction = (int) substr_count( $conversation, 'wp-chat-user-msg' );
532 if ( $interaction == 0 ) {
533 $interaction = (int) substr_count( $conversation, 'woo-chat-user-msg' );
534 }
535
536 if ( $interaction != 0 ) {
537 $wpdb->insert( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
538 $tableuser,
539 array(
540 'date' => current_time( 'mysql' ),
541 'name' => $name,
542 'email' => $email,
543 'phone' => $phone,
544 'session_id' => $session_id,
545 'interaction' => $interaction,
546 'user_id' => $wpuser_id,
547 )
548 );
549 $user_id = $wpdb->insert_id;
550 $wpdb->insert( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
551 $tableconversation,
552 array(
553 'user_id' => $user_id,
554 'conversation' => $conversation,
555 'interaction' => $interaction,
556 'environment_info' => $user_agent,
557 )
558 );
559 $is_new_insert = true;
560 }
561 delete_option( $lock_key );
562 } else {
563 $retries = 3;
564 while ( $retries > 0 ) {
565 usleep( 500000 );
566 $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
567 if ( ! empty( $user_exists ) ) {
568 break;
569 }
570 $retries--;
571 }
572 }
573 }
574
575 if ( ! $is_new_insert && ! empty( $user_exists ) ) {
576 $interaction = (int) substr_count( $conversation, 'wp-chat-user-msg' );
577 if ( $interaction == 0 ) {
578 $interaction = (int) substr_count( $conversation, 'woo-chat-user-msg' );
579 }
580
581 $user_id = isset( $user_exists->id ) ? $user_exists->id : get_current_user_id();
582 $wpdb->update( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
583 $tableuser,
584 array(
585 'date' => current_time( 'mysql' ),
586 'name' => $name,
587 'email' => $email,
588 'phone' => $phone,
589 'interaction' => $interaction,
590 'user_id' => $wpuser_id,
591 ),
592 array( 'id' => $user_id ),
593 array( '%s', '%s', '%s', '%s', '%d', '%d' ),
594 array( '%d' )
595 );
596 $wpdb->update( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
597 $tableconversation,
598 array(
599 'conversation' => $conversation,
600 'interaction' => $interaction,
601 ),
602 array( 'user_id' => $user_id ),
603 array( '%s', '%d' ),
604 array( '%d' )
605 );
606 }
607
608 // Email notification for new session.
609 if ( $is_new_insert && ( get_option( 'session_email_notification_update' ) == 'checked' ) ) {
610 $admin_email = get_option( 'admin_email' );
611 $subject = esc_html__( 'Someone has started a new chat session with ChatBot.', 'wpchatbot' );
612 $bodyContent = '<p>' . esc_html__( 'Hi,', 'wpchatbot' ) . '</p>';
613 $bodyContent .= '<p>' . esc_html__( 'Someone has started a new chat session with ChatBot. Please go to ', 'wpchatbot' ) . '<a href="' . admin_url() . 'admin.php?page=wbcs-botsessions-page">' . esc_html__( 'Bot Sessions Dashboard', 'wpchatbot' ) . '</a>' . esc_html__( ' and find him/her.', 'wpchatbot' ) . '</p>';
614
615 $bodyContent .= '<ul>';
616 $bodyContent .= '<li>' . esc_html__( 'Session ID:', 'wpchatbot' ) . ' <strong>' . esc_html( $session_id ) . '</strong></li>';
617 if ( ! empty( $email ) ) {
618 $bodyContent .= '<li>' . esc_html__( 'Email:', 'wpchatbot' ) . ' <strong>' . esc_html( $email ) . '</strong></li>';
619 }
620 if ( ! empty( $phone ) ) {
621 $bodyContent .= '<li>' . esc_html__( 'Phone:', 'wpchatbot' ) . ' <strong>' . esc_html( $phone ) . '</strong></li>';
622 }
623 if ( ! empty( $source_url ) ) {
624 $bodyContent .= '<li>' . esc_html__( 'Page Link:', 'wpchatbot' ) . ' <strong><a href="' . esc_url( $source_url ) . '">' . esc_html( $source_url ) . '</a></strong></li>';
625 }
626 if ( ! empty( $user_agent ) ) {
627 $bodyContent .= '<li>' . esc_html__( 'Browser:', 'wpchatbot' ) . ' <strong>' . esc_html( $user_agent ) . '</strong></li>';
628 }
629 $bodyContent .= '</ul>';
630
631 $bodyContent .= '<p>' . esc_html__( 'Thanks', 'wpchatbot' ) . '</p>';
632 $bodyContent .= '<p>' . esc_html__( '(You can disable email notifications from ', 'wpchatbot' ) . '<a href="' . admin_url() . 'admin.php?page=wbcs-botsessions-page">' . esc_html__( 'Bot - Sessions)', 'wpchatbot' ) . '</a></p>';
633
634 $to = get_option( 'qlcd_wp_chatbot_admin_email' ) != '' ? get_option( 'qlcd_wp_chatbot_admin_email' ) : $admin_email;
635 $headers = array( 'Content-Type: text/html; charset=UTF-8' );
636 wp_mail( $to, $subject, $bodyContent, $headers );
637 }
638
639 echo wp_json_encode( $response );
640 die();
641 }
642 }
643 add_action( 'wp_ajax_qcld_wb_chatbot_conversation_save', 'qcld_wb_chatbot_conversation_save' );
644 add_action( 'wp_ajax_nopriv_qcld_wb_chatbot_conversation_save', 'qcld_wb_chatbot_conversation_save' );
645
646 // ─── AJAX: Date Filter ────────────────────────────────────────────────────────
647 add_action( 'wp_ajax_qcld_chatbot_session_date_filter', 'qcld_chatbot_session_date_filter_free' );
648 add_action( 'wp_ajax_nopriv_qcld_chatbot_session_date_filter', 'qcld_chatbot_session_date_filter_free' );
649
650 function qcld_chatbot_session_date_filter_free() {
651 global $wpdb;
652 $tableuser = $wpdb->prefix . 'wpbot_user';
653 $start_date = sanitize_text_field( $_POST['start_date'] ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
654 $end_date = sanitize_text_field( $_POST['end_date'] ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
655 $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
656 echo wp_json_encode( $result );
657 wp_die();
658 }
659
660 // ─── AJAX: Email Transcript ───────────────────────────────────────────────────
661 add_action( 'wp_ajax_wpbot_send_email_transcript', 'wpbot_send_email_transcript_free' );
662 add_action( 'wp_ajax_nopriv_wpbot_send_email_transcript', 'wpbot_send_email_transcript_free' );
663
664 function wpbot_send_email_transcript_free() {
665 global $wpdb;
666
667 $session = trim( sanitize_text_field( $_POST['session'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
668 $email = sanitize_email( $_POST['email'] ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
669
670 $url = wp_parse_url( get_site_url() );
671 $domain = $url['host'];
672 $admin_email = get_option( 'admin_email' );
673 $fromEmail = get_option( 'qlcd_wp_chatbot_from_email' ) ? get_option( 'qlcd_wp_chatbot_from_email' ) : 'wordpress@' . $domain;
674 $subject = 'Chat transcript by ' . get_bloginfo( 'name' );
675
676 $tableuser = $wpdb->prefix . 'wpbot_user';
677 $tableconversation = $wpdb->prefix . 'wpbot_conversation';
678
679 $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
680
681 $response = array( 'status' => 'fail', 'message' => 'Session not found.' );
682
683 if ( ! empty( $user ) ) {
684 $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
685 $bodyContent = '';
686 $bodyContent .= '<p><strong>' . esc_html__( 'User Details', 'wpchatbot' ) . ':</strong></p><hr>';
687 $bodyContent .= '<p>' . esc_html__( 'Name', 'wpchatbot' ) . ' : ' . esc_html( $user->name ) . '</p>';
688 $bodyContent .= '<p>' . esc_html__( 'Email', 'wpchatbot' ) . ' : ' . esc_html( $email ) . '</p>';
689 $bodyContent .= '<p><b>Conversations</b></p><p>-----------------------</p>';
690 $messages = qcld_wpch_conversation_extract( htmlspecialchars_decode( $result->conversation ) );
691 foreach ( $messages as $message ) {
692 if ( isset( $message['bot'] ) && trim( $message['bot'] ) != '' ) {
693 $bodyContent .= '<p>Chatbot : ' . esc_html( trim( $message['bot'] ) ) . '</p>';
694 }
695 if ( isset( $message['user'] ) && trim( $message['user'] ) != '' ) {
696 $bodyContent .= '<p>' . esc_html( $user->name ) . ' : ' . esc_html( trim( $message['user'] ) ) . '</p>';
697 }
698 }
699 $bodyContent .= '<p>-----------------------</p>';
700 $bodyContent .= '<p>Mail Generated on: ' . current_time( 'F j, Y, g:i a' ) . '</p>';
701 $headers = array(
702 'Content-Type: text/html; charset=UTF-8',
703 'From: ' . esc_html( $user->name ) . ' <' . esc_html( $fromEmail ) . '>',
704 'Reply-To: ' . esc_html( $user->name ) . ' <' . esc_html( $email ) . '>',
705 );
706 $result_mail = wp_mail( $email, $subject, $bodyContent, $headers );
707 if ( $result_mail ) {
708 $response = array( 'status' => 'success', 'message' => 'Email transcript sent successfully.' );
709 }
710 }
711 echo wp_json_encode( $response );
712 die();
713 }
714
715 // ─── AJAX: Forward Session to Email ──────────────────────────────────────────
716 add_action( 'wp_ajax_forward_session_to_email', 'forward_session_to_email_free' );
717 add_action( 'wp_ajax_nopriv_forward_session_to_email', 'forward_session_to_email_free' );
718
719 function forward_session_to_email_free() {
720 if ( ! current_user_can( 'manage_options' ) ) {
721 wp_send_json( array( 'success' => false, 'msg' => esc_html__( 'Insufficient permissions', 'wpchatbot' ) ) );
722 wp_die();
723 }
724 global $wpdb;
725
726 $session_id = sanitize_text_field( $_POST['session_id'] ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
727 $to = sanitize_email( $_POST['email'] ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
728 $tableuser = $wpdb->prefix . 'wpbot_user';
729 $tableconversation = $wpdb->prefix . 'wpbot_conversation';
730
731 $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
732 $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
733
734 if ( ! empty( $result ) ) {
735 $raw_html = isset( $result->conversation ) ? (string) $result->conversation : '';
736 $decoded_content = html_entity_decode( $raw_html );
737 $doc = new DOMDocument();
738 libxml_use_internal_errors( true );
739 $doc->loadHTML( '<meta http-equiv="Content-Type" content="text/html; charset=utf-8">' . $decoded_content );
740 libxml_clear_errors();
741
742 $decoded_content = '';
743 $body_nodes = $doc->getElementsByTagName( 'body' );
744 if ( $body_nodes->length > 0 ) {
745 foreach ( $body_nodes->item( 0 )->childNodes as $child_node ) {
746 $decoded_content .= $doc->saveHTML( $child_node );
747 }
748 }
749
750 $email_body = '<!DOCTYPE html><html><head><style>
751 .wp-chatbot-messages-container { list-style: none; padding: 20px; background: #f4f7f6; font-family: sans-serif; }
752 .wp-chatbot-msg { margin-bottom: 15px; display: flex; flex-wrap: wrap; }
753 .wp-chatbot-agent { font-weight: bold; color: #333; display: block; margin-bottom: 4px; }
754 .wp-chatbot-paragraph { background: #ffffff; padding: 10px; border-radius: 8px; border: 1px solid #ddd; flex: 1; }
755 .wp-chat-user-msg { display: flex; flex-wrap: wrap; flex-direction: row-reverse; }
756 .wp-chat-user-msg .wp-chatbot-paragraph { background: #ffffff; padding: 10px; border-radius: 8px; border: 1px solid #ddd; flex: none; }
757 body ul { width:100%; max-width: 640px; list-style: none; padding: 0; margin: 0 auto; }
758 </style></head><body>' . $decoded_content . '</body></html>';
759
760 $subject = isset( $_POST['subject'] ) ? sanitize_text_field( wp_unslash( $_POST['subject'] ) ) : 'Chat Session Transcript'; // phpcs:ignore WordPress.Security.NonceVerification.Missing
761 if ( empty( $subject ) ) { $subject = 'Chat Session Transcript'; }
762 $headers = array( 'Content-Type: text/html; charset=UTF-8' );
763 wp_mail( $to, $subject, $email_body, $headers );
764 wp_send_json( array( 'success' => true, 'msg' => esc_html__( 'Session has been forwarded to email successfully', 'wpchatbot' ) ) );
765 wp_die();
766 } else {
767 wp_send_json( array( 'success' => false, 'msg' => esc_html__( 'No conversation found for this session', 'wpchatbot' ) ) );
768 wp_die();
769 }
770 }
771
772 // ─── AJAX: Session Hover Details ─────────────────────────────────────────────
773 add_action( 'wp_ajax_wpbot_session_hover_details', 'wpbot_session_hover_details_free' );
774 add_action( 'wp_ajax_nopriv_wpbot_session_hover_details', 'wpbot_session_hover_details_free' );
775
776 function wpbot_session_hover_details_free() {
777 if ( ! current_user_can( 'manage_options' ) ) {
778 wp_send_json( array( 'success' => false, 'msg' => esc_html__( 'Insufficient permissions', 'wpchatbot' ) ) );
779 wp_die();
780 }
781 global $wpdb;
782 $session_id = sanitize_text_field( $_POST['session_id'] ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
783 $tableconversation = $wpdb->prefix . 'wpbot_conversation';
784 $result = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $tableconversation WHERE 1 AND user_id = %d", $session_id ) ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
785 if ( ! empty( $result ) ) {
786 $result->status = 'success';
787 }
788 echo wp_json_encode( $result );
789 wp_die();
790 }
791
792 // ─── AJAX: Save Cron Settings ─────────────────────────────────────────────────
793 add_action( 'wp_ajax_wpbot_seesion_corn_save', 'wpbot_seesion_corn_save_free' );
794
795 function wpbot_seesion_corn_save_free() {
796 if ( ! current_user_can( 'manage_options' ) ) {
797 wp_send_json( array( 'success' => false, 'msg' => esc_html__( 'Insufficient permissions', 'wpchatbot' ) ) );
798 wp_die();
799 }
800
801 $wbsession_ai_enabled = isset( $_POST['ai_enabled'] ) ? sanitize_text_field( $_POST['ai_enabled'] ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing
802 $wbsession_corn_schedule_interval = isset( $_POST['corn_schedule_interval'] ) ? sanitize_text_field( $_POST['corn_schedule_interval'] ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing
803 $qcld_wpsession_corn_promt = isset( $_POST['qcld_wpsession_corn_promt'] ) ? sanitize_text_field( $_POST['qcld_wpsession_corn_promt'] ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing
804 $qcld_wbsession_corn_starttime = isset( $_POST['qcld_wbsession_corn_starttime'] ) ? sanitize_text_field( $_POST['qcld_wbsession_corn_starttime'] ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing
805
806 $openai_enabled = get_option( 'ai_enabled' );
807 $apiKey = get_option( 'open_ai_api_key' );
808
809 if ( $openai_enabled != '1' ) {
810 wp_send_json( array( 'success' => false, 'icon' => 'error', 'response' => esc_html__( 'OpenAI is Not Enabled', 'wpchatbot' ) ) );
811 wp_die();
812 }
813 if ( $apiKey == '' ) {
814 wp_send_json( array( 'success' => false, 'icon' => 'error', 'response' => esc_html__( 'OpenAI API key is not set', 'wpchatbot' ) ) );
815 wp_die();
816 }
817
818 update_option( 'qcld_wbsession_ai_enable', $wbsession_ai_enabled );
819 update_option( 'qcld_wbsession_corn_interval', $wbsession_corn_schedule_interval );
820 update_option( 'qcld_wbsession_corn_starttime', $qcld_wbsession_corn_starttime );
821 update_option( 'qcld_wpsession_corn_promt', $qcld_wpsession_corn_promt );
822
823 wp_clear_scheduled_hook( 'qcld_wpsession_mysql_scraper_event' );
824 wp_send_json( array( 'success' => true, 'icon' => 'success', 'response' => esc_html__( 'Settings Saved Successfully', 'wpchatbot' ) ) );
825 wp_die();
826 }
827
828 // ─── AJAX: Manual AI Scraper ──────────────────────────────────────────────────
829 add_action( 'wp_ajax_qcld_chatbot_session_mannual_scraper', 'qcld_chatbot_session_mannual_scraper_free' );
830
831 if ( ! function_exists( 'qcld_chatbot_session_mannual_scraper_free' ) ) {
832 function qcld_chatbot_session_mannual_scraper_free() {
833 if ( ! current_user_can( 'manage_options' ) ) {
834 wp_send_json_error( array( 'msg' => 'Insufficient permissions.' ) );
835 wp_die();
836 }
837 if ( get_option( 'qcld_wbsession_ai_enable' ) != '1' ) {
838 wp_send_json( array( 'success' => false, 'icon' => 'error', 'response' => esc_html__( 'AI Insight is not enabled.', 'wpchatbot' ) ) );
839 wp_die();
840 }
841
842 global $wpdb;
843 $num = isset( $_POST['wpchatbot_session_mannual_number'] ) ? intval( $_POST['wpchatbot_session_mannual_number'] ) : 20; // phpcs:ignore WordPress.Security.NonceVerification.Missing
844 if ( ! is_numeric( $num ) || $num <= 0 ) {
845 wp_send_json( array( 'success' => false, 'icon' => 'error', 'response' => esc_html__( 'Invalid number of sessions.', 'wpchatbot' ) ) );
846 wp_die();
847 }
848
849 $tableuser = $wpdb->prefix . 'wpbot_user';
850 $tableconversation = $wpdb->prefix . 'wpbot_conversation';
851 $results = $wpdb->get_results( $wpdb->prepare( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
852 "SELECT u.id, c.user_id, u.date, u.session_id, c.id AS conversation_id, c.conversation
853 FROM $tableuser AS u LEFT JOIN $tableconversation AS c ON u.id = c.user_id
854 ORDER BY u.date DESC LIMIT %d", $num ) // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
855 );
856
857 $remarkable_session = array();
858 foreach ( $results as $row ) {
859 $trimmed = wpsession_message_html_filter_free( htmlspecialchars_decode( $row->conversation ) );
860 $remarkable_session[] = array( 'id' => $row->session_id, 'conversation' => $trimmed );
861 }
862
863 $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.';
864 $gptkeyword = array(
865 array( 'role' => 'system', 'content' => array( array( 'type' => 'input_text', 'text' => $keyword ) ) ),
866 array( 'role' => 'user', 'content' => array( array( 'type' => 'input_text', 'text' => wp_json_encode( $remarkable_session ) ) ) ),
867 );
868
869 $api_key = get_option( 'open_ai_api_key' );
870 $engines = get_option( 'openai_engines' );
871 $post_fields = array( 'model' => $engines, 'input' => $gptkeyword );
872 $header = array( 'Content-Type: application/json', 'Authorization: Bearer ' . $api_key );
873
874 $ch = curl_init();
875 curl_setopt( $ch, CURLOPT_URL, 'https://api.openai.com/v1/responses' );
876 curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
877 curl_setopt( $ch, CURLOPT_POST, 1 );
878 curl_setopt( $ch, CURLOPT_POSTFIELDS, wp_json_encode( $post_fields ) );
879 curl_setopt( $ch, CURLOPT_HTTPHEADER, $header );
880 $result = curl_exec( $ch );
881 curl_close( $ch );
882
883 $mess = json_decode( $result );
884 if ( ! empty( $mess->error ) ) {
885 wp_send_json( array( 'status' => 'error', 'icon' => 'error', 'msg' => esc_html( $mess->error->code ), 'response' => esc_html( $mess->error->message ) ) );
886 wp_die();
887 }
888
889 $msg = isset( $mess->output[0]->content ) ? $mess->output[0]->content[0]->text : ( $mess->output[1]->content[0]->text ?? '' );
890 $msg = preg_replace( "/\r\n|\r|\n/", '<br/>', $msg );
891
892 $to = get_option( 'qlcd_wp_chatbot_admin_email' ) ?: get_option( 'admin_email' );
893 $headers = array(
894 'Content-Type: text/html; charset=UTF-8',
895 'From: ' . esc_html( get_bloginfo( 'name' ) ) . ' <wordpress@' . wp_parse_url( get_site_url(), PHP_URL_HOST ) . '>',
896 );
897 wp_mail( $to, 'ChatBot Sessions Analysis', $msg, $headers );
898
899 wp_send_json( array( 'status' => 'success', 'icon' => 'success', 'response' => 'Please Check Email for Report' ) );
900 wp_die();
901 }
902 }
903
904 // ─── Helper: HTML filter for AI scraper ──────────────────────────────────────
905 if ( ! function_exists( 'wpsession_message_html_filter_free' ) ) {
906 function wpsession_message_html_filter_free( $html ) {
907 $dom = new DOMDocument();
908 libxml_use_internal_errors( true );
909 $dom->loadHTML( '<?xml encoding="utf-8" ?>' . $html );
910
911 $lis = $dom->getElementsByTagName( 'li' );
912 $full_conversation = array();
913 foreach ( $lis as $li ) {
914 $agentDiv = $li->getElementsByTagName( 'div' )->item( 1 );
915 $paragraphDiv = $li->getElementsByTagName( 'div' )->item( 2 );
916 if ( $paragraphDiv ) {
917 $full_conversation[] = array(
918 'id' => trim( $agentDiv->textContent ),
919 'conversation' => trim( $paragraphDiv->textContent ),
920 );
921 }
922 }
923 return wp_json_encode( $full_conversation );
924 }
925 }
926
927 // ─── Helper: Conversation Extract ────────────────────────────────────────────
928 if ( ! function_exists( 'qcld_wpch_conversation_extract' ) ) {
929 function qcld_wpch_conversation_extract( $html ) {
930 $doc = new DOMDocument();
931 libxml_use_internal_errors( true );
932 $doc->loadHTML( '<meta http-equiv="Content-Type" content="text/html; charset=utf-8">' . $html );
933 $lis = iterator_to_array( $doc->getElementsByTagName( 'li' ) );
934 $messages = array();
935 foreach ( $lis as $li ) {
936 if ( strpos( $li->getAttribute( 'class' ), 'wp-chatbot-msg' ) !== false ) {
937 $messages[]['bot'] = trim( $li->textContent );
938 }
939 if ( strpos( $li->getAttribute( 'class' ), 'wp-chat-user-msg' ) !== false ) {
940 $messages[]['user'] = trim( $li->textContent );
941 }
942 }
943 $messages = array_filter( $messages, function( $val ) {
944 if ( isset( $val['bot'] ) && empty( $val['bot'] ) ) { return false; }
945 return true;
946 } );
947 return $messages;
948 }
949 }
950
951 // ─── CSV Export Helpers ───────────────────────────────────────────────────────
952 add_action( 'admin_post_wpbot_conversations.csv', 'wpbot_conversations_csv_export_free' );
953
954 function wpbot_conversations_csv_export_free() {
955 global $wpdb;
956 $tableuser = $wpdb->prefix . 'wpbot_user';
957 $tableconversation = $wpdb->prefix . 'wpbot_conversation';
958 $userid = sanitize_text_field( $_GET['user_id'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
959
960 $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
961 $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
962 $data = array();
963
964 if ( ! empty( $result ) ) {
965 $data[] = array( 'User Name', $userinfo->name );
966 $data[] = array( 'User Email', $userinfo->email );
967 $data[] = array( 'Session ID', $userinfo->session_id );
968 $data[] = array( 'Date', date( 'M,d,Y h:i:s A', strtotime( $userinfo->date ) ) );
969 $data[] = array( 'Bot Message', 'User Message' );
970 $messages = qcld_wpch_conversation_extract( htmlspecialchars_decode( $result->conversation ) );
971 foreach ( $messages as $message ) {
972 if ( isset( $message['bot'] ) && trim( $message['bot'] ) != '' ) {
973 $data[] = array( str_replace( '&nbsp;', ' ', trim( $message['bot'] ) ), '' );
974 }
975 if ( isset( $message['user'] ) && trim( $message['user'] ) != '' ) {
976 $data[] = array( '', str_replace( '&nbsp;', ' ', trim( $message['user'] ) ) );
977 }
978 }
979 }
980 qcld_wpbot_chatsession_download_send_headers( $userinfo->name . '_wpbot_chatsession_' . date( 'Y-m-d' ) . '.csv' );
981 print wpbot_chatsession_array2csv( $data );
982 }
983
984 if ( ! function_exists( 'wpbot_conversations_export' ) ) {
985 function wpbot_conversations_export( $user ) {
986 $user_id = isset( $user->id ) ? $user->id : $user;
987 $dataArray = array();
988 if ( ! empty( $user ) ) {
989 $messages = qcld_wpch_conversation_extract( htmlspecialchars_decode( $user->conversation ) );
990 $dataArray = array(
991 'Session ID' => $user->session_id,
992 'Date' => date( 'M,d,Y h:i:s A', strtotime( $user->date ) ),
993 'User Name' => $user->name,
994 'User Email' => $user->email,
995 );
996 $conversations = '';
997 foreach ( $messages as $message ) {
998 if ( isset( $message['bot'] ) && trim( $message['bot'] ) != '' ) {
999 $conversations .= 'Bot Message: ' . str_replace( '&nbsp;', ' ', trim( $message['bot'] ) ) . "\n";
1000 }
1001 if ( isset( $message['user'] ) && trim( $message['user'] ) != '' ) {
1002 $conversations .= 'User Message: ' . str_replace( '&nbsp;', ' ', trim( $message['user'] ) ) . "\n";
1003 }
1004 }
1005 $dataArray['Conversations'] = $conversations;
1006 }
1007 $dataArray['Interaction'] = $user->interaction;
1008 return $dataArray;
1009 }
1010 }
1011
1012 if ( ! function_exists( 'qcld_wpbot_chatsession_download_send_headers' ) ) {
1013 function qcld_wpbot_chatsession_download_send_headers( $filename ) {
1014 $now = gmdate( 'D, d M Y H:i:s' );
1015 header( 'Expires: Tue, 03 Jul 2001 06:00:00 GMT' );
1016 header( 'Cache-Control: max-age=0, no-cache, must-revalidate, proxy-revalidate' );
1017 header( "Last-Modified: {$now} GMT" );
1018 header( 'Content-Encoding: UTF-8' );
1019 header( 'Content-type: text/csv; charset=UTF-8' );
1020 header( "Content-Disposition: attachment;filename={$filename}" );
1021 header( 'Content-Transfer-Encoding: binary' );
1022 }
1023 }
1024
1025 if ( ! function_exists( 'wpbot_chatsession_array2csv' ) ) {
1026 function wpbot_chatsession_array2csv( array &$array ) {
1027 if ( count( $array ) == 0 ) { return null; }
1028 ob_start();
1029 $df = fopen( 'php://output', 'w' );
1030 fputs( $df, chr( 0xEF ) . chr( 0xBB ) . chr( 0xBF ) ); // UTF-8 BOM
1031 foreach ( $array as $data ) {
1032 fputcsv( $df, array_keys( $data ) );
1033 break;
1034 }
1035 foreach ( $array as $row ) {
1036 fputcsv( $df, $row );
1037 }
1038 fclose( $df );
1039 return ob_get_clean();
1040 }
1041 }
1042
1043 // ─── Shortcode: User Session History ─────────────────────────────────────────
1044 if ( ! function_exists( 'qc_current_user_session' ) ) {
1045 function qc_current_user_session() {
1046 $user = wp_get_current_user();
1047 global $wpdb;
1048 $tableuser = $wpdb->prefix . 'wpbot_user';
1049 $conversatios_table = $wpdb->prefix . 'wpbot_conversation';
1050 $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
1051 if ( ! $user->exists() ) {
1052 return '<p>No user logged in.</p>';
1053 }
1054 ob_start(); ?>
1055 <style>
1056 .cell-content #wp-chatbot-messages-container { height: 200px; overflow: scroll; overflow-x: hidden; }
1057 .session_start_url { display: none; }
1058 .table-striped tr { border: 2px solid #888; }
1059 </style>
1060 <table class="table table-striped align-middle" id="chatsession-table">
1061 <thead>
1062 <tr class="table-primary">
1063 <th class="text-left"><?php echo esc_html__( 'Date', 'wpchatbot' ); ?></th>
1064 <th class="text-left"><?php echo esc_html__( 'Session ID', 'wpchatbot' ); ?></th>
1065 <th class="text-left"><?php echo esc_html__( 'Name', 'wpchatbot' ); ?></th>
1066 <th class="text-left" data-dt-order="disable"><?php echo esc_html__( 'Conversation', 'wpchatbot' ); ?></th>
1067 </tr>
1068 <?php foreach ( $result as $key => $value ) : ?>
1069 <tr>
1070 <td class="text-left"><?php echo esc_html( $value->date ); ?></td>
1071 <td class="text-left"><?php echo esc_html( $value->session_id ); ?></td>
1072 <td class="text-left"><?php echo esc_html( $value->name ); ?></td>
1073 <td class="text-left"><div class="cell-content"><a class="qcld-modal-content" data-value="<?php echo esc_attr( $value->conversation ); ?>">view data</a></div></td>
1074 </tr>
1075 <?php endforeach; ?>
1076 </thead>
1077 </table>
1078 <?php
1079 return ob_get_clean();
1080 }
1081 }
1082 add_shortcode( 'qcpress_user', 'qc_current_user_session' );
1083
1084 // ─── WP-Cron: AI Insight Scheduled Email ─────────────────────────────────────
1085 add_filter( 'cron_schedules', 'qcld_wpsession_wp_cron_schedule_free' );
1086
1087 if ( ! function_exists( 'qcld_wpsession_wp_cron_schedule_free' ) ) {
1088 function qcld_wpsession_wp_cron_schedule_free( $schedules ) {
1089 $schedules['session_schedules'] = array(
1090 'interval' => ( get_option( 'qcld_wbsession_corn_interval' ) != null ) ? get_option( 'qcld_wbsession_corn_interval' ) : 86400,
1091 'display' => esc_attr( 'Session min', 'wpchatbot' ),
1092 );
1093 return $schedules;
1094 }
1095 }
1096
1097 $wpsession_corn_start_times = wp_date( 'Y-m-d' ) . ' ' . get_option( 'qcld_wbsession_corn_starttime' );
1098 $wpsession_corn_start_time = strtotime( $wpsession_corn_start_times );
1099 if ( ! wp_next_scheduled( 'qcld_wpsession_mysql_scraper_event' ) && ( get_option( 'qcld_wbsession_ai_enable' ) == '1' ) ) {
1100 wp_schedule_event( $wpsession_corn_start_time, 'session_schedules', 'qcld_wpsession_mysql_scraper_event' );
1101 }
1102
1103 add_action( 'qcld_wpsession_mysql_scraper_event', 'qcld_wpsession_mysql_scraper_function_free' );
1104
1105 if ( ! function_exists( 'qcld_wpsession_mysql_scraper_function_free' ) ) {
1106 function qcld_wpsession_mysql_scraper_function_free() {
1107 if ( get_option( 'qcld_wbsession_ai_enable' ) != '1' ) { return; }
1108
1109 global $wpdb;
1110 $interval_hours = ( (int) get_option( 'qcld_wbsession_corn_interval' ) ?: 86400 ) / 3600;
1111 $tableuser = $wpdb->prefix . 'wpbot_user';
1112 $tableconversation = $wpdb->prefix . 'wpbot_conversation';
1113 $results = $wpdb->get_results( $wpdb->prepare( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
1114 "SELECT u.id, c.user_id, u.date, u.session_id, c.id, c.conversation
1115 FROM $tableuser AS u LEFT JOIN $tableconversation AS c ON u.id = c.user_id
1116 WHERE u.date >= (NOW() - INTERVAL %d HOUR) ORDER BY u.date DESC", $interval_hours ) // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
1117 );
1118
1119 $remarkable_session = array();
1120 foreach ( $results as $row ) {
1121 $remarkable_session[] = array( 'id' => $row->session_id, 'conversation' => wpsession_message_html_filter_free( htmlspecialchars_decode( $row->conversation ) ) );
1122 }
1123
1124 $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?';
1125 $gptkeyword = array(
1126 array( 'role' => 'system', 'content' => array( array( 'type' => 'input_text', 'text' => $keyword ) ) ),
1127 array( 'role' => 'user', 'content' => array( array( 'type' => 'input_text', 'text' => wp_json_encode( $remarkable_session ) ) ) ),
1128 );
1129
1130 $api_key = get_option( 'open_ai_api_key' );
1131 $engines = get_option( 'openai_engines' );
1132 $post_fields = array( 'model' => $engines, 'input' => $gptkeyword );
1133 $header = array( 'Content-Type: application/json', 'Authorization: Bearer ' . $api_key );
1134
1135 $ch = curl_init();
1136 curl_setopt( $ch, CURLOPT_URL, 'https://api.openai.com/v1/responses' );
1137 curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
1138 curl_setopt( $ch, CURLOPT_POST, 1 );
1139 curl_setopt( $ch, CURLOPT_POSTFIELDS, wp_json_encode( $post_fields ) );
1140 curl_setopt( $ch, CURLOPT_HTTPHEADER, $header );
1141 $result = curl_exec( $ch );
1142 curl_close( $ch );
1143
1144 $mess = json_decode( $result );
1145 $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.' );
1146 $msg = preg_replace( "/\r\n|\r|\n/", '<br/>', $msg );
1147
1148 $to = get_option( 'qlcd_wp_chatbot_admin_email' ) ?: get_option( 'admin_email' );
1149 $headers = array(
1150 'Content-Type: text/html; charset=UTF-8',
1151 'From: ' . esc_html( get_bloginfo( 'name' ) ) . ' <wordpress@' . wp_parse_url( get_site_url(), PHP_URL_HOST ) . '>',
1152 );
1153 wp_mail( $to, 'ChatBot Sessions Analysis', $msg, $headers );
1154 }
1155 }
1156
1157 // ─── Reports (Bot - Reports submenu) ─────────────────────────────────────────
1158 require_once QCLD_CHATBOT_FREE_SESSION_DIR_PATH . 'reports/chatbot-history-reporting.php';
1159