PluginProbe
Kognetiks Chatbot for WordPress / 2.4.2
Kognetiks Chatbot for WordPress v2.4.2
trunk 1.0.0 1.1.0 1.2.0 1.3.0 1.4.0 1.4.1 1.4.2 1.5.0 1.5.1 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 1.7.3 1.7.4 All 98 releases
chatbot-chatgpt / chatbot-chatgpt.php

chatbot-chatgpt.php in Kognetiks Chatbot for WordPress 2.4.2, at chatbot-chatgpt.php

3,043 lines 158.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /*
4 * Plugin Name: Kognetiks Chatbot
5 * Plugin URI: https://github.com/kognetiks/kognetiks-chatbot
6 * Description: This simple plugin adds an AI powered chatbot to your WordPress website.
7 * Version: 2.4.2
8 * Author: Kognetiks.com
9 * Author URI: https://www.kognetiks.com
10 * License: GPLv3 or later
11 * License URI: https://www.gnu.org/licenses/gpl-30.html
12 *
13 * Copyright (c) 2023-2025 Stephen Howell
14 *
15 * This program is free software; you can redistribute it and/or modify it under the terms of the GNU
16 * General Public License version 3, as published by the Free Software Foundation. You may NOT assume
17 * that you can use any other version of the GPL.
18 *
19 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
20 * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with Kognetiks Chatbot. If not, see https://www.gnu.org/licenses/gpl-3.0.html.
24 *
25 * @package chatbot-chatgpt
26 * @version 2.4.2
27 * @author Kognetiks.com
28 */
29 if ( !defined( 'ABSPATH' ) ) {
30 exit;
31 }
32 if ( function_exists( 'chatbot_chatgpt_freemius' ) ) {
33 chatbot_chatgpt_freemius()->set_basename( false, __FILE__ );
34 } else {
35 /**
36 * DO NOT REMOVE THIS IF, IT IS ESSENTIAL FOR THE
37 * `function_exists` CALL ABOVE TO PROPERLY WORK.
38 */
39 if ( !function_exists( 'chatbot_chatgpt_freemius' ) ) {
40 function chatbot_chatgpt_freemius() {
41 global $chatbot_chatgpt_freemius;
42 if ( !isset( $chatbot_chatgpt_freemius ) ) {
43 // Include Freemius SDK
44 require_once dirname( __FILE__ ) . '/vendor/freemius/start.php';
45 $chatbot_chatgpt_freemius = fs_dynamic_init( array(
46 'id' => '18850',
47 'slug' => 'chatbot-chatgpt',
48 'type' => 'plugin',
49 'public_key' => 'pk_ea667ce516b3acd5d3756a0c2530b',
50 'is_premium' => false,
51 'premium_suffix' => 'Premium',
52 'has_paid_plans' => true,
53 'trial' => array(
54 'days' => 7,
55 'is_require_payment' => false,
56 ),
57 'menu' => array(
58 'slug' => 'chatbot-chatgpt',
59 'first-path' => 'admin.php?page=chatbot-chatgpt&tab=support',
60 'network' => true,
61 ),
62 'is_live' => true,
63 ) );
64 }
65 return $chatbot_chatgpt_freemius;
66 }
67
68 // Initialize Freemius
69 chatbot_chatgpt_freemius();
70 do_action( 'chatbot_chatgpt_freemius_loaded' );
71 }
72 // ADD THIS TO THE END OF THE FILE - NOT HERE
73 // }
74 // Start output buffering earlier to prevent "headers already sent" issues - Ver 2.1.8
75 ob_start();
76 // Plugin version
77 global $chatbot_chatgpt_plugin_version;
78 $chatbot_chatgpt_plugin_version = '2.4.2';
79 // Plugin directory path
80 global $chatbot_chatgpt_plugin_dir_path;
81 $chatbot_chatgpt_plugin_dir_path = plugin_dir_path( __FILE__ );
82 // Plugin directory URL
83 global $chatbot_chatgpt_plugin_dir_url;
84 $chatbot_chatgpt_plugin_dir_url = plugins_url( '/', __FILE__ );
85 // Declare Globals
86 global $wpdb;
87 // Uniquely Identify the Visitor
88 global $session_id;
89 global $user_id;
90 // Assign a unique ID to the visitor and logged-in users - Ver 2.0.4
91 // Ver 2.3.7 - Fixed headers already sent warning by checking if headers can be sent
92 // Ver 2.4.0 - Added @ operator to suppress warnings as additional safety measure
93 function kognetiks_assign_unique_id() {
94 if ( !isset( $_COOKIE['kognetiks_unique_id'] ) ) {
95 $unique_id = uniqid( 'kognetiks_', true );
96 // Check if headers have already been sent before trying to set cookie
97 // Ver 2.3.7 - Prevent "headers already sent" warning
98 // Ver 2.4.0 - Use @ operator to suppress any warnings as additional safety measure
99 if ( !headers_sent() ) {
100 // Set a cookie using the built-in setcookie function
101 // Using @ operator to suppress warnings in case headers are sent between check and setcookie
102 @setcookie(
103 'kognetiks_unique_id',
104 $unique_id,
105 time() + 86400 * 30,
106 "/",
107 "",
108 true,
109 true
110 );
111 // HttpOnly and Secure flags set to true
112 }
113 // Ensure the cookie is set for the current request (works even if headers were already sent)
114 $_COOKIE['kognetiks_unique_id'] = $unique_id;
115 }
116 }
117
118 add_action( 'init', 'kognetiks_assign_unique_id', 1 );
119 // Set higher priority
120 // Get the unique ID of the visitor or logged-in user - Ver 2.0.4
121 function kognetiks_get_unique_id() {
122 if ( isset( $_COOKIE['kognetiks_unique_id'] ) ) {
123 // error_log('[Chatbot] [chatbot-chatgpt.php] Unique ID found: ' . $_COOKIE['kognetiks_unique_id']);
124 return sanitize_text_field( $_COOKIE['kognetiks_unique_id'] );
125 }
126 // error_log('[Chatbot] [chatbot-chatgpt.php] Unique ID not found');
127 return null;
128 }
129
130 // Fetch the User ID - Updated Ver 2.0.6 - 2024 07 11
131 $user_id = get_current_user_id();
132 // Fetch the Kognetiks cookie
133 $session_id = kognetiks_get_unique_id();
134 if ( empty( $user_id ) || $user_id == 0 ) {
135 $user_id = $session_id;
136 }
137 ob_end_flush();
138 // End output buffering and send the buffer to the browser
139 // Include necessary files - Utilities (must be loaded before API files that use them)
140 require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-utilities.php';
141 // Ver 1.8.6
142 // Include necessary files - Main files
143 require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-call-anthropic-api.php';
144 // ANT API - Ver 2.0.7
145 require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-call-azure-openai-api.php';
146 // Azure OpenAI API - Ver 2.2.6
147 require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-call-azure-api-assistant.php';
148 // Azure OpenAI Assistants API - Ver 2.2.6
149 require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-call-deepseek-api.php';
150 // ChatGPT API - Ver 2.2.2
151 require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-call-google-api.php';
152 // Google API - Ver 2.3.9
153 require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-call-kognetiks-api-mc.php';
154 // Kognetiks - Markov Chain API - Ver 2.1.6
155 require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-call-kognetiks-api-tm.php';
156 // Kognetiks - Transformer Model API - Ver 2.2.0
157 require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-call-local-api.php';
158 // Local API - Ver 2.2.6
159 require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-call-mistral-api.php';
160 // Mistral API - Ver 2.3.0
161 require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-call-mistral-agent-api.php';
162 // Mistral Agent API - Ver 2.3.0
163 require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-call-nvidia-api.php';
164 // NVIDIA API - Ver 2.1.8
165 require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-call-openai-api-assistant.php';
166 // GPT Assistants - Ver 1.6.9
167 require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-call-openai-api-chatgpt.php';
168 // ChatGPT API - Ver 1.6.9
169 require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-call-openai-api-image.php';
170 // Image API - Ver 1.9.4
171 require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-call-openai-api-kflow.php';
172 // Kognetiks - Flow API - Ver 1.9.5
173 require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-call-openai-api-omni.php';
174 // ChatGPT API - Ver 2.0.2.1
175 require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-call-openai-api-stt.php';
176 // STT API - Ver 2.0.1
177 require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-call-openai-api-tts.php';
178 // TTS API - Ver 1.9.4
179 require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-globals.php';
180 // Globals - Ver 1.6.5
181 require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-shortcode.php';
182 // Shortcode - Ver 1.6.5
183 // Include necessary files - Appearance - Ver 1.8.1
184 require_once plugin_dir_path( __FILE__ ) . 'includes/appearance/chatbot-settings-appearance-body.php';
185 require_once plugin_dir_path( __FILE__ ) . 'includes/appearance/chatbot-settings-appearance-dimensions.php';
186 require_once plugin_dir_path( __FILE__ ) . 'includes/appearance/chatbot-settings-appearance-text.php';
187 require_once plugin_dir_path( __FILE__ ) . 'includes/appearance/chatbot-settings-appearance-user-css.php';
188 // Include necessary files - Knowledge Navigator
189 require_once plugin_dir_path( __FILE__ ) . 'includes/knowledge-navigator/chatbot-kn-acquire-controller.php';
190 // Knowledge Navigator Acquisition - Ver 1.9.6
191 require_once plugin_dir_path( __FILE__ ) . 'includes/knowledge-navigator/chatbot-kn-acquire-words.php';
192 // Knowledge Navigator Acquisition - Ver 1.9.6
193 require_once plugin_dir_path( __FILE__ ) . 'includes/knowledge-navigator/chatbot-kn-analysis.php';
194 // Knowledge Navigator Analysis- Ver 1.6.2
195 require_once plugin_dir_path( __FILE__ ) . 'includes/knowledge-navigator/chatbot-kn-db.php';
196 // Knowledge Navigator - Database Management - Ver 1.6.3
197 require_once plugin_dir_path( __FILE__ ) . 'includes/knowledge-navigator/chatbot-kn-enhance-context.php';
198 // Knowledge Navigator - Enhance Context - Ver 1.6.9
199 require_once plugin_dir_path( __FILE__ ) . 'includes/knowledge-navigator/chatbot-kn-enhance-response.php';
200 // Knowledge Navigator - TD-IDF Response Enhancement - Ver 1.6.9
201 require_once plugin_dir_path( __FILE__ ) . 'includes/knowledge-navigator/chatbot-kn-scheduler.php';
202 // Knowledge Navigator - Scheduler - Ver 1.6.3
203 require_once plugin_dir_path( __FILE__ ) . 'includes/knowledge-navigator/chatbot-kn-settings.php';
204 // Knowledge Navigator - Settings - Ver 1.6.1
205 // Include necessary files - Markov Chain - Ver 2.1.9
206 require_once plugin_dir_path( __FILE__ ) . 'includes/markov-chain/chatbot-markov-chain-decode.php';
207 // Functions - Ver 2.1.9
208 require_once plugin_dir_path( __FILE__ ) . 'includes/markov-chain/chatbot-markov-chain-decode-beaker.php';
209 // Functions - Ver 2.2.0
210 require_once plugin_dir_path( __FILE__ ) . 'includes/markov-chain/chatbot-markov-chain-encode.php';
211 // Functions - Ver 2.1.9
212 require_once plugin_dir_path( __FILE__ ) . 'includes/markov-chain/chatbot-markov-chain-scheduler.php';
213 // Functions - Ver 2.1.9
214 // Include necessary files - Transformer Model - Ver 2.2.0
215 require_once plugin_dir_path( __FILE__ ) . 'includes/transformers/lexical-context-model.php';
216 // Functions - Ver 2.2.0
217 require_once plugin_dir_path( __FILE__ ) . 'includes/transformers/sentential-context-model.php';
218 // Functions - Ver 2.2.0
219 require_once plugin_dir_path( __FILE__ ) . 'includes/transformers/transformer-model-scheduler.php';
220 // Functions - Ver 2.2.0
221 // Include necessary files - Settings
222 require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-api-anthropic.php';
223 // Anthropic
224 require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-api-azure-assistants.php';
225 // Azure Assistants - Ver 2.2.6
226 require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-api-azure.php';
227 // Azure - Ver 2.2.6
228 require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-api-deepseek.php';
229 // DeepSeek
230 require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-api-google.php';
231 // Google - Ver 2.3.9
232 require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-api-nvidia.php';
233 // NVIDIA
234 require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-api-local.php';
235 // Local Server - Ver 2.2.6
236 require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-api-mistral-agents.php';
237 // Mistral Agents - Ver 2.3.0
238 require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-api-mistral.php';
239 // Mistral
240 require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-api-openai-assistants.php';
241 // OpenAI ChatGPT
242 require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-api-openai.php';
243 // OpenAI ChatGPT
244 require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-api-test.php';
245 require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-appearance.php';
246 require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-avatar.php';
247 require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-buttons.php';
248 require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-diagnostics.php';
249 require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-general.php';
250 require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-links.php';
251 require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-localization.php';
252 require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-localize.php';
253 require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-markov-chain.php';
254 require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-menus.php';
255 require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-notices.php';
256 require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-registration-api.php';
257 require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-registration-kn.php';
258 require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-registration.php';
259 require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-reporting.php';
260 require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-support.php';
261 require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-tools.php';
262 require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-transformers.php';
263 require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings.php';
264 // Include necessary files - Utilities - Ver 1.9.0
265 require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-agents-mistral.php';
266 // Mistral Agents - Ver 2.3.0
267 require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-api-endpoints.php';
268 // API Endpoints - Ver 2.2.2
269 require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-assistants.php';
270 // Assistants Management for OpenAI - Ver 2.0.4
271 require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-assistants-azure.php';
272 // Assistants Management for Azure - Ver 2.2.6
273 require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-assisted-search.php';
274 // Assisted Search - Ver 2.2.7 - 2025-03-26
275 require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-conversation-context.php';
276 // Conversation Context - Ver 2.3.9
277 require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-conversation-digest.php';
278 // Conversation Digest - Ver 2.3.9
279 require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-conversation-history.php';
280 // Ver 1.9.2
281 require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-content-search.php';
282 // Functions - Ver 2.2.4
283 require_once plugin_dir_path( __FILE__ ) . 'includes/dashboard/chatbot-chatgpt-dashboard-widget.php';
284 // Dashboard Widget - Ver 2.2.7
285 require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-db-management.php';
286 // Database Management for Reporting - Ver 1.6.3
287 require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-deactivate.php';
288 // Deactivation - Ver 1.9.9
289 require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-download-transcript.php';
290 // Functions - Ver 1.9.9
291 require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-erase-conversation.php';
292 // Functions - Ver 1.8.6
293 require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-file-download.php';
294 // Download a file via the API - Ver 2.0.3
295 require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-file-helper.php';
296 // Functions - Ver 2.0.3
297 require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-file-upload.php';
298 // Functions - Ver 1.7.6
299 require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-filter-out-html-tags.php';
300 // Functions - Ver 1.9.6
301 require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-helper-functions.php';
302 // Functions - Ver 1.0.0
303 require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-keyguard.php';
304 // Functions - Ver 2.2.6
305 require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-link-and-image-handling.php';
306 // Globals - Ver 1.9.1
307 require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-models.php';
308 // Functions - Ver 1.9.4
309 require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-names.php';
310 // Functions - Ver 1.9.4
311 require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-options-helper.php';
312 // Functions - Ver 2.0.5
313 require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-threads.php';
314 // Ver 1.7.2.1
315 require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-transients-file.php';
316 // Ver 1.9.2
317 require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-transients.php';
318 // Ver 1.7.2
319 require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-upgrade.php';
320 // Ver 1.6.7
321 // chatbot-utilities.php moved above to be loaded before API files - Ver 2.3.9
322 // Third-party libraries
323 require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/parsedown.php';
324 // Version 2.0.2.1
325 // Include necessary files - Tools - Ver 2.0.6
326 require_once plugin_dir_path( __FILE__ ) . 'tools/chatbot-capability-tester.php';
327 require_once plugin_dir_path( __FILE__ ) . 'tools/chatbot-manage-error-logs.php';
328 require_once plugin_dir_path( __FILE__ ) . 'tools/chatbot-options-exporter.php';
329 require_once plugin_dir_path( __FILE__ ) . 'tools/chatbot-shortcode-tester.php';
330 require_once plugin_dir_path( __FILE__ ) . 'tools/chatbot-shortcode-tester-tool.php';
331 // Include necessary files - Insights - Ver 2.3.6
332 // require_once plugin_dir_path(__FILE__) . 'includes/insights/insights-settings.php';
333 // require_once plugin_dir_path(__FILE__) . 'includes/insights/chatbot-insights.php';
334 // require_once plugin_dir_path(__FILE__) . 'includes/insights/languages/en_US.php';
335 // require_once plugin_dir_path(__FILE__) . 'includes/insights/scoring-models/sentiment-analysis.php';
336 // require_once plugin_dir_path(__FILE__) . 'includes/insights/utilities.php';
337 // require_once plugin_dir_path(__FILE__) . 'includes/insights/globals.php';
338 /**
339 * Dynamically load Insights files when premium status is detected
340 * This function can be called on-demand to load Insights files after plan upgrades
341 *
342 * NOTE: Uses chatbot_chatgpt_is_premium() which follows Freemius best practices.
343 *
344 * @return bool True if files were loaded, false otherwise
345 * @since 2.4.2
346 */
347 function chatbot_chatgpt_load_insights_files() {
348 // Check if files are already loaded
349 if ( function_exists( 'kognetiks_insights_settings_page' ) ) {
350 return true;
351 }
352 // Check if user has premium access using the centralized helper function
353 // This follows Freemius best practices
354 if ( !function_exists( 'chatbot_chatgpt_is_premium' ) ) {
355 return false;
356 }
357 $has_premium_access = chatbot_chatgpt_is_premium();
358 // Load files if user has premium access
359 if ( $has_premium_access ) {
360 $plugin_dir = plugin_dir_path( __FILE__ );
361 $insights_files = array(
362 'includes/insights/scoring-models/sentiment-analysis.php',
363 'includes/insights/automated-emails.php',
364 'includes/insights/chatbot-insights.php',
365 'includes/insights/globals.php',
366 'includes/insights/insights-settings.php',
367 'includes/insights/languages/en_US.php',
368 'includes/insights/utilities.php'
369 );
370 foreach ( $insights_files as $file ) {
371 $file_path = $plugin_dir . $file;
372 if ( file_exists( $file_path ) ) {
373 require_once $file_path;
374 }
375 }
376 // Register admin_init action for period filter if not already registered
377 if ( !has_action( 'admin_init', 'chatbot_chatgpt_insights_period_filter_handler' ) ) {
378 add_action( 'admin_init', 'chatbot_chatgpt_insights_period_filter_handler' );
379 }
380 return true;
381 }
382 return false;
383 }
384
385 /**
386 * Handle Insights period filter form submission
387 *
388 * @since 2.4.2
389 */
390 function chatbot_chatgpt_insights_period_filter_handler() {
391 if ( isset( $_POST['chatbot_chatgpt_insights_action'] ) && $_POST['chatbot_chatgpt_insights_action'] === 'period_filter' && isset( $_POST['chatbot_chatgpt_insights_period_filter_nonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['chatbot_chatgpt_insights_period_filter_nonce'] ) ), 'chatbot_chatgpt_insights_period_filter_action' ) ) {
392 // Handle the period filter logic here
393 $selected_period = ( isset( $_POST['chatbot_chatgpt_insights_period_filter'] ) ? sanitize_text_field( wp_unslash( $_POST['chatbot_chatgpt_insights_period_filter'] ) ) : 'Today' );
394 // Store in a transient or option, or pass as needed
395 set_transient( 'chatbot_chatgpt_selected_period', $selected_period, 60 * 5 );
396 wp_redirect( admin_url( 'admin.php?page=chatbot-chatgpt&tab=insights' ) );
397 exit;
398 }
399 }
400
401 // Include Insights library - Premium Only (at plugin init)
402 // Check for premium access including trial status (trial users should have premium access)
403 if ( function_exists( 'chatbot_chatgpt_is_premium' ) && chatbot_chatgpt_is_premium() ) {
404 chatbot_chatgpt_load_insights_files();
405 } elseif ( function_exists( 'chatbot_chatgpt_freemius' ) ) {
406 // Fallback: use same logic as chatbot_chatgpt_is_premium()
407 $fs = chatbot_chatgpt_freemius();
408 if ( is_object( $fs ) ) {
409 // Detect whether we are running inside the premium build
410 $running_premium_build = false;
411 if ( method_exists( $fs, 'is__premium_only' ) ) {
412 $running_premium_build = $fs->is__premium_only();
413 }
414 // Check if paying
415 if ( method_exists( $fs, 'is_paying' ) && $fs->is_paying() ) {
416 chatbot_chatgpt_load_insights_files();
417 } elseif ( method_exists( $fs, 'has_active_valid_license' ) && $fs->has_active_valid_license() ) {
418 chatbot_chatgpt_load_insights_files();
419 } elseif ( method_exists( $fs, 'is_trial' ) && $fs->is_trial() && $running_premium_build ) {
420 chatbot_chatgpt_load_insights_files();
421 }
422 }
423 }
424 // Handle plan changes and premium activation - Ver 2.4.2
425 // This ensures Insights files are loaded after plan upgrades
426 add_action( 'fs_after_account_plan_sync_chatbot-chatgpt', function () {
427 // When plan is synced, try to load Insights files if premium status is detected
428 chatbot_chatgpt_load_insights_files();
429 }, 10 );
430 add_action( 'fs_after_license_change_chatbot-chatgpt', function () {
431 // When license changes, try to load Insights files if premium status is detected
432 chatbot_chatgpt_load_insights_files();
433 }, 10 );
434 // Also hook into Freemius after_premium_version_activation if available
435 if ( function_exists( 'chatbot_chatgpt_freemius' ) ) {
436 chatbot_chatgpt_freemius()->add_action( 'after_premium_version_activation', function () {
437 chatbot_chatgpt_load_insights_files();
438 } );
439 }
440 // Include necessary files - Widgets - Ver 2.1.3
441 require_once plugin_dir_path( __FILE__ ) . 'widgets/chatbot-manage-widget-logs.php';
442 // Log the User ID and Session ID - Ver 2.0.6 - 2024 07 11
443 // Check for Upgrades - Ver 1.7.7
444 if ( !esc_attr( get_option( 'chatbot_chatgpt_upgraded' ) ) ) {
445 chatbot_chatgpt_upgrade();
446 update_option( 'chatbot_chatgpt_upgraded', 'Yes' );
447 }
448 // Diagnotics on/off setting can be found on the Settings tab - Ver 1.5.0
449 $chatbot_chatgpt_diagnostics = esc_attr( get_option( 'chatbot_chatgpt_diagnostics', 'Off' ) );
450 global $chatbot_ai_platform_choice;
451 global $model;
452 global $voice;
453 // FIXME - SEE AI Platform Selection setting - Ver 2.1.8
454 $chatbot_ai_platform_choice = esc_attr( get_option( 'chatbot_ai_platform_choice', 'OpenAI' ) );
455 // DIAG - Diagnostics
456 // ( 'NOTICE', 'AI Platform: ' . $chatbot_ai_platform_choice);
457 switch ( $chatbot_ai_platform_choice ) {
458 case 'OpenAI':
459 update_option( 'chatbot_ai_platform_choice', 'OpenAI' );
460 $chatbot_chatgpt_api_enabled = 'Yes';
461 update_option( 'chatbot_chatgpt_api_enabled', 'Yes' );
462 $chatbot_azure_api_enabled = 'No';
463 update_option( 'chatbot_azure_api_enabled', 'No' );
464 $chatbot_nvidia_api_enabled = 'No';
465 update_option( 'chatbot_nvidia_api_enabled', 'No' );
466 $chatbot_anthropic_api_enabled = 'No';
467 update_option( 'chatbot_anthropic_api_enabled', 'No' );
468 $chatbot_deepseek_api_enabled = 'No';
469 update_option( 'chatbot_deepseek_api_enabled', 'No' );
470 $chatbot_markov_chain_api_enabled = 'No';
471 update_option( 'chatbot_markov_chain_api_enabled', 'No' );
472 $chatbot_transformer_model_api_enabled = 'No';
473 update_option( 'chatbot_transformer_model_api_enabled', 'No' );
474 $chatbot_local_api_enabled = 'No';
475 update_option( 'chatbot_local_api_enabled', 'No' );
476 $chatbot_mistral_api_enabled = 'No';
477 update_option( 'chatbot_mistral_api_enabled', 'No' );
478 $chatbot_google_api_enabled = 'No';
479 update_option( 'chatbot_google_api_enabled', 'No' );
480 // Model choice - Ver 1.9.4
481 if ( esc_attr( get_option( 'chatbot_chatgpt_model_choice' ) ) === null ) {
482 $model = 'gpt-4-1106-preview';
483 update_option( 'chatbot_chatgpt_model_choice', $model );
484 // DIAG - Diagnostics
485 } elseif ( empty( $model ) ) {
486 $model = 'gpt-4-1106-preview';
487 }
488 // Voice choice - Ver 1.9.5
489 if ( esc_attr( get_option( 'chatbot_chatgpt_voice_option' ) ) === null ) {
490 $voice = 'alloy';
491 update_option( 'chatbot_chatgpt_voice_option', $voice );
492 // DIAG - Diagnostics
493 }
494 break;
495 case 'Azure OpenAI':
496 update_option( 'chatbot_ai_platform_choice', 'Azure OpenAI' );
497 $chatbot_chatgpt_api_enabled = 'No';
498 update_option( 'chatbot_chatgpt_api_enabled', 'No' );
499 $chatbot_azure_api_enabled = 'Yes';
500 update_option( 'chatbot_azure_api_enabled', 'Yes' );
501 $chatbot_nvidia_api_enabled = 'No';
502 update_option( 'chatbot_nvidia_api_enabled', 'No' );
503 $chatbot_anthropic_api_enabled = 'No';
504 update_option( 'chatbot_anthropic_api_enabled', 'No' );
505 $chatbot_deepseek_api_enabled = 'No';
506 update_option( 'chatbot_deepseek_api_enabled', 'No' );
507 $chatbot_markov_chain_api_enabled = 'No';
508 update_option( 'chatbot_markov_chain_api_enabled', 'No' );
509 $chatbot_transformer_model_api_enabled = 'No';
510 update_option( 'chatbot_transformer_model_api_enabled', 'No' );
511 $chatbot_local_api_enabled = 'No';
512 update_option( 'chatbot_local_api_enabled', 'No' );
513 $chatbot_mistral_api_enabled = 'No';
514 update_option( 'chatbot_mistral_api_enabled', 'No' );
515 $chatbot_google_api_enabled = 'No';
516 update_option( 'chatbot_google_api_enabled', 'No' );
517 // Model choice - Ver 1.9.4
518 if ( esc_attr( get_option( 'chatbot_azure_model_choice' ) ) === null ) {
519 $model = 'gpt-4-1106-preview';
520 update_option( 'chatbot_azure_model_choice', $model );
521 // DIAG - Diagnostics
522 } elseif ( empty( $model ) ) {
523 $model = 'gpt-4-1106-preview';
524 }
525 // FIXME - TEMPORARILY DISABLED - 2025-03-07
526 // Disable Read Aloud - Ver 2.2.6
527 update_option( 'chatbot_chatgpt_read_aloud_option', 'no' );
528 // Voice choice - Ver 1.9.5
529 // if (esc_attr(get_option('chatbot_azure_voice_option')) === null) {
530 // $voice = 'alloy';
531 // update_option('chatbot_azure_voice_option', $voice);
532 // // DIAG - Diagnostics
533 // }
534 break;
535 case 'NVIDIA':
536 update_option( 'chatbot_ai_platform_choice', 'NVIDIA' );
537 $chatbot_chatgpt_api_enabled = 'No';
538 update_option( 'chatbot_chatgpt_api_enabled', 'No' );
539 $chatbot_azure_api_enabled = 'No';
540 update_option( 'chatbot_azure_api_enabled', 'No' );
541 $chatbot_nvidia_api_enabled = 'Yes';
542 update_option( 'chatbot_nvidia_api_enabled', 'Yes' );
543 $chatbot_anthropic_api_enabled = 'No';
544 update_option( 'chatbot_anthropic_api_enabled', 'No' );
545 $chatbot_deepseek_api_enabled = 'No';
546 update_option( 'chatbot_deepseek_api_enabled', 'No' );
547 $chatbot_markov_chain_api_enabled = 'No';
548 update_option( 'chatbot_markov_chain_api_enabled', 'No' );
549 $chatbot_transformer_model_api_enabled = 'No';
550 update_option( 'chatbot_transformer_model_api_enabled', 'No' );
551 $chatbot_local_api_enabled = 'No';
552 update_option( 'chatbot_local_api_enabled', 'No' );
553 $chatbot_mistral_api_enabled = 'No';
554 update_option( 'chatbot_mistral_api_enabled', 'No' );
555 $chatbot_google_api_enabled = 'No';
556 update_option( 'chatbot_google_api_enabled', 'No' );
557 // Model choice - Ver 2.1.8
558 if ( esc_attr( get_option( 'chatbot_nvidia_model_choice' ) ) === null ) {
559 $model = 'nvidia/llama-3.1-nemotron-51b-instruct';
560 update_option( 'chatbot_nvidia_model_choice', $model );
561 // DIAG - Diagnostics
562 } elseif ( empty( $model ) ) {
563 $model = 'nvidia/llama-3.1-nemotron-51b-instruct';
564 }
565 // Disable Read Aloud - Ver 2.2.1
566 update_option( 'chatbot_chatgpt_read_aloud_option', 'no' );
567 // Disable File Uploads - Ver 2.2.1
568 update_option( 'chatbot_chatgpt_allow_file_uploads', 'No' );
569 // Disable MP3 Uploads - Ver 2.2.1
570 update_option( 'chatbot_chatgpt_allow_mp3_uploads', 'No' );
571 break;
572 case 'Anthropic':
573 update_option( 'chatbot_ai_platform_choice', 'Anthropic' );
574 $chatbot_chatgpt_api_enabled = 'No';
575 update_option( 'chatbot_chatgpt_api_enabled', 'No' );
576 $chatbot_azure_api_enabled = 'No';
577 update_option( 'chatbot_azure_api_enabled', 'No' );
578 $chatbot_nvidia_api_enabled = 'No';
579 update_option( 'chatbot_nvidia_api_enabled', 'No' );
580 $chatbot_anthropic_api_enabled = 'Yes';
581 update_option( 'chatbot_anthropic_api_enabled', 'Yes' );
582 $chatbot_deepseek_api_enabled = 'No';
583 update_option( 'chatbot_deepseek_api_enabled', 'No' );
584 $chatbot_markov_chain_api_enabled = 'No';
585 update_option( 'chatbot_markov_chain_api_enabled', 'No' );
586 $chatbot_transformer_model_api_enabled = 'No';
587 update_option( 'chatbot_transformer_model_api_enabled', 'No' );
588 $chatbot_local_api_enabled = 'No';
589 update_option( 'chatbot_local_api_enabled', 'No' );
590 $chatbot_mistral_api_enabled = 'No';
591 update_option( 'chatbot_mistral_api_enabled', 'No' );
592 $chatbot_google_api_enabled = 'No';
593 update_option( 'chatbot_google_api_enabled', 'No' );
594 // Model choice - Ver 2.2.1
595 if ( esc_attr( get_option( 'chatbot_anthropic_model_choice' ) ) === null ) {
596 $model = 'claude-3-5-sonnet-latest';
597 update_option( 'chatbot_anthropic_model_choice', $model );
598 // DIAG - Diagnostics
599 } elseif ( empty( $model ) ) {
600 $model = 'claude-3-5-sonnet-latest';
601 }
602 // Disable Read Aloud - Ver 2.2.1
603 update_option( 'chatbot_chatgpt_read_aloud_option', 'no' );
604 // Disable File Uploads - Ver 2.2.1
605 update_option( 'chatbot_chatgpt_allow_file_uploads', 'No' );
606 // Disable MP3 Uploads - Ver 2.2.1
607 update_option( 'chatbot_chatgpt_allow_mp3_uploads', 'No' );
608 break;
609 case 'DeepSeek':
610 update_option( 'chatbot_ai_platform_choice', 'DeepSeek' );
611 $chatbot_chatgpt_api_enabled = 'No';
612 update_option( 'chatbot_chatgpt_api_enabled', 'No' );
613 $chatbot_azure_api_enabled = 'No';
614 update_option( 'chatbot_azure_api_enabled', 'No' );
615 $chatbot_nvidia_api_enabled = 'No';
616 update_option( 'chatbot_nvidia_api_enabled', 'No' );
617 $chatbot_anthropic_api_enabled = 'No';
618 update_option( 'chatbot_anthropic_api_enabled', 'No' );
619 $chatbot_deepseek_api_enabled = 'Yes';
620 update_option( 'chatbot_deepseek_api_enabled', 'Yes' );
621 $chatbot_markov_chain_api_enabled = 'No';
622 update_option( 'chatbot_markov_chain_api_enabled', 'No' );
623 $chatbot_transformer_model_api_enabled = 'No';
624 update_option( 'chatbot_transformer_model_api_enabled', 'No' );
625 $chatbot_local_api_enabled = 'No';
626 update_option( 'chatbot_local_api_enabled', 'No' );
627 $chatbot_mistral_api_enabled = 'No';
628 update_option( 'chatbot_mistral_api_enabled', 'No' );
629 $chatbot_google_api_enabled = 'No';
630 update_option( 'chatbot_google_api_enabled', 'No' );
631 // Model choice - Ver 2.2.1
632 if ( esc_attr( get_option( 'chatbot_deepseek_model_choice' ) ) === null ) {
633 $model = 'deepseek-chat';
634 update_option( 'chatbot_deepseek_model_choice', $model );
635 // DIAG - Diagnostics
636 } elseif ( empty( $model ) ) {
637 $model = 'deepseek-chat';
638 }
639 // Disable Read Aloud - Ver 2.2.1
640 update_option( 'chatbot_chatgpt_read_aloud_option', 'no' );
641 // Disable File Uploads - Ver 2.2.1
642 update_option( 'chatbot_chatgpt_allow_file_uploads', 'No' );
643 // Disable MP3 Uploads - Ver 2.2.1
644 update_option( 'chatbot_chatgpt_allow_mp3_uploads', 'No' );
645 break;
646 case 'Mistral':
647 update_option( 'chatbot_ai_platform_choice', 'Mistral' );
648 $chatbot_chatgpt_api_enabled = 'No';
649 update_option( 'chatbot_chatgpt_api_enabled', 'No' );
650 $chatbot_azure_api_enabled = 'No';
651 update_option( 'chatbot_azure_api_enabled', 'No' );
652 $chatbot_nvidia_api_enabled = 'No';
653 update_option( 'chatbot_nvidia_api_enabled', 'No' );
654 $chatbot_anthropic_api_enabled = 'No';
655 update_option( 'chatbot_anthropic_api_enabled', 'No' );
656 $chatbot_deepseek_api_enabled = 'No';
657 update_option( 'chatbot_deepseek_api_enabled', 'No' );
658 $chatbot_markov_chain_api_enabled = 'No';
659 update_option( 'chatbot_markov_chain_api_enabled', 'No' );
660 $chatbot_transformer_model_api_enabled = 'No';
661 update_option( 'chatbot_transformer_model_api_enabled', 'No' );
662 $chatbot_local_api_enabled = 'No';
663 update_option( 'chatbot_local_api_enabled', 'No' );
664 $chatbot_mistral_api_enabled = 'Yes';
665 update_option( 'chatbot_mistral_api_enabled', 'Yes' );
666 $chatbot_google_api_enabled = 'No';
667 update_option( 'chatbot_google_api_enabled', 'No' );
668 // Model choice - Ver 2.2.1
669 if ( esc_attr( get_option( 'chatbot_mistral_model_choice' ) ) === null ) {
670 $model = 'mistral-small-latest';
671 update_option( 'chatbot_mistral_model_choice', $model );
672 // DIAG - Diagnostics
673 } elseif ( empty( $model ) ) {
674 $model = 'mistral-small-latest';
675 }
676 // Disable Read Aloud - Ver 2.2.1
677 update_option( 'chatbot_chatgpt_read_aloud_option', 'no' );
678 // Disable File Uploads - Ver 2.2.1
679 update_option( 'chatbot_chatgpt_allow_file_uploads', 'No' );
680 // Disable MP3 Uploads - Ver 2.2.1
681 update_option( 'chatbot_chatgpt_allow_mp3_uploads', 'No' );
682 break;
683 case 'Google':
684 update_option( 'chatbot_ai_platform_choice', 'Google' );
685 $chatbot_chatgpt_api_enabled = 'No';
686 update_option( 'chatbot_chatgpt_api_enabled', 'No' );
687 $chatbot_azure_api_enabled = 'No';
688 update_option( 'chatbot_azure_api_enabled', 'No' );
689 $chatbot_nvidia_api_enabled = 'No';
690 update_option( 'chatbot_nvidia_api_enabled', 'No' );
691 $chatbot_anthropic_api_enabled = 'No';
692 update_option( 'chatbot_anthropic_api_enabled', 'No' );
693 $chatbot_deepseek_api_enabled = 'No';
694 update_option( 'chatbot_deepseek_api_enabled', 'No' );
695 $chatbot_markov_chain_api_enabled = 'No';
696 update_option( 'chatbot_markov_chain_api_enabled', 'No' );
697 $chatbot_transformer_model_api_enabled = 'No';
698 update_option( 'chatbot_transformer_model_api_enabled', 'No' );
699 $chatbot_local_api_enabled = 'No';
700 update_option( 'chatbot_local_api_enabled', 'No' );
701 $chatbot_mistral_api_enabled = 'No';
702 update_option( 'chatbot_mistral_api_enabled', 'No' );
703 $chatbot_google_api_enabled = 'Yes';
704 update_option( 'chatbot_google_api_enabled', 'Yes' );
705 // Model choice - Ver 2.3.9
706 if ( esc_attr( get_option( 'chatbot_google_model_choice' ) ) === null ) {
707 $model = 'gemini-2.0-flash';
708 update_option( 'chatbot_google_model_choice', $model );
709 // DIAG - Diagnostics
710 } elseif ( empty( $model ) ) {
711 $model = 'gemini-2.0-flash';
712 }
713 // Disable Read Aloud - Ver 2.3.9
714 update_option( 'chatbot_chatgpt_read_aloud_option', 'no' );
715 // Disable File Uploads - Ver 2.3.9
716 update_option( 'chatbot_chatgpt_allow_file_uploads', 'No' );
717 // Disable MP3 Uploads - Ver 2.3.9
718 update_option( 'chatbot_chatgpt_allow_mp3_uploads', 'No' );
719 break;
720 case 'Markov Chain':
721 update_option( 'chatbot_ai_platform_choice', 'Markov Chain' );
722 $chatbot_chatgpt_api_enabled = 'No';
723 update_option( 'chatbot_chatgpt_api_enabled', 'No' );
724 $chatbot_azure_api_enabled = 'No';
725 update_option( 'chatbot_azure_api_enabled', 'No' );
726 $chatbot_nvidia_api_enabled = 'No';
727 update_option( 'chatbot_nvidia_api_enabled', 'No' );
728 $chatbot_anthropic_api_enabled = 'No';
729 update_option( 'chatbot_anthropic_api_enabled', 'No' );
730 $chatbot_deepseek_api_enabled = 'No';
731 update_option( 'chatbot_deepseek_api_enabled', 'No' );
732 $chatbot_markov_chain_api_enabled = 'Yes';
733 update_option( 'chatbot_markov_chain_api_enabled', 'Yes' );
734 $chatbot_transformer_model_api_enabled = 'No';
735 update_option( 'chatbot_transformer_model_api_enabled', 'No' );
736 $chatbot_local_api_enabled = 'No';
737 update_option( 'chatbot_local_api_enabled', 'No' );
738 $chatbot_mistral_api_enabled = 'No';
739 update_option( 'chatbot_mistral_api_enabled', 'No' );
740 $chatbot_google_api_enabled = 'No';
741 update_option( 'chatbot_google_api_enabled', 'No' );
742 // Model choice - Ver 2.1.8
743 if ( esc_attr( get_option( 'chatbot_markov_chain_model_choice' ) ) === null ) {
744 $model = 'markov-chain-flask';
745 update_option( 'chatbot_markov_chain_model_choice', $model );
746 // DIAG - Diagnostics
747 } elseif ( empty( $model ) ) {
748 $model = 'markov-chain-flask';
749 }
750 // Disable Read Aloud - Ver 2.2.1
751 update_option( 'chatbot_chatgpt_read_aloud_option', 'no' );
752 // Disable File Uploads - Ver 2.2.1
753 update_option( 'chatbot_chatgpt_allow_file_uploads', 'No' );
754 // Disable MP3 Uploads - Ver 2.2.1
755 update_option( 'chatbot_chatgpt_allow_mp3_uploads', 'No' );
756 break;
757 case 'Transformer':
758 update_option( 'chatbot_ai_platform_choice', 'Transformer' );
759 $chatbot_chatgpt_api_enabled = 'No';
760 update_option( 'chatbot_chatgpt_api_enabled', 'No' );
761 $chatbot_azure_api_enabled = 'No';
762 update_option( 'chatbot_azure_api_enabled', 'No' );
763 $chatbot_nvidia_api_enabled = 'No';
764 update_option( 'chatbot_nvidia_api_enabled', 'No' );
765 $chatbot_anthropic_api_enabled = 'No';
766 update_option( 'chatbot_anthropic_api_enabled', 'No' );
767 $chatbot_deepseek_api_enabled = 'No';
768 update_option( 'chatbot_deepseek_api_enabled', 'No' );
769 $chatbot_markov_chain_api_enabled = 'No';
770 update_option( 'chatbot_markov_chain_api_enabled', 'No' );
771 $chatbot_transformer_model_api_enabled = 'Yes';
772 update_option( 'chatbot_transformer_model_api_enabled', 'Yes' );
773 $chatbot_local_api_enabled = 'No';
774 update_option( 'chatbot_local_api_enabled', 'No' );
775 $chatbot_mistral_api_enabled = 'No';
776 update_option( 'chatbot_mistral_api_enabled', 'No' );
777 $chatbot_google_api_enabled = 'No';
778 update_option( 'chatbot_google_api_enabled', 'No' );
779 // Model choice - Ver 2.2.0
780 if ( esc_attr( get_option( 'chatbot_transformer_model_choice' ) ) === null ) {
781 $model = 'sentential-context-model';
782 update_option( 'chatbot_transformer_model_choice', $model );
783 // DIAG - Diagnostics
784 } elseif ( empty( $model ) ) {
785 $model = 'sentential-context-model';
786 }
787 // Disable Read Aloud - Ver 2.2.1
788 update_option( 'chatbot_chatgpt_read_aloud_option', 'no' );
789 // Disable File Uploads - Ver 2.2.1
790 update_option( 'chatbot_chatgpt_allow_file_uploads', 'No' );
791 // Disable MP3 Uploads - Ver 2.2.1
792 update_option( 'chatbot_chatgpt_allow_mp3_uploads', 'No' );
793 break;
794 case 'Local Server':
795 // DIAG - Diagnostics
796 update_option( 'chatbot_ai_platform_choice', 'Local Server' );
797 $chatbot_chatgpt_api_enabled = 'No';
798 update_option( 'chatbot_chatgpt_api_enabled', 'No' );
799 $chatbot_azure_api_enabled = 'No';
800 update_option( 'chatbot_azure_api_enabled', 'No' );
801 $chatbot_nvidia_api_enabled = 'No';
802 update_option( 'chatbot_nvidia_api_enabled', 'No' );
803 $chatbot_anthropic_api_enabled = 'No';
804 update_option( 'chatbot_anthropic_api_enabled', 'No' );
805 $chatbot_deepseek_api_enabled = 'No';
806 update_option( 'chatbot_deepseek_api_enabled', 'No' );
807 $chatbot_markov_chain_api_enabled = 'No';
808 update_option( 'chatbot_markov_chain_api_enabled', 'No' );
809 $chatbot_transformer_model_api_enabled = 'No';
810 update_option( 'chatbot_transformer_model_api_enabled', 'No' );
811 $chatbot_local_api_enabled = 'Yes';
812 update_option( 'chatbot_local_api_enabled', 'Yes' );
813 $chatbot_mistral_api_enabled = 'No';
814 update_option( 'chatbot_mistral_api_enabled', 'No' );
815 $chatbot_google_api_enabled = 'No';
816 update_option( 'chatbot_google_api_enabled', 'No' );
817 // Model choice - Ver 2.2.0
818 if ( esc_attr( get_option( 'chatbot_local_model_choice' ) ) === null ) {
819 $model = 'llama3.2-3b-instruct';
820 update_option( 'chatbot_local_model_choice', $model );
821 // DIAG - Diagnostics
822 } elseif ( empty( $model ) ) {
823 $model = 'llama3.2-3b-instruct';
824 }
825 // Disable Read Aloud - Ver 2.2.1
826 update_option( 'chatbot_chatgpt_read_aloud_option', 'no' );
827 // Disable File Uploads - Ver 2.2.1
828 update_option( 'chatbot_chatgpt_allow_file_uploads', 'No' );
829 // Disable MP3 Uploads - Ver 2.2.1
830 update_option( 'chatbot_chatgpt_allow_mp3_uploads', 'No' );
831 break;
832 default:
833 update_option( 'chatbot_ai_platform_choice', 'OpenAI' );
834 $chatbot_chatgpt_api_enabled = 'Yes';
835 update_option( 'chatbot_chatgpt_api_enabled', 'Yes' );
836 $chatbot_azure_api_enabled = 'No';
837 update_option( 'chatbot_azure_api_enabled', 'No' );
838 $chatbot_nvidia_api_enabled = 'No';
839 update_option( 'chatbot_nvidia_api_enabled', 'No' );
840 $chatbot_anthropic_api_enabled = 'No';
841 update_option( 'chatbot_anthropic_api_enabled', 'No' );
842 $chatbot_deepseek_api_enabled = 'No';
843 update_option( 'chatbot_deepseek_api_enabled', 'No' );
844 $chatbot_markov_chain_api_enabled = 'No';
845 update_option( 'chatbot_markov_chain_api_enabled', 'No' );
846 $chatbot_transformer_model_api_enabled = 'No';
847 update_option( 'chatbot_transformer_model_api_enabled', 'No' );
848 $chatbot_mistral_api_enabled = 'No';
849 update_option( 'chatbot_mistral_api_enabled', 'No' );
850 $chatbot_google_api_enabled = 'No';
851 update_option( 'chatbot_google_api_enabled', 'No' );
852 // Model choice - Ver 1.9.4
853 if ( esc_attr( get_option( 'chatbot_chatgpt_model_choice' ) ) === null ) {
854 $model = 'gpt-4-1106-preview';
855 update_option( 'chatbot_chatgpt_model_choice', $model );
856 // DIAG - Diagnostics
857 } elseif ( empty( $model ) ) {
858 $model = 'gpt-4-1106-preview';
859 }
860 // Voice choice - Ver 1.9.5
861 if ( esc_attr( get_option( 'chatbot_chatgpt_voice_option' ) ) === null ) {
862 $voice = 'alloy';
863 update_option( 'chatbot_chatgpt_voice_option', $voice );
864 // DIAG - Diagnostics
865 }
866 break;
867 }
868 // Custom buttons on/off setting can be found on the Settings tab - Ver 1.6.5
869 $chatbot_chatgpt_enable_custom_buttons = esc_attr( get_option( 'chatbot_chatgpt_enable_custom_buttons', 'Off' ) );
870 // Allow file uploads on/off setting can be found on the Settings tab - Ver 1.7.6
871 global $chatbot_chatgpt_allow_file_uploads;
872 $chatbot_ai_platform_choice = esc_attr( get_option( 'chatbot_ai_platform_choice', 'OpenAI' ) );
873 if ( $chatbot_ai_platform_choice == 'OpenAI' ) {
874 $chatbot_chatgpt_allow_file_uploads = esc_attr( get_option( 'chatbot_chatgpt_allow_file_uploads', 'No' ) );
875 // DIAG - Diagnostics - Ver 2.2.6
876 } elseif ( $chatbot_ai_platform_choice == 'Azure OpenAI' ) {
877 $chatbot_chatgpt_allow_file_uploads = esc_attr( get_option( 'chatbot_azure_allow_file_uploads', 'No' ) );
878 // DIAG - Diagnostics - Ver 2.2.6
879 } else {
880 $chatbot_chatgpt_allow_file_uploads = esc_attr( get_option( 'chatbot_chatgpt_allow_file_uploads', 'No' ) );
881 // DIAG - Diagnostics - Ver 2.2.6
882 }
883 // Suppress Notices on/off setting can be found on the Settings tab - Ver 1.6.5
884 global $chatbot_chatgpt_suppress_notices;
885 $chatbot_chatgpt_suppress_notices = esc_attr( get_option( 'chatbot_chatgpt_suppress_notices', 'Off' ) );
886 // Suppress Attribution on/off setting can be found on the Settings tab - Ver 1.6.5
887 global $chatbot_chatgpt_suppress_attribution;
888 $chatbot_chatgpt_suppress_attribution = esc_attr( get_option( 'chatbot_chatgpt_suppress_attribution', 'On' ) );
889 // Suppress Learnings Message - Ver 1.7.1
890 global $chatbot_chatgpt_suppress_learnings;
891 $chatbot_chatgpt_suppress_learnings = esc_attr( get_option( 'chatbot_chatgpt_suppress_learnings', 'Random' ) );
892 // Context History - Ver 1.6.1
893 $context_history = [];
894 function chatbot_chatgpt_enqueue_admin_scripts() {
895 global $chatbot_chatgpt_plugin_version;
896 wp_enqueue_script( 'jquery' );
897 // Ensure jQuery is enqueued
898 wp_enqueue_script(
899 'chatbot_chatgpt_admin',
900 plugins_url( 'assets/js/chatbot-chatgpt-admin.js', __FILE__ ),
901 array('jquery'),
902 $chatbot_chatgpt_plugin_version,
903 true
904 );
905 }
906
907 add_action( 'admin_enqueue_scripts', 'chatbot_chatgpt_enqueue_admin_scripts' );
908 // Activation, deactivation, and uninstall functions
909 register_activation_hook( __FILE__, 'chatbot_chatgpt_activate' );
910 register_activation_hook( __FILE__, 'create_chatbot_chatgpt_assistants_table' );
911 register_activation_hook( __FILE__, 'create_chatbot_azure_assistants_table' );
912 register_deactivation_hook( __FILE__, 'chatbot_chatgpt_deactivate' );
913 register_uninstall_hook( __FILE__, 'chatbot_chatgpt_uninstall' );
914 add_action(
915 'upgrader_process_complete',
916 'chatbot_chatgpt_upgrade_completed',
917 10,
918 2
919 );
920 // Enqueue plugin scripts and styles
921 function chatbot_chatgpt_enqueue_scripts() {
922 global $chatbot_chatgpt_plugin_dir_url;
923 global $chatbot_chatgpt_plugin_version;
924 global $session_id;
925 global $user_id;
926 global $page_id;
927 global $thread_id;
928 global $assistant_id;
929 global $kchat_settings;
930 global $additional_instructions;
931 global $model;
932 global $voice;
933 global $chatbot_chatgpt_display_style;
934 // Enqueue the styles
935 wp_enqueue_style( 'dashicons' );
936 wp_enqueue_style(
937 'chatbot-chatgpt-css',
938 plugins_url( 'assets/css/chatbot-chatgpt.css', __FILE__ ),
939 array(),
940 $chatbot_chatgpt_plugin_version,
941 'all'
942 );
943 // Now override the default styles with the custom styles - Ver 1.8.1
944 chatbot_chatgpt_appearance_custom_css_settings();
945 // Enqueue the scripts
946 wp_enqueue_script( 'jquery' );
947 wp_enqueue_script(
948 'chatbot-chatgpt-js',
949 plugins_url( 'assets/js/chatbot-chatgpt.js', __FILE__ ),
950 array('jquery'),
951 $chatbot_chatgpt_plugin_version,
952 true
953 );
954 // Enqueue DOMPurify - Ver 1.8.1
955 // https://raw.githubusercontent.com/cure53/DOMPurify/main/dist/purify.min.js
956 // https://chat.openai.com/c/275770c1-fa72-404b-97c2-2dad2e8a0230
957 wp_enqueue_script(
958 'dompurify',
959 plugin_dir_url( __FILE__ ) . 'assets/js/purify.min.js',
960 array(),
961 $chatbot_chatgpt_plugin_version,
962 true
963 );
964 // Localize the data for user id and page id
965 $user_id = get_current_user_id();
966 $page_id = get_the_id();
967 // Fetch the User ID - Updated Ver 2.0.6 - 2024 07 11
968 $user_id = get_current_user_id();
969 // Fetch the Kognetiks cookie
970 if ( empty( $session_id ) || $session_id == 0 ) {
971 $session_id = kognetiks_get_unique_id();
972 }
973 // $session_id = kognetiks_get_unique_id();
974 if ( empty( $user_id ) || $user_id == 0 ) {
975 $user_id = $session_id;
976 }
977 // Check if the $kchat_settings array is empty
978 if ( !$kchat_settings || !is_array( $kchat_settings ) ) {
979 $kchat_settings = [];
980 }
981 // Initial settings
982 $kchat_settings = array_merge( $kchat_settings, array(
983 'user_id' => $user_id,
984 'page_id' => $page_id,
985 'session_id' => $session_id,
986 'thread_id' => $thread_id,
987 'assistant_id' => $assistant_id,
988 'additional_instructions' => $additional_instructions,
989 'model' => $model,
990 'voice' => $voice,
991 'chatbot_message_nonce' => wp_create_nonce( 'chatbot_message_nonce' ),
992 'chatbot_upload_nonce' => wp_create_nonce( 'chatbot_upload_nonce' ),
993 'chatbot_erase_nonce' => wp_create_nonce( 'chatbot_erase_nonce' ),
994 'chatbot_unlock_nonce' => wp_create_nonce( 'chatbot_unlock_nonce' ),
995 'chatbot_reset_nonce' => wp_create_nonce( 'chatbot_reset_nonce' ),
996 'chatbot_queue_nonce' => wp_create_nonce( 'chatbot_queue_nonce' ),
997 'chatbot_tts_nonce' => wp_create_nonce( 'chatbot_tts_nonce' ),
998 'chatbot_transcript_nonce' => wp_create_nonce( 'chatbot_transcript_nonce' ),
999 'nonce_timestamp' => time() * 1000,
1000 ) );
1001 // DIAG - Diagnostics - Ver 1.8.6
1002 // Set visitor and logged in user limits - Ver 2.0.1
1003 if ( is_user_logged_in() ) {
1004 $kchat_settings['chatbot_chatgpt_message_limit_setting'] = esc_attr( get_option( 'chatbot_chatgpt_user_message_limit_setting', '999' ) );
1005 $kchat_settings['chatbot_chatgpt_message_limit_period_setting'] = esc_attr( get_option( 'chatbot_chatgpt_user_message_limit_period_setting', 'Lifetime' ) );
1006 $kchat_settings['chatbot_chatgpt_display_message_count'] = esc_attr( get_option( 'chatbot_chatgpt_display_message_count', 'No' ) );
1007 } else {
1008 $kchat_settings['chatbot_chatgpt_message_limit_setting'] = esc_attr( get_option( 'chatbot_chatgpt_visitor_message_limit_setting', '999' ) );
1009 $kchat_settings['chatbot_chatgpt_message_limit_period_setting'] = esc_attr( get_option( 'chatbot_chatgpt_visitor_message_limit_period_setting', 'Lifetime' ) );
1010 $kchat_settings['chatbot_chatgpt_display_message_count'] = esc_attr( get_option( 'chatbot_chatgpt_display_message_count', 'No' ) );
1011 }
1012 // Localize the data for the chatbot - Ver 2.1.1.1
1013 $kchat_settings = array_merge( $kchat_settings, array(
1014 'chatbot_chatgpt_display_style' => $chatbot_chatgpt_display_style,
1015 'chatbot_chatgpt_version' => $chatbot_chatgpt_plugin_version,
1016 'plugins_url' => $chatbot_chatgpt_plugin_dir_url,
1017 'ajax_url' => admin_url( 'admin-ajax.php' ),
1018 'user_id' => $user_id,
1019 'page_id' => $page_id,
1020 'session_id' => $session_id,
1021 'thread_id' => $thread_id,
1022 'assistant_id' => $assistant_id,
1023 'additional_instructions' => $additional_instructions,
1024 'model' => $model,
1025 'voice' => $voice,
1026 'chatbot_chatgpt_timeout_setting' => esc_attr( get_option( 'chatbot_chatgpt_timeout_setting', '240' ) ),
1027 'chatbot_chatgpt_avatar_icon_setting' => esc_attr( get_option( 'chatbot_chatgpt_avatar_icon_setting', '' ) ),
1028 'chatbot_chatgpt_custom_avatar_icon_setting' => esc_attr( get_option( 'chatbot_chatgpt_custom_avatar_icon_setting', '' ) ),
1029 'chatbot_chatgpt_avatar_greeting_setting' => esc_attr( get_option( 'chatbot_chatgpt_avatar_greeting_setting', 'Howdy!!! Great to see you today! How can I help you?' ) ),
1030 'chatbot_chatgpt_force_page_reload' => esc_attr( get_option( 'chatbot_chatgpt_force_page_reload', 'No' ) ),
1031 'chatbot_chatgpt_custom_error_message' => esc_attr( get_option( 'chatbot_chatgpt_custom_error_message', 'Your custom error message goes here.' ) ),
1032 ) );
1033 $kchat_settings_json = wp_json_encode( $kchat_settings );
1034 // Enqueue the main chatbot script - CHANGED TO LOAD ORDER IN V2.1.2
1035 wp_enqueue_script(
1036 'chatbot-chatgpt-js',
1037 plugins_url( 'assets/js/chatbot-chatgpt.js', __FILE__ ),
1038 array(),
1039 $chatbot_chatgpt_plugin_version,
1040 true
1041 );
1042 // Add the inline script to define kchat_settings before the main script runs - CHANGED THE LOAD ORDER IN VER 2.1.2
1043 wp_add_inline_script( 'chatbot-chatgpt-js', 'if (typeof kchat_settings === "undefined") { var kchat_settings = ' . $kchat_settings_json . '; } else { kchat_settings = ' . $kchat_settings_json . '; }', 'before' );
1044 // FIXME - REMOVED IN V2.1.2
1045 // wp_add_inline_script('chatbot-chatgpt-local', 'if (typeof kchat_settings === "undefined") { var kchat_settings = ' . $kchat_settings_json . '; } else { kchat_settings = ' . $kchat_settings_json . '; }', 'before');
1046 }
1047
1048 add_action( 'wp_enqueue_scripts', 'chatbot_chatgpt_enqueue_scripts' );
1049 // Enqueue MathJax with custom configuration - Ver 2.1.2
1050 // https://docs.mathjax.org/en/latest/
1051 // https://github.com/mathjax/MathJax/blob/master/LICENSE
1052 // https://cdnjs.cloudflare.com/ajax/libs/mathjax/3.2.0/es5/tex-mml-chtml.js
1053 // https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js
1054 function enqueue_mathjax_with_custom_config() {
1055 // Check to see if MathJax is enabled
1056 if ( esc_attr( get_option( 'chatbot_chatgpt_enable_mathjax', 'Yes' ) ) === 'Yes' ) {
1057 global $chatbot_chatgpt_plugin_version;
1058 global $chatbot_chatgpt_plugin_dir_url;
1059 // Add the MathJax configuration script
1060 $mathjax_config = "\r\n window.MathJax = {\r\n tex: {\r\n inlineMath: [['\$', '\$'], ['\\\\(', '\\\\)']],\r\n displayMath: [['\$\$', '\$\$'], ['\\\\[', '\\\\]']],\r\n },\r\n chtml: {\r\n fontURL: '" . plugin_dir_url( __FILE__ ) . "assets/fonts/woff-v2'\r\n }\r\n };\r\n ";
1061 // Enqueue the MathJax script
1062 // wp_enqueue_script( 'mathjax', plugin_dir_url(__FILE__) . 'assets/js/tex-chtml.js', array(), $chatbot_chatgpt_plugin_version, true );
1063 wp_enqueue_script(
1064 'mathjax',
1065 $chatbot_chatgpt_plugin_dir_url . 'assets/js/tex-mml-chtml.js',
1066 array(),
1067 $chatbot_chatgpt_plugin_version,
1068 true
1069 );
1070 // Add the inline script before MathJax script
1071 wp_add_inline_script( 'mathjax', $mathjax_config, 'before' );
1072 }
1073 }
1074
1075 add_action( 'wp_enqueue_scripts', 'enqueue_mathjax_with_custom_config' );
1076 // CORS - Cross Origin Resource Sharing - CAUTION: This allows all domains to access the end point - Ver 2.1.2
1077 // function allow_cross_domain_requests() {
1078 // header("Access-Control-Allow-Origin: *");
1079 // header("Access-Control-Allow-Methods: GET, POST, OPTIONS");
1080 // header("Access-Control-Allow-Headers: X-Requested-With");
1081 // }
1082 // add_action('init', 'allow_cross_domain_requests');
1083 // Settings and Deactivation Links - Ver - 1.5.0
1084 if ( !function_exists( 'enqueue_jquery_ui' ) ) {
1085 function enqueue_jquery_ui() {
1086 wp_enqueue_style( 'wp-jquery-ui-dialog' );
1087 wp_enqueue_script( 'jquery-ui-dialog' );
1088 }
1089
1090 add_action( 'admin_enqueue_scripts', 'enqueue_jquery_ui' );
1091 }
1092 // Schedule Cleanup of Expired Transients
1093 if ( !wp_next_scheduled( 'chatbot_chatgpt_cleanup_event' ) ) {
1094 wp_schedule_event( time(), 'daily', 'chatbot_chatgpt_cleanup_event' );
1095 }
1096 add_action( 'chatbot_chatgpt_cleanup_event', 'clean_specific_expired_transients' );
1097 // Schedule Conversation Log Cleanup - Ver 1.6.7
1098 if ( !wp_next_scheduled( 'chatbot_chatgpt_conversation_log_cleanup_event' ) ) {
1099 wp_schedule_event( time(), 'daily', 'chatbot_chatgpt_conversation_log_cleanup_event' );
1100 }
1101 add_action( 'chatbot_chatgpt_conversation_log_cleanup_event', 'chatbot_chatgpt_conversation_log_cleanup' );
1102 // Schedule the transcript file cleanup event if it's not already scheduled - Ver 1.9.9
1103 // Schedule the cleanup event if it's not already scheduled
1104 if ( !wp_next_scheduled( 'chatbot_chatgpt_cleanup_transcript_files' ) ) {
1105 wp_schedule_event( time(), 'hourly', 'chatbot_chatgpt_cleanup_transcript_files' );
1106 }
1107 // Deactivate old hooks - Ver 2.0.1
1108 if ( esc_attr( get_option( 'chatbot_chatgpt_cleanup_old_hooks' ) !== 'Completed' ) ) {
1109 // Deactivate old hooks - Ver 2.0.1
1110 wp_clear_scheduled_hook( 'chatbot_chatgpt_cleanup_transcripts' );
1111 // Then update the option
1112 update_option( 'chatbot_chatgpt_cleanup_old_hooks', 'Completed' );
1113 }
1114 // Schedule the audio file cleanup event if it's not already scheduled - Ver 1.9.9
1115 // Schedule the cleanup event if it's not already scheduled
1116 if ( !wp_next_scheduled( 'chatbot_chatgpt_cleanup_audio_files' ) ) {
1117 wp_schedule_event( time(), 'hourly', 'chatbot_chatgpt_cleanup_audio_files' );
1118 }
1119 // Schedule the upload file cleanup event if it's not already scheduled - Ver 1.9.9
1120 // Schedule the cleanup event if it's not already scheduled
1121 if ( !wp_next_scheduled( 'chatbot_chatgpt_cleanup_upload_files' ) ) {
1122 wp_schedule_event( time(), 'hourly', 'chatbot_chatgpt_cleanup_upload_files' );
1123 }
1124 // Schedule the download file cleanup event if it's not already scheduled - Ver 2.0.3
1125 // Schedule the cleanup event if it's not already scheduled
1126 if ( !wp_next_scheduled( 'chatbot_chatgpt_cleanup_download_files' ) ) {
1127 wp_schedule_event( time(), 'hourly', 'chatbot_chatgpt_cleanup_download_files' );
1128 }
1129 // Add the Opean AI Assistant table to the database - Ver 2.0.4
1130 // REMOVED Ver 2.2.7 and MOVED to the activation hook
1131 // create_chatbot_chatgpt_assistants_table();
1132 // Add the Azure Assistants table to the database - Ver 2.2.6
1133 // REMOVED Ver 2.2.7 and MOVED to the activation hook
1134 // create_chatbot_azure_assistants_table();
1135 // Message Queue Management Functions
1136 function chatbot_chatgpt_enqueue_message(
1137 $user_id,
1138 $page_id,
1139 $session_id,
1140 $assistant_id,
1141 $message,
1142 $client_message_id = null
1143 ) {
1144 $queue_key = 'chatbot_message_queue_' . wp_hash( $assistant_id . '|' . $user_id . '|' . $page_id . '|' . $session_id );
1145 $queue = get_transient( $queue_key );
1146 if ( !$queue ) {
1147 $queue = [];
1148 }
1149 $queue_item = [
1150 'message' => $message,
1151 'client_message_id' => ( $client_message_id ?: wp_generate_uuid4() ),
1152 'timestamp' => time(),
1153 'user_id' => $user_id,
1154 'page_id' => $page_id,
1155 'session_id' => $session_id,
1156 'assistant_id' => $assistant_id,
1157 ];
1158 $queue[] = $queue_item;
1159 set_transient( $queue_key, $queue, 3600 );
1160 // 1 hour expiry
1161 return $queue_item['client_message_id'];
1162 }
1163
1164 function chatbot_chatgpt_dequeue_message(
1165 $user_id,
1166 $page_id,
1167 $session_id,
1168 $assistant_id
1169 ) {
1170 $queue_key = 'chatbot_message_queue_' . wp_hash( $assistant_id . '|' . $user_id . '|' . $page_id . '|' . $session_id );
1171 $queue = get_transient( $queue_key );
1172 if ( !$queue || empty( $queue ) ) {
1173 return null;
1174 }
1175 $message = array_shift( $queue );
1176 if ( empty( $queue ) ) {
1177 delete_transient( $queue_key );
1178 } else {
1179 set_transient( $queue_key, $queue, 3600 );
1180 }
1181 return $message;
1182 }
1183
1184 function chatbot_chatgpt_get_queue_status(
1185 $user_id,
1186 $page_id,
1187 $session_id,
1188 $assistant_id
1189 ) {
1190 $queue_key = 'chatbot_message_queue_' . wp_hash( $assistant_id . '|' . $user_id . '|' . $page_id . '|' . $session_id );
1191 $queue = get_transient( $queue_key );
1192 return [
1193 'has_messages' => !empty( $queue ),
1194 'count' => ( $queue ? count( $queue ) : 0 ),
1195 'next_message' => ( $queue ? $queue[0] : null ),
1196 ];
1197 }
1198
1199 function chatbot_chatgpt_process_queue(
1200 $user_id,
1201 $page_id,
1202 $session_id,
1203 $assistant_id
1204 ) {
1205 // DIAG - Diagnostics - Ver 2.3.4
1206 $queue_status = chatbot_chatgpt_get_queue_status(
1207 $user_id,
1208 $page_id,
1209 $session_id,
1210 $assistant_id
1211 );
1212 // DIAG - Diagnostics - Ver 2.3.4
1213 if ( !$queue_status['has_messages'] ) {
1214 return false;
1215 }
1216 $message_data = chatbot_chatgpt_dequeue_message(
1217 $user_id,
1218 $page_id,
1219 $session_id,
1220 $assistant_id
1221 );
1222 if ( !$message_data ) {
1223 return false;
1224 }
1225 // Set conversation lock for the queued message
1226 $conv_lock = 'chatgpt_conv_lock_' . wp_hash( $assistant_id . '|' . $user_id . '|' . $page_id . '|' . $session_id );
1227 set_transient( $conv_lock, true, 60 );
1228 // DIAG - Diagnostics - Ver 2.3.4
1229 // Process the message using the existing logic
1230 $response = chatbot_chatgpt_process_queued_message( $message_data );
1231 // Clear conversation lock
1232 delete_transient( $conv_lock );
1233 // DIAG - Diagnostics - Ver 2.3.4
1234 // Recursively process the next message in queue
1235 chatbot_chatgpt_process_queue(
1236 $user_id,
1237 $page_id,
1238 $session_id,
1239 $assistant_id
1240 );
1241 return true;
1242 }
1243
1244 // AJAX handler to get queue status
1245 function chatbot_chatgpt_get_queue_status_ajax() {
1246 // Security: Verify nonce for CSRF protection
1247 if ( !isset( $_POST['chatbot_nonce'] ) || !wp_verify_nonce( $_POST['chatbot_nonce'], 'chatbot_queue_nonce' ) ) {
1248 wp_send_json_error( 'Security check failed. Please refresh the page and try again.', 403 );
1249 return;
1250 }
1251 $user_id = sanitize_text_field( $_POST['user_id'] );
1252 $page_id = sanitize_text_field( $_POST['page_id'] );
1253 $session_id = sanitize_text_field( $_POST['session_id'] );
1254 $assistant_id = sanitize_text_field( $_POST['assistant_id'] );
1255 if ( !$user_id || !$page_id || !$session_id || !$assistant_id ) {
1256 wp_send_json_error( 'Missing required parameters' );
1257 return;
1258 }
1259 $queue_status = chatbot_chatgpt_get_queue_status(
1260 $user_id,
1261 $page_id,
1262 $session_id,
1263 $assistant_id
1264 );
1265 wp_send_json_success( $queue_status );
1266 }
1267
1268 function chatbot_chatgpt_process_queued_message( $message_data ) {
1269 // This function processes a queued message using the same logic as the main handler
1270 // but without the AJAX response handling
1271 global $session_id;
1272 global $user_id;
1273 global $page_id;
1274 global $thread_id;
1275 global $assistant_id;
1276 global $chatbot_chatgpt_assistant_alias;
1277 global $kchat_settings;
1278 global $additional_instructions;
1279 global $model;
1280 global $voice;
1281 global $flow_data;
1282 $api_key = '';
1283 $message = $message_data['message'];
1284 $user_id = $message_data['user_id'];
1285 $page_id = $message_data['page_id'];
1286 $session_id = $message_data['session_id'];
1287 $assistant_id = $message_data['assistant_id'];
1288 $client_message_id = $message_data['client_message_id'];
1289 $chatbot_ai_platform_choice = esc_attr( get_option( 'chatbot_ai_platform_choice', 'OpenAI' ) );
1290 // Get API key and model based on platform choice
1291 switch ( $chatbot_ai_platform_choice ) {
1292 case 'OpenAI':
1293 $api_key = esc_attr( get_option( 'chatbot_chatgpt_api_key' ) );
1294 $api_key = chatbot_chatgpt_decrypt_api_key( $api_key );
1295 $model = esc_attr( get_option( 'chatbot_chatgpt_model_choice', 'gpt-4-1106-preview' ) );
1296 break;
1297 case 'Azure OpenAI':
1298 $api_key = esc_attr( get_option( 'chatbot_azure_api_key' ) );
1299 $api_key = chatbot_chatgpt_decrypt_api_key( $api_key );
1300 $model = esc_attr( get_option( 'chatbot_azure_model_choice', 'gpt-4-1106-preview' ) );
1301 break;
1302 case 'NVIDIA':
1303 $api_key = esc_attr( get_option( 'chatbot_nvidia_api_key' ) );
1304 $api_key = chatbot_chatgpt_decrypt_api_key( $api_key );
1305 $model = esc_attr( get_option( 'chatbot_nvidia_model_choice', 'nvidia/llama-3.1-nemotron-51b-instruct' ) );
1306 break;
1307 case 'Anthropic':
1308 $api_key = esc_attr( get_option( 'chatbot_anthropic_api_key' ) );
1309 $api_key = chatbot_chatgpt_decrypt_api_key( $api_key );
1310 $model = esc_attr( get_option( 'chatbot_anthropic_model_choice', 'claude-3-5-sonnet-latest' ) );
1311 break;
1312 case 'DeepSeek':
1313 $api_key = esc_attr( get_option( 'chatbot_deepseek_api_key' ) );
1314 $api_key = chatbot_chatgpt_decrypt_api_key( $api_key );
1315 $model = esc_attr( get_option( 'chatbot_deepseek_model_choice', 'deepseek-chat' ) );
1316 break;
1317 case 'Google':
1318 $api_key = esc_attr( get_option( 'chatbot_google_api_key' ) );
1319 $api_key = chatbot_chatgpt_decrypt_api_key( $api_key );
1320 $model = esc_attr( get_option( 'chatbot_google_model_choice', 'gemini-2.0-flash' ) );
1321 break;
1322 case 'Markov Chain':
1323 $api_key = esc_attr( get_option( 'chatbot_markov_chain_api_key', 'NOT REQUIRED' ) );
1324 $model = esc_attr( get_option( 'chatbot_markov_chain_model_choice', 'markov-chain-flask' ) );
1325 break;
1326 case 'Transformer':
1327 $api_key = esc_attr( get_option( 'chatbot_transformer_api_key', 'NOT REQUIRED' ) );
1328 $model = esc_attr( get_option( 'chatbot_transformer_model_choice', 'lexical-context-model' ) );
1329 break;
1330 case 'Local Server':
1331 $api_key = esc_attr( get_option( 'chatbot_local_api_key', 'NOT REQUIRED' ) );
1332 $api_key = chatbot_chatgpt_decrypt_api_key( $api_key );
1333 $model = esc_attr( get_option( 'chatbot_local_model_choice', 'llama3.2-3b-instruct' ) );
1334 break;
1335 case 'Mistral':
1336 $api_key = esc_attr( get_option( 'chatbot_mistral_api_key' ) );
1337 $api_key = chatbot_chatgpt_decrypt_api_key( $api_key );
1338 $model = esc_attr( get_option( 'chatbot_mistral_model_choice', 'mistral-small-latest' ) );
1339 break;
1340 default:
1341 $api_key = esc_attr( get_option( 'chatbot_chatgpt_api_key' ) );
1342 $api_key = chatbot_chatgpt_decrypt_api_key( $api_key );
1343 $model = esc_attr( get_option( 'chatbot_chatgpt_model_choice', 'gpt-3.5-turbo' ) );
1344 break;
1345 }
1346 // Retrieve settings from transients (same as main handler) - Ver 2.3.6
1347 $kchat_settings['chatbot_chatgpt_display_style'] = get_chatbot_chatgpt_transients(
1348 'display_style',
1349 $user_id,
1350 $page_id,
1351 $session_id
1352 );
1353 $kchat_settings['chatbot_chatgpt_assistant_alias'] = get_chatbot_chatgpt_transients(
1354 'assistant_alias',
1355 $user_id,
1356 $page_id,
1357 $session_id
1358 );
1359 $kchat_settings['assistant_id'] = get_chatbot_chatgpt_transients(
1360 'assistant_id',
1361 $user_id,
1362 $page_id,
1363 $session_id
1364 );
1365 $kchat_settings['thread_id'] = get_chatbot_chatgpt_transients(
1366 'thread_id',
1367 $user_id,
1368 $page_id,
1369 $session_id
1370 );
1371 $kchat_settings['chatbot_chatgpt_model'] = get_chatbot_chatgpt_transients(
1372 'model',
1373 $user_id,
1374 $page_id,
1375 $session_id
1376 );
1377 $kchat_settings['model'] = ( $kchat_settings['chatbot_chatgpt_model'] ?: $model );
1378 $kchat_settings['chatbot_chatgpt_voice_option'] = get_chatbot_chatgpt_transients(
1379 'voice',
1380 $user_id,
1381 $page_id,
1382 $session_id
1383 );
1384 $kchat_settings['additional_instructions'] = get_chatbot_chatgpt_transients(
1385 'additional_instructions',
1386 $user_id,
1387 $page_id,
1388 $session_id
1389 );
1390 $voice = $kchat_settings['chatbot_chatgpt_voice_option'];
1391 $model = ( $kchat_settings['model'] ?: $model );
1392 $additional_instructions = $kchat_settings['additional_instructions'];
1393 $chatbot_chatgpt_assistant_alias = $kchat_settings['chatbot_chatgpt_assistant_alias'];
1394 // Override assistant_id from transient if available - Ver 2.3.6
1395 if ( !empty( $kchat_settings['assistant_id'] ) ) {
1396 $assistant_id = $kchat_settings['assistant_id'];
1397 }
1398 // Get thread information
1399 $thread_id = get_chatbot_chatgpt_threads(
1400 $user_id,
1401 $session_id,
1402 $page_id,
1403 $assistant_id
1404 );
1405 // Log the message
1406 append_message_to_conversation_log(
1407 $session_id,
1408 $user_id,
1409 $page_id,
1410 'Visitor',
1411 $thread_id,
1412 $assistant_id,
1413 null,
1414 $message
1415 );
1416 // Determine whether to use assistant_id or regular ChatGPT API (same logic as main handler) - Ver 2.3.6
1417 // Which Assistant ID to use - Ver 1.7.2
1418 if ( $chatbot_chatgpt_assistant_alias == 'original' ) {
1419 $use_assistant_id = 'No';
1420 // DIAG - Diagnostics - Ver 2.3.6
1421 } elseif ( $chatbot_chatgpt_assistant_alias == 'primary' ) {
1422 $assistant_id = esc_attr( get_option( 'assistant_id' ) );
1423 $use_assistant_id = 'Yes';
1424 // DIAG - Diagnostics - Ver 2.3.6
1425 // Check if the GPT Assistant ID is blank, null, or "Please provide the GPT Assistant ID."
1426 if ( empty( $assistant_id ) || $assistant_id == "Please provide the Assistant Id." ) {
1427 // Primary assistant_id not set
1428 $chatbot_chatgpt_assistant_alias = 'original';
1429 $use_assistant_id = 'No';
1430 // DIAG - Diagnostics - Ver 2.3.6
1431 }
1432 } elseif ( $chatbot_chatgpt_assistant_alias == 'alternate' ) {
1433 $assistant_id = esc_attr( get_option( 'chatbot_chatgpt_assistant_id_alternate' ) );
1434 $use_assistant_id = 'Yes';
1435 // DIAG - Diagnostics - Ver 2.3.6
1436 // Check if the GPT Assistant ID is blank, null, or "Please provide the GPT Assistant ID."
1437 if ( empty( $assistant_id ) || $assistant_id == "Please provide the Assistant Id." ) {
1438 /// Alternate assistant_id not set
1439 $chatbot_chatgpt_assistant_alias = 'original';
1440 $use_assistant_id = 'No';
1441 // DIAG - Diagnostics - Ver 2.3.6
1442 }
1443 } elseif ( str_starts_with( $assistant_id, 'asst_' ) ) {
1444 $chatbot_chatgpt_assistant_alias = $assistant_id;
1445 // Belt & Suspenders
1446 $use_assistant_id = 'Yes';
1447 // DIAG - Diagnostics - Ver 2.3.6
1448 } elseif ( str_starts_with( $assistant_id, 'ag:' ) ) {
1449 $chatbot_chatgpt_assistant_alias = $assistant_id;
1450 // Belt & Suspenders
1451 $use_assistant_id = 'Yes';
1452 // DIAG - Diagnostics - Ver 2.3.6
1453 } elseif ( str_starts_with( $assistant_id, 'websearch' ) ) {
1454 $chatbot_chatgpt_assistant_alias = $assistant_id;
1455 // Belt & Suspenders
1456 $use_assistant_id = 'Yes';
1457 // DIAG - Diagnostics - Ver 2.3.6
1458 } else {
1459 // Reference GPT Assistant IDs directly - Ver 1.7.3
1460 // Check both $chatbot_chatgpt_assistant_alias and $assistant_id - Ver 2.3.6
1461 if ( !empty( $chatbot_chatgpt_assistant_alias ) && (str_starts_with( $chatbot_chatgpt_assistant_alias, 'asst_' ) || str_starts_with( $chatbot_chatgpt_assistant_alias, 'ag:' ) || str_starts_with( $chatbot_chatgpt_assistant_alias, 'websearch' )) ) {
1462 // DIAG - Diagnostics - Ver 2.3.6
1463 // Override the $assistant_id with the GPT Assistant ID
1464 $assistant_id = $chatbot_chatgpt_assistant_alias;
1465 $use_assistant_id = 'Yes';
1466 // DIAG - Diagnostics - Ver 2.3.6
1467 } elseif ( !empty( $assistant_id ) && (str_starts_with( $assistant_id, 'asst_' ) || str_starts_with( $assistant_id, 'ag:' ) || str_starts_with( $assistant_id, 'websearch' )) ) {
1468 // Check $assistant_id directly if $chatbot_chatgpt_assistant_alias is empty - Ver 2.3.6
1469 // DIAG - Diagnostics - Ver 2.3.6
1470 // Set the alias to match the assistant_id
1471 $chatbot_chatgpt_assistant_alias = $assistant_id;
1472 $use_assistant_id = 'Yes';
1473 // DIAG - Diagnostics - Ver 2.3.6
1474 } else {
1475 // DIAG - Diagnostics - Ver 2.3.6
1476 // Override the $use_assistant_id and set it to 'No'
1477 $use_assistant_id = 'No';
1478 // DIAG - Diagnostics - Ver 2.3.6
1479 }
1480 }
1481 // Process the message based on platform and use_assistant_id - Ver 2.3.6
1482 // DIAG - Diagnostics - Ver 2.3.6
1483 // Check if we should use assistant_id or regular API
1484 if ( $use_assistant_id == 'Yes' && $chatbot_ai_platform_choice == 'OpenAI' ) {
1485 // DIAG - Diagnostics - Ver 2.3.6
1486 $response = chatbot_chatgpt_custom_gpt_call_api(
1487 $api_key,
1488 $message,
1489 $assistant_id,
1490 $thread_id,
1491 $session_id,
1492 $user_id,
1493 $page_id,
1494 $client_message_id
1495 );
1496 } elseif ( $use_assistant_id == 'Yes' && $chatbot_ai_platform_choice == 'Azure OpenAI' ) {
1497 // DIAG - Diagnostics - Ver 2.3.6
1498 $response = chatbot_azure_custom_gpt_call_api(
1499 $api_key,
1500 $message,
1501 $assistant_id,
1502 $thread_id,
1503 $session_id,
1504 $user_id,
1505 $page_id,
1506 $client_message_id
1507 );
1508 } elseif ( $use_assistant_id == 'Yes' && $chatbot_ai_platform_choice == 'Mistral' ) {
1509 // DIAG - Diagnostics - Ver 2.3.6
1510 $response = chatbot_mistral_agent_call_api(
1511 $api_key,
1512 $message,
1513 $assistant_id,
1514 $thread_id,
1515 $session_id,
1516 $user_id,
1517 $page_id,
1518 $client_message_id
1519 );
1520 } else {
1521 // Use regular API calls (not assistant_id) - Ver 2.3.6
1522 switch ( $chatbot_ai_platform_choice ) {
1523 case 'OpenAI':
1524 // Determine which OpenAI API to call based on model
1525 if ( str_starts_with( $model, 'gpt-4o' ) ) {
1526 $response = chatbot_chatgpt_call_omni(
1527 $api_key,
1528 $message,
1529 $user_id,
1530 $page_id,
1531 $session_id,
1532 $assistant_id,
1533 $client_message_id
1534 );
1535 } elseif ( str_starts_with( $model, 'gpt' ) ) {
1536 $response = chatbot_chatgpt_call_api(
1537 $api_key,
1538 $message,
1539 $user_id,
1540 $page_id,
1541 $session_id,
1542 $assistant_id,
1543 $client_message_id
1544 );
1545 } elseif ( str_starts_with( $model, 'dall' ) ) {
1546 $response = chatbot_chatgpt_call_image_api(
1547 $api_key,
1548 $message,
1549 $user_id,
1550 $page_id,
1551 $session_id,
1552 $assistant_id,
1553 $client_message_id
1554 );
1555 } elseif ( str_starts_with( $model, 'tts' ) ) {
1556 $response = chatbot_chatgpt_call_tts_api(
1557 $api_key,
1558 $message,
1559 $voice,
1560 $user_id,
1561 $page_id,
1562 $session_id,
1563 $assistant_id,
1564 $client_message_id
1565 );
1566 } elseif ( str_starts_with( $model, 'whisper' ) ) {
1567 $response = chatbot_chatgpt_call_stt_api( $api_key, $message );
1568 } else {
1569 $response = chatbot_chatgpt_call_api(
1570 $api_key,
1571 $message,
1572 $user_id,
1573 $page_id,
1574 $session_id,
1575 $assistant_id,
1576 $client_message_id
1577 );
1578 }
1579 break;
1580 case 'Azure OpenAI':
1581 $response = chatbot_call_azure_openai_api( $api_key, $message );
1582 break;
1583 case 'NVIDIA':
1584 $response = chatbot_nvidia_call_api( $api_key, $message );
1585 break;
1586 case 'Anthropic':
1587 $response = chatbot_call_anthropic_api( $api_key, $message );
1588 break;
1589 case 'DeepSeek':
1590 $response = chatbot_call_deepseek_api( $api_key, $message );
1591 break;
1592 case 'Google':
1593 $response = chatbot_call_google_api( $api_key, $message );
1594 break;
1595 case 'Markov Chain':
1596 $response = chatbot_chatgpt_call_markov_chain_api( $message );
1597 break;
1598 case 'Transformer':
1599 $response = chatbot_chatgpt_call_transformer_model_api( $message );
1600 break;
1601 case 'Local Server':
1602 $response = chatbot_chatgpt_call_local_model_api( $message );
1603 break;
1604 case 'Mistral':
1605 // If use_assistant_id is No, use regular Mistral API
1606 $response = chatbot_chatgpt_call_mistral_api( $api_key, $message );
1607 break;
1608 default:
1609 $response = chatbot_chatgpt_call_api(
1610 $api_key,
1611 $message,
1612 $user_id,
1613 $page_id,
1614 $session_id,
1615 $assistant_id,
1616 $client_message_id
1617 );
1618 break;
1619 }
1620 }
1621 // Log the response
1622 append_message_to_conversation_log(
1623 $session_id,
1624 $user_id,
1625 $page_id,
1626 'Chatbot',
1627 $thread_id,
1628 $assistant_id,
1629 null,
1630 $response
1631 );
1632 return $response;
1633 }
1634
1635 function chatbot_chatgpt_process_single_message( $message_data ) {
1636 // This function contains the core message processing logic
1637 // It's extracted from the main send_message function
1638 global $session_id;
1639 global $user_id;
1640 global $page_id;
1641 global $thread_id;
1642 global $assistant_id;
1643 global $chatbot_chatgpt_assistant_alias;
1644 global $kchat_settings;
1645 global $additional_instructions;
1646 global $model;
1647 global $voice;
1648 global $flow_data;
1649 $api_key = '';
1650 $message = $message_data['message'];
1651 $user_id = $message_data['user_id'];
1652 $page_id = $message_data['page_id'];
1653 $session_id = $message_data['session_id'];
1654 $assistant_id = $message_data['assistant_id'];
1655 $client_message_id = $message_data['client_message_id'];
1656 $chatbot_ai_platform_choice = esc_attr( get_option( 'chatbot_ai_platform_choice', 'OpenAI' ) );
1657 // If your core pipeline expects a nonce in $_POST, we can safely provide one here:
1658 if ( !isset( $_POST['chatbot_nonce'] ) ) {
1659 $_POST['chatbot_nonce'] = wp_create_nonce( 'chatbot_message_nonce' );
1660 }
1661 // IMPORTANT: pass the full array, not just $message
1662 $response = chatbot_chatgpt_send_message( $message_data );
1663 return $response;
1664 }
1665
1666 // Handle Ajax requests
1667 function chatbot_chatgpt_send_message() {
1668 // Security: Verify nonce for CSRF protection
1669 $nonce_present = isset( $_POST['chatbot_nonce'] );
1670 $nonce_valid = false;
1671 if ( $nonce_present ) {
1672 $nonce_valid = wp_verify_nonce( $_POST['chatbot_nonce'], 'chatbot_message_nonce' );
1673 }
1674 if ( !$nonce_present || !$nonce_valid ) {
1675 // Log the security failure for debugging with more detail
1676 $nonce_status = ( !$nonce_present ? 'missing' : 'invalid' );
1677 $post_data_sanitized = array();
1678 foreach ( $_POST as $key => $value ) {
1679 // Sanitize POST data for logging (exclude sensitive data)
1680 if ( $key !== 'chatbot_nonce' ) {
1681 $post_data_sanitized[$key] = ( is_string( $value ) ? substr( $value, 0, 100 ) : $value );
1682 } else {
1683 $post_data_sanitized[$key] = ( $nonce_present ? ( strlen( $value ) > 0 ? '[present]' : '[empty]' ) : '[missing]' );
1684 }
1685 }
1686 prod_trace( 'ERROR', 'Chatbot Security Check Failed - Nonce ' . $nonce_status . '. POST data: ' . print_r( $post_data_sanitized, true ) );
1687 // Enhanced error response with nonce refresh suggestion
1688 wp_send_json_error( array(
1689 'message' => 'Security check failed. Please refresh the page and try again.',
1690 'code' => 'nonce_failed',
1691 'suggestion' => 'refresh_nonce',
1692 'nonce_status' => $nonce_status,
1693 ), 403 );
1694 return;
1695 }
1696 // Security: Get current user and verify authorization
1697 $current_user = wp_get_current_user();
1698 $current_user_id = $current_user->ID;
1699 // For anonymous users, we need to verify they own the session
1700 if ( $current_user_id === 0 ) {
1701 // Anonymous user - verify session ownership through session_id
1702 if ( !isset( $_POST['session_id'] ) ) {
1703 wp_send_json_error( 'Session ID required for anonymous users.', 403 );
1704 return;
1705 }
1706 $session_id = sanitize_text_field( $_POST['session_id'] );
1707 // Verify the session belongs to the current request
1708 if ( !verify_session_ownership( $session_id ) ) {
1709 // Log the session validation failure for debugging
1710 prod_trace( 'ERROR', 'Chatbot Session Validation Failed - Session ID: ' . $session_id . ', Length: ' . strlen( $session_id ) );
1711 wp_send_json_error( 'Unauthorized access to conversation.', 403 );
1712 return;
1713 }
1714 // For anonymous users, user_id should be 0 (session_id is used in transient key via get_chatbot_chatgpt_transients)
1715 $user_id = 0;
1716 // Rate limiting for unauthenticated users to prevent API abuse
1717 $client_ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown';
1718 $rate_limit_key = 'chatbot_rate_limit_' . (( function_exists( 'wp_fast_hash' ) ? wp_fast_hash( $client_ip ) : hash( 'sha256', $client_ip ) ));
1719 // Check rate limit (max 10 requests per minute for unauthenticated users)
1720 $current_count = ( get_transient( $rate_limit_key ) ?: 0 );
1721 if ( $current_count >= 10 ) {
1722 wp_send_json_error( 'Rate limit exceeded. Please wait before sending another message.', 429 );
1723 return;
1724 }
1725 // Increment rate limit counter
1726 set_transient( $rate_limit_key, $current_count + 1, 60 );
1727 // 60 seconds
1728 } else {
1729 // Logged-in user - use their actual user ID
1730 // Get session_id for logged-in users (needed for transient keys) - Ver 2.3.6
1731 if ( !isset( $_POST['session_id'] ) ) {
1732 $session_id = kognetiks_get_unique_id();
1733 } else {
1734 $session_id = sanitize_text_field( $_POST['session_id'] );
1735 }
1736 }
1737 // Global variables
1738 // Fixed Ver 2.3.6: Set global variables AFTER determining the correct values
1739 // This ensures the global $user_id is set correctly for logged-in users
1740 global $session_id;
1741 global $user_id;
1742 global $page_id;
1743 // Set the global $user_id to the correct value (don't let global declaration overwrite it)
1744 if ( $current_user_id === 0 ) {
1745 $user_id = 0;
1746 // Anonymous user
1747 } else {
1748 $user_id = $current_user_id;
1749 // Logged-in user - preserve their WordPress user ID
1750 }
1751 global $thread_id;
1752 global $assistant_id;
1753 global $chatbot_chatgpt_assistant_alias;
1754 global $kchat_settings;
1755 global $additional_instructions;
1756 global $model;
1757 global $voice;
1758 global $flow_data;
1759 $api_key = '';
1760 $chatbot_ai_platform_choice = esc_attr( get_option( 'chatbot_ai_platform_choice', 'OpenAI' ) );
1761 // DIAG - Diagnostics - Ver 2.2.1
1762 switch ( $chatbot_ai_platform_choice ) {
1763 case 'OpenAI':
1764 $api_key = esc_attr( get_option( 'chatbot_chatgpt_api_key' ) );
1765 // Decrypt the API key - Ver 2.2.6
1766 $api_key = chatbot_chatgpt_decrypt_api_key( $api_key );
1767 $model = esc_attr( get_option( 'chatbot_chatgpt_model_choice', 'gpt-4-1106-preview' ) );
1768 $kchat_settings['chatbot_chatgpt_model'] = $model;
1769 $kchat_settings['model'] = $model;
1770 // DIAG - Diagnostics - Ver 2.1.8
1771 break;
1772 case 'Azure OpenAI':
1773 $api_key = esc_attr( get_option( 'chatbot_azure_api_key' ) );
1774 // Decrypt the API key - Ver 2.2.6
1775 $api_key = chatbot_chatgpt_decrypt_api_key( $api_key );
1776 $model = esc_attr( get_option( 'chatbot_azure_model_choice', 'gpt-4-1106-preview' ) );
1777 $kchat_settings['chatbot_chatgpt_model'] = $model;
1778 $kchat_settings['model'] = $model;
1779 // DIAG - Diagnostics - Ver 2.2.6
1780 break;
1781 case 'NVIDIA':
1782 $api_key = esc_attr( get_option( 'chatbot_nvidia_api_key' ) );
1783 $model = esc_attr( get_option( 'chatbot_nvidia_model_choice', 'nvidia/llama-3.1-nemotron-51b-instruct' ) );
1784 // Decrypt the API key - Ver 2.2.6
1785 $api_key = chatbot_chatgpt_decrypt_api_key( $api_key );
1786 $kchat_settings['chatbot_chatgpt_model'] = $model;
1787 $kchat_settings['model'] = $model;
1788 // DIAG - Diagnostics - Ver 2.1.8
1789 break;
1790 case 'Anthropic':
1791 $api_key = esc_attr( get_option( 'chatbot_anthropic_api_key' ) );
1792 // Decrypt the API key - Ver 2.2.6
1793 $api_key = chatbot_chatgpt_decrypt_api_key( $api_key );
1794 $model = esc_attr( get_option( 'chatbot_anthropic_model_choice', 'claude-3-5-sonnet-latest' ) );
1795 $kchat_settings['chatbot_chatgpt_model'] = $model;
1796 $kchat_settings['model'] = $model;
1797 // DIAG - Diagnostics - Ver 2.1.8
1798 break;
1799 case 'DeepSeek':
1800 $api_key = esc_attr( get_option( 'chatbot_deepseek_api_key' ) );
1801 // Decrypt the API key - Ver 2.2.6
1802 $api_key = chatbot_chatgpt_decrypt_api_key( $api_key );
1803 $model = esc_attr( get_option( 'chatbot_deepseek_model_choice', 'deepseek-chat' ) );
1804 $kchat_settings['chatbot_chatgpt_model'] = $model;
1805 $kchat_settings['model'] = $model;
1806 // DIAG - Diagnostics - Ver 2.2.2
1807 break;
1808 case 'Google':
1809 $api_key = esc_attr( get_option( 'chatbot_google_api_key' ) );
1810 // Decrypt the API key - Ver 2.3.9
1811 $api_key = chatbot_chatgpt_decrypt_api_key( $api_key );
1812 $model = esc_attr( get_option( 'chatbot_google_model_choice', 'gemini-2.0-flash' ) );
1813 $kchat_settings['chatbot_chatgpt_model'] = $model;
1814 $kchat_settings['model'] = $model;
1815 // DIAG - Diagnostics - Ver 2.3.9
1816 break;
1817 case 'Markov Chain':
1818 $api_key = esc_attr( get_option( 'chatbot_markov_chain_api_key', 'NOT REQUIRED' ) );
1819 $model = esc_attr( get_option( 'chatbot_markov_chain_model_choice', 'markov-chain-flask' ) );
1820 $kchat_settings['chatbot_chatgpt_model'] = $model;
1821 $kchat_settings['model'] = $model;
1822 // DIAG - Diagnostics - Ver 2.1.8
1823 break;
1824 case 'Transformer':
1825 $api_key = esc_attr( get_option( 'chatbot_transformer_api_key', 'NOT REQUIRED' ) );
1826 $model = esc_attr( get_option( 'chatbot_transformer_model_choice', 'lexical-context-model' ) );
1827 $kchat_settings['chatbot_chatgpt_model'] = $model;
1828 $kchat_settings['model'] = $model;
1829 // DIAG - Diagnostics - Ver 2.1.8
1830 break;
1831 case 'Local Server':
1832 $api_key = esc_attr( get_option( 'chatbot_local_api_key', 'NOT REQUIRED' ) );
1833 // Decrypt the API key - Ver 2.2.6
1834 $api_key = chatbot_chatgpt_decrypt_api_key( $api_key );
1835 $model = esc_attr( get_option( 'chatbot_local_model_choice', 'llama3.2-3b-instruct' ) );
1836 $kchat_settings['chatbot_chatgpt_model'] = $model;
1837 $kchat_settings['model'] = $model;
1838 // DIAG - Diagnostics - Ver 2.2.6
1839 break;
1840 case 'Mistral':
1841 $api_key = esc_attr( get_option( 'chatbot_mistral_api_key' ) );
1842 // Decrypt the API key - Ver 2.2.6
1843 $api_key = chatbot_chatgpt_decrypt_api_key( $api_key );
1844 $model = esc_attr( get_option( 'chatbot_mistral_model_choice', 'mistral-small-latest' ) );
1845 $kchat_settings['chatbot_chatgpt_model'] = $model;
1846 $kchat_settings['model'] = $model;
1847 // DIAG - Diagnostics - Ver 2.2.2
1848 break;
1849 default:
1850 $api_key = esc_attr( get_option( 'chatbot_chatgpt_api_key' ) );
1851 // Decrypt the API key - Ver 2.2.6
1852 $api_key = chatbot_chatgpt_decrypt_api_key( $api_key );
1853 $model = esc_attr( get_option( 'chatbot_chatgpt_model_choice', 'gpt-3.5-turbo' ) );
1854 $kchat_settings['chatbot_chatgpt_model'] = $model;
1855 $kchat_settings['model'] = $model;
1856 // DIAG - Diagnostics - Ver 2.1.8
1857 break;
1858 }
1859 // DIAG - Diagnostics - Ver 2.1.8
1860 // Send only clean text via the API - Ver 2.3.7
1861 // Validate message exists in POST before sanitizing
1862 if ( !isset( $_POST['message'] ) || empty( $_POST['message'] ) ) {
1863 prod_trace( 'ERROR', 'Chatbot: Message is missing from POST data. POST keys: ' . implode( ', ', array_keys( $_POST ) ) );
1864 global $chatbot_chatgpt_fixed_literal_messages;
1865 $default_message = 'Error: Message is required. Please enter a message and try again.';
1866 $error_message = ( isset( $chatbot_chatgpt_fixed_literal_messages[15] ) ? $chatbot_chatgpt_fixed_literal_messages[15] : $default_message );
1867 wp_send_json_error( $error_message );
1868 return;
1869 }
1870 $message = sanitize_text_field( $_POST['message'] );
1871 // Additional validation - ensure message is not empty after sanitization
1872 if ( empty( trim( $message ) ) ) {
1873 prod_trace( 'ERROR', 'Chatbot: Message is empty after sanitization. Original POST message length: ' . strlen( $_POST['message'] ) );
1874 global $chatbot_chatgpt_fixed_literal_messages;
1875 $default_message = 'Error: Message cannot be empty. Please enter a message and try again.';
1876 $error_message = ( isset( $chatbot_chatgpt_fixed_literal_messages[15] ) ? $chatbot_chatgpt_fixed_literal_messages[15] : $default_message );
1877 wp_send_json_error( $error_message );
1878 return;
1879 }
1880 // Log the message being processed for debugging - Ver 2.3.7
1881 // DIAG - Diagnostics - Uncomment for debugging
1882 // prod_trace('NOTICE', 'Chatbot: Processing message - Length: ' . strlen($message) . ', First 50 chars: ' . substr($message, 0, 50));
1883 // Get client message ID if provided
1884 $client_message_id = ( isset( $_POST['client_message_id'] ) ? sanitize_text_field( $_POST['client_message_id'] ) : null );
1885 // Check for missing API key or message
1886 // if (!$api_key || !$message) {
1887 if ( !$message ) {
1888 // DIAG - Diagnostics
1889 global $chatbot_chatgpt_fixed_literal_messages;
1890 // Define a default fallback message
1891 $default_message = 'Error: Invalid API key or Message. Please check the plugin settings.';
1892 $error_message = ( isset( $chatbot_chatgpt_fixed_literal_messages[15] ) ? $chatbot_chatgpt_fixed_literal_messages[15] : $default_message );
1893 // Send error response
1894 wp_send_json_error( $error_message );
1895 return;
1896 }
1897 // Removed in Ver 1.8.6 - 2024 02 15
1898 // $thread_id = '';
1899 // $assistant_id = '';
1900 // $user_id = '';
1901 // $page_id = '';
1902 // Check the transient for the Assistant ID - Ver 1.7.2
1903 // Security: Get page_id from POST (this is safe as it's just identifying the page)
1904 $page_id = ( isset( $_POST['page_id'] ) ? sanitize_text_field( $_POST['page_id'] ) : '' );
1905 // For logged-in users, session_id should come from the secure session
1906 // For anonymous users, session_id was already validated above
1907 if ( $current_user_id === 0 ) {
1908 // session_id was already validated and set above for anonymous users
1909 // No need to overwrite it
1910 } else {
1911 // For logged-in users, get session_id from POST but validate it
1912 if ( isset( $_POST['session_id'] ) ) {
1913 $session_id = sanitize_text_field( $_POST['session_id'] );
1914 } else {
1915 // Fallback to generating a new session ID
1916 $session_id = kognetiks_get_unique_id();
1917 }
1918 }
1919 // Additional security: Verify the conversation belongs to this user
1920 if ( !verify_conversation_ownership( $user_id, $page_id ) ) {
1921 // Log the conversation ownership validation failure for debugging
1922 prod_trace( 'ERROR', 'Chatbot Conversation Ownership Validation Failed - User ID: ' . $user_id . ', Page ID: ' . $page_id );
1923 wp_send_json_error( 'Unauthorized access to conversation.', 403 );
1924 return;
1925 }
1926 // DIAG - Diagnostics - Ver 1.8.6
1927 $kchat_settings['chatbot_chatgpt_display_style'] = get_chatbot_chatgpt_transients(
1928 'display_style',
1929 $user_id,
1930 $page_id,
1931 $session_id
1932 );
1933 $kchat_settings['chatbot_chatgpt_assistant_alias'] = get_chatbot_chatgpt_transients(
1934 'assistant_alias',
1935 $user_id,
1936 $page_id,
1937 $session_id
1938 );
1939 $kchat_settings['assistant_id'] = get_chatbot_chatgpt_transients(
1940 'assistant_id',
1941 $user_id,
1942 $page_id,
1943 $session_id
1944 );
1945 $kchat_settings['thread_id'] = get_chatbot_chatgpt_transients(
1946 'thread_id',
1947 $user_id,
1948 $page_id,
1949 $session_id
1950 );
1951 $kchat_settings['chatbot_chatgpt_model'] = get_chatbot_chatgpt_transients(
1952 'model',
1953 $user_id,
1954 $page_id,
1955 $session_id
1956 );
1957 $kchat_settings['model'] = $kchat_settings['chatbot_chatgpt_model'];
1958 $kchat_settings['chatbot_chatgpt_voice_option'] = get_chatbot_chatgpt_transients(
1959 'voice',
1960 $user_id,
1961 $page_id,
1962 $session_id
1963 );
1964 $kchat_settings['additional_instructions'] = get_chatbot_chatgpt_transients(
1965 'additional_instructions',
1966 $user_id,
1967 $page_id,
1968 $session_id
1969 );
1970 $voice = $kchat_settings['chatbot_chatgpt_voice_option'];
1971 $model = $kchat_settings['chatbot_chatgpt_model'];
1972 // FIXME - TESTING - Ver 2.1.8
1973 $additional_instructions = $kchat_settings['additional_instructions'];
1974 $chatbot_chatgpt_assistant_alias = $kchat_settings['chatbot_chatgpt_assistant_alias'];
1975 // Get the thread information - Ver 2.0.7
1976 $thread_id = get_chatbot_chatgpt_threads(
1977 $user_id,
1978 $session_id,
1979 $page_id,
1980 $assistant_id
1981 );
1982 $kchat_settings['thread_id'] = $thread_id;
1983 // $kchat_settings = array_merge($kchat_settings, get_chatbot_chatgpt_threads($user_id, $page_id));
1984 $assistant_id = ( isset( $kchat_settings['assistant_id'] ) ? $kchat_settings['assistant_id'] : '' );
1985 $thread_Id = ( isset( $kchat_settings['thread_id'] ) ? $kchat_settings['thread_id'] : '' );
1986 $model = ( isset( $kchat_settings['chatbot_chatgpt_model'] ) ? $kchat_settings['chatbot_chatgpt_model'] : '' );
1987 // FIXME - TESTING - Ver 2.1.8
1988 $voice = ( isset( $kchat_settings['chatbot_chatgpt_voice_option'] ) ? $kchat_settings['chatbot_chatgpt_voice_option'] : '' );
1989 // Check if there's already a conversation lock (active processing)
1990 $conv_lock = 'chatgpt_conv_lock_' . wp_hash( $assistant_id . '|' . $user_id . '|' . $page_id . '|' . $session_id );
1991 $is_processing = get_transient( $conv_lock );
1992 // Debug logging for lock check
1993 // DIAG - Diagnostics - Ver 2.3.4
1994 // For visitors, add additional lock validation to prevent stuck locks
1995 if ( $is_processing && $current_user_id === 0 ) {
1996 // Check if the lock is older than 2 minutes (120 seconds) - likely stuck
1997 $lock_timeout_key = '_transient_timeout_' . $conv_lock;
1998 $lock_timeout = get_option( $lock_timeout_key );
1999 if ( $lock_timeout && time() - ($lock_timeout - 60) > 120 ) {
2000 // Lock is older than 2 minutes, clear it
2001 delete_transient( $conv_lock );
2002 $is_processing = false;
2003 // DIAG - Diagnostics - Ver 2.3.6
2004 }
2005 }
2006 if ( $is_processing ) {
2007 // If already processing, enqueue the message
2008 $enqueued_id = chatbot_chatgpt_enqueue_message(
2009 $user_id,
2010 $page_id,
2011 $session_id,
2012 $assistant_id,
2013 $message,
2014 $client_message_id
2015 );
2016 // Return queue status
2017 global $chatbot_chatgpt_fixed_literal_messages;
2018 $default_message = 'Message queued. Processing...';
2019 $queued_message = ( isset( $chatbot_chatgpt_fixed_literal_messages[20] ) ? $chatbot_chatgpt_fixed_literal_messages[20] : $default_message );
2020 wp_send_json_success( [
2021 'queued' => true,
2022 'client_message_id' => $enqueued_id,
2023 'message' => $queued_message,
2024 ] );
2025 }
2026 // Set conversation lock with shorter timeout for visitors to prevent stuck locks
2027 $lock_timeout = ( $current_user_id === 0 ? 30 : 60 );
2028 // 30 seconds for visitors, 60 for logged-in users
2029 set_transient( $conv_lock, true, $lock_timeout );
2030 // Debug logging for lock setting
2031 // DIAG - Diagnostics - Ver 2.3.4
2032 // DIAG - Diagnostics - Ver 1.8.6
2033 // DIAG - Diagnostics - Ver 2.0.9
2034 foreach ( $kchat_settings as $key => $value ) {
2035 }
2036 // Assistants
2037 // $chatbot_chatgpt_assistant_alias == 'original'; // Default
2038 // $chatbot_chatgpt_assistant_alias == 'primary';
2039 // $chatbot_chatgpt_assistant_alias == 'alternate';
2040 // $chatbot_chatgpt_assistant_alias == 'asst_xxxxxxxxxxxxxxxxxxxxxxxx'; // GPT Assistant Id
2041 // $chatbot_chatgpt_assistant_alias == 'ag:xxxxxxxxxxxxxxxxxxxxxxxx'; // MistralAgent Id
2042 // $chatbot_chatgpt_assistant_alias == 'websearch'; // Mistral Websearch Id
2043 // Which Assistant ID to use - Ver 1.7.2
2044 if ( $chatbot_chatgpt_assistant_alias == 'original' ) {
2045 // DIAG - Diagnostics - Ver 2.3.6
2046 // DIAG - Diagnostics - Ver 2.3.6
2047 $use_assistant_id = 'No';
2048 // DIAG - Diagnostics - Ver 2.0.5
2049 } elseif ( $chatbot_chatgpt_assistant_alias == 'primary' ) {
2050 // DIAG - Diagnostics - Ver 2.3.6
2051 $assistant_id = esc_attr( get_option( 'assistant_id' ) );
2052 // $additional_instructions = esc_attr(get_option('chatbot_chatgpt_assistant_instructions', '')); // REMOVED VER 2.0.9
2053 $use_assistant_id = 'Yes';
2054 // DIAG - Diagnostics - Ver 2.0.5
2055 // Check if the GPT Assistant ID is blank, null, or "Please provide the GPT Assistant ID."
2056 if ( empty( $assistant_id ) || $assistant_id == "Please provide the Assistant Id." ) {
2057 // Primary assistant_id not set
2058 $chatbot_chatgpt_assistant_alias = 'original';
2059 $use_assistant_id = 'No';
2060 // DIAG - Diagnostics - Ver 2.0.5
2061 }
2062 } elseif ( $chatbot_chatgpt_assistant_alias == 'alternate' ) {
2063 // DIAG - Diagnostics - Ver 2.3.6
2064 $assistant_id = esc_attr( get_option( 'chatbot_chatgpt_assistant_id_alternate' ) );
2065 // $additional_instructions = esc_attr(get_option('chatbot_chatgpt_assistant_instructions_alternate', '')); // REMOVED VER 2.0.9
2066 $use_assistant_id = 'Yes';
2067 // DIAG - Diagnostics - Ver 2.0.5
2068 // Check if the GPT Assistant ID is blank, null, or "Please provide the GPT Assistant ID."
2069 if ( empty( $assistant_id ) || $assistant_id == "Please provide the Assistant Id." ) {
2070 /// Alternate assistant_id not set
2071 $chatbot_chatgpt_assistant_alias = 'original';
2072 $use_assistant_id = 'No';
2073 // DIAG - Diagnostics - Ver 2.0.5
2074 }
2075 } elseif ( str_starts_with( $assistant_id, 'asst_' ) ) {
2076 // DIAG - Diagnostics - Ver 2.3.6
2077 $chatbot_chatgpt_assistant_alias = $assistant_id;
2078 // Belt & Suspenders
2079 $use_assistant_id = 'Yes';
2080 // DIAG - Diagnostics - Ver 2.0.5
2081 } elseif ( str_starts_with( $assistant_id, 'ag:' ) ) {
2082 // DIAG - Diagnostics - Ver 2.3.6
2083 $chatbot_chatgpt_assistant_alias = $assistant_id;
2084 // Belt & Suspenders
2085 $use_assistant_id = 'Yes';
2086 // DIAG - Diagnostics - Ver 2.0.5
2087 } elseif ( str_starts_with( $assistant_id, 'websearch' ) ) {
2088 // DIAG - Diagnostics - Ver 2.3.6
2089 $chatbot_chatgpt_assistant_alias = $assistant_id;
2090 // Belt & Suspenders
2091 $use_assistant_id = 'Yes';
2092 // DIAG - Diagnostics - Ver 3.2.1
2093 } else {
2094 // Reference GPT Assistant IDs directly - Ver 1.7.3
2095 // Check both $chatbot_chatgpt_assistant_alias and $assistant_id - Ver 2.3.6
2096 if ( !empty( $chatbot_chatgpt_assistant_alias ) && (str_starts_with( $chatbot_chatgpt_assistant_alias, 'asst_' ) || str_starts_with( $chatbot_chatgpt_assistant_alias, 'ag:' ) || str_starts_with( $chatbot_chatgpt_assistant_alias, 'websearch' )) ) {
2097 // DIAG - Diagnostics - 2.0.5
2098 // Override the $assistant_id with the GPT Assistant ID
2099 $assistant_id = $chatbot_chatgpt_assistant_alias;
2100 $use_assistant_id = 'Yes';
2101 // DIAG - Diagnostics - Ver 2.0.5
2102 } elseif ( !empty( $assistant_id ) && (str_starts_with( $assistant_id, 'asst_' ) || str_starts_with( $assistant_id, 'ag:' ) || str_starts_with( $assistant_id, 'websearch' )) ) {
2103 // Check $assistant_id directly if $chatbot_chatgpt_assistant_alias is empty - Ver 2.3.6
2104 // DIAG - Diagnostics - Ver 2.3.6
2105 // Set the alias to match the assistant_id
2106 $chatbot_chatgpt_assistant_alias = $assistant_id;
2107 $use_assistant_id = 'Yes';
2108 // DIAG - Diagnostics - Ver 2.3.6
2109 } else {
2110 // DIAG - Diagnostics - Ver 2.0.5
2111 // Override the $use_assistant_id and set it to 'No'
2112 $use_assistant_id = 'No';
2113 // DIAG - Diagnostics - Ver 1.8.1
2114 }
2115 }
2116 // Get any additional instructions - Ver 2.0.9
2117 $additional_instructions = get_chatbot_chatgpt_transients(
2118 'additional_instructions',
2119 $user_id,
2120 $page_id,
2121 $session_id
2122 );
2123 // Decide whether to use Flow, Assistant or Original ChatGPT
2124 // DIAG - Diagnostics - Ver 2.3.4
2125 if ( $model == 'flow' ) {
2126 // DIAG - Diagnostics - Ver 2.1.1.1
2127 // Reload the model - BELT & SUSPENDERS
2128 $kchat_settings['model'] = $model;
2129 // Get the step from the transient
2130 $kflow_step = get_chatbot_chatgpt_transients(
2131 'kflow_step',
2132 null,
2133 null,
2134 $session_id
2135 );
2136 if ( empty( $kflow_step ) ) {
2137 $kflow_step = 0;
2138 // FIXME - Set to 1 or to zero?
2139 }
2140 // $thread_id
2141 $thread_id = '[answer=' . $kflow_step + 1 . ']';
2142 // Add +1 to $kchat_settings['next_step']
2143 $kflow_step = $kflow_step + 1;
2144 // Set the next step
2145 set_chatbot_chatgpt_transients(
2146 'kflow_step',
2147 $kflow_step,
2148 null,
2149 null,
2150 $session_id
2151 );
2152 // DIAG - Diagnostics
2153 $thread_id = get_chatbot_chatgpt_threads(
2154 $user_id,
2155 $session_id,
2156 $page_id,
2157 $assistant_id
2158 );
2159 append_message_to_conversation_log(
2160 $session_id,
2161 $user_id,
2162 $page_id,
2163 'Visitor',
2164 $thread_id,
2165 $assistant_id,
2166 null,
2167 $message
2168 );
2169 // BELT & SUSPENDERS
2170 $thread_id = '';
2171 // Send message to ChatGPT API - Ver 1.6.7
2172 $response = chatbot_chatgpt_call_flow_api( $api_key, $message );
2173 wp_send_json_success( $response );
2174 } elseif ( $use_assistant_id == 'Yes' ) {
2175 // DIAG - Diagnostics - Ver 2.3.4
2176 // DIAG - Diagnostics - Ver 2.1.1.1
2177 // DIAG - Diagnostics
2178 $thread_id = get_chatbot_chatgpt_threads(
2179 $user_id,
2180 $session_id,
2181 $page_id,
2182 $assistant_id
2183 );
2184 append_message_to_conversation_log(
2185 $session_id,
2186 $user_id,
2187 $page_id,
2188 'Visitor',
2189 $thread_id,
2190 $assistant_id,
2191 null,
2192 $message
2193 );
2194 // DIAG - Diagnostics - Ver 2.0.9
2195 // Send message to Custom GPT API - Ver 1.6.7
2196 $chatbot_ai_platform_choice = esc_attr( get_option( 'chatbot_ai_platform_choice', 'OpenAI' ) );
2197 // Route based on chatbot_ai_platform_choice setting - Ver 2.3.6
2198 if ( $chatbot_ai_platform_choice == 'OpenAI' ) {
2199 // Send message to OpenAI Assitant API - Ver 1.6.7
2200 // DIAG - Diagnostics
2201 $response = chatbot_chatgpt_custom_gpt_call_api(
2202 $api_key,
2203 $message,
2204 $assistant_id,
2205 $thread_id,
2206 $session_id,
2207 $user_id,
2208 $page_id,
2209 $client_message_id
2210 );
2211 } elseif ( $chatbot_ai_platform_choice == 'Azure OpenAI' ) {
2212 // Send message to Azure Assistant API - Ver 2.2.6
2213 // DIAG - Diagnostics
2214 $response = chatbot_azure_custom_gpt_call_api(
2215 $api_key,
2216 $message,
2217 $assistant_id,
2218 $thread_id,
2219 $session_id,
2220 $user_id,
2221 $page_id,
2222 $client_message_id
2223 );
2224 } elseif ( $chatbot_ai_platform_choice == 'Mistral' ) {
2225 // Send message to Mistral Assistant API - Ver 2.2.6
2226 // DIAG - Diagnostics
2227 $response = chatbot_mistral_agent_call_api(
2228 $api_key,
2229 $message,
2230 $assistant_id,
2231 $thread_id,
2232 $session_id,
2233 $user_id,
2234 $page_id,
2235 $client_message_id
2236 );
2237 } else {
2238 return 'ERROR: Invalid AI Platform';
2239 }
2240 // Replace " ." at the end of $response with "."
2241 $response = str_replace( " .", ".", $response );
2242 // Use TF-IDF to enhance response
2243 $chatbot_chatgpt_suppress_learnings = esc_attr( get_option( 'chatbot_chatgpt_suppress_learnings', 'Random' ) );
2244 if ( $chatbot_chatgpt_suppress_learnings != 'None' ) {
2245 $response = $response . '<br><br>' . chatbot_chatgpt_enhance_with_tfidf( $message );
2246 }
2247 // DIAG - Diagnostics
2248 $thread_id = get_chatbot_chatgpt_threads(
2249 $user_id,
2250 $session_id,
2251 $page_id,
2252 $assistant_id
2253 );
2254 append_message_to_conversation_log(
2255 $session_id,
2256 $user_id,
2257 $page_id,
2258 'Chatbot',
2259 $thread_id,
2260 $assistant_id,
2261 null,
2262 $response
2263 );
2264 // Clean (erase) the output buffer - Ver 1.6.8
2265 // Check if output buffering is active before attempting to clean it
2266 if ( ob_get_level() > 0 ) {
2267 ob_clean();
2268 // DIAG - Diagnostics
2269 } else {
2270 // Optionally start output buffering if needed for your application
2271 // ob_start();
2272 // DIAG - Diagnostics
2273 }
2274 if ( str_starts_with( $response, 'Error:' ) || str_starts_with( $response, 'Failed:' ) ) {
2275 global $chatbot_chatgpt_fixed_literal_messages;
2276 // Define a default fallback message
2277 $default_message = 'Oops! Something went wrong on our end. Please try again later!';
2278 $error_message = ( isset( $chatbot_chatgpt_fixed_literal_messages[0] ) ? $chatbot_chatgpt_fixed_literal_messages[0] : $default_message );
2279 // Send error response
2280 wp_send_json_error( $error_message );
2281 } else {
2282 // Process response for links and images
2283 $response = chatbot_chatgpt_check_for_links_and_images( $response );
2284 // Append any extra message if configured
2285 $extra_message = esc_attr( get_option( 'chatbot_chatgpt_extra_message', '' ) );
2286 $response = chatbot_chatgpt_append_extra_message( $response, $extra_message );
2287 // Clear conversation lock and process queue BEFORE sending response
2288 delete_transient( $conv_lock );
2289 // DIAG - Diagnostics - Ver 2.3.4
2290 chatbot_chatgpt_process_queue(
2291 $user_id,
2292 $page_id,
2293 $session_id,
2294 $assistant_id
2295 );
2296 // Send success response
2297 wp_send_json_success( $response );
2298 }
2299 } else {
2300 // DIAG - Diagnostics - Ver 2.3.4
2301 // Belt & Suspenders - Ver 2.1.5.1
2302 if ( !isset( $kchat_settings['model'] ) ) {
2303 $kchat_settings['model'] = $model;
2304 }
2305 // FIXME - TESTING - Ver 2.1.8
2306 // if (str_starts_with($model,'dall')) {
2307 // } else {
2308 // }
2309 $thread_id = get_chatbot_chatgpt_threads(
2310 $user_id,
2311 $session_id,
2312 $page_id,
2313 $assistant_id
2314 );
2315 append_message_to_conversation_log(
2316 $session_id,
2317 $user_id,
2318 $page_id,
2319 'Visitor',
2320 $thread_id,
2321 $assistant_id,
2322 null,
2323 $message
2324 );
2325 // If $model starts with 'gpt' then the chatbot_chatgpt_call_api or 'dall' then chatbot_chatgpt_call_image_api
2326 // TRY NOT TO FETCH MODEL AGAIN
2327 // $model = esc_attr(get_option('chatbot_chatgpt_model_choice', 'gpt-3.5-turbo'));
2328 $model = ( isset( $kchat_settings['model'] ) ? $kchat_settings['model'] : null );
2329 $voice = ( isset( $kchat_settings['voice'] ) ? $kchat_settings['voice'] : null );
2330 // FIXME - TESTING - Ver 2.1.8
2331 $chatbot_ai_platform_choice = esc_attr( get_option( 'chatbot_ai_platform_choice', 'OpenAI' ) );
2332 // DIAG - Diagnostics - Ver 2.2.6
2333 switch ( $chatbot_ai_platform_choice ) {
2334 case 'OpenAI':
2335 switch ( $model ) {
2336 case str_starts_with( $model, 'gpt-4o' ):
2337 // The string 'gpt-4o' is found in $model
2338 // Reload the model - BELT & SUSPENDERS
2339 $kchat_settings['model'] = $model;
2340 // DIAG - Diagnostics - Ver 2.1.8
2341 // Send message to ChatGPT API - Ver 1.6.7
2342 $response = chatbot_chatgpt_call_omni(
2343 $api_key,
2344 $message,
2345 $user_id,
2346 $page_id,
2347 $session_id,
2348 $assistant_id,
2349 $client_message_id
2350 );
2351 break;
2352 case str_starts_with( $model, 'gpt' ):
2353 // Reload the model - BELT & SUSPENDERS
2354 $kchat_settings['model'] = $model;
2355 // DIAG - Diagnostics - Ver 2.1.8
2356 // Send message to ChatGPT API - Ver 1.6.7
2357 $response = chatbot_chatgpt_call_api(
2358 $api_key,
2359 $message,
2360 $user_id,
2361 $page_id,
2362 $session_id,
2363 $assistant_id,
2364 $client_message_id
2365 );
2366 break;
2367 case str_starts_with( $model, 'dall' ):
2368 // Reload the model - BELT & SUSPENDERS
2369 $kchat_settings['model'] = $model;
2370 // DIAG - Diagnostics - Ver 2.1.8
2371 // Send message to Image API - Ver 1.9.4
2372 $response = chatbot_chatgpt_call_image_api(
2373 $api_key,
2374 $message,
2375 $user_id,
2376 $page_id,
2377 $session_id,
2378 $assistant_id,
2379 $client_message_id
2380 );
2381 break;
2382 case str_starts_with( $model, 'tts' ):
2383 // Reload the model - BELT & SUSPENDERS
2384 $kchat_settings['model'] = $model;
2385 $kchat_settings['voice'] = $voice;
2386 // DIAG - Diagnostics - Ver 2.1.8
2387 // Send message to TTS API - Text-to-speech - Ver 1.9.5
2388 $response = chatbot_chatgpt_call_tts_api(
2389 $api_key,
2390 $message,
2391 $voice,
2392 $user_id,
2393 $page_id,
2394 $session_id,
2395 $assistant_id,
2396 $client_message_id
2397 );
2398 break;
2399 case str_starts_with( $model, 'whisper' ):
2400 // Reload the model - BELT & SUSPENDERS
2401 $kchat_settings['model'] = $model;
2402 // DIAG - Diagnostics - Ver 2.1.8
2403 // Send message to STT API - Speech-to-text - Ver 1.9.6
2404 $response = chatbot_chatgpt_call_stt_api( $api_key, $message );
2405 break;
2406 }
2407 break;
2408 case 'Azure OpenAI':
2409 $kchat_settings['model'] = $model;
2410 // DIAG - Diagnostics - Ver 2.2.6
2411 // Send message to Azure OpenAI API - Ver 2.2.6
2412 $response = chatbot_call_azure_openai_api( $api_key, $message );
2413 break;
2414 case 'NVIDIA':
2415 $kchat_settings['model'] = $model;
2416 // DIAG - Diagnostics - Ver 2.1.8
2417 // Send message to NVIDIA API - Ver 2.1.8
2418 $response = chatbot_nvidia_call_api( $api_key, $message );
2419 break;
2420 case 'Anthropic':
2421 $kchat_settings['model'] = $model;
2422 // DIAG - Diagnostics - Ver 2.1.8
2423 // Send message to Claude API - Ver 2.1.8
2424 $response = chatbot_call_anthropic_api( $api_key, $message );
2425 break;
2426 case 'DeepSeek':
2427 $kchat_settings['model'] = $model;
2428 // DIAG - Diagnostics - Ver 2.2.2
2429 // Send message to DeepSeek API - Ver 2.2.2
2430 $response = chatbot_call_deepseek_api( $api_key, $message );
2431 break;
2432 case 'Google':
2433 $kchat_settings['model'] = $model;
2434 // DIAG - Diagnostics - Ver 2.3.9
2435 // Send message to Google API - Ver 2.3.9
2436 $response = chatbot_call_google_api( $api_key, $message );
2437 break;
2438 case 'Mistral':
2439 $kchat_settings['model'] = $model;
2440 // DIAG - Diagnostics - Ver 2.3.0
2441 // Send message to Mistral API - Ver 2.3.0
2442 $response = chatbot_chatgpt_call_mistral_api( $api_key, $message );
2443 break;
2444 case 'Markov Chain':
2445 $kchat_settings['model'] = $model;
2446 // DIAG - Diagnostics - Ver 2.1.8
2447 // Send message to Markov API - Ver 1.9.7
2448 $response = chatbot_chatgpt_call_markov_chain_api( $message );
2449 break;
2450 case 'Transformer':
2451 $kchat_settings['model'] = $model;
2452 // DIAG - Diagnostics - Ver 2.2.0
2453 // Send message to Transformer Model API - Ver 2.2.0
2454 $response = chatbot_chatgpt_call_transformer_model_api( $message );
2455 break;
2456 case 'Local Server':
2457 $kchat_settings['model'] = $model;
2458 // DIAG - Diagnostics - Ver 2.2.6
2459 // Send message to Local Model API - Ver 2.2.6
2460 $response = chatbot_chatgpt_call_local_model_api( $message );
2461 break;
2462 default:
2463 $kchat_settings['model'] = $model;
2464 // DIAG - Diagnostics - Ver 2.2.6
2465 // Send message to ChatGPT API - Ver 1.6.7
2466 $response = chatbot_chatgpt_call_api( $api_key, $message );
2467 }
2468 // DIAG - Diagnostics
2469 // Defensive programming - Ver 2.2.9
2470 if ( is_array( $response ) ) {
2471 if ( isset( $response['response'] ) ) {
2472 // Likely nested from a mistake — pull the actual content out
2473 $response = $response['response'];
2474 } else {
2475 // Fallback: flatten it all into a string just to be safe
2476 $response = print_r( $response, true );
2477 }
2478 }
2479 // Use TF-IDF to enhance response
2480 $chatbot_chatgpt_suppress_learnings = esc_attr( get_option( 'chatbot_chatgpt_suppress_learnings', 'Random' ) );
2481 if ( $chatbot_chatgpt_suppress_learnings != 'None' ) {
2482 $response = $response . '<br><br>' . chatbot_chatgpt_enhance_with_tfidf( $message );
2483 }
2484 // DIAG - Diagnostics
2485 // DIAG - Diagnostics
2486 $thread_id = get_chatbot_chatgpt_threads(
2487 $user_id,
2488 $session_id,
2489 $page_id,
2490 $assistant_id
2491 );
2492 append_message_to_conversation_log(
2493 $session_id,
2494 $user_id,
2495 $page_id,
2496 'Chatbot',
2497 $thread_id,
2498 $assistant_id,
2499 null,
2500 $response
2501 );
2502 // DIAG - Diagnostics
2503 $response = chatbot_chatgpt_check_for_links_and_images( $response );
2504 // DIAG - Diagnostics - Ver 2.0.5
2505 // FIXME - Append extra message - Ver 2.1.1.1.1
2506 // Danger Will Robinson! Danger!
2507 $extra_message = esc_attr( get_option( 'chatbot_chatgpt_extra_message', '' ) );
2508 $response = chatbot_chatgpt_append_extra_message( $response, $extra_message );
2509 // DIAG - Diagnostics - Ver 2.1.8
2510 // Clear conversation lock and process queue BEFORE sending response
2511 delete_transient( $conv_lock );
2512 // DIAG - Diagnostics - Ver 2.3.4
2513 chatbot_chatgpt_process_queue(
2514 $user_id,
2515 $page_id,
2516 $session_id,
2517 $assistant_id
2518 );
2519 // Return response
2520 wp_send_json_success( $response );
2521 }
2522 // DIAG - Diagnostics
2523 global $chatbot_chatgpt_fixed_literal_messages;
2524 // Define a default fallback message
2525 $default_message = 'Oops! I fell through the cracks!';
2526 $error_message = ( isset( $chatbot_chatgpt_fixed_literal_messages[1] ) ? $chatbot_chatgpt_fixed_literal_messages[1] : $default_message );
2527 // Send error response
2528 wp_send_json_error( $error_message );
2529 // Clear conversation lock on error
2530 delete_transient( $conv_lock );
2531 }
2532
2533 // Handle nonce refresh requests - Ver 2.3.6
2534 function chatbot_chatgpt_refresh_nonce() {
2535 // Generate fresh nonces
2536 $nonces = array(
2537 'chatbot_message_nonce' => wp_create_nonce( 'chatbot_message_nonce' ),
2538 'chatbot_upload_nonce' => wp_create_nonce( 'chatbot_upload_nonce' ),
2539 'chatbot_erase_nonce' => wp_create_nonce( 'chatbot_erase_nonce' ),
2540 'chatbot_unlock_nonce' => wp_create_nonce( 'chatbot_unlock_nonce' ),
2541 'chatbot_reset_nonce' => wp_create_nonce( 'chatbot_reset_nonce' ),
2542 'chatbot_queue_nonce' => wp_create_nonce( 'chatbot_queue_nonce' ),
2543 'chatbot_tts_nonce' => wp_create_nonce( 'chatbot_tts_nonce' ),
2544 'chatbot_transcript_nonce' => wp_create_nonce( 'chatbot_transcript_nonce' ),
2545 );
2546 wp_send_json_success( $nonces );
2547 }
2548
2549 // Function to clear stuck visitor locks - Ver 2.3.6
2550 function chatbot_chatgpt_clear_stuck_visitor_locks() {
2551 global $wpdb;
2552 // Only run for visitors (not logged in users)
2553 if ( is_user_logged_in() ) {
2554 return;
2555 }
2556 // Clear locks older than 2 minutes
2557 $expired_time = time() - 120;
2558 // 2 minutes ago
2559 $lock_patterns = ['_transient_chatgpt_conv_lock_%', '_transient_timeout_chatgpt_conv_lock_%'];
2560 foreach ( $lock_patterns as $pattern ) {
2561 $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s AND option_value < %d", $pattern, $expired_time ) );
2562 }
2563 }
2564
2565 // Hook to clear stuck locks on init for visitors
2566 add_action( 'init', 'chatbot_chatgpt_clear_stuck_visitor_locks', 5 );
2567 // Add admin menu for visitor lock clearing tool - Ver 2.3.6
2568 function chatbot_chatgpt_add_visitor_lock_tool_menu() {
2569 add_submenu_page(
2570 'chatbot-chatgpt',
2571 'Clear Visitor Locks',
2572 'Clear Visitor Locks',
2573 'manage_options',
2574 'chatbot-clear-visitor-locks',
2575 'chatbot_chatgpt_visitor_lock_tool_page'
2576 );
2577 }
2578
2579 add_action( 'admin_menu', 'chatbot_chatgpt_add_visitor_lock_tool_menu' );
2580 // Admin page for visitor lock clearing tool
2581 function chatbot_chatgpt_visitor_lock_tool_page() {
2582 if ( isset( $_POST['clear_locks'] ) && wp_verify_nonce( $_POST['_wpnonce'], 'clear_visitor_locks' ) ) {
2583 chatbot_chatgpt_clear_stuck_visitor_locks();
2584 echo '<div class="notice notice-success"><p>Visitor locks cleared successfully!</p></div>';
2585 }
2586 echo '<div class="wrap">';
2587 echo '<h1>Clear Visitor Locks</h1>';
2588 echo '<p>This tool clears stuck conversation locks that may be preventing visitors from using the chatbot.</p>';
2589 echo '<p><strong>Use this if visitors are getting "system is busy processing requests" messages.</strong></p>';
2590 echo '<form method="post">';
2591 wp_nonce_field( 'clear_visitor_locks' );
2592 echo '<p><input type="submit" name="clear_locks" class="button-primary" value="Clear All Visitor Locks" onclick="return confirm(\'Are you sure you want to clear all visitor locks?\')"></p>';
2593 echo '</form>';
2594 echo '</div>';
2595 }
2596
2597 // Add action to send messages - Ver 1.0.0
2598 add_action( 'wp_ajax_chatbot_chatgpt_send_message', 'chatbot_chatgpt_send_message' );
2599 add_action( 'wp_ajax_nopriv_chatbot_chatgpt_send_message', 'chatbot_chatgpt_send_message' );
2600 // Add action to refresh nonce - Ver 2.3.6
2601 add_action( 'wp_ajax_chatbot_chatgpt_refresh_nonce', 'chatbot_chatgpt_refresh_nonce' );
2602 add_action( 'wp_ajax_nopriv_chatbot_chatgpt_refresh_nonce', 'chatbot_chatgpt_refresh_nonce' );
2603 // Add action to get queue status
2604 add_action( 'wp_ajax_chatbot_chatgpt_get_queue_status', 'chatbot_chatgpt_get_queue_status_ajax' );
2605 add_action( 'wp_ajax_nopriv_chatbot_chatgpt_get_queue_status', 'chatbot_chatgpt_get_queue_status_ajax' );
2606 // Add action to upload files - Ver 1.7.6 (Security: Authentication required)
2607 add_action( 'wp_ajax_chatbot_chatgpt_upload_files', 'chatbot_chatgpt_upload_files' );
2608 // Add action to upload mp3 files - Ver 1.7.6 (Security: Authentication required)
2609 add_action( 'wp_ajax_chatbot_chatgpt_upload_mp3', 'chatbot_chatgpt_upload_mp3' );
2610 // Add action to erase conversation - Ver 1.8.6 (Security: Authentication required)
2611 add_action( 'wp_ajax_chatbot_chatgpt_erase_conversation', 'chatbot_chatgpt_erase_conversation_handler' );
2612 add_action( 'wp_ajax_nopriv_chatbot_chatgpt_erase_conversation', 'chatbot_chatgpt_erase_conversation_handler' );
2613 // Add action to unlock conversation - Ver 2.3.0 (Security: Authentication required)
2614 add_action( 'wp_ajax_chatbot_chatgpt_unlock_conversation', 'chatbot_chatgpt_unlock_conversation_handler' );
2615 // Add action to reset all locks (Security: Authentication required)
2616 add_action( 'wp_ajax_chatbot_chatgpt_reset_all_locks', 'chatbot_chatgpt_reset_all_locks_handler' );
2617 // Add action to reset cache and locks (Security: Authentication required) - Ver 2.3.6
2618 add_action( 'wp_ajax_chatbot_chatgpt_reset_cache_locks', 'chatbot_chatgpt_reset_cache_locks_handler' );
2619 // Add action for text-to-speech (Security: Authentication required)
2620 add_action( 'wp_ajax_chatbot_chatgpt_read_aloud', 'chatbot_chatgpt_read_aloud' );
2621 // Add action for transcript download (Security: Authentication required)
2622 add_action( 'wp_ajax_chatbot_chatgpt_download_transcript', 'chatbot_chatgpt_download_transcript' );
2623 // Settings and Deactivation - Ver 1.5.0
2624 add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), 'chatbot_chatgpt_plugin_action_links' );
2625 // Unlock conversation handler - Ver 2.3.0
2626 function chatbot_chatgpt_unlock_conversation_handler() {
2627 // Security: Check if user has permission to manage options (admin capability)
2628 if ( !current_user_can( 'manage_options' ) ) {
2629 wp_send_json_error( 'Insufficient permissions to unlock conversation.', 403 );
2630 return;
2631 }
2632 // Security: Verify nonce for CSRF protection
2633 if ( !isset( $_POST['chatbot_nonce'] ) || !wp_verify_nonce( $_POST['chatbot_nonce'], 'chatbot_unlock_nonce' ) ) {
2634 wp_send_json_error( 'Security check failed. Please refresh the page and try again.', 403 );
2635 return;
2636 }
2637 // Get parameters from POST
2638 $user_id = ( isset( $_POST['user_id'] ) ? sanitize_text_field( $_POST['user_id'] ) : '' );
2639 $page_id = ( isset( $_POST['page_id'] ) ? sanitize_text_field( $_POST['page_id'] ) : '' );
2640 $session_id = ( isset( $_POST['session_id'] ) ? sanitize_text_field( $_POST['session_id'] ) : '' );
2641 $assistant_id = ( isset( $_POST['assistant_id'] ) ? sanitize_text_field( $_POST['assistant_id'] ) : '' );
2642 if ( $user_id && $page_id && $session_id && $assistant_id ) {
2643 // Clear the conversation lock
2644 $conv_lock = 'chatgpt_conv_lock_' . wp_hash( $assistant_id . '|' . $user_id . '|' . $page_id . '|' . $session_id );
2645 $lock_exists = get_transient( $conv_lock );
2646 $deleted_lock = delete_transient( $conv_lock );
2647 // Clear the message queue
2648 $queue_key = 'chatbot_message_queue_' . wp_hash( $assistant_id . '|' . $user_id . '|' . $page_id . '|' . $session_id );
2649 $queue_exists = get_transient( $queue_key );
2650 $deleted_queue = delete_transient( $queue_key );
2651 // DIAG - Diagnostics - Ver 2.3.4
2652 // Try to clear all possible lock variations
2653 $possible_locks = [
2654 'chatgpt_conv_lock_' . wp_hash( $assistant_id . '|' . $user_id . '|' . $page_id . '|' . $session_id ),
2655 'chatgpt_conv_lock_' . wp_hash( $user_id . '|' . $page_id . '|' . $session_id ),
2656 'chatgpt_conv_lock_' . wp_hash( $session_id ),
2657 'chatgpt_conv_lock_' . $session_id,
2658 'chatgpt_conv_lock_' . $user_id . '_' . $page_id . '_' . $session_id,
2659 // Additional variations for visitor locks
2660 'chatgpt_conv_lock_' . wp_hash( $assistant_id . '|' . $session_id . '|' . $page_id ),
2661 'chatgpt_conv_lock_' . wp_hash( $session_id . '|' . $page_id ),
2662 ];
2663 foreach ( $possible_locks as $lock_key ) {
2664 if ( get_transient( $lock_key ) ) {
2665 delete_transient( $lock_key );
2666 // DIAG - Diagnostics - Ver 2.3.4
2667 }
2668 }
2669 wp_send_json_success( 'Conversation unlocked' );
2670 } else {
2671 // DIAG - Diagnostics - Ver 2.3.4
2672 wp_send_json_error( 'Missing parameters' );
2673 }
2674 }
2675
2676 // Global lock reset handler - Ver 2.3.0
2677 function chatbot_chatgpt_reset_all_locks_handler() {
2678 // Security: Check if user has permission to manage options (admin capability)
2679 if ( !current_user_can( 'manage_options' ) ) {
2680 wp_send_json_error( 'Insufficient permissions to reset locks.', 403 );
2681 return;
2682 }
2683 // Security: Verify nonce for CSRF protection
2684 if ( !isset( $_POST['chatbot_nonce'] ) || !wp_verify_nonce( $_POST['chatbot_nonce'], 'chatbot_reset_nonce' ) ) {
2685 wp_send_json_error( 'Security check failed. Please refresh the page and try again.', 403 );
2686 return;
2687 }
2688 // Get parameters from POST
2689 $user_id = ( isset( $_POST['user_id'] ) ? sanitize_text_field( $_POST['user_id'] ) : '' );
2690 $page_id = ( isset( $_POST['page_id'] ) ? sanitize_text_field( $_POST['page_id'] ) : '' );
2691 $session_id = ( isset( $_POST['session_id'] ) ? sanitize_text_field( $_POST['session_id'] ) : '' );
2692 $assistant_id = ( isset( $_POST['assistant_id'] ) ? sanitize_text_field( $_POST['assistant_id'] ) : '' );
2693 $cleared_count = 0;
2694 if ( $user_id && $page_id && $session_id && $assistant_id ) {
2695 // Clear all possible lock variations for this conversation
2696 $possible_locks = [
2697 'chatgpt_conv_lock_' . wp_hash( $assistant_id . '|' . $user_id . '|' . $page_id . '|' . $session_id ),
2698 'chatgpt_conv_lock_' . wp_hash( $user_id . '|' . $page_id . '|' . $session_id ),
2699 'chatgpt_conv_lock_' . wp_hash( $session_id ),
2700 'chatgpt_conv_lock_' . $session_id,
2701 'chatgpt_conv_lock_' . $user_id . '_' . $page_id . '_' . $session_id,
2702 'chatgpt_run_lock_' . wp_hash( $assistant_id . '|' . $user_id . '|' . $page_id . '|' . $session_id ),
2703 'chatgpt_run_lock_' . wp_hash( $user_id . '|' . $page_id . '|' . $session_id ),
2704 'chatgpt_run_lock_' . wp_hash( $session_id ),
2705 'chatgpt_run_lock_' . $session_id,
2706 'chatgpt_run_lock_' . $user_id . '_' . $page_id . '_' . $session_id
2707 ];
2708 foreach ( $possible_locks as $lock_key ) {
2709 if ( get_transient( $lock_key ) ) {
2710 delete_transient( $lock_key );
2711 $cleared_count++;
2712 // DIAG - Diagnostics - Ver 2.3.4
2713 }
2714 }
2715 // Clear all possible queue variations
2716 $possible_queues = [
2717 'chatbot_message_queue_' . wp_hash( $assistant_id . '|' . $user_id . '|' . $page_id . '|' . $session_id ),
2718 'chatbot_message_queue_' . wp_hash( $user_id . '|' . $page_id . '|' . $session_id ),
2719 'chatbot_message_queue_' . wp_hash( $session_id ),
2720 'chatbot_message_queue_' . $session_id,
2721 'chatbot_message_queue_' . $user_id . '_' . $page_id . '_' . $session_id
2722 ];
2723 foreach ( $possible_queues as $queue_key ) {
2724 if ( get_transient( $queue_key ) ) {
2725 delete_transient( $queue_key );
2726 $cleared_count++;
2727 // DIAG - Diagnostics - Ver 2.3.4
2728 }
2729 }
2730 // DIAG - Diagnostics - Ver 2.3.4
2731 wp_send_json_success( 'Reset completed - Cleared ' . $cleared_count . ' locks/queues' );
2732 } else {
2733 // DIAG - Diagnostics - Ver 2.3.4
2734 wp_send_json_error( 'Missing parameters' );
2735 }
2736 }
2737
2738 // Reset Cache and Locks Handler - Ver 2.3.6
2739 function chatbot_chatgpt_reset_cache_locks_handler() {
2740 // Security: Check if user has permission to manage options (admin capability)
2741 if ( !current_user_can( 'manage_options' ) ) {
2742 wp_send_json_error( 'Insufficient permissions to reset cache and locks.', 403 );
2743 return;
2744 }
2745 // Security: Verify nonce for CSRF protection
2746 if ( !isset( $_POST['chatbot_nonce'] ) || !wp_verify_nonce( $_POST['chatbot_nonce'], 'chatbot_reset_cache_locks' ) ) {
2747 wp_send_json_error( 'Security check failed. Please refresh the page and try again.', 403 );
2748 return;
2749 }
2750 global $wpdb;
2751 $cleared_count = 0;
2752 try {
2753 // Clear all conversation locks
2754 $lock_patterns = [
2755 '_transient_chatgpt_conv_lock_%',
2756 '_transient_timeout_chatgpt_conv_lock_%',
2757 '_transient_chatgpt_run_lock_%',
2758 '_transient_timeout_chatgpt_run_lock_%',
2759 '_transient_chatbot_message_queue_%',
2760 '_transient_timeout_chatbot_message_queue_%',
2761 '_transient_chatbot_chatgpt_%',
2762 '_transient_timeout_chatbot_chatgpt_%'
2763 ];
2764 foreach ( $lock_patterns as $pattern ) {
2765 $result = $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s", $pattern ) );
2766 $cleared_count += $result;
2767 }
2768 // Clear expired transients
2769 $expired_result = $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s AND option_value < %d", '_transient_timeout_%', time() ) );
2770 $cleared_count += $expired_result;
2771 // Clear WordPress object cache if available
2772 if ( function_exists( 'wp_cache_flush' ) ) {
2773 wp_cache_flush();
2774 }
2775 // Clear any file-based caches
2776 $cache_dirs = [
2777 WP_CONTENT_DIR . '/cache/',
2778 WP_CONTENT_DIR . '/uploads/chatbot-chatgpt/',
2779 plugin_dir_path( __FILE__ ) . 'cache/',
2780 plugin_dir_path( __FILE__ ) . 'audio/',
2781 plugin_dir_path( __FILE__ ) . 'downloads/',
2782 plugin_dir_path( __FILE__ ) . 'transcripts/'
2783 ];
2784 foreach ( $cache_dirs as $cache_dir ) {
2785 if ( is_dir( $cache_dir ) ) {
2786 $files = glob( $cache_dir . '*' );
2787 foreach ( $files as $file ) {
2788 if ( is_file( $file ) && filemtime( $file ) < time() - 3600 ) {
2789 // Older than 1 hour
2790 @unlink( $file );
2791 $cleared_count++;
2792 }
2793 }
2794 }
2795 }
2796 // Log the action
2797 $log_message = '[' . date( 'Y-m-d H:i:s' ) . '] [Chatbot] [Advanced Reset] Cache and locks reset by admin user ID: ' . get_current_user_id() . ' - Cleared ' . $cleared_count . ' entries';
2798 chatbot_error_log( $log_message );
2799 wp_send_json_success( 'Cache and locks reset successfully. Cleared ' . $cleared_count . ' entries.' );
2800 } catch ( Exception $e ) {
2801 $log_message = '[' . date( 'Y-m-d H:i:s' ) . '] [Chatbot] [Advanced Reset] Error: ' . $e->getMessage();
2802 chatbot_error_log( $log_message );
2803 wp_send_json_error( 'Error resetting cache and locks: ' . $e->getMessage() );
2804 }
2805 }
2806
2807 // Append an extra message to the response - Ver 2.0.9
2808 function chatbot_chatgpt_append_extra_message( $response, $extra_message ) {
2809 // Append the extra message to the response
2810 $response = $response . ' ' . $extra_message;
2811 return $response;
2812 }
2813
2814 // Crawler aka Knowledge Navigator - Ver 1.6.1
2815 function chatbot_chatgpt_kn_status_activation() {
2816 add_option( 'chatbot_chatgpt_kn_status', 'Never Run' );
2817 // clear any old scheduled runs
2818 if ( wp_next_scheduled( 'crawl_scheduled_event_hook' ) ) {
2819 wp_clear_scheduled_hook( 'crawl_scheduled_event_hook' );
2820 }
2821 // clear the 'knowledge_navigator_scan_hook' hook on plugin activation - Ver 1.6.3
2822 if ( wp_next_scheduled( 'knowledge_navigator_scan_hook' ) ) {
2823 // BREAK/FIX - Do not unset the hook - Ver 1.8.5
2824 // wp_clear_scheduled_hook('knowledge_navigator_scan_hook'); // Clear scheduled runs
2825 }
2826 }
2827
2828 register_activation_hook( __FILE__, 'chatbot_chatgpt_kn_status_activation' );
2829 // Clean Up in Aisle 4
2830 function chatbot_chatgpt_kn_status_deactivation() {
2831 delete_option( 'chatbot_chatgpt_kn_status' );
2832 wp_clear_scheduled_hook( 'knowledge_navigator_scan_hook' );
2833 }
2834
2835 register_deactivation_hook( __FILE__, 'chatbot_chatgpt_kn_status_deactivation' );
2836 // Markov Chain builder - Activation Hook - Ver 2.1.6
2837 function chatbot_markov_chain_status_activation() {
2838 // DIAG - Diagnostics - Ver 2.1.6
2839 // Add the option for build status with a default value of 'Never Run'
2840 add_option( 'chatbot_markov_chain_build_status', 'Never Run' );
2841 // Clear any old scheduled runs, if present
2842 if ( wp_next_scheduled( 'chatbot_markov_chain_scan_hook' ) ) {
2843 // BREAK/FIX - Do not unset the hook - Ver 2.1.6
2844 // wp_clear_scheduled_hook('chatbot_markov_chain_scan_hook'); // Clear scheduled runs
2845 }
2846 }
2847
2848 register_activation_hook( __FILE__, 'chatbot_markov_chain_status_activation' );
2849 // Clean up scheduled events and options - Deactivation Hook
2850 function chatbot_markov_chain_status_deactivation() {
2851 // DIAG - Diagnostics - Ver 2.1.6
2852 // Delete the build status option on deactivation
2853 delete_option( 'chatbot_markov_chain_build_status' );
2854 // Clear any scheduled events related to the Markov Chain scan
2855 wp_clear_scheduled_hook( 'chatbot_markov_chain_scan_hook' );
2856 }
2857
2858 register_deactivation_hook( __FILE__, 'chatbot_markov_chain_status_deactivation' );
2859 // Transformer Model builder - Activation Hook - Ver 2.2.0
2860 function chatbot_transformer_model_status_activation() {
2861 // DIAG - Diagnostics - Ver 2.2.0
2862 // Add the option for build status with a default value of 'Never Run'
2863 add_option( 'chatbot_transformer_model_build_status', 'Never Run' );
2864 // Clear any old scheduled runs, if present
2865 if ( wp_next_scheduled( 'chatbot_transformer_model_scan_hook' ) ) {
2866 // BREAK/FIX - Do not unset the hook - Ver 2.2.0
2867 // wp_clear_scheduled_hook('chatbot_transformer_model_scan_hook'); // Clear scheduled runs
2868 }
2869 }
2870
2871 register_activation_hook( __FILE__, 'chatbot_transformer_model_status_activation' );
2872 // Clean up scheduled events and options - Deactivation Hook
2873 function chatbot_transformer_model_status_deactivation() {
2874 // DIAG - Diagnostics - Ver 2.2.0
2875 // Delete the build status option on deactivation
2876 delete_option( 'chatbot_transformer_model_build_status' );
2877 // Clear any scheduled events related to the Transformer Model scan
2878 wp_clear_scheduled_hook( 'chatbot_transformer_model_scan_hook' );
2879 }
2880
2881 register_deactivation_hook( __FILE__, 'chatbot_transformer_model_status_deactivation' );
2882 // Function to add a new message and response, keeping only the last five - Ver 1.6.1
2883 function addEntry( $transient_name, $newEntry ) {
2884 $context_history = get_transient( $transient_name );
2885 if ( !$context_history ) {
2886 $context_history = [];
2887 }
2888 // Determine the total length of all existing entries
2889 $totalLength = 0;
2890 foreach ( $context_history as $entry ) {
2891 if ( is_string( $entry ) ) {
2892 $totalLength += strlen( $entry );
2893 } elseif ( is_array( $entry ) ) {
2894 $totalLength += strlen( json_encode( $entry ) );
2895 // Convert to string if an array
2896 }
2897 }
2898 // IDEA - How will the new threading option from OpenAI change how this works?
2899 // Define thresholds for the number of entries to keep
2900 $maxEntries = 30;
2901 // Default maximum number of entries
2902 if ( $totalLength > 5000 ) {
2903 // Higher threshold
2904 $maxEntries = 20;
2905 }
2906 if ( $totalLength > 10000 ) {
2907 // Lower threshold
2908 $maxEntries = 10;
2909 }
2910 while ( count( $context_history ) >= $maxEntries ) {
2911 array_shift( $context_history );
2912 // Remove the oldest element
2913 }
2914 if ( is_array( $newEntry ) ) {
2915 $newEntry = json_encode( $newEntry );
2916 // Convert the array to a string
2917 }
2918 array_push( $context_history, $newEntry );
2919 // Append the new element
2920 set_transient( $transient_name, $context_history );
2921 // Update the transient
2922 }
2923
2924 // Function to return message and response - Ver 1.6.1
2925 function concatenateHistory( $transient_name ) {
2926 $context_history = get_transient( $transient_name );
2927 if ( !$context_history ) {
2928 return '';
2929 // Return an empty string if the transient does not exist
2930 }
2931 return implode( ' ', $context_history );
2932 // Concatenate the array values into a single string
2933 }
2934
2935 // FIXME - MOVE CORE FUNCTIONS TO A SEPARATE FILE, LEAVING ONLY THE HOOKS HERE
2936 // Initialize the Greetings - Ver 1.6.1
2937 function enqueue_greetings_script( $initial_greeting = null, $subsequent_greeting = null ) {
2938 // If user is logged in, then modify greeting if greeting contains "[...]" or remove if not logged in - Ver 1.9.4
2939 if ( is_user_logged_in() ) {
2940 $current_user_id = get_current_user_id();
2941 $current_user = get_userdata( $current_user_id );
2942 //Do this for Initial Greeting
2943 if ( empty( $initial_greeting ) ) {
2944 $initial_greeting = esc_attr( get_option( 'chatbot_chatgpt_initial_greeting', 'Hello! How can I help you today?' ) );
2945 }
2946 // Determine what the field name is between the brackets
2947 $user_field_name = '';
2948 $user_field_name = substr( $initial_greeting, strpos( $initial_greeting, '[' ) + 1, strpos( $initial_greeting, ']' ) - strpos( $initial_greeting, '[' ) - 1 );
2949 // If $initial_greeting contains "[$user_field_name]" then replace with field from DB
2950 if ( strpos( $initial_greeting, '[' . $user_field_name . ']' ) !== false ) {
2951 $initial_greeting = str_replace( '[' . $user_field_name . ']', $current_user->{$user_field_name}, $initial_greeting );
2952 } else {
2953 $initial_greeting = str_replace( '[' . $user_field_name . ']', '', $initial_greeting );
2954 // Remove the extra space when two spaces are present
2955 $initial_greeting = str_replace( ' ', ' ', $initial_greeting );
2956 // Remove the extra space before punctuation including period, comma, exclamation mark, and question mark
2957 $initial_greeting = preg_replace( '/\\s*([.,!?])/', '$1', $initial_greeting );
2958 }
2959 // Do this for Subsequent Greeting
2960 if ( empty( $subsequent_greeting ) ) {
2961 $subsequent_greeting = esc_attr( get_option( 'chatbot_chatgpt_subsequent_greeting', 'Hello again! How can I help you?' ) );
2962 }
2963 // Determine what the field name is between the brackets
2964 $user_field_name = '';
2965 $user_field_name = substr( $subsequent_greeting, strpos( $subsequent_greeting, '[' ) + 1, strpos( $subsequent_greeting, ']' ) - strpos( $subsequent_greeting, '[' ) - 1 );
2966 // If $subsequent_greeting contains "[$user_field_name]" then replace with field from DB
2967 if ( strpos( $subsequent_greeting, '[' . $user_field_name . ']' ) !== false ) {
2968 $subsequent_greeting = str_replace( '[' . $user_field_name . ']', $current_user->{$user_field_name}, $subsequent_greeting );
2969 } else {
2970 $subsequent_greeting = str_replace( '[' . $user_field_name . ']', '', $subsequent_greeting );
2971 // Remove the extra space when two spaces are present
2972 $subsequent_greeting = str_replace( ' ', ' ', $subsequent_greeting );
2973 // Remove the extra space before punctuation including period, comma, exclamation mark, and question mark
2974 $subsequent_greeting = preg_replace( '/\\s*([.,!?])/', '$1', $subsequent_greeting );
2975 }
2976 } else {
2977 //Do this for Initial Greeting
2978 if ( empty( $initial_greeting ) ) {
2979 $initial_greeting = esc_attr( get_option( 'chatbot_chatgpt_initial_greeting', 'Hello! How can I help you today?' ) );
2980 }
2981 $user_field_name = '';
2982 $user_field_name = substr( $initial_greeting, strpos( $initial_greeting, '[' ) + 1, strpos( $initial_greeting, ']' ) - strpos( $initial_greeting, '[' ) - 1 );
2983 // $initial_greeting = preg_replace('/\s*\[' . preg_quote($user_field_name, '/') . '\]\s*/', '', $initial_greeting);
2984 $initial_greeting = str_replace( '[' . $user_field_name . ']', '', $initial_greeting );
2985 // Remove the extra space when two spaces are present
2986 $initial_greeting = str_replace( ' ', ' ', $initial_greeting );
2987 // Remove the extra space before punctuation including period, comma, exclamation mark, and question mark
2988 $initial_greeting = preg_replace( '/\\s*([.,!?])/', '$1', $initial_greeting );
2989 //Do this for Subsequent Greeting
2990 if ( empty( $subsequent_greeting ) ) {
2991 $subsequent_greeting = esc_attr( get_option( 'chatbot_chatgpt_subsequent_greeting', 'Hello again! How can I help you?' ) );
2992 }
2993 $user_field_name = '';
2994 $user_field_name = substr( $subsequent_greeting, strpos( $subsequent_greeting, '[' ) + 1, strpos( $subsequent_greeting, ']' ) - strpos( $subsequent_greeting, '[' ) - 1 );
2995 // $subsequent_greeting = preg_replace('/\s*\[' . preg_quote($user_field_name, '/') . '\]\s*/', '', $subsequent_greeting);
2996 $subsequent_greeting = str_replace( '[' . $user_field_name . ']', '', $subsequent_greeting );
2997 // Remove the extra space when two spaces are present
2998 $subsequent_greeting = str_replace( ' ', ' ', $subsequent_greeting );
2999 // Remove the extra space before punctuation including period, comma, exclamation mark, and question mark
3000 $subsequent_greeting = preg_replace( '/\\s*([.,!?])/', '$1', $subsequent_greeting );
3001 }
3002 $greetings = array(
3003 'initial_greeting' => $initial_greeting,
3004 'subsequent_greeting' => $subsequent_greeting,
3005 );
3006 return $greetings;
3007 }
3008
3009 //
3010 add_action( 'wp_enqueue_scripts', 'enqueue_greetings_script' );
3011 // Add the color picker to the adaptive appearance settings section - Ver 1.8.1
3012 function enqueue_color_picker( $hook_suffix ) {
3013 global $chatbot_chatgpt_plugin_version;
3014 // first check that $hook_suffix is appropriate for your admin page
3015 wp_enqueue_style( 'wp-color-picker' );
3016 wp_enqueue_script(
3017 'my-script-handle',
3018 plugin_dir_url( __FILE__ ) . 'assets/js/chatbot-chatgpt-color-picker.js',
3019 array('wp-color-picker'),
3020 $chatbot_chatgpt_plugin_version,
3021 true
3022 );
3023 }
3024
3025 add_action( 'admin_enqueue_scripts', 'enqueue_color_picker' );
3026 // Determine if the plugin is installed
3027 function kchat_get_plugin_version() {
3028 global $chatbot_chatgpt_plugin_version;
3029 if ( !function_exists( 'get_plugin_data' ) ) {
3030 require_once ABSPATH . 'wp-admin/includes/plugin.php';
3031 }
3032 $plugin_data = get_plugin_data( plugin_dir_path( __FILE__ ) . 'chatbot-chatgpt.php' );
3033 // DIAG - Print the plugin data
3034 // $plugin_version = $plugin_data['chatbot_chatgpt_version'];
3035 $plugin_version = $plugin_data['Version'];
3036 // $plugin_version = $chatbot_chatgpt_plugin_version;
3037 update_option( 'chatbot_chatgpt_plugin_version', $plugin_version );
3038 // DIAG - Log the plugin version
3039 return $plugin_version;
3040 }
3041
3042 // DO NOT REMOVE THIS IF, IT IS ESSENTIAL FOR THE AUTOMATIC DEACTIVATION OF THE PLUGIN
3043 }