PluginProbe
WPBot – AI ChatBot for Live Support, Lead Generation, WordPress Automation, AI Services / 8.5.2
WPBot – AI ChatBot for Live Support, Lead Generation, WordPress Automation, AI Services v8.5.2
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.5.2, at includes/chat-sessions/wpbot-chat-sessions.php

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