{"repo": "agwise-eia/agwise-website", "files": {"wp-content/plugins/chatbot-chatgpt/includes/settings/chatbot-settings-api-deepseek.php": {"de6c3bda23246fe11f7d20255df14f55b5865b77": {"t": 1785745774.8362296, "n": 13736, "h": "577bf92e0a4ab916", "c": "\n

Configure the default settings for the Chatbot plugin to use DeepSeek for chat generation. Start by adding your API key then selecting your choices below.

\n

More information about DeepSeek models and their capability can be found at https://api-docs.deepseek.com/quick_start/pricing.

\n

Don't forget to click Save Settings to save any changes your might make.

\n

For an explanation of the API/DeepSeek settings and additional documentation please click here.

\n \n

Configure the settings for the plugin by adding your API key. This plugin requires an API key from DeepSeek to function. You can obtain an API key by signing up at https://platform.deepseek.com/sign_in.

\n \n \" class=\"regular-text\" autocomplete=\"off\">\n \n

Configure the settings for the plugin when using chat models. Depending on the DeepSeek model you choose, the maximum tokens may be as high as 4097. The default is 150. For more information about the maximum tokens parameter, please see https://api-docs.deepseek.com/quick_start/pricing. Enter a conversation context to help the model understand the conversation. See the default for ideas. Some example shortcodes include:

\n

NOTE: Enter your API key (above), click Save Settings at the bottom of this page, in order to retrieve the full list of available models.

\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n

CAUTION: Configure the advanced settings for the plugin. Enter the base URL for the DeepSeek API. The default is https://api.deepseek.com.

\n \n \" class=\"regular-text\">\n \n \n 'string',\n 'sanitize_callback' => 'sanitize_text_field',\n )\n );\n\n register_setting(\n 'chatbot_deepseek_api_model',\n 'chatbot_deepseek_max_tokens_setting',\n array(\n 'type' => 'string',\n 'sanitize_callback' => 'sanitize_text_field',\n )\n );\n\n add_settings_section(\n 'chatbot_deepseek_api_model_chat_settings_section',\n 'Chat Settings',\n 'chatbot_deepseek_api_model_chat_settings_section_callback',\n 'chatbot_deepseek_api_model_chat_settings'\n );\n\n add_settings_field(\n 'chatbot_deepseek_model_choice',\n 'DeepSeek Model Choice',\n 'chatbot_deepseek_chat_model_choice_callback',\n 'chatbot_deepseek_api_model_chat_settings',\n 'chatbot_deepseek_api_model_chat_settings_section'\n );\n\n // Setting to adjust in small increments the number of Max Tokens - Ver 1.4.2\n add_settings_field(\n 'chatbot_deepseek_max_tokens_setting',\n 'Maximum Tokens Setting',\n 'chatbot_deepseek_max_tokens_setting_callback',\n 'chatbot_deepseek_api_model_chat_settings',\n 'chatbot_deepseek_api_model_chat_settings_section'\n );\n\n // Setting to adjust the conversation context\n add_settings_field(\n 'chatbot_deepseek_conversation_context',\n 'Conversation Context',\n 'chatbot_deepseek_conversation_context_callback',\n 'chatbot_deepseek_api_model_chat_settings',\n 'chatbot_deepseek_api_model_chat_settings_section'\n );\n\n // Temperature\n add_settings_field(\n 'chatbot_deepseek_temperature',\n 'Temperature',\n 'chatbot_deepseek_temperature_callback',\n 'chatbot_deepseek_api_model_chat_settings',\n 'chatbot_deepseek_api_model_chat_settings_section'\n );\n\n // Top P\n add_settings_field(\n 'chatbot_deepseek_top_p',\n 'Top P',\n 'chatbot_deepseek_top_p_callback',\n 'chatbot_deepseek_api_model_chat_settings',\n 'chatbot_deepseek_api_model_chat_settings_section'\n );\n\n // Advanced Model Settings - Ver 1.9.5\n register_setting('chatbot_deepseek_api_model', 'chatbot_deepseek_base_url');\n register_setting('chatbot_deepseek_api_model', 'chatbot_deepseek_timeout_setting');\n\n add_settings_section(\n 'chatbot_deepseek_api_model_advanced_section',\n 'Advanced API Settings',\n 'chatbot_deepseek_api_model_advanced_section_callback',\n 'chatbot_deepseek_api_model_advanced'\n );\n\n // Set the base URL for the API\n add_settings_field(\n 'chatbot_deepseek_base_url',\n 'Base URL for API',\n 'chatbot_deepseek_base_url_callback',\n 'chatbot_deepseek_api_model_advanced',\n 'chatbot_deepseek_api_model_advanced_section'\n );\n\n // Timeout setting\n add_settings_field(\n 'chatbot_deepseek_timeout_setting',\n 'Timeout Setting (in seconds)',\n 'chatbot_deepseek_timeout_setting_callback',\n 'chatbot_deepseek_api_model_advanced',\n 'chatbot_deepseek_api_model_advanced_section'\n );\n}\nadd_action('admin_init', 'chatbot_deepseek_api_settings_init');\n"}, "81133d2416ab2ca1d8784ec5469d49357805af5a": {"t": 1785756404.5740414, "n": 13736, "h": "577bf92e0a4ab916", "c": "\n

Configure the default settings for the Chatbot plugin to use DeepSeek for chat generation. Start by adding your API key then selecting your choices below.

\n

More information about DeepSeek models and their capability can be found at https://api-docs.deepseek.com/quick_start/pricing.

\n

Don't forget to click Save Settings to save any changes your might make.

\n

For an explanation of the API/DeepSeek settings and additional documentation please click here.

\n \n

Configure the settings for the plugin by adding your API key. This plugin requires an API key from DeepSeek to function. You can obtain an API key by signing up at https://platform.deepseek.com/sign_in.

\n \n \" class=\"regular-text\" autocomplete=\"off\">\n \n

Configure the settings for the plugin when using chat models. Depending on the DeepSeek model you choose, the maximum tokens may be as high as 4097. The default is 150. For more information about the maximum tokens parameter, please see https://api-docs.deepseek.com/quick_start/pricing. Enter a conversation context to help the model understand the conversation. See the default for ideas. Some example shortcodes include:

\n

NOTE: Enter your API key (above), click Save Settings at the bottom of this page, in order to retrieve the full list of available models.

\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n

CAUTION: Configure the advanced settings for the plugin. Enter the base URL for the DeepSeek API. The default is https://api.deepseek.com.

\n \n \" class=\"regular-text\">\n \n \n 'string',\n 'sanitize_callback' => 'sanitize_text_field',\n )\n );\n\n register_setting(\n 'chatbot_deepseek_api_model',\n 'chatbot_deepseek_max_tokens_setting',\n array(\n 'type' => 'string',\n 'sanitize_callback' => 'sanitize_text_field',\n )\n );\n\n add_settings_section(\n 'chatbot_deepseek_api_model_chat_settings_section',\n 'Chat Settings',\n 'chatbot_deepseek_api_model_chat_settings_section_callback',\n 'chatbot_deepseek_api_model_chat_settings'\n );\n\n add_settings_field(\n 'chatbot_deepseek_model_choice',\n 'DeepSeek Model Choice',\n 'chatbot_deepseek_chat_model_choice_callback',\n 'chatbot_deepseek_api_model_chat_settings',\n 'chatbot_deepseek_api_model_chat_settings_section'\n );\n\n // Setting to adjust in small increments the number of Max Tokens - Ver 1.4.2\n add_settings_field(\n 'chatbot_deepseek_max_tokens_setting',\n 'Maximum Tokens Setting',\n 'chatbot_deepseek_max_tokens_setting_callback',\n 'chatbot_deepseek_api_model_chat_settings',\n 'chatbot_deepseek_api_model_chat_settings_section'\n );\n\n // Setting to adjust the conversation context\n add_settings_field(\n 'chatbot_deepseek_conversation_context',\n 'Conversation Context',\n 'chatbot_deepseek_conversation_context_callback',\n 'chatbot_deepseek_api_model_chat_settings',\n 'chatbot_deepseek_api_model_chat_settings_section'\n );\n\n // Temperature\n add_settings_field(\n 'chatbot_deepseek_temperature',\n 'Temperature',\n 'chatbot_deepseek_temperature_callback',\n 'chatbot_deepseek_api_model_chat_settings',\n 'chatbot_deepseek_api_model_chat_settings_section'\n );\n\n // Top P\n add_settings_field(\n 'chatbot_deepseek_top_p',\n 'Top P',\n 'chatbot_deepseek_top_p_callback',\n 'chatbot_deepseek_api_model_chat_settings',\n 'chatbot_deepseek_api_model_chat_settings_section'\n );\n\n // Advanced Model Settings - Ver 1.9.5\n register_setting('chatbot_deepseek_api_model', 'chatbot_deepseek_base_url');\n register_setting('chatbot_deepseek_api_model', 'chatbot_deepseek_timeout_setting');\n\n add_settings_section(\n 'chatbot_deepseek_api_model_advanced_section',\n 'Advanced API Settings',\n 'chatbot_deepseek_api_model_advanced_section_callback',\n 'chatbot_deepseek_api_model_advanced'\n );\n\n // Set the base URL for the API\n add_settings_field(\n 'chatbot_deepseek_base_url',\n 'Base URL for API',\n 'chatbot_deepseek_base_url_callback',\n 'chatbot_deepseek_api_model_advanced',\n 'chatbot_deepseek_api_model_advanced_section'\n );\n\n // Timeout setting\n add_settings_field(\n 'chatbot_deepseek_timeout_setting',\n 'Timeout Setting (in seconds)',\n 'chatbot_deepseek_timeout_setting_callback',\n 'chatbot_deepseek_api_model_advanced',\n 'chatbot_deepseek_api_model_advanced_section'\n );\n}\nadd_action('admin_init', 'chatbot_deepseek_api_settings_init');\n"}}, "wp-content/plugins/chatbot-chatgpt/includes/utilities/chatbot-keyguard.php": {"de6c3bda23246fe11f7d20255df14f55b5865b77": {"t": 1785745784.4763155, "n": 14569, "h": "0fccf40841c37e5d", "c": " base64_encode($iv),\n 'encrypted' => $encrypted\n ];\n return json_encode($data);\n\n}\n\n// Decrypts the given JSON encoded string using AES-256-CBC with the provided secret key - Ver 2.2.6\nfunction chatbot_chatgpt_decrypt_api_key_with_key($data, $keyguard) {\n\n $decoded = json_decode($data, true);\n if (!isset($decoded['iv']) || !isset($decoded['encrypted'])) {\n return false;\n }\n $iv = base64_decode($decoded['iv']);\n $encrypted = $decoded['encrypted'];\n // Convert the hex-encoded keyguard to binary.\n $binary_key = hex2bin($keyguard);\n return openssl_decrypt($encrypted, 'aes-256-cbc', $binary_key, 0, $iv);\n\n}\n\n// Convenience function to encrypt an API key using the stored secret key - Ver 2.2.6\nfunction chatbot_chatgpt_encrypt_api_key($plaintext) {\n\n $keyguard = chatbot_chatgpt_generate_and_store_keyguard();\n return chatbot_chatgpt_encrypt_api_key_with_key($plaintext, $keyguard);\n\n}\n\n// Convenience function to decrypt an API key using the stored secret key - Ver 2.2.6\nfunction chatbot_chatgpt_decrypt_api_key($data, $option_name = null) {\n\n // Fix the JSON before decrypting.\n $data = html_entity_decode($data);\n // error_log('[Chatbot] [chatbot-keyguard.php] chatbot_chatgpt_decrypt_api_key() - $data: ' . print_r($data, true));\n \n // Attempt to decode the data as JSON.\n $decoded = json_decode($data, true);\n \n // If not in the expected JSON format, assume it's plain text.\n if (!is_array($decoded) || !isset($decoded['iv']) || !isset($decoded['encrypted'])) {\n // error_log('[Chatbot] [chatbot-keyguard.php] Plaintext detected.');\n\n $chatbot_ai_platform_choice = esc_attr( get_option('chatbot_ai_platform_choice') );\n switch ($chatbot_ai_platform_choice) {\n case 'OpenAI':\n $option_name = 'chatbot_chatgpt_api_key';\n break;\n case 'NVIDIA':\n $option_name = 'chatbot_nvidia_api_key';\n break;\n case 'Anthropic':\n $option_name = 'chatbot_anthropic_api_key';\n break;\n case 'DeepSeek':\n $option_name = 'chatbot_deepseek_api_key';\n break;\n case 'Google':\n $option_name = 'chatbot_google_api_key';\n break;\n case 'Mistral':\n $option_name = 'chatbot_mistral_api_key';\n break;\n case 'Azure OpenAI':\n $option_name = 'chatbot_azure_api_key';\n break;\n case 'Local':\n $option_name = 'chatbot_local_api_key';\n break;\n default:\n $option_name = null;\n }\n \n // If an option name is provided, encrypt the plain text and update the DB.\n if (!empty($option_name)) {\n $encrypted_value = chatbot_chatgpt_encrypt_api_key($data);\n update_option($option_name, $encrypted_value);\n // error_log('[Chatbot] [chatbot-keyguard.php] Failed to insert row into table: ' . $table_name);\n // error_log('[Chatbot] [chatbot-keyguard.php] Updated option ' . $option_name . ' with encrypted value.');\n }\n // Return the plain text.\n return $data;\n }\n \n // Otherwise, use the stored keyguard to decrypt.\n $keyguard = chatbot_chatgpt_generate_and_store_keyguard();\n // error_log('[Chatbot] [chatbot-keyguard.php] chatbot_chatgpt_decrypt_api_key() - $keyguard: ' . $keyguard);\n $decrypted_key = chatbot_chatgpt_decrypt_api_key_with_key($data, $keyguard);\n // error_log('[Chatbot] [chatbot-keyguard.php] chatbot_chatgpt_decrypt_api_key() - $decrypted_key: ' . $decrypted_key);\n return $decrypted_key;\n\n}\n\n// Upgrades stored encrypted API keys to use the new secret key.\n//\n// This function assumes you have stored API keys encrypted with an old secret key.\n// You must supply the old key so that each API key can be decrypted and then re-encrypted\n// with the new secret key (retrieved via chatbot_chatgpt_generate_and_store_keyguard()). The function takes two callbacks:\n// one to fetch all stored keys and one to update each key in storage.\n//\nfunction chatbot_chatgpt_upgrade_encrypted_api_keys(callable $fetch_keys_callback, callable $update_key_callback, $old_keyguard) {\n\n // Get the new secret key (this will generate one if it doesn't exist).\n $new_keyguard = chatbot_chatgpt_generate_and_store_keyguard();\n \n // Fetch stored keys. Expected format: [ 'key_id1' => 'encrypted_data', ... ]\n $stored_keys = $fetch_keys_callback();\n \n foreach ($stored_keys as $key_id => $encrypted_api_key) {\n\n // Decrypt using the old secret key.\n $decrypted = chatbot_chatgpt_decrypt_api_key_with_key($encrypted_api_key, $old_keyguard);\n if ($decrypted === false) {\n // Log or handle the decryption error, then skip this key.\n continue;\n }\n // Re-encrypt using the new secret key.\n $new_encrypted = chatbot_chatgpt_encrypt_api_key_with_key($decrypted, $new_keyguard);\n if ($new_encrypted === false) {\n // Log or handle the encryption error.\n continue;\n }\n // Update the stored key using the provided callback.\n $update_key_callback($key_id, $new_encrypted);\n }\n\n}\n\n// Fetch stored API keys from the database - Ver 2.2.6\n// \n// Example: Fetch keys from the database. Replace this with your actual DB call.\n// Expected format: [ 'key1' => 'plain_text_or_encrypted_value', ... ]\n// return [\n// 'key1' => 'UNENCRYPTED_API_KEY_1',\n// 'key2' => '{\"iv\":\"...\",\"encrypted\":\"...\"}', // Already encrypted key\n// 'key3' => 'UNENCRYPTED_API_KEY_3'\n// ];\n//\nfunction chatbot_chatgpt_fetch_stored_api_keys($chatbot_ai_platform_choice = null) {\n\n // Example: Fetch keys from the database. Replace this with your actual DB call.\n // Expected format: [ 'key1' => 'plain_text_or_encrypted_value', ... ]\n // return [\n // 'key1' => 'UNENCRYPTED_API_KEY_1',\n // 'key2' => '{\"iv\":\"...\",\"encrypted\":\"...\"}', // Already encrypted key\n // 'key3' => 'UNENCRYPTED_API_KEY_3'\n // ];\n $stored_keys = array();\n $stored_keys = array(\n 'chatbot_chatgpt_api_key' => esc_attr( get_option('chatbot_chatgpt_api_key') ),\n 'chatbot_nvidia_api_key' => esc_attr( get_option('chatbot_nvidia_api_key') ),\n 'chatbot_anthropic_api_key' => esc_attr( get_option('chatbot_anthropic_api_key') ),\n 'chatbot_deepseek_api_key' => esc_attr( get_option('chatbot_deepseek_api_key') ),\n 'chatbot_google_api_key' => esc_attr( get_option('chatbot_google_api_key') ),\n 'chatbot_mistral_api_key' => esc_attr( get_option('chatbot_mistral_api_key') ),\n 'chatbot_azure_api_key' => esc_attr( get_option('chatbot_azure_api_key') ),\n );\n \n return $stored_keys;\n\n}\n\n// Update stored API key in the database - Ver 2.2.6\nfunction chatbot_chatgpt_update_stored_api_key($key_id, $new_encrypted_value) {\n\n // Example: Update the key in the database. Replace with your actual update logic.\n // echo \"Updating key {$key_id} with new value: {$new_encrypted_value}\\n\";\n if ($key_id == 'chatbot_chatgpt_api_key') {\n update_option('chatbot_chatgpt_api_key', $new_encrypted_value);\n } elseif ($key_id == 'chatbot_nvidia_api_key') {\n update_option('chatbot_nvidia_api_key', $new_encrypted_value);\n } elseif ($key_id == 'chatbot_anthropic_api_key') {\n update_option('chatbot_anthropic_api_key', $new_encrypted_value);\n } elseif ($key_id == 'chatbot_deepseek_api_key') {\n update_option('chatbot_deepseek_api_key', $new_encrypted_value);\n } elseif ($key_id == 'chatbot_google_api_key') {\n update_option('chatbot_google_api_key', $new_encrypted_value);\n } elseif ($key_id == 'chatbot_mistral_api_key') {\n update_option('chatbot_mistral_api_key', $new_encrypted_value);\n } elseif ($key_id == 'chatbot_azure_api_key') {\n update_option('chatbot_azure_api_key', $new_encrypted_value);\n }\n\n}\n\n// Upgrade unencrypted API keys stored in the database - Ver 2.2.6\n//\n// This function fetches stored API keys via the provided callback.\n// It then checks each key—if the key is not already in the encrypted JSON format,\n// it encrypts the key and uses the update callback to save the new encrypted value.\n//\nfunction chatbot_chatgpt_upgrade_unencrypted_api_keys(callable $fetch_keys_callback, callable $update_key_callback) {\n\n // Retrieve the secret key (auto-generates it if it doesn't exist)\n $keyguard = chatbot_chatgpt_generate_and_store_keyguard();\n\n // Fetch all stored keys. Expected format: [ 'key_id1' => 'stored_value', ... ]\n $stored_keys = $fetch_keys_callback();\n\n foreach ($stored_keys as $key_id => $stored_value) {\n // Try decoding the stored value as JSON.\n $decoded = json_decode($stored_value, true);\n\n // Check if the stored value is already encrypted:\n // It should be an array with both 'iv' and 'encrypted' keys.\n if (is_array($decoded) && isset($decoded['iv']) && isset($decoded['encrypted'])) {\n // This key is already encrypted. Skip upgrading.\n continue;\n }\n\n // Otherwise, assume it's a plain text (unencrypted) key.\n $new_encrypted_value = chatbot_chatgpt_encrypt_api_key_with_key($stored_value, $keyguard);\n if ($new_encrypted_value !== false) {\n // Update the stored key using the provided callback.\n $update_key_callback($key_id, $new_encrypted_value);\n }\n }\n \n}\n\n// Hook our upgrade process into admin initialization - Ver 2.2.6\nadd_action('admin_init', 'chatbot_chatgpt_run_chatbot_api_key_upgrade');\n\n// Force the upgrade process to run - Ver 2.2.6\nfunction chatbot_chatgpt_run_chatbot_api_key_upgrade() {\n\n // Check if the upgrade has already run.\n if ( get_option('kognetiks_keyguard_upgraded') !== 'yes' ) {\n // For unencrypted keys, run the upgrade.\n chatbot_chatgpt_upgrade_unencrypted_api_keys('chatbot_chatgpt_fetch_stored_api_keys', 'chatbot_chatgpt_update_stored_api_key');\n \n // Optionally, if you need to upgrade keys encrypted with an old secret key,\n // call chatbot_chatgpt_upgrade_encrypted_api_keys here as well:\n // chatbot_chatgpt_upgrade_encrypted_api_keys('chatbot_chatgpt_fetch_stored_api_keys', 'chatbot_chatgpt_update_stored_api_key', $old_keyguard);\n \n // Mark that the upgrade has been performed.\n update_option('kognetiks_keyguard_upgraded', 'yes');\n }\n\n}\n\n// Sanitize the API key - Ver 2.2.6\nfunction chatbot_chatgpt_sanitize_api_key($input) {\n\n // Check if input is already in encrypted JSON format.\n $decoded = json_decode($input, true);\n if (is_array($decoded) && isset($decoded['iv']) && isset($decoded['encrypted'])) {\n // Already encrypted; do not encrypt again.\n return $input;\n }\n // Otherwise, encrypt the plain text API key.\n if (!empty($input)) {\n $encrypted_key = chatbot_chatgpt_encrypt_api_key($input);\n return $encrypted_key;\n }\n return $input;\n\n}\n"}, "81133d2416ab2ca1d8784ec5469d49357805af5a": {"t": 1785756403.1090007, "n": 14569, "h": "0fccf40841c37e5d", "c": " base64_encode($iv),\n 'encrypted' => $encrypted\n ];\n return json_encode($data);\n\n}\n\n// Decrypts the given JSON encoded string using AES-256-CBC with the provided secret key - Ver 2.2.6\nfunction chatbot_chatgpt_decrypt_api_key_with_key($data, $keyguard) {\n\n $decoded = json_decode($data, true);\n if (!isset($decoded['iv']) || !isset($decoded['encrypted'])) {\n return false;\n }\n $iv = base64_decode($decoded['iv']);\n $encrypted = $decoded['encrypted'];\n // Convert the hex-encoded keyguard to binary.\n $binary_key = hex2bin($keyguard);\n return openssl_decrypt($encrypted, 'aes-256-cbc', $binary_key, 0, $iv);\n\n}\n\n// Convenience function to encrypt an API key using the stored secret key - Ver 2.2.6\nfunction chatbot_chatgpt_encrypt_api_key($plaintext) {\n\n $keyguard = chatbot_chatgpt_generate_and_store_keyguard();\n return chatbot_chatgpt_encrypt_api_key_with_key($plaintext, $keyguard);\n\n}\n\n// Convenience function to decrypt an API key using the stored secret key - Ver 2.2.6\nfunction chatbot_chatgpt_decrypt_api_key($data, $option_name = null) {\n\n // Fix the JSON before decrypting.\n $data = html_entity_decode($data);\n // error_log('[Chatbot] [chatbot-keyguard.php] chatbot_chatgpt_decrypt_api_key() - $data: ' . print_r($data, true));\n \n // Attempt to decode the data as JSON.\n $decoded = json_decode($data, true);\n \n // If not in the expected JSON format, assume it's plain text.\n if (!is_array($decoded) || !isset($decoded['iv']) || !isset($decoded['encrypted'])) {\n // error_log('[Chatbot] [chatbot-keyguard.php] Plaintext detected.');\n\n $chatbot_ai_platform_choice = esc_attr( get_option('chatbot_ai_platform_choice') );\n switch ($chatbot_ai_platform_choice) {\n case 'OpenAI':\n $option_name = 'chatbot_chatgpt_api_key';\n break;\n case 'NVIDIA':\n $option_name = 'chatbot_nvidia_api_key';\n break;\n case 'Anthropic':\n $option_name = 'chatbot_anthropic_api_key';\n break;\n case 'DeepSeek':\n $option_name = 'chatbot_deepseek_api_key';\n break;\n case 'Google':\n $option_name = 'chatbot_google_api_key';\n break;\n case 'Mistral':\n $option_name = 'chatbot_mistral_api_key';\n break;\n case 'Azure OpenAI':\n $option_name = 'chatbot_azure_api_key';\n break;\n case 'Local':\n $option_name = 'chatbot_local_api_key';\n break;\n default:\n $option_name = null;\n }\n \n // If an option name is provided, encrypt the plain text and update the DB.\n if (!empty($option_name)) {\n $encrypted_value = chatbot_chatgpt_encrypt_api_key($data);\n update_option($option_name, $encrypted_value);\n // error_log('[Chatbot] [chatbot-keyguard.php] Failed to insert row into table: ' . $table_name);\n // error_log('[Chatbot] [chatbot-keyguard.php] Updated option ' . $option_name . ' with encrypted value.');\n }\n // Return the plain text.\n return $data;\n }\n \n // Otherwise, use the stored keyguard to decrypt.\n $keyguard = chatbot_chatgpt_generate_and_store_keyguard();\n // error_log('[Chatbot] [chatbot-keyguard.php] chatbot_chatgpt_decrypt_api_key() - $keyguard: ' . $keyguard);\n $decrypted_key = chatbot_chatgpt_decrypt_api_key_with_key($data, $keyguard);\n // error_log('[Chatbot] [chatbot-keyguard.php] chatbot_chatgpt_decrypt_api_key() - $decrypted_key: ' . $decrypted_key);\n return $decrypted_key;\n\n}\n\n// Upgrades stored encrypted API keys to use the new secret key.\n//\n// This function assumes you have stored API keys encrypted with an old secret key.\n// You must supply the old key so that each API key can be decrypted and then re-encrypted\n// with the new secret key (retrieved via chatbot_chatgpt_generate_and_store_keyguard()). The function takes two callbacks:\n// one to fetch all stored keys and one to update each key in storage.\n//\nfunction chatbot_chatgpt_upgrade_encrypted_api_keys(callable $fetch_keys_callback, callable $update_key_callback, $old_keyguard) {\n\n // Get the new secret key (this will generate one if it doesn't exist).\n $new_keyguard = chatbot_chatgpt_generate_and_store_keyguard();\n \n // Fetch stored keys. Expected format: [ 'key_id1' => 'encrypted_data', ... ]\n $stored_keys = $fetch_keys_callback();\n \n foreach ($stored_keys as $key_id => $encrypted_api_key) {\n\n // Decrypt using the old secret key.\n $decrypted = chatbot_chatgpt_decrypt_api_key_with_key($encrypted_api_key, $old_keyguard);\n if ($decrypted === false) {\n // Log or handle the decryption error, then skip this key.\n continue;\n }\n // Re-encrypt using the new secret key.\n $new_encrypted = chatbot_chatgpt_encrypt_api_key_with_key($decrypted, $new_keyguard);\n if ($new_encrypted === false) {\n // Log or handle the encryption error.\n continue;\n }\n // Update the stored key using the provided callback.\n $update_key_callback($key_id, $new_encrypted);\n }\n\n}\n\n// Fetch stored API keys from the database - Ver 2.2.6\n// \n// Example: Fetch keys from the database. Replace this with your actual DB call.\n// Expected format: [ 'key1' => 'plain_text_or_encrypted_value', ... ]\n// return [\n// 'key1' => 'UNENCRYPTED_API_KEY_1',\n// 'key2' => '{\"iv\":\"...\",\"encrypted\":\"...\"}', // Already encrypted key\n// 'key3' => 'UNENCRYPTED_API_KEY_3'\n// ];\n//\nfunction chatbot_chatgpt_fetch_stored_api_keys($chatbot_ai_platform_choice = null) {\n\n // Example: Fetch keys from the database. Replace this with your actual DB call.\n // Expected format: [ 'key1' => 'plain_text_or_encrypted_value', ... ]\n // return [\n // 'key1' => 'UNENCRYPTED_API_KEY_1',\n // 'key2' => '{\"iv\":\"...\",\"encrypted\":\"...\"}', // Already encrypted key\n // 'key3' => 'UNENCRYPTED_API_KEY_3'\n // ];\n $stored_keys = array();\n $stored_keys = array(\n 'chatbot_chatgpt_api_key' => esc_attr( get_option('chatbot_chatgpt_api_key') ),\n 'chatbot_nvidia_api_key' => esc_attr( get_option('chatbot_nvidia_api_key') ),\n 'chatbot_anthropic_api_key' => esc_attr( get_option('chatbot_anthropic_api_key') ),\n 'chatbot_deepseek_api_key' => esc_attr( get_option('chatbot_deepseek_api_key') ),\n 'chatbot_google_api_key' => esc_attr( get_option('chatbot_google_api_key') ),\n 'chatbot_mistral_api_key' => esc_attr( get_option('chatbot_mistral_api_key') ),\n 'chatbot_azure_api_key' => esc_attr( get_option('chatbot_azure_api_key') ),\n );\n \n return $stored_keys;\n\n}\n\n// Update stored API key in the database - Ver 2.2.6\nfunction chatbot_chatgpt_update_stored_api_key($key_id, $new_encrypted_value) {\n\n // Example: Update the key in the database. Replace with your actual update logic.\n // echo \"Updating key {$key_id} with new value: {$new_encrypted_value}\\n\";\n if ($key_id == 'chatbot_chatgpt_api_key') {\n update_option('chatbot_chatgpt_api_key', $new_encrypted_value);\n } elseif ($key_id == 'chatbot_nvidia_api_key') {\n update_option('chatbot_nvidia_api_key', $new_encrypted_value);\n } elseif ($key_id == 'chatbot_anthropic_api_key') {\n update_option('chatbot_anthropic_api_key', $new_encrypted_value);\n } elseif ($key_id == 'chatbot_deepseek_api_key') {\n update_option('chatbot_deepseek_api_key', $new_encrypted_value);\n } elseif ($key_id == 'chatbot_google_api_key') {\n update_option('chatbot_google_api_key', $new_encrypted_value);\n } elseif ($key_id == 'chatbot_mistral_api_key') {\n update_option('chatbot_mistral_api_key', $new_encrypted_value);\n } elseif ($key_id == 'chatbot_azure_api_key') {\n update_option('chatbot_azure_api_key', $new_encrypted_value);\n }\n\n}\n\n// Upgrade unencrypted API keys stored in the database - Ver 2.2.6\n//\n// This function fetches stored API keys via the provided callback.\n// It then checks each key—if the key is not already in the encrypted JSON format,\n// it encrypts the key and uses the update callback to save the new encrypted value.\n//\nfunction chatbot_chatgpt_upgrade_unencrypted_api_keys(callable $fetch_keys_callback, callable $update_key_callback) {\n\n // Retrieve the secret key (auto-generates it if it doesn't exist)\n $keyguard = chatbot_chatgpt_generate_and_store_keyguard();\n\n // Fetch all stored keys. Expected format: [ 'key_id1' => 'stored_value', ... ]\n $stored_keys = $fetch_keys_callback();\n\n foreach ($stored_keys as $key_id => $stored_value) {\n // Try decoding the stored value as JSON.\n $decoded = json_decode($stored_value, true);\n\n // Check if the stored value is already encrypted:\n // It should be an array with both 'iv' and 'encrypted' keys.\n if (is_array($decoded) && isset($decoded['iv']) && isset($decoded['encrypted'])) {\n // This key is already encrypted. Skip upgrading.\n continue;\n }\n\n // Otherwise, assume it's a plain text (unencrypted) key.\n $new_encrypted_value = chatbot_chatgpt_encrypt_api_key_with_key($stored_value, $keyguard);\n if ($new_encrypted_value !== false) {\n // Update the stored key using the provided callback.\n $update_key_callback($key_id, $new_encrypted_value);\n }\n }\n \n}\n\n// Hook our upgrade process into admin initialization - Ver 2.2.6\nadd_action('admin_init', 'chatbot_chatgpt_run_chatbot_api_key_upgrade');\n\n// Force the upgrade process to run - Ver 2.2.6\nfunction chatbot_chatgpt_run_chatbot_api_key_upgrade() {\n\n // Check if the upgrade has already run.\n if ( get_option('kognetiks_keyguard_upgraded') !== 'yes' ) {\n // For unencrypted keys, run the upgrade.\n chatbot_chatgpt_upgrade_unencrypted_api_keys('chatbot_chatgpt_fetch_stored_api_keys', 'chatbot_chatgpt_update_stored_api_key');\n \n // Optionally, if you need to upgrade keys encrypted with an old secret key,\n // call chatbot_chatgpt_upgrade_encrypted_api_keys here as well:\n // chatbot_chatgpt_upgrade_encrypted_api_keys('chatbot_chatgpt_fetch_stored_api_keys', 'chatbot_chatgpt_update_stored_api_key', $old_keyguard);\n \n // Mark that the upgrade has been performed.\n update_option('kognetiks_keyguard_upgraded', 'yes');\n }\n\n}\n\n// Sanitize the API key - Ver 2.2.6\nfunction chatbot_chatgpt_sanitize_api_key($input) {\n\n // Check if input is already in encrypted JSON format.\n $decoded = json_decode($input, true);\n if (is_array($decoded) && isset($decoded['iv']) && isset($decoded['encrypted'])) {\n // Already encrypted; do not encrypt again.\n return $input;\n }\n // Otherwise, encrypt the plain text API key.\n if (!empty($input)) {\n $encrypted_key = chatbot_chatgpt_encrypt_api_key($input);\n return $encrypted_key;\n }\n return $input;\n\n}\n"}}, "wp-content/plugins/chatbot-chatgpt/includes/utilities/chatbot-models.php": {"de6c3bda23246fe11f7d20255df14f55b5865b77": {"t": 1785745785.440198, "n": 24184, "h": "f0f82e61f23673e0", "c": " 'dall-e-3',\n 'object' => 'model',\n 'created' => 1698785189,\n 'owned_by' => 'system'\n ),\n array(\n 'id' => 'gpt-3.5-turbo',\n 'object' => 'model',\n 'created' => 1677610602,\n 'owned_by' => 'system'\n ),\n array(\n 'id' => 'tts-1-hd',\n 'object' => 'model',\n 'created' => 1699053241,\n 'owned_by' => 'system'\n ),\n array(\n 'id' => 'whisper-1',\n 'object' => 'model',\n 'created' => 1677532384,\n 'owned_by' => 'openai-internal'\n )\n );\n\n // See if the option exists, if not then create it and set the default\n if (esc_attr(get_option('chatbot_chatgpt_model_choice')) === false) {\n update_option('chatbot_chatgpt_model_choice', 'gpt-3.5-turbo');\n }\n if (esc_attr(get_option('chatbot_chatgpt_image_model_option')) === false) {\n update_option('chatbot_chatgpt_image_model_option', 'dall-e-3');\n }\n if (esc_attr(get_option('chatbot_chatgpt_voice_model_option')) === false) {\n update_option('chatbot_chatgpt_voice_model_option', 'tts-1-hd');\n }\n if (esc_attr(get_option('chatbot_chatgpt_whisper_model_option')) === false) {\n update_option('chatbot_chatgpt_whisper_model_option', 'whisper-1');\n }\n\n // Check if the API key is empty\n if (empty($api_key)) {\n return $default_model_list;\n }\n\n $openai_models_url = esc_attr(get_option('chatbot_chatgpt_base_url'));\n $openai_models_url = rtrim($openai_models_url, '/') . '/models';\n\n // Set HTTP request arguments\n $args = array(\n 'headers' => array(\n 'Content-Type' => 'application/json',\n 'Authorization' => 'Bearer ' . $api_key\n ),\n 'timeout' => 15, // Set a timeout to avoid long waits\n );\n\n // Make the request using WP HTTP API\n $response = wp_remote_get($openai_models_url, $args);\n\n // Check for errors\n if (is_wp_error($response)) {\n prod_trace( 'ERROR' . 'Error fetching OpenAI models: ' . $response->get_error_message());\n return $default_model_list;\n }\n\n // Decode the JSON response\n $data = json_decode(wp_remote_retrieve_body($response), true);\n\n // Check for API errors\n if (isset($data['error'])) {\n // return \"Error: \" . $data['error']['message'];\n // On 1st install needs an API key\n // So return a short list of the base models until an API key is entered\n return $default_model_list;\n }\n\n // Extract the models from the response\n if (isset($data['data']) && !is_null($data['data'])) {\n $models = $data['data'];\n } else {\n // Handle the case where 'data' is not set or is null\n $models = []; // Empty array\n prod_trace( 'WARNING', 'Data key is not set or is null in the \\$data array.');\n }\n\n // Ensure $models is an array\n if (!is_array($models)) {\n return $default_model_list;\n } else {\n // Sort the models by name\n usort($models, function($a, $b) {\n return $a['id'] <=> $b['id'];\n });\n }\n\n // Return the list of models\n return $models;\n\n}\n\n// Function to get the Model names from OpenAI API\nfunction chatbot_azure_get_models() {\n\n global $session_id;\n global $user_id;\n global $page_id;\n global $thread_id;\n global $assistant_id;\n global $kchat_settings;\n global $additional_instructions;\n global $model;\n global $voice;\n\n global $chatbot_chatgpt_display_style;\n global $chatbot_chatgpt_assistant_alias;\n \n $api_key = '';\n\n // Retrieve the API key\n $api_key = esc_attr(get_option('chatbot_azure_api_key'));\n // Decrypt the API key - Ver 2.2.6\n $api_key = chatbot_chatgpt_decrypt_api_key($api_key);\n\n // Default model list\n $default_model_list = '';\n $default_model_list = array(\n array(\n 'id' => 'dall-e-3',\n 'object' => 'model',\n 'created' => 1691712000,\n 'owned_by' => 'system'\n ),\n array(\n 'id' => 'gpt-3.5-turbo',\n 'object' => 'model',\n 'created' => 1707955200,\n 'owned_by' => 'system'\n ),\n array(\n 'id' => 'gpt-4o',\n 'object' => 'model',\n 'created' => 1715558400,\n 'owned_by' => 'system'\n ),\n array(\n 'id' => 'gpt-4o-mini',\n 'object' => 'model',\n 'created' => 1721347200,\n 'owned_by' => 'system'\n ),\n array(\n 'id' => 'gpt-4o-audio-preview',\n 'object' => 'model',\n 'created' => 1731369600,\n 'owned_by' => 'system'\n ),\n array(\n 'id' => 'text-embedding-ada-002',\n 'object' => 'model',\n 'created' => 1680480000,\n 'owned_by' => 'system'\n ),\n array(\n 'id' => 'whisper-1',\n 'object' => 'model',\n 'created' => 1677532384,\n 'owned_by' => 'openai-internal'\n )\n ); \n\n // See if the option exists, if not then create it and set the default\n if (esc_attr(get_option('chatbot_azure_model_choice')) === false) {\n update_option('chatbot_azure_model_choice', 'gpt-3.5-turbo');\n }\n if (esc_attr(get_option('chatbot_azure_image_model_option')) === false) {\n update_option('chatbot_azure_image_model_option', 'dall-e-3');\n }\n if (esc_attr(get_option('chatbot_azure_voice_model_option')) === false) {\n update_option('chatbot_azure_voice_model_option', 'tts-1-hd');\n }\n if (esc_attr(get_option('chatbot_azure_whisper_model_option')) === false) {\n update_option('chatbot_azure_whisper_model_option', 'whisper-1');\n }\n\n // Check if the API key is empty\n if (empty($api_key)) {\n return $default_model_list;\n }\n\n // Assemble the URL from resource name and deployment name\n $chatbot_azure_resource_name = esc_attr(get_option('chatbot_azure_resource_name', 'YOUR_RESOURCE_NAME'));\n $chatbot_azure_deployment_name = esc_attr(get_option('chatbot_azure_deployment_name', 'DEPLOYMENT_NAME'));\n $chatbot_azure_api_version = esc_attr(get_option('chatbot_azure_api_version', '2024-08-01-preview'));\n $azure_models_url = 'https://' . $chatbot_azure_resource_name . '.openai.azure.com/openai/models?api-version=' . $chatbot_azure_api_version;\n\n // Set HTTP request arguments\n $args = array(\n 'headers' => array(\n 'Content-Type' => 'application/json',\n 'api-key' => trim($api_key),\n 'Accept' => 'application/json',\n ),\n 'timeout' => 15, // Set a timeout to avoid long waits\n );\n\n // Make the request using WP HTTP API\n $response = wp_remote_get($azure_models_url, $args);\n\n // Check for errors\n if (is_wp_error($response)) {\n prod_trace( 'ERROR' . 'Error fetching Azure OpenAI models: ' . $response->get_error_message());\n return $default_model_list;\n }\n\n // Decode the JSON response\n $data = json_decode(wp_remote_retrieve_body($response), true);\n\n // Check for API errors\n if (isset($data['error'])) {\n // return \"Error: \" . $data['error']['message'];\n // On 1st install needs an API key\n // So return a short list of the base models until an API key is entered\n return $default_model_list;\n }\n\n // Extract the models from the response\n if (isset($data['data']) && !is_null($data['data'])) {\n $models = $data['data'];\n } else {\n // Handle the case where 'data' is not set or is null\n $models = []; // Empty array\n prod_trace( 'WARNING', 'Data key is not set or is null in the \\$data array.');\n }\n\n // Ensure $models is an array\n if (!is_array($models)) {\n return $default_model_list;\n } else {\n // Sort the models by name\n usort($models, function($a, $b) {\n return $a['id'] <=> $b['id'];\n });\n }\n\n // Return the list of models\n return $models;\n\n}\n\n// Function to get the Model names from NVIDIA API\nfunction chatbot_nvidia_get_models() {\n\n global $session_id;\n global $user_id;\n global $page_id;\n global $thread_id;\n global $assistant_id;\n global $kchat_settings;\n global $additional_instructions;\n global $model;\n global $voice;\n\n global $chatbot_chatgpt_display_style;\n global $chatbot_chatgpt_assistant_alias;\n \n $api_key = '';\n\n // Retrieve the API key\n $api_key = esc_attr(get_option('chatbot_nvidia_api_key'));\n // Decrypt the API key - Ver 2.2.6\n $api_key = chatbot_chatgpt_decrypt_api_key($api_key);\n\n // Default model list\n $default_model_list = '';\n $default_model_list = array(\n array(\n 'id' => 'nvidia/llama-3.1-nemotron-51b-instruct',\n 'object' => 'model',\n 'created' => 735790403,\n 'owned_by' => 'nvidia'\n ),\n );\n\n // See if the option exists, if not then create it and set the default\n if (esc_attr(get_option('chatbot_nvidia_model_choice')) === false) {\n update_option('chatbot_nvidia_model_choice', 'nvidia/llama-3_1-nemotron-70b-instruct');\n }\n\n // Check if the API key is empty\n if (empty($api_key)) {\n return $default_model_list;\n }\n\n $nvidia_models_url = esc_attr(get_option('chatbot_nvidia_base_url'));\n $nvidia_models_url = rtrim($nvidia_models_url, '/') . '/models';\n\n // Set HTTP request arguments\n $args = array(\n 'headers' => array(\n 'Content-Type' => 'application/json',\n 'Authorization' => 'Bearer ' . $api_key\n ),\n 'timeout' => 15, // Avoid long waits\n );\n\n // Make the request using WP HTTP API\n $response = wp_remote_get($nvidia_models_url, $args);\n\n // Check for errors\n if (is_wp_error($response)) {\n prod_trace( 'ERROR' , 'Error fetching NVIDIA models: ' . $response->get_error_message());\n return $default_model_list;\n }\n\n // Retrieve response body\n $response_body = wp_remote_retrieve_body($response);\n\n // Decode JSON response\n $data = json_decode($response_body, true);\n\n // Validate JSON\n if (json_last_error() !== JSON_ERROR_NONE) {\n prod_trace( 'ERROR' , 'Invalid JSON response from NVIDIA API.');\n return $default_model_list;\n }\n\n // Extract the models from the response\n if (isset($data['data']) && !is_null($data['data'])) {\n $models = $data['data'];\n } else {\n // Handle the case where 'data' is not set or is null\n $models = []; // Empty array\n prod_trace( 'WARNING', 'Data key is not set or is null in the \\$data array.');\n }\n\n // Ensure $models is an array\n if (!is_array($models)) {\n return $default_model_list;\n } else {\n // Sort the models by name\n usort($models, function($a, $b) {\n return $a['id'] <=> $b['id'];\n });\n }\n\n // Return the list of models\n return $models;\n\n}\n\n// Function to get the Model names from Anthropic API\nfunction chatbot_anthropic_get_models() {\n\n // https://docs.anthropic.com/en/api/messages-examples\n // https://docs.anthropic.com/en/docs/models-overview\n // https://docs.anthropic.com/en/docs/about-claude/models\n\n // Default model list\n $default_model_list = '';\n $default_model_list = array(\n array(\n 'id' => 'claude-3-5-sonnet-latest',\n 'object' => 'model',\n 'created' => 20241022,\n 'owned_by' => 'anthropic'\n ),\n array(\n 'id' => 'claude-3-5-haiku-latest',\n 'object' => 'model',\n 'created' => 20241022,\n 'owned_by' => 'anthropic'\n ),\n array(\n 'id' => 'claude-3-opus-latest',\n 'object' => 'model',\n 'created' => 20240229,\n 'owned_by' => 'anthropic'\n ),\n array(\n 'id' => 'claude-3-sonnet-20240229',\n 'object' => 'model',\n 'created' => 20240229,\n 'owned_by' => 'anthropic'\n ),\n array(\n 'id' => 'claude-3-haiku-20240307',\n 'object' => 'model',\n 'created' => 20240307,\n 'owned_by' => 'anthropic'\n )\n );\n\n // FIXME - Anthropic API does not have an endpoint for models\n // Call the API to get the models\n\n // Decode the JSON response\n // $data = json_decode($response, true);\n\n // FIXME - Force an error since there is no api endpoint for models\n $data = array('error' => array('message' => 'No models endpoint available'));\n\n // Check for API errors\n if (isset($data['error'])) {\n // return \"Error: \" . $data['error']['message'];\n // On 1st install needs an API key\n // So return a short list of the base models until an API key is entered\n return $default_model_list;\n }\n\n // Extract the models from the response\n if (isset($data['data']) && !is_null($data['data'])) {\n $models = $data['data'];\n } else {\n // Handle the case where 'data' is not set or is null\n $models = []; // Empty array\n ksum_prod_trace( 'WARNING', 'Data key is not set or is null in the \\$data array.');\n }\n\n // Ensure $models is an array\n if (!is_array($models)) {\n return $default_model_list;\n } else {\n // Sort the models by name\n usort($models, function($a, $b) {\n return $a['id'] <=> $b['id'];\n });\n }\n\n // Return the list of models\n return $models;\n\n}\n\n// Function to get the Model names from DeepSeek API\nfunction chatbot_deepseek_get_models() {\n\n $api_key = '';\n\n // Retrieve the API key\n $api_key = esc_attr(get_option('chatbot_deepseek_api_key'));\n // Decrypt the API key - Ver 2.2.6\n $api_key = chatbot_chatgpt_decrypt_api_key($api_key);\n\n // https://api-docs.deepseek.com/\n // https://api-docs.deepseek.com/quick_start/pricing\n // https://api.deepseek.com/models\n\n // Default model list\n $default_model_list = '';\n $default_model_list = array(\n array(\n 'id' => 'deepseek-chat',\n 'object' => 'model',\n 'created' => null,\n 'owned_by' => 'deepseek'\n ),\n );\n\n // Check if the API key is empty\n if (empty($api_key)) {\n return $default_model_list;\n }\n\n $deepseek_models_url = esc_attr(get_option('chatbot_deepseek_base_url'));\n $deepseek_models_url = rtrim($deepseek_models_url, '/') . '/models';\n\n // Set headers\n $args = array(\n 'headers' => array(\n 'Content-Type' => 'application/json',\n 'Authorization' => 'Bearer ' . $api_key,\n ),\n );\n\n // Perform the request\n $response = wp_remote_get($deepseek_models_url, $args);\n \n // Check for errors in the response\n if (is_wp_error($response)) {\n return $default_model_list;\n }\n\n // Decode the JSON response\n $body = wp_remote_retrieve_body($response);\n $data = json_decode($body, true);\n\n // Check if the response is valid and contains data\n if (isset($data['data']) && is_array($data['data'])) {\n $default_model_list = array_map(function($model) {\n return array(\n 'id' => $model['id'],\n 'object' => $model['object'],\n 'created' => null, // Assuming 'created' is not provided in the response\n 'owned_by' => $model['owned_by']\n );\n }, $data['data']);\n } else {\n // Handle the case where the response is not valid\n $default_model_list = array(\n array(\n 'id' => 'deepseek-chat',\n 'object' => 'model',\n 'created' => null,\n 'owned_by' => 'deepseek'\n ),\n );\n }\n\n // DeepSeek API does not have an endpoint for models\n return $default_model_list;\n\n}\n\n// Function to get the Model names from Mistral API\nfunction chatbot_mistral_get_models() {\n\n\n $api_key = '';\n\n // Retrieve the API key\n $api_key = esc_attr(get_option('chatbot_mistral_api_key'));\n // Decrypt the API key - Ver 2.2.6\n $api_key = chatbot_chatgpt_decrypt_api_key($api_key);\n\n // Default model list\n $default_model_list = '';\n $default_model_list = array(\n array(\n 'id' => 'mistral-small-latest',\n 'object' => 'model',\n 'created' => null,\n 'owned_by' => 'mistral'\n ),\n );\n\n // Check if the API key is empty\n if (empty($api_key)) {\n return $default_model_list;\n }\n\n // Set the API endpoint\n $mistral_models_url = esc_attr(get_option('chatbot_mistral_base_url'));\n $mistral_models_url = rtrim($mistral_models_url, '/') . '/models';\n\n // Set headers\n $args = array(\n 'headers' => array(\n 'Content-Type' => 'application/json',\n 'Authorization' => 'Bearer ' . $api_key,\n ),\n );\n\n // Perform the request\n $response = wp_remote_get($mistral_models_url, $args);\n\n // Check for errors in the response\n if (is_wp_error($response)) {\n return $default_model_list;\n }\n\n // Decode the JSON response\n $body = wp_remote_retrieve_body($response);\n $data = json_decode($body, true);\n\n // Check if the response is valid and contains data\n if (isset($data['data']) && is_array($data['data'])) {\n $default_model_list = array_map(function($model) {\n return array(\n 'id' => $model['id'],\n 'object' => $model['object'],\n 'created' => null,\n 'owned_by' => $model['owned_by']\n );\n }, $data['data']);\n } else {\n // Handle the case where the response is not valid\n $default_model_list = array(\n array(\n 'id' => 'mistral-small-latest',\n 'object' => 'model',\n 'created' => null,\n 'owned_by' => 'mistral'\n ),\n );\n }\n\n // Mistral API does not have an endpoint for models\n return $default_model_list;\n\n}\n\n// Function to get the Model names from Google API\nfunction chatbot_google_get_models() {\n\n $api_key = '';\n\n // Retrieve the API key\n $api_key = esc_attr(get_option('chatbot_google_api_key'));\n // Decrypt the API key - Ver 2.3.9\n $api_key = chatbot_chatgpt_decrypt_api_key($api_key);\n\n // Default model list\n $default_model_list = '';\n $default_model_list = array(\n array(\n 'id' => 'gemini-pro',\n 'object' => 'model',\n 'created' => null,\n 'owned_by' => 'google'\n ),\n array(\n 'id' => 'gemini-pro-vision',\n 'object' => 'model',\n 'created' => null,\n 'owned_by' => 'google'\n ),\n array(\n 'id' => 'gemini-1.5-pro',\n 'object' => 'model',\n 'created' => null,\n 'owned_by' => 'google'\n ),\n array(\n 'id' => 'gemini-1.5-flash',\n 'object' => 'model',\n 'created' => null,\n 'owned_by' => 'google'\n ),\n array(\n 'id' => 'gemini-2.0-flash',\n 'object' => 'model',\n 'created' => null,\n 'owned_by' => 'google'\n ),\n );\n\n // See if the option exists, if not then create it and set the default\n if (esc_attr(get_option('chatbot_google_model_choice')) === false) {\n update_option('chatbot_google_model_choice', 'gemini-2.0-flash');\n }\n\n // Check if the API key is empty\n if (empty($api_key)) {\n return $default_model_list;\n }\n\n // Get the base URL from settings\n $google_base_url = esc_attr(get_option('chatbot_google_base_url', 'https://generativelanguage.googleapis.com/v1beta'));\n $google_models_url = rtrim($google_base_url, '/');\n \n // If the URL doesn't end with /models, add it\n if (substr($google_models_url, -7) !== '/models') {\n $google_models_url = rtrim($google_models_url, '/') . '/models';\n }\n\n // Google API uses query parameter for API key\n $google_models_url = add_query_arg('key', $api_key, $google_models_url);\n\n // Set HTTP request arguments\n $args = array(\n 'headers' => array(\n 'Content-Type' => 'application/json'\n ),\n 'timeout' => 15, // Set a timeout to avoid long waits\n );\n\n // Make the request using WP HTTP API\n $response = wp_remote_get($google_models_url, $args);\n\n // Check for errors\n if (is_wp_error($response)) {\n prod_trace( 'ERROR', 'Error fetching Google models: ' . $response->get_error_message());\n return $default_model_list;\n }\n\n // Decode the JSON response\n $body = wp_remote_retrieve_body($response);\n $data = json_decode($body, true);\n\n // Check for API errors\n if (isset($data['error'])) {\n // return \"Error: \" . $data['error']['message'];\n // On 1st install needs an API key\n // So return a short list of the base models until an API key is entered\n return $default_model_list;\n }\n\n // Extract the models from the response\n // Google API may return models in different formats\n if (isset($data['models']) && is_array($data['models'])) {\n $models = array_map(function($model) {\n // Google API returns model names as \"models/gemini-pro\" - extract just the model name\n $model_id = $model['name'] ?? $model['displayName'] ?? $model['id'] ?? '';\n // Remove \"models/\" prefix if present\n if (strpos($model_id, 'models/') === 0) {\n $model_id = substr($model_id, 7);\n }\n return array(\n 'id' => $model_id,\n 'object' => 'model',\n 'created' => null,\n 'owned_by' => 'google'\n );\n }, $data['models']);\n } elseif (isset($data['data']) && is_array($data['data'])) {\n $models = array_map(function($model) {\n // Google API returns model names as \"models/gemini-pro\" - extract just the model name\n $model_id = $model['id'] ?? $model['name'] ?? '';\n // Remove \"models/\" prefix if present\n if (strpos($model_id, 'models/') === 0) {\n $model_id = substr($model_id, 7);\n }\n return array(\n 'id' => $model_id,\n 'object' => $model['object'] ?? 'model',\n 'created' => $model['created'] ?? null,\n 'owned_by' => $model['owned_by'] ?? 'google'\n );\n }, $data['data']);\n } else {\n // Handle the case where models are not in expected format\n $models = [];\n prod_trace( 'WARNING', 'Models not found in expected format in Google API response.');\n }\n\n // Ensure $models is an array\n if (!is_array($models) || empty($models)) {\n return $default_model_list;\n } else {\n // Sort the models by name\n usort($models, function($a, $b) {\n return $a['id'] <=> $b['id'];\n });\n }\n\n // Return the list of models\n return $models;\n\n}\n"}, "81133d2416ab2ca1d8784ec5469d49357805af5a": {"t": 1785756404.0929172, "n": 24184, "h": "f0f82e61f23673e0", "c": " 'dall-e-3',\n 'object' => 'model',\n 'created' => 1698785189,\n 'owned_by' => 'system'\n ),\n array(\n 'id' => 'gpt-3.5-turbo',\n 'object' => 'model',\n 'created' => 1677610602,\n 'owned_by' => 'system'\n ),\n array(\n 'id' => 'tts-1-hd',\n 'object' => 'model',\n 'created' => 1699053241,\n 'owned_by' => 'system'\n ),\n array(\n 'id' => 'whisper-1',\n 'object' => 'model',\n 'created' => 1677532384,\n 'owned_by' => 'openai-internal'\n )\n );\n\n // See if the option exists, if not then create it and set the default\n if (esc_attr(get_option('chatbot_chatgpt_model_choice')) === false) {\n update_option('chatbot_chatgpt_model_choice', 'gpt-3.5-turbo');\n }\n if (esc_attr(get_option('chatbot_chatgpt_image_model_option')) === false) {\n update_option('chatbot_chatgpt_image_model_option', 'dall-e-3');\n }\n if (esc_attr(get_option('chatbot_chatgpt_voice_model_option')) === false) {\n update_option('chatbot_chatgpt_voice_model_option', 'tts-1-hd');\n }\n if (esc_attr(get_option('chatbot_chatgpt_whisper_model_option')) === false) {\n update_option('chatbot_chatgpt_whisper_model_option', 'whisper-1');\n }\n\n // Check if the API key is empty\n if (empty($api_key)) {\n return $default_model_list;\n }\n\n $openai_models_url = esc_attr(get_option('chatbot_chatgpt_base_url'));\n $openai_models_url = rtrim($openai_models_url, '/') . '/models';\n\n // Set HTTP request arguments\n $args = array(\n 'headers' => array(\n 'Content-Type' => 'application/json',\n 'Authorization' => 'Bearer ' . $api_key\n ),\n 'timeout' => 15, // Set a timeout to avoid long waits\n );\n\n // Make the request using WP HTTP API\n $response = wp_remote_get($openai_models_url, $args);\n\n // Check for errors\n if (is_wp_error($response)) {\n prod_trace( 'ERROR' . 'Error fetching OpenAI models: ' . $response->get_error_message());\n return $default_model_list;\n }\n\n // Decode the JSON response\n $data = json_decode(wp_remote_retrieve_body($response), true);\n\n // Check for API errors\n if (isset($data['error'])) {\n // return \"Error: \" . $data['error']['message'];\n // On 1st install needs an API key\n // So return a short list of the base models until an API key is entered\n return $default_model_list;\n }\n\n // Extract the models from the response\n if (isset($data['data']) && !is_null($data['data'])) {\n $models = $data['data'];\n } else {\n // Handle the case where 'data' is not set or is null\n $models = []; // Empty array\n prod_trace( 'WARNING', 'Data key is not set or is null in the \\$data array.');\n }\n\n // Ensure $models is an array\n if (!is_array($models)) {\n return $default_model_list;\n } else {\n // Sort the models by name\n usort($models, function($a, $b) {\n return $a['id'] <=> $b['id'];\n });\n }\n\n // Return the list of models\n return $models;\n\n}\n\n// Function to get the Model names from OpenAI API\nfunction chatbot_azure_get_models() {\n\n global $session_id;\n global $user_id;\n global $page_id;\n global $thread_id;\n global $assistant_id;\n global $kchat_settings;\n global $additional_instructions;\n global $model;\n global $voice;\n\n global $chatbot_chatgpt_display_style;\n global $chatbot_chatgpt_assistant_alias;\n \n $api_key = '';\n\n // Retrieve the API key\n $api_key = esc_attr(get_option('chatbot_azure_api_key'));\n // Decrypt the API key - Ver 2.2.6\n $api_key = chatbot_chatgpt_decrypt_api_key($api_key);\n\n // Default model list\n $default_model_list = '';\n $default_model_list = array(\n array(\n 'id' => 'dall-e-3',\n 'object' => 'model',\n 'created' => 1691712000,\n 'owned_by' => 'system'\n ),\n array(\n 'id' => 'gpt-3.5-turbo',\n 'object' => 'model',\n 'created' => 1707955200,\n 'owned_by' => 'system'\n ),\n array(\n 'id' => 'gpt-4o',\n 'object' => 'model',\n 'created' => 1715558400,\n 'owned_by' => 'system'\n ),\n array(\n 'id' => 'gpt-4o-mini',\n 'object' => 'model',\n 'created' => 1721347200,\n 'owned_by' => 'system'\n ),\n array(\n 'id' => 'gpt-4o-audio-preview',\n 'object' => 'model',\n 'created' => 1731369600,\n 'owned_by' => 'system'\n ),\n array(\n 'id' => 'text-embedding-ada-002',\n 'object' => 'model',\n 'created' => 1680480000,\n 'owned_by' => 'system'\n ),\n array(\n 'id' => 'whisper-1',\n 'object' => 'model',\n 'created' => 1677532384,\n 'owned_by' => 'openai-internal'\n )\n ); \n\n // See if the option exists, if not then create it and set the default\n if (esc_attr(get_option('chatbot_azure_model_choice')) === false) {\n update_option('chatbot_azure_model_choice', 'gpt-3.5-turbo');\n }\n if (esc_attr(get_option('chatbot_azure_image_model_option')) === false) {\n update_option('chatbot_azure_image_model_option', 'dall-e-3');\n }\n if (esc_attr(get_option('chatbot_azure_voice_model_option')) === false) {\n update_option('chatbot_azure_voice_model_option', 'tts-1-hd');\n }\n if (esc_attr(get_option('chatbot_azure_whisper_model_option')) === false) {\n update_option('chatbot_azure_whisper_model_option', 'whisper-1');\n }\n\n // Check if the API key is empty\n if (empty($api_key)) {\n return $default_model_list;\n }\n\n // Assemble the URL from resource name and deployment name\n $chatbot_azure_resource_name = esc_attr(get_option('chatbot_azure_resource_name', 'YOUR_RESOURCE_NAME'));\n $chatbot_azure_deployment_name = esc_attr(get_option('chatbot_azure_deployment_name', 'DEPLOYMENT_NAME'));\n $chatbot_azure_api_version = esc_attr(get_option('chatbot_azure_api_version', '2024-08-01-preview'));\n $azure_models_url = 'https://' . $chatbot_azure_resource_name . '.openai.azure.com/openai/models?api-version=' . $chatbot_azure_api_version;\n\n // Set HTTP request arguments\n $args = array(\n 'headers' => array(\n 'Content-Type' => 'application/json',\n 'api-key' => trim($api_key),\n 'Accept' => 'application/json',\n ),\n 'timeout' => 15, // Set a timeout to avoid long waits\n );\n\n // Make the request using WP HTTP API\n $response = wp_remote_get($azure_models_url, $args);\n\n // Check for errors\n if (is_wp_error($response)) {\n prod_trace( 'ERROR' . 'Error fetching Azure OpenAI models: ' . $response->get_error_message());\n return $default_model_list;\n }\n\n // Decode the JSON response\n $data = json_decode(wp_remote_retrieve_body($response), true);\n\n // Check for API errors\n if (isset($data['error'])) {\n // return \"Error: \" . $data['error']['message'];\n // On 1st install needs an API key\n // So return a short list of the base models until an API key is entered\n return $default_model_list;\n }\n\n // Extract the models from the response\n if (isset($data['data']) && !is_null($data['data'])) {\n $models = $data['data'];\n } else {\n // Handle the case where 'data' is not set or is null\n $models = []; // Empty array\n prod_trace( 'WARNING', 'Data key is not set or is null in the \\$data array.');\n }\n\n // Ensure $models is an array\n if (!is_array($models)) {\n return $default_model_list;\n } else {\n // Sort the models by name\n usort($models, function($a, $b) {\n return $a['id'] <=> $b['id'];\n });\n }\n\n // Return the list of models\n return $models;\n\n}\n\n// Function to get the Model names from NVIDIA API\nfunction chatbot_nvidia_get_models() {\n\n global $session_id;\n global $user_id;\n global $page_id;\n global $thread_id;\n global $assistant_id;\n global $kchat_settings;\n global $additional_instructions;\n global $model;\n global $voice;\n\n global $chatbot_chatgpt_display_style;\n global $chatbot_chatgpt_assistant_alias;\n \n $api_key = '';\n\n // Retrieve the API key\n $api_key = esc_attr(get_option('chatbot_nvidia_api_key'));\n // Decrypt the API key - Ver 2.2.6\n $api_key = chatbot_chatgpt_decrypt_api_key($api_key);\n\n // Default model list\n $default_model_list = '';\n $default_model_list = array(\n array(\n 'id' => 'nvidia/llama-3.1-nemotron-51b-instruct',\n 'object' => 'model',\n 'created' => 735790403,\n 'owned_by' => 'nvidia'\n ),\n );\n\n // See if the option exists, if not then create it and set the default\n if (esc_attr(get_option('chatbot_nvidia_model_choice')) === false) {\n update_option('chatbot_nvidia_model_choice', 'nvidia/llama-3_1-nemotron-70b-instruct');\n }\n\n // Check if the API key is empty\n if (empty($api_key)) {\n return $default_model_list;\n }\n\n $nvidia_models_url = esc_attr(get_option('chatbot_nvidia_base_url'));\n $nvidia_models_url = rtrim($nvidia_models_url, '/') . '/models';\n\n // Set HTTP request arguments\n $args = array(\n 'headers' => array(\n 'Content-Type' => 'application/json',\n 'Authorization' => 'Bearer ' . $api_key\n ),\n 'timeout' => 15, // Avoid long waits\n );\n\n // Make the request using WP HTTP API\n $response = wp_remote_get($nvidia_models_url, $args);\n\n // Check for errors\n if (is_wp_error($response)) {\n prod_trace( 'ERROR' , 'Error fetching NVIDIA models: ' . $response->get_error_message());\n return $default_model_list;\n }\n\n // Retrieve response body\n $response_body = wp_remote_retrieve_body($response);\n\n // Decode JSON response\n $data = json_decode($response_body, true);\n\n // Validate JSON\n if (json_last_error() !== JSON_ERROR_NONE) {\n prod_trace( 'ERROR' , 'Invalid JSON response from NVIDIA API.');\n return $default_model_list;\n }\n\n // Extract the models from the response\n if (isset($data['data']) && !is_null($data['data'])) {\n $models = $data['data'];\n } else {\n // Handle the case where 'data' is not set or is null\n $models = []; // Empty array\n prod_trace( 'WARNING', 'Data key is not set or is null in the \\$data array.');\n }\n\n // Ensure $models is an array\n if (!is_array($models)) {\n return $default_model_list;\n } else {\n // Sort the models by name\n usort($models, function($a, $b) {\n return $a['id'] <=> $b['id'];\n });\n }\n\n // Return the list of models\n return $models;\n\n}\n\n// Function to get the Model names from Anthropic API\nfunction chatbot_anthropic_get_models() {\n\n // https://docs.anthropic.com/en/api/messages-examples\n // https://docs.anthropic.com/en/docs/models-overview\n // https://docs.anthropic.com/en/docs/about-claude/models\n\n // Default model list\n $default_model_list = '';\n $default_model_list = array(\n array(\n 'id' => 'claude-3-5-sonnet-latest',\n 'object' => 'model',\n 'created' => 20241022,\n 'owned_by' => 'anthropic'\n ),\n array(\n 'id' => 'claude-3-5-haiku-latest',\n 'object' => 'model',\n 'created' => 20241022,\n 'owned_by' => 'anthropic'\n ),\n array(\n 'id' => 'claude-3-opus-latest',\n 'object' => 'model',\n 'created' => 20240229,\n 'owned_by' => 'anthropic'\n ),\n array(\n 'id' => 'claude-3-sonnet-20240229',\n 'object' => 'model',\n 'created' => 20240229,\n 'owned_by' => 'anthropic'\n ),\n array(\n 'id' => 'claude-3-haiku-20240307',\n 'object' => 'model',\n 'created' => 20240307,\n 'owned_by' => 'anthropic'\n )\n );\n\n // FIXME - Anthropic API does not have an endpoint for models\n // Call the API to get the models\n\n // Decode the JSON response\n // $data = json_decode($response, true);\n\n // FIXME - Force an error since there is no api endpoint for models\n $data = array('error' => array('message' => 'No models endpoint available'));\n\n // Check for API errors\n if (isset($data['error'])) {\n // return \"Error: \" . $data['error']['message'];\n // On 1st install needs an API key\n // So return a short list of the base models until an API key is entered\n return $default_model_list;\n }\n\n // Extract the models from the response\n if (isset($data['data']) && !is_null($data['data'])) {\n $models = $data['data'];\n } else {\n // Handle the case where 'data' is not set or is null\n $models = []; // Empty array\n ksum_prod_trace( 'WARNING', 'Data key is not set or is null in the \\$data array.');\n }\n\n // Ensure $models is an array\n if (!is_array($models)) {\n return $default_model_list;\n } else {\n // Sort the models by name\n usort($models, function($a, $b) {\n return $a['id'] <=> $b['id'];\n });\n }\n\n // Return the list of models\n return $models;\n\n}\n\n// Function to get the Model names from DeepSeek API\nfunction chatbot_deepseek_get_models() {\n\n $api_key = '';\n\n // Retrieve the API key\n $api_key = esc_attr(get_option('chatbot_deepseek_api_key'));\n // Decrypt the API key - Ver 2.2.6\n $api_key = chatbot_chatgpt_decrypt_api_key($api_key);\n\n // https://api-docs.deepseek.com/\n // https://api-docs.deepseek.com/quick_start/pricing\n // https://api.deepseek.com/models\n\n // Default model list\n $default_model_list = '';\n $default_model_list = array(\n array(\n 'id' => 'deepseek-chat',\n 'object' => 'model',\n 'created' => null,\n 'owned_by' => 'deepseek'\n ),\n );\n\n // Check if the API key is empty\n if (empty($api_key)) {\n return $default_model_list;\n }\n\n $deepseek_models_url = esc_attr(get_option('chatbot_deepseek_base_url'));\n $deepseek_models_url = rtrim($deepseek_models_url, '/') . '/models';\n\n // Set headers\n $args = array(\n 'headers' => array(\n 'Content-Type' => 'application/json',\n 'Authorization' => 'Bearer ' . $api_key,\n ),\n );\n\n // Perform the request\n $response = wp_remote_get($deepseek_models_url, $args);\n \n // Check for errors in the response\n if (is_wp_error($response)) {\n return $default_model_list;\n }\n\n // Decode the JSON response\n $body = wp_remote_retrieve_body($response);\n $data = json_decode($body, true);\n\n // Check if the response is valid and contains data\n if (isset($data['data']) && is_array($data['data'])) {\n $default_model_list = array_map(function($model) {\n return array(\n 'id' => $model['id'],\n 'object' => $model['object'],\n 'created' => null, // Assuming 'created' is not provided in the response\n 'owned_by' => $model['owned_by']\n );\n }, $data['data']);\n } else {\n // Handle the case where the response is not valid\n $default_model_list = array(\n array(\n 'id' => 'deepseek-chat',\n 'object' => 'model',\n 'created' => null,\n 'owned_by' => 'deepseek'\n ),\n );\n }\n\n // DeepSeek API does not have an endpoint for models\n return $default_model_list;\n\n}\n\n// Function to get the Model names from Mistral API\nfunction chatbot_mistral_get_models() {\n\n\n $api_key = '';\n\n // Retrieve the API key\n $api_key = esc_attr(get_option('chatbot_mistral_api_key'));\n // Decrypt the API key - Ver 2.2.6\n $api_key = chatbot_chatgpt_decrypt_api_key($api_key);\n\n // Default model list\n $default_model_list = '';\n $default_model_list = array(\n array(\n 'id' => 'mistral-small-latest',\n 'object' => 'model',\n 'created' => null,\n 'owned_by' => 'mistral'\n ),\n );\n\n // Check if the API key is empty\n if (empty($api_key)) {\n return $default_model_list;\n }\n\n // Set the API endpoint\n $mistral_models_url = esc_attr(get_option('chatbot_mistral_base_url'));\n $mistral_models_url = rtrim($mistral_models_url, '/') . '/models';\n\n // Set headers\n $args = array(\n 'headers' => array(\n 'Content-Type' => 'application/json',\n 'Authorization' => 'Bearer ' . $api_key,\n ),\n );\n\n // Perform the request\n $response = wp_remote_get($mistral_models_url, $args);\n\n // Check for errors in the response\n if (is_wp_error($response)) {\n return $default_model_list;\n }\n\n // Decode the JSON response\n $body = wp_remote_retrieve_body($response);\n $data = json_decode($body, true);\n\n // Check if the response is valid and contains data\n if (isset($data['data']) && is_array($data['data'])) {\n $default_model_list = array_map(function($model) {\n return array(\n 'id' => $model['id'],\n 'object' => $model['object'],\n 'created' => null,\n 'owned_by' => $model['owned_by']\n );\n }, $data['data']);\n } else {\n // Handle the case where the response is not valid\n $default_model_list = array(\n array(\n 'id' => 'mistral-small-latest',\n 'object' => 'model',\n 'created' => null,\n 'owned_by' => 'mistral'\n ),\n );\n }\n\n // Mistral API does not have an endpoint for models\n return $default_model_list;\n\n}\n\n// Function to get the Model names from Google API\nfunction chatbot_google_get_models() {\n\n $api_key = '';\n\n // Retrieve the API key\n $api_key = esc_attr(get_option('chatbot_google_api_key'));\n // Decrypt the API key - Ver 2.3.9\n $api_key = chatbot_chatgpt_decrypt_api_key($api_key);\n\n // Default model list\n $default_model_list = '';\n $default_model_list = array(\n array(\n 'id' => 'gemini-pro',\n 'object' => 'model',\n 'created' => null,\n 'owned_by' => 'google'\n ),\n array(\n 'id' => 'gemini-pro-vision',\n 'object' => 'model',\n 'created' => null,\n 'owned_by' => 'google'\n ),\n array(\n 'id' => 'gemini-1.5-pro',\n 'object' => 'model',\n 'created' => null,\n 'owned_by' => 'google'\n ),\n array(\n 'id' => 'gemini-1.5-flash',\n 'object' => 'model',\n 'created' => null,\n 'owned_by' => 'google'\n ),\n array(\n 'id' => 'gemini-2.0-flash',\n 'object' => 'model',\n 'created' => null,\n 'owned_by' => 'google'\n ),\n );\n\n // See if the option exists, if not then create it and set the default\n if (esc_attr(get_option('chatbot_google_model_choice')) === false) {\n update_option('chatbot_google_model_choice', 'gemini-2.0-flash');\n }\n\n // Check if the API key is empty\n if (empty($api_key)) {\n return $default_model_list;\n }\n\n // Get the base URL from settings\n $google_base_url = esc_attr(get_option('chatbot_google_base_url', 'https://generativelanguage.googleapis.com/v1beta'));\n $google_models_url = rtrim($google_base_url, '/');\n \n // If the URL doesn't end with /models, add it\n if (substr($google_models_url, -7) !== '/models') {\n $google_models_url = rtrim($google_models_url, '/') . '/models';\n }\n\n // Google API uses query parameter for API key\n $google_models_url = add_query_arg('key', $api_key, $google_models_url);\n\n // Set HTTP request arguments\n $args = array(\n 'headers' => array(\n 'Content-Type' => 'application/json'\n ),\n 'timeout' => 15, // Set a timeout to avoid long waits\n );\n\n // Make the request using WP HTTP API\n $response = wp_remote_get($google_models_url, $args);\n\n // Check for errors\n if (is_wp_error($response)) {\n prod_trace( 'ERROR', 'Error fetching Google models: ' . $response->get_error_message());\n return $default_model_list;\n }\n\n // Decode the JSON response\n $body = wp_remote_retrieve_body($response);\n $data = json_decode($body, true);\n\n // Check for API errors\n if (isset($data['error'])) {\n // return \"Error: \" . $data['error']['message'];\n // On 1st install needs an API key\n // So return a short list of the base models until an API key is entered\n return $default_model_list;\n }\n\n // Extract the models from the response\n // Google API may return models in different formats\n if (isset($data['models']) && is_array($data['models'])) {\n $models = array_map(function($model) {\n // Google API returns model names as \"models/gemini-pro\" - extract just the model name\n $model_id = $model['name'] ?? $model['displayName'] ?? $model['id'] ?? '';\n // Remove \"models/\" prefix if present\n if (strpos($model_id, 'models/') === 0) {\n $model_id = substr($model_id, 7);\n }\n return array(\n 'id' => $model_id,\n 'object' => 'model',\n 'created' => null,\n 'owned_by' => 'google'\n );\n }, $data['models']);\n } elseif (isset($data['data']) && is_array($data['data'])) {\n $models = array_map(function($model) {\n // Google API returns model names as \"models/gemini-pro\" - extract just the model name\n $model_id = $model['id'] ?? $model['name'] ?? '';\n // Remove \"models/\" prefix if present\n if (strpos($model_id, 'models/') === 0) {\n $model_id = substr($model_id, 7);\n }\n return array(\n 'id' => $model_id,\n 'object' => $model['object'] ?? 'model',\n 'created' => $model['created'] ?? null,\n 'owned_by' => $model['owned_by'] ?? 'google'\n );\n }, $data['data']);\n } else {\n // Handle the case where models are not in expected format\n $models = [];\n prod_trace( 'WARNING', 'Models not found in expected format in Google API response.');\n }\n\n // Ensure $models is an array\n if (!is_array($models) || empty($models)) {\n return $default_model_list;\n } else {\n // Sort the models by name\n usort($models, function($a, $b) {\n return $a['id'] <=> $b['id'];\n });\n }\n\n // Return the list of models\n return $models;\n\n}\n"}, "59557d101e594948af227c78eb676c94ea226503": {"t": 1785756405.8578994, "n": 7173, "h": "c83b8b448370b09e", "c": " 'dall-e-3',\n 'object' => 'model',\n 'created' => 1698785189,\n 'owned_by' => 'system'\n ),\n array(\n 'id' => 'gpt-3.5-turbo',\n 'object' => 'model',\n 'created' => 1677610602,\n 'owned_by' => 'system'\n ),\n array(\n 'id' => 'tts-1-hd',\n 'object' => 'model',\n 'created' => 1699053241,\n 'owned_by' => 'system'\n ),\n array(\n 'id' => 'whisper-1',\n 'object' => 'model',\n 'created' => 1677532384,\n 'owned_by' => 'openai-internal'\n )\n );\n\n // See if the option exists, if not then create it and set the default\n if (get_option('chatbot_chatgpt_model_choice') === false) {\n update_option('chatbot_chatgpt_model_choice', 'gpt-3.5-turbo');\n }\n if (get_option('chatbot_chatgpt_image_model_option') === false) {\n update_option('chatbot_chatgpt_image_model_option', 'dall-e-3');\n }\n if (get_option('chatbot_chatgpt_voice_model_option') === false) {\n update_option('chatbot_chatgpt_voice_model_option', 'tts-1-hd');\n }\n if (get_option('chatbot_chatgpt_whisper_model_option') === false) {\n update_option('chatbot_chatgpt_whisper_model_option', 'whisper-1');\n }\n\n // Check if the API key is empty\n if (empty($api_key)) {\n return $default_model_list;\n }\n\n // Initialize cURL session\n $ch = curl_init();\n\n $openai_models_url = esc_attr(get_option('chatbot_chatgpt_base_url'));\n $openai_models_url = rtrim($openai_models_url, '/') . '/models';\n\n // Set the URL\n curl_setopt($ch, CURLOPT_URL, \"$openai_models_url\");\n\n // Include the headers\n curl_setopt($ch, CURLOPT_HTTPHEADER, array(\n \"Content-Type: application/json\",\n \"Authorization: Bearer \" . $api_key\n ));\n // Return the response as a string instead of directly outputting it\n curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);\n\n // Execute the request and decode the JSON response into an associative array\n $response = curl_exec($ch);\n curl_close($ch);\n\n // Decode the JSON response\n $data = json_decode($response, true);\n\n // Check for API errors\n if (isset($data['error'])) {\n // return \"Error: \" . $data['error']['message'];\n // On 1st install needs an API key\n // So return a short list of the base models until an API key is entered\n return $default_model_list;\n }\n\n // Extract the models from the response\n if (isset($data['data']) && !is_null($data['data'])) {\n $models = $data['data'];\n } else {\n // Handle the case where 'data' is not set or is null\n $models = []; // Empty array\n prod_trace( 'WARNING', 'Data key is not set or is null in the \\$data array.');\n }\n\n // Ensure $models is an array\n if (!is_array($models)) {\n return $default_model_list;\n } else {\n // Sort the models by name\n usort($models, function($a, $b) {\n return $a['id'] <=> $b['id'];\n });\n }\n\n // DIAG - Diagnostics - Ver 2.0.2.1\n // back_trace( 'NOTICE' , '$models: ' . print_r($models, true));\n\n // Return the list of models\n return $models;\n\n}\n\n// Function to get the Model names from NVIDIA API\nfunction chatbot_nvidia_get_models() {\n\n global $session_id;\n global $user_id;\n global $page_id;\n global $thread_id;\n global $assistant_id;\n global $kchat_settings;\n global $additional_instructions;\n global $model;\n global $voice;\n\n global $chatbot_chatgpt_display_style;\n global $chatbot_chatgpt_assistant_alias;\n \n $api_key = '';\n\n // Retrieve the API key\n $api_key = esc_attr(get_option('chatbot_nvidia_api_key'));\n\n // Default model list\n $default_model_list = '';\n $default_model_list = array(\n array(\n 'id' => 'nvidia/llama-3.1-nemotron-51b-instruct',\n 'object' => 'model',\n 'created' => 735790403,\n 'owned_by' => 'nvidia'\n ),\n );\n\n // See if the option exists, if not then create it and set the default\n if (get_option('chatbot_nvidia_model_choice') === false) {\n update_option('chatbot_nvidia_model_choice', 'nvidia/llama-3_1-nemotron-70b-instruct');\n }\n\n // Check if the API key is empty\n if (empty($api_key)) {\n return $default_model_list;\n }\n\n // Initialize cURL session\n $ch = curl_init();\n\n $nvidia_models_url = esc_attr(get_option('chatbot_nvidia_base_url'));\n $nvidia_models_url = rtrim($nvidia_models_url, '/') . '/models';\n\n // Set the URL\n curl_setopt($ch, CURLOPT_URL, \"$nvidia_models_url\");\n // Include the headers\n curl_setopt($ch, CURLOPT_HTTPHEADER, array(\n \"Content-Type: application/json\",\n \"Authorization: Bearer \" . $api_key\n ));\n // Return the response as a string instead of directly outputting it\n curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);\n\n // Execute the request and decode the JSON response into an associative array\n $response = curl_exec($ch);\n curl_close($ch);\n\n // Decode the JSON response\n $data = json_decode($response, true);\n\n // Check for API errors\n if (isset($data['error'])) {\n // return \"Error: \" . $data['error']['message'];\n // On 1st install needs an API key\n // So return a short list of the base models until an API key is entered\n return $default_model_list;\n }\n\n // Extract the models from the response\n if (isset($data['data']) && !is_null($data['data'])) {\n $models = $data['data'];\n } else {\n // Handle the case where 'data' is not set or is null\n $models = []; // Empty array\n prod_trace( 'WARNING', 'Data key is not set or is null in the \\$data array.');\n }\n\n // Ensure $models is an array\n if (!is_array($models)) {\n return $default_model_list;\n } else {\n // Sort the models by name\n usort($models, function($a, $b) {\n return $a['id'] <=> $b['id'];\n });\n }\n\n // DIAG - Diagnostics - Ver 2.0.2.1\n // back_trace( 'NOTICE' , '$models: ' . print_r($models, true));\n\n // Return the list of models\n return $models;\n\n}\n"}, "771d22f58dfb56861b51c8711da96e8daea5b710": {"t": 1785756407.2569654, "n": 3660, "h": "1035e8f139ba8c6e", "c": " 'dall-e-3',\n 'object' => 'model',\n 'created' => 1698785189,\n 'owned_by' => 'system'\n ),\n array(\n 'id' => 'gpt-3.5-turbo',\n 'object' => 'model',\n 'created' => 1677610602,\n 'owned_by' => 'system'\n ),\n array(\n 'id' => 'tts-1-hd',\n 'object' => 'model',\n 'created' => 1699053241,\n 'owned_by' => 'system'\n ),\n array(\n 'id' => 'whisper-1',\n 'object' => 'model',\n 'created' => 1677532384,\n 'owned_by' => 'openai-internal'\n )\n );\n\n // See if the option exists, if not then create it and set the default\n if (get_option('chatbot_chatgpt_model_choice') === false) {\n update_option('chatbot_chatgpt_model_choice', 'gpt-3.5-turbo');\n }\n if (get_option('chatbot_chatgpt_image_model_option') === false) {\n update_option('chatbot_chatgpt_image_model_option', 'dall-e-3');\n }\n if (get_option('chatbot_chatgpt_voice_model_option') === false) {\n update_option('chatbot_chatgpt_voice_model_option', 'tts-1-hd');\n }\n if (get_option('chatbot_chatgpt_whisper_model_option') === false) {\n update_option('chatbot_chatgpt_whisper_model_option', 'whisper-1');\n }\n\n // Check if the API key is empty\n if (empty($api_key)) {\n return $default_model_list;\n }\n\n // Initialize cURL session\n $ch = curl_init();\n\n // Set the URL\n curl_setopt($ch, CURLOPT_URL, \"https://api.openai.com/v1/models\");\n // Include the headers\n curl_setopt($ch, CURLOPT_HTTPHEADER, array(\n \"Content-Type: application/json\",\n \"Authorization: Bearer \" . $api_key\n ));\n // Return the response as a string instead of directly outputting it\n curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);\n\n // Execute the request and decode the JSON response into an associative array\n $response = curl_exec($ch);\n curl_close($ch);\n\n // Decode the JSON response\n $data = json_decode($response, true);\n\n // Check for API errors\n if (isset($data['error'])) {\n // return \"Error: \" . $data['error']['message'];\n // On 1st install needs an API key\n // So return a short list of the base models until an API key is entered\n return $default_model_list;\n }\n\n // Extract the models from the response\n $models = $data['data'];\n\n // Sort the models by name\n usort($models, function($a, $b) {\n return $a['id'] <=> $b['id'];\n });\n\n // DIAG - Diagnostics - Ver 2.0.2.1\n // back_trace( 'NOTICE' , '$models: ' . print_r($models, true));\n\n // Return the list of models\n return $models;\n\n}\n"}, "9243ea9cff42972f09ca18c624e79eb656cce0fd": {"t": 1785756408.581965, "n": 3660, "h": "1035e8f139ba8c6e", "c": " 'dall-e-3',\n 'object' => 'model',\n 'created' => 1698785189,\n 'owned_by' => 'system'\n ),\n array(\n 'id' => 'gpt-3.5-turbo',\n 'object' => 'model',\n 'created' => 1677610602,\n 'owned_by' => 'system'\n ),\n array(\n 'id' => 'tts-1-hd',\n 'object' => 'model',\n 'created' => 1699053241,\n 'owned_by' => 'system'\n ),\n array(\n 'id' => 'whisper-1',\n 'object' => 'model',\n 'created' => 1677532384,\n 'owned_by' => 'openai-internal'\n )\n );\n\n // See if the option exists, if not then create it and set the default\n if (get_option('chatbot_chatgpt_model_choice') === false) {\n update_option('chatbot_chatgpt_model_choice', 'gpt-3.5-turbo');\n }\n if (get_option('chatbot_chatgpt_image_model_option') === false) {\n update_option('chatbot_chatgpt_image_model_option', 'dall-e-3');\n }\n if (get_option('chatbot_chatgpt_voice_model_option') === false) {\n update_option('chatbot_chatgpt_voice_model_option', 'tts-1-hd');\n }\n if (get_option('chatbot_chatgpt_whisper_model_option') === false) {\n update_option('chatbot_chatgpt_whisper_model_option', 'whisper-1');\n }\n\n // Check if the API key is empty\n if (empty($api_key)) {\n return $default_model_list;\n }\n\n // Initialize cURL session\n $ch = curl_init();\n\n // Set the URL\n curl_setopt($ch, CURLOPT_URL, \"https://api.openai.com/v1/models\");\n // Include the headers\n curl_setopt($ch, CURLOPT_HTTPHEADER, array(\n \"Content-Type: application/json\",\n \"Authorization: Bearer \" . $api_key\n ));\n // Return the response as a string instead of directly outputting it\n curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);\n\n // Execute the request and decode the JSON response into an associative array\n $response = curl_exec($ch);\n curl_close($ch);\n\n // Decode the JSON response\n $data = json_decode($response, true);\n\n // Check for API errors\n if (isset($data['error'])) {\n // return \"Error: \" . $data['error']['message'];\n // On 1st install needs an API key\n // So return a short list of the base models until an API key is entered\n return $default_model_list;\n }\n\n // Extract the models from the response\n $models = $data['data'];\n\n // Sort the models by name\n usort($models, function($a, $b) {\n return $a['id'] <=> $b['id'];\n });\n\n // DIAG - Diagnostics - Ver 2.0.2.1\n // back_trace( 'NOTICE' , '$models: ' . print_r($models, true));\n\n // Return the list of models\n return $models;\n\n}\n"}, "53a4485ab6439d52457c55fb665257cade49b168": {"t": 1785756410.9697154, "n": 3660, "h": "1035e8f139ba8c6e", "c": " 'dall-e-3',\n 'object' => 'model',\n 'created' => 1698785189,\n 'owned_by' => 'system'\n ),\n array(\n 'id' => 'gpt-3.5-turbo',\n 'object' => 'model',\n 'created' => 1677610602,\n 'owned_by' => 'system'\n ),\n array(\n 'id' => 'tts-1-hd',\n 'object' => 'model',\n 'created' => 1699053241,\n 'owned_by' => 'system'\n ),\n array(\n 'id' => 'whisper-1',\n 'object' => 'model',\n 'created' => 1677532384,\n 'owned_by' => 'openai-internal'\n )\n );\n\n // See if the option exists, if not then create it and set the default\n if (get_option('chatbot_chatgpt_model_choice') === false) {\n update_option('chatbot_chatgpt_model_choice', 'gpt-3.5-turbo');\n }\n if (get_option('chatbot_chatgpt_image_model_option') === false) {\n update_option('chatbot_chatgpt_image_model_option', 'dall-e-3');\n }\n if (get_option('chatbot_chatgpt_voice_model_option') === false) {\n update_option('chatbot_chatgpt_voice_model_option', 'tts-1-hd');\n }\n if (get_option('chatbot_chatgpt_whisper_model_option') === false) {\n update_option('chatbot_chatgpt_whisper_model_option', 'whisper-1');\n }\n\n // Check if the API key is empty\n if (empty($api_key)) {\n return $default_model_list;\n }\n\n // Initialize cURL session\n $ch = curl_init();\n\n // Set the URL\n curl_setopt($ch, CURLOPT_URL, \"https://api.openai.com/v1/models\");\n // Include the headers\n curl_setopt($ch, CURLOPT_HTTPHEADER, array(\n \"Content-Type: application/json\",\n \"Authorization: Bearer \" . $api_key\n ));\n // Return the response as a string instead of directly outputting it\n curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);\n\n // Execute the request and decode the JSON response into an associative array\n $response = curl_exec($ch);\n curl_close($ch);\n\n // Decode the JSON response\n $data = json_decode($response, true);\n\n // Check for API errors\n if (isset($data['error'])) {\n // return \"Error: \" . $data['error']['message'];\n // On 1st install needs an API key\n // So return a short list of the base models until an API key is entered\n return $default_model_list;\n }\n\n // Extract the models from the response\n $models = $data['data'];\n\n // Sort the models by name\n usort($models, function($a, $b) {\n return $a['id'] <=> $b['id'];\n });\n\n // DIAG - Diagnostics - Ver 2.0.2.1\n // back_trace( 'NOTICE' , '$models: ' . print_r($models, true));\n\n // Return the list of models\n return $models;\n\n}\n"}, "f714b212a9a77bae93a1e7e925a7c263927b9afd": {"t": 1785756412.3993063, "n": 3673, "h": "50df5e3dacc8fc9f", "c": " 'dall-e-3',\n 'object' => 'model',\n 'created' => 1698785189,\n 'owned_by' => 'system'\n ),\n array(\n 'id' => 'gpt-3.5-turbo',\n 'object' => 'model',\n 'created' => 1677610602,\n 'owned_by' => 'system'\n ),\n array(\n 'id' => 'tts-1-1106',\n 'object' => 'model',\n 'created' => 1699053241,\n 'owned_by' => 'system'\n ),\n array(\n 'id' => 'whisper-1',\n 'object' => 'model',\n 'created' => 1677532384,\n 'owned_by' => 'openai-internal'\n )\n );\n\n // See if the option exists, if not then create it and set the default\n if (get_option('chatbot_chatgpt_model_choice') === false) {\n update_option('chatbot_chatgpt_model_choice', 'gpt-3.5-turbo');\n }\n if (get_option('chatbot_chatgpt_image_model_option') === false) {\n update_option('chatbot_chatgpt_image_model_option', 'dall-e-3');\n }\n if (get_option('chatbot_chatgpt_voice_model_option') === false) {\n update_option('chatbot_chatgpt_voice_model_option', 'tts-1-1106');\n }\n if (get_option('chatbot_chatgpt_whisper_model_option') === false) {\n update_option('chatbot_chatgpt_whisper_model_option', 'whisper-1');\n }\n\n // Check if the API key is empty\n if (empty($api_key)) {\n return $default_model_list;\n }\n\n // Initialize cURL session\n $ch = curl_init();\n\n // Set the URL\n curl_setopt($ch, CURLOPT_URL, \"https://api.openai.com/v1/models\");\n // Include the headers\n curl_setopt($ch, CURLOPT_HTTPHEADER, array(\n \"Content-Type: application/json\",\n \"Authorization: Bearer \" . $api_key\n ));\n // Return the response as a string instead of directly outputting it\n curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);\n\n // Execute the request and decode the JSON response into an associative array\n $response = curl_exec($ch);\n curl_close($ch);\n\n // Decode the JSON response\n $data = json_decode($response, true);\n\n // Check for API errors\n if (isset($data['error'])) {\n // return \"Error: \" . $data['error']['message'];\n // On 1st install needs an API key\n // So return a short list of the base models until an API key is entered\n return $default_model_list;\n }\n\n // Extract the models from the response\n $models = $data['data'];\n\n // Sort the models by name\n usort($models, function($a, $b) {\n return $a['id'] <=> $b['id'];\n });\n\n // DIAG - Diagnostics - Ver 2.0.2.1\n // back_trace( 'NOTICE' , '$models: ' . print_r($models, true));\n\n // Return the list of models\n return $models;\n\n}\n"}, "e6670437117240aa1e350cd1eaccbea61c6125d8": {"t": 1785756413.903675, "n": 3674, "h": "e741cc5ed13be071", "c": " 'dall-e-3',\n 'object' => 'model',\n 'created' => 1698785189,\n 'owned_by' => 'system'\n ),\n array(\n 'id' => 'gpt-3.5-turbo',\n 'object' => 'model',\n 'created' => 1677610602,\n 'owned_by' => 'system'\n ),\n array(\n 'id' => 'tts-1-1106',\n 'object' => 'model',\n 'created' => 1699053241,\n 'owned_by' => 'system'\n ),\n array(\n 'id' => 'whisper-1',\n 'object' => 'model',\n 'created' => 1677532384,\n 'owned_by' => 'openai-internal'\n )\n );\n\n // See if the option exists, if not then create it and set the default\n if (get_option('chatbot_chatgpt_model_choice') === false) {\n update_option('chatbot_chatgpt_model_choice', 'gpt-3.5-turbo');\n }\n if (get_option('chatbot_chatgpt_image_model_option') === false) {\n update_option('chatbot_chatgpt_image_model_option', 'dall-e-3');\n }\n if (get_option('chatbot_chatgpt_voice_model_option') === false) {\n update_option('chatbot_chatgpt_voice_model_option', 'tts-1-1106');\n }\n if (get_option('chatbot_chatgpt_whisper_model_option') === false) {\n update_option('chatbot_chatgpt_whisper_model_option', 'whisper-1');\n }\n\n // Check if the API key is empty\n if (empty($api_key)) {\n return $default_model_list;\n }\n\n // Initialize cURL session\n $ch = curl_init();\n\n // Set the URL\n curl_setopt($ch, CURLOPT_URL, \"https://api.openai.com/v1/models\");\n // Include the headers\n curl_setopt($ch, CURLOPT_HTTPHEADER, array(\n \"Content-Type: application/json\",\n \"Authorization: Bearer \" . $api_key\n ));\n // Return the response as a string instead of directly outputting it\n curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);\n\n // Execute the request and decode the JSON response into an associative array\n $response = curl_exec($ch);\n curl_close($ch);\n\n // Decode the JSON response\n $data = json_decode($response, true);\n\n // Check for API errors\n if (isset($data['error'])) {\n // return \"Error: \" . $data['error']['message'];\n // On 1st install needs an API key\n // So return a short list of the base models until an API key is entered\n return $default_model_list;\n }\n\n // Extract the models from the response\n $models = $data['data'];\n\n // Sort the models by name\n usort($models, function($a, $b) {\n return $a['id'] <=> $b['id'];\n });\n\n // DIAG - Diagnostics - Ver 2.0.2.1\n // back_trace ( 'NOTICE' , '$models: ' . print_r($models, true));\n\n // Return the list of models\n return $models;\n\n}\n"}, "052efc504048a4ba155ea15e3a4ab7777b82eeed": {"t": 1785756417.0577564, "n": 3674, "h": "e741cc5ed13be071", "c": " 'dall-e-3',\n 'object' => 'model',\n 'created' => 1698785189,\n 'owned_by' => 'system'\n ),\n array(\n 'id' => 'gpt-3.5-turbo',\n 'object' => 'model',\n 'created' => 1677610602,\n 'owned_by' => 'system'\n ),\n array(\n 'id' => 'tts-1-1106',\n 'object' => 'model',\n 'created' => 1699053241,\n 'owned_by' => 'system'\n ),\n array(\n 'id' => 'whisper-1',\n 'object' => 'model',\n 'created' => 1677532384,\n 'owned_by' => 'openai-internal'\n )\n );\n\n // See if the option exists, if not then create it and set the default\n if (get_option('chatbot_chatgpt_model_choice') === false) {\n update_option('chatbot_chatgpt_model_choice', 'gpt-3.5-turbo');\n }\n if (get_option('chatbot_chatgpt_image_model_option') === false) {\n update_option('chatbot_chatgpt_image_model_option', 'dall-e-3');\n }\n if (get_option('chatbot_chatgpt_voice_model_option') === false) {\n update_option('chatbot_chatgpt_voice_model_option', 'tts-1-1106');\n }\n if (get_option('chatbot_chatgpt_whisper_model_option') === false) {\n update_option('chatbot_chatgpt_whisper_model_option', 'whisper-1');\n }\n\n // Check if the API key is empty\n if (empty($api_key)) {\n return $default_model_list;\n }\n\n // Initialize cURL session\n $ch = curl_init();\n\n // Set the URL\n curl_setopt($ch, CURLOPT_URL, \"https://api.openai.com/v1/models\");\n // Include the headers\n curl_setopt($ch, CURLOPT_HTTPHEADER, array(\n \"Content-Type: application/json\",\n \"Authorization: Bearer \" . $api_key\n ));\n // Return the response as a string instead of directly outputting it\n curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);\n\n // Execute the request and decode the JSON response into an associative array\n $response = curl_exec($ch);\n curl_close($ch);\n\n // Decode the JSON response\n $data = json_decode($response, true);\n\n // Check for API errors\n if (isset($data['error'])) {\n // return \"Error: \" . $data['error']['message'];\n // On 1st install needs an API key\n // So return a short list of the base models until an API key is entered\n return $default_model_list;\n }\n\n // Extract the models from the response\n $models = $data['data'];\n\n // Sort the models by name\n usort($models, function($a, $b) {\n return $a['id'] <=> $b['id'];\n });\n\n // DIAG - Diagnostics - Ver 2.0.2.1\n // back_trace ( 'NOTICE' , '$models: ' . print_r($models, true));\n\n // Return the list of models\n return $models;\n\n}\n"}, "7360609efbfca6902539f38cd3d99864bd62e5e7": {"t": 1785756420.5513616, "n": 2634, "h": "de0b3bb6de9d3d80", "c": " 'dall-e-3',\n 'object' => 'model',\n 'created' => 1698785189,\n 'owned_by' => 'system'\n ),\n array(\n 'id' => 'gpt-4-1106-preview',\n 'object' => 'model',\n 'created' => 1698957206,\n 'owned_by' => 'system'\n ),\n array(\n 'id' => 'tts-1-1106',\n 'object' => 'model',\n 'created' => 1699053241,\n 'owned_by' => 'system'\n )\n );\n\n return $data;\n\n }\n\n // Extract the models from the response\n $models = $data['data'];\n\n // Sort the models by name\n usort($models, function($a, $b) {\n return $a['id'] <=> $b['id'];\n });\n\n // Return the list of models\n return $models;\n\n}\n"}}, "wp-content/plugins/chatbot-chatgpt/chatbot-chatgpt.php": {"de6c3bda23246fe11f7d20255df14f55b5865b77": {"t": 1785745785.7580836, "n": 167437, "h": "8b902d1831b1c4d5", "c": "set_basename( false, __FILE__ );\r\n} else {\r\n /**\r\n * DO NOT REMOVE THIS IF, IT IS ESSENTIAL FOR THE\r\n * `function_exists` CALL ABOVE TO PROPERLY WORK.\r\n */\r\n if ( !function_exists( 'chatbot_chatgpt_freemius' ) ) {\r\n function chatbot_chatgpt_freemius() {\r\n global $chatbot_chatgpt_freemius;\r\n if ( !isset( $chatbot_chatgpt_freemius ) ) {\r\n // Include Freemius SDK\r\n require_once dirname( __FILE__ ) . '/vendor/freemius/start.php';\r\n $chatbot_chatgpt_freemius = fs_dynamic_init( array(\r\n 'id' => '18850',\r\n 'slug' => 'chatbot-chatgpt',\r\n 'type' => 'plugin',\r\n 'public_key' => 'pk_ea667ce516b3acd5d3756a0c2530b',\r\n 'is_premium' => false,\r\n 'premium_suffix' => 'Premium',\r\n 'has_paid_plans' => true,\r\n 'trial' => array(\r\n 'days' => 7,\r\n 'is_require_payment' => false,\r\n ),\r\n 'menu' => array(\r\n 'slug' => 'chatbot-chatgpt',\r\n 'first-path' => 'admin.php?page=chatbot-chatgpt&tab=support',\r\n 'network' => true,\r\n ),\r\n 'is_live' => true,\r\n ) );\r\n }\r\n return $chatbot_chatgpt_freemius;\r\n }\r\n\r\n // Initialize Freemius\r\n chatbot_chatgpt_freemius();\r\n do_action( 'chatbot_chatgpt_freemius_loaded' );\r\n }\r\n // ADD THIS TO THE END OF THE FILE - NOT HERE\r\n // }\r\n // Start output buffering earlier to prevent \"headers already sent\" issues - Ver 2.1.8\r\n ob_start();\r\n // Plugin version\r\n global $chatbot_chatgpt_plugin_version;\r\n $chatbot_chatgpt_plugin_version = '2.4.6';\r\n // Plugin directory path\r\n global $chatbot_chatgpt_plugin_dir_path;\r\n $chatbot_chatgpt_plugin_dir_path = plugin_dir_path( __FILE__ );\r\n // Plugin directory URL\r\n global $chatbot_chatgpt_plugin_dir_url;\r\n $chatbot_chatgpt_plugin_dir_url = plugins_url( '/', __FILE__ );\r\n // Main plugin file pointer (used by vendor-management hooks, etc.)\r\n if ( !defined( 'CHATBOT_CHATGPT_PLUGIN_FILE' ) ) {\r\n define( 'CHATBOT_CHATGPT_PLUGIN_FILE', __FILE__ );\r\n }\r\n // Declare Globals\r\n global $wpdb;\r\n // Uniquely Identify the Visitor\r\n global $session_id;\r\n global $user_id;\r\n // Assign a unique ID to the visitor and logged-in users - Ver 2.0.4\r\n // Ver 2.3.7 - Fixed headers already sent warning by checking if headers can be sent\r\n // Ver 2.4.0 - Added @ operator to suppress warnings as additional safety measure\r\n function kognetiks_assign_unique_id() {\r\n if ( !isset( $_COOKIE['kognetiks_unique_id'] ) ) {\r\n $unique_id = uniqid( 'kognetiks_', true );\r\n // Check if headers have already been sent before trying to set cookie\r\n // Ver 2.3.7 - Prevent \"headers already sent\" warning\r\n // Ver 2.4.0 - Use @ operator to suppress any warnings as additional safety measure\r\n if ( !headers_sent() ) {\r\n // Set a cookie using the built-in setcookie function\r\n // Using @ operator to suppress warnings in case headers are sent between check and setcookie\r\n @setcookie(\r\n 'kognetiks_unique_id',\r\n $unique_id,\r\n time() + 86400 * 30,\r\n \"/\",\r\n \"\",\r\n true,\r\n true\r\n );\r\n // HttpOnly and Secure flags set to true\r\n }\r\n // Ensure the cookie is set for the current request (works even if headers were already sent)\r\n $_COOKIE['kognetiks_unique_id'] = $unique_id;\r\n }\r\n }\r\n\r\n add_action( 'init', 'kognetiks_assign_unique_id', 1 );\r\n // Set higher priority\r\n // Get the unique ID of the visitor or logged-in user - Ver 2.0.4\r\n function kognetiks_get_unique_id() {\r\n if ( isset( $_COOKIE['kognetiks_unique_id'] ) ) {\r\n // back_trace('NOTICE', 'Unique ID found: ' . $_COOKIE['kognetiks_unique_id']);\r\n return sanitize_text_field( $_COOKIE['kognetiks_unique_id'] );\r\n }\r\n // back_trace('NOTICE', 'Unique ID not found');\r\n return null;\r\n }\r\n\r\n // Fetch the User ID - Updated Ver 2.0.6 - 2024 07 11\r\n $user_id = get_current_user_id();\r\n // Fetch the Kognetiks cookie\r\n $session_id = kognetiks_get_unique_id();\r\n if ( empty( $user_id ) || $user_id == 0 ) {\r\n $user_id = $session_id;\r\n }\r\n ob_end_flush();\r\n // End output buffering and send the buffer to the browser\r\n // Include necessary files - Utilities (must be loaded before API files that use them)\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-utilities.php';\r\n // Ver 1.8.6\r\n // Include necessary files - Main files\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-call-anthropic-api.php';\r\n // ANT API - Ver 2.0.7\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-call-azure-openai-api.php';\r\n // Azure OpenAI API - Ver 2.2.6\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-call-azure-api-assistant.php';\r\n // Azure OpenAI Assistants API - Ver 2.2.6\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-call-deepseek-api.php';\r\n // ChatGPT API - Ver 2.2.2\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-call-google-api.php';\r\n // Google API - Ver 2.3.9\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-call-kognetiks-api-mc.php';\r\n // Kognetiks - Markov Chain API - Ver 2.1.6\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-call-kognetiks-api-tm.php';\r\n // Kognetiks - Transformer Model API - Ver 2.2.0\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-call-local-api.php';\r\n // Local API - Ver 2.2.6\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-call-mistral-api.php';\r\n // Mistral API - Ver 2.3.0\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-call-mistral-agent-api.php';\r\n // Mistral Agent API - Ver 2.3.0\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-call-nvidia-api.php';\r\n // NVIDIA API - Ver 2.1.8\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-call-openai-api-assistant.php';\r\n // GPT Assistants - Ver 1.6.9\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-call-openai-api-chatgpt.php';\r\n // ChatGPT API - Ver 1.6.9\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-call-openai-api-image.php';\r\n // Image API - Ver 1.9.4\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-call-openai-api-kflow.php';\r\n // Kognetiks - Flow API - Ver 1.9.5\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-call-openai-api-omni.php';\r\n // ChatGPT API - Ver 2.0.2.1\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-call-openai-api-stt.php';\r\n // STT API - Ver 2.0.1\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-call-openai-api-responses.php';\r\n // OpenAI Responses - Ver 2.4.5\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-call-openai-api-tts.php';\r\n // TTS API - Ver 1.9.4\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-globals.php';\r\n // Globals - Ver 1.6.5\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-shortcode.php';\r\n // Shortcode - Ver 1.6.5\r\n // Include necessary files - Appearance - Ver 1.8.1\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/appearance/chatbot-settings-appearance-body.php';\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/appearance/chatbot-settings-appearance-dimensions.php';\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/appearance/chatbot-settings-appearance-text.php';\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/appearance/chatbot-settings-appearance-user-css.php';\r\n // Include necessary files - Knowledge Navigator\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/knowledge-navigator/chatbot-kn-acquire-controller.php';\r\n // Knowledge Navigator Acquisition - Ver 1.9.6\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/knowledge-navigator/chatbot-kn-acquire-words.php';\r\n // Knowledge Navigator Acquisition - Ver 1.9.6\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/knowledge-navigator/chatbot-kn-analysis.php';\r\n // Knowledge Navigator Analysis- Ver 1.6.2\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/knowledge-navigator/chatbot-kn-db.php';\r\n // Knowledge Navigator - Database Management - Ver 1.6.3\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/knowledge-navigator/chatbot-kn-enhance-context.php';\r\n // Knowledge Navigator - Enhance Context - Ver 1.6.9\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/knowledge-navigator/chatbot-kn-enhance-response.php';\r\n // Knowledge Navigator - TD-IDF Response Enhancement - Ver 1.6.9\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/knowledge-navigator/chatbot-kn-scheduler.php';\r\n // Knowledge Navigator - Scheduler - Ver 1.6.3\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/knowledge-navigator/chatbot-kn-settings.php';\r\n // Knowledge Navigator - Settings - Ver 1.6.1\r\n // Include necessary files - Markov Chain - Ver 2.1.9\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/markov-chain/chatbot-markov-chain-decode.php';\r\n // Functions - Ver 2.1.9\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/markov-chain/chatbot-markov-chain-decode-beaker.php';\r\n // Functions - Ver 2.2.0\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/markov-chain/chatbot-markov-chain-encode.php';\r\n // Functions - Ver 2.1.9\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/markov-chain/chatbot-markov-chain-scheduler.php';\r\n // Functions - Ver 2.1.9\r\n // Include necessary files - Transformer Model - Ver 2.2.0\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/transformers/lexical-context-model.php';\r\n // Functions - Ver 2.2.0\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/transformers/sentential-context-model.php';\r\n // Functions - Ver 2.2.0\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/transformers/transformer-model-scheduler.php';\r\n // Functions - Ver 2.2.0\r\n // Include necessary files - Settings\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-api-anthropic.php';\r\n // Anthropic\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-api-azure-assistants.php';\r\n // Azure Assistants - Ver 2.2.6\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-api-azure.php';\r\n // Azure - Ver 2.2.6\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-api-deepseek.php';\r\n // DeepSeek\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-api-google.php';\r\n // Google - Ver 2.3.9\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-api-nvidia.php';\r\n // NVIDIA\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-api-local.php';\r\n // Local Server - Ver 2.2.6\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-api-mistral-agents.php';\r\n // Mistral Agents - Ver 2.3.0\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-api-mistral.php';\r\n // Mistral\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-api-openai-assistants.php';\r\n // OpenAI ChatGPT\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-api-openai.php';\r\n // OpenAI ChatGPT\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-api-test.php';\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-appearance.php';\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-avatar.php';\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-buttons.php';\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-diagnostics.php';\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-general.php';\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-links.php';\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-localization.php';\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-localize.php';\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-markov-chain.php';\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-menus.php';\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-notices.php';\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-registration-api.php';\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-registration-kn.php';\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-registration.php';\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-reporting.php';\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-support.php';\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-tools.php';\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-transformers.php';\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings.php';\r\n // Include necessary files - Utilities - Ver 1.9.0\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-agents-mistral.php';\r\n // Mistral Agents - Ver 2.3.0\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-api-endpoints.php';\r\n // API Endpoints - Ver 2.2.2\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-assistants.php';\r\n // Assistants Management for OpenAI - Ver 2.0.4\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-assistants-azure.php';\r\n // Assistants Management for Azure - Ver 2.2.6\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-assisted-search.php';\r\n // Assisted Search - Ver 2.2.7 - 2025-03-26\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-conversation-context.php';\r\n // Conversation Context - Ver 2.3.9\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-conversation-digest.php';\r\n // Conversation Digest - Ver 2.3.9\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-conversation-history.php';\r\n // Ver 1.9.2\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-content-search.php';\r\n // Functions - Ver 2.2.4\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/dashboard/chatbot-chatgpt-dashboard-widget.php';\r\n // Dashboard Widget - Ver 2.2.7\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-db-management.php';\r\n // Database Management for Reporting - Ver 1.6.3\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-deactivate.php';\r\n // Deactivation - Ver 1.9.9\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-download-transcript.php';\r\n // Functions - Ver 1.9.9\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-erase-conversation.php';\r\n // Functions - Ver 1.8.6\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-file-download.php';\r\n // Download a file via the API - Ver 2.0.3\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-file-helper.php';\r\n // Functions - Ver 2.0.3\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-file-upload.php';\r\n // Functions - Ver 1.7.6\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-filter-out-html-tags.php';\r\n // Functions - Ver 1.9.6\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-helper-functions.php';\r\n // Functions - Ver 1.0.0\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-keyguard.php';\r\n // Functions - Ver 2.2.6\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-link-and-image-handling.php';\r\n // Globals - Ver 1.9.1\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-models.php';\r\n // Functions - Ver 1.9.4\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-names.php';\r\n // Functions - Ver 1.9.4\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-options-helper.php';\r\n // Functions - Ver 2.0.5\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-threads.php';\r\n // Ver 1.7.2.1\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-transients-file.php';\r\n // Ver 1.9.2\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-transients.php';\r\n // Ver 1.7.2\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-upgrade.php';\r\n // Ver 1.6.7\r\n // chatbot-utilities.php moved above to be loaded before API files - Ver 2.3.9\r\n // chatbot-vendor-management.php loaded at top of file (before Freemius init) - Ver 2.4.4\r\n // Third-party libraries\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/parsedown.php';\r\n // Version 2.0.2.1\r\n // Include necessary files - Tools - Ver 2.0.6\r\n require_once plugin_dir_path( __FILE__ ) . 'tools/chatbot-capability-tester.php';\r\n require_once plugin_dir_path( __FILE__ ) . 'tools/chatbot-manage-error-logs.php';\r\n require_once plugin_dir_path( __FILE__ ) . 'tools/chatbot-options-exporter.php';\r\n require_once plugin_dir_path( __FILE__ ) . 'tools/chatbot-shortcode-tester.php';\r\n require_once plugin_dir_path( __FILE__ ) . 'tools/chatbot-shortcode-tester-tool.php';\r\n // Include necessary files - Insights - Ver 2.3.6\r\n // require_once plugin_dir_path(__FILE__) . 'includes/insights/insights-settings.php';\r\n // require_once plugin_dir_path(__FILE__) . 'includes/insights/chatbot-insights.php';\r\n // require_once plugin_dir_path(__FILE__) . 'includes/insights/languages/en_US.php';\r\n // require_once plugin_dir_path(__FILE__) . 'includes/insights/scoring-models/sentiment-analysis.php';\r\n // require_once plugin_dir_path(__FILE__) . 'includes/insights/utilities.php';\r\n // require_once plugin_dir_path(__FILE__) . 'includes/insights/globals.php';\r\n /**\r\n * Dynamically load Insights files when premium status is detected\r\n * This function can be called on-demand to load Insights files after plan upgrades\r\n * \r\n * NOTE: Uses chatbot_chatgpt_is_premium() which follows Freemius best practices.\r\n * \r\n * @return bool True if files were loaded, false otherwise\r\n * @since 2.4.2\r\n */\r\n function chatbot_chatgpt_load_insights_files() {\r\n // Check if files are already loaded\r\n if ( function_exists( 'kognetiks_insights_settings_page' ) ) {\r\n return true;\r\n }\r\n // Check if user has premium access using the centralized helper function\r\n // This follows Freemius best practices\r\n if ( !function_exists( 'chatbot_chatgpt_is_premium' ) ) {\r\n return false;\r\n }\r\n $has_premium_access = chatbot_chatgpt_is_premium();\r\n // Load files if user has premium access\r\n if ( $has_premium_access ) {\r\n $plugin_dir = plugin_dir_path( __FILE__ );\r\n $insights_files = array(\r\n 'includes/insights/scoring-models/sentiment-analysis.php',\r\n 'includes/insights/automated-emails.php',\r\n 'includes/insights/chatbot-insights.php',\r\n 'includes/insights/globals.php',\r\n 'includes/insights/insights-settings.php',\r\n 'includes/insights/languages/en_US.php',\r\n 'includes/insights/utilities.php'\r\n );\r\n foreach ( $insights_files as $file ) {\r\n $file_path = $plugin_dir . $file;\r\n if ( file_exists( $file_path ) ) {\r\n require_once $file_path;\r\n }\r\n }\r\n // Register admin_init action for period filter if not already registered\r\n if ( !has_action( 'admin_init', 'chatbot_chatgpt_insights_period_filter_handler' ) ) {\r\n add_action( 'admin_init', 'chatbot_chatgpt_insights_period_filter_handler' );\r\n }\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * Handle Insights period filter form submission\r\n * \r\n * @since 2.4.2\r\n */\r\n function chatbot_chatgpt_insights_period_filter_handler() {\r\n 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' ) ) {\r\n // Handle the period filter logic here\r\n $selected_period = ( isset( $_POST['chatbot_chatgpt_insights_period_filter'] ) ? sanitize_text_field( wp_unslash( $_POST['chatbot_chatgpt_insights_period_filter'] ) ) : 'Today' );\r\n // Store in a transient or option, or pass as needed\r\n set_transient( 'chatbot_chatgpt_selected_period', $selected_period, 60 * 5 );\r\n wp_redirect( admin_url( 'admin.php?page=chatbot-chatgpt&tab=insights' ) );\r\n exit;\r\n }\r\n }\r\n\r\n // Include Insights library - Premium Only (at plugin init)\r\n // Check for premium access including trial status (trial users should have premium access)\r\n if ( function_exists( 'chatbot_chatgpt_is_premium' ) && chatbot_chatgpt_is_premium() ) {\r\n chatbot_chatgpt_load_insights_files();\r\n } elseif ( function_exists( 'chatbot_chatgpt_freemius' ) ) {\r\n // Fallback: use same logic as chatbot_chatgpt_is_premium()\r\n $fs = chatbot_chatgpt_freemius();\r\n if ( is_object( $fs ) ) {\r\n // Detect whether we are running inside the premium build\r\n $running_premium_build = false;\r\n if ( method_exists( $fs, 'is__premium_only' ) ) {\r\n $running_premium_build = $fs->is__premium_only();\r\n }\r\n // Check if paying\r\n if ( method_exists( $fs, 'is_paying' ) && $fs->is_paying() ) {\r\n chatbot_chatgpt_load_insights_files();\r\n } elseif ( method_exists( $fs, 'has_active_valid_license' ) && $fs->has_active_valid_license() ) {\r\n chatbot_chatgpt_load_insights_files();\r\n } elseif ( method_exists( $fs, 'is_trial' ) && $fs->is_trial() && $running_premium_build ) {\r\n chatbot_chatgpt_load_insights_files();\r\n }\r\n }\r\n }\r\n // Handle plan changes and premium activation - Ver 2.4.2\r\n // This ensures Insights files are loaded after plan upgrades\r\n add_action( 'fs_after_account_plan_sync_chatbot-chatgpt', function () {\r\n // When plan is synced, try to load Insights files if premium status is detected\r\n chatbot_chatgpt_load_insights_files();\r\n }, 10 );\r\n add_action( 'fs_after_license_change_chatbot-chatgpt', function () {\r\n // When license changes, try to load Insights files if premium status is detected\r\n chatbot_chatgpt_load_insights_files();\r\n }, 10 );\r\n // Also hook into Freemius after_premium_version_activation if available\r\n if ( function_exists( 'chatbot_chatgpt_freemius' ) ) {\r\n chatbot_chatgpt_freemius()->add_action( 'after_premium_version_activation', function () {\r\n chatbot_chatgpt_load_insights_files();\r\n } );\r\n // Uninstall cleanup runs via Freemius after_uninstall so Freemius can report the event (and user feedback) first.\r\n chatbot_chatgpt_freemius()->add_action( 'after_uninstall', 'chatbot_chatgpt_uninstall' );\r\n }\r\n // Include necessary files - Widgets - Ver 2.1.3\r\n require_once plugin_dir_path( __FILE__ ) . 'widgets/chatbot-manage-widget-logs.php';\r\n // Log the User ID and Session ID - Ver 2.0.6 - 2024 07 11\r\n // Check for Upgrades - Ver 1.7.7\r\n if ( !esc_attr( get_option( 'chatbot_chatgpt_upgraded' ) ) ) {\r\n chatbot_chatgpt_upgrade();\r\n update_option( 'chatbot_chatgpt_upgraded', 'Yes' );\r\n }\r\n // Diagnostics on/off setting can be found on the Settings tab - Ver 2.4.5\r\n $chatbot_chatgpt_diagnostics = esc_attr( get_option( 'chatbot_chatgpt_diagnostics', 'Off' ) );\r\n global $chatbot_ai_platform_choice;\r\n global $model;\r\n global $voice;\r\n // FIXME - SEE AI Platform Selection setting - Ver 2.1.8\r\n $chatbot_ai_platform_choice = esc_attr( get_option( 'chatbot_ai_platform_choice', 'OpenAI' ) );\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n // back_trace( 'NOTICE', 'AI Platform: ' . $chatbot_ai_platform_choice);\r\n switch ( $chatbot_ai_platform_choice ) {\r\n case 'OpenAI':\r\n update_option( 'chatbot_ai_platform_choice', 'OpenAI' );\r\n $chatbot_chatgpt_api_enabled = 'Yes';\r\n update_option( 'chatbot_chatgpt_api_enabled', 'Yes' );\r\n $chatbot_azure_api_enabled = 'No';\r\n update_option( 'chatbot_azure_api_enabled', 'No' );\r\n $chatbot_nvidia_api_enabled = 'No';\r\n update_option( 'chatbot_nvidia_api_enabled', 'No' );\r\n $chatbot_anthropic_api_enabled = 'No';\r\n update_option( 'chatbot_anthropic_api_enabled', 'No' );\r\n $chatbot_deepseek_api_enabled = 'No';\r\n update_option( 'chatbot_deepseek_api_enabled', 'No' );\r\n $chatbot_markov_chain_api_enabled = 'No';\r\n update_option( 'chatbot_markov_chain_api_enabled', 'No' );\r\n $chatbot_transformer_model_api_enabled = 'No';\r\n update_option( 'chatbot_transformer_model_api_enabled', 'No' );\r\n $chatbot_local_api_enabled = 'No';\r\n update_option( 'chatbot_local_api_enabled', 'No' );\r\n $chatbot_mistral_api_enabled = 'No';\r\n update_option( 'chatbot_mistral_api_enabled', 'No' );\r\n $chatbot_google_api_enabled = 'No';\r\n update_option( 'chatbot_google_api_enabled', 'No' );\r\n // Model choice - Ver 1.9.4\r\n if ( esc_attr( get_option( 'chatbot_chatgpt_model_choice' ) ) === null ) {\r\n $model = 'gpt-4-1106-preview';\r\n update_option( 'chatbot_chatgpt_model_choice', $model );\r\n } elseif ( empty( $model ) ) {\r\n $model = 'gpt-4-1106-preview';\r\n }\r\n // Voice choice - Ver 1.9.5\r\n if ( esc_attr( get_option( 'chatbot_chatgpt_voice_option' ) ) === null ) {\r\n $voice = 'alloy';\r\n update_option( 'chatbot_chatgpt_voice_option', $voice );\r\n }\r\n break;\r\n case 'Azure OpenAI':\r\n update_option( 'chatbot_ai_platform_choice', 'Azure OpenAI' );\r\n $chatbot_chatgpt_api_enabled = 'No';\r\n update_option( 'chatbot_chatgpt_api_enabled', 'No' );\r\n $chatbot_azure_api_enabled = 'Yes';\r\n update_option( 'chatbot_azure_api_enabled', 'Yes' );\r\n $chatbot_nvidia_api_enabled = 'No';\r\n update_option( 'chatbot_nvidia_api_enabled', 'No' );\r\n $chatbot_anthropic_api_enabled = 'No';\r\n update_option( 'chatbot_anthropic_api_enabled', 'No' );\r\n $chatbot_deepseek_api_enabled = 'No';\r\n update_option( 'chatbot_deepseek_api_enabled', 'No' );\r\n $chatbot_markov_chain_api_enabled = 'No';\r\n update_option( 'chatbot_markov_chain_api_enabled', 'No' );\r\n $chatbot_transformer_model_api_enabled = 'No';\r\n update_option( 'chatbot_transformer_model_api_enabled', 'No' );\r\n $chatbot_local_api_enabled = 'No';\r\n update_option( 'chatbot_local_api_enabled', 'No' );\r\n $chatbot_mistral_api_enabled = 'No';\r\n update_option( 'chatbot_mistral_api_enabled', 'No' );\r\n $chatbot_google_api_enabled = 'No';\r\n update_option( 'chatbot_google_api_enabled', 'No' );\r\n // Model choice - Ver 1.9.4\r\n if ( esc_attr( get_option( 'chatbot_azure_model_choice' ) ) === null ) {\r\n $model = 'gpt-4-1106-preview';\r\n update_option( 'chatbot_azure_model_choice', $model );\r\n } elseif ( empty( $model ) ) {\r\n $model = 'gpt-4-1106-preview';\r\n }\r\n // FIXME - TEMPORARILY DISABLED - 2025-03-07\r\n // Disable Read Aloud - Ver 2.2.6\r\n update_option( 'chatbot_chatgpt_read_aloud_option', 'no' );\r\n // Voice choice - Ver 1.9.5\r\n // if (esc_attr(get_option('chatbot_azure_voice_option')) === null) {\r\n // $voice = 'alloy';\r\n // update_option('chatbot_azure_voice_option', $voice);\r\n // }\r\n break;\r\n case 'NVIDIA':\r\n update_option( 'chatbot_ai_platform_choice', 'NVIDIA' );\r\n $chatbot_chatgpt_api_enabled = 'No';\r\n update_option( 'chatbot_chatgpt_api_enabled', 'No' );\r\n $chatbot_azure_api_enabled = 'No';\r\n update_option( 'chatbot_azure_api_enabled', 'No' );\r\n $chatbot_nvidia_api_enabled = 'Yes';\r\n update_option( 'chatbot_nvidia_api_enabled', 'Yes' );\r\n $chatbot_anthropic_api_enabled = 'No';\r\n update_option( 'chatbot_anthropic_api_enabled', 'No' );\r\n $chatbot_deepseek_api_enabled = 'No';\r\n update_option( 'chatbot_deepseek_api_enabled', 'No' );\r\n $chatbot_markov_chain_api_enabled = 'No';\r\n update_option( 'chatbot_markov_chain_api_enabled', 'No' );\r\n $chatbot_transformer_model_api_enabled = 'No';\r\n update_option( 'chatbot_transformer_model_api_enabled', 'No' );\r\n $chatbot_local_api_enabled = 'No';\r\n update_option( 'chatbot_local_api_enabled', 'No' );\r\n $chatbot_mistral_api_enabled = 'No';\r\n update_option( 'chatbot_mistral_api_enabled', 'No' );\r\n $chatbot_google_api_enabled = 'No';\r\n update_option( 'chatbot_google_api_enabled', 'No' );\r\n // Model choice - Ver 2.1.8\r\n if ( esc_attr( get_option( 'chatbot_nvidia_model_choice' ) ) === null ) {\r\n $model = 'nvidia/llama-3.1-nemotron-51b-instruct';\r\n update_option( 'chatbot_nvidia_model_choice', $model );\r\n } elseif ( empty( $model ) ) {\r\n $model = 'nvidia/llama-3.1-nemotron-51b-instruct';\r\n }\r\n // Disable Read Aloud - Ver 2.2.1\r\n update_option( 'chatbot_chatgpt_read_aloud_option', 'no' );\r\n // Disable File Uploads - Ver 2.2.1\r\n update_option( 'chatbot_chatgpt_allow_file_uploads', 'No' );\r\n // Disable MP3 Uploads - Ver 2.2.1\r\n update_option( 'chatbot_chatgpt_allow_mp3_uploads', 'No' );\r\n break;\r\n case 'Anthropic':\r\n update_option( 'chatbot_ai_platform_choice', 'Anthropic' );\r\n $chatbot_chatgpt_api_enabled = 'No';\r\n update_option( 'chatbot_chatgpt_api_enabled', 'No' );\r\n $chatbot_azure_api_enabled = 'No';\r\n update_option( 'chatbot_azure_api_enabled', 'No' );\r\n $chatbot_nvidia_api_enabled = 'No';\r\n update_option( 'chatbot_nvidia_api_enabled', 'No' );\r\n $chatbot_anthropic_api_enabled = 'Yes';\r\n update_option( 'chatbot_anthropic_api_enabled', 'Yes' );\r\n $chatbot_deepseek_api_enabled = 'No';\r\n update_option( 'chatbot_deepseek_api_enabled', 'No' );\r\n $chatbot_markov_chain_api_enabled = 'No';\r\n update_option( 'chatbot_markov_chain_api_enabled', 'No' );\r\n $chatbot_transformer_model_api_enabled = 'No';\r\n update_option( 'chatbot_transformer_model_api_enabled', 'No' );\r\n $chatbot_local_api_enabled = 'No';\r\n update_option( 'chatbot_local_api_enabled', 'No' );\r\n $chatbot_mistral_api_enabled = 'No';\r\n update_option( 'chatbot_mistral_api_enabled', 'No' );\r\n $chatbot_google_api_enabled = 'No';\r\n update_option( 'chatbot_google_api_enabled', 'No' );\r\n // Model choice - Ver 2.2.1\r\n if ( esc_attr( get_option( 'chatbot_anthropic_model_choice' ) ) === null ) {\r\n $model = 'claude-3-5-sonnet-latest';\r\n update_option( 'chatbot_anthropic_model_choice', $model );\r\n } elseif ( empty( $model ) ) {\r\n $model = 'claude-3-5-sonnet-latest';\r\n }\r\n // Disable Read Aloud - Ver 2.2.1\r\n update_option( 'chatbot_chatgpt_read_aloud_option', 'no' );\r\n // Disable File Uploads - Ver 2.2.1\r\n update_option( 'chatbot_chatgpt_allow_file_uploads', 'No' );\r\n // Disable MP3 Uploads - Ver 2.2.1\r\n update_option( 'chatbot_chatgpt_allow_mp3_uploads', 'No' );\r\n break;\r\n case 'DeepSeek':\r\n update_option( 'chatbot_ai_platform_choice', 'DeepSeek' );\r\n $chatbot_chatgpt_api_enabled = 'No';\r\n update_option( 'chatbot_chatgpt_api_enabled', 'No' );\r\n $chatbot_azure_api_enabled = 'No';\r\n update_option( 'chatbot_azure_api_enabled', 'No' );\r\n $chatbot_nvidia_api_enabled = 'No';\r\n update_option( 'chatbot_nvidia_api_enabled', 'No' );\r\n $chatbot_anthropic_api_enabled = 'No';\r\n update_option( 'chatbot_anthropic_api_enabled', 'No' );\r\n $chatbot_deepseek_api_enabled = 'Yes';\r\n update_option( 'chatbot_deepseek_api_enabled', 'Yes' );\r\n $chatbot_markov_chain_api_enabled = 'No';\r\n update_option( 'chatbot_markov_chain_api_enabled', 'No' );\r\n $chatbot_transformer_model_api_enabled = 'No';\r\n update_option( 'chatbot_transformer_model_api_enabled', 'No' );\r\n $chatbot_local_api_enabled = 'No';\r\n update_option( 'chatbot_local_api_enabled', 'No' );\r\n $chatbot_mistral_api_enabled = 'No';\r\n update_option( 'chatbot_mistral_api_enabled', 'No' );\r\n $chatbot_google_api_enabled = 'No';\r\n update_option( 'chatbot_google_api_enabled', 'No' );\r\n // Model choice - Ver 2.2.1\r\n if ( esc_attr( get_option( 'chatbot_deepseek_model_choice' ) ) === null ) {\r\n $model = 'deepseek-chat';\r\n update_option( 'chatbot_deepseek_model_choice', $model );\r\n } elseif ( empty( $model ) ) {\r\n $model = 'deepseek-chat';\r\n }\r\n // Disable Read Aloud - Ver 2.2.1\r\n update_option( 'chatbot_chatgpt_read_aloud_option', 'no' );\r\n // Disable File Uploads - Ver 2.2.1\r\n update_option( 'chatbot_chatgpt_allow_file_uploads', 'No' );\r\n // Disable MP3 Uploads - Ver 2.2.1\r\n update_option( 'chatbot_chatgpt_allow_mp3_uploads', 'No' );\r\n break;\r\n case 'Mistral':\r\n update_option( 'chatbot_ai_platform_choice', 'Mistral' );\r\n $chatbot_chatgpt_api_enabled = 'No';\r\n update_option( 'chatbot_chatgpt_api_enabled', 'No' );\r\n $chatbot_azure_api_enabled = 'No';\r\n update_option( 'chatbot_azure_api_enabled', 'No' );\r\n $chatbot_nvidia_api_enabled = 'No';\r\n update_option( 'chatbot_nvidia_api_enabled', 'No' );\r\n $chatbot_anthropic_api_enabled = 'No';\r\n update_option( 'chatbot_anthropic_api_enabled', 'No' );\r\n $chatbot_deepseek_api_enabled = 'No';\r\n update_option( 'chatbot_deepseek_api_enabled', 'No' );\r\n $chatbot_markov_chain_api_enabled = 'No';\r\n update_option( 'chatbot_markov_chain_api_enabled', 'No' );\r\n $chatbot_transformer_model_api_enabled = 'No';\r\n update_option( 'chatbot_transformer_model_api_enabled', 'No' );\r\n $chatbot_local_api_enabled = 'No';\r\n update_option( 'chatbot_local_api_enabled', 'No' );\r\n $chatbot_mistral_api_enabled = 'Yes';\r\n update_option( 'chatbot_mistral_api_enabled', 'Yes' );\r\n $chatbot_google_api_enabled = 'No';\r\n update_option( 'chatbot_google_api_enabled', 'No' );\r\n // Model choice - Ver 2.2.1\r\n if ( esc_attr( get_option( 'chatbot_mistral_model_choice' ) ) === null ) {\r\n $model = 'mistral-small-latest';\r\n update_option( 'chatbot_mistral_model_choice', $model );\r\n } elseif ( empty( $model ) ) {\r\n $model = 'mistral-small-latest';\r\n }\r\n // Disable Read Aloud - Ver 2.2.1\r\n update_option( 'chatbot_chatgpt_read_aloud_option', 'no' );\r\n // Disable File Uploads - Ver 2.2.1\r\n update_option( 'chatbot_chatgpt_allow_file_uploads', 'No' );\r\n // Disable MP3 Uploads - Ver 2.2.1\r\n update_option( 'chatbot_chatgpt_allow_mp3_uploads', 'No' );\r\n break;\r\n case 'Google':\r\n update_option( 'chatbot_ai_platform_choice', 'Google' );\r\n $chatbot_chatgpt_api_enabled = 'No';\r\n update_option( 'chatbot_chatgpt_api_enabled', 'No' );\r\n $chatbot_azure_api_enabled = 'No';\r\n update_option( 'chatbot_azure_api_enabled', 'No' );\r\n $chatbot_nvidia_api_enabled = 'No';\r\n update_option( 'chatbot_nvidia_api_enabled', 'No' );\r\n $chatbot_anthropic_api_enabled = 'No';\r\n update_option( 'chatbot_anthropic_api_enabled', 'No' );\r\n $chatbot_deepseek_api_enabled = 'No';\r\n update_option( 'chatbot_deepseek_api_enabled', 'No' );\r\n $chatbot_markov_chain_api_enabled = 'No';\r\n update_option( 'chatbot_markov_chain_api_enabled', 'No' );\r\n $chatbot_transformer_model_api_enabled = 'No';\r\n update_option( 'chatbot_transformer_model_api_enabled', 'No' );\r\n $chatbot_local_api_enabled = 'No';\r\n update_option( 'chatbot_local_api_enabled', 'No' );\r\n $chatbot_mistral_api_enabled = 'No';\r\n update_option( 'chatbot_mistral_api_enabled', 'No' );\r\n $chatbot_google_api_enabled = 'Yes';\r\n update_option( 'chatbot_google_api_enabled', 'Yes' );\r\n // Model choice - Ver 2.3.9\r\n if ( esc_attr( get_option( 'chatbot_google_model_choice' ) ) === null ) {\r\n $model = 'gemini-2.0-flash';\r\n update_option( 'chatbot_google_model_choice', $model );\r\n } elseif ( empty( $model ) ) {\r\n $model = 'gemini-2.0-flash';\r\n }\r\n // Disable Read Aloud - Ver 2.3.9\r\n update_option( 'chatbot_chatgpt_read_aloud_option', 'no' );\r\n // Disable File Uploads - Ver 2.3.9\r\n update_option( 'chatbot_chatgpt_allow_file_uploads', 'No' );\r\n // Disable MP3 Uploads - Ver 2.3.9\r\n update_option( 'chatbot_chatgpt_allow_mp3_uploads', 'No' );\r\n break;\r\n case 'Markov Chain':\r\n update_option( 'chatbot_ai_platform_choice', 'Markov Chain' );\r\n $chatbot_chatgpt_api_enabled = 'No';\r\n update_option( 'chatbot_chatgpt_api_enabled', 'No' );\r\n $chatbot_azure_api_enabled = 'No';\r\n update_option( 'chatbot_azure_api_enabled', 'No' );\r\n $chatbot_nvidia_api_enabled = 'No';\r\n update_option( 'chatbot_nvidia_api_enabled', 'No' );\r\n $chatbot_anthropic_api_enabled = 'No';\r\n update_option( 'chatbot_anthropic_api_enabled', 'No' );\r\n $chatbot_deepseek_api_enabled = 'No';\r\n update_option( 'chatbot_deepseek_api_enabled', 'No' );\r\n $chatbot_markov_chain_api_enabled = 'Yes';\r\n update_option( 'chatbot_markov_chain_api_enabled', 'Yes' );\r\n $chatbot_transformer_model_api_enabled = 'No';\r\n update_option( 'chatbot_transformer_model_api_enabled', 'No' );\r\n $chatbot_local_api_enabled = 'No';\r\n update_option( 'chatbot_local_api_enabled', 'No' );\r\n $chatbot_mistral_api_enabled = 'No';\r\n update_option( 'chatbot_mistral_api_enabled', 'No' );\r\n $chatbot_google_api_enabled = 'No';\r\n update_option( 'chatbot_google_api_enabled', 'No' );\r\n // Model choice - Ver 2.1.8\r\n if ( esc_attr( get_option( 'chatbot_markov_chain_model_choice' ) ) === null ) {\r\n $model = 'markov-chain-flask';\r\n update_option( 'chatbot_markov_chain_model_choice', $model );\r\n } elseif ( empty( $model ) ) {\r\n $model = 'markov-chain-flask';\r\n }\r\n // Disable Read Aloud - Ver 2.2.1\r\n update_option( 'chatbot_chatgpt_read_aloud_option', 'no' );\r\n // Disable File Uploads - Ver 2.2.1\r\n update_option( 'chatbot_chatgpt_allow_file_uploads', 'No' );\r\n // Disable MP3 Uploads - Ver 2.2.1\r\n update_option( 'chatbot_chatgpt_allow_mp3_uploads', 'No' );\r\n break;\r\n case 'Transformer':\r\n update_option( 'chatbot_ai_platform_choice', 'Transformer' );\r\n $chatbot_chatgpt_api_enabled = 'No';\r\n update_option( 'chatbot_chatgpt_api_enabled', 'No' );\r\n $chatbot_azure_api_enabled = 'No';\r\n update_option( 'chatbot_azure_api_enabled', 'No' );\r\n $chatbot_nvidia_api_enabled = 'No';\r\n update_option( 'chatbot_nvidia_api_enabled', 'No' );\r\n $chatbot_anthropic_api_enabled = 'No';\r\n update_option( 'chatbot_anthropic_api_enabled', 'No' );\r\n $chatbot_deepseek_api_enabled = 'No';\r\n update_option( 'chatbot_deepseek_api_enabled', 'No' );\r\n $chatbot_markov_chain_api_enabled = 'No';\r\n update_option( 'chatbot_markov_chain_api_enabled', 'No' );\r\n $chatbot_transformer_model_api_enabled = 'Yes';\r\n update_option( 'chatbot_transformer_model_api_enabled', 'Yes' );\r\n $chatbot_local_api_enabled = 'No';\r\n update_option( 'chatbot_local_api_enabled', 'No' );\r\n $chatbot_mistral_api_enabled = 'No';\r\n update_option( 'chatbot_mistral_api_enabled', 'No' );\r\n $chatbot_google_api_enabled = 'No';\r\n update_option( 'chatbot_google_api_enabled', 'No' );\r\n // Model choice - Ver 2.2.0\r\n if ( esc_attr( get_option( 'chatbot_transformer_model_choice' ) ) === null ) {\r\n $model = 'sentential-context-model';\r\n update_option( 'chatbot_transformer_model_choice', $model );\r\n } elseif ( empty( $model ) ) {\r\n $model = 'sentential-context-model';\r\n }\r\n // Disable Read Aloud - Ver 2.2.1\r\n update_option( 'chatbot_chatgpt_read_aloud_option', 'no' );\r\n // Disable File Uploads - Ver 2.2.1\r\n update_option( 'chatbot_chatgpt_allow_file_uploads', 'No' );\r\n // Disable MP3 Uploads - Ver 2.2.1\r\n update_option( 'chatbot_chatgpt_allow_mp3_uploads', 'No' );\r\n break;\r\n case 'Local Server':\r\n update_option( 'chatbot_ai_platform_choice', 'Local Server' );\r\n $chatbot_chatgpt_api_enabled = 'No';\r\n update_option( 'chatbot_chatgpt_api_enabled', 'No' );\r\n $chatbot_azure_api_enabled = 'No';\r\n update_option( 'chatbot_azure_api_enabled', 'No' );\r\n $chatbot_nvidia_api_enabled = 'No';\r\n update_option( 'chatbot_nvidia_api_enabled', 'No' );\r\n $chatbot_anthropic_api_enabled = 'No';\r\n update_option( 'chatbot_anthropic_api_enabled', 'No' );\r\n $chatbot_deepseek_api_enabled = 'No';\r\n update_option( 'chatbot_deepseek_api_enabled', 'No' );\r\n $chatbot_markov_chain_api_enabled = 'No';\r\n update_option( 'chatbot_markov_chain_api_enabled', 'No' );\r\n $chatbot_transformer_model_api_enabled = 'No';\r\n update_option( 'chatbot_transformer_model_api_enabled', 'No' );\r\n $chatbot_local_api_enabled = 'Yes';\r\n update_option( 'chatbot_local_api_enabled', 'Yes' );\r\n $chatbot_mistral_api_enabled = 'No';\r\n update_option( 'chatbot_mistral_api_enabled', 'No' );\r\n $chatbot_google_api_enabled = 'No';\r\n update_option( 'chatbot_google_api_enabled', 'No' );\r\n // Model choice - Ver 2.2.0\r\n if ( esc_attr( get_option( 'chatbot_local_model_choice' ) ) === null ) {\r\n $model = 'llama3.2-3b-instruct';\r\n update_option( 'chatbot_local_model_choice', $model );\r\n } elseif ( empty( $model ) ) {\r\n $model = 'llama3.2-3b-instruct';\r\n }\r\n // Disable Read Aloud - Ver 2.2.1\r\n update_option( 'chatbot_chatgpt_read_aloud_option', 'no' );\r\n // Disable File Uploads - Ver 2.2.1\r\n update_option( 'chatbot_chatgpt_allow_file_uploads', 'No' );\r\n // Disable MP3 Uploads - Ver 2.2.1\r\n update_option( 'chatbot_chatgpt_allow_mp3_uploads', 'No' );\r\n break;\r\n default:\r\n update_option( 'chatbot_ai_platform_choice', 'OpenAI' );\r\n $chatbot_chatgpt_api_enabled = 'Yes';\r\n update_option( 'chatbot_chatgpt_api_enabled', 'Yes' );\r\n $chatbot_azure_api_enabled = 'No';\r\n update_option( 'chatbot_azure_api_enabled', 'No' );\r\n $chatbot_nvidia_api_enabled = 'No';\r\n update_option( 'chatbot_nvidia_api_enabled', 'No' );\r\n $chatbot_anthropic_api_enabled = 'No';\r\n update_option( 'chatbot_anthropic_api_enabled', 'No' );\r\n $chatbot_deepseek_api_enabled = 'No';\r\n update_option( 'chatbot_deepseek_api_enabled', 'No' );\r\n $chatbot_markov_chain_api_enabled = 'No';\r\n update_option( 'chatbot_markov_chain_api_enabled', 'No' );\r\n $chatbot_transformer_model_api_enabled = 'No';\r\n update_option( 'chatbot_transformer_model_api_enabled', 'No' );\r\n $chatbot_mistral_api_enabled = 'No';\r\n update_option( 'chatbot_mistral_api_enabled', 'No' );\r\n $chatbot_google_api_enabled = 'No';\r\n update_option( 'chatbot_google_api_enabled', 'No' );\r\n // Model choice - Ver 1.9.4\r\n if ( esc_attr( get_option( 'chatbot_chatgpt_model_choice' ) ) === null ) {\r\n $model = 'gpt-4-1106-preview';\r\n update_option( 'chatbot_chatgpt_model_choice', $model );\r\n } elseif ( empty( $model ) ) {\r\n $model = 'gpt-4-1106-preview';\r\n }\r\n // Voice choice - Ver 1.9.5\r\n if ( esc_attr( get_option( 'chatbot_chatgpt_voice_option' ) ) === null ) {\r\n $voice = 'alloy';\r\n update_option( 'chatbot_chatgpt_voice_option', $voice );\r\n }\r\n break;\r\n }\r\n // Custom buttons on/off setting can be found on the Settings tab - Ver 1.6.5\r\n $chatbot_chatgpt_enable_custom_buttons = esc_attr( get_option( 'chatbot_chatgpt_enable_custom_buttons', 'Off' ) );\r\n // Allow file uploads on/off setting can be found on the Settings tab - Ver 1.7.6\r\n global $chatbot_chatgpt_allow_file_uploads;\r\n $chatbot_ai_platform_choice = esc_attr( get_option( 'chatbot_ai_platform_choice', 'OpenAI' ) );\r\n if ( $chatbot_ai_platform_choice == 'OpenAI' ) {\r\n $chatbot_chatgpt_allow_file_uploads = esc_attr( get_option( 'chatbot_chatgpt_allow_file_uploads', 'No' ) );\r\n } elseif ( $chatbot_ai_platform_choice == 'Azure OpenAI' ) {\r\n $chatbot_chatgpt_allow_file_uploads = esc_attr( get_option( 'chatbot_azure_allow_file_uploads', 'No' ) );\r\n } else {\r\n $chatbot_chatgpt_allow_file_uploads = esc_attr( get_option( 'chatbot_chatgpt_allow_file_uploads', 'No' ) );\r\n }\r\n // Suppress Notices on/off setting can be found on the Settings tab - Ver 1.6.5\r\n global $chatbot_chatgpt_suppress_notices;\r\n $chatbot_chatgpt_suppress_notices = esc_attr( get_option( 'chatbot_chatgpt_suppress_notices', 'Off' ) );\r\n // Suppress Attribution on/off setting can be found on the Settings tab - Ver 1.6.5\r\n global $chatbot_chatgpt_suppress_attribution;\r\n $chatbot_chatgpt_suppress_attribution = esc_attr( get_option( 'chatbot_chatgpt_suppress_attribution', 'On' ) );\r\n // Suppress Learnings Message - Ver 1.7.1\r\n global $chatbot_chatgpt_suppress_learnings;\r\n $chatbot_chatgpt_suppress_learnings = esc_attr( get_option( 'chatbot_chatgpt_suppress_learnings', 'Random' ) );\r\n // Context History - Ver 1.6.1\r\n $context_history = [];\r\n function chatbot_chatgpt_enqueue_admin_scripts() {\r\n global $chatbot_chatgpt_plugin_version;\r\n wp_enqueue_script( 'jquery' );\r\n // Ensure jQuery is enqueued\r\n wp_enqueue_script(\r\n 'chatbot_chatgpt_admin',\r\n plugins_url( 'assets/js/chatbot-chatgpt-admin.js', __FILE__ ),\r\n array('jquery'),\r\n $chatbot_chatgpt_plugin_version,\r\n true\r\n );\r\n }\r\n\r\n add_action( 'admin_enqueue_scripts', 'chatbot_chatgpt_enqueue_admin_scripts' );\r\n // Activation, deactivation, and uninstall functions\r\n register_activation_hook( __FILE__, 'chatbot_chatgpt_activate' );\r\n register_activation_hook( __FILE__, 'create_chatbot_chatgpt_assistants_table' );\r\n register_activation_hook( __FILE__, 'create_chatbot_azure_assistants_table' );\r\n register_deactivation_hook( __FILE__, 'chatbot_chatgpt_deactivate' );\r\n // Uninstall cleanup runs via Freemius after_uninstall (see Freemius block above).\r\n // register_uninstall_hook(__FILE__, 'chatbot_chatgpt_uninstall');\r\n add_action(\r\n 'upgrader_process_complete',\r\n 'chatbot_chatgpt_upgrade_completed',\r\n 10,\r\n 2\r\n );\r\n // Enqueue plugin scripts and styles\r\n function chatbot_chatgpt_enqueue_scripts() {\r\n global $chatbot_chatgpt_plugin_dir_url;\r\n global $chatbot_chatgpt_plugin_version;\r\n global $session_id;\r\n global $user_id;\r\n global $page_id;\r\n global $thread_id;\r\n global $assistant_id;\r\n global $kchat_settings;\r\n global $additional_instructions;\r\n global $model;\r\n global $voice;\r\n global $chatbot_chatgpt_display_style;\r\n // Enqueue the styles\r\n wp_enqueue_style( 'dashicons' );\r\n wp_enqueue_style(\r\n 'chatbot-chatgpt-css',\r\n plugins_url( 'assets/css/chatbot-chatgpt.css', __FILE__ ),\r\n array(),\r\n $chatbot_chatgpt_plugin_version,\r\n 'all'\r\n );\r\n // Now override the default styles with the custom styles - Ver 1.8.1\r\n chatbot_chatgpt_appearance_custom_css_settings();\r\n // Enqueue the scripts\r\n wp_enqueue_script( 'jquery' );\r\n wp_enqueue_script(\r\n 'chatbot-chatgpt-js',\r\n plugins_url( 'assets/js/chatbot-chatgpt.js', __FILE__ ),\r\n array('jquery'),\r\n $chatbot_chatgpt_plugin_version,\r\n true\r\n );\r\n // Enqueue DOMPurify - Ver 1.8.1\r\n // https://raw.githubusercontent.com/cure53/DOMPurify/main/dist/purify.min.js\r\n // https://chat.openai.com/c/275770c1-fa72-404b-97c2-2dad2e8a0230\r\n wp_enqueue_script(\r\n 'dompurify',\r\n plugin_dir_url( __FILE__ ) . 'assets/js/purify.min.js',\r\n array(),\r\n $chatbot_chatgpt_plugin_version,\r\n true\r\n );\r\n // Localize the data for user id and page id\r\n $user_id = get_current_user_id();\r\n $page_id = get_the_id();\r\n // Fetch the User ID - Updated Ver 2.0.6 - 2024 07 11\r\n $user_id = get_current_user_id();\r\n // Fetch the Kognetiks cookie\r\n if ( empty( $session_id ) || $session_id == 0 ) {\r\n $session_id = kognetiks_get_unique_id();\r\n }\r\n // $session_id = kognetiks_get_unique_id();\r\n if ( empty( $user_id ) || $user_id == 0 ) {\r\n $user_id = $session_id;\r\n }\r\n // Check if the $kchat_settings array is empty\r\n if ( !$kchat_settings || !is_array( $kchat_settings ) ) {\r\n $kchat_settings = [];\r\n }\r\n // Initial settings\r\n $kchat_settings = array_merge( $kchat_settings, array(\r\n 'user_id' => $user_id,\r\n 'page_id' => $page_id,\r\n 'session_id' => $session_id,\r\n 'thread_id' => $thread_id,\r\n 'assistant_id' => $assistant_id,\r\n 'additional_instructions' => $additional_instructions,\r\n 'model' => $model,\r\n 'voice' => $voice,\r\n 'chatbot_message_nonce' => wp_create_nonce( 'chatbot_message_nonce' ),\r\n 'chatbot_upload_nonce' => wp_create_nonce( 'chatbot_upload_nonce' ),\r\n 'chatbot_erase_nonce' => wp_create_nonce( 'chatbot_erase_nonce' ),\r\n 'chatbot_unlock_nonce' => wp_create_nonce( 'chatbot_unlock_nonce' ),\r\n 'chatbot_reset_nonce' => wp_create_nonce( 'chatbot_reset_nonce' ),\r\n 'chatbot_queue_nonce' => wp_create_nonce( 'chatbot_queue_nonce' ),\r\n 'chatbot_tts_nonce' => wp_create_nonce( 'chatbot_tts_nonce' ),\r\n 'chatbot_transcript_nonce' => wp_create_nonce( 'chatbot_transcript_nonce' ),\r\n 'nonce_timestamp' => time() * 1000,\r\n ) );\r\n // Set visitor and logged in user limits - Ver 2.0.1\r\n if ( is_user_logged_in() ) {\r\n $kchat_settings['chatbot_chatgpt_message_limit_setting'] = esc_attr( get_option( 'chatbot_chatgpt_user_message_limit_setting', '999' ) );\r\n $kchat_settings['chatbot_chatgpt_message_limit_period_setting'] = esc_attr( get_option( 'chatbot_chatgpt_user_message_limit_period_setting', 'Lifetime' ) );\r\n $kchat_settings['chatbot_chatgpt_display_message_count'] = esc_attr( get_option( 'chatbot_chatgpt_display_message_count', 'No' ) );\r\n } else {\r\n $kchat_settings['chatbot_chatgpt_message_limit_setting'] = esc_attr( get_option( 'chatbot_chatgpt_visitor_message_limit_setting', '999' ) );\r\n $kchat_settings['chatbot_chatgpt_message_limit_period_setting'] = esc_attr( get_option( 'chatbot_chatgpt_visitor_message_limit_period_setting', 'Lifetime' ) );\r\n $kchat_settings['chatbot_chatgpt_display_message_count'] = esc_attr( get_option( 'chatbot_chatgpt_display_message_count', 'No' ) );\r\n }\r\n // Localize the data for the chatbot - Ver 2.1.1.1\r\n $kchat_settings = array_merge( $kchat_settings, array(\r\n 'chatbot_chatgpt_display_style' => $chatbot_chatgpt_display_style,\r\n 'chatbot_chatgpt_version' => $chatbot_chatgpt_plugin_version,\r\n 'plugins_url' => $chatbot_chatgpt_plugin_dir_url,\r\n 'ajax_url' => admin_url( 'admin-ajax.php' ),\r\n 'user_id' => $user_id,\r\n 'page_id' => $page_id,\r\n 'session_id' => $session_id,\r\n 'thread_id' => $thread_id,\r\n 'assistant_id' => $assistant_id,\r\n 'additional_instructions' => $additional_instructions,\r\n 'model' => $model,\r\n 'voice' => $voice,\r\n 'chatbot_chatgpt_timeout_setting' => esc_attr( get_option( 'chatbot_chatgpt_timeout_setting', '240' ) ),\r\n 'chatbot_chatgpt_avatar_icon_setting' => esc_attr( get_option( 'chatbot_chatgpt_avatar_icon_setting', '' ) ),\r\n 'chatbot_chatgpt_custom_avatar_icon_setting' => esc_attr( get_option( 'chatbot_chatgpt_custom_avatar_icon_setting', '' ) ),\r\n '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?' ) ),\r\n 'chatbot_chatgpt_force_page_reload' => esc_attr( get_option( 'chatbot_chatgpt_force_page_reload', 'No' ) ),\r\n 'chatbot_chatgpt_custom_error_message' => esc_attr( get_option( 'chatbot_chatgpt_custom_error_message', 'Your custom error message goes here.' ) ),\r\n ) );\r\n $kchat_settings_json = wp_json_encode( $kchat_settings );\r\n // Enqueue the main chatbot script - CHANGED TO LOAD ORDER IN V2.1.2\r\n wp_enqueue_script(\r\n 'chatbot-chatgpt-js',\r\n plugins_url( 'assets/js/chatbot-chatgpt.js', __FILE__ ),\r\n array(),\r\n $chatbot_chatgpt_plugin_version,\r\n true\r\n );\r\n // Add the inline script to define kchat_settings before the main script runs - CHANGED THE LOAD ORDER IN VER 2.1.2\r\n 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' );\r\n // FIXME - REMOVED IN V2.1.2\r\n // 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');\r\n }\r\n\r\n add_action( 'wp_enqueue_scripts', 'chatbot_chatgpt_enqueue_scripts' );\r\n // Enqueue MathJax with custom configuration - Ver 2.1.2\r\n // https://docs.mathjax.org/en/latest/\r\n // https://github.com/mathjax/MathJax/blob/master/LICENSE\r\n // https://cdnjs.cloudflare.com/ajax/libs/mathjax/3.2.0/es5/tex-mml-chtml.js\r\n // https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js\r\n function enqueue_mathjax_with_custom_config() {\r\n // Check to see if MathJax is enabled\r\n if ( esc_attr( get_option( 'chatbot_chatgpt_enable_mathjax', 'Yes' ) ) === 'Yes' ) {\r\n global $chatbot_chatgpt_plugin_version;\r\n global $chatbot_chatgpt_plugin_dir_url;\r\n // Add the MathJax configuration script\r\n $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 \";\r\n // Enqueue the MathJax script\r\n // wp_enqueue_script( 'mathjax', plugin_dir_url(__FILE__) . 'assets/js/tex-chtml.js', array(), $chatbot_chatgpt_plugin_version, true );\r\n wp_enqueue_script(\r\n 'mathjax',\r\n $chatbot_chatgpt_plugin_dir_url . 'assets/js/tex-mml-chtml.js',\r\n array(),\r\n $chatbot_chatgpt_plugin_version,\r\n true\r\n );\r\n // Add the inline script before MathJax script\r\n wp_add_inline_script( 'mathjax', $mathjax_config, 'before' );\r\n }\r\n }\r\n\r\n add_action( 'wp_enqueue_scripts', 'enqueue_mathjax_with_custom_config' );\r\n // CORS - Cross Origin Resource Sharing - CAUTION: This allows all domains to access the end point - Ver 2.1.2\r\n // function allow_cross_domain_requests() {\r\n // header(\"Access-Control-Allow-Origin: *\");\r\n // header(\"Access-Control-Allow-Methods: GET, POST, OPTIONS\");\r\n // header(\"Access-Control-Allow-Headers: X-Requested-With\");\r\n // }\r\n // add_action('init', 'allow_cross_domain_requests');\r\n // Settings and Deactivation Links - Ver - 1.5.0\r\n if ( !function_exists( 'enqueue_jquery_ui' ) ) {\r\n function enqueue_jquery_ui() {\r\n wp_enqueue_style( 'wp-jquery-ui-dialog' );\r\n wp_enqueue_script( 'jquery-ui-dialog' );\r\n }\r\n\r\n add_action( 'admin_enqueue_scripts', 'enqueue_jquery_ui' );\r\n }\r\n // Schedule Cleanup of Expired Transients\r\n if ( !wp_next_scheduled( 'chatbot_chatgpt_cleanup_event' ) ) {\r\n wp_schedule_event( time(), 'daily', 'chatbot_chatgpt_cleanup_event' );\r\n }\r\n add_action( 'chatbot_chatgpt_cleanup_event', 'clean_specific_expired_transients' );\r\n // Schedule Conversation Log Cleanup - Ver 1.6.7\r\n if ( !wp_next_scheduled( 'chatbot_chatgpt_conversation_log_cleanup_event' ) ) {\r\n wp_schedule_event( time(), 'daily', 'chatbot_chatgpt_conversation_log_cleanup_event' );\r\n }\r\n add_action( 'chatbot_chatgpt_conversation_log_cleanup_event', 'chatbot_chatgpt_conversation_log_cleanup' );\r\n // Schedule the transcript file cleanup event if it's not already scheduled - Ver 1.9.9\r\n // Schedule the cleanup event if it's not already scheduled\r\n if ( !wp_next_scheduled( 'chatbot_chatgpt_cleanup_transcript_files' ) ) {\r\n wp_schedule_event( time(), 'hourly', 'chatbot_chatgpt_cleanup_transcript_files' );\r\n }\r\n // Deactivate old hooks - Ver 2.0.1\r\n if ( esc_attr( get_option( 'chatbot_chatgpt_cleanup_old_hooks' ) !== 'Completed' ) ) {\r\n // Deactivate old hooks - Ver 2.0.1\r\n wp_clear_scheduled_hook( 'chatbot_chatgpt_cleanup_transcripts' );\r\n // Then update the option\r\n update_option( 'chatbot_chatgpt_cleanup_old_hooks', 'Completed' );\r\n }\r\n // Schedule the audio file cleanup event if it's not already scheduled - Ver 1.9.9\r\n // Schedule the cleanup event if it's not already scheduled\r\n if ( !wp_next_scheduled( 'chatbot_chatgpt_cleanup_audio_files' ) ) {\r\n wp_schedule_event( time(), 'hourly', 'chatbot_chatgpt_cleanup_audio_files' );\r\n }\r\n // Schedule the upload file cleanup event if it's not already scheduled - Ver 1.9.9\r\n // Schedule the cleanup event if it's not already scheduled\r\n if ( !wp_next_scheduled( 'chatbot_chatgpt_cleanup_upload_files' ) ) {\r\n wp_schedule_event( time(), 'hourly', 'chatbot_chatgpt_cleanup_upload_files' );\r\n }\r\n // Schedule the download file cleanup event if it's not already scheduled - Ver 2.0.3\r\n // Schedule the cleanup event if it's not already scheduled\r\n if ( !wp_next_scheduled( 'chatbot_chatgpt_cleanup_download_files' ) ) {\r\n wp_schedule_event( time(), 'hourly', 'chatbot_chatgpt_cleanup_download_files' );\r\n }\r\n // Add the Opean AI Assistant table to the database - Ver 2.0.4\r\n // REMOVED Ver 2.2.7 and MOVED to the activation hook\r\n // create_chatbot_chatgpt_assistants_table();\r\n // Add the Azure Assistants table to the database - Ver 2.2.6\r\n // REMOVED Ver 2.2.7 and MOVED to the activation hook\r\n // create_chatbot_azure_assistants_table();\r\n // Message Queue Management Functions\r\n function chatbot_chatgpt_enqueue_message(\r\n $user_id,\r\n $page_id,\r\n $session_id,\r\n $assistant_id,\r\n $message,\r\n $client_message_id = null\r\n ) {\r\n $queue_key = 'chatbot_message_queue_' . wp_hash( $assistant_id . '|' . $user_id . '|' . $page_id . '|' . $session_id );\r\n $queue = get_transient( $queue_key );\r\n if ( !$queue ) {\r\n $queue = [];\r\n }\r\n $queue_item = [\r\n 'message' => $message,\r\n 'client_message_id' => ( $client_message_id ?: wp_generate_uuid4() ),\r\n 'timestamp' => time(),\r\n 'user_id' => $user_id,\r\n 'page_id' => $page_id,\r\n 'session_id' => $session_id,\r\n 'assistant_id' => $assistant_id,\r\n ];\r\n $queue[] = $queue_item;\r\n set_transient( $queue_key, $queue, 3600 );\r\n // 1 hour expiry\r\n return $queue_item['client_message_id'];\r\n }\r\n\r\n function chatbot_chatgpt_dequeue_message(\r\n $user_id,\r\n $page_id,\r\n $session_id,\r\n $assistant_id\r\n ) {\r\n $queue_key = 'chatbot_message_queue_' . wp_hash( $assistant_id . '|' . $user_id . '|' . $page_id . '|' . $session_id );\r\n $queue = get_transient( $queue_key );\r\n if ( !$queue || empty( $queue ) ) {\r\n return null;\r\n }\r\n $message = array_shift( $queue );\r\n if ( empty( $queue ) ) {\r\n delete_transient( $queue_key );\r\n } else {\r\n set_transient( $queue_key, $queue, 3600 );\r\n }\r\n return $message;\r\n }\r\n\r\n function chatbot_chatgpt_get_queue_status(\r\n $user_id,\r\n $page_id,\r\n $session_id,\r\n $assistant_id\r\n ) {\r\n $queue_key = 'chatbot_message_queue_' . wp_hash( $assistant_id . '|' . $user_id . '|' . $page_id . '|' . $session_id );\r\n $queue = get_transient( $queue_key );\r\n return [\r\n 'has_messages' => !empty( $queue ),\r\n 'count' => ( $queue ? count( $queue ) : 0 ),\r\n 'next_message' => ( $queue ? $queue[0] : null ),\r\n ];\r\n }\r\n\r\n function chatbot_chatgpt_process_queue(\r\n $user_id,\r\n $page_id,\r\n $session_id,\r\n $assistant_id\r\n ) {\r\n $queue_status = chatbot_chatgpt_get_queue_status(\r\n $user_id,\r\n $page_id,\r\n $session_id,\r\n $assistant_id\r\n );\r\n if ( !$queue_status['has_messages'] ) {\r\n return false;\r\n }\r\n $message_data = chatbot_chatgpt_dequeue_message(\r\n $user_id,\r\n $page_id,\r\n $session_id,\r\n $assistant_id\r\n );\r\n if ( !$message_data ) {\r\n return false;\r\n }\r\n // Set conversation lock for the queued message\r\n $conv_lock = 'chatgpt_conv_lock_' . wp_hash( $assistant_id . '|' . $user_id . '|' . $page_id . '|' . $session_id );\r\n set_transient( $conv_lock, true, 60 );\r\n // Process the message using the existing logic\r\n $response = chatbot_chatgpt_process_queued_message( $message_data );\r\n // Clear conversation lock\r\n delete_transient( $conv_lock );\r\n // Recursively process the next message in queue\r\n chatbot_chatgpt_process_queue(\r\n $user_id,\r\n $page_id,\r\n $session_id,\r\n $assistant_id\r\n );\r\n return true;\r\n }\r\n\r\n // AJAX handler to get queue status\r\n function chatbot_chatgpt_get_queue_status_ajax() {\r\n // Security: Verify nonce for CSRF protection\r\n if ( !isset( $_POST['chatbot_nonce'] ) || !wp_verify_nonce( $_POST['chatbot_nonce'], 'chatbot_queue_nonce' ) ) {\r\n wp_send_json_error( 'Security check failed. Please refresh the page and try again.', 403 );\r\n return;\r\n }\r\n $user_id = sanitize_text_field( $_POST['user_id'] );\r\n $page_id = sanitize_text_field( $_POST['page_id'] );\r\n $session_id = sanitize_text_field( $_POST['session_id'] );\r\n $assistant_id = sanitize_text_field( $_POST['assistant_id'] );\r\n if ( !$user_id || !$page_id || !$session_id || !$assistant_id ) {\r\n wp_send_json_error( 'Missing required parameters' );\r\n return;\r\n }\r\n $queue_status = chatbot_chatgpt_get_queue_status(\r\n $user_id,\r\n $page_id,\r\n $session_id,\r\n $assistant_id\r\n );\r\n wp_send_json_success( $queue_status );\r\n }\r\n\r\n function chatbot_chatgpt_process_queued_message( $message_data ) {\r\n // This function processes a queued message using the same logic as the main handler\r\n // but without the AJAX response handling\r\n global $session_id;\r\n global $user_id;\r\n global $page_id;\r\n global $thread_id;\r\n global $assistant_id;\r\n global $chatbot_chatgpt_assistant_alias;\r\n global $kchat_settings;\r\n global $additional_instructions;\r\n global $model;\r\n global $voice;\r\n global $flow_data;\r\n $api_key = '';\r\n $message = $message_data['message'];\r\n $user_id = $message_data['user_id'];\r\n $page_id = $message_data['page_id'];\r\n $session_id = $message_data['session_id'];\r\n $assistant_id = $message_data['assistant_id'];\r\n $client_message_id = $message_data['client_message_id'];\r\n $chatbot_ai_platform_choice = esc_attr( get_option( 'chatbot_ai_platform_choice', 'OpenAI' ) );\r\n // Get API key and model based on platform choice\r\n switch ( $chatbot_ai_platform_choice ) {\r\n case 'OpenAI':\r\n $api_key = esc_attr( get_option( 'chatbot_chatgpt_api_key' ) );\r\n $api_key = chatbot_chatgpt_decrypt_api_key( $api_key );\r\n $model = esc_attr( get_option( 'chatbot_chatgpt_model_choice', 'gpt-4-1106-preview' ) );\r\n break;\r\n case 'Azure OpenAI':\r\n $api_key = esc_attr( get_option( 'chatbot_azure_api_key' ) );\r\n $api_key = chatbot_chatgpt_decrypt_api_key( $api_key );\r\n $model = esc_attr( get_option( 'chatbot_azure_model_choice', 'gpt-4-1106-preview' ) );\r\n break;\r\n case 'NVIDIA':\r\n $api_key = esc_attr( get_option( 'chatbot_nvidia_api_key' ) );\r\n $api_key = chatbot_chatgpt_decrypt_api_key( $api_key );\r\n $model = esc_attr( get_option( 'chatbot_nvidia_model_choice', 'nvidia/llama-3.1-nemotron-51b-instruct' ) );\r\n break;\r\n case 'Anthropic':\r\n $api_key = esc_attr( get_option( 'chatbot_anthropic_api_key' ) );\r\n $api_key = chatbot_chatgpt_decrypt_api_key( $api_key );\r\n $model = esc_attr( get_option( 'chatbot_anthropic_model_choice', 'claude-3-5-sonnet-latest' ) );\r\n break;\r\n case 'DeepSeek':\r\n $api_key = esc_attr( get_option( 'chatbot_deepseek_api_key' ) );\r\n $api_key = chatbot_chatgpt_decrypt_api_key( $api_key );\r\n $model = esc_attr( get_option( 'chatbot_deepseek_model_choice', 'deepseek-chat' ) );\r\n break;\r\n case 'Google':\r\n $api_key = esc_attr( get_option( 'chatbot_google_api_key' ) );\r\n $api_key = chatbot_chatgpt_decrypt_api_key( $api_key );\r\n $model = esc_attr( get_option( 'chatbot_google_model_choice', 'gemini-2.0-flash' ) );\r\n break;\r\n case 'Markov Chain':\r\n $api_key = esc_attr( get_option( 'chatbot_markov_chain_api_key', 'NOT REQUIRED' ) );\r\n $model = esc_attr( get_option( 'chatbot_markov_chain_model_choice', 'markov-chain-flask' ) );\r\n break;\r\n case 'Transformer':\r\n $api_key = esc_attr( get_option( 'chatbot_transformer_api_key', 'NOT REQUIRED' ) );\r\n $model = esc_attr( get_option( 'chatbot_transformer_model_choice', 'lexical-context-model' ) );\r\n break;\r\n case 'Local Server':\r\n $api_key = esc_attr( get_option( 'chatbot_local_api_key', 'NOT REQUIRED' ) );\r\n $api_key = chatbot_chatgpt_decrypt_api_key( $api_key );\r\n $model = esc_attr( get_option( 'chatbot_local_model_choice', 'llama3.2-3b-instruct' ) );\r\n break;\r\n case 'Mistral':\r\n $api_key = esc_attr( get_option( 'chatbot_mistral_api_key' ) );\r\n $api_key = chatbot_chatgpt_decrypt_api_key( $api_key );\r\n $model = esc_attr( get_option( 'chatbot_mistral_model_choice', 'mistral-small-latest' ) );\r\n break;\r\n default:\r\n $api_key = esc_attr( get_option( 'chatbot_chatgpt_api_key' ) );\r\n $api_key = chatbot_chatgpt_decrypt_api_key( $api_key );\r\n $model = esc_attr( get_option( 'chatbot_chatgpt_model_choice', 'gpt-3.5-turbo' ) );\r\n break;\r\n }\r\n // Retrieve settings from transients (same as main handler) - Ver 2.3.6\r\n $kchat_settings['chatbot_chatgpt_display_style'] = get_chatbot_chatgpt_transients(\r\n 'display_style',\r\n $user_id,\r\n $page_id,\r\n $session_id\r\n );\r\n $kchat_settings['chatbot_chatgpt_assistant_alias'] = get_chatbot_chatgpt_transients(\r\n 'assistant_alias',\r\n $user_id,\r\n $page_id,\r\n $session_id\r\n );\r\n $kchat_settings['assistant_id'] = get_chatbot_chatgpt_transients(\r\n 'assistant_id',\r\n $user_id,\r\n $page_id,\r\n $session_id\r\n );\r\n $kchat_settings['thread_id'] = get_chatbot_chatgpt_transients(\r\n 'thread_id',\r\n $user_id,\r\n $page_id,\r\n $session_id\r\n );\r\n $kchat_settings['chatbot_chatgpt_model'] = get_chatbot_chatgpt_transients(\r\n 'model',\r\n $user_id,\r\n $page_id,\r\n $session_id\r\n );\r\n $kchat_settings['model'] = ( $kchat_settings['chatbot_chatgpt_model'] ?: $model );\r\n $kchat_settings['chatbot_chatgpt_voice_option'] = get_chatbot_chatgpt_transients(\r\n 'voice',\r\n $user_id,\r\n $page_id,\r\n $session_id\r\n );\r\n $kchat_settings['additional_instructions'] = get_chatbot_chatgpt_transients(\r\n 'additional_instructions',\r\n $user_id,\r\n $page_id,\r\n $session_id\r\n );\r\n $voice = $kchat_settings['chatbot_chatgpt_voice_option'];\r\n $model = ( $kchat_settings['model'] ?: $model );\r\n $additional_instructions = $kchat_settings['additional_instructions'];\r\n $chatbot_chatgpt_assistant_alias = $kchat_settings['chatbot_chatgpt_assistant_alias'];\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n // back_trace('NOTICE', '$kchat_settings[\\'chatbot_chatgpt_assistant_alias\\']: ' . $kchat_settings['chatbot_chatgpt_assistant_alias']);\r\n // back_trace('NOTICE', '$kchat_settings[\\'assistant_id\\']: ' . $kchat_settings['assistant_id']);\r\n // Override assistant_id from transient if available - Ver 2.3.6\r\n if ( !empty( $kchat_settings['assistant_id'] ) ) {\r\n $assistant_id = $kchat_settings['assistant_id'];\r\n }\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n // back_trace('NOTICE', '$kchat_settings[\\'chatbot_chatgpt_assistant_alias\\']: ' . $kchat_settings['chatbot_chatgpt_assistant_alias']);\r\n // back_trace('NOTICE', '$kchat_settings[\\'assistant_id\\']: ' . $kchat_settings['assistant_id']);\r\n // back_trace('NOTICE', '$assistant_id: ' . $assistant_id);\r\n // Get thread information\r\n $thread_id = get_chatbot_chatgpt_threads(\r\n $user_id,\r\n $session_id,\r\n $page_id,\r\n $assistant_id\r\n );\r\n // Log the message\r\n append_message_to_conversation_log(\r\n $session_id,\r\n $user_id,\r\n $page_id,\r\n 'Visitor',\r\n $thread_id,\r\n $assistant_id,\r\n null,\r\n $message\r\n );\r\n // Determine whether to use assistant_id or regular ChatGPT API (same logic as main handler) - Ver 2.3.6\r\n // Which Assistant ID to use - Ver 1.7.2\r\n if ( $chatbot_chatgpt_assistant_alias == 'original' ) {\r\n $use_assistant_id = 'No';\r\n } elseif ( $chatbot_chatgpt_assistant_alias == 'primary' ) {\r\n $assistant_id = esc_attr( get_option( 'assistant_id' ) );\r\n $use_assistant_id = 'Yes';\r\n // Check if the GPT Assistant ID is blank, null, or \"Please provide the GPT Assistant ID.\"\r\n if ( empty( $assistant_id ) || $assistant_id == \"Please provide the Assistant Id.\" ) {\r\n // Primary assistant_id not set\r\n $chatbot_chatgpt_assistant_alias = 'original';\r\n $use_assistant_id = 'No';\r\n }\r\n } elseif ( $chatbot_chatgpt_assistant_alias == 'alternate' ) {\r\n $assistant_id = esc_attr( get_option( 'chatbot_chatgpt_assistant_id_alternate' ) );\r\n $use_assistant_id = 'Yes';\r\n // Check if the GPT Assistant ID is blank, null, or \"Please provide the GPT Assistant ID.\"\r\n if ( empty( $assistant_id ) || $assistant_id == \"Please provide the Assistant Id.\" ) {\r\n /// Alternate assistant_id not set\r\n $chatbot_chatgpt_assistant_alias = 'original';\r\n $use_assistant_id = 'No';\r\n }\r\n } elseif ( str_starts_with( $assistant_id, 'asst_' ) ) {\r\n $chatbot_chatgpt_assistant_alias = $assistant_id;\r\n // Belt & Suspenders\r\n $use_assistant_id = 'Yes';\r\n } elseif ( str_starts_with( $assistant_id, 'pmpt_' ) ) {\r\n $chatbot_chatgpt_assistant_alias = $assistant_id;\r\n // Belt & Suspenders\r\n $use_assistant_id = 'Yes';\r\n } elseif ( str_starts_with( $assistant_id, 'ag:' ) ) {\r\n $chatbot_chatgpt_assistant_alias = $assistant_id;\r\n // Belt & Suspenders\r\n $use_assistant_id = 'Yes';\r\n } elseif ( str_starts_with( $assistant_id, 'websearch' ) ) {\r\n $chatbot_chatgpt_assistant_alias = $assistant_id;\r\n // Belt & Suspenders\r\n $use_assistant_id = 'Yes';\r\n } else {\r\n // Reference GPT Assistant IDs directly - Ver 1.7.3\r\n // Check both $chatbot_chatgpt_assistant_alias and $assistant_id - Ver 2.3.6\r\n if ( !empty( $chatbot_chatgpt_assistant_alias ) && (str_starts_with( $chatbot_chatgpt_assistant_alias, 'asst_' ) || str_starts_with( $chatbot_chatgpt_assistant_alias, 'pmpt_' ) || str_starts_with( $chatbot_chatgpt_assistant_alias, 'ag:' ) || str_starts_with( $chatbot_chatgpt_assistant_alias, 'websearch' )) ) {\r\n // Override the $assistant_id with the GPT Assistant ID\r\n $assistant_id = $chatbot_chatgpt_assistant_alias;\r\n $use_assistant_id = 'Yes';\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n // back_trace('NOTICE', 'Using Assistant ID - Ver 2.4.5');\r\n // back_trace('NOTICE', 'Assistant ID: ' . $assistant_id);\r\n // back_trace('NOTICE', 'Use Assistant ID: ' . $use_assistant_id);\r\n // back_trace('NOTICE', 'Chatbot ChatGPT Assistant Alias: ' . $chatbot_chatgpt_assistant_alias);\r\n } elseif ( !empty( $assistant_id ) && (str_starts_with( $assistant_id, 'asst_' ) || str_starts_with( $assistant_id, 'pmpt_' ) || str_starts_with( $assistant_id, 'ag:' ) || str_starts_with( $assistant_id, 'websearch' )) ) {\r\n // Set the alias to match the assistant_id\r\n $chatbot_chatgpt_assistant_alias = $assistant_id;\r\n $use_assistant_id = 'Yes';\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n // back_trace('NOTICE', 'Using Assistant ID - Ver 2.4.5');\r\n // back_trace('NOTICE', 'Assistant ID: ' . $assistant_id);\r\n // back_trace('NOTICE', 'Use Assistant ID: ' . $use_assistant_id);\r\n // back_trace('NOTICE', 'Chatbot ChatGPT Assistant Alias: ' . $chatbot_chatgpt_assistant_alias);\r\n } else {\r\n // Override the $use_assistant_id and set it to 'No'\r\n $use_assistant_id = 'No';\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n // back_trace('NOTICE', 'Using Original Assistant ID - Ver 2.4.5');\r\n // back_trace('NOTICE', 'Assistant ID: ' . $assistant_id);\r\n // back_trace('NOTICE', 'Use Assistant ID: ' . $use_assistant_id);\r\n // back_trace('NOTICE', 'Chatbot ChatGPT Assistant Alias: ' . $chatbot_chatgpt_assistant_alias);\r\n }\r\n }\r\n // Process the message based on platform and use_assistant_id - Ver 2.3.6\r\n // Check if we should use assistant_id or regular API\r\n if ( $use_assistant_id == 'Yes' && $chatbot_ai_platform_choice == 'OpenAI' && str_starts_with( $assistant_id, 'asst_' ) ) {\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n // back_trace('NOTICE', 'Using Assistant ID - Ver 2.4.5');\r\n // back_trace('NOTICE', 'Assistant ID: ' . $assistant_id);\r\n // back_trace('NOTICE', 'Use Assistant ID: ' . $use_assistant_id);\r\n // back_trace('NOTICE', 'Chatbot ChatGPT Assistant Alias: ' . $chatbot_chatgpt_assistant_alias);\r\n $response = chatbot_chatgpt_custom_gpt_call_api(\r\n $api_key,\r\n $message,\r\n $assistant_id,\r\n $thread_id,\r\n $session_id,\r\n $user_id,\r\n $page_id,\r\n $client_message_id\r\n );\r\n } elseif ( $use_assistant_id == 'Yes' && $chatbot_ai_platform_choice == 'OpenAI' && str_starts_with( $assistant_id, 'pmpt_' ) ) {\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n // back_trace('NOTICE', 'Using Prompt ID - Ver 2.4.5');\r\n // back_trace('NOTICE', 'Prompt ID: ' . $assistant_id);\r\n // back_trace('NOTICE', 'Use Assistant ID: ' . $use_assistant_id);\r\n // back_trace('NOTICE', 'Chatbot ChatGPT Assistant Alias: ' . $chatbot_chatgpt_assistant_alias);\r\n $response = chatbot_chatgpt_custom_pmpt_call_api(\r\n $api_key,\r\n $message,\r\n $assistant_id,\r\n $thread_id,\r\n $session_id,\r\n $user_id,\r\n $page_id,\r\n $client_message_id\r\n );\r\n } elseif ( $use_assistant_id == 'Yes' && $chatbot_ai_platform_choice == 'Azure OpenAI' ) {\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n // back_trace('NOTICE', 'Using Azure OpenAI - Ver 2.4.5');\r\n // back_trace('NOTICE', 'Azure OpenAI ID: ' . $assistant_id);\r\n // back_trace('NOTICE', 'Use Assistant ID: ' . $use_assistant_id);\r\n // back_trace('NOTICE', 'Chatbot ChatGPT Assistant Alias: ' . $chatbot_chatgpt_assistant_alias);\r\n $response = chatbot_azure_custom_gpt_call_api(\r\n $api_key,\r\n $message,\r\n $assistant_id,\r\n $thread_id,\r\n $session_id,\r\n $user_id,\r\n $page_id,\r\n $client_message_id\r\n );\r\n } elseif ( $use_assistant_id == 'Yes' && $chatbot_ai_platform_choice == 'Mistral' ) {\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n // back_trace('NOTICE', 'Using Mistral Agent ID - Ver 2.4.5');\r\n // back_trace('NOTICE', 'Mistral Agent ID: ' . $assistant_id);\r\n // back_trace('NOTICE', 'Use Assistant ID: ' . $use_assistant_id);\r\n // back_trace('NOTICE', 'Chatbot ChatGPT Assistant Alias: ' . $chatbot_chatgpt_assistant_alias);\r\n $response = chatbot_mistral_agent_call_api(\r\n $api_key,\r\n $message,\r\n $assistant_id,\r\n $thread_id,\r\n $session_id,\r\n $user_id,\r\n $page_id,\r\n $client_message_id\r\n );\r\n } else {\r\n // Use regular API calls (not assistant_id)\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n // back_trace('NOTICE', 'Using Regular API - Ver 2.4.5');\r\n // back_trace('NOTICE', 'Chatbot AI Platform Choice: ' . $chatbot_ai_platform_choice);\r\n // back_trace('NOTICE', 'Use Assistant ID: ' . $use_assistant_id);\r\n // back_trace('NOTICE', 'Chatbot ChatGPT Assistant Alias: ' . $chatbot_chatgpt_assistant_alias);\r\n switch ( $chatbot_ai_platform_choice ) {\r\n case 'OpenAI':\r\n // Determine which OpenAI API to call based on model\r\n if ( str_starts_with( $model, 'gpt-4o' ) ) {\r\n $response = chatbot_chatgpt_call_omni(\r\n $api_key,\r\n $message,\r\n $user_id,\r\n $page_id,\r\n $session_id,\r\n $assistant_id,\r\n $client_message_id\r\n );\r\n } elseif ( str_starts_with( $model, 'gpt' ) ) {\r\n $response = chatbot_chatgpt_call_api(\r\n $api_key,\r\n $message,\r\n $user_id,\r\n $page_id,\r\n $session_id,\r\n $assistant_id,\r\n $client_message_id\r\n );\r\n } elseif ( str_starts_with( $model, 'dall' ) ) {\r\n $response = chatbot_chatgpt_call_image_api(\r\n $api_key,\r\n $message,\r\n $user_id,\r\n $page_id,\r\n $session_id,\r\n $assistant_id,\r\n $client_message_id\r\n );\r\n } elseif ( str_starts_with( $model, 'tts' ) ) {\r\n $response = chatbot_chatgpt_call_tts_api(\r\n $api_key,\r\n $message,\r\n $voice,\r\n $user_id,\r\n $page_id,\r\n $session_id,\r\n $assistant_id,\r\n $client_message_id\r\n );\r\n } elseif ( str_starts_with( $model, 'whisper' ) ) {\r\n $response = chatbot_chatgpt_call_stt_api( $api_key, $message );\r\n } else {\r\n $response = chatbot_chatgpt_call_api(\r\n $api_key,\r\n $message,\r\n $user_id,\r\n $page_id,\r\n $session_id,\r\n $assistant_id,\r\n $client_message_id\r\n );\r\n }\r\n break;\r\n case 'Azure OpenAI':\r\n $response = chatbot_call_azure_openai_api( $api_key, $message );\r\n break;\r\n case 'NVIDIA':\r\n $response = chatbot_nvidia_call_api( $api_key, $message );\r\n break;\r\n case 'Anthropic':\r\n $response = chatbot_call_anthropic_api( $api_key, $message );\r\n break;\r\n case 'DeepSeek':\r\n $response = chatbot_call_deepseek_api( $api_key, $message );\r\n break;\r\n case 'Google':\r\n $response = chatbot_call_google_api( $api_key, $message );\r\n break;\r\n case 'Markov Chain':\r\n $response = chatbot_chatgpt_call_markov_chain_api( $message );\r\n break;\r\n case 'Transformer':\r\n $response = chatbot_chatgpt_call_transformer_model_api( $message );\r\n break;\r\n case 'Local Server':\r\n $response = chatbot_chatgpt_call_local_model_api( $message );\r\n break;\r\n case 'Mistral':\r\n // If use_assistant_id is No, use regular Mistral API\r\n $response = chatbot_chatgpt_call_mistral_api( $api_key, $message );\r\n break;\r\n default:\r\n $response = chatbot_chatgpt_call_api(\r\n $api_key,\r\n $message,\r\n $user_id,\r\n $page_id,\r\n $session_id,\r\n $assistant_id,\r\n $client_message_id\r\n );\r\n break;\r\n }\r\n }\r\n // Log the response\r\n append_message_to_conversation_log(\r\n $session_id,\r\n $user_id,\r\n $page_id,\r\n 'Chatbot',\r\n $thread_id,\r\n $assistant_id,\r\n null,\r\n $response\r\n );\r\n return $response;\r\n }\r\n\r\n function chatbot_chatgpt_process_single_message( $message_data ) {\r\n // This function contains the core message processing logic\r\n // It's extracted from the main send_message function\r\n global $session_id;\r\n global $user_id;\r\n global $page_id;\r\n global $thread_id;\r\n global $assistant_id;\r\n global $chatbot_chatgpt_assistant_alias;\r\n global $kchat_settings;\r\n global $additional_instructions;\r\n global $model;\r\n global $voice;\r\n global $flow_data;\r\n $api_key = '';\r\n $message = $message_data['message'];\r\n $user_id = $message_data['user_id'];\r\n $page_id = $message_data['page_id'];\r\n $session_id = $message_data['session_id'];\r\n $assistant_id = $message_data['assistant_id'];\r\n $client_message_id = $message_data['client_message_id'];\r\n $chatbot_ai_platform_choice = esc_attr( get_option( 'chatbot_ai_platform_choice', 'OpenAI' ) );\r\n // If your core pipeline expects a nonce in $_POST, we can safely provide one here:\r\n if ( !isset( $_POST['chatbot_nonce'] ) ) {\r\n $_POST['chatbot_nonce'] = wp_create_nonce( 'chatbot_message_nonce' );\r\n }\r\n // IMPORTANT: pass the full array, not just $message\r\n $response = chatbot_chatgpt_send_message( $message_data );\r\n return $response;\r\n }\r\n\r\n // Handle Ajax requests\r\n function chatbot_chatgpt_send_message() {\r\n // Security: Verify nonce for CSRF protection\r\n $nonce_present = isset( $_POST['chatbot_nonce'] );\r\n $nonce_valid = false;\r\n if ( $nonce_present ) {\r\n $nonce_valid = wp_verify_nonce( $_POST['chatbot_nonce'], 'chatbot_message_nonce' );\r\n }\r\n if ( !$nonce_present || !$nonce_valid ) {\r\n // Log the security failure for debugging with more detail\r\n $nonce_status = ( !$nonce_present ? 'missing' : 'invalid' );\r\n $post_data_sanitized = array();\r\n foreach ( $_POST as $key => $value ) {\r\n // Sanitize POST data for logging (exclude sensitive data)\r\n if ( $key !== 'chatbot_nonce' ) {\r\n $post_data_sanitized[$key] = ( is_string( $value ) ? substr( $value, 0, 100 ) : $value );\r\n } else {\r\n $post_data_sanitized[$key] = ( $nonce_present ? ( strlen( $value ) > 0 ? '[present]' : '[empty]' ) : '[missing]' );\r\n }\r\n }\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n prod_trace( 'ERROR', 'Chatbot Security Check Failed - Nonce ' . $nonce_status . '. POST data: ' . print_r( $post_data_sanitized, true ) );\r\n // Enhanced error response with nonce refresh suggestion\r\n wp_send_json_error( array(\r\n 'message' => 'Security check failed. Please refresh the page and try again.',\r\n 'code' => 'nonce_failed',\r\n 'suggestion' => 'refresh_nonce',\r\n 'nonce_status' => $nonce_status,\r\n ), 403 );\r\n return;\r\n }\r\n // Security: Get current user and verify authorization\r\n $current_user = wp_get_current_user();\r\n $current_user_id = $current_user->ID;\r\n // For anonymous users, we need to verify they own the session\r\n if ( $current_user_id === 0 ) {\r\n // Anonymous user - verify session ownership through session_id\r\n if ( !isset( $_POST['session_id'] ) ) {\r\n wp_send_json_error( 'Session ID required for anonymous users.', 403 );\r\n return;\r\n }\r\n $session_id = sanitize_text_field( $_POST['session_id'] );\r\n // Verify the session belongs to the current request\r\n if ( !verify_session_ownership( $session_id ) ) {\r\n // Log the session validation failure for debugging\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n prod_trace( 'ERROR', 'Chatbot Session Validation Failed - Session ID: ' . $session_id . ', Length: ' . strlen( $session_id ) );\r\n wp_send_json_error( 'Unauthorized access to conversation.', 403 );\r\n return;\r\n }\r\n // For anonymous users, user_id should be 0 (session_id is used in transient key via get_chatbot_chatgpt_transients)\r\n $user_id = 0;\r\n // Rate limiting for unauthenticated users to prevent API abuse\r\n $client_ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown';\r\n $rate_limit_key = 'chatbot_rate_limit_' . (( function_exists( 'wp_fast_hash' ) ? wp_fast_hash( $client_ip ) : hash( 'sha256', $client_ip ) ));\r\n // Check rate limit (max 10 requests per minute for unauthenticated users)\r\n $current_count = ( get_transient( $rate_limit_key ) ?: 0 );\r\n if ( $current_count >= 10 ) {\r\n wp_send_json_error( 'Rate limit exceeded. Please wait before sending another message.', 429 );\r\n return;\r\n }\r\n // Increment rate limit counter\r\n set_transient( $rate_limit_key, $current_count + 1, 60 );\r\n // 60 seconds\r\n } else {\r\n // Logged-in user - use their actual user ID\r\n // Get session_id for logged-in users (needed for transient keys) - Ver 2.3.6\r\n if ( !isset( $_POST['session_id'] ) ) {\r\n $session_id = kognetiks_get_unique_id();\r\n } else {\r\n $session_id = sanitize_text_field( $_POST['session_id'] );\r\n }\r\n }\r\n // Global variables\r\n // Fixed Ver 2.3.6: Set global variables AFTER determining the correct values\r\n // This ensures the global $user_id is set correctly for logged-in users\r\n global $session_id;\r\n global $user_id;\r\n global $page_id;\r\n // Set the global $user_id to the correct value (don't let global declaration overwrite it)\r\n if ( $current_user_id === 0 ) {\r\n $user_id = 0;\r\n // Anonymous user\r\n } else {\r\n $user_id = $current_user_id;\r\n // Logged-in user - preserve their WordPress user ID\r\n }\r\n global $thread_id;\r\n global $assistant_id;\r\n global $chatbot_chatgpt_assistant_alias;\r\n global $kchat_settings;\r\n global $additional_instructions;\r\n global $model;\r\n global $voice;\r\n global $flow_data;\r\n $api_key = '';\r\n $chatbot_ai_platform_choice = esc_attr( get_option( 'chatbot_ai_platform_choice', 'OpenAI' ) );\r\n switch ( $chatbot_ai_platform_choice ) {\r\n case 'OpenAI':\r\n $api_key = esc_attr( get_option( 'chatbot_chatgpt_api_key' ) );\r\n // Decrypt the API key - Ver 2.2.6\r\n $api_key = chatbot_chatgpt_decrypt_api_key( $api_key );\r\n $model = esc_attr( get_option( 'chatbot_chatgpt_model_choice', 'gpt-4-1106-preview' ) );\r\n $kchat_settings['chatbot_chatgpt_model'] = $model;\r\n $kchat_settings['model'] = $model;\r\n break;\r\n case 'Azure OpenAI':\r\n $api_key = esc_attr( get_option( 'chatbot_azure_api_key' ) );\r\n // Decrypt the API key - Ver 2.2.6\r\n $api_key = chatbot_chatgpt_decrypt_api_key( $api_key );\r\n $model = esc_attr( get_option( 'chatbot_azure_model_choice', 'gpt-4-1106-preview' ) );\r\n $kchat_settings['chatbot_chatgpt_model'] = $model;\r\n $kchat_settings['model'] = $model;\r\n break;\r\n case 'NVIDIA':\r\n $api_key = esc_attr( get_option( 'chatbot_nvidia_api_key' ) );\r\n $model = esc_attr( get_option( 'chatbot_nvidia_model_choice', 'nvidia/llama-3.1-nemotron-51b-instruct' ) );\r\n // Decrypt the API key - Ver 2.2.6\r\n $api_key = chatbot_chatgpt_decrypt_api_key( $api_key );\r\n $kchat_settings['chatbot_chatgpt_model'] = $model;\r\n $kchat_settings['model'] = $model;\r\n break;\r\n case 'Anthropic':\r\n $api_key = esc_attr( get_option( 'chatbot_anthropic_api_key' ) );\r\n // Decrypt the API key - Ver 2.2.6\r\n $api_key = chatbot_chatgpt_decrypt_api_key( $api_key );\r\n $model = esc_attr( get_option( 'chatbot_anthropic_model_choice', 'claude-3-5-sonnet-latest' ) );\r\n $kchat_settings['chatbot_chatgpt_model'] = $model;\r\n $kchat_settings['model'] = $model;\r\n break;\r\n case 'DeepSeek':\r\n $api_key = esc_attr( get_option( 'chatbot_deepseek_api_key' ) );\r\n // Decrypt the API key - Ver 2.2.6\r\n $api_key = chatbot_chatgpt_decrypt_api_key( $api_key );\r\n $model = esc_attr( get_option( 'chatbot_deepseek_model_choice', 'deepseek-chat' ) );\r\n $kchat_settings['chatbot_chatgpt_model'] = $model;\r\n $kchat_settings['model'] = $model;\r\n break;\r\n case 'Google':\r\n $api_key = esc_attr( get_option( 'chatbot_google_api_key' ) );\r\n // Decrypt the API key - Ver 2.3.9\r\n $api_key = chatbot_chatgpt_decrypt_api_key( $api_key );\r\n $model = esc_attr( get_option( 'chatbot_google_model_choice', 'gemini-2.0-flash' ) );\r\n $kchat_settings['chatbot_chatgpt_model'] = $model;\r\n $kchat_settings['model'] = $model;\r\n break;\r\n case 'Markov Chain':\r\n $api_key = esc_attr( get_option( 'chatbot_markov_chain_api_key', 'NOT REQUIRED' ) );\r\n $model = esc_attr( get_option( 'chatbot_markov_chain_model_choice', 'markov-chain-flask' ) );\r\n $kchat_settings['chatbot_chatgpt_model'] = $model;\r\n $kchat_settings['model'] = $model;\r\n break;\r\n case 'Transformer':\r\n $api_key = esc_attr( get_option( 'chatbot_transformer_api_key', 'NOT REQUIRED' ) );\r\n $model = esc_attr( get_option( 'chatbot_transformer_model_choice', 'lexical-context-model' ) );\r\n $kchat_settings['chatbot_chatgpt_model'] = $model;\r\n $kchat_settings['model'] = $model;\r\n break;\r\n case 'Local Server':\r\n $api_key = esc_attr( get_option( 'chatbot_local_api_key', 'NOT REQUIRED' ) );\r\n // Decrypt the API key - Ver 2.2.6\r\n $api_key = chatbot_chatgpt_decrypt_api_key( $api_key );\r\n $model = esc_attr( get_option( 'chatbot_local_model_choice', 'llama3.2-3b-instruct' ) );\r\n $kchat_settings['chatbot_chatgpt_model'] = $model;\r\n $kchat_settings['model'] = $model;\r\n break;\r\n case 'Mistral':\r\n $api_key = esc_attr( get_option( 'chatbot_mistral_api_key' ) );\r\n // Decrypt the API key - Ver 2.2.6\r\n $api_key = chatbot_chatgpt_decrypt_api_key( $api_key );\r\n $model = esc_attr( get_option( 'chatbot_mistral_model_choice', 'mistral-small-latest' ) );\r\n $kchat_settings['chatbot_chatgpt_model'] = $model;\r\n $kchat_settings['model'] = $model;\r\n break;\r\n default:\r\n $api_key = esc_attr( get_option( 'chatbot_chatgpt_api_key' ) );\r\n // Decrypt the API key - Ver 2.2.6\r\n $api_key = chatbot_chatgpt_decrypt_api_key( $api_key );\r\n $model = esc_attr( get_option( 'chatbot_chatgpt_model_choice', 'gpt-3.5-turbo' ) );\r\n $kchat_settings['chatbot_chatgpt_model'] = $model;\r\n $kchat_settings['model'] = $model;\r\n break;\r\n }\r\n // Send only clean text via the API - Ver 2.3.7\r\n // Validate message exists in POST before sanitizing\r\n if ( !isset( $_POST['message'] ) || empty( $_POST['message'] ) ) {\r\n prod_trace( 'ERROR', 'Chatbot: Message is missing from POST data. POST keys: ' . implode( ', ', array_keys( $_POST ) ) );\r\n global $chatbot_chatgpt_fixed_literal_messages;\r\n $default_message = 'Error: Message is required. Please enter a message and try again.';\r\n $error_message = ( isset( $chatbot_chatgpt_fixed_literal_messages[15] ) ? $chatbot_chatgpt_fixed_literal_messages[15] : $default_message );\r\n wp_send_json_error( $error_message );\r\n return;\r\n }\r\n $message = sanitize_text_field( $_POST['message'] );\r\n // Additional validation - ensure message is not empty after sanitization\r\n if ( empty( trim( $message ) ) ) {\r\n prod_trace( 'ERROR', 'Chatbot: Message is empty after sanitization. Original POST message length: ' . strlen( $_POST['message'] ) );\r\n global $chatbot_chatgpt_fixed_literal_messages;\r\n $default_message = 'Error: Message cannot be empty. Please enter a message and try again.';\r\n $error_message = ( isset( $chatbot_chatgpt_fixed_literal_messages[15] ) ? $chatbot_chatgpt_fixed_literal_messages[15] : $default_message );\r\n wp_send_json_error( $error_message );\r\n return;\r\n }\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n // prod_trace('NOTICE', 'Chatbot: Processing message - Length: ' . strlen($message) . ', First 50 chars: ' . substr($message, 0, 50));\r\n // Get client message ID if provided\r\n $client_message_id = ( isset( $_POST['client_message_id'] ) ? sanitize_text_field( $_POST['client_message_id'] ) : null );\r\n // Check for missing API key or message\r\n // if (!$api_key || !$message) {\r\n if ( !$message ) {\r\n global $chatbot_chatgpt_fixed_literal_messages;\r\n // Define a default fallback message\r\n $default_message = 'Error: Invalid API key or Message. Please check the plugin settings.';\r\n $error_message = ( isset( $chatbot_chatgpt_fixed_literal_messages[15] ) ? $chatbot_chatgpt_fixed_literal_messages[15] : $default_message );\r\n // Send error response\r\n wp_send_json_error( $error_message );\r\n return;\r\n }\r\n // Removed in Ver 1.8.6 - 2024 02 15\r\n // $thread_id = '';\r\n // $assistant_id = '';\r\n // $user_id = '';\r\n // $page_id = '';\r\n // Check the transient for the Assistant ID - Ver 1.7.2\r\n // Security: Get page_id from POST (this is safe as it's just identifying the page)\r\n $page_id = ( isset( $_POST['page_id'] ) ? sanitize_text_field( $_POST['page_id'] ) : '' );\r\n // For logged-in users, session_id should come from the secure session\r\n // For anonymous users, session_id was already validated above\r\n if ( $current_user_id === 0 ) {\r\n // session_id was already validated and set above for anonymous users\r\n // No need to overwrite it\r\n } else {\r\n // For logged-in users, get session_id from POST but validate it\r\n if ( isset( $_POST['session_id'] ) ) {\r\n $session_id = sanitize_text_field( $_POST['session_id'] );\r\n } else {\r\n // Fallback to generating a new session ID\r\n $session_id = kognetiks_get_unique_id();\r\n }\r\n }\r\n // Additional security: Verify the conversation belongs to this user\r\n if ( !verify_conversation_ownership( $user_id, $page_id ) ) {\r\n // Log the conversation ownership validation failure for debugging\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n prod_trace( 'ERROR', 'Chatbot Conversation Ownership Validation Failed - User ID: ' . $user_id . ', Page ID: ' . $page_id );\r\n wp_send_json_error( 'Unauthorized access to conversation.', 403 );\r\n return;\r\n }\r\n $kchat_settings['chatbot_chatgpt_display_style'] = get_chatbot_chatgpt_transients(\r\n 'display_style',\r\n $user_id,\r\n $page_id,\r\n $session_id\r\n );\r\n $kchat_settings['chatbot_chatgpt_assistant_alias'] = get_chatbot_chatgpt_transients(\r\n 'assistant_alias',\r\n $user_id,\r\n $page_id,\r\n $session_id\r\n );\r\n $kchat_settings['assistant_id'] = get_chatbot_chatgpt_transients(\r\n 'assistant_id',\r\n $user_id,\r\n $page_id,\r\n $session_id\r\n );\r\n $kchat_settings['thread_id'] = get_chatbot_chatgpt_transients(\r\n 'thread_id',\r\n $user_id,\r\n $page_id,\r\n $session_id\r\n );\r\n $kchat_settings['chatbot_chatgpt_model'] = get_chatbot_chatgpt_transients(\r\n 'model',\r\n $user_id,\r\n $page_id,\r\n $session_id\r\n );\r\n $kchat_settings['model'] = $kchat_settings['chatbot_chatgpt_model'];\r\n $kchat_settings['chatbot_chatgpt_voice_option'] = get_chatbot_chatgpt_transients(\r\n 'voice',\r\n $user_id,\r\n $page_id,\r\n $session_id\r\n );\r\n $kchat_settings['additional_instructions'] = get_chatbot_chatgpt_transients(\r\n 'additional_instructions',\r\n $user_id,\r\n $page_id,\r\n $session_id\r\n );\r\n $voice = $kchat_settings['chatbot_chatgpt_voice_option'];\r\n $model = $kchat_settings['chatbot_chatgpt_model'];\r\n $additional_instructions = $kchat_settings['additional_instructions'];\r\n $chatbot_chatgpt_assistant_alias = $kchat_settings['chatbot_chatgpt_assistant_alias'];\r\n // Get the thread information - Ver 2.0.7\r\n $thread_id = get_chatbot_chatgpt_threads(\r\n $user_id,\r\n $session_id,\r\n $page_id,\r\n $assistant_id\r\n );\r\n $kchat_settings['thread_id'] = $thread_id;\r\n // $kchat_settings = array_merge($kchat_settings, get_chatbot_chatgpt_threads($user_id, $page_id));\r\n $assistant_id = ( isset( $kchat_settings['assistant_id'] ) ? $kchat_settings['assistant_id'] : '' );\r\n $thread_Id = ( isset( $kchat_settings['thread_id'] ) ? $kchat_settings['thread_id'] : '' );\r\n $model = ( isset( $kchat_settings['chatbot_chatgpt_model'] ) ? $kchat_settings['chatbot_chatgpt_model'] : '' );\r\n $voice = ( isset( $kchat_settings['chatbot_chatgpt_voice_option'] ) ? $kchat_settings['chatbot_chatgpt_voice_option'] : '' );\r\n // Check if there's already a conversation lock (active processing)\r\n $conv_lock = 'chatgpt_conv_lock_' . wp_hash( $assistant_id . '|' . $user_id . '|' . $page_id . '|' . $session_id );\r\n $is_processing = get_transient( $conv_lock );\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n // back_trace('NOTICE', 'Conv Lock: ' . $conv_lock);\r\n // back_trace('NOTICE', 'Is Processing: ' . $is_processing);\r\n // For visitors, add additional lock validation to prevent stuck locks\r\n if ( $is_processing && $current_user_id === 0 ) {\r\n // Check if the lock is older than 2 minutes (120 seconds) - likely stuck\r\n $lock_timeout_key = '_transient_timeout_' . $conv_lock;\r\n $lock_timeout = get_option( $lock_timeout_key );\r\n if ( $lock_timeout && time() - ($lock_timeout - 60) > 120 ) {\r\n // Lock is older than 2 minutes, clear it\r\n delete_transient( $conv_lock );\r\n $is_processing = false;\r\n }\r\n }\r\n if ( $is_processing ) {\r\n // If already processing, enqueue the message\r\n $enqueued_id = chatbot_chatgpt_enqueue_message(\r\n $user_id,\r\n $page_id,\r\n $session_id,\r\n $assistant_id,\r\n $message,\r\n $client_message_id\r\n );\r\n // Return queue status\r\n global $chatbot_chatgpt_fixed_literal_messages;\r\n $default_message = 'Message queued. Processing...';\r\n $queued_message = ( isset( $chatbot_chatgpt_fixed_literal_messages[20] ) ? $chatbot_chatgpt_fixed_literal_messages[20] : $default_message );\r\n wp_send_json_success( [\r\n 'queued' => true,\r\n 'client_message_id' => $enqueued_id,\r\n 'message' => $queued_message,\r\n ] );\r\n }\r\n // Set conversation lock with shorter timeout for visitors to prevent stuck locks\r\n $lock_timeout = ( $current_user_id === 0 ? 30 : 60 );\r\n // 30 seconds for visitors, 60 for logged-in users\r\n set_transient( $conv_lock, true, $lock_timeout );\r\n foreach ( $kchat_settings as $key => $value ) {\r\n }\r\n // Assistants\r\n // $chatbot_chatgpt_assistant_alias == 'original'; // Default\r\n // $chatbot_chatgpt_assistant_alias == 'primary';\r\n // $chatbot_chatgpt_assistant_alias == 'alternate';\r\n // $chatbot_chatgpt_assistant_alias == 'asst_xxxxxxxxxxxxxxxxxxxxxxxx'; // GPT Assistant Id\r\n // $chatbot_chatgpt_assistant_alias == 'pmpt_xxxxxxxxxxxxxxxxxxxxxxxx'; // GPT Prompt Id\r\n // $chatbot_chatgpt_assistant_alias == 'ag:xxxxxxxxxxxxxxxxxxxxxxxx'; // MistralAgent Id\r\n // $chatbot_chatgpt_assistant_alias == 'websearch'; // Mistral Websearch Id\r\n // Which Assistant ID to use - Ver 1.7.2\r\n if ( $chatbot_chatgpt_assistant_alias == 'original' ) {\r\n $use_assistant_id = 'No';\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n // back_trace('NOTICE', 'Using Original Assistant ID - Ver 2.4.5');\r\n // back_trace('NOTICE', 'Original Assistant ID: ' . $assistant_id);\r\n // back_trace('NOTICE', 'Use Assistant ID: ' . $use_assistant_id);\r\n // back_trace('NOTICE', 'Chatbot ChatGPT Assistant Alias: ' . $chatbot_chatgpt_assistant_alias);\r\n } elseif ( $chatbot_chatgpt_assistant_alias == 'primary' ) {\r\n $assistant_id = esc_attr( get_option( 'assistant_id' ) );\r\n $use_assistant_id = 'Yes';\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n // back_trace('NOTICE', 'Using Primary Assistant ID - Ver 2.4.5');\r\n // back_trace('NOTICE', 'Primary Assistant ID: ' . $assistant_id);\r\n // back_trace('NOTICE', 'Use Assistant ID: ' . $use_assistant_id);\r\n // back_trace('NOTICE', 'Chatbot ChatGPT Assistant Alias: ' . $chatbot_chatgpt_assistant_alias);\r\n // Check if the GPT Assistant ID is blank, null, or \"Please provide the GPT Assistant ID.\"\r\n if ( empty( $assistant_id ) || $assistant_id == \"Please provide the Assistant Id.\" ) {\r\n // Primary assistant_id not set\r\n $chatbot_chatgpt_assistant_alias = 'original';\r\n $use_assistant_id = 'No';\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n // back_trace('NOTICE', 'Primary Assistant ID not set - Ver 2.4.5');\r\n // back_trace('NOTICE', 'Primary Assistant ID: ' . $assistant_id);\r\n // back_trace('NOTICE', 'Use Assistant ID: ' . $use_assistant_id);\r\n // back_trace('NOTICE', 'Chatbot ChatGPT Assistant Alias: ' . $chatbot_chatgpt_assistant_alias);\r\n }\r\n } elseif ( $chatbot_chatgpt_assistant_alias == 'alternate' ) {\r\n $assistant_id = esc_attr( get_option( 'chatbot_chatgpt_assistant_id_alternate' ) );\r\n $use_assistant_id = 'Yes';\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n // back_trace('NOTICE', 'Using Alternate Assistant ID - Ver 2.4.5');\r\n // back_trace('NOTICE', 'Alternate Assistant ID: ' . $assistant_id);\r\n // back_trace('NOTICE', 'Use Assistant ID: ' . $use_assistant_id);\r\n // back_trace('NOTICE', 'Chatbot ChatGPT Assistant Alias: ' . $chatbot_chatgpt_assistant_alias);\r\n // Check if the GPT Assistant ID is blank, null, or \"Please provide the GPT Assistant ID.\"\r\n if ( empty( $assistant_id ) || $assistant_id == \"Please provide the Assistant Id.\" ) {\r\n /// Alternate assistant_id not set\r\n $chatbot_chatgpt_assistant_alias = 'original';\r\n $use_assistant_id = 'No';\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n // back_trace('NOTICE', 'Alternate Assistant ID not set - Ver 2.4.5');\r\n // back_trace('NOTICE', 'Alternate Assistant ID: ' . $assistant_id);\r\n // back_trace('NOTICE', 'Use Assistant ID: ' . $use_assistant_id);\r\n // back_trace('NOTICE', 'Chatbot ChatGPT Assistant Alias: ' . $chatbot_chatgpt_assistant_alias);\r\n }\r\n } elseif ( str_starts_with( $assistant_id, 'asst_' ) ) {\r\n $chatbot_chatgpt_assistant_alias = $assistant_id;\r\n // Belt & Suspenders\r\n $use_assistant_id = 'Yes';\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n // back_trace('NOTICE', 'Using Assistant ID - Ver 2.4.5');\r\n // back_trace('NOTICE', 'Assistant ID: ' . $assistant_id);\r\n // back_trace('NOTICE', 'Use Assistant ID: ' . $use_assistant_id);\r\n // back_trace('NOTICE', 'Chatbot ChatGPT Assistant Alias: ' . $chatbot_chatgpt_assistant_alias);\r\n } elseif ( str_starts_with( $assistant_id, 'pmpt_' ) ) {\r\n $chatbot_chatgpt_assistant_alias = $assistant_id;\r\n // Belt & Suspenders\r\n $use_assistant_id = 'Yes';\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n // back_trace('NOTICE', 'Using Prompt ID - Ver 2.4.5');\r\n // back_trace('NOTICE', 'Prompt ID: ' . $assistant_id);\r\n // back_trace('NOTICE', 'Use Assistant ID: ' . $use_assistant_id);\r\n // back_trace('NOTICE', 'Chatbot ChatGPT Assistant Alias: ' . $chatbot_chatgpt_assistant_alias);\r\n } elseif ( str_starts_with( $assistant_id, 'ag:' ) ) {\r\n $chatbot_chatgpt_assistant_alias = $assistant_id;\r\n // Belt & Suspenders\r\n $use_assistant_id = 'Yes';\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n // back_trace('NOTICE', 'Using Mistral Agent ID - Ver 2.4.5');\r\n // back_trace('NOTICE', 'Mistral Agent ID: ' . $assistant_id);\r\n // back_trace('NOTICE', 'Use Assistant ID: ' . $use_assistant_id);\r\n } elseif ( str_starts_with( $assistant_id, 'websearch' ) ) {\r\n $chatbot_chatgpt_assistant_alias = $assistant_id;\r\n // Belt & Suspenders\r\n $use_assistant_id = 'Yes';\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n // back_trace('NOTICE', 'Using Mistral Agent ID - Ver 2.4.5');\r\n // back_trace('NOTICE', 'Mistral Agent ID: ' . $assistant_id);\r\n // back_trace('NOTICE', 'Use Assistant ID: ' . $use_assistant_id);\r\n // back_trace('NOTICE', 'Chatbot ChatGPT Assistant Alias: ' . $chatbot_chatgpt_assistant_alias);\r\n } else {\r\n // Reference GPT Assistant IDs directly - Ver 1.7.3\r\n // Check both $chatbot_chatgpt_assistant_alias and $assistant_id - Ver 2.3.6\r\n 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' ) || str_starts_with( $chatbot_chatgpt_assistant_alias, 'pmpt_' )) ) {\r\n // Override the $assistant_id with the GPT Assistant ID\r\n $assistant_id = $chatbot_chatgpt_assistant_alias;\r\n $use_assistant_id = 'Yes';\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n // back_trace('NOTICE', 'Using Assistant ID - Ver 2.4.5');\r\n // back_trace('NOTICE', 'Assistant ID: ' . $assistant_id);\r\n // back_trace('NOTICE', 'Use Assistant ID: ' . $use_assistant_id);\r\n // back_trace('NOTICE', 'Chatbot ChatGPT Assistant Alias: ' . $chatbot_chatgpt_assistant_alias);\r\n } elseif ( !empty( $assistant_id ) && (str_starts_with( $assistant_id, 'asst_' ) || str_starts_with( $assistant_id, 'ag:' ) || str_starts_with( $assistant_id, 'websearch' ) || str_starts_with( $assistant_id, 'pmpt_' )) ) {\r\n // Set the alias to match the assistant_id\r\n $chatbot_chatgpt_assistant_alias = $assistant_id;\r\n $use_assistant_id = 'Yes';\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n // back_trace('NOTICE', 'Using Assistant ID - Ver 2.4.5');\r\n // back_trace('NOTICE', 'Assistant ID: ' . $assistant_id);\r\n // back_trace('NOTICE', 'Use Assistant ID: ' . $use_assistant_id);\r\n // back_trace('NOTICE', 'Chatbot ChatGPT Assistant Alias: ' . $chatbot_chatgpt_assistant_alias);\r\n } else {\r\n // Override the $use_assistant_id and set it to 'No'\r\n $use_assistant_id = 'No';\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n // back_trace('NOTICE', 'Using Original Assistant ID - Ver 2.4.5');\r\n // back_trace('NOTICE', 'Assistant ID: ' . $assistant_id);\r\n // back_trace('NOTICE', 'Use Assistant ID: ' . $use_assistant_id);\r\n // back_trace('NOTICE', 'Chatbot ChatGPT Assistant Alias: ' . $chatbot_chatgpt_assistant_alias);\r\n }\r\n }\r\n // Get any additional instructions - Ver 2.0.9\r\n $additional_instructions = get_chatbot_chatgpt_transients(\r\n 'additional_instructions',\r\n $user_id,\r\n $page_id,\r\n $session_id\r\n );\r\n // Decide whether to use Flow, Assistant or Original ChatGPT\r\n if ( $model == 'flow' ) {\r\n // Reload the model - BELT & SUSPENDERS\r\n $kchat_settings['model'] = $model;\r\n // Get the step from the transient\r\n $kflow_step = get_chatbot_chatgpt_transients(\r\n 'kflow_step',\r\n null,\r\n null,\r\n $session_id\r\n );\r\n if ( empty( $kflow_step ) ) {\r\n $kflow_step = 0;\r\n // FIXME - Set to 1 or to zero?\r\n }\r\n // $thread_id\r\n $thread_id = '[answer=' . $kflow_step + 1 . ']';\r\n // Add +1 to $kchat_settings['next_step']\r\n $kflow_step = $kflow_step + 1;\r\n // Set the next step\r\n set_chatbot_chatgpt_transients(\r\n 'kflow_step',\r\n $kflow_step,\r\n null,\r\n null,\r\n $session_id\r\n );\r\n $thread_id = get_chatbot_chatgpt_threads(\r\n $user_id,\r\n $session_id,\r\n $page_id,\r\n $assistant_id\r\n );\r\n append_message_to_conversation_log(\r\n $session_id,\r\n $user_id,\r\n $page_id,\r\n 'Visitor',\r\n $thread_id,\r\n $assistant_id,\r\n null,\r\n $message\r\n );\r\n // BELT & SUSPENDERS\r\n $thread_id = '';\r\n // Send message to ChatGPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_call_flow_api( $api_key, $message );\r\n wp_send_json_success( $response );\r\n } elseif ( $use_assistant_id == 'Yes' ) {\r\n $thread_id = get_chatbot_chatgpt_threads(\r\n $user_id,\r\n $session_id,\r\n $page_id,\r\n $assistant_id\r\n );\r\n append_message_to_conversation_log(\r\n $session_id,\r\n $user_id,\r\n $page_id,\r\n 'Visitor',\r\n $thread_id,\r\n $assistant_id,\r\n null,\r\n $message\r\n );\r\n // Send message to Custom GPT API - Ver 1.6.7\r\n $chatbot_ai_platform_choice = esc_attr( get_option( 'chatbot_ai_platform_choice', 'OpenAI' ) );\r\n // Route based on chatbot_ai_platform_choice setting - Ver 2.3.6\r\n if ( $chatbot_ai_platform_choice == 'OpenAI' ) {\r\n // Original Assistant or Prompt\r\n if ( str_starts_with( $assistant_id, 'asst_' ) ) {\r\n $response = chatbot_chatgpt_custom_gpt_call_api(\r\n $api_key,\r\n $message,\r\n $assistant_id,\r\n $thread_id,\r\n $session_id,\r\n $user_id,\r\n $page_id,\r\n $client_message_id\r\n );\r\n } elseif ( str_starts_with( $assistant_id, 'pmpt_' ) ) {\r\n $response = chatbot_chatgpt_custom_pmpt_call_api(\r\n $api_key,\r\n $message,\r\n $assistant_id,\r\n $thread_id,\r\n $session_id,\r\n $user_id,\r\n $page_id,\r\n $client_message_id\r\n );\r\n } else {\r\n return 'ERROR: Invalid Assistant ID';\r\n }\r\n } elseif ( $chatbot_ai_platform_choice == 'Azure OpenAI' ) {\r\n // Send message to Azure Assistant API - Ver 2.2.6\r\n $response = chatbot_azure_custom_gpt_call_api(\r\n $api_key,\r\n $message,\r\n $assistant_id,\r\n $thread_id,\r\n $session_id,\r\n $user_id,\r\n $page_id,\r\n $client_message_id\r\n );\r\n } elseif ( $chatbot_ai_platform_choice == 'Mistral' ) {\r\n // Send message to Mistral Assistant API - Ver 2.2.6\r\n $response = chatbot_mistral_agent_call_api(\r\n $api_key,\r\n $message,\r\n $assistant_id,\r\n $thread_id,\r\n $session_id,\r\n $user_id,\r\n $page_id,\r\n $client_message_id\r\n );\r\n } else {\r\n return 'ERROR: Invalid AI Platform';\r\n }\r\n // Replace \" .\" at the end of $response with \".\"\r\n $response = str_replace( \" .\", \".\", $response );\r\n // Use TF-IDF to enhance response\r\n $chatbot_chatgpt_suppress_learnings = esc_attr( get_option( 'chatbot_chatgpt_suppress_learnings', 'Random' ) );\r\n if ( $chatbot_chatgpt_suppress_learnings != 'None' ) {\r\n $response = $response . '

' . chatbot_chatgpt_enhance_with_tfidf( $message );\r\n }\r\n $thread_id = get_chatbot_chatgpt_threads(\r\n $user_id,\r\n $session_id,\r\n $page_id,\r\n $assistant_id\r\n );\r\n append_message_to_conversation_log(\r\n $session_id,\r\n $user_id,\r\n $page_id,\r\n 'Chatbot',\r\n $thread_id,\r\n $assistant_id,\r\n null,\r\n $response\r\n );\r\n // Clean (erase) the output buffer - Ver 1.6.8\r\n // Check if output buffering is active before attempting to clean it\r\n if ( ob_get_level() > 0 ) {\r\n ob_clean();\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n // back_trace('NOTICE', 'Output buffer cleaned');\r\n } else {\r\n // Optionally start output buffering if needed for your application\r\n // ob_start();\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n // back_trace('NOTICE', 'Output buffer not cleaned');\r\n }\r\n if ( str_starts_with( $response, 'Error:' ) || str_starts_with( $response, 'Failed:' ) ) {\r\n global $chatbot_chatgpt_fixed_literal_messages;\r\n // Define a default fallback message\r\n $default_message = 'Oops! Something went wrong on our end. Please try again later!';\r\n $error_message = ( isset( $chatbot_chatgpt_fixed_literal_messages[0] ) ? $chatbot_chatgpt_fixed_literal_messages[0] : $default_message );\r\n // Send error response\r\n wp_send_json_error( $error_message );\r\n } else {\r\n // Process response for links and images\r\n $response = chatbot_chatgpt_check_for_links_and_images( $response );\r\n // Append any extra message if configured\r\n $extra_message = esc_attr( get_option( 'chatbot_chatgpt_extra_message', '' ) );\r\n $response = chatbot_chatgpt_append_extra_message( $response, $extra_message );\r\n // Clear conversation lock and process queue BEFORE sending response\r\n delete_transient( $conv_lock );\r\n chatbot_chatgpt_process_queue(\r\n $user_id,\r\n $page_id,\r\n $session_id,\r\n $assistant_id\r\n );\r\n // Send success response\r\n wp_send_json_success( $response );\r\n }\r\n } else {\r\n // Belt & Suspenders - Ver 2.1.5.1\r\n if ( !isset( $kchat_settings['model'] ) ) {\r\n $kchat_settings['model'] = $model;\r\n }\r\n $thread_id = get_chatbot_chatgpt_threads(\r\n $user_id,\r\n $session_id,\r\n $page_id,\r\n $assistant_id\r\n );\r\n append_message_to_conversation_log(\r\n $session_id,\r\n $user_id,\r\n $page_id,\r\n 'Visitor',\r\n $thread_id,\r\n $assistant_id,\r\n null,\r\n $message\r\n );\r\n // If $model starts with 'gpt' then the chatbot_chatgpt_call_api or 'dall' then chatbot_chatgpt_call_image_api\r\n // TRY NOT TO FETCH MODEL AGAIN\r\n // $model = esc_attr(get_option('chatbot_chatgpt_model_choice', 'gpt-3.5-turbo'));\r\n $model = ( isset( $kchat_settings['model'] ) ? $kchat_settings['model'] : null );\r\n $voice = ( isset( $kchat_settings['voice'] ) ? $kchat_settings['voice'] : null );\r\n $chatbot_ai_platform_choice = esc_attr( get_option( 'chatbot_ai_platform_choice', 'OpenAI' ) );\r\n switch ( $chatbot_ai_platform_choice ) {\r\n case 'OpenAI':\r\n switch ( $model ) {\r\n case str_starts_with( $model, 'gpt-4o' ):\r\n // The string 'gpt-4o' is found in $model\r\n // Reload the model - BELT & SUSPENDERS\r\n $kchat_settings['model'] = $model;\r\n // Send message to ChatGPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_call_omni(\r\n $api_key,\r\n $message,\r\n $user_id,\r\n $page_id,\r\n $session_id,\r\n $assistant_id,\r\n $client_message_id\r\n );\r\n break;\r\n case str_starts_with( $model, 'gpt' ):\r\n // Reload the model - BELT & SUSPENDERS\r\n $kchat_settings['model'] = $model;\r\n // Send message to ChatGPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_call_api(\r\n $api_key,\r\n $message,\r\n $user_id,\r\n $page_id,\r\n $session_id,\r\n $assistant_id,\r\n $client_message_id\r\n );\r\n break;\r\n case str_starts_with( $model, 'dall' ):\r\n // Reload the model - BELT & SUSPENDERS\r\n $kchat_settings['model'] = $model;\r\n // Send message to Image API - Ver 1.9.4\r\n $response = chatbot_chatgpt_call_image_api(\r\n $api_key,\r\n $message,\r\n $user_id,\r\n $page_id,\r\n $session_id,\r\n $assistant_id,\r\n $client_message_id\r\n );\r\n break;\r\n case str_starts_with( $model, 'tts' ):\r\n // Reload the model - BELT & SUSPENDERS\r\n $kchat_settings['model'] = $model;\r\n $kchat_settings['voice'] = $voice;\r\n // Send message to TTS API - Text-to-speech - Ver 1.9.5\r\n $response = chatbot_chatgpt_call_tts_api(\r\n $api_key,\r\n $message,\r\n $voice,\r\n $user_id,\r\n $page_id,\r\n $session_id,\r\n $assistant_id,\r\n $client_message_id\r\n );\r\n break;\r\n case str_starts_with( $model, 'whisper' ):\r\n // Reload the model - BELT & SUSPENDERS\r\n $kchat_settings['model'] = $model;\r\n // Send message to STT API - Speech-to-text - Ver 1.9.6\r\n $response = chatbot_chatgpt_call_stt_api( $api_key, $message );\r\n break;\r\n }\r\n break;\r\n case 'Azure OpenAI':\r\n $kchat_settings['model'] = $model;\r\n // Send message to Azure OpenAI API - Ver 2.2.6\r\n $response = chatbot_call_azure_openai_api( $api_key, $message );\r\n break;\r\n case 'NVIDIA':\r\n $kchat_settings['model'] = $model;\r\n // Send message to NVIDIA API - Ver 2.1.8\r\n $response = chatbot_nvidia_call_api( $api_key, $message );\r\n break;\r\n case 'Anthropic':\r\n $kchat_settings['model'] = $model;\r\n // Send message to Claude API - Ver 2.1.8\r\n $response = chatbot_call_anthropic_api( $api_key, $message );\r\n break;\r\n case 'DeepSeek':\r\n $kchat_settings['model'] = $model;\r\n // Send message to DeepSeek API - Ver 2.2.2\r\n $response = chatbot_call_deepseek_api( $api_key, $message );\r\n break;\r\n case 'Google':\r\n $kchat_settings['model'] = $model;\r\n // Send message to Google API - Ver 2.3.9\r\n $response = chatbot_call_google_api( $api_key, $message );\r\n break;\r\n case 'Mistral':\r\n $kchat_settings['model'] = $model;\r\n // Send message to Mistral API - Ver 2.3.0\r\n $response = chatbot_chatgpt_call_mistral_api( $api_key, $message );\r\n break;\r\n case 'Markov Chain':\r\n $kchat_settings['model'] = $model;\r\n // Send message to Markov API - Ver 1.9.7\r\n $response = chatbot_chatgpt_call_markov_chain_api( $message );\r\n break;\r\n case 'Transformer':\r\n $kchat_settings['model'] = $model;\r\n // Send message to Transformer Model API - Ver 2.2.0\r\n $response = chatbot_chatgpt_call_transformer_model_api( $message );\r\n break;\r\n case 'Local Server':\r\n $kchat_settings['model'] = $model;\r\n // Send message to Local Model API - Ver 2.2.6\r\n $response = chatbot_chatgpt_call_local_model_api( $message );\r\n break;\r\n default:\r\n $kchat_settings['model'] = $model;\r\n // Send message to ChatGPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_call_api( $api_key, $message );\r\n }\r\n // Defensive programming - Ver 2.2.9\r\n if ( is_array( $response ) ) {\r\n if ( isset( $response['response'] ) ) {\r\n // Likely nested from a mistake — pull the actual content out\r\n $response = $response['response'];\r\n } else {\r\n // Fallback: flatten it all into a string just to be safe\r\n $response = print_r( $response, true );\r\n }\r\n }\r\n // Use TF-IDF to enhance response\r\n $chatbot_chatgpt_suppress_learnings = esc_attr( get_option( 'chatbot_chatgpt_suppress_learnings', 'Random' ) );\r\n if ( $chatbot_chatgpt_suppress_learnings != 'None' ) {\r\n $response = $response . '

' . chatbot_chatgpt_enhance_with_tfidf( $message );\r\n }\r\n $thread_id = get_chatbot_chatgpt_threads(\r\n $user_id,\r\n $session_id,\r\n $page_id,\r\n $assistant_id\r\n );\r\n append_message_to_conversation_log(\r\n $session_id,\r\n $user_id,\r\n $page_id,\r\n 'Chatbot',\r\n $thread_id,\r\n $assistant_id,\r\n null,\r\n $response\r\n );\r\n $response = chatbot_chatgpt_check_for_links_and_images( $response );\r\n // FIXME - Append extra message - Ver 2.1.1.1.1\r\n // Danger Will Robinson! Danger!\r\n $extra_message = esc_attr( get_option( 'chatbot_chatgpt_extra_message', '' ) );\r\n $response = chatbot_chatgpt_append_extra_message( $response, $extra_message );\r\n // Clear conversation lock and process queue BEFORE sending response\r\n delete_transient( $conv_lock );\r\n chatbot_chatgpt_process_queue(\r\n $user_id,\r\n $page_id,\r\n $session_id,\r\n $assistant_id\r\n );\r\n // Return response\r\n wp_send_json_success( $response );\r\n }\r\n global $chatbot_chatgpt_fixed_literal_messages;\r\n // Define a default fallback message\r\n $default_message = 'Oops! I fell through the cracks!';\r\n $error_message = ( isset( $chatbot_chatgpt_fixed_literal_messages[1] ) ? $chatbot_chatgpt_fixed_literal_messages[1] : $default_message );\r\n // Send error response\r\n wp_send_json_error( $error_message );\r\n // Clear conversation lock on error\r\n delete_transient( $conv_lock );\r\n }\r\n\r\n // Handle nonce refresh requests - Ver 2.3.6\r\n function chatbot_chatgpt_refresh_nonce() {\r\n // Generate fresh nonces\r\n $nonces = array(\r\n 'chatbot_message_nonce' => wp_create_nonce( 'chatbot_message_nonce' ),\r\n 'chatbot_upload_nonce' => wp_create_nonce( 'chatbot_upload_nonce' ),\r\n 'chatbot_erase_nonce' => wp_create_nonce( 'chatbot_erase_nonce' ),\r\n 'chatbot_unlock_nonce' => wp_create_nonce( 'chatbot_unlock_nonce' ),\r\n 'chatbot_reset_nonce' => wp_create_nonce( 'chatbot_reset_nonce' ),\r\n 'chatbot_queue_nonce' => wp_create_nonce( 'chatbot_queue_nonce' ),\r\n 'chatbot_tts_nonce' => wp_create_nonce( 'chatbot_tts_nonce' ),\r\n 'chatbot_transcript_nonce' => wp_create_nonce( 'chatbot_transcript_nonce' ),\r\n );\r\n wp_send_json_success( $nonces );\r\n }\r\n\r\n // Function to clear stuck visitor locks - Ver 2.3.6\r\n function chatbot_chatgpt_clear_stuck_visitor_locks() {\r\n global $wpdb;\r\n // Only run for visitors (not logged in users)\r\n if ( is_user_logged_in() ) {\r\n return;\r\n }\r\n // Clear locks older than 2 minutes\r\n $expired_time = time() - 120;\r\n // 2 minutes ago\r\n $lock_patterns = ['_transient_chatgpt_conv_lock_%', '_transient_timeout_chatgpt_conv_lock_%'];\r\n foreach ( $lock_patterns as $pattern ) {\r\n $wpdb->query( $wpdb->prepare( \"DELETE FROM {$wpdb->options} WHERE option_name LIKE %s AND option_value < %d\", $pattern, $expired_time ) );\r\n }\r\n }\r\n\r\n // Hook to clear stuck locks on init for visitors\r\n add_action( 'init', 'chatbot_chatgpt_clear_stuck_visitor_locks', 5 );\r\n // Add admin menu for visitor lock clearing tool - Ver 2.3.6\r\n function chatbot_chatgpt_add_visitor_lock_tool_menu() {\r\n add_submenu_page(\r\n 'chatbot-chatgpt',\r\n 'Clear Visitor Locks',\r\n 'Clear Visitor Locks',\r\n 'manage_options',\r\n 'chatbot-clear-visitor-locks',\r\n 'chatbot_chatgpt_visitor_lock_tool_page'\r\n );\r\n }\r\n\r\n add_action( 'admin_menu', 'chatbot_chatgpt_add_visitor_lock_tool_menu' );\r\n // Admin page for visitor lock clearing tool\r\n function chatbot_chatgpt_visitor_lock_tool_page() {\r\n if ( isset( $_POST['clear_locks'] ) && wp_verify_nonce( $_POST['_wpnonce'], 'clear_visitor_locks' ) ) {\r\n chatbot_chatgpt_clear_stuck_visitor_locks();\r\n echo '

Visitor locks cleared successfully!

';\r\n }\r\n echo '
';\r\n echo '

Clear Visitor Locks

';\r\n echo '

This tool clears stuck conversation locks that may be preventing visitors from using the chatbot.

';\r\n echo '

Use this if visitors are getting \"system is busy processing requests\" messages.

';\r\n echo '
';\r\n wp_nonce_field( 'clear_visitor_locks' );\r\n echo '

';\r\n echo '
';\r\n echo '
';\r\n }\r\n\r\n // Add action to send messages - Ver 1.0.0\r\n add_action( 'wp_ajax_chatbot_chatgpt_send_message', 'chatbot_chatgpt_send_message' );\r\n add_action( 'wp_ajax_nopriv_chatbot_chatgpt_send_message', 'chatbot_chatgpt_send_message' );\r\n // Add action to refresh nonce - Ver 2.3.6\r\n add_action( 'wp_ajax_chatbot_chatgpt_refresh_nonce', 'chatbot_chatgpt_refresh_nonce' );\r\n add_action( 'wp_ajax_nopriv_chatbot_chatgpt_refresh_nonce', 'chatbot_chatgpt_refresh_nonce' );\r\n // Add action to get queue status\r\n add_action( 'wp_ajax_chatbot_chatgpt_get_queue_status', 'chatbot_chatgpt_get_queue_status_ajax' );\r\n add_action( 'wp_ajax_nopriv_chatbot_chatgpt_get_queue_status', 'chatbot_chatgpt_get_queue_status_ajax' );\r\n // Add action to upload files - Ver 1.7.6 (Security: Authentication required)\r\n add_action( 'wp_ajax_chatbot_chatgpt_upload_files', 'chatbot_chatgpt_upload_files' );\r\n // Add action to upload mp3 files - Ver 1.7.6 (Security: Authentication required)\r\n add_action( 'wp_ajax_chatbot_chatgpt_upload_mp3', 'chatbot_chatgpt_upload_mp3' );\r\n // Add action to erase conversation - Ver 1.8.6 (Security: Authentication required)\r\n add_action( 'wp_ajax_chatbot_chatgpt_erase_conversation', 'chatbot_chatgpt_erase_conversation_handler' );\r\n add_action( 'wp_ajax_nopriv_chatbot_chatgpt_erase_conversation', 'chatbot_chatgpt_erase_conversation_handler' );\r\n // Add action to unlock conversation - Ver 2.3.0 (Security: Authentication required)\r\n add_action( 'wp_ajax_chatbot_chatgpt_unlock_conversation', 'chatbot_chatgpt_unlock_conversation_handler' );\r\n // Add action to reset all locks (Security: Authentication required)\r\n add_action( 'wp_ajax_chatbot_chatgpt_reset_all_locks', 'chatbot_chatgpt_reset_all_locks_handler' );\r\n // Add action to reset cache and locks (Security: Authentication required) - Ver 2.3.6\r\n add_action( 'wp_ajax_chatbot_chatgpt_reset_cache_locks', 'chatbot_chatgpt_reset_cache_locks_handler' );\r\n // Add action for text-to-speech (Security: Authentication required)\r\n add_action( 'wp_ajax_chatbot_chatgpt_read_aloud', 'chatbot_chatgpt_read_aloud' );\r\n // Add action for transcript download (Security: Authentication required)\r\n add_action( 'wp_ajax_chatbot_chatgpt_download_transcript', 'chatbot_chatgpt_download_transcript' );\r\n // Settings and Deactivation - Ver 1.5.0\r\n add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), 'chatbot_chatgpt_plugin_action_links' );\r\n // Unlock conversation handler - Ver 2.3.0\r\n function chatbot_chatgpt_unlock_conversation_handler() {\r\n // Security: Check if user has permission to manage options (admin capability)\r\n if ( !current_user_can( 'manage_options' ) ) {\r\n wp_send_json_error( 'Insufficient permissions to unlock conversation.', 403 );\r\n return;\r\n }\r\n // Security: Verify nonce for CSRF protection\r\n if ( !isset( $_POST['chatbot_nonce'] ) || !wp_verify_nonce( $_POST['chatbot_nonce'], 'chatbot_unlock_nonce' ) ) {\r\n wp_send_json_error( 'Security check failed. Please refresh the page and try again.', 403 );\r\n return;\r\n }\r\n // Get parameters from POST\r\n $user_id = ( isset( $_POST['user_id'] ) ? sanitize_text_field( $_POST['user_id'] ) : '' );\r\n $page_id = ( isset( $_POST['page_id'] ) ? sanitize_text_field( $_POST['page_id'] ) : '' );\r\n $session_id = ( isset( $_POST['session_id'] ) ? sanitize_text_field( $_POST['session_id'] ) : '' );\r\n $assistant_id = ( isset( $_POST['assistant_id'] ) ? sanitize_text_field( $_POST['assistant_id'] ) : '' );\r\n if ( $user_id && $page_id && $session_id && $assistant_id ) {\r\n // Clear the conversation lock\r\n $conv_lock = 'chatgpt_conv_lock_' . wp_hash( $assistant_id . '|' . $user_id . '|' . $page_id . '|' . $session_id );\r\n $lock_exists = get_transient( $conv_lock );\r\n $deleted_lock = delete_transient( $conv_lock );\r\n // Clear the message queue\r\n $queue_key = 'chatbot_message_queue_' . wp_hash( $assistant_id . '|' . $user_id . '|' . $page_id . '|' . $session_id );\r\n $queue_exists = get_transient( $queue_key );\r\n $deleted_queue = delete_transient( $queue_key );\r\n // Try to clear all possible lock variations\r\n $possible_locks = [\r\n 'chatgpt_conv_lock_' . wp_hash( $assistant_id . '|' . $user_id . '|' . $page_id . '|' . $session_id ),\r\n 'chatgpt_conv_lock_' . wp_hash( $user_id . '|' . $page_id . '|' . $session_id ),\r\n 'chatgpt_conv_lock_' . wp_hash( $session_id ),\r\n 'chatgpt_conv_lock_' . $session_id,\r\n 'chatgpt_conv_lock_' . $user_id . '_' . $page_id . '_' . $session_id,\r\n // Additional variations for visitor locks\r\n 'chatgpt_conv_lock_' . wp_hash( $assistant_id . '|' . $session_id . '|' . $page_id ),\r\n 'chatgpt_conv_lock_' . wp_hash( $session_id . '|' . $page_id ),\r\n ];\r\n foreach ( $possible_locks as $lock_key ) {\r\n if ( get_transient( $lock_key ) ) {\r\n delete_transient( $lock_key );\r\n }\r\n }\r\n wp_send_json_success( 'Conversation unlocked' );\r\n } else {\r\n wp_send_json_error( 'Missing parameters' );\r\n }\r\n }\r\n\r\n // Global lock reset handler - Ver 2.3.0\r\n function chatbot_chatgpt_reset_all_locks_handler() {\r\n // Security: Check if user has permission to manage options (admin capability)\r\n if ( !current_user_can( 'manage_options' ) ) {\r\n wp_send_json_error( 'Insufficient permissions to reset locks.', 403 );\r\n return;\r\n }\r\n // Security: Verify nonce for CSRF protection\r\n if ( !isset( $_POST['chatbot_nonce'] ) || !wp_verify_nonce( $_POST['chatbot_nonce'], 'chatbot_reset_nonce' ) ) {\r\n wp_send_json_error( 'Security check failed. Please refresh the page and try again.', 403 );\r\n return;\r\n }\r\n // Get parameters from POST\r\n $user_id = ( isset( $_POST['user_id'] ) ? sanitize_text_field( $_POST['user_id'] ) : '' );\r\n $page_id = ( isset( $_POST['page_id'] ) ? sanitize_text_field( $_POST['page_id'] ) : '' );\r\n $session_id = ( isset( $_POST['session_id'] ) ? sanitize_text_field( $_POST['session_id'] ) : '' );\r\n $assistant_id = ( isset( $_POST['assistant_id'] ) ? sanitize_text_field( $_POST['assistant_id'] ) : '' );\r\n $cleared_count = 0;\r\n if ( $user_id && $page_id && $session_id && $assistant_id ) {\r\n // Clear all possible lock variations for this conversation\r\n $possible_locks = [\r\n 'chatgpt_conv_lock_' . wp_hash( $assistant_id . '|' . $user_id . '|' . $page_id . '|' . $session_id ),\r\n 'chatgpt_conv_lock_' . wp_hash( $user_id . '|' . $page_id . '|' . $session_id ),\r\n 'chatgpt_conv_lock_' . wp_hash( $session_id ),\r\n 'chatgpt_conv_lock_' . $session_id,\r\n 'chatgpt_conv_lock_' . $user_id . '_' . $page_id . '_' . $session_id,\r\n 'chatgpt_run_lock_' . wp_hash( $assistant_id . '|' . $user_id . '|' . $page_id . '|' . $session_id ),\r\n 'chatgpt_run_lock_' . wp_hash( $user_id . '|' . $page_id . '|' . $session_id ),\r\n 'chatgpt_run_lock_' . wp_hash( $session_id ),\r\n 'chatgpt_run_lock_' . $session_id,\r\n 'chatgpt_run_lock_' . $user_id . '_' . $page_id . '_' . $session_id\r\n ];\r\n foreach ( $possible_locks as $lock_key ) {\r\n if ( get_transient( $lock_key ) ) {\r\n delete_transient( $lock_key );\r\n $cleared_count++;\r\n }\r\n }\r\n // Clear all possible queue variations\r\n $possible_queues = [\r\n 'chatbot_message_queue_' . wp_hash( $assistant_id . '|' . $user_id . '|' . $page_id . '|' . $session_id ),\r\n 'chatbot_message_queue_' . wp_hash( $user_id . '|' . $page_id . '|' . $session_id ),\r\n 'chatbot_message_queue_' . wp_hash( $session_id ),\r\n 'chatbot_message_queue_' . $session_id,\r\n 'chatbot_message_queue_' . $user_id . '_' . $page_id . '_' . $session_id\r\n ];\r\n foreach ( $possible_queues as $queue_key ) {\r\n if ( get_transient( $queue_key ) ) {\r\n delete_transient( $queue_key );\r\n $cleared_count++;\r\n }\r\n }\r\n wp_send_json_success( 'Reset completed - Cleared ' . $cleared_count . ' locks/queues' );\r\n } else {\r\n wp_send_json_error( 'Missing parameters' );\r\n }\r\n }\r\n\r\n // Reset Cache and Locks Handler - Ver 2.3.6\r\n function chatbot_chatgpt_reset_cache_locks_handler() {\r\n // Security: Check if user has permission to manage options (admin capability)\r\n if ( !current_user_can( 'manage_options' ) ) {\r\n wp_send_json_error( 'Insufficient permissions to reset cache and locks.', 403 );\r\n return;\r\n }\r\n // Security: Verify nonce for CSRF protection\r\n if ( !isset( $_POST['chatbot_nonce'] ) || !wp_verify_nonce( $_POST['chatbot_nonce'], 'chatbot_reset_cache_locks' ) ) {\r\n wp_send_json_error( 'Security check failed. Please refresh the page and try again.', 403 );\r\n return;\r\n }\r\n global $wpdb;\r\n $cleared_count = 0;\r\n try {\r\n // Clear all conversation locks\r\n $lock_patterns = [\r\n '_transient_chatgpt_conv_lock_%',\r\n '_transient_timeout_chatgpt_conv_lock_%',\r\n '_transient_chatgpt_run_lock_%',\r\n '_transient_timeout_chatgpt_run_lock_%',\r\n '_transient_chatbot_message_queue_%',\r\n '_transient_timeout_chatbot_message_queue_%',\r\n '_transient_chatbot_chatgpt_%',\r\n '_transient_timeout_chatbot_chatgpt_%'\r\n ];\r\n foreach ( $lock_patterns as $pattern ) {\r\n $result = $wpdb->query( $wpdb->prepare( \"DELETE FROM {$wpdb->options} WHERE option_name LIKE %s\", $pattern ) );\r\n $cleared_count += $result;\r\n }\r\n // Clear expired transients\r\n $expired_result = $wpdb->query( $wpdb->prepare( \"DELETE FROM {$wpdb->options} WHERE option_name LIKE %s AND option_value < %d\", '_transient_timeout_%', time() ) );\r\n $cleared_count += $expired_result;\r\n // Clear WordPress object cache if available\r\n if ( function_exists( 'wp_cache_flush' ) ) {\r\n wp_cache_flush();\r\n }\r\n // Clear any file-based caches\r\n $cache_dirs = [\r\n WP_CONTENT_DIR . '/cache/',\r\n WP_CONTENT_DIR . '/uploads/chatbot-chatgpt/',\r\n plugin_dir_path( __FILE__ ) . 'cache/',\r\n plugin_dir_path( __FILE__ ) . 'audio/',\r\n plugin_dir_path( __FILE__ ) . 'downloads/',\r\n plugin_dir_path( __FILE__ ) . 'transcripts/'\r\n ];\r\n foreach ( $cache_dirs as $cache_dir ) {\r\n if ( is_dir( $cache_dir ) ) {\r\n $files = glob( $cache_dir . '*' );\r\n foreach ( $files as $file ) {\r\n if ( is_file( $file ) && filemtime( $file ) < time() - 3600 ) {\r\n // Older than 1 hour\r\n @unlink( $file );\r\n $cleared_count++;\r\n }\r\n }\r\n }\r\n }\r\n // Log the action\r\n $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';\r\n chatbot_error_log( $log_message );\r\n wp_send_json_success( 'Cache and locks reset successfully. Cleared ' . $cleared_count . ' entries.' );\r\n } catch ( Exception $e ) {\r\n $log_message = '[' . date( 'Y-m-d H:i:s' ) . '] [Chatbot] [Advanced Reset] Error: ' . $e->getMessage();\r\n chatbot_error_log( $log_message );\r\n wp_send_json_error( 'Error resetting cache and locks: ' . $e->getMessage() );\r\n }\r\n }\r\n\r\n // Append an extra message to the response - Ver 2.0.9\r\n function chatbot_chatgpt_append_extra_message( $response, $extra_message ) {\r\n // Append the extra message to the response\r\n $response = $response . ' ' . $extra_message;\r\n return $response;\r\n }\r\n\r\n // Crawler aka Knowledge Navigator - Ver 1.6.1\r\n function chatbot_chatgpt_kn_status_activation() {\r\n add_option( 'chatbot_chatgpt_kn_status', 'Never Run' );\r\n // clear any old scheduled runs\r\n if ( wp_next_scheduled( 'crawl_scheduled_event_hook' ) ) {\r\n wp_clear_scheduled_hook( 'crawl_scheduled_event_hook' );\r\n }\r\n // clear the 'knowledge_navigator_scan_hook' hook on plugin activation - Ver 1.6.3\r\n if ( wp_next_scheduled( 'knowledge_navigator_scan_hook' ) ) {\r\n // BREAK/FIX - Do not unset the hook - Ver 1.8.5\r\n // wp_clear_scheduled_hook('knowledge_navigator_scan_hook'); // Clear scheduled runs\r\n }\r\n }\r\n\r\n register_activation_hook( __FILE__, 'chatbot_chatgpt_kn_status_activation' );\r\n // Clean Up in Aisle 4\r\n function chatbot_chatgpt_kn_status_deactivation() {\r\n delete_option( 'chatbot_chatgpt_kn_status' );\r\n wp_clear_scheduled_hook( 'knowledge_navigator_scan_hook' );\r\n }\r\n\r\n register_deactivation_hook( __FILE__, 'chatbot_chatgpt_kn_status_deactivation' );\r\n // Markov Chain builder - Activation Hook - Ver 2.1.6\r\n function chatbot_markov_chain_status_activation() {\r\n // Add the option for build status with a default value of 'Never Run'\r\n add_option( 'chatbot_markov_chain_build_status', 'Never Run' );\r\n // Clear any old scheduled runs, if present\r\n if ( wp_next_scheduled( 'chatbot_markov_chain_scan_hook' ) ) {\r\n // BREAK/FIX - Do not unset the hook - Ver 2.1.6\r\n // wp_clear_scheduled_hook('chatbot_markov_chain_scan_hook'); // Clear scheduled runs\r\n }\r\n }\r\n\r\n register_activation_hook( __FILE__, 'chatbot_markov_chain_status_activation' );\r\n // Clean up scheduled events and options - Deactivation Hook\r\n function chatbot_markov_chain_status_deactivation() {\r\n // Delete the build status option on deactivation\r\n delete_option( 'chatbot_markov_chain_build_status' );\r\n // Clear any scheduled events related to the Markov Chain scan\r\n wp_clear_scheduled_hook( 'chatbot_markov_chain_scan_hook' );\r\n }\r\n\r\n register_deactivation_hook( __FILE__, 'chatbot_markov_chain_status_deactivation' );\r\n // Transformer Model builder - Activation Hook - Ver 2.2.0\r\n function chatbot_transformer_model_status_activation() {\r\n // Add the option for build status with a default value of 'Never Run'\r\n add_option( 'chatbot_transformer_model_build_status', 'Never Run' );\r\n // Clear any old scheduled runs, if present\r\n if ( wp_next_scheduled( 'chatbot_transformer_model_scan_hook' ) ) {\r\n // BREAK/FIX - Do not unset the hook - Ver 2.2.0\r\n // wp_clear_scheduled_hook('chatbot_transformer_model_scan_hook'); // Clear scheduled runs\r\n }\r\n }\r\n\r\n register_activation_hook( __FILE__, 'chatbot_transformer_model_status_activation' );\r\n // Clean up scheduled events and options - Deactivation Hook\r\n function chatbot_transformer_model_status_deactivation() {\r\n // Delete the build status option on deactivation\r\n delete_option( 'chatbot_transformer_model_build_status' );\r\n // Clear any scheduled events related to the Transformer Model scan\r\n wp_clear_scheduled_hook( 'chatbot_transformer_model_scan_hook' );\r\n }\r\n\r\n register_deactivation_hook( __FILE__, 'chatbot_transformer_model_status_deactivation' );\r\n // Function to add a new message and response, keeping only the last five - Ver 1.6.1\r\n function addEntry( $transient_name, $newEntry ) {\r\n $context_history = get_transient( $transient_name );\r\n if ( !$context_history ) {\r\n $context_history = [];\r\n }\r\n // Determine the total length of all existing entries\r\n $totalLength = 0;\r\n foreach ( $context_history as $entry ) {\r\n if ( is_string( $entry ) ) {\r\n $totalLength += strlen( $entry );\r\n } elseif ( is_array( $entry ) ) {\r\n $totalLength += strlen( json_encode( $entry ) );\r\n // Convert to string if an array\r\n }\r\n }\r\n // IDEA - How will the new threading option from OpenAI change how this works?\r\n // Define thresholds for the number of entries to keep\r\n $maxEntries = 30;\r\n // Default maximum number of entries\r\n if ( $totalLength > 5000 ) {\r\n // Higher threshold\r\n $maxEntries = 20;\r\n }\r\n if ( $totalLength > 10000 ) {\r\n // Lower threshold\r\n $maxEntries = 10;\r\n }\r\n while ( count( $context_history ) >= $maxEntries ) {\r\n array_shift( $context_history );\r\n // Remove the oldest element\r\n }\r\n if ( is_array( $newEntry ) ) {\r\n $newEntry = json_encode( $newEntry );\r\n // Convert the array to a string\r\n }\r\n array_push( $context_history, $newEntry );\r\n // Append the new element\r\n set_transient( $transient_name, $context_history );\r\n // Update the transient\r\n }\r\n\r\n // Function to return message and response - Ver 1.6.1\r\n function concatenateHistory( $transient_name ) {\r\n $context_history = get_transient( $transient_name );\r\n if ( !$context_history ) {\r\n return '';\r\n // Return an empty string if the transient does not exist\r\n }\r\n return implode( ' ', $context_history );\r\n // Concatenate the array values into a single string\r\n }\r\n\r\n // FIXME - MOVE CORE FUNCTIONS TO A SEPARATE FILE, LEAVING ONLY THE HOOKS HERE\r\n // Initialize the Greetings - Ver 1.6.1\r\n function enqueue_greetings_script( $initial_greeting = null, $subsequent_greeting = null ) {\r\n // If user is logged in, then modify greeting if greeting contains \"[...]\" or remove if not logged in - Ver 1.9.4\r\n if ( is_user_logged_in() ) {\r\n $current_user_id = get_current_user_id();\r\n $current_user = get_userdata( $current_user_id );\r\n //Do this for Initial Greeting\r\n if ( empty( $initial_greeting ) ) {\r\n $initial_greeting = esc_attr( get_option( 'chatbot_chatgpt_initial_greeting', 'Hello! How can I help you today?' ) );\r\n }\r\n // Determine what the field name is between the brackets\r\n $user_field_name = '';\r\n $user_field_name = substr( $initial_greeting, strpos( $initial_greeting, '[' ) + 1, strpos( $initial_greeting, ']' ) - strpos( $initial_greeting, '[' ) - 1 );\r\n // If $initial_greeting contains \"[$user_field_name]\" then replace with field from DB\r\n if ( strpos( $initial_greeting, '[' . $user_field_name . ']' ) !== false ) {\r\n $initial_greeting = str_replace( '[' . $user_field_name . ']', $current_user->{$user_field_name}, $initial_greeting );\r\n } else {\r\n $initial_greeting = str_replace( '[' . $user_field_name . ']', '', $initial_greeting );\r\n // Remove the extra space when two spaces are present\r\n $initial_greeting = str_replace( ' ', ' ', $initial_greeting );\r\n // Remove the extra space before punctuation including period, comma, exclamation mark, and question mark\r\n $initial_greeting = preg_replace( '/\\\\s*([.,!?])/', '$1', $initial_greeting );\r\n }\r\n // Do this for Subsequent Greeting\r\n if ( empty( $subsequent_greeting ) ) {\r\n $subsequent_greeting = esc_attr( get_option( 'chatbot_chatgpt_subsequent_greeting', 'Hello again! How can I help you?' ) );\r\n }\r\n // Determine what the field name is between the brackets\r\n $user_field_name = '';\r\n $user_field_name = substr( $subsequent_greeting, strpos( $subsequent_greeting, '[' ) + 1, strpos( $subsequent_greeting, ']' ) - strpos( $subsequent_greeting, '[' ) - 1 );\r\n // If $subsequent_greeting contains \"[$user_field_name]\" then replace with field from DB\r\n if ( strpos( $subsequent_greeting, '[' . $user_field_name . ']' ) !== false ) {\r\n $subsequent_greeting = str_replace( '[' . $user_field_name . ']', $current_user->{$user_field_name}, $subsequent_greeting );\r\n } else {\r\n $subsequent_greeting = str_replace( '[' . $user_field_name . ']', '', $subsequent_greeting );\r\n // Remove the extra space when two spaces are present\r\n $subsequent_greeting = str_replace( ' ', ' ', $subsequent_greeting );\r\n // Remove the extra space before punctuation including period, comma, exclamation mark, and question mark\r\n $subsequent_greeting = preg_replace( '/\\\\s*([.,!?])/', '$1', $subsequent_greeting );\r\n }\r\n } else {\r\n //Do this for Initial Greeting\r\n if ( empty( $initial_greeting ) ) {\r\n $initial_greeting = esc_attr( get_option( 'chatbot_chatgpt_initial_greeting', 'Hello! How can I help you today?' ) );\r\n }\r\n $user_field_name = '';\r\n $user_field_name = substr( $initial_greeting, strpos( $initial_greeting, '[' ) + 1, strpos( $initial_greeting, ']' ) - strpos( $initial_greeting, '[' ) - 1 );\r\n // $initial_greeting = preg_replace('/\\s*\\[' . preg_quote($user_field_name, '/') . '\\]\\s*/', '', $initial_greeting);\r\n $initial_greeting = str_replace( '[' . $user_field_name . ']', '', $initial_greeting );\r\n // Remove the extra space when two spaces are present\r\n $initial_greeting = str_replace( ' ', ' ', $initial_greeting );\r\n // Remove the extra space before punctuation including period, comma, exclamation mark, and question mark\r\n $initial_greeting = preg_replace( '/\\\\s*([.,!?])/', '$1', $initial_greeting );\r\n //Do this for Subsequent Greeting\r\n if ( empty( $subsequent_greeting ) ) {\r\n $subsequent_greeting = esc_attr( get_option( 'chatbot_chatgpt_subsequent_greeting', 'Hello again! How can I help you?' ) );\r\n }\r\n $user_field_name = '';\r\n $user_field_name = substr( $subsequent_greeting, strpos( $subsequent_greeting, '[' ) + 1, strpos( $subsequent_greeting, ']' ) - strpos( $subsequent_greeting, '[' ) - 1 );\r\n // $subsequent_greeting = preg_replace('/\\s*\\[' . preg_quote($user_field_name, '/') . '\\]\\s*/', '', $subsequent_greeting);\r\n $subsequent_greeting = str_replace( '[' . $user_field_name . ']', '', $subsequent_greeting );\r\n // Remove the extra space when two spaces are present\r\n $subsequent_greeting = str_replace( ' ', ' ', $subsequent_greeting );\r\n // Remove the extra space before punctuation including period, comma, exclamation mark, and question mark\r\n $subsequent_greeting = preg_replace( '/\\\\s*([.,!?])/', '$1', $subsequent_greeting );\r\n }\r\n $greetings = array(\r\n 'initial_greeting' => $initial_greeting,\r\n 'subsequent_greeting' => $subsequent_greeting,\r\n );\r\n return $greetings;\r\n }\r\n\r\n add_action( 'wp_enqueue_scripts', 'enqueue_greetings_script' );\r\n // Add the color picker to the adaptive appearance settings section - Ver 1.8.1\r\n function enqueue_color_picker( $hook_suffix ) {\r\n global $chatbot_chatgpt_plugin_version;\r\n // first check that $hook_suffix is appropriate for your admin page\r\n wp_enqueue_style( 'wp-color-picker' );\r\n wp_enqueue_script(\r\n 'my-script-handle',\r\n plugin_dir_url( __FILE__ ) . 'assets/js/chatbot-chatgpt-color-picker.js',\r\n array('wp-color-picker'),\r\n $chatbot_chatgpt_plugin_version,\r\n true\r\n );\r\n }\r\n\r\n add_action( 'admin_enqueue_scripts', 'enqueue_color_picker' );\r\n // Determine if the plugin is installed\r\n // NOTE: This function is deprecated. Version tracking is now handled via chatbot_chatgpt_version_installed option.\r\n // Kept for backward compatibility but no longer updates the legacy chatbot_chatgpt_plugin_version option.\r\n function kchat_get_plugin_version() {\r\n global $chatbot_chatgpt_plugin_version;\r\n if ( !function_exists( 'get_plugin_data' ) ) {\r\n require_once ABSPATH . 'wp-admin/includes/plugin.php';\r\n }\r\n $plugin_data = get_plugin_data( plugin_dir_path( __FILE__ ) . 'chatbot-chatgpt.php' );\r\n $plugin_version = $plugin_data['Version'];\r\n // Return version without updating legacy option (chatbot_chatgpt_plugin_version is deprecated)\r\n return $plugin_version;\r\n }\r\n\r\n // DO NOT REMOVE THIS IF, IT IS ESSENTIAL FOR THE AUTOMATIC DEACTIVATION OF THE PLUGIN\r\n}"}, "81133d2416ab2ca1d8784ec5469d49357805af5a": {"t": 1785756403.8158, "n": 167437, "h": "8b902d1831b1c4d5", "c": "set_basename( false, __FILE__ );\r\n} else {\r\n /**\r\n * DO NOT REMOVE THIS IF, IT IS ESSENTIAL FOR THE\r\n * `function_exists` CALL ABOVE TO PROPERLY WORK.\r\n */\r\n if ( !function_exists( 'chatbot_chatgpt_freemius' ) ) {\r\n function chatbot_chatgpt_freemius() {\r\n global $chatbot_chatgpt_freemius;\r\n if ( !isset( $chatbot_chatgpt_freemius ) ) {\r\n // Include Freemius SDK\r\n require_once dirname( __FILE__ ) . '/vendor/freemius/start.php';\r\n $chatbot_chatgpt_freemius = fs_dynamic_init( array(\r\n 'id' => '18850',\r\n 'slug' => 'chatbot-chatgpt',\r\n 'type' => 'plugin',\r\n 'public_key' => 'pk_ea667ce516b3acd5d3756a0c2530b',\r\n 'is_premium' => false,\r\n 'premium_suffix' => 'Premium',\r\n 'has_paid_plans' => true,\r\n 'trial' => array(\r\n 'days' => 7,\r\n 'is_require_payment' => false,\r\n ),\r\n 'menu' => array(\r\n 'slug' => 'chatbot-chatgpt',\r\n 'first-path' => 'admin.php?page=chatbot-chatgpt&tab=support',\r\n 'network' => true,\r\n ),\r\n 'is_live' => true,\r\n ) );\r\n }\r\n return $chatbot_chatgpt_freemius;\r\n }\r\n\r\n // Initialize Freemius\r\n chatbot_chatgpt_freemius();\r\n do_action( 'chatbot_chatgpt_freemius_loaded' );\r\n }\r\n // ADD THIS TO THE END OF THE FILE - NOT HERE\r\n // }\r\n // Start output buffering earlier to prevent \"headers already sent\" issues - Ver 2.1.8\r\n ob_start();\r\n // Plugin version\r\n global $chatbot_chatgpt_plugin_version;\r\n $chatbot_chatgpt_plugin_version = '2.4.6';\r\n // Plugin directory path\r\n global $chatbot_chatgpt_plugin_dir_path;\r\n $chatbot_chatgpt_plugin_dir_path = plugin_dir_path( __FILE__ );\r\n // Plugin directory URL\r\n global $chatbot_chatgpt_plugin_dir_url;\r\n $chatbot_chatgpt_plugin_dir_url = plugins_url( '/', __FILE__ );\r\n // Main plugin file pointer (used by vendor-management hooks, etc.)\r\n if ( !defined( 'CHATBOT_CHATGPT_PLUGIN_FILE' ) ) {\r\n define( 'CHATBOT_CHATGPT_PLUGIN_FILE', __FILE__ );\r\n }\r\n // Declare Globals\r\n global $wpdb;\r\n // Uniquely Identify the Visitor\r\n global $session_id;\r\n global $user_id;\r\n // Assign a unique ID to the visitor and logged-in users - Ver 2.0.4\r\n // Ver 2.3.7 - Fixed headers already sent warning by checking if headers can be sent\r\n // Ver 2.4.0 - Added @ operator to suppress warnings as additional safety measure\r\n function kognetiks_assign_unique_id() {\r\n if ( !isset( $_COOKIE['kognetiks_unique_id'] ) ) {\r\n $unique_id = uniqid( 'kognetiks_', true );\r\n // Check if headers have already been sent before trying to set cookie\r\n // Ver 2.3.7 - Prevent \"headers already sent\" warning\r\n // Ver 2.4.0 - Use @ operator to suppress any warnings as additional safety measure\r\n if ( !headers_sent() ) {\r\n // Set a cookie using the built-in setcookie function\r\n // Using @ operator to suppress warnings in case headers are sent between check and setcookie\r\n @setcookie(\r\n 'kognetiks_unique_id',\r\n $unique_id,\r\n time() + 86400 * 30,\r\n \"/\",\r\n \"\",\r\n true,\r\n true\r\n );\r\n // HttpOnly and Secure flags set to true\r\n }\r\n // Ensure the cookie is set for the current request (works even if headers were already sent)\r\n $_COOKIE['kognetiks_unique_id'] = $unique_id;\r\n }\r\n }\r\n\r\n add_action( 'init', 'kognetiks_assign_unique_id', 1 );\r\n // Set higher priority\r\n // Get the unique ID of the visitor or logged-in user - Ver 2.0.4\r\n function kognetiks_get_unique_id() {\r\n if ( isset( $_COOKIE['kognetiks_unique_id'] ) ) {\r\n // back_trace('NOTICE', 'Unique ID found: ' . $_COOKIE['kognetiks_unique_id']);\r\n return sanitize_text_field( $_COOKIE['kognetiks_unique_id'] );\r\n }\r\n // back_trace('NOTICE', 'Unique ID not found');\r\n return null;\r\n }\r\n\r\n // Fetch the User ID - Updated Ver 2.0.6 - 2024 07 11\r\n $user_id = get_current_user_id();\r\n // Fetch the Kognetiks cookie\r\n $session_id = kognetiks_get_unique_id();\r\n if ( empty( $user_id ) || $user_id == 0 ) {\r\n $user_id = $session_id;\r\n }\r\n ob_end_flush();\r\n // End output buffering and send the buffer to the browser\r\n // Include necessary files - Utilities (must be loaded before API files that use them)\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-utilities.php';\r\n // Ver 1.8.6\r\n // Include necessary files - Main files\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-call-anthropic-api.php';\r\n // ANT API - Ver 2.0.7\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-call-azure-openai-api.php';\r\n // Azure OpenAI API - Ver 2.2.6\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-call-azure-api-assistant.php';\r\n // Azure OpenAI Assistants API - Ver 2.2.6\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-call-deepseek-api.php';\r\n // ChatGPT API - Ver 2.2.2\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-call-google-api.php';\r\n // Google API - Ver 2.3.9\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-call-kognetiks-api-mc.php';\r\n // Kognetiks - Markov Chain API - Ver 2.1.6\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-call-kognetiks-api-tm.php';\r\n // Kognetiks - Transformer Model API - Ver 2.2.0\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-call-local-api.php';\r\n // Local API - Ver 2.2.6\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-call-mistral-api.php';\r\n // Mistral API - Ver 2.3.0\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-call-mistral-agent-api.php';\r\n // Mistral Agent API - Ver 2.3.0\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-call-nvidia-api.php';\r\n // NVIDIA API - Ver 2.1.8\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-call-openai-api-assistant.php';\r\n // GPT Assistants - Ver 1.6.9\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-call-openai-api-chatgpt.php';\r\n // ChatGPT API - Ver 1.6.9\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-call-openai-api-image.php';\r\n // Image API - Ver 1.9.4\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-call-openai-api-kflow.php';\r\n // Kognetiks - Flow API - Ver 1.9.5\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-call-openai-api-omni.php';\r\n // ChatGPT API - Ver 2.0.2.1\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-call-openai-api-stt.php';\r\n // STT API - Ver 2.0.1\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-call-openai-api-responses.php';\r\n // OpenAI Responses - Ver 2.4.5\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-call-openai-api-tts.php';\r\n // TTS API - Ver 1.9.4\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-globals.php';\r\n // Globals - Ver 1.6.5\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/chatbot-shortcode.php';\r\n // Shortcode - Ver 1.6.5\r\n // Include necessary files - Appearance - Ver 1.8.1\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/appearance/chatbot-settings-appearance-body.php';\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/appearance/chatbot-settings-appearance-dimensions.php';\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/appearance/chatbot-settings-appearance-text.php';\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/appearance/chatbot-settings-appearance-user-css.php';\r\n // Include necessary files - Knowledge Navigator\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/knowledge-navigator/chatbot-kn-acquire-controller.php';\r\n // Knowledge Navigator Acquisition - Ver 1.9.6\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/knowledge-navigator/chatbot-kn-acquire-words.php';\r\n // Knowledge Navigator Acquisition - Ver 1.9.6\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/knowledge-navigator/chatbot-kn-analysis.php';\r\n // Knowledge Navigator Analysis- Ver 1.6.2\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/knowledge-navigator/chatbot-kn-db.php';\r\n // Knowledge Navigator - Database Management - Ver 1.6.3\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/knowledge-navigator/chatbot-kn-enhance-context.php';\r\n // Knowledge Navigator - Enhance Context - Ver 1.6.9\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/knowledge-navigator/chatbot-kn-enhance-response.php';\r\n // Knowledge Navigator - TD-IDF Response Enhancement - Ver 1.6.9\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/knowledge-navigator/chatbot-kn-scheduler.php';\r\n // Knowledge Navigator - Scheduler - Ver 1.6.3\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/knowledge-navigator/chatbot-kn-settings.php';\r\n // Knowledge Navigator - Settings - Ver 1.6.1\r\n // Include necessary files - Markov Chain - Ver 2.1.9\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/markov-chain/chatbot-markov-chain-decode.php';\r\n // Functions - Ver 2.1.9\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/markov-chain/chatbot-markov-chain-decode-beaker.php';\r\n // Functions - Ver 2.2.0\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/markov-chain/chatbot-markov-chain-encode.php';\r\n // Functions - Ver 2.1.9\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/markov-chain/chatbot-markov-chain-scheduler.php';\r\n // Functions - Ver 2.1.9\r\n // Include necessary files - Transformer Model - Ver 2.2.0\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/transformers/lexical-context-model.php';\r\n // Functions - Ver 2.2.0\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/transformers/sentential-context-model.php';\r\n // Functions - Ver 2.2.0\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/transformers/transformer-model-scheduler.php';\r\n // Functions - Ver 2.2.0\r\n // Include necessary files - Settings\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-api-anthropic.php';\r\n // Anthropic\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-api-azure-assistants.php';\r\n // Azure Assistants - Ver 2.2.6\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-api-azure.php';\r\n // Azure - Ver 2.2.6\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-api-deepseek.php';\r\n // DeepSeek\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-api-google.php';\r\n // Google - Ver 2.3.9\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-api-nvidia.php';\r\n // NVIDIA\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-api-local.php';\r\n // Local Server - Ver 2.2.6\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-api-mistral-agents.php';\r\n // Mistral Agents - Ver 2.3.0\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-api-mistral.php';\r\n // Mistral\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-api-openai-assistants.php';\r\n // OpenAI ChatGPT\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-api-openai.php';\r\n // OpenAI ChatGPT\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-api-test.php';\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-appearance.php';\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-avatar.php';\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-buttons.php';\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-diagnostics.php';\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-general.php';\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-links.php';\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-localization.php';\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-localize.php';\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-markov-chain.php';\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-menus.php';\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-notices.php';\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-registration-api.php';\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-registration-kn.php';\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-registration.php';\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-reporting.php';\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-support.php';\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-tools.php';\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings-transformers.php';\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/settings/chatbot-settings.php';\r\n // Include necessary files - Utilities - Ver 1.9.0\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-agents-mistral.php';\r\n // Mistral Agents - Ver 2.3.0\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-api-endpoints.php';\r\n // API Endpoints - Ver 2.2.2\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-assistants.php';\r\n // Assistants Management for OpenAI - Ver 2.0.4\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-assistants-azure.php';\r\n // Assistants Management for Azure - Ver 2.2.6\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-assisted-search.php';\r\n // Assisted Search - Ver 2.2.7 - 2025-03-26\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-conversation-context.php';\r\n // Conversation Context - Ver 2.3.9\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-conversation-digest.php';\r\n // Conversation Digest - Ver 2.3.9\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-conversation-history.php';\r\n // Ver 1.9.2\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-content-search.php';\r\n // Functions - Ver 2.2.4\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/dashboard/chatbot-chatgpt-dashboard-widget.php';\r\n // Dashboard Widget - Ver 2.2.7\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-db-management.php';\r\n // Database Management for Reporting - Ver 1.6.3\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-deactivate.php';\r\n // Deactivation - Ver 1.9.9\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-download-transcript.php';\r\n // Functions - Ver 1.9.9\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-erase-conversation.php';\r\n // Functions - Ver 1.8.6\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-file-download.php';\r\n // Download a file via the API - Ver 2.0.3\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-file-helper.php';\r\n // Functions - Ver 2.0.3\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-file-upload.php';\r\n // Functions - Ver 1.7.6\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-filter-out-html-tags.php';\r\n // Functions - Ver 1.9.6\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-helper-functions.php';\r\n // Functions - Ver 1.0.0\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-keyguard.php';\r\n // Functions - Ver 2.2.6\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-link-and-image-handling.php';\r\n // Globals - Ver 1.9.1\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-models.php';\r\n // Functions - Ver 1.9.4\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-names.php';\r\n // Functions - Ver 1.9.4\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-options-helper.php';\r\n // Functions - Ver 2.0.5\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-threads.php';\r\n // Ver 1.7.2.1\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-transients-file.php';\r\n // Ver 1.9.2\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-transients.php';\r\n // Ver 1.7.2\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/chatbot-upgrade.php';\r\n // Ver 1.6.7\r\n // chatbot-utilities.php moved above to be loaded before API files - Ver 2.3.9\r\n // chatbot-vendor-management.php loaded at top of file (before Freemius init) - Ver 2.4.4\r\n // Third-party libraries\r\n require_once plugin_dir_path( __FILE__ ) . 'includes/utilities/parsedown.php';\r\n // Version 2.0.2.1\r\n // Include necessary files - Tools - Ver 2.0.6\r\n require_once plugin_dir_path( __FILE__ ) . 'tools/chatbot-capability-tester.php';\r\n require_once plugin_dir_path( __FILE__ ) . 'tools/chatbot-manage-error-logs.php';\r\n require_once plugin_dir_path( __FILE__ ) . 'tools/chatbot-options-exporter.php';\r\n require_once plugin_dir_path( __FILE__ ) . 'tools/chatbot-shortcode-tester.php';\r\n require_once plugin_dir_path( __FILE__ ) . 'tools/chatbot-shortcode-tester-tool.php';\r\n // Include necessary files - Insights - Ver 2.3.6\r\n // require_once plugin_dir_path(__FILE__) . 'includes/insights/insights-settings.php';\r\n // require_once plugin_dir_path(__FILE__) . 'includes/insights/chatbot-insights.php';\r\n // require_once plugin_dir_path(__FILE__) . 'includes/insights/languages/en_US.php';\r\n // require_once plugin_dir_path(__FILE__) . 'includes/insights/scoring-models/sentiment-analysis.php';\r\n // require_once plugin_dir_path(__FILE__) . 'includes/insights/utilities.php';\r\n // require_once plugin_dir_path(__FILE__) . 'includes/insights/globals.php';\r\n /**\r\n * Dynamically load Insights files when premium status is detected\r\n * This function can be called on-demand to load Insights files after plan upgrades\r\n * \r\n * NOTE: Uses chatbot_chatgpt_is_premium() which follows Freemius best practices.\r\n * \r\n * @return bool True if files were loaded, false otherwise\r\n * @since 2.4.2\r\n */\r\n function chatbot_chatgpt_load_insights_files() {\r\n // Check if files are already loaded\r\n if ( function_exists( 'kognetiks_insights_settings_page' ) ) {\r\n return true;\r\n }\r\n // Check if user has premium access using the centralized helper function\r\n // This follows Freemius best practices\r\n if ( !function_exists( 'chatbot_chatgpt_is_premium' ) ) {\r\n return false;\r\n }\r\n $has_premium_access = chatbot_chatgpt_is_premium();\r\n // Load files if user has premium access\r\n if ( $has_premium_access ) {\r\n $plugin_dir = plugin_dir_path( __FILE__ );\r\n $insights_files = array(\r\n 'includes/insights/scoring-models/sentiment-analysis.php',\r\n 'includes/insights/automated-emails.php',\r\n 'includes/insights/chatbot-insights.php',\r\n 'includes/insights/globals.php',\r\n 'includes/insights/insights-settings.php',\r\n 'includes/insights/languages/en_US.php',\r\n 'includes/insights/utilities.php'\r\n );\r\n foreach ( $insights_files as $file ) {\r\n $file_path = $plugin_dir . $file;\r\n if ( file_exists( $file_path ) ) {\r\n require_once $file_path;\r\n }\r\n }\r\n // Register admin_init action for period filter if not already registered\r\n if ( !has_action( 'admin_init', 'chatbot_chatgpt_insights_period_filter_handler' ) ) {\r\n add_action( 'admin_init', 'chatbot_chatgpt_insights_period_filter_handler' );\r\n }\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * Handle Insights period filter form submission\r\n * \r\n * @since 2.4.2\r\n */\r\n function chatbot_chatgpt_insights_period_filter_handler() {\r\n 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' ) ) {\r\n // Handle the period filter logic here\r\n $selected_period = ( isset( $_POST['chatbot_chatgpt_insights_period_filter'] ) ? sanitize_text_field( wp_unslash( $_POST['chatbot_chatgpt_insights_period_filter'] ) ) : 'Today' );\r\n // Store in a transient or option, or pass as needed\r\n set_transient( 'chatbot_chatgpt_selected_period', $selected_period, 60 * 5 );\r\n wp_redirect( admin_url( 'admin.php?page=chatbot-chatgpt&tab=insights' ) );\r\n exit;\r\n }\r\n }\r\n\r\n // Include Insights library - Premium Only (at plugin init)\r\n // Check for premium access including trial status (trial users should have premium access)\r\n if ( function_exists( 'chatbot_chatgpt_is_premium' ) && chatbot_chatgpt_is_premium() ) {\r\n chatbot_chatgpt_load_insights_files();\r\n } elseif ( function_exists( 'chatbot_chatgpt_freemius' ) ) {\r\n // Fallback: use same logic as chatbot_chatgpt_is_premium()\r\n $fs = chatbot_chatgpt_freemius();\r\n if ( is_object( $fs ) ) {\r\n // Detect whether we are running inside the premium build\r\n $running_premium_build = false;\r\n if ( method_exists( $fs, 'is__premium_only' ) ) {\r\n $running_premium_build = $fs->is__premium_only();\r\n }\r\n // Check if paying\r\n if ( method_exists( $fs, 'is_paying' ) && $fs->is_paying() ) {\r\n chatbot_chatgpt_load_insights_files();\r\n } elseif ( method_exists( $fs, 'has_active_valid_license' ) && $fs->has_active_valid_license() ) {\r\n chatbot_chatgpt_load_insights_files();\r\n } elseif ( method_exists( $fs, 'is_trial' ) && $fs->is_trial() && $running_premium_build ) {\r\n chatbot_chatgpt_load_insights_files();\r\n }\r\n }\r\n }\r\n // Handle plan changes and premium activation - Ver 2.4.2\r\n // This ensures Insights files are loaded after plan upgrades\r\n add_action( 'fs_after_account_plan_sync_chatbot-chatgpt', function () {\r\n // When plan is synced, try to load Insights files if premium status is detected\r\n chatbot_chatgpt_load_insights_files();\r\n }, 10 );\r\n add_action( 'fs_after_license_change_chatbot-chatgpt', function () {\r\n // When license changes, try to load Insights files if premium status is detected\r\n chatbot_chatgpt_load_insights_files();\r\n }, 10 );\r\n // Also hook into Freemius after_premium_version_activation if available\r\n if ( function_exists( 'chatbot_chatgpt_freemius' ) ) {\r\n chatbot_chatgpt_freemius()->add_action( 'after_premium_version_activation', function () {\r\n chatbot_chatgpt_load_insights_files();\r\n } );\r\n // Uninstall cleanup runs via Freemius after_uninstall so Freemius can report the event (and user feedback) first.\r\n chatbot_chatgpt_freemius()->add_action( 'after_uninstall', 'chatbot_chatgpt_uninstall' );\r\n }\r\n // Include necessary files - Widgets - Ver 2.1.3\r\n require_once plugin_dir_path( __FILE__ ) . 'widgets/chatbot-manage-widget-logs.php';\r\n // Log the User ID and Session ID - Ver 2.0.6 - 2024 07 11\r\n // Check for Upgrades - Ver 1.7.7\r\n if ( !esc_attr( get_option( 'chatbot_chatgpt_upgraded' ) ) ) {\r\n chatbot_chatgpt_upgrade();\r\n update_option( 'chatbot_chatgpt_upgraded', 'Yes' );\r\n }\r\n // Diagnostics on/off setting can be found on the Settings tab - Ver 2.4.5\r\n $chatbot_chatgpt_diagnostics = esc_attr( get_option( 'chatbot_chatgpt_diagnostics', 'Off' ) );\r\n global $chatbot_ai_platform_choice;\r\n global $model;\r\n global $voice;\r\n // FIXME - SEE AI Platform Selection setting - Ver 2.1.8\r\n $chatbot_ai_platform_choice = esc_attr( get_option( 'chatbot_ai_platform_choice', 'OpenAI' ) );\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n // back_trace( 'NOTICE', 'AI Platform: ' . $chatbot_ai_platform_choice);\r\n switch ( $chatbot_ai_platform_choice ) {\r\n case 'OpenAI':\r\n update_option( 'chatbot_ai_platform_choice', 'OpenAI' );\r\n $chatbot_chatgpt_api_enabled = 'Yes';\r\n update_option( 'chatbot_chatgpt_api_enabled', 'Yes' );\r\n $chatbot_azure_api_enabled = 'No';\r\n update_option( 'chatbot_azure_api_enabled', 'No' );\r\n $chatbot_nvidia_api_enabled = 'No';\r\n update_option( 'chatbot_nvidia_api_enabled', 'No' );\r\n $chatbot_anthropic_api_enabled = 'No';\r\n update_option( 'chatbot_anthropic_api_enabled', 'No' );\r\n $chatbot_deepseek_api_enabled = 'No';\r\n update_option( 'chatbot_deepseek_api_enabled', 'No' );\r\n $chatbot_markov_chain_api_enabled = 'No';\r\n update_option( 'chatbot_markov_chain_api_enabled', 'No' );\r\n $chatbot_transformer_model_api_enabled = 'No';\r\n update_option( 'chatbot_transformer_model_api_enabled', 'No' );\r\n $chatbot_local_api_enabled = 'No';\r\n update_option( 'chatbot_local_api_enabled', 'No' );\r\n $chatbot_mistral_api_enabled = 'No';\r\n update_option( 'chatbot_mistral_api_enabled', 'No' );\r\n $chatbot_google_api_enabled = 'No';\r\n update_option( 'chatbot_google_api_enabled', 'No' );\r\n // Model choice - Ver 1.9.4\r\n if ( esc_attr( get_option( 'chatbot_chatgpt_model_choice' ) ) === null ) {\r\n $model = 'gpt-4-1106-preview';\r\n update_option( 'chatbot_chatgpt_model_choice', $model );\r\n } elseif ( empty( $model ) ) {\r\n $model = 'gpt-4-1106-preview';\r\n }\r\n // Voice choice - Ver 1.9.5\r\n if ( esc_attr( get_option( 'chatbot_chatgpt_voice_option' ) ) === null ) {\r\n $voice = 'alloy';\r\n update_option( 'chatbot_chatgpt_voice_option', $voice );\r\n }\r\n break;\r\n case 'Azure OpenAI':\r\n update_option( 'chatbot_ai_platform_choice', 'Azure OpenAI' );\r\n $chatbot_chatgpt_api_enabled = 'No';\r\n update_option( 'chatbot_chatgpt_api_enabled', 'No' );\r\n $chatbot_azure_api_enabled = 'Yes';\r\n update_option( 'chatbot_azure_api_enabled', 'Yes' );\r\n $chatbot_nvidia_api_enabled = 'No';\r\n update_option( 'chatbot_nvidia_api_enabled', 'No' );\r\n $chatbot_anthropic_api_enabled = 'No';\r\n update_option( 'chatbot_anthropic_api_enabled', 'No' );\r\n $chatbot_deepseek_api_enabled = 'No';\r\n update_option( 'chatbot_deepseek_api_enabled', 'No' );\r\n $chatbot_markov_chain_api_enabled = 'No';\r\n update_option( 'chatbot_markov_chain_api_enabled', 'No' );\r\n $chatbot_transformer_model_api_enabled = 'No';\r\n update_option( 'chatbot_transformer_model_api_enabled', 'No' );\r\n $chatbot_local_api_enabled = 'No';\r\n update_option( 'chatbot_local_api_enabled', 'No' );\r\n $chatbot_mistral_api_enabled = 'No';\r\n update_option( 'chatbot_mistral_api_enabled', 'No' );\r\n $chatbot_google_api_enabled = 'No';\r\n update_option( 'chatbot_google_api_enabled', 'No' );\r\n // Model choice - Ver 1.9.4\r\n if ( esc_attr( get_option( 'chatbot_azure_model_choice' ) ) === null ) {\r\n $model = 'gpt-4-1106-preview';\r\n update_option( 'chatbot_azure_model_choice', $model );\r\n } elseif ( empty( $model ) ) {\r\n $model = 'gpt-4-1106-preview';\r\n }\r\n // FIXME - TEMPORARILY DISABLED - 2025-03-07\r\n // Disable Read Aloud - Ver 2.2.6\r\n update_option( 'chatbot_chatgpt_read_aloud_option', 'no' );\r\n // Voice choice - Ver 1.9.5\r\n // if (esc_attr(get_option('chatbot_azure_voice_option')) === null) {\r\n // $voice = 'alloy';\r\n // update_option('chatbot_azure_voice_option', $voice);\r\n // }\r\n break;\r\n case 'NVIDIA':\r\n update_option( 'chatbot_ai_platform_choice', 'NVIDIA' );\r\n $chatbot_chatgpt_api_enabled = 'No';\r\n update_option( 'chatbot_chatgpt_api_enabled', 'No' );\r\n $chatbot_azure_api_enabled = 'No';\r\n update_option( 'chatbot_azure_api_enabled', 'No' );\r\n $chatbot_nvidia_api_enabled = 'Yes';\r\n update_option( 'chatbot_nvidia_api_enabled', 'Yes' );\r\n $chatbot_anthropic_api_enabled = 'No';\r\n update_option( 'chatbot_anthropic_api_enabled', 'No' );\r\n $chatbot_deepseek_api_enabled = 'No';\r\n update_option( 'chatbot_deepseek_api_enabled', 'No' );\r\n $chatbot_markov_chain_api_enabled = 'No';\r\n update_option( 'chatbot_markov_chain_api_enabled', 'No' );\r\n $chatbot_transformer_model_api_enabled = 'No';\r\n update_option( 'chatbot_transformer_model_api_enabled', 'No' );\r\n $chatbot_local_api_enabled = 'No';\r\n update_option( 'chatbot_local_api_enabled', 'No' );\r\n $chatbot_mistral_api_enabled = 'No';\r\n update_option( 'chatbot_mistral_api_enabled', 'No' );\r\n $chatbot_google_api_enabled = 'No';\r\n update_option( 'chatbot_google_api_enabled', 'No' );\r\n // Model choice - Ver 2.1.8\r\n if ( esc_attr( get_option( 'chatbot_nvidia_model_choice' ) ) === null ) {\r\n $model = 'nvidia/llama-3.1-nemotron-51b-instruct';\r\n update_option( 'chatbot_nvidia_model_choice', $model );\r\n } elseif ( empty( $model ) ) {\r\n $model = 'nvidia/llama-3.1-nemotron-51b-instruct';\r\n }\r\n // Disable Read Aloud - Ver 2.2.1\r\n update_option( 'chatbot_chatgpt_read_aloud_option', 'no' );\r\n // Disable File Uploads - Ver 2.2.1\r\n update_option( 'chatbot_chatgpt_allow_file_uploads', 'No' );\r\n // Disable MP3 Uploads - Ver 2.2.1\r\n update_option( 'chatbot_chatgpt_allow_mp3_uploads', 'No' );\r\n break;\r\n case 'Anthropic':\r\n update_option( 'chatbot_ai_platform_choice', 'Anthropic' );\r\n $chatbot_chatgpt_api_enabled = 'No';\r\n update_option( 'chatbot_chatgpt_api_enabled', 'No' );\r\n $chatbot_azure_api_enabled = 'No';\r\n update_option( 'chatbot_azure_api_enabled', 'No' );\r\n $chatbot_nvidia_api_enabled = 'No';\r\n update_option( 'chatbot_nvidia_api_enabled', 'No' );\r\n $chatbot_anthropic_api_enabled = 'Yes';\r\n update_option( 'chatbot_anthropic_api_enabled', 'Yes' );\r\n $chatbot_deepseek_api_enabled = 'No';\r\n update_option( 'chatbot_deepseek_api_enabled', 'No' );\r\n $chatbot_markov_chain_api_enabled = 'No';\r\n update_option( 'chatbot_markov_chain_api_enabled', 'No' );\r\n $chatbot_transformer_model_api_enabled = 'No';\r\n update_option( 'chatbot_transformer_model_api_enabled', 'No' );\r\n $chatbot_local_api_enabled = 'No';\r\n update_option( 'chatbot_local_api_enabled', 'No' );\r\n $chatbot_mistral_api_enabled = 'No';\r\n update_option( 'chatbot_mistral_api_enabled', 'No' );\r\n $chatbot_google_api_enabled = 'No';\r\n update_option( 'chatbot_google_api_enabled', 'No' );\r\n // Model choice - Ver 2.2.1\r\n if ( esc_attr( get_option( 'chatbot_anthropic_model_choice' ) ) === null ) {\r\n $model = 'claude-3-5-sonnet-latest';\r\n update_option( 'chatbot_anthropic_model_choice', $model );\r\n } elseif ( empty( $model ) ) {\r\n $model = 'claude-3-5-sonnet-latest';\r\n }\r\n // Disable Read Aloud - Ver 2.2.1\r\n update_option( 'chatbot_chatgpt_read_aloud_option', 'no' );\r\n // Disable File Uploads - Ver 2.2.1\r\n update_option( 'chatbot_chatgpt_allow_file_uploads', 'No' );\r\n // Disable MP3 Uploads - Ver 2.2.1\r\n update_option( 'chatbot_chatgpt_allow_mp3_uploads', 'No' );\r\n break;\r\n case 'DeepSeek':\r\n update_option( 'chatbot_ai_platform_choice', 'DeepSeek' );\r\n $chatbot_chatgpt_api_enabled = 'No';\r\n update_option( 'chatbot_chatgpt_api_enabled', 'No' );\r\n $chatbot_azure_api_enabled = 'No';\r\n update_option( 'chatbot_azure_api_enabled', 'No' );\r\n $chatbot_nvidia_api_enabled = 'No';\r\n update_option( 'chatbot_nvidia_api_enabled', 'No' );\r\n $chatbot_anthropic_api_enabled = 'No';\r\n update_option( 'chatbot_anthropic_api_enabled', 'No' );\r\n $chatbot_deepseek_api_enabled = 'Yes';\r\n update_option( 'chatbot_deepseek_api_enabled', 'Yes' );\r\n $chatbot_markov_chain_api_enabled = 'No';\r\n update_option( 'chatbot_markov_chain_api_enabled', 'No' );\r\n $chatbot_transformer_model_api_enabled = 'No';\r\n update_option( 'chatbot_transformer_model_api_enabled', 'No' );\r\n $chatbot_local_api_enabled = 'No';\r\n update_option( 'chatbot_local_api_enabled', 'No' );\r\n $chatbot_mistral_api_enabled = 'No';\r\n update_option( 'chatbot_mistral_api_enabled', 'No' );\r\n $chatbot_google_api_enabled = 'No';\r\n update_option( 'chatbot_google_api_enabled', 'No' );\r\n // Model choice - Ver 2.2.1\r\n if ( esc_attr( get_option( 'chatbot_deepseek_model_choice' ) ) === null ) {\r\n $model = 'deepseek-chat';\r\n update_option( 'chatbot_deepseek_model_choice', $model );\r\n } elseif ( empty( $model ) ) {\r\n $model = 'deepseek-chat';\r\n }\r\n // Disable Read Aloud - Ver 2.2.1\r\n update_option( 'chatbot_chatgpt_read_aloud_option', 'no' );\r\n // Disable File Uploads - Ver 2.2.1\r\n update_option( 'chatbot_chatgpt_allow_file_uploads', 'No' );\r\n // Disable MP3 Uploads - Ver 2.2.1\r\n update_option( 'chatbot_chatgpt_allow_mp3_uploads', 'No' );\r\n break;\r\n case 'Mistral':\r\n update_option( 'chatbot_ai_platform_choice', 'Mistral' );\r\n $chatbot_chatgpt_api_enabled = 'No';\r\n update_option( 'chatbot_chatgpt_api_enabled', 'No' );\r\n $chatbot_azure_api_enabled = 'No';\r\n update_option( 'chatbot_azure_api_enabled', 'No' );\r\n $chatbot_nvidia_api_enabled = 'No';\r\n update_option( 'chatbot_nvidia_api_enabled', 'No' );\r\n $chatbot_anthropic_api_enabled = 'No';\r\n update_option( 'chatbot_anthropic_api_enabled', 'No' );\r\n $chatbot_deepseek_api_enabled = 'No';\r\n update_option( 'chatbot_deepseek_api_enabled', 'No' );\r\n $chatbot_markov_chain_api_enabled = 'No';\r\n update_option( 'chatbot_markov_chain_api_enabled', 'No' );\r\n $chatbot_transformer_model_api_enabled = 'No';\r\n update_option( 'chatbot_transformer_model_api_enabled', 'No' );\r\n $chatbot_local_api_enabled = 'No';\r\n update_option( 'chatbot_local_api_enabled', 'No' );\r\n $chatbot_mistral_api_enabled = 'Yes';\r\n update_option( 'chatbot_mistral_api_enabled', 'Yes' );\r\n $chatbot_google_api_enabled = 'No';\r\n update_option( 'chatbot_google_api_enabled', 'No' );\r\n // Model choice - Ver 2.2.1\r\n if ( esc_attr( get_option( 'chatbot_mistral_model_choice' ) ) === null ) {\r\n $model = 'mistral-small-latest';\r\n update_option( 'chatbot_mistral_model_choice', $model );\r\n } elseif ( empty( $model ) ) {\r\n $model = 'mistral-small-latest';\r\n }\r\n // Disable Read Aloud - Ver 2.2.1\r\n update_option( 'chatbot_chatgpt_read_aloud_option', 'no' );\r\n // Disable File Uploads - Ver 2.2.1\r\n update_option( 'chatbot_chatgpt_allow_file_uploads', 'No' );\r\n // Disable MP3 Uploads - Ver 2.2.1\r\n update_option( 'chatbot_chatgpt_allow_mp3_uploads', 'No' );\r\n break;\r\n case 'Google':\r\n update_option( 'chatbot_ai_platform_choice', 'Google' );\r\n $chatbot_chatgpt_api_enabled = 'No';\r\n update_option( 'chatbot_chatgpt_api_enabled', 'No' );\r\n $chatbot_azure_api_enabled = 'No';\r\n update_option( 'chatbot_azure_api_enabled', 'No' );\r\n $chatbot_nvidia_api_enabled = 'No';\r\n update_option( 'chatbot_nvidia_api_enabled', 'No' );\r\n $chatbot_anthropic_api_enabled = 'No';\r\n update_option( 'chatbot_anthropic_api_enabled', 'No' );\r\n $chatbot_deepseek_api_enabled = 'No';\r\n update_option( 'chatbot_deepseek_api_enabled', 'No' );\r\n $chatbot_markov_chain_api_enabled = 'No';\r\n update_option( 'chatbot_markov_chain_api_enabled', 'No' );\r\n $chatbot_transformer_model_api_enabled = 'No';\r\n update_option( 'chatbot_transformer_model_api_enabled', 'No' );\r\n $chatbot_local_api_enabled = 'No';\r\n update_option( 'chatbot_local_api_enabled', 'No' );\r\n $chatbot_mistral_api_enabled = 'No';\r\n update_option( 'chatbot_mistral_api_enabled', 'No' );\r\n $chatbot_google_api_enabled = 'Yes';\r\n update_option( 'chatbot_google_api_enabled', 'Yes' );\r\n // Model choice - Ver 2.3.9\r\n if ( esc_attr( get_option( 'chatbot_google_model_choice' ) ) === null ) {\r\n $model = 'gemini-2.0-flash';\r\n update_option( 'chatbot_google_model_choice', $model );\r\n } elseif ( empty( $model ) ) {\r\n $model = 'gemini-2.0-flash';\r\n }\r\n // Disable Read Aloud - Ver 2.3.9\r\n update_option( 'chatbot_chatgpt_read_aloud_option', 'no' );\r\n // Disable File Uploads - Ver 2.3.9\r\n update_option( 'chatbot_chatgpt_allow_file_uploads', 'No' );\r\n // Disable MP3 Uploads - Ver 2.3.9\r\n update_option( 'chatbot_chatgpt_allow_mp3_uploads', 'No' );\r\n break;\r\n case 'Markov Chain':\r\n update_option( 'chatbot_ai_platform_choice', 'Markov Chain' );\r\n $chatbot_chatgpt_api_enabled = 'No';\r\n update_option( 'chatbot_chatgpt_api_enabled', 'No' );\r\n $chatbot_azure_api_enabled = 'No';\r\n update_option( 'chatbot_azure_api_enabled', 'No' );\r\n $chatbot_nvidia_api_enabled = 'No';\r\n update_option( 'chatbot_nvidia_api_enabled', 'No' );\r\n $chatbot_anthropic_api_enabled = 'No';\r\n update_option( 'chatbot_anthropic_api_enabled', 'No' );\r\n $chatbot_deepseek_api_enabled = 'No';\r\n update_option( 'chatbot_deepseek_api_enabled', 'No' );\r\n $chatbot_markov_chain_api_enabled = 'Yes';\r\n update_option( 'chatbot_markov_chain_api_enabled', 'Yes' );\r\n $chatbot_transformer_model_api_enabled = 'No';\r\n update_option( 'chatbot_transformer_model_api_enabled', 'No' );\r\n $chatbot_local_api_enabled = 'No';\r\n update_option( 'chatbot_local_api_enabled', 'No' );\r\n $chatbot_mistral_api_enabled = 'No';\r\n update_option( 'chatbot_mistral_api_enabled', 'No' );\r\n $chatbot_google_api_enabled = 'No';\r\n update_option( 'chatbot_google_api_enabled', 'No' );\r\n // Model choice - Ver 2.1.8\r\n if ( esc_attr( get_option( 'chatbot_markov_chain_model_choice' ) ) === null ) {\r\n $model = 'markov-chain-flask';\r\n update_option( 'chatbot_markov_chain_model_choice', $model );\r\n } elseif ( empty( $model ) ) {\r\n $model = 'markov-chain-flask';\r\n }\r\n // Disable Read Aloud - Ver 2.2.1\r\n update_option( 'chatbot_chatgpt_read_aloud_option', 'no' );\r\n // Disable File Uploads - Ver 2.2.1\r\n update_option( 'chatbot_chatgpt_allow_file_uploads', 'No' );\r\n // Disable MP3 Uploads - Ver 2.2.1\r\n update_option( 'chatbot_chatgpt_allow_mp3_uploads', 'No' );\r\n break;\r\n case 'Transformer':\r\n update_option( 'chatbot_ai_platform_choice', 'Transformer' );\r\n $chatbot_chatgpt_api_enabled = 'No';\r\n update_option( 'chatbot_chatgpt_api_enabled', 'No' );\r\n $chatbot_azure_api_enabled = 'No';\r\n update_option( 'chatbot_azure_api_enabled', 'No' );\r\n $chatbot_nvidia_api_enabled = 'No';\r\n update_option( 'chatbot_nvidia_api_enabled', 'No' );\r\n $chatbot_anthropic_api_enabled = 'No';\r\n update_option( 'chatbot_anthropic_api_enabled', 'No' );\r\n $chatbot_deepseek_api_enabled = 'No';\r\n update_option( 'chatbot_deepseek_api_enabled', 'No' );\r\n $chatbot_markov_chain_api_enabled = 'No';\r\n update_option( 'chatbot_markov_chain_api_enabled', 'No' );\r\n $chatbot_transformer_model_api_enabled = 'Yes';\r\n update_option( 'chatbot_transformer_model_api_enabled', 'Yes' );\r\n $chatbot_local_api_enabled = 'No';\r\n update_option( 'chatbot_local_api_enabled', 'No' );\r\n $chatbot_mistral_api_enabled = 'No';\r\n update_option( 'chatbot_mistral_api_enabled', 'No' );\r\n $chatbot_google_api_enabled = 'No';\r\n update_option( 'chatbot_google_api_enabled', 'No' );\r\n // Model choice - Ver 2.2.0\r\n if ( esc_attr( get_option( 'chatbot_transformer_model_choice' ) ) === null ) {\r\n $model = 'sentential-context-model';\r\n update_option( 'chatbot_transformer_model_choice', $model );\r\n } elseif ( empty( $model ) ) {\r\n $model = 'sentential-context-model';\r\n }\r\n // Disable Read Aloud - Ver 2.2.1\r\n update_option( 'chatbot_chatgpt_read_aloud_option', 'no' );\r\n // Disable File Uploads - Ver 2.2.1\r\n update_option( 'chatbot_chatgpt_allow_file_uploads', 'No' );\r\n // Disable MP3 Uploads - Ver 2.2.1\r\n update_option( 'chatbot_chatgpt_allow_mp3_uploads', 'No' );\r\n break;\r\n case 'Local Server':\r\n update_option( 'chatbot_ai_platform_choice', 'Local Server' );\r\n $chatbot_chatgpt_api_enabled = 'No';\r\n update_option( 'chatbot_chatgpt_api_enabled', 'No' );\r\n $chatbot_azure_api_enabled = 'No';\r\n update_option( 'chatbot_azure_api_enabled', 'No' );\r\n $chatbot_nvidia_api_enabled = 'No';\r\n update_option( 'chatbot_nvidia_api_enabled', 'No' );\r\n $chatbot_anthropic_api_enabled = 'No';\r\n update_option( 'chatbot_anthropic_api_enabled', 'No' );\r\n $chatbot_deepseek_api_enabled = 'No';\r\n update_option( 'chatbot_deepseek_api_enabled', 'No' );\r\n $chatbot_markov_chain_api_enabled = 'No';\r\n update_option( 'chatbot_markov_chain_api_enabled', 'No' );\r\n $chatbot_transformer_model_api_enabled = 'No';\r\n update_option( 'chatbot_transformer_model_api_enabled', 'No' );\r\n $chatbot_local_api_enabled = 'Yes';\r\n update_option( 'chatbot_local_api_enabled', 'Yes' );\r\n $chatbot_mistral_api_enabled = 'No';\r\n update_option( 'chatbot_mistral_api_enabled', 'No' );\r\n $chatbot_google_api_enabled = 'No';\r\n update_option( 'chatbot_google_api_enabled', 'No' );\r\n // Model choice - Ver 2.2.0\r\n if ( esc_attr( get_option( 'chatbot_local_model_choice' ) ) === null ) {\r\n $model = 'llama3.2-3b-instruct';\r\n update_option( 'chatbot_local_model_choice', $model );\r\n } elseif ( empty( $model ) ) {\r\n $model = 'llama3.2-3b-instruct';\r\n }\r\n // Disable Read Aloud - Ver 2.2.1\r\n update_option( 'chatbot_chatgpt_read_aloud_option', 'no' );\r\n // Disable File Uploads - Ver 2.2.1\r\n update_option( 'chatbot_chatgpt_allow_file_uploads', 'No' );\r\n // Disable MP3 Uploads - Ver 2.2.1\r\n update_option( 'chatbot_chatgpt_allow_mp3_uploads', 'No' );\r\n break;\r\n default:\r\n update_option( 'chatbot_ai_platform_choice', 'OpenAI' );\r\n $chatbot_chatgpt_api_enabled = 'Yes';\r\n update_option( 'chatbot_chatgpt_api_enabled', 'Yes' );\r\n $chatbot_azure_api_enabled = 'No';\r\n update_option( 'chatbot_azure_api_enabled', 'No' );\r\n $chatbot_nvidia_api_enabled = 'No';\r\n update_option( 'chatbot_nvidia_api_enabled', 'No' );\r\n $chatbot_anthropic_api_enabled = 'No';\r\n update_option( 'chatbot_anthropic_api_enabled', 'No' );\r\n $chatbot_deepseek_api_enabled = 'No';\r\n update_option( 'chatbot_deepseek_api_enabled', 'No' );\r\n $chatbot_markov_chain_api_enabled = 'No';\r\n update_option( 'chatbot_markov_chain_api_enabled', 'No' );\r\n $chatbot_transformer_model_api_enabled = 'No';\r\n update_option( 'chatbot_transformer_model_api_enabled', 'No' );\r\n $chatbot_mistral_api_enabled = 'No';\r\n update_option( 'chatbot_mistral_api_enabled', 'No' );\r\n $chatbot_google_api_enabled = 'No';\r\n update_option( 'chatbot_google_api_enabled', 'No' );\r\n // Model choice - Ver 1.9.4\r\n if ( esc_attr( get_option( 'chatbot_chatgpt_model_choice' ) ) === null ) {\r\n $model = 'gpt-4-1106-preview';\r\n update_option( 'chatbot_chatgpt_model_choice', $model );\r\n } elseif ( empty( $model ) ) {\r\n $model = 'gpt-4-1106-preview';\r\n }\r\n // Voice choice - Ver 1.9.5\r\n if ( esc_attr( get_option( 'chatbot_chatgpt_voice_option' ) ) === null ) {\r\n $voice = 'alloy';\r\n update_option( 'chatbot_chatgpt_voice_option', $voice );\r\n }\r\n break;\r\n }\r\n // Custom buttons on/off setting can be found on the Settings tab - Ver 1.6.5\r\n $chatbot_chatgpt_enable_custom_buttons = esc_attr( get_option( 'chatbot_chatgpt_enable_custom_buttons', 'Off' ) );\r\n // Allow file uploads on/off setting can be found on the Settings tab - Ver 1.7.6\r\n global $chatbot_chatgpt_allow_file_uploads;\r\n $chatbot_ai_platform_choice = esc_attr( get_option( 'chatbot_ai_platform_choice', 'OpenAI' ) );\r\n if ( $chatbot_ai_platform_choice == 'OpenAI' ) {\r\n $chatbot_chatgpt_allow_file_uploads = esc_attr( get_option( 'chatbot_chatgpt_allow_file_uploads', 'No' ) );\r\n } elseif ( $chatbot_ai_platform_choice == 'Azure OpenAI' ) {\r\n $chatbot_chatgpt_allow_file_uploads = esc_attr( get_option( 'chatbot_azure_allow_file_uploads', 'No' ) );\r\n } else {\r\n $chatbot_chatgpt_allow_file_uploads = esc_attr( get_option( 'chatbot_chatgpt_allow_file_uploads', 'No' ) );\r\n }\r\n // Suppress Notices on/off setting can be found on the Settings tab - Ver 1.6.5\r\n global $chatbot_chatgpt_suppress_notices;\r\n $chatbot_chatgpt_suppress_notices = esc_attr( get_option( 'chatbot_chatgpt_suppress_notices', 'Off' ) );\r\n // Suppress Attribution on/off setting can be found on the Settings tab - Ver 1.6.5\r\n global $chatbot_chatgpt_suppress_attribution;\r\n $chatbot_chatgpt_suppress_attribution = esc_attr( get_option( 'chatbot_chatgpt_suppress_attribution', 'On' ) );\r\n // Suppress Learnings Message - Ver 1.7.1\r\n global $chatbot_chatgpt_suppress_learnings;\r\n $chatbot_chatgpt_suppress_learnings = esc_attr( get_option( 'chatbot_chatgpt_suppress_learnings', 'Random' ) );\r\n // Context History - Ver 1.6.1\r\n $context_history = [];\r\n function chatbot_chatgpt_enqueue_admin_scripts() {\r\n global $chatbot_chatgpt_plugin_version;\r\n wp_enqueue_script( 'jquery' );\r\n // Ensure jQuery is enqueued\r\n wp_enqueue_script(\r\n 'chatbot_chatgpt_admin',\r\n plugins_url( 'assets/js/chatbot-chatgpt-admin.js', __FILE__ ),\r\n array('jquery'),\r\n $chatbot_chatgpt_plugin_version,\r\n true\r\n );\r\n }\r\n\r\n add_action( 'admin_enqueue_scripts', 'chatbot_chatgpt_enqueue_admin_scripts' );\r\n // Activation, deactivation, and uninstall functions\r\n register_activation_hook( __FILE__, 'chatbot_chatgpt_activate' );\r\n register_activation_hook( __FILE__, 'create_chatbot_chatgpt_assistants_table' );\r\n register_activation_hook( __FILE__, 'create_chatbot_azure_assistants_table' );\r\n register_deactivation_hook( __FILE__, 'chatbot_chatgpt_deactivate' );\r\n // Uninstall cleanup runs via Freemius after_uninstall (see Freemius block above).\r\n // register_uninstall_hook(__FILE__, 'chatbot_chatgpt_uninstall');\r\n add_action(\r\n 'upgrader_process_complete',\r\n 'chatbot_chatgpt_upgrade_completed',\r\n 10,\r\n 2\r\n );\r\n // Enqueue plugin scripts and styles\r\n function chatbot_chatgpt_enqueue_scripts() {\r\n global $chatbot_chatgpt_plugin_dir_url;\r\n global $chatbot_chatgpt_plugin_version;\r\n global $session_id;\r\n global $user_id;\r\n global $page_id;\r\n global $thread_id;\r\n global $assistant_id;\r\n global $kchat_settings;\r\n global $additional_instructions;\r\n global $model;\r\n global $voice;\r\n global $chatbot_chatgpt_display_style;\r\n // Enqueue the styles\r\n wp_enqueue_style( 'dashicons' );\r\n wp_enqueue_style(\r\n 'chatbot-chatgpt-css',\r\n plugins_url( 'assets/css/chatbot-chatgpt.css', __FILE__ ),\r\n array(),\r\n $chatbot_chatgpt_plugin_version,\r\n 'all'\r\n );\r\n // Now override the default styles with the custom styles - Ver 1.8.1\r\n chatbot_chatgpt_appearance_custom_css_settings();\r\n // Enqueue the scripts\r\n wp_enqueue_script( 'jquery' );\r\n wp_enqueue_script(\r\n 'chatbot-chatgpt-js',\r\n plugins_url( 'assets/js/chatbot-chatgpt.js', __FILE__ ),\r\n array('jquery'),\r\n $chatbot_chatgpt_plugin_version,\r\n true\r\n );\r\n // Enqueue DOMPurify - Ver 1.8.1\r\n // https://raw.githubusercontent.com/cure53/DOMPurify/main/dist/purify.min.js\r\n // https://chat.openai.com/c/275770c1-fa72-404b-97c2-2dad2e8a0230\r\n wp_enqueue_script(\r\n 'dompurify',\r\n plugin_dir_url( __FILE__ ) . 'assets/js/purify.min.js',\r\n array(),\r\n $chatbot_chatgpt_plugin_version,\r\n true\r\n );\r\n // Localize the data for user id and page id\r\n $user_id = get_current_user_id();\r\n $page_id = get_the_id();\r\n // Fetch the User ID - Updated Ver 2.0.6 - 2024 07 11\r\n $user_id = get_current_user_id();\r\n // Fetch the Kognetiks cookie\r\n if ( empty( $session_id ) || $session_id == 0 ) {\r\n $session_id = kognetiks_get_unique_id();\r\n }\r\n // $session_id = kognetiks_get_unique_id();\r\n if ( empty( $user_id ) || $user_id == 0 ) {\r\n $user_id = $session_id;\r\n }\r\n // Check if the $kchat_settings array is empty\r\n if ( !$kchat_settings || !is_array( $kchat_settings ) ) {\r\n $kchat_settings = [];\r\n }\r\n // Initial settings\r\n $kchat_settings = array_merge( $kchat_settings, array(\r\n 'user_id' => $user_id,\r\n 'page_id' => $page_id,\r\n 'session_id' => $session_id,\r\n 'thread_id' => $thread_id,\r\n 'assistant_id' => $assistant_id,\r\n 'additional_instructions' => $additional_instructions,\r\n 'model' => $model,\r\n 'voice' => $voice,\r\n 'chatbot_message_nonce' => wp_create_nonce( 'chatbot_message_nonce' ),\r\n 'chatbot_upload_nonce' => wp_create_nonce( 'chatbot_upload_nonce' ),\r\n 'chatbot_erase_nonce' => wp_create_nonce( 'chatbot_erase_nonce' ),\r\n 'chatbot_unlock_nonce' => wp_create_nonce( 'chatbot_unlock_nonce' ),\r\n 'chatbot_reset_nonce' => wp_create_nonce( 'chatbot_reset_nonce' ),\r\n 'chatbot_queue_nonce' => wp_create_nonce( 'chatbot_queue_nonce' ),\r\n 'chatbot_tts_nonce' => wp_create_nonce( 'chatbot_tts_nonce' ),\r\n 'chatbot_transcript_nonce' => wp_create_nonce( 'chatbot_transcript_nonce' ),\r\n 'nonce_timestamp' => time() * 1000,\r\n ) );\r\n // Set visitor and logged in user limits - Ver 2.0.1\r\n if ( is_user_logged_in() ) {\r\n $kchat_settings['chatbot_chatgpt_message_limit_setting'] = esc_attr( get_option( 'chatbot_chatgpt_user_message_limit_setting', '999' ) );\r\n $kchat_settings['chatbot_chatgpt_message_limit_period_setting'] = esc_attr( get_option( 'chatbot_chatgpt_user_message_limit_period_setting', 'Lifetime' ) );\r\n $kchat_settings['chatbot_chatgpt_display_message_count'] = esc_attr( get_option( 'chatbot_chatgpt_display_message_count', 'No' ) );\r\n } else {\r\n $kchat_settings['chatbot_chatgpt_message_limit_setting'] = esc_attr( get_option( 'chatbot_chatgpt_visitor_message_limit_setting', '999' ) );\r\n $kchat_settings['chatbot_chatgpt_message_limit_period_setting'] = esc_attr( get_option( 'chatbot_chatgpt_visitor_message_limit_period_setting', 'Lifetime' ) );\r\n $kchat_settings['chatbot_chatgpt_display_message_count'] = esc_attr( get_option( 'chatbot_chatgpt_display_message_count', 'No' ) );\r\n }\r\n // Localize the data for the chatbot - Ver 2.1.1.1\r\n $kchat_settings = array_merge( $kchat_settings, array(\r\n 'chatbot_chatgpt_display_style' => $chatbot_chatgpt_display_style,\r\n 'chatbot_chatgpt_version' => $chatbot_chatgpt_plugin_version,\r\n 'plugins_url' => $chatbot_chatgpt_plugin_dir_url,\r\n 'ajax_url' => admin_url( 'admin-ajax.php' ),\r\n 'user_id' => $user_id,\r\n 'page_id' => $page_id,\r\n 'session_id' => $session_id,\r\n 'thread_id' => $thread_id,\r\n 'assistant_id' => $assistant_id,\r\n 'additional_instructions' => $additional_instructions,\r\n 'model' => $model,\r\n 'voice' => $voice,\r\n 'chatbot_chatgpt_timeout_setting' => esc_attr( get_option( 'chatbot_chatgpt_timeout_setting', '240' ) ),\r\n 'chatbot_chatgpt_avatar_icon_setting' => esc_attr( get_option( 'chatbot_chatgpt_avatar_icon_setting', '' ) ),\r\n 'chatbot_chatgpt_custom_avatar_icon_setting' => esc_attr( get_option( 'chatbot_chatgpt_custom_avatar_icon_setting', '' ) ),\r\n '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?' ) ),\r\n 'chatbot_chatgpt_force_page_reload' => esc_attr( get_option( 'chatbot_chatgpt_force_page_reload', 'No' ) ),\r\n 'chatbot_chatgpt_custom_error_message' => esc_attr( get_option( 'chatbot_chatgpt_custom_error_message', 'Your custom error message goes here.' ) ),\r\n ) );\r\n $kchat_settings_json = wp_json_encode( $kchat_settings );\r\n // Enqueue the main chatbot script - CHANGED TO LOAD ORDER IN V2.1.2\r\n wp_enqueue_script(\r\n 'chatbot-chatgpt-js',\r\n plugins_url( 'assets/js/chatbot-chatgpt.js', __FILE__ ),\r\n array(),\r\n $chatbot_chatgpt_plugin_version,\r\n true\r\n );\r\n // Add the inline script to define kchat_settings before the main script runs - CHANGED THE LOAD ORDER IN VER 2.1.2\r\n 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' );\r\n // FIXME - REMOVED IN V2.1.2\r\n // 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');\r\n }\r\n\r\n add_action( 'wp_enqueue_scripts', 'chatbot_chatgpt_enqueue_scripts' );\r\n // Enqueue MathJax with custom configuration - Ver 2.1.2\r\n // https://docs.mathjax.org/en/latest/\r\n // https://github.com/mathjax/MathJax/blob/master/LICENSE\r\n // https://cdnjs.cloudflare.com/ajax/libs/mathjax/3.2.0/es5/tex-mml-chtml.js\r\n // https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js\r\n function enqueue_mathjax_with_custom_config() {\r\n // Check to see if MathJax is enabled\r\n if ( esc_attr( get_option( 'chatbot_chatgpt_enable_mathjax', 'Yes' ) ) === 'Yes' ) {\r\n global $chatbot_chatgpt_plugin_version;\r\n global $chatbot_chatgpt_plugin_dir_url;\r\n // Add the MathJax configuration script\r\n $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 \";\r\n // Enqueue the MathJax script\r\n // wp_enqueue_script( 'mathjax', plugin_dir_url(__FILE__) . 'assets/js/tex-chtml.js', array(), $chatbot_chatgpt_plugin_version, true );\r\n wp_enqueue_script(\r\n 'mathjax',\r\n $chatbot_chatgpt_plugin_dir_url . 'assets/js/tex-mml-chtml.js',\r\n array(),\r\n $chatbot_chatgpt_plugin_version,\r\n true\r\n );\r\n // Add the inline script before MathJax script\r\n wp_add_inline_script( 'mathjax', $mathjax_config, 'before' );\r\n }\r\n }\r\n\r\n add_action( 'wp_enqueue_scripts', 'enqueue_mathjax_with_custom_config' );\r\n // CORS - Cross Origin Resource Sharing - CAUTION: This allows all domains to access the end point - Ver 2.1.2\r\n // function allow_cross_domain_requests() {\r\n // header(\"Access-Control-Allow-Origin: *\");\r\n // header(\"Access-Control-Allow-Methods: GET, POST, OPTIONS\");\r\n // header(\"Access-Control-Allow-Headers: X-Requested-With\");\r\n // }\r\n // add_action('init', 'allow_cross_domain_requests');\r\n // Settings and Deactivation Links - Ver - 1.5.0\r\n if ( !function_exists( 'enqueue_jquery_ui' ) ) {\r\n function enqueue_jquery_ui() {\r\n wp_enqueue_style( 'wp-jquery-ui-dialog' );\r\n wp_enqueue_script( 'jquery-ui-dialog' );\r\n }\r\n\r\n add_action( 'admin_enqueue_scripts', 'enqueue_jquery_ui' );\r\n }\r\n // Schedule Cleanup of Expired Transients\r\n if ( !wp_next_scheduled( 'chatbot_chatgpt_cleanup_event' ) ) {\r\n wp_schedule_event( time(), 'daily', 'chatbot_chatgpt_cleanup_event' );\r\n }\r\n add_action( 'chatbot_chatgpt_cleanup_event', 'clean_specific_expired_transients' );\r\n // Schedule Conversation Log Cleanup - Ver 1.6.7\r\n if ( !wp_next_scheduled( 'chatbot_chatgpt_conversation_log_cleanup_event' ) ) {\r\n wp_schedule_event( time(), 'daily', 'chatbot_chatgpt_conversation_log_cleanup_event' );\r\n }\r\n add_action( 'chatbot_chatgpt_conversation_log_cleanup_event', 'chatbot_chatgpt_conversation_log_cleanup' );\r\n // Schedule the transcript file cleanup event if it's not already scheduled - Ver 1.9.9\r\n // Schedule the cleanup event if it's not already scheduled\r\n if ( !wp_next_scheduled( 'chatbot_chatgpt_cleanup_transcript_files' ) ) {\r\n wp_schedule_event( time(), 'hourly', 'chatbot_chatgpt_cleanup_transcript_files' );\r\n }\r\n // Deactivate old hooks - Ver 2.0.1\r\n if ( esc_attr( get_option( 'chatbot_chatgpt_cleanup_old_hooks' ) !== 'Completed' ) ) {\r\n // Deactivate old hooks - Ver 2.0.1\r\n wp_clear_scheduled_hook( 'chatbot_chatgpt_cleanup_transcripts' );\r\n // Then update the option\r\n update_option( 'chatbot_chatgpt_cleanup_old_hooks', 'Completed' );\r\n }\r\n // Schedule the audio file cleanup event if it's not already scheduled - Ver 1.9.9\r\n // Schedule the cleanup event if it's not already scheduled\r\n if ( !wp_next_scheduled( 'chatbot_chatgpt_cleanup_audio_files' ) ) {\r\n wp_schedule_event( time(), 'hourly', 'chatbot_chatgpt_cleanup_audio_files' );\r\n }\r\n // Schedule the upload file cleanup event if it's not already scheduled - Ver 1.9.9\r\n // Schedule the cleanup event if it's not already scheduled\r\n if ( !wp_next_scheduled( 'chatbot_chatgpt_cleanup_upload_files' ) ) {\r\n wp_schedule_event( time(), 'hourly', 'chatbot_chatgpt_cleanup_upload_files' );\r\n }\r\n // Schedule the download file cleanup event if it's not already scheduled - Ver 2.0.3\r\n // Schedule the cleanup event if it's not already scheduled\r\n if ( !wp_next_scheduled( 'chatbot_chatgpt_cleanup_download_files' ) ) {\r\n wp_schedule_event( time(), 'hourly', 'chatbot_chatgpt_cleanup_download_files' );\r\n }\r\n // Add the Opean AI Assistant table to the database - Ver 2.0.4\r\n // REMOVED Ver 2.2.7 and MOVED to the activation hook\r\n // create_chatbot_chatgpt_assistants_table();\r\n // Add the Azure Assistants table to the database - Ver 2.2.6\r\n // REMOVED Ver 2.2.7 and MOVED to the activation hook\r\n // create_chatbot_azure_assistants_table();\r\n // Message Queue Management Functions\r\n function chatbot_chatgpt_enqueue_message(\r\n $user_id,\r\n $page_id,\r\n $session_id,\r\n $assistant_id,\r\n $message,\r\n $client_message_id = null\r\n ) {\r\n $queue_key = 'chatbot_message_queue_' . wp_hash( $assistant_id . '|' . $user_id . '|' . $page_id . '|' . $session_id );\r\n $queue = get_transient( $queue_key );\r\n if ( !$queue ) {\r\n $queue = [];\r\n }\r\n $queue_item = [\r\n 'message' => $message,\r\n 'client_message_id' => ( $client_message_id ?: wp_generate_uuid4() ),\r\n 'timestamp' => time(),\r\n 'user_id' => $user_id,\r\n 'page_id' => $page_id,\r\n 'session_id' => $session_id,\r\n 'assistant_id' => $assistant_id,\r\n ];\r\n $queue[] = $queue_item;\r\n set_transient( $queue_key, $queue, 3600 );\r\n // 1 hour expiry\r\n return $queue_item['client_message_id'];\r\n }\r\n\r\n function chatbot_chatgpt_dequeue_message(\r\n $user_id,\r\n $page_id,\r\n $session_id,\r\n $assistant_id\r\n ) {\r\n $queue_key = 'chatbot_message_queue_' . wp_hash( $assistant_id . '|' . $user_id . '|' . $page_id . '|' . $session_id );\r\n $queue = get_transient( $queue_key );\r\n if ( !$queue || empty( $queue ) ) {\r\n return null;\r\n }\r\n $message = array_shift( $queue );\r\n if ( empty( $queue ) ) {\r\n delete_transient( $queue_key );\r\n } else {\r\n set_transient( $queue_key, $queue, 3600 );\r\n }\r\n return $message;\r\n }\r\n\r\n function chatbot_chatgpt_get_queue_status(\r\n $user_id,\r\n $page_id,\r\n $session_id,\r\n $assistant_id\r\n ) {\r\n $queue_key = 'chatbot_message_queue_' . wp_hash( $assistant_id . '|' . $user_id . '|' . $page_id . '|' . $session_id );\r\n $queue = get_transient( $queue_key );\r\n return [\r\n 'has_messages' => !empty( $queue ),\r\n 'count' => ( $queue ? count( $queue ) : 0 ),\r\n 'next_message' => ( $queue ? $queue[0] : null ),\r\n ];\r\n }\r\n\r\n function chatbot_chatgpt_process_queue(\r\n $user_id,\r\n $page_id,\r\n $session_id,\r\n $assistant_id\r\n ) {\r\n $queue_status = chatbot_chatgpt_get_queue_status(\r\n $user_id,\r\n $page_id,\r\n $session_id,\r\n $assistant_id\r\n );\r\n if ( !$queue_status['has_messages'] ) {\r\n return false;\r\n }\r\n $message_data = chatbot_chatgpt_dequeue_message(\r\n $user_id,\r\n $page_id,\r\n $session_id,\r\n $assistant_id\r\n );\r\n if ( !$message_data ) {\r\n return false;\r\n }\r\n // Set conversation lock for the queued message\r\n $conv_lock = 'chatgpt_conv_lock_' . wp_hash( $assistant_id . '|' . $user_id . '|' . $page_id . '|' . $session_id );\r\n set_transient( $conv_lock, true, 60 );\r\n // Process the message using the existing logic\r\n $response = chatbot_chatgpt_process_queued_message( $message_data );\r\n // Clear conversation lock\r\n delete_transient( $conv_lock );\r\n // Recursively process the next message in queue\r\n chatbot_chatgpt_process_queue(\r\n $user_id,\r\n $page_id,\r\n $session_id,\r\n $assistant_id\r\n );\r\n return true;\r\n }\r\n\r\n // AJAX handler to get queue status\r\n function chatbot_chatgpt_get_queue_status_ajax() {\r\n // Security: Verify nonce for CSRF protection\r\n if ( !isset( $_POST['chatbot_nonce'] ) || !wp_verify_nonce( $_POST['chatbot_nonce'], 'chatbot_queue_nonce' ) ) {\r\n wp_send_json_error( 'Security check failed. Please refresh the page and try again.', 403 );\r\n return;\r\n }\r\n $user_id = sanitize_text_field( $_POST['user_id'] );\r\n $page_id = sanitize_text_field( $_POST['page_id'] );\r\n $session_id = sanitize_text_field( $_POST['session_id'] );\r\n $assistant_id = sanitize_text_field( $_POST['assistant_id'] );\r\n if ( !$user_id || !$page_id || !$session_id || !$assistant_id ) {\r\n wp_send_json_error( 'Missing required parameters' );\r\n return;\r\n }\r\n $queue_status = chatbot_chatgpt_get_queue_status(\r\n $user_id,\r\n $page_id,\r\n $session_id,\r\n $assistant_id\r\n );\r\n wp_send_json_success( $queue_status );\r\n }\r\n\r\n function chatbot_chatgpt_process_queued_message( $message_data ) {\r\n // This function processes a queued message using the same logic as the main handler\r\n // but without the AJAX response handling\r\n global $session_id;\r\n global $user_id;\r\n global $page_id;\r\n global $thread_id;\r\n global $assistant_id;\r\n global $chatbot_chatgpt_assistant_alias;\r\n global $kchat_settings;\r\n global $additional_instructions;\r\n global $model;\r\n global $voice;\r\n global $flow_data;\r\n $api_key = '';\r\n $message = $message_data['message'];\r\n $user_id = $message_data['user_id'];\r\n $page_id = $message_data['page_id'];\r\n $session_id = $message_data['session_id'];\r\n $assistant_id = $message_data['assistant_id'];\r\n $client_message_id = $message_data['client_message_id'];\r\n $chatbot_ai_platform_choice = esc_attr( get_option( 'chatbot_ai_platform_choice', 'OpenAI' ) );\r\n // Get API key and model based on platform choice\r\n switch ( $chatbot_ai_platform_choice ) {\r\n case 'OpenAI':\r\n $api_key = esc_attr( get_option( 'chatbot_chatgpt_api_key' ) );\r\n $api_key = chatbot_chatgpt_decrypt_api_key( $api_key );\r\n $model = esc_attr( get_option( 'chatbot_chatgpt_model_choice', 'gpt-4-1106-preview' ) );\r\n break;\r\n case 'Azure OpenAI':\r\n $api_key = esc_attr( get_option( 'chatbot_azure_api_key' ) );\r\n $api_key = chatbot_chatgpt_decrypt_api_key( $api_key );\r\n $model = esc_attr( get_option( 'chatbot_azure_model_choice', 'gpt-4-1106-preview' ) );\r\n break;\r\n case 'NVIDIA':\r\n $api_key = esc_attr( get_option( 'chatbot_nvidia_api_key' ) );\r\n $api_key = chatbot_chatgpt_decrypt_api_key( $api_key );\r\n $model = esc_attr( get_option( 'chatbot_nvidia_model_choice', 'nvidia/llama-3.1-nemotron-51b-instruct' ) );\r\n break;\r\n case 'Anthropic':\r\n $api_key = esc_attr( get_option( 'chatbot_anthropic_api_key' ) );\r\n $api_key = chatbot_chatgpt_decrypt_api_key( $api_key );\r\n $model = esc_attr( get_option( 'chatbot_anthropic_model_choice', 'claude-3-5-sonnet-latest' ) );\r\n break;\r\n case 'DeepSeek':\r\n $api_key = esc_attr( get_option( 'chatbot_deepseek_api_key' ) );\r\n $api_key = chatbot_chatgpt_decrypt_api_key( $api_key );\r\n $model = esc_attr( get_option( 'chatbot_deepseek_model_choice', 'deepseek-chat' ) );\r\n break;\r\n case 'Google':\r\n $api_key = esc_attr( get_option( 'chatbot_google_api_key' ) );\r\n $api_key = chatbot_chatgpt_decrypt_api_key( $api_key );\r\n $model = esc_attr( get_option( 'chatbot_google_model_choice', 'gemini-2.0-flash' ) );\r\n break;\r\n case 'Markov Chain':\r\n $api_key = esc_attr( get_option( 'chatbot_markov_chain_api_key', 'NOT REQUIRED' ) );\r\n $model = esc_attr( get_option( 'chatbot_markov_chain_model_choice', 'markov-chain-flask' ) );\r\n break;\r\n case 'Transformer':\r\n $api_key = esc_attr( get_option( 'chatbot_transformer_api_key', 'NOT REQUIRED' ) );\r\n $model = esc_attr( get_option( 'chatbot_transformer_model_choice', 'lexical-context-model' ) );\r\n break;\r\n case 'Local Server':\r\n $api_key = esc_attr( get_option( 'chatbot_local_api_key', 'NOT REQUIRED' ) );\r\n $api_key = chatbot_chatgpt_decrypt_api_key( $api_key );\r\n $model = esc_attr( get_option( 'chatbot_local_model_choice', 'llama3.2-3b-instruct' ) );\r\n break;\r\n case 'Mistral':\r\n $api_key = esc_attr( get_option( 'chatbot_mistral_api_key' ) );\r\n $api_key = chatbot_chatgpt_decrypt_api_key( $api_key );\r\n $model = esc_attr( get_option( 'chatbot_mistral_model_choice', 'mistral-small-latest' ) );\r\n break;\r\n default:\r\n $api_key = esc_attr( get_option( 'chatbot_chatgpt_api_key' ) );\r\n $api_key = chatbot_chatgpt_decrypt_api_key( $api_key );\r\n $model = esc_attr( get_option( 'chatbot_chatgpt_model_choice', 'gpt-3.5-turbo' ) );\r\n break;\r\n }\r\n // Retrieve settings from transients (same as main handler) - Ver 2.3.6\r\n $kchat_settings['chatbot_chatgpt_display_style'] = get_chatbot_chatgpt_transients(\r\n 'display_style',\r\n $user_id,\r\n $page_id,\r\n $session_id\r\n );\r\n $kchat_settings['chatbot_chatgpt_assistant_alias'] = get_chatbot_chatgpt_transients(\r\n 'assistant_alias',\r\n $user_id,\r\n $page_id,\r\n $session_id\r\n );\r\n $kchat_settings['assistant_id'] = get_chatbot_chatgpt_transients(\r\n 'assistant_id',\r\n $user_id,\r\n $page_id,\r\n $session_id\r\n );\r\n $kchat_settings['thread_id'] = get_chatbot_chatgpt_transients(\r\n 'thread_id',\r\n $user_id,\r\n $page_id,\r\n $session_id\r\n );\r\n $kchat_settings['chatbot_chatgpt_model'] = get_chatbot_chatgpt_transients(\r\n 'model',\r\n $user_id,\r\n $page_id,\r\n $session_id\r\n );\r\n $kchat_settings['model'] = ( $kchat_settings['chatbot_chatgpt_model'] ?: $model );\r\n $kchat_settings['chatbot_chatgpt_voice_option'] = get_chatbot_chatgpt_transients(\r\n 'voice',\r\n $user_id,\r\n $page_id,\r\n $session_id\r\n );\r\n $kchat_settings['additional_instructions'] = get_chatbot_chatgpt_transients(\r\n 'additional_instructions',\r\n $user_id,\r\n $page_id,\r\n $session_id\r\n );\r\n $voice = $kchat_settings['chatbot_chatgpt_voice_option'];\r\n $model = ( $kchat_settings['model'] ?: $model );\r\n $additional_instructions = $kchat_settings['additional_instructions'];\r\n $chatbot_chatgpt_assistant_alias = $kchat_settings['chatbot_chatgpt_assistant_alias'];\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n // back_trace('NOTICE', '$kchat_settings[\\'chatbot_chatgpt_assistant_alias\\']: ' . $kchat_settings['chatbot_chatgpt_assistant_alias']);\r\n // back_trace('NOTICE', '$kchat_settings[\\'assistant_id\\']: ' . $kchat_settings['assistant_id']);\r\n // Override assistant_id from transient if available - Ver 2.3.6\r\n if ( !empty( $kchat_settings['assistant_id'] ) ) {\r\n $assistant_id = $kchat_settings['assistant_id'];\r\n }\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n // back_trace('NOTICE', '$kchat_settings[\\'chatbot_chatgpt_assistant_alias\\']: ' . $kchat_settings['chatbot_chatgpt_assistant_alias']);\r\n // back_trace('NOTICE', '$kchat_settings[\\'assistant_id\\']: ' . $kchat_settings['assistant_id']);\r\n // back_trace('NOTICE', '$assistant_id: ' . $assistant_id);\r\n // Get thread information\r\n $thread_id = get_chatbot_chatgpt_threads(\r\n $user_id,\r\n $session_id,\r\n $page_id,\r\n $assistant_id\r\n );\r\n // Log the message\r\n append_message_to_conversation_log(\r\n $session_id,\r\n $user_id,\r\n $page_id,\r\n 'Visitor',\r\n $thread_id,\r\n $assistant_id,\r\n null,\r\n $message\r\n );\r\n // Determine whether to use assistant_id or regular ChatGPT API (same logic as main handler) - Ver 2.3.6\r\n // Which Assistant ID to use - Ver 1.7.2\r\n if ( $chatbot_chatgpt_assistant_alias == 'original' ) {\r\n $use_assistant_id = 'No';\r\n } elseif ( $chatbot_chatgpt_assistant_alias == 'primary' ) {\r\n $assistant_id = esc_attr( get_option( 'assistant_id' ) );\r\n $use_assistant_id = 'Yes';\r\n // Check if the GPT Assistant ID is blank, null, or \"Please provide the GPT Assistant ID.\"\r\n if ( empty( $assistant_id ) || $assistant_id == \"Please provide the Assistant Id.\" ) {\r\n // Primary assistant_id not set\r\n $chatbot_chatgpt_assistant_alias = 'original';\r\n $use_assistant_id = 'No';\r\n }\r\n } elseif ( $chatbot_chatgpt_assistant_alias == 'alternate' ) {\r\n $assistant_id = esc_attr( get_option( 'chatbot_chatgpt_assistant_id_alternate' ) );\r\n $use_assistant_id = 'Yes';\r\n // Check if the GPT Assistant ID is blank, null, or \"Please provide the GPT Assistant ID.\"\r\n if ( empty( $assistant_id ) || $assistant_id == \"Please provide the Assistant Id.\" ) {\r\n /// Alternate assistant_id not set\r\n $chatbot_chatgpt_assistant_alias = 'original';\r\n $use_assistant_id = 'No';\r\n }\r\n } elseif ( str_starts_with( $assistant_id, 'asst_' ) ) {\r\n $chatbot_chatgpt_assistant_alias = $assistant_id;\r\n // Belt & Suspenders\r\n $use_assistant_id = 'Yes';\r\n } elseif ( str_starts_with( $assistant_id, 'pmpt_' ) ) {\r\n $chatbot_chatgpt_assistant_alias = $assistant_id;\r\n // Belt & Suspenders\r\n $use_assistant_id = 'Yes';\r\n } elseif ( str_starts_with( $assistant_id, 'ag:' ) ) {\r\n $chatbot_chatgpt_assistant_alias = $assistant_id;\r\n // Belt & Suspenders\r\n $use_assistant_id = 'Yes';\r\n } elseif ( str_starts_with( $assistant_id, 'websearch' ) ) {\r\n $chatbot_chatgpt_assistant_alias = $assistant_id;\r\n // Belt & Suspenders\r\n $use_assistant_id = 'Yes';\r\n } else {\r\n // Reference GPT Assistant IDs directly - Ver 1.7.3\r\n // Check both $chatbot_chatgpt_assistant_alias and $assistant_id - Ver 2.3.6\r\n if ( !empty( $chatbot_chatgpt_assistant_alias ) && (str_starts_with( $chatbot_chatgpt_assistant_alias, 'asst_' ) || str_starts_with( $chatbot_chatgpt_assistant_alias, 'pmpt_' ) || str_starts_with( $chatbot_chatgpt_assistant_alias, 'ag:' ) || str_starts_with( $chatbot_chatgpt_assistant_alias, 'websearch' )) ) {\r\n // Override the $assistant_id with the GPT Assistant ID\r\n $assistant_id = $chatbot_chatgpt_assistant_alias;\r\n $use_assistant_id = 'Yes';\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n // back_trace('NOTICE', 'Using Assistant ID - Ver 2.4.5');\r\n // back_trace('NOTICE', 'Assistant ID: ' . $assistant_id);\r\n // back_trace('NOTICE', 'Use Assistant ID: ' . $use_assistant_id);\r\n // back_trace('NOTICE', 'Chatbot ChatGPT Assistant Alias: ' . $chatbot_chatgpt_assistant_alias);\r\n } elseif ( !empty( $assistant_id ) && (str_starts_with( $assistant_id, 'asst_' ) || str_starts_with( $assistant_id, 'pmpt_' ) || str_starts_with( $assistant_id, 'ag:' ) || str_starts_with( $assistant_id, 'websearch' )) ) {\r\n // Set the alias to match the assistant_id\r\n $chatbot_chatgpt_assistant_alias = $assistant_id;\r\n $use_assistant_id = 'Yes';\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n // back_trace('NOTICE', 'Using Assistant ID - Ver 2.4.5');\r\n // back_trace('NOTICE', 'Assistant ID: ' . $assistant_id);\r\n // back_trace('NOTICE', 'Use Assistant ID: ' . $use_assistant_id);\r\n // back_trace('NOTICE', 'Chatbot ChatGPT Assistant Alias: ' . $chatbot_chatgpt_assistant_alias);\r\n } else {\r\n // Override the $use_assistant_id and set it to 'No'\r\n $use_assistant_id = 'No';\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n // back_trace('NOTICE', 'Using Original Assistant ID - Ver 2.4.5');\r\n // back_trace('NOTICE', 'Assistant ID: ' . $assistant_id);\r\n // back_trace('NOTICE', 'Use Assistant ID: ' . $use_assistant_id);\r\n // back_trace('NOTICE', 'Chatbot ChatGPT Assistant Alias: ' . $chatbot_chatgpt_assistant_alias);\r\n }\r\n }\r\n // Process the message based on platform and use_assistant_id - Ver 2.3.6\r\n // Check if we should use assistant_id or regular API\r\n if ( $use_assistant_id == 'Yes' && $chatbot_ai_platform_choice == 'OpenAI' && str_starts_with( $assistant_id, 'asst_' ) ) {\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n // back_trace('NOTICE', 'Using Assistant ID - Ver 2.4.5');\r\n // back_trace('NOTICE', 'Assistant ID: ' . $assistant_id);\r\n // back_trace('NOTICE', 'Use Assistant ID: ' . $use_assistant_id);\r\n // back_trace('NOTICE', 'Chatbot ChatGPT Assistant Alias: ' . $chatbot_chatgpt_assistant_alias);\r\n $response = chatbot_chatgpt_custom_gpt_call_api(\r\n $api_key,\r\n $message,\r\n $assistant_id,\r\n $thread_id,\r\n $session_id,\r\n $user_id,\r\n $page_id,\r\n $client_message_id\r\n );\r\n } elseif ( $use_assistant_id == 'Yes' && $chatbot_ai_platform_choice == 'OpenAI' && str_starts_with( $assistant_id, 'pmpt_' ) ) {\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n // back_trace('NOTICE', 'Using Prompt ID - Ver 2.4.5');\r\n // back_trace('NOTICE', 'Prompt ID: ' . $assistant_id);\r\n // back_trace('NOTICE', 'Use Assistant ID: ' . $use_assistant_id);\r\n // back_trace('NOTICE', 'Chatbot ChatGPT Assistant Alias: ' . $chatbot_chatgpt_assistant_alias);\r\n $response = chatbot_chatgpt_custom_pmpt_call_api(\r\n $api_key,\r\n $message,\r\n $assistant_id,\r\n $thread_id,\r\n $session_id,\r\n $user_id,\r\n $page_id,\r\n $client_message_id\r\n );\r\n } elseif ( $use_assistant_id == 'Yes' && $chatbot_ai_platform_choice == 'Azure OpenAI' ) {\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n // back_trace('NOTICE', 'Using Azure OpenAI - Ver 2.4.5');\r\n // back_trace('NOTICE', 'Azure OpenAI ID: ' . $assistant_id);\r\n // back_trace('NOTICE', 'Use Assistant ID: ' . $use_assistant_id);\r\n // back_trace('NOTICE', 'Chatbot ChatGPT Assistant Alias: ' . $chatbot_chatgpt_assistant_alias);\r\n $response = chatbot_azure_custom_gpt_call_api(\r\n $api_key,\r\n $message,\r\n $assistant_id,\r\n $thread_id,\r\n $session_id,\r\n $user_id,\r\n $page_id,\r\n $client_message_id\r\n );\r\n } elseif ( $use_assistant_id == 'Yes' && $chatbot_ai_platform_choice == 'Mistral' ) {\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n // back_trace('NOTICE', 'Using Mistral Agent ID - Ver 2.4.5');\r\n // back_trace('NOTICE', 'Mistral Agent ID: ' . $assistant_id);\r\n // back_trace('NOTICE', 'Use Assistant ID: ' . $use_assistant_id);\r\n // back_trace('NOTICE', 'Chatbot ChatGPT Assistant Alias: ' . $chatbot_chatgpt_assistant_alias);\r\n $response = chatbot_mistral_agent_call_api(\r\n $api_key,\r\n $message,\r\n $assistant_id,\r\n $thread_id,\r\n $session_id,\r\n $user_id,\r\n $page_id,\r\n $client_message_id\r\n );\r\n } else {\r\n // Use regular API calls (not assistant_id)\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n // back_trace('NOTICE', 'Using Regular API - Ver 2.4.5');\r\n // back_trace('NOTICE', 'Chatbot AI Platform Choice: ' . $chatbot_ai_platform_choice);\r\n // back_trace('NOTICE', 'Use Assistant ID: ' . $use_assistant_id);\r\n // back_trace('NOTICE', 'Chatbot ChatGPT Assistant Alias: ' . $chatbot_chatgpt_assistant_alias);\r\n switch ( $chatbot_ai_platform_choice ) {\r\n case 'OpenAI':\r\n // Determine which OpenAI API to call based on model\r\n if ( str_starts_with( $model, 'gpt-4o' ) ) {\r\n $response = chatbot_chatgpt_call_omni(\r\n $api_key,\r\n $message,\r\n $user_id,\r\n $page_id,\r\n $session_id,\r\n $assistant_id,\r\n $client_message_id\r\n );\r\n } elseif ( str_starts_with( $model, 'gpt' ) ) {\r\n $response = chatbot_chatgpt_call_api(\r\n $api_key,\r\n $message,\r\n $user_id,\r\n $page_id,\r\n $session_id,\r\n $assistant_id,\r\n $client_message_id\r\n );\r\n } elseif ( str_starts_with( $model, 'dall' ) ) {\r\n $response = chatbot_chatgpt_call_image_api(\r\n $api_key,\r\n $message,\r\n $user_id,\r\n $page_id,\r\n $session_id,\r\n $assistant_id,\r\n $client_message_id\r\n );\r\n } elseif ( str_starts_with( $model, 'tts' ) ) {\r\n $response = chatbot_chatgpt_call_tts_api(\r\n $api_key,\r\n $message,\r\n $voice,\r\n $user_id,\r\n $page_id,\r\n $session_id,\r\n $assistant_id,\r\n $client_message_id\r\n );\r\n } elseif ( str_starts_with( $model, 'whisper' ) ) {\r\n $response = chatbot_chatgpt_call_stt_api( $api_key, $message );\r\n } else {\r\n $response = chatbot_chatgpt_call_api(\r\n $api_key,\r\n $message,\r\n $user_id,\r\n $page_id,\r\n $session_id,\r\n $assistant_id,\r\n $client_message_id\r\n );\r\n }\r\n break;\r\n case 'Azure OpenAI':\r\n $response = chatbot_call_azure_openai_api( $api_key, $message );\r\n break;\r\n case 'NVIDIA':\r\n $response = chatbot_nvidia_call_api( $api_key, $message );\r\n break;\r\n case 'Anthropic':\r\n $response = chatbot_call_anthropic_api( $api_key, $message );\r\n break;\r\n case 'DeepSeek':\r\n $response = chatbot_call_deepseek_api( $api_key, $message );\r\n break;\r\n case 'Google':\r\n $response = chatbot_call_google_api( $api_key, $message );\r\n break;\r\n case 'Markov Chain':\r\n $response = chatbot_chatgpt_call_markov_chain_api( $message );\r\n break;\r\n case 'Transformer':\r\n $response = chatbot_chatgpt_call_transformer_model_api( $message );\r\n break;\r\n case 'Local Server':\r\n $response = chatbot_chatgpt_call_local_model_api( $message );\r\n break;\r\n case 'Mistral':\r\n // If use_assistant_id is No, use regular Mistral API\r\n $response = chatbot_chatgpt_call_mistral_api( $api_key, $message );\r\n break;\r\n default:\r\n $response = chatbot_chatgpt_call_api(\r\n $api_key,\r\n $message,\r\n $user_id,\r\n $page_id,\r\n $session_id,\r\n $assistant_id,\r\n $client_message_id\r\n );\r\n break;\r\n }\r\n }\r\n // Log the response\r\n append_message_to_conversation_log(\r\n $session_id,\r\n $user_id,\r\n $page_id,\r\n 'Chatbot',\r\n $thread_id,\r\n $assistant_id,\r\n null,\r\n $response\r\n );\r\n return $response;\r\n }\r\n\r\n function chatbot_chatgpt_process_single_message( $message_data ) {\r\n // This function contains the core message processing logic\r\n // It's extracted from the main send_message function\r\n global $session_id;\r\n global $user_id;\r\n global $page_id;\r\n global $thread_id;\r\n global $assistant_id;\r\n global $chatbot_chatgpt_assistant_alias;\r\n global $kchat_settings;\r\n global $additional_instructions;\r\n global $model;\r\n global $voice;\r\n global $flow_data;\r\n $api_key = '';\r\n $message = $message_data['message'];\r\n $user_id = $message_data['user_id'];\r\n $page_id = $message_data['page_id'];\r\n $session_id = $message_data['session_id'];\r\n $assistant_id = $message_data['assistant_id'];\r\n $client_message_id = $message_data['client_message_id'];\r\n $chatbot_ai_platform_choice = esc_attr( get_option( 'chatbot_ai_platform_choice', 'OpenAI' ) );\r\n // If your core pipeline expects a nonce in $_POST, we can safely provide one here:\r\n if ( !isset( $_POST['chatbot_nonce'] ) ) {\r\n $_POST['chatbot_nonce'] = wp_create_nonce( 'chatbot_message_nonce' );\r\n }\r\n // IMPORTANT: pass the full array, not just $message\r\n $response = chatbot_chatgpt_send_message( $message_data );\r\n return $response;\r\n }\r\n\r\n // Handle Ajax requests\r\n function chatbot_chatgpt_send_message() {\r\n // Security: Verify nonce for CSRF protection\r\n $nonce_present = isset( $_POST['chatbot_nonce'] );\r\n $nonce_valid = false;\r\n if ( $nonce_present ) {\r\n $nonce_valid = wp_verify_nonce( $_POST['chatbot_nonce'], 'chatbot_message_nonce' );\r\n }\r\n if ( !$nonce_present || !$nonce_valid ) {\r\n // Log the security failure for debugging with more detail\r\n $nonce_status = ( !$nonce_present ? 'missing' : 'invalid' );\r\n $post_data_sanitized = array();\r\n foreach ( $_POST as $key => $value ) {\r\n // Sanitize POST data for logging (exclude sensitive data)\r\n if ( $key !== 'chatbot_nonce' ) {\r\n $post_data_sanitized[$key] = ( is_string( $value ) ? substr( $value, 0, 100 ) : $value );\r\n } else {\r\n $post_data_sanitized[$key] = ( $nonce_present ? ( strlen( $value ) > 0 ? '[present]' : '[empty]' ) : '[missing]' );\r\n }\r\n }\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n prod_trace( 'ERROR', 'Chatbot Security Check Failed - Nonce ' . $nonce_status . '. POST data: ' . print_r( $post_data_sanitized, true ) );\r\n // Enhanced error response with nonce refresh suggestion\r\n wp_send_json_error( array(\r\n 'message' => 'Security check failed. Please refresh the page and try again.',\r\n 'code' => 'nonce_failed',\r\n 'suggestion' => 'refresh_nonce',\r\n 'nonce_status' => $nonce_status,\r\n ), 403 );\r\n return;\r\n }\r\n // Security: Get current user and verify authorization\r\n $current_user = wp_get_current_user();\r\n $current_user_id = $current_user->ID;\r\n // For anonymous users, we need to verify they own the session\r\n if ( $current_user_id === 0 ) {\r\n // Anonymous user - verify session ownership through session_id\r\n if ( !isset( $_POST['session_id'] ) ) {\r\n wp_send_json_error( 'Session ID required for anonymous users.', 403 );\r\n return;\r\n }\r\n $session_id = sanitize_text_field( $_POST['session_id'] );\r\n // Verify the session belongs to the current request\r\n if ( !verify_session_ownership( $session_id ) ) {\r\n // Log the session validation failure for debugging\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n prod_trace( 'ERROR', 'Chatbot Session Validation Failed - Session ID: ' . $session_id . ', Length: ' . strlen( $session_id ) );\r\n wp_send_json_error( 'Unauthorized access to conversation.', 403 );\r\n return;\r\n }\r\n // For anonymous users, user_id should be 0 (session_id is used in transient key via get_chatbot_chatgpt_transients)\r\n $user_id = 0;\r\n // Rate limiting for unauthenticated users to prevent API abuse\r\n $client_ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown';\r\n $rate_limit_key = 'chatbot_rate_limit_' . (( function_exists( 'wp_fast_hash' ) ? wp_fast_hash( $client_ip ) : hash( 'sha256', $client_ip ) ));\r\n // Check rate limit (max 10 requests per minute for unauthenticated users)\r\n $current_count = ( get_transient( $rate_limit_key ) ?: 0 );\r\n if ( $current_count >= 10 ) {\r\n wp_send_json_error( 'Rate limit exceeded. Please wait before sending another message.', 429 );\r\n return;\r\n }\r\n // Increment rate limit counter\r\n set_transient( $rate_limit_key, $current_count + 1, 60 );\r\n // 60 seconds\r\n } else {\r\n // Logged-in user - use their actual user ID\r\n // Get session_id for logged-in users (needed for transient keys) - Ver 2.3.6\r\n if ( !isset( $_POST['session_id'] ) ) {\r\n $session_id = kognetiks_get_unique_id();\r\n } else {\r\n $session_id = sanitize_text_field( $_POST['session_id'] );\r\n }\r\n }\r\n // Global variables\r\n // Fixed Ver 2.3.6: Set global variables AFTER determining the correct values\r\n // This ensures the global $user_id is set correctly for logged-in users\r\n global $session_id;\r\n global $user_id;\r\n global $page_id;\r\n // Set the global $user_id to the correct value (don't let global declaration overwrite it)\r\n if ( $current_user_id === 0 ) {\r\n $user_id = 0;\r\n // Anonymous user\r\n } else {\r\n $user_id = $current_user_id;\r\n // Logged-in user - preserve their WordPress user ID\r\n }\r\n global $thread_id;\r\n global $assistant_id;\r\n global $chatbot_chatgpt_assistant_alias;\r\n global $kchat_settings;\r\n global $additional_instructions;\r\n global $model;\r\n global $voice;\r\n global $flow_data;\r\n $api_key = '';\r\n $chatbot_ai_platform_choice = esc_attr( get_option( 'chatbot_ai_platform_choice', 'OpenAI' ) );\r\n switch ( $chatbot_ai_platform_choice ) {\r\n case 'OpenAI':\r\n $api_key = esc_attr( get_option( 'chatbot_chatgpt_api_key' ) );\r\n // Decrypt the API key - Ver 2.2.6\r\n $api_key = chatbot_chatgpt_decrypt_api_key( $api_key );\r\n $model = esc_attr( get_option( 'chatbot_chatgpt_model_choice', 'gpt-4-1106-preview' ) );\r\n $kchat_settings['chatbot_chatgpt_model'] = $model;\r\n $kchat_settings['model'] = $model;\r\n break;\r\n case 'Azure OpenAI':\r\n $api_key = esc_attr( get_option( 'chatbot_azure_api_key' ) );\r\n // Decrypt the API key - Ver 2.2.6\r\n $api_key = chatbot_chatgpt_decrypt_api_key( $api_key );\r\n $model = esc_attr( get_option( 'chatbot_azure_model_choice', 'gpt-4-1106-preview' ) );\r\n $kchat_settings['chatbot_chatgpt_model'] = $model;\r\n $kchat_settings['model'] = $model;\r\n break;\r\n case 'NVIDIA':\r\n $api_key = esc_attr( get_option( 'chatbot_nvidia_api_key' ) );\r\n $model = esc_attr( get_option( 'chatbot_nvidia_model_choice', 'nvidia/llama-3.1-nemotron-51b-instruct' ) );\r\n // Decrypt the API key - Ver 2.2.6\r\n $api_key = chatbot_chatgpt_decrypt_api_key( $api_key );\r\n $kchat_settings['chatbot_chatgpt_model'] = $model;\r\n $kchat_settings['model'] = $model;\r\n break;\r\n case 'Anthropic':\r\n $api_key = esc_attr( get_option( 'chatbot_anthropic_api_key' ) );\r\n // Decrypt the API key - Ver 2.2.6\r\n $api_key = chatbot_chatgpt_decrypt_api_key( $api_key );\r\n $model = esc_attr( get_option( 'chatbot_anthropic_model_choice', 'claude-3-5-sonnet-latest' ) );\r\n $kchat_settings['chatbot_chatgpt_model'] = $model;\r\n $kchat_settings['model'] = $model;\r\n break;\r\n case 'DeepSeek':\r\n $api_key = esc_attr( get_option( 'chatbot_deepseek_api_key' ) );\r\n // Decrypt the API key - Ver 2.2.6\r\n $api_key = chatbot_chatgpt_decrypt_api_key( $api_key );\r\n $model = esc_attr( get_option( 'chatbot_deepseek_model_choice', 'deepseek-chat' ) );\r\n $kchat_settings['chatbot_chatgpt_model'] = $model;\r\n $kchat_settings['model'] = $model;\r\n break;\r\n case 'Google':\r\n $api_key = esc_attr( get_option( 'chatbot_google_api_key' ) );\r\n // Decrypt the API key - Ver 2.3.9\r\n $api_key = chatbot_chatgpt_decrypt_api_key( $api_key );\r\n $model = esc_attr( get_option( 'chatbot_google_model_choice', 'gemini-2.0-flash' ) );\r\n $kchat_settings['chatbot_chatgpt_model'] = $model;\r\n $kchat_settings['model'] = $model;\r\n break;\r\n case 'Markov Chain':\r\n $api_key = esc_attr( get_option( 'chatbot_markov_chain_api_key', 'NOT REQUIRED' ) );\r\n $model = esc_attr( get_option( 'chatbot_markov_chain_model_choice', 'markov-chain-flask' ) );\r\n $kchat_settings['chatbot_chatgpt_model'] = $model;\r\n $kchat_settings['model'] = $model;\r\n break;\r\n case 'Transformer':\r\n $api_key = esc_attr( get_option( 'chatbot_transformer_api_key', 'NOT REQUIRED' ) );\r\n $model = esc_attr( get_option( 'chatbot_transformer_model_choice', 'lexical-context-model' ) );\r\n $kchat_settings['chatbot_chatgpt_model'] = $model;\r\n $kchat_settings['model'] = $model;\r\n break;\r\n case 'Local Server':\r\n $api_key = esc_attr( get_option( 'chatbot_local_api_key', 'NOT REQUIRED' ) );\r\n // Decrypt the API key - Ver 2.2.6\r\n $api_key = chatbot_chatgpt_decrypt_api_key( $api_key );\r\n $model = esc_attr( get_option( 'chatbot_local_model_choice', 'llama3.2-3b-instruct' ) );\r\n $kchat_settings['chatbot_chatgpt_model'] = $model;\r\n $kchat_settings['model'] = $model;\r\n break;\r\n case 'Mistral':\r\n $api_key = esc_attr( get_option( 'chatbot_mistral_api_key' ) );\r\n // Decrypt the API key - Ver 2.2.6\r\n $api_key = chatbot_chatgpt_decrypt_api_key( $api_key );\r\n $model = esc_attr( get_option( 'chatbot_mistral_model_choice', 'mistral-small-latest' ) );\r\n $kchat_settings['chatbot_chatgpt_model'] = $model;\r\n $kchat_settings['model'] = $model;\r\n break;\r\n default:\r\n $api_key = esc_attr( get_option( 'chatbot_chatgpt_api_key' ) );\r\n // Decrypt the API key - Ver 2.2.6\r\n $api_key = chatbot_chatgpt_decrypt_api_key( $api_key );\r\n $model = esc_attr( get_option( 'chatbot_chatgpt_model_choice', 'gpt-3.5-turbo' ) );\r\n $kchat_settings['chatbot_chatgpt_model'] = $model;\r\n $kchat_settings['model'] = $model;\r\n break;\r\n }\r\n // Send only clean text via the API - Ver 2.3.7\r\n // Validate message exists in POST before sanitizing\r\n if ( !isset( $_POST['message'] ) || empty( $_POST['message'] ) ) {\r\n prod_trace( 'ERROR', 'Chatbot: Message is missing from POST data. POST keys: ' . implode( ', ', array_keys( $_POST ) ) );\r\n global $chatbot_chatgpt_fixed_literal_messages;\r\n $default_message = 'Error: Message is required. Please enter a message and try again.';\r\n $error_message = ( isset( $chatbot_chatgpt_fixed_literal_messages[15] ) ? $chatbot_chatgpt_fixed_literal_messages[15] : $default_message );\r\n wp_send_json_error( $error_message );\r\n return;\r\n }\r\n $message = sanitize_text_field( $_POST['message'] );\r\n // Additional validation - ensure message is not empty after sanitization\r\n if ( empty( trim( $message ) ) ) {\r\n prod_trace( 'ERROR', 'Chatbot: Message is empty after sanitization. Original POST message length: ' . strlen( $_POST['message'] ) );\r\n global $chatbot_chatgpt_fixed_literal_messages;\r\n $default_message = 'Error: Message cannot be empty. Please enter a message and try again.';\r\n $error_message = ( isset( $chatbot_chatgpt_fixed_literal_messages[15] ) ? $chatbot_chatgpt_fixed_literal_messages[15] : $default_message );\r\n wp_send_json_error( $error_message );\r\n return;\r\n }\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n // prod_trace('NOTICE', 'Chatbot: Processing message - Length: ' . strlen($message) . ', First 50 chars: ' . substr($message, 0, 50));\r\n // Get client message ID if provided\r\n $client_message_id = ( isset( $_POST['client_message_id'] ) ? sanitize_text_field( $_POST['client_message_id'] ) : null );\r\n // Check for missing API key or message\r\n // if (!$api_key || !$message) {\r\n if ( !$message ) {\r\n global $chatbot_chatgpt_fixed_literal_messages;\r\n // Define a default fallback message\r\n $default_message = 'Error: Invalid API key or Message. Please check the plugin settings.';\r\n $error_message = ( isset( $chatbot_chatgpt_fixed_literal_messages[15] ) ? $chatbot_chatgpt_fixed_literal_messages[15] : $default_message );\r\n // Send error response\r\n wp_send_json_error( $error_message );\r\n return;\r\n }\r\n // Removed in Ver 1.8.6 - 2024 02 15\r\n // $thread_id = '';\r\n // $assistant_id = '';\r\n // $user_id = '';\r\n // $page_id = '';\r\n // Check the transient for the Assistant ID - Ver 1.7.2\r\n // Security: Get page_id from POST (this is safe as it's just identifying the page)\r\n $page_id = ( isset( $_POST['page_id'] ) ? sanitize_text_field( $_POST['page_id'] ) : '' );\r\n // For logged-in users, session_id should come from the secure session\r\n // For anonymous users, session_id was already validated above\r\n if ( $current_user_id === 0 ) {\r\n // session_id was already validated and set above for anonymous users\r\n // No need to overwrite it\r\n } else {\r\n // For logged-in users, get session_id from POST but validate it\r\n if ( isset( $_POST['session_id'] ) ) {\r\n $session_id = sanitize_text_field( $_POST['session_id'] );\r\n } else {\r\n // Fallback to generating a new session ID\r\n $session_id = kognetiks_get_unique_id();\r\n }\r\n }\r\n // Additional security: Verify the conversation belongs to this user\r\n if ( !verify_conversation_ownership( $user_id, $page_id ) ) {\r\n // Log the conversation ownership validation failure for debugging\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n prod_trace( 'ERROR', 'Chatbot Conversation Ownership Validation Failed - User ID: ' . $user_id . ', Page ID: ' . $page_id );\r\n wp_send_json_error( 'Unauthorized access to conversation.', 403 );\r\n return;\r\n }\r\n $kchat_settings['chatbot_chatgpt_display_style'] = get_chatbot_chatgpt_transients(\r\n 'display_style',\r\n $user_id,\r\n $page_id,\r\n $session_id\r\n );\r\n $kchat_settings['chatbot_chatgpt_assistant_alias'] = get_chatbot_chatgpt_transients(\r\n 'assistant_alias',\r\n $user_id,\r\n $page_id,\r\n $session_id\r\n );\r\n $kchat_settings['assistant_id'] = get_chatbot_chatgpt_transients(\r\n 'assistant_id',\r\n $user_id,\r\n $page_id,\r\n $session_id\r\n );\r\n $kchat_settings['thread_id'] = get_chatbot_chatgpt_transients(\r\n 'thread_id',\r\n $user_id,\r\n $page_id,\r\n $session_id\r\n );\r\n $kchat_settings['chatbot_chatgpt_model'] = get_chatbot_chatgpt_transients(\r\n 'model',\r\n $user_id,\r\n $page_id,\r\n $session_id\r\n );\r\n $kchat_settings['model'] = $kchat_settings['chatbot_chatgpt_model'];\r\n $kchat_settings['chatbot_chatgpt_voice_option'] = get_chatbot_chatgpt_transients(\r\n 'voice',\r\n $user_id,\r\n $page_id,\r\n $session_id\r\n );\r\n $kchat_settings['additional_instructions'] = get_chatbot_chatgpt_transients(\r\n 'additional_instructions',\r\n $user_id,\r\n $page_id,\r\n $session_id\r\n );\r\n $voice = $kchat_settings['chatbot_chatgpt_voice_option'];\r\n $model = $kchat_settings['chatbot_chatgpt_model'];\r\n $additional_instructions = $kchat_settings['additional_instructions'];\r\n $chatbot_chatgpt_assistant_alias = $kchat_settings['chatbot_chatgpt_assistant_alias'];\r\n // Get the thread information - Ver 2.0.7\r\n $thread_id = get_chatbot_chatgpt_threads(\r\n $user_id,\r\n $session_id,\r\n $page_id,\r\n $assistant_id\r\n );\r\n $kchat_settings['thread_id'] = $thread_id;\r\n // $kchat_settings = array_merge($kchat_settings, get_chatbot_chatgpt_threads($user_id, $page_id));\r\n $assistant_id = ( isset( $kchat_settings['assistant_id'] ) ? $kchat_settings['assistant_id'] : '' );\r\n $thread_Id = ( isset( $kchat_settings['thread_id'] ) ? $kchat_settings['thread_id'] : '' );\r\n $model = ( isset( $kchat_settings['chatbot_chatgpt_model'] ) ? $kchat_settings['chatbot_chatgpt_model'] : '' );\r\n $voice = ( isset( $kchat_settings['chatbot_chatgpt_voice_option'] ) ? $kchat_settings['chatbot_chatgpt_voice_option'] : '' );\r\n // Check if there's already a conversation lock (active processing)\r\n $conv_lock = 'chatgpt_conv_lock_' . wp_hash( $assistant_id . '|' . $user_id . '|' . $page_id . '|' . $session_id );\r\n $is_processing = get_transient( $conv_lock );\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n // back_trace('NOTICE', 'Conv Lock: ' . $conv_lock);\r\n // back_trace('NOTICE', 'Is Processing: ' . $is_processing);\r\n // For visitors, add additional lock validation to prevent stuck locks\r\n if ( $is_processing && $current_user_id === 0 ) {\r\n // Check if the lock is older than 2 minutes (120 seconds) - likely stuck\r\n $lock_timeout_key = '_transient_timeout_' . $conv_lock;\r\n $lock_timeout = get_option( $lock_timeout_key );\r\n if ( $lock_timeout && time() - ($lock_timeout - 60) > 120 ) {\r\n // Lock is older than 2 minutes, clear it\r\n delete_transient( $conv_lock );\r\n $is_processing = false;\r\n }\r\n }\r\n if ( $is_processing ) {\r\n // If already processing, enqueue the message\r\n $enqueued_id = chatbot_chatgpt_enqueue_message(\r\n $user_id,\r\n $page_id,\r\n $session_id,\r\n $assistant_id,\r\n $message,\r\n $client_message_id\r\n );\r\n // Return queue status\r\n global $chatbot_chatgpt_fixed_literal_messages;\r\n $default_message = 'Message queued. Processing...';\r\n $queued_message = ( isset( $chatbot_chatgpt_fixed_literal_messages[20] ) ? $chatbot_chatgpt_fixed_literal_messages[20] : $default_message );\r\n wp_send_json_success( [\r\n 'queued' => true,\r\n 'client_message_id' => $enqueued_id,\r\n 'message' => $queued_message,\r\n ] );\r\n }\r\n // Set conversation lock with shorter timeout for visitors to prevent stuck locks\r\n $lock_timeout = ( $current_user_id === 0 ? 30 : 60 );\r\n // 30 seconds for visitors, 60 for logged-in users\r\n set_transient( $conv_lock, true, $lock_timeout );\r\n foreach ( $kchat_settings as $key => $value ) {\r\n }\r\n // Assistants\r\n // $chatbot_chatgpt_assistant_alias == 'original'; // Default\r\n // $chatbot_chatgpt_assistant_alias == 'primary';\r\n // $chatbot_chatgpt_assistant_alias == 'alternate';\r\n // $chatbot_chatgpt_assistant_alias == 'asst_xxxxxxxxxxxxxxxxxxxxxxxx'; // GPT Assistant Id\r\n // $chatbot_chatgpt_assistant_alias == 'pmpt_xxxxxxxxxxxxxxxxxxxxxxxx'; // GPT Prompt Id\r\n // $chatbot_chatgpt_assistant_alias == 'ag:xxxxxxxxxxxxxxxxxxxxxxxx'; // MistralAgent Id\r\n // $chatbot_chatgpt_assistant_alias == 'websearch'; // Mistral Websearch Id\r\n // Which Assistant ID to use - Ver 1.7.2\r\n if ( $chatbot_chatgpt_assistant_alias == 'original' ) {\r\n $use_assistant_id = 'No';\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n // back_trace('NOTICE', 'Using Original Assistant ID - Ver 2.4.5');\r\n // back_trace('NOTICE', 'Original Assistant ID: ' . $assistant_id);\r\n // back_trace('NOTICE', 'Use Assistant ID: ' . $use_assistant_id);\r\n // back_trace('NOTICE', 'Chatbot ChatGPT Assistant Alias: ' . $chatbot_chatgpt_assistant_alias);\r\n } elseif ( $chatbot_chatgpt_assistant_alias == 'primary' ) {\r\n $assistant_id = esc_attr( get_option( 'assistant_id' ) );\r\n $use_assistant_id = 'Yes';\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n // back_trace('NOTICE', 'Using Primary Assistant ID - Ver 2.4.5');\r\n // back_trace('NOTICE', 'Primary Assistant ID: ' . $assistant_id);\r\n // back_trace('NOTICE', 'Use Assistant ID: ' . $use_assistant_id);\r\n // back_trace('NOTICE', 'Chatbot ChatGPT Assistant Alias: ' . $chatbot_chatgpt_assistant_alias);\r\n // Check if the GPT Assistant ID is blank, null, or \"Please provide the GPT Assistant ID.\"\r\n if ( empty( $assistant_id ) || $assistant_id == \"Please provide the Assistant Id.\" ) {\r\n // Primary assistant_id not set\r\n $chatbot_chatgpt_assistant_alias = 'original';\r\n $use_assistant_id = 'No';\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n // back_trace('NOTICE', 'Primary Assistant ID not set - Ver 2.4.5');\r\n // back_trace('NOTICE', 'Primary Assistant ID: ' . $assistant_id);\r\n // back_trace('NOTICE', 'Use Assistant ID: ' . $use_assistant_id);\r\n // back_trace('NOTICE', 'Chatbot ChatGPT Assistant Alias: ' . $chatbot_chatgpt_assistant_alias);\r\n }\r\n } elseif ( $chatbot_chatgpt_assistant_alias == 'alternate' ) {\r\n $assistant_id = esc_attr( get_option( 'chatbot_chatgpt_assistant_id_alternate' ) );\r\n $use_assistant_id = 'Yes';\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n // back_trace('NOTICE', 'Using Alternate Assistant ID - Ver 2.4.5');\r\n // back_trace('NOTICE', 'Alternate Assistant ID: ' . $assistant_id);\r\n // back_trace('NOTICE', 'Use Assistant ID: ' . $use_assistant_id);\r\n // back_trace('NOTICE', 'Chatbot ChatGPT Assistant Alias: ' . $chatbot_chatgpt_assistant_alias);\r\n // Check if the GPT Assistant ID is blank, null, or \"Please provide the GPT Assistant ID.\"\r\n if ( empty( $assistant_id ) || $assistant_id == \"Please provide the Assistant Id.\" ) {\r\n /// Alternate assistant_id not set\r\n $chatbot_chatgpt_assistant_alias = 'original';\r\n $use_assistant_id = 'No';\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n // back_trace('NOTICE', 'Alternate Assistant ID not set - Ver 2.4.5');\r\n // back_trace('NOTICE', 'Alternate Assistant ID: ' . $assistant_id);\r\n // back_trace('NOTICE', 'Use Assistant ID: ' . $use_assistant_id);\r\n // back_trace('NOTICE', 'Chatbot ChatGPT Assistant Alias: ' . $chatbot_chatgpt_assistant_alias);\r\n }\r\n } elseif ( str_starts_with( $assistant_id, 'asst_' ) ) {\r\n $chatbot_chatgpt_assistant_alias = $assistant_id;\r\n // Belt & Suspenders\r\n $use_assistant_id = 'Yes';\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n // back_trace('NOTICE', 'Using Assistant ID - Ver 2.4.5');\r\n // back_trace('NOTICE', 'Assistant ID: ' . $assistant_id);\r\n // back_trace('NOTICE', 'Use Assistant ID: ' . $use_assistant_id);\r\n // back_trace('NOTICE', 'Chatbot ChatGPT Assistant Alias: ' . $chatbot_chatgpt_assistant_alias);\r\n } elseif ( str_starts_with( $assistant_id, 'pmpt_' ) ) {\r\n $chatbot_chatgpt_assistant_alias = $assistant_id;\r\n // Belt & Suspenders\r\n $use_assistant_id = 'Yes';\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n // back_trace('NOTICE', 'Using Prompt ID - Ver 2.4.5');\r\n // back_trace('NOTICE', 'Prompt ID: ' . $assistant_id);\r\n // back_trace('NOTICE', 'Use Assistant ID: ' . $use_assistant_id);\r\n // back_trace('NOTICE', 'Chatbot ChatGPT Assistant Alias: ' . $chatbot_chatgpt_assistant_alias);\r\n } elseif ( str_starts_with( $assistant_id, 'ag:' ) ) {\r\n $chatbot_chatgpt_assistant_alias = $assistant_id;\r\n // Belt & Suspenders\r\n $use_assistant_id = 'Yes';\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n // back_trace('NOTICE', 'Using Mistral Agent ID - Ver 2.4.5');\r\n // back_trace('NOTICE', 'Mistral Agent ID: ' . $assistant_id);\r\n // back_trace('NOTICE', 'Use Assistant ID: ' . $use_assistant_id);\r\n } elseif ( str_starts_with( $assistant_id, 'websearch' ) ) {\r\n $chatbot_chatgpt_assistant_alias = $assistant_id;\r\n // Belt & Suspenders\r\n $use_assistant_id = 'Yes';\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n // back_trace('NOTICE', 'Using Mistral Agent ID - Ver 2.4.5');\r\n // back_trace('NOTICE', 'Mistral Agent ID: ' . $assistant_id);\r\n // back_trace('NOTICE', 'Use Assistant ID: ' . $use_assistant_id);\r\n // back_trace('NOTICE', 'Chatbot ChatGPT Assistant Alias: ' . $chatbot_chatgpt_assistant_alias);\r\n } else {\r\n // Reference GPT Assistant IDs directly - Ver 1.7.3\r\n // Check both $chatbot_chatgpt_assistant_alias and $assistant_id - Ver 2.3.6\r\n 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' ) || str_starts_with( $chatbot_chatgpt_assistant_alias, 'pmpt_' )) ) {\r\n // Override the $assistant_id with the GPT Assistant ID\r\n $assistant_id = $chatbot_chatgpt_assistant_alias;\r\n $use_assistant_id = 'Yes';\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n // back_trace('NOTICE', 'Using Assistant ID - Ver 2.4.5');\r\n // back_trace('NOTICE', 'Assistant ID: ' . $assistant_id);\r\n // back_trace('NOTICE', 'Use Assistant ID: ' . $use_assistant_id);\r\n // back_trace('NOTICE', 'Chatbot ChatGPT Assistant Alias: ' . $chatbot_chatgpt_assistant_alias);\r\n } elseif ( !empty( $assistant_id ) && (str_starts_with( $assistant_id, 'asst_' ) || str_starts_with( $assistant_id, 'ag:' ) || str_starts_with( $assistant_id, 'websearch' ) || str_starts_with( $assistant_id, 'pmpt_' )) ) {\r\n // Set the alias to match the assistant_id\r\n $chatbot_chatgpt_assistant_alias = $assistant_id;\r\n $use_assistant_id = 'Yes';\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n // back_trace('NOTICE', 'Using Assistant ID - Ver 2.4.5');\r\n // back_trace('NOTICE', 'Assistant ID: ' . $assistant_id);\r\n // back_trace('NOTICE', 'Use Assistant ID: ' . $use_assistant_id);\r\n // back_trace('NOTICE', 'Chatbot ChatGPT Assistant Alias: ' . $chatbot_chatgpt_assistant_alias);\r\n } else {\r\n // Override the $use_assistant_id and set it to 'No'\r\n $use_assistant_id = 'No';\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n // back_trace('NOTICE', 'Using Original Assistant ID - Ver 2.4.5');\r\n // back_trace('NOTICE', 'Assistant ID: ' . $assistant_id);\r\n // back_trace('NOTICE', 'Use Assistant ID: ' . $use_assistant_id);\r\n // back_trace('NOTICE', 'Chatbot ChatGPT Assistant Alias: ' . $chatbot_chatgpt_assistant_alias);\r\n }\r\n }\r\n // Get any additional instructions - Ver 2.0.9\r\n $additional_instructions = get_chatbot_chatgpt_transients(\r\n 'additional_instructions',\r\n $user_id,\r\n $page_id,\r\n $session_id\r\n );\r\n // Decide whether to use Flow, Assistant or Original ChatGPT\r\n if ( $model == 'flow' ) {\r\n // Reload the model - BELT & SUSPENDERS\r\n $kchat_settings['model'] = $model;\r\n // Get the step from the transient\r\n $kflow_step = get_chatbot_chatgpt_transients(\r\n 'kflow_step',\r\n null,\r\n null,\r\n $session_id\r\n );\r\n if ( empty( $kflow_step ) ) {\r\n $kflow_step = 0;\r\n // FIXME - Set to 1 or to zero?\r\n }\r\n // $thread_id\r\n $thread_id = '[answer=' . $kflow_step + 1 . ']';\r\n // Add +1 to $kchat_settings['next_step']\r\n $kflow_step = $kflow_step + 1;\r\n // Set the next step\r\n set_chatbot_chatgpt_transients(\r\n 'kflow_step',\r\n $kflow_step,\r\n null,\r\n null,\r\n $session_id\r\n );\r\n $thread_id = get_chatbot_chatgpt_threads(\r\n $user_id,\r\n $session_id,\r\n $page_id,\r\n $assistant_id\r\n );\r\n append_message_to_conversation_log(\r\n $session_id,\r\n $user_id,\r\n $page_id,\r\n 'Visitor',\r\n $thread_id,\r\n $assistant_id,\r\n null,\r\n $message\r\n );\r\n // BELT & SUSPENDERS\r\n $thread_id = '';\r\n // Send message to ChatGPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_call_flow_api( $api_key, $message );\r\n wp_send_json_success( $response );\r\n } elseif ( $use_assistant_id == 'Yes' ) {\r\n $thread_id = get_chatbot_chatgpt_threads(\r\n $user_id,\r\n $session_id,\r\n $page_id,\r\n $assistant_id\r\n );\r\n append_message_to_conversation_log(\r\n $session_id,\r\n $user_id,\r\n $page_id,\r\n 'Visitor',\r\n $thread_id,\r\n $assistant_id,\r\n null,\r\n $message\r\n );\r\n // Send message to Custom GPT API - Ver 1.6.7\r\n $chatbot_ai_platform_choice = esc_attr( get_option( 'chatbot_ai_platform_choice', 'OpenAI' ) );\r\n // Route based on chatbot_ai_platform_choice setting - Ver 2.3.6\r\n if ( $chatbot_ai_platform_choice == 'OpenAI' ) {\r\n // Original Assistant or Prompt\r\n if ( str_starts_with( $assistant_id, 'asst_' ) ) {\r\n $response = chatbot_chatgpt_custom_gpt_call_api(\r\n $api_key,\r\n $message,\r\n $assistant_id,\r\n $thread_id,\r\n $session_id,\r\n $user_id,\r\n $page_id,\r\n $client_message_id\r\n );\r\n } elseif ( str_starts_with( $assistant_id, 'pmpt_' ) ) {\r\n $response = chatbot_chatgpt_custom_pmpt_call_api(\r\n $api_key,\r\n $message,\r\n $assistant_id,\r\n $thread_id,\r\n $session_id,\r\n $user_id,\r\n $page_id,\r\n $client_message_id\r\n );\r\n } else {\r\n return 'ERROR: Invalid Assistant ID';\r\n }\r\n } elseif ( $chatbot_ai_platform_choice == 'Azure OpenAI' ) {\r\n // Send message to Azure Assistant API - Ver 2.2.6\r\n $response = chatbot_azure_custom_gpt_call_api(\r\n $api_key,\r\n $message,\r\n $assistant_id,\r\n $thread_id,\r\n $session_id,\r\n $user_id,\r\n $page_id,\r\n $client_message_id\r\n );\r\n } elseif ( $chatbot_ai_platform_choice == 'Mistral' ) {\r\n // Send message to Mistral Assistant API - Ver 2.2.6\r\n $response = chatbot_mistral_agent_call_api(\r\n $api_key,\r\n $message,\r\n $assistant_id,\r\n $thread_id,\r\n $session_id,\r\n $user_id,\r\n $page_id,\r\n $client_message_id\r\n );\r\n } else {\r\n return 'ERROR: Invalid AI Platform';\r\n }\r\n // Replace \" .\" at the end of $response with \".\"\r\n $response = str_replace( \" .\", \".\", $response );\r\n // Use TF-IDF to enhance response\r\n $chatbot_chatgpt_suppress_learnings = esc_attr( get_option( 'chatbot_chatgpt_suppress_learnings', 'Random' ) );\r\n if ( $chatbot_chatgpt_suppress_learnings != 'None' ) {\r\n $response = $response . '

' . chatbot_chatgpt_enhance_with_tfidf( $message );\r\n }\r\n $thread_id = get_chatbot_chatgpt_threads(\r\n $user_id,\r\n $session_id,\r\n $page_id,\r\n $assistant_id\r\n );\r\n append_message_to_conversation_log(\r\n $session_id,\r\n $user_id,\r\n $page_id,\r\n 'Chatbot',\r\n $thread_id,\r\n $assistant_id,\r\n null,\r\n $response\r\n );\r\n // Clean (erase) the output buffer - Ver 1.6.8\r\n // Check if output buffering is active before attempting to clean it\r\n if ( ob_get_level() > 0 ) {\r\n ob_clean();\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n // back_trace('NOTICE', 'Output buffer cleaned');\r\n } else {\r\n // Optionally start output buffering if needed for your application\r\n // ob_start();\r\n // DIAG - Diagnostics - Ver 2.4.5\r\n // back_trace('NOTICE', 'Output buffer not cleaned');\r\n }\r\n if ( str_starts_with( $response, 'Error:' ) || str_starts_with( $response, 'Failed:' ) ) {\r\n global $chatbot_chatgpt_fixed_literal_messages;\r\n // Define a default fallback message\r\n $default_message = 'Oops! Something went wrong on our end. Please try again later!';\r\n $error_message = ( isset( $chatbot_chatgpt_fixed_literal_messages[0] ) ? $chatbot_chatgpt_fixed_literal_messages[0] : $default_message );\r\n // Send error response\r\n wp_send_json_error( $error_message );\r\n } else {\r\n // Process response for links and images\r\n $response = chatbot_chatgpt_check_for_links_and_images( $response );\r\n // Append any extra message if configured\r\n $extra_message = esc_attr( get_option( 'chatbot_chatgpt_extra_message', '' ) );\r\n $response = chatbot_chatgpt_append_extra_message( $response, $extra_message );\r\n // Clear conversation lock and process queue BEFORE sending response\r\n delete_transient( $conv_lock );\r\n chatbot_chatgpt_process_queue(\r\n $user_id,\r\n $page_id,\r\n $session_id,\r\n $assistant_id\r\n );\r\n // Send success response\r\n wp_send_json_success( $response );\r\n }\r\n } else {\r\n // Belt & Suspenders - Ver 2.1.5.1\r\n if ( !isset( $kchat_settings['model'] ) ) {\r\n $kchat_settings['model'] = $model;\r\n }\r\n $thread_id = get_chatbot_chatgpt_threads(\r\n $user_id,\r\n $session_id,\r\n $page_id,\r\n $assistant_id\r\n );\r\n append_message_to_conversation_log(\r\n $session_id,\r\n $user_id,\r\n $page_id,\r\n 'Visitor',\r\n $thread_id,\r\n $assistant_id,\r\n null,\r\n $message\r\n );\r\n // If $model starts with 'gpt' then the chatbot_chatgpt_call_api or 'dall' then chatbot_chatgpt_call_image_api\r\n // TRY NOT TO FETCH MODEL AGAIN\r\n // $model = esc_attr(get_option('chatbot_chatgpt_model_choice', 'gpt-3.5-turbo'));\r\n $model = ( isset( $kchat_settings['model'] ) ? $kchat_settings['model'] : null );\r\n $voice = ( isset( $kchat_settings['voice'] ) ? $kchat_settings['voice'] : null );\r\n $chatbot_ai_platform_choice = esc_attr( get_option( 'chatbot_ai_platform_choice', 'OpenAI' ) );\r\n switch ( $chatbot_ai_platform_choice ) {\r\n case 'OpenAI':\r\n switch ( $model ) {\r\n case str_starts_with( $model, 'gpt-4o' ):\r\n // The string 'gpt-4o' is found in $model\r\n // Reload the model - BELT & SUSPENDERS\r\n $kchat_settings['model'] = $model;\r\n // Send message to ChatGPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_call_omni(\r\n $api_key,\r\n $message,\r\n $user_id,\r\n $page_id,\r\n $session_id,\r\n $assistant_id,\r\n $client_message_id\r\n );\r\n break;\r\n case str_starts_with( $model, 'gpt' ):\r\n // Reload the model - BELT & SUSPENDERS\r\n $kchat_settings['model'] = $model;\r\n // Send message to ChatGPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_call_api(\r\n $api_key,\r\n $message,\r\n $user_id,\r\n $page_id,\r\n $session_id,\r\n $assistant_id,\r\n $client_message_id\r\n );\r\n break;\r\n case str_starts_with( $model, 'dall' ):\r\n // Reload the model - BELT & SUSPENDERS\r\n $kchat_settings['model'] = $model;\r\n // Send message to Image API - Ver 1.9.4\r\n $response = chatbot_chatgpt_call_image_api(\r\n $api_key,\r\n $message,\r\n $user_id,\r\n $page_id,\r\n $session_id,\r\n $assistant_id,\r\n $client_message_id\r\n );\r\n break;\r\n case str_starts_with( $model, 'tts' ):\r\n // Reload the model - BELT & SUSPENDERS\r\n $kchat_settings['model'] = $model;\r\n $kchat_settings['voice'] = $voice;\r\n // Send message to TTS API - Text-to-speech - Ver 1.9.5\r\n $response = chatbot_chatgpt_call_tts_api(\r\n $api_key,\r\n $message,\r\n $voice,\r\n $user_id,\r\n $page_id,\r\n $session_id,\r\n $assistant_id,\r\n $client_message_id\r\n );\r\n break;\r\n case str_starts_with( $model, 'whisper' ):\r\n // Reload the model - BELT & SUSPENDERS\r\n $kchat_settings['model'] = $model;\r\n // Send message to STT API - Speech-to-text - Ver 1.9.6\r\n $response = chatbot_chatgpt_call_stt_api( $api_key, $message );\r\n break;\r\n }\r\n break;\r\n case 'Azure OpenAI':\r\n $kchat_settings['model'] = $model;\r\n // Send message to Azure OpenAI API - Ver 2.2.6\r\n $response = chatbot_call_azure_openai_api( $api_key, $message );\r\n break;\r\n case 'NVIDIA':\r\n $kchat_settings['model'] = $model;\r\n // Send message to NVIDIA API - Ver 2.1.8\r\n $response = chatbot_nvidia_call_api( $api_key, $message );\r\n break;\r\n case 'Anthropic':\r\n $kchat_settings['model'] = $model;\r\n // Send message to Claude API - Ver 2.1.8\r\n $response = chatbot_call_anthropic_api( $api_key, $message );\r\n break;\r\n case 'DeepSeek':\r\n $kchat_settings['model'] = $model;\r\n // Send message to DeepSeek API - Ver 2.2.2\r\n $response = chatbot_call_deepseek_api( $api_key, $message );\r\n break;\r\n case 'Google':\r\n $kchat_settings['model'] = $model;\r\n // Send message to Google API - Ver 2.3.9\r\n $response = chatbot_call_google_api( $api_key, $message );\r\n break;\r\n case 'Mistral':\r\n $kchat_settings['model'] = $model;\r\n // Send message to Mistral API - Ver 2.3.0\r\n $response = chatbot_chatgpt_call_mistral_api( $api_key, $message );\r\n break;\r\n case 'Markov Chain':\r\n $kchat_settings['model'] = $model;\r\n // Send message to Markov API - Ver 1.9.7\r\n $response = chatbot_chatgpt_call_markov_chain_api( $message );\r\n break;\r\n case 'Transformer':\r\n $kchat_settings['model'] = $model;\r\n // Send message to Transformer Model API - Ver 2.2.0\r\n $response = chatbot_chatgpt_call_transformer_model_api( $message );\r\n break;\r\n case 'Local Server':\r\n $kchat_settings['model'] = $model;\r\n // Send message to Local Model API - Ver 2.2.6\r\n $response = chatbot_chatgpt_call_local_model_api( $message );\r\n break;\r\n default:\r\n $kchat_settings['model'] = $model;\r\n // Send message to ChatGPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_call_api( $api_key, $message );\r\n }\r\n // Defensive programming - Ver 2.2.9\r\n if ( is_array( $response ) ) {\r\n if ( isset( $response['response'] ) ) {\r\n // Likely nested from a mistake — pull the actual content out\r\n $response = $response['response'];\r\n } else {\r\n // Fallback: flatten it all into a string just to be safe\r\n $response = print_r( $response, true );\r\n }\r\n }\r\n // Use TF-IDF to enhance response\r\n $chatbot_chatgpt_suppress_learnings = esc_attr( get_option( 'chatbot_chatgpt_suppress_learnings', 'Random' ) );\r\n if ( $chatbot_chatgpt_suppress_learnings != 'None' ) {\r\n $response = $response . '

' . chatbot_chatgpt_enhance_with_tfidf( $message );\r\n }\r\n $thread_id = get_chatbot_chatgpt_threads(\r\n $user_id,\r\n $session_id,\r\n $page_id,\r\n $assistant_id\r\n );\r\n append_message_to_conversation_log(\r\n $session_id,\r\n $user_id,\r\n $page_id,\r\n 'Chatbot',\r\n $thread_id,\r\n $assistant_id,\r\n null,\r\n $response\r\n );\r\n $response = chatbot_chatgpt_check_for_links_and_images( $response );\r\n // FIXME - Append extra message - Ver 2.1.1.1.1\r\n // Danger Will Robinson! Danger!\r\n $extra_message = esc_attr( get_option( 'chatbot_chatgpt_extra_message', '' ) );\r\n $response = chatbot_chatgpt_append_extra_message( $response, $extra_message );\r\n // Clear conversation lock and process queue BEFORE sending response\r\n delete_transient( $conv_lock );\r\n chatbot_chatgpt_process_queue(\r\n $user_id,\r\n $page_id,\r\n $session_id,\r\n $assistant_id\r\n );\r\n // Return response\r\n wp_send_json_success( $response );\r\n }\r\n global $chatbot_chatgpt_fixed_literal_messages;\r\n // Define a default fallback message\r\n $default_message = 'Oops! I fell through the cracks!';\r\n $error_message = ( isset( $chatbot_chatgpt_fixed_literal_messages[1] ) ? $chatbot_chatgpt_fixed_literal_messages[1] : $default_message );\r\n // Send error response\r\n wp_send_json_error( $error_message );\r\n // Clear conversation lock on error\r\n delete_transient( $conv_lock );\r\n }\r\n\r\n // Handle nonce refresh requests - Ver 2.3.6\r\n function chatbot_chatgpt_refresh_nonce() {\r\n // Generate fresh nonces\r\n $nonces = array(\r\n 'chatbot_message_nonce' => wp_create_nonce( 'chatbot_message_nonce' ),\r\n 'chatbot_upload_nonce' => wp_create_nonce( 'chatbot_upload_nonce' ),\r\n 'chatbot_erase_nonce' => wp_create_nonce( 'chatbot_erase_nonce' ),\r\n 'chatbot_unlock_nonce' => wp_create_nonce( 'chatbot_unlock_nonce' ),\r\n 'chatbot_reset_nonce' => wp_create_nonce( 'chatbot_reset_nonce' ),\r\n 'chatbot_queue_nonce' => wp_create_nonce( 'chatbot_queue_nonce' ),\r\n 'chatbot_tts_nonce' => wp_create_nonce( 'chatbot_tts_nonce' ),\r\n 'chatbot_transcript_nonce' => wp_create_nonce( 'chatbot_transcript_nonce' ),\r\n );\r\n wp_send_json_success( $nonces );\r\n }\r\n\r\n // Function to clear stuck visitor locks - Ver 2.3.6\r\n function chatbot_chatgpt_clear_stuck_visitor_locks() {\r\n global $wpdb;\r\n // Only run for visitors (not logged in users)\r\n if ( is_user_logged_in() ) {\r\n return;\r\n }\r\n // Clear locks older than 2 minutes\r\n $expired_time = time() - 120;\r\n // 2 minutes ago\r\n $lock_patterns = ['_transient_chatgpt_conv_lock_%', '_transient_timeout_chatgpt_conv_lock_%'];\r\n foreach ( $lock_patterns as $pattern ) {\r\n $wpdb->query( $wpdb->prepare( \"DELETE FROM {$wpdb->options} WHERE option_name LIKE %s AND option_value < %d\", $pattern, $expired_time ) );\r\n }\r\n }\r\n\r\n // Hook to clear stuck locks on init for visitors\r\n add_action( 'init', 'chatbot_chatgpt_clear_stuck_visitor_locks', 5 );\r\n // Add admin menu for visitor lock clearing tool - Ver 2.3.6\r\n function chatbot_chatgpt_add_visitor_lock_tool_menu() {\r\n add_submenu_page(\r\n 'chatbot-chatgpt',\r\n 'Clear Visitor Locks',\r\n 'Clear Visitor Locks',\r\n 'manage_options',\r\n 'chatbot-clear-visitor-locks',\r\n 'chatbot_chatgpt_visitor_lock_tool_page'\r\n );\r\n }\r\n\r\n add_action( 'admin_menu', 'chatbot_chatgpt_add_visitor_lock_tool_menu' );\r\n // Admin page for visitor lock clearing tool\r\n function chatbot_chatgpt_visitor_lock_tool_page() {\r\n if ( isset( $_POST['clear_locks'] ) && wp_verify_nonce( $_POST['_wpnonce'], 'clear_visitor_locks' ) ) {\r\n chatbot_chatgpt_clear_stuck_visitor_locks();\r\n echo '

Visitor locks cleared successfully!

';\r\n }\r\n echo '
';\r\n echo '

Clear Visitor Locks

';\r\n echo '

This tool clears stuck conversation locks that may be preventing visitors from using the chatbot.

';\r\n echo '

Use this if visitors are getting \"system is busy processing requests\" messages.

';\r\n echo '
';\r\n wp_nonce_field( 'clear_visitor_locks' );\r\n echo '

';\r\n echo '
';\r\n echo '
';\r\n }\r\n\r\n // Add action to send messages - Ver 1.0.0\r\n add_action( 'wp_ajax_chatbot_chatgpt_send_message', 'chatbot_chatgpt_send_message' );\r\n add_action( 'wp_ajax_nopriv_chatbot_chatgpt_send_message', 'chatbot_chatgpt_send_message' );\r\n // Add action to refresh nonce - Ver 2.3.6\r\n add_action( 'wp_ajax_chatbot_chatgpt_refresh_nonce', 'chatbot_chatgpt_refresh_nonce' );\r\n add_action( 'wp_ajax_nopriv_chatbot_chatgpt_refresh_nonce', 'chatbot_chatgpt_refresh_nonce' );\r\n // Add action to get queue status\r\n add_action( 'wp_ajax_chatbot_chatgpt_get_queue_status', 'chatbot_chatgpt_get_queue_status_ajax' );\r\n add_action( 'wp_ajax_nopriv_chatbot_chatgpt_get_queue_status', 'chatbot_chatgpt_get_queue_status_ajax' );\r\n // Add action to upload files - Ver 1.7.6 (Security: Authentication required)\r\n add_action( 'wp_ajax_chatbot_chatgpt_upload_files', 'chatbot_chatgpt_upload_files' );\r\n // Add action to upload mp3 files - Ver 1.7.6 (Security: Authentication required)\r\n add_action( 'wp_ajax_chatbot_chatgpt_upload_mp3', 'chatbot_chatgpt_upload_mp3' );\r\n // Add action to erase conversation - Ver 1.8.6 (Security: Authentication required)\r\n add_action( 'wp_ajax_chatbot_chatgpt_erase_conversation', 'chatbot_chatgpt_erase_conversation_handler' );\r\n add_action( 'wp_ajax_nopriv_chatbot_chatgpt_erase_conversation', 'chatbot_chatgpt_erase_conversation_handler' );\r\n // Add action to unlock conversation - Ver 2.3.0 (Security: Authentication required)\r\n add_action( 'wp_ajax_chatbot_chatgpt_unlock_conversation', 'chatbot_chatgpt_unlock_conversation_handler' );\r\n // Add action to reset all locks (Security: Authentication required)\r\n add_action( 'wp_ajax_chatbot_chatgpt_reset_all_locks', 'chatbot_chatgpt_reset_all_locks_handler' );\r\n // Add action to reset cache and locks (Security: Authentication required) - Ver 2.3.6\r\n add_action( 'wp_ajax_chatbot_chatgpt_reset_cache_locks', 'chatbot_chatgpt_reset_cache_locks_handler' );\r\n // Add action for text-to-speech (Security: Authentication required)\r\n add_action( 'wp_ajax_chatbot_chatgpt_read_aloud', 'chatbot_chatgpt_read_aloud' );\r\n // Add action for transcript download (Security: Authentication required)\r\n add_action( 'wp_ajax_chatbot_chatgpt_download_transcript', 'chatbot_chatgpt_download_transcript' );\r\n // Settings and Deactivation - Ver 1.5.0\r\n add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), 'chatbot_chatgpt_plugin_action_links' );\r\n // Unlock conversation handler - Ver 2.3.0\r\n function chatbot_chatgpt_unlock_conversation_handler() {\r\n // Security: Check if user has permission to manage options (admin capability)\r\n if ( !current_user_can( 'manage_options' ) ) {\r\n wp_send_json_error( 'Insufficient permissions to unlock conversation.', 403 );\r\n return;\r\n }\r\n // Security: Verify nonce for CSRF protection\r\n if ( !isset( $_POST['chatbot_nonce'] ) || !wp_verify_nonce( $_POST['chatbot_nonce'], 'chatbot_unlock_nonce' ) ) {\r\n wp_send_json_error( 'Security check failed. Please refresh the page and try again.', 403 );\r\n return;\r\n }\r\n // Get parameters from POST\r\n $user_id = ( isset( $_POST['user_id'] ) ? sanitize_text_field( $_POST['user_id'] ) : '' );\r\n $page_id = ( isset( $_POST['page_id'] ) ? sanitize_text_field( $_POST['page_id'] ) : '' );\r\n $session_id = ( isset( $_POST['session_id'] ) ? sanitize_text_field( $_POST['session_id'] ) : '' );\r\n $assistant_id = ( isset( $_POST['assistant_id'] ) ? sanitize_text_field( $_POST['assistant_id'] ) : '' );\r\n if ( $user_id && $page_id && $session_id && $assistant_id ) {\r\n // Clear the conversation lock\r\n $conv_lock = 'chatgpt_conv_lock_' . wp_hash( $assistant_id . '|' . $user_id . '|' . $page_id . '|' . $session_id );\r\n $lock_exists = get_transient( $conv_lock );\r\n $deleted_lock = delete_transient( $conv_lock );\r\n // Clear the message queue\r\n $queue_key = 'chatbot_message_queue_' . wp_hash( $assistant_id . '|' . $user_id . '|' . $page_id . '|' . $session_id );\r\n $queue_exists = get_transient( $queue_key );\r\n $deleted_queue = delete_transient( $queue_key );\r\n // Try to clear all possible lock variations\r\n $possible_locks = [\r\n 'chatgpt_conv_lock_' . wp_hash( $assistant_id . '|' . $user_id . '|' . $page_id . '|' . $session_id ),\r\n 'chatgpt_conv_lock_' . wp_hash( $user_id . '|' . $page_id . '|' . $session_id ),\r\n 'chatgpt_conv_lock_' . wp_hash( $session_id ),\r\n 'chatgpt_conv_lock_' . $session_id,\r\n 'chatgpt_conv_lock_' . $user_id . '_' . $page_id . '_' . $session_id,\r\n // Additional variations for visitor locks\r\n 'chatgpt_conv_lock_' . wp_hash( $assistant_id . '|' . $session_id . '|' . $page_id ),\r\n 'chatgpt_conv_lock_' . wp_hash( $session_id . '|' . $page_id ),\r\n ];\r\n foreach ( $possible_locks as $lock_key ) {\r\n if ( get_transient( $lock_key ) ) {\r\n delete_transient( $lock_key );\r\n }\r\n }\r\n wp_send_json_success( 'Conversation unlocked' );\r\n } else {\r\n wp_send_json_error( 'Missing parameters' );\r\n }\r\n }\r\n\r\n // Global lock reset handler - Ver 2.3.0\r\n function chatbot_chatgpt_reset_all_locks_handler() {\r\n // Security: Check if user has permission to manage options (admin capability)\r\n if ( !current_user_can( 'manage_options' ) ) {\r\n wp_send_json_error( 'Insufficient permissions to reset locks.', 403 );\r\n return;\r\n }\r\n // Security: Verify nonce for CSRF protection\r\n if ( !isset( $_POST['chatbot_nonce'] ) || !wp_verify_nonce( $_POST['chatbot_nonce'], 'chatbot_reset_nonce' ) ) {\r\n wp_send_json_error( 'Security check failed. Please refresh the page and try again.', 403 );\r\n return;\r\n }\r\n // Get parameters from POST\r\n $user_id = ( isset( $_POST['user_id'] ) ? sanitize_text_field( $_POST['user_id'] ) : '' );\r\n $page_id = ( isset( $_POST['page_id'] ) ? sanitize_text_field( $_POST['page_id'] ) : '' );\r\n $session_id = ( isset( $_POST['session_id'] ) ? sanitize_text_field( $_POST['session_id'] ) : '' );\r\n $assistant_id = ( isset( $_POST['assistant_id'] ) ? sanitize_text_field( $_POST['assistant_id'] ) : '' );\r\n $cleared_count = 0;\r\n if ( $user_id && $page_id && $session_id && $assistant_id ) {\r\n // Clear all possible lock variations for this conversation\r\n $possible_locks = [\r\n 'chatgpt_conv_lock_' . wp_hash( $assistant_id . '|' . $user_id . '|' . $page_id . '|' . $session_id ),\r\n 'chatgpt_conv_lock_' . wp_hash( $user_id . '|' . $page_id . '|' . $session_id ),\r\n 'chatgpt_conv_lock_' . wp_hash( $session_id ),\r\n 'chatgpt_conv_lock_' . $session_id,\r\n 'chatgpt_conv_lock_' . $user_id . '_' . $page_id . '_' . $session_id,\r\n 'chatgpt_run_lock_' . wp_hash( $assistant_id . '|' . $user_id . '|' . $page_id . '|' . $session_id ),\r\n 'chatgpt_run_lock_' . wp_hash( $user_id . '|' . $page_id . '|' . $session_id ),\r\n 'chatgpt_run_lock_' . wp_hash( $session_id ),\r\n 'chatgpt_run_lock_' . $session_id,\r\n 'chatgpt_run_lock_' . $user_id . '_' . $page_id . '_' . $session_id\r\n ];\r\n foreach ( $possible_locks as $lock_key ) {\r\n if ( get_transient( $lock_key ) ) {\r\n delete_transient( $lock_key );\r\n $cleared_count++;\r\n }\r\n }\r\n // Clear all possible queue variations\r\n $possible_queues = [\r\n 'chatbot_message_queue_' . wp_hash( $assistant_id . '|' . $user_id . '|' . $page_id . '|' . $session_id ),\r\n 'chatbot_message_queue_' . wp_hash( $user_id . '|' . $page_id . '|' . $session_id ),\r\n 'chatbot_message_queue_' . wp_hash( $session_id ),\r\n 'chatbot_message_queue_' . $session_id,\r\n 'chatbot_message_queue_' . $user_id . '_' . $page_id . '_' . $session_id\r\n ];\r\n foreach ( $possible_queues as $queue_key ) {\r\n if ( get_transient( $queue_key ) ) {\r\n delete_transient( $queue_key );\r\n $cleared_count++;\r\n }\r\n }\r\n wp_send_json_success( 'Reset completed - Cleared ' . $cleared_count . ' locks/queues' );\r\n } else {\r\n wp_send_json_error( 'Missing parameters' );\r\n }\r\n }\r\n\r\n // Reset Cache and Locks Handler - Ver 2.3.6\r\n function chatbot_chatgpt_reset_cache_locks_handler() {\r\n // Security: Check if user has permission to manage options (admin capability)\r\n if ( !current_user_can( 'manage_options' ) ) {\r\n wp_send_json_error( 'Insufficient permissions to reset cache and locks.', 403 );\r\n return;\r\n }\r\n // Security: Verify nonce for CSRF protection\r\n if ( !isset( $_POST['chatbot_nonce'] ) || !wp_verify_nonce( $_POST['chatbot_nonce'], 'chatbot_reset_cache_locks' ) ) {\r\n wp_send_json_error( 'Security check failed. Please refresh the page and try again.', 403 );\r\n return;\r\n }\r\n global $wpdb;\r\n $cleared_count = 0;\r\n try {\r\n // Clear all conversation locks\r\n $lock_patterns = [\r\n '_transient_chatgpt_conv_lock_%',\r\n '_transient_timeout_chatgpt_conv_lock_%',\r\n '_transient_chatgpt_run_lock_%',\r\n '_transient_timeout_chatgpt_run_lock_%',\r\n '_transient_chatbot_message_queue_%',\r\n '_transient_timeout_chatbot_message_queue_%',\r\n '_transient_chatbot_chatgpt_%',\r\n '_transient_timeout_chatbot_chatgpt_%'\r\n ];\r\n foreach ( $lock_patterns as $pattern ) {\r\n $result = $wpdb->query( $wpdb->prepare( \"DELETE FROM {$wpdb->options} WHERE option_name LIKE %s\", $pattern ) );\r\n $cleared_count += $result;\r\n }\r\n // Clear expired transients\r\n $expired_result = $wpdb->query( $wpdb->prepare( \"DELETE FROM {$wpdb->options} WHERE option_name LIKE %s AND option_value < %d\", '_transient_timeout_%', time() ) );\r\n $cleared_count += $expired_result;\r\n // Clear WordPress object cache if available\r\n if ( function_exists( 'wp_cache_flush' ) ) {\r\n wp_cache_flush();\r\n }\r\n // Clear any file-based caches\r\n $cache_dirs = [\r\n WP_CONTENT_DIR . '/cache/',\r\n WP_CONTENT_DIR . '/uploads/chatbot-chatgpt/',\r\n plugin_dir_path( __FILE__ ) . 'cache/',\r\n plugin_dir_path( __FILE__ ) . 'audio/',\r\n plugin_dir_path( __FILE__ ) . 'downloads/',\r\n plugin_dir_path( __FILE__ ) . 'transcripts/'\r\n ];\r\n foreach ( $cache_dirs as $cache_dir ) {\r\n if ( is_dir( $cache_dir ) ) {\r\n $files = glob( $cache_dir . '*' );\r\n foreach ( $files as $file ) {\r\n if ( is_file( $file ) && filemtime( $file ) < time() - 3600 ) {\r\n // Older than 1 hour\r\n @unlink( $file );\r\n $cleared_count++;\r\n }\r\n }\r\n }\r\n }\r\n // Log the action\r\n $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';\r\n chatbot_error_log( $log_message );\r\n wp_send_json_success( 'Cache and locks reset successfully. Cleared ' . $cleared_count . ' entries.' );\r\n } catch ( Exception $e ) {\r\n $log_message = '[' . date( 'Y-m-d H:i:s' ) . '] [Chatbot] [Advanced Reset] Error: ' . $e->getMessage();\r\n chatbot_error_log( $log_message );\r\n wp_send_json_error( 'Error resetting cache and locks: ' . $e->getMessage() );\r\n }\r\n }\r\n\r\n // Append an extra message to the response - Ver 2.0.9\r\n function chatbot_chatgpt_append_extra_message( $response, $extra_message ) {\r\n // Append the extra message to the response\r\n $response = $response . ' ' . $extra_message;\r\n return $response;\r\n }\r\n\r\n // Crawler aka Knowledge Navigator - Ver 1.6.1\r\n function chatbot_chatgpt_kn_status_activation() {\r\n add_option( 'chatbot_chatgpt_kn_status', 'Never Run' );\r\n // clear any old scheduled runs\r\n if ( wp_next_scheduled( 'crawl_scheduled_event_hook' ) ) {\r\n wp_clear_scheduled_hook( 'crawl_scheduled_event_hook' );\r\n }\r\n // clear the 'knowledge_navigator_scan_hook' hook on plugin activation - Ver 1.6.3\r\n if ( wp_next_scheduled( 'knowledge_navigator_scan_hook' ) ) {\r\n // BREAK/FIX - Do not unset the hook - Ver 1.8.5\r\n // wp_clear_scheduled_hook('knowledge_navigator_scan_hook'); // Clear scheduled runs\r\n }\r\n }\r\n\r\n register_activation_hook( __FILE__, 'chatbot_chatgpt_kn_status_activation' );\r\n // Clean Up in Aisle 4\r\n function chatbot_chatgpt_kn_status_deactivation() {\r\n delete_option( 'chatbot_chatgpt_kn_status' );\r\n wp_clear_scheduled_hook( 'knowledge_navigator_scan_hook' );\r\n }\r\n\r\n register_deactivation_hook( __FILE__, 'chatbot_chatgpt_kn_status_deactivation' );\r\n // Markov Chain builder - Activation Hook - Ver 2.1.6\r\n function chatbot_markov_chain_status_activation() {\r\n // Add the option for build status with a default value of 'Never Run'\r\n add_option( 'chatbot_markov_chain_build_status', 'Never Run' );\r\n // Clear any old scheduled runs, if present\r\n if ( wp_next_scheduled( 'chatbot_markov_chain_scan_hook' ) ) {\r\n // BREAK/FIX - Do not unset the hook - Ver 2.1.6\r\n // wp_clear_scheduled_hook('chatbot_markov_chain_scan_hook'); // Clear scheduled runs\r\n }\r\n }\r\n\r\n register_activation_hook( __FILE__, 'chatbot_markov_chain_status_activation' );\r\n // Clean up scheduled events and options - Deactivation Hook\r\n function chatbot_markov_chain_status_deactivation() {\r\n // Delete the build status option on deactivation\r\n delete_option( 'chatbot_markov_chain_build_status' );\r\n // Clear any scheduled events related to the Markov Chain scan\r\n wp_clear_scheduled_hook( 'chatbot_markov_chain_scan_hook' );\r\n }\r\n\r\n register_deactivation_hook( __FILE__, 'chatbot_markov_chain_status_deactivation' );\r\n // Transformer Model builder - Activation Hook - Ver 2.2.0\r\n function chatbot_transformer_model_status_activation() {\r\n // Add the option for build status with a default value of 'Never Run'\r\n add_option( 'chatbot_transformer_model_build_status', 'Never Run' );\r\n // Clear any old scheduled runs, if present\r\n if ( wp_next_scheduled( 'chatbot_transformer_model_scan_hook' ) ) {\r\n // BREAK/FIX - Do not unset the hook - Ver 2.2.0\r\n // wp_clear_scheduled_hook('chatbot_transformer_model_scan_hook'); // Clear scheduled runs\r\n }\r\n }\r\n\r\n register_activation_hook( __FILE__, 'chatbot_transformer_model_status_activation' );\r\n // Clean up scheduled events and options - Deactivation Hook\r\n function chatbot_transformer_model_status_deactivation() {\r\n // Delete the build status option on deactivation\r\n delete_option( 'chatbot_transformer_model_build_status' );\r\n // Clear any scheduled events related to the Transformer Model scan\r\n wp_clear_scheduled_hook( 'chatbot_transformer_model_scan_hook' );\r\n }\r\n\r\n register_deactivation_hook( __FILE__, 'chatbot_transformer_model_status_deactivation' );\r\n // Function to add a new message and response, keeping only the last five - Ver 1.6.1\r\n function addEntry( $transient_name, $newEntry ) {\r\n $context_history = get_transient( $transient_name );\r\n if ( !$context_history ) {\r\n $context_history = [];\r\n }\r\n // Determine the total length of all existing entries\r\n $totalLength = 0;\r\n foreach ( $context_history as $entry ) {\r\n if ( is_string( $entry ) ) {\r\n $totalLength += strlen( $entry );\r\n } elseif ( is_array( $entry ) ) {\r\n $totalLength += strlen( json_encode( $entry ) );\r\n // Convert to string if an array\r\n }\r\n }\r\n // IDEA - How will the new threading option from OpenAI change how this works?\r\n // Define thresholds for the number of entries to keep\r\n $maxEntries = 30;\r\n // Default maximum number of entries\r\n if ( $totalLength > 5000 ) {\r\n // Higher threshold\r\n $maxEntries = 20;\r\n }\r\n if ( $totalLength > 10000 ) {\r\n // Lower threshold\r\n $maxEntries = 10;\r\n }\r\n while ( count( $context_history ) >= $maxEntries ) {\r\n array_shift( $context_history );\r\n // Remove the oldest element\r\n }\r\n if ( is_array( $newEntry ) ) {\r\n $newEntry = json_encode( $newEntry );\r\n // Convert the array to a string\r\n }\r\n array_push( $context_history, $newEntry );\r\n // Append the new element\r\n set_transient( $transient_name, $context_history );\r\n // Update the transient\r\n }\r\n\r\n // Function to return message and response - Ver 1.6.1\r\n function concatenateHistory( $transient_name ) {\r\n $context_history = get_transient( $transient_name );\r\n if ( !$context_history ) {\r\n return '';\r\n // Return an empty string if the transient does not exist\r\n }\r\n return implode( ' ', $context_history );\r\n // Concatenate the array values into a single string\r\n }\r\n\r\n // FIXME - MOVE CORE FUNCTIONS TO A SEPARATE FILE, LEAVING ONLY THE HOOKS HERE\r\n // Initialize the Greetings - Ver 1.6.1\r\n function enqueue_greetings_script( $initial_greeting = null, $subsequent_greeting = null ) {\r\n // If user is logged in, then modify greeting if greeting contains \"[...]\" or remove if not logged in - Ver 1.9.4\r\n if ( is_user_logged_in() ) {\r\n $current_user_id = get_current_user_id();\r\n $current_user = get_userdata( $current_user_id );\r\n //Do this for Initial Greeting\r\n if ( empty( $initial_greeting ) ) {\r\n $initial_greeting = esc_attr( get_option( 'chatbot_chatgpt_initial_greeting', 'Hello! How can I help you today?' ) );\r\n }\r\n // Determine what the field name is between the brackets\r\n $user_field_name = '';\r\n $user_field_name = substr( $initial_greeting, strpos( $initial_greeting, '[' ) + 1, strpos( $initial_greeting, ']' ) - strpos( $initial_greeting, '[' ) - 1 );\r\n // If $initial_greeting contains \"[$user_field_name]\" then replace with field from DB\r\n if ( strpos( $initial_greeting, '[' . $user_field_name . ']' ) !== false ) {\r\n $initial_greeting = str_replace( '[' . $user_field_name . ']', $current_user->{$user_field_name}, $initial_greeting );\r\n } else {\r\n $initial_greeting = str_replace( '[' . $user_field_name . ']', '', $initial_greeting );\r\n // Remove the extra space when two spaces are present\r\n $initial_greeting = str_replace( ' ', ' ', $initial_greeting );\r\n // Remove the extra space before punctuation including period, comma, exclamation mark, and question mark\r\n $initial_greeting = preg_replace( '/\\\\s*([.,!?])/', '$1', $initial_greeting );\r\n }\r\n // Do this for Subsequent Greeting\r\n if ( empty( $subsequent_greeting ) ) {\r\n $subsequent_greeting = esc_attr( get_option( 'chatbot_chatgpt_subsequent_greeting', 'Hello again! How can I help you?' ) );\r\n }\r\n // Determine what the field name is between the brackets\r\n $user_field_name = '';\r\n $user_field_name = substr( $subsequent_greeting, strpos( $subsequent_greeting, '[' ) + 1, strpos( $subsequent_greeting, ']' ) - strpos( $subsequent_greeting, '[' ) - 1 );\r\n // If $subsequent_greeting contains \"[$user_field_name]\" then replace with field from DB\r\n if ( strpos( $subsequent_greeting, '[' . $user_field_name . ']' ) !== false ) {\r\n $subsequent_greeting = str_replace( '[' . $user_field_name . ']', $current_user->{$user_field_name}, $subsequent_greeting );\r\n } else {\r\n $subsequent_greeting = str_replace( '[' . $user_field_name . ']', '', $subsequent_greeting );\r\n // Remove the extra space when two spaces are present\r\n $subsequent_greeting = str_replace( ' ', ' ', $subsequent_greeting );\r\n // Remove the extra space before punctuation including period, comma, exclamation mark, and question mark\r\n $subsequent_greeting = preg_replace( '/\\\\s*([.,!?])/', '$1', $subsequent_greeting );\r\n }\r\n } else {\r\n //Do this for Initial Greeting\r\n if ( empty( $initial_greeting ) ) {\r\n $initial_greeting = esc_attr( get_option( 'chatbot_chatgpt_initial_greeting', 'Hello! How can I help you today?' ) );\r\n }\r\n $user_field_name = '';\r\n $user_field_name = substr( $initial_greeting, strpos( $initial_greeting, '[' ) + 1, strpos( $initial_greeting, ']' ) - strpos( $initial_greeting, '[' ) - 1 );\r\n // $initial_greeting = preg_replace('/\\s*\\[' . preg_quote($user_field_name, '/') . '\\]\\s*/', '', $initial_greeting);\r\n $initial_greeting = str_replace( '[' . $user_field_name . ']', '', $initial_greeting );\r\n // Remove the extra space when two spaces are present\r\n $initial_greeting = str_replace( ' ', ' ', $initial_greeting );\r\n // Remove the extra space before punctuation including period, comma, exclamation mark, and question mark\r\n $initial_greeting = preg_replace( '/\\\\s*([.,!?])/', '$1', $initial_greeting );\r\n //Do this for Subsequent Greeting\r\n if ( empty( $subsequent_greeting ) ) {\r\n $subsequent_greeting = esc_attr( get_option( 'chatbot_chatgpt_subsequent_greeting', 'Hello again! How can I help you?' ) );\r\n }\r\n $user_field_name = '';\r\n $user_field_name = substr( $subsequent_greeting, strpos( $subsequent_greeting, '[' ) + 1, strpos( $subsequent_greeting, ']' ) - strpos( $subsequent_greeting, '[' ) - 1 );\r\n // $subsequent_greeting = preg_replace('/\\s*\\[' . preg_quote($user_field_name, '/') . '\\]\\s*/', '', $subsequent_greeting);\r\n $subsequent_greeting = str_replace( '[' . $user_field_name . ']', '', $subsequent_greeting );\r\n // Remove the extra space when two spaces are present\r\n $subsequent_greeting = str_replace( ' ', ' ', $subsequent_greeting );\r\n // Remove the extra space before punctuation including period, comma, exclamation mark, and question mark\r\n $subsequent_greeting = preg_replace( '/\\\\s*([.,!?])/', '$1', $subsequent_greeting );\r\n }\r\n $greetings = array(\r\n 'initial_greeting' => $initial_greeting,\r\n 'subsequent_greeting' => $subsequent_greeting,\r\n );\r\n return $greetings;\r\n }\r\n\r\n add_action( 'wp_enqueue_scripts', 'enqueue_greetings_script' );\r\n // Add the color picker to the adaptive appearance settings section - Ver 1.8.1\r\n function enqueue_color_picker( $hook_suffix ) {\r\n global $chatbot_chatgpt_plugin_version;\r\n // first check that $hook_suffix is appropriate for your admin page\r\n wp_enqueue_style( 'wp-color-picker' );\r\n wp_enqueue_script(\r\n 'my-script-handle',\r\n plugin_dir_url( __FILE__ ) . 'assets/js/chatbot-chatgpt-color-picker.js',\r\n array('wp-color-picker'),\r\n $chatbot_chatgpt_plugin_version,\r\n true\r\n );\r\n }\r\n\r\n add_action( 'admin_enqueue_scripts', 'enqueue_color_picker' );\r\n // Determine if the plugin is installed\r\n // NOTE: This function is deprecated. Version tracking is now handled via chatbot_chatgpt_version_installed option.\r\n // Kept for backward compatibility but no longer updates the legacy chatbot_chatgpt_plugin_version option.\r\n function kchat_get_plugin_version() {\r\n global $chatbot_chatgpt_plugin_version;\r\n if ( !function_exists( 'get_plugin_data' ) ) {\r\n require_once ABSPATH . 'wp-admin/includes/plugin.php';\r\n }\r\n $plugin_data = get_plugin_data( plugin_dir_path( __FILE__ ) . 'chatbot-chatgpt.php' );\r\n $plugin_version = $plugin_data['Version'];\r\n // Return version without updating legacy option (chatbot_chatgpt_plugin_version is deprecated)\r\n return $plugin_version;\r\n }\r\n\r\n // DO NOT REMOVE THIS IF, IT IS ESSENTIAL FOR THE AUTOMATIC DEACTIVATION OF THE PLUGIN\r\n}"}, "d220016661204e86dcb7dcd9ca07f72b8b4dd5d6": {"t": 1785756406.5378149, "n": 66783, "h": "2959a3aa364950c6", "c": " $user_id,\r\n 'page_id' => $page_id,\r\n 'session_id' => $session_id,\r\n 'thread_id' => $thread_id,\r\n 'assistant_id' => $assistant_id,\r\n 'additional_instructions' => $additional_instructions,\r\n 'model' => $model,\r\n 'voice' => $voice,\r\n ));\r\n\r\n // DIAG - Diagnostics - Ver 1.8.6\r\n // back_trace( 'NOTICE', '$user_id: ' . $user_id);\r\n // back_trace( 'NOTICE', '$page_id: ' . $page_id);\r\n // back_trace( 'NOTICE', '$session_id: ' . $session_id);\r\n // back_trace( 'NOTICE', '$thread_id: ' . $thread_id);\r\n // back_trace( 'NOTICE', '$assistant_id: ' . $assistant_id);\r\n // back_trace( 'NOTICE', '$additional_instructions: ' . $additional_instructions);\r\n // back_trace( 'NOTICE', '$model: ' . $model);\r\n \r\n // Set visitor and logged in user limits - Ver 2.0.1\r\n if (is_user_logged_in()) {\r\n // back_trace( 'NOTICE', 'User is logged in');\r\n $kchat_settings['chatbot_chatgpt_message_limit_setting'] = esc_attr(get_option('chatbot_chatgpt_user_message_limit_setting', '999'));\r\n $kchat_settings['chatbot_chatgpt_message_limit_period_setting'] = esc_attr(get_option('chatbot_chatgpt_user_message_limit_period_setting', 'Lifetime'));\r\n } else {\r\n // back_trace( 'NOTICE', 'User is NOT logged in');\r\n $kchat_settings['chatbot_chatgpt_message_limit_setting'] = esc_attr(get_option('chatbot_chatgpt_visitor_message_limit_setting', '999'));\r\n $kchat_settings['chatbot_chatgpt_message_limit_period_setting'] = esc_attr(get_option('chatbot_chatgpt_visitor_message_limit_period_setting', 'Lifetime'));\r\n }\r\n\r\n // Localize the data for the chatbot - Ver 2.1.1.1\r\n $kchat_settings = array_merge($kchat_settings, array(\r\n 'chatbot_chatgpt_display_style' => $chatbot_chatgpt_display_style,\r\n 'chatbot_chatgpt_version' => $chatbot_chatgpt_plugin_version,\r\n 'plugins_url' => $chatbot_chatgpt_plugin_dir_url,\r\n 'ajax_url' => admin_url('admin-ajax.php'),\r\n 'user_id' => $user_id,\r\n 'page_id' => $page_id,\r\n 'session_id' => $session_id,\r\n 'thread_id' => $thread_id,\r\n 'assistant_id' => $assistant_id,\r\n 'additional_instructions' => $additional_instructions,\r\n 'model' => $model,\r\n 'voice' => $voice,\r\n 'chatbot_chatgpt_timeout_setting' => esc_attr(get_option('chatbot_chatgpt_timeout_setting', '240')),\r\n 'chatbot_chatgpt_avatar_icon_setting' => esc_attr(get_option('chatbot_chatgpt_avatar_icon_setting', '')),\r\n 'chatbot_chatgpt_custom_avatar_icon_setting' => esc_attr(get_option('chatbot_chatgpt_custom_avatar_icon_setting', '')),\r\n '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?')),\r\n 'chatbot_chatgpt_force_page_reload' => esc_attr(get_option('chatbot_chatgpt_force_page_reload', 'No')),\r\n 'chatbot_chatgpt_custom_error_message' => esc_attr(get_option('chatbot_chatgpt_custom_error_message', 'Your custom error message goes here.')),\r\n ));\r\n \r\n $kchat_settings_json = wp_json_encode($kchat_settings);\r\n\r\n // Enqueue the main chatbot script - CHANGED TO LOAD ORDER IN V2.1.2\r\n wp_enqueue_script('chatbot-chatgpt-js', plugins_url('assets/js/chatbot-chatgpt.js', __FILE__), array(), $chatbot_chatgpt_plugin_version, true);\r\n\r\n // Add the inline script to define kchat_settings before the main script runs - CHANGED THE LOAD ORDER IN VER 2.1.2\r\n 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');\r\n // FIXME - REMOVED IN V2.1.2\r\n // 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');\r\n\r\n}\r\nadd_action('wp_enqueue_scripts', 'chatbot_chatgpt_enqueue_scripts');\r\n\r\n// Enqueue MathJax with custom configuration - Ver 2.1.2\r\n// https://docs.mathjax.org/en/latest/\r\n// https://github.com/mathjax/MathJax/blob/master/LICENSE\r\n// https://cdnjs.cloudflare.com/ajax/libs/mathjax/3.2.0/es5/tex-mml-chtml.js\r\n// https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js\r\nfunction enqueue_mathjax_with_custom_config() {\r\n\r\n global $chatbot_chatgpt_plugin_version;\r\n global $chatbot_chatgpt_plugin_dir_url;\r\n\r\n // Add the MathJax configuration script\r\n $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 \";\r\n\r\n // Enqueue the MathJax script\r\n // wp_enqueue_script( 'mathjax', plugin_dir_url(__FILE__) . 'assets/js/tex-chtml.js', array(), $chatbot_chatgpt_plugin_version, true );\r\n wp_enqueue_script( 'mathjax', $chatbot_chatgpt_plugin_dir_url . 'assets/js/tex-mml-chtml.js', array(), $chatbot_chatgpt_plugin_version, true );\r\n\r\n // Add the inline script before MathJax script\r\n wp_add_inline_script( 'mathjax', $mathjax_config, 'before' );\r\n\r\n}\r\nadd_action( 'wp_enqueue_scripts', 'enqueue_mathjax_with_custom_config' );\r\n\r\n// CORS - Cross Origin Resource Sharing - CAUTION: This allows all domains to access the end point - Ver 2.1.2\r\n// function allow_cross_domain_requests() {\r\n// header(\"Access-Control-Allow-Origin: *\");\r\n// header(\"Access-Control-Allow-Methods: GET, POST, OPTIONS\");\r\n// header(\"Access-Control-Allow-Headers: X-Requested-With\");\r\n// }\r\n// add_action('init', 'allow_cross_domain_requests');\r\n\r\n// Settings and Deactivation Links - Ver - 1.5.0\r\nif (!function_exists('enqueue_jquery_ui')) {\r\n function enqueue_jquery_ui() {\r\n wp_enqueue_style('wp-jquery-ui-dialog');\r\n wp_enqueue_script('jquery-ui-dialog');\r\n }\r\n add_action( 'admin_enqueue_scripts', 'enqueue_jquery_ui' );\r\n}\r\n\r\n// Schedule Cleanup of Expired Transients\r\nif (!wp_next_scheduled('chatbot_chatgpt_cleanup_event')) {\r\n wp_schedule_event(time(), 'daily', 'chatbot_chatgpt_cleanup_event');\r\n}\r\nadd_action('chatbot_chatgpt_cleanup_event', 'clean_specific_expired_transients');\r\n\r\n// Schedule Conversation Log Cleanup - Ver 1.6.7\r\nif (!wp_next_scheduled('chatbot_chatgpt_conversation_log_cleanup_event')) {\r\n wp_schedule_event(time(), 'daily', 'chatbot_chatgpt_conversation_log_cleanup_event');\r\n}\r\nadd_action('chatbot_chatgpt_conversation_log_cleanup_event', 'chatbot_chatgpt_conversation_log_cleanup');\r\n\r\n// Schedule the transcript file cleanup event if it's not already scheduled - Ver 1.9.9\r\n// Schedule the cleanup event if it's not already scheduled\r\nif (!wp_next_scheduled('chatbot_chatgpt_cleanup_transcript_files')) {\r\n wp_schedule_event(time(), 'hourly', 'chatbot_chatgpt_cleanup_transcript_files');\r\n}\r\n\r\n// Deactivate old hooks - Ver 2.0.1\r\nif(esc_attr(get_option('chatbot_chatgpt_cleanup_old_hooks') !== 'Completed')) {\r\n // Deactivate old hooks - Ver 2.0.1\r\n wp_clear_scheduled_hook('chatbot_chatgpt_cleanup_transcripts');\r\n // Then update the option\r\n update_option('chatbot_chatgpt_cleanup_old_hooks', 'Completed');\r\n}\r\n\r\n// Schedule the audio file cleanup event if it's not already scheduled - Ver 1.9.9\r\n// Schedule the cleanup event if it's not already scheduled\r\nif (!wp_next_scheduled('chatbot_chatgpt_cleanup_audio_files')) {\r\n wp_schedule_event(time(), 'hourly', 'chatbot_chatgpt_cleanup_audio_files');\r\n}\r\n\r\n// Schedule the upload file cleanup event if it's not already scheduled - Ver 1.9.9\r\n// Schedule the cleanup event if it's not already scheduled\r\nif (!wp_next_scheduled('chatbot_chatgpt_cleanup_upload_files')) {\r\n wp_schedule_event(time(), 'hourly', 'chatbot_chatgpt_cleanup_upload_files');\r\n}\r\n\r\n// Schedule the download file cleanup event if it's not already scheduled - Ver 2.0.3\r\n// Schedule the cleanup event if it's not already scheduled\r\nif (!wp_next_scheduled('chatbot_chatgpt_cleanup_download_files')) {\r\n wp_schedule_event(time(), 'hourly', 'chatbot_chatgpt_cleanup_download_files');\r\n}\r\n\r\n// Add the Assistant table to the database - Ver 2.0.4\r\ncreate_chatbot_chatgpt_assistants_table();\r\n\r\n// Handle Ajax requests\r\nfunction chatbot_chatgpt_send_message() {\r\n\r\n // Global variables\r\n global $session_id;\r\n global $user_id;\r\n global $page_id;\r\n global $thread_id;\r\n global $assistant_id;\r\n global $chatbot_chatgpt_assistant_alias;\r\n global $kchat_settings;\r\n global $additional_instructions;\r\n global $model;\r\n global $voice;\r\n\r\n global $flow_data;\r\n\r\n $api_key = '';\r\n\r\n // Retrieve the API key\r\n if (esc_attr(get_option('chatbot_nvidia_api_enabled')) == 'Yes') {\r\n $api_key = esc_attr(get_option('chatbot_nvidia_api_key'));\r\n $model = esc_attr(get_option('chatbot_nvidia_model_choice', 'nvidia/llama-3.1-nemotron-51b-instruct'));\r\n $kchat_settings['chatbot_chatgpt_model'] = $model;\r\n $kchat_settings['model'] = $model;\r\n // DIAG - Diagnostics - Ver 2.1.8\r\n // back_trace( 'NOTICE', 'LINE 537 - $model: ' . $model);\r\n } else if (esc_attr(get_option('chatbot_markov_chain_api_enabled')) == 'Yes') {\r\n $api_key = esc_attr(get_option('chatbot_markov_chain_api_key'));\r\n $model = esc_attr(get_option('chatbot_markov_chain_model_choice', 'markov-chain-2024-09-17'));\r\n $kchat_settings['chatbot_chatgpt_model'] = $model;\r\n $kchat_settings['model'] = $model;\r\n // DIAG - Diagnostics - Ver 2.1.8\r\n // back_trace( 'NOTICE', 'LINE 544 - $model: ' . $model);\r\n } else {\r\n $api_key = esc_attr(get_option('chatbot_chatgpt_api_key'));\r\n $model = esc_attr(get_option('chatbot_chatgpt_model_choice', 'gpt-3.5-turbo'));\r\n $kchat_settings['chatbot_chatgpt_model'] = $model;\r\n $kchat_settings['model'] = $model;\r\n // DIAG - Diagnostics - Ver 2.1.8\r\n // back_trace( 'NOTICE', 'LINE 551 - $model: ' . $model);\r\n }\r\n\r\n // DIAG - Diagnostics - Ver 2.1.8\r\n // back_trace( 'NOTICE', 'LINE 555 - $model: ' . $model);\r\n\r\n // Send only clean text via the API\r\n $message = sanitize_text_field($_POST['message']);\r\n\r\n // If Markov Chain is enabled, then process the message\r\n if (esc_attr(get_option('chatbot_markov_chain_api_enabled', 'No')) == 'Yes') {\r\n // Check for missing Message\r\n if (!$message) {\r\n // DIAG - Diagnostics\r\n // back_trace( 'ERROR', 'Invalid API Key or Message.');\r\n wp_send_json_error('Error: Invalid API key or Message. Please check the plugin settings.');\r\n }\r\n } else {\r\n // Check for missing API key or Message\r\n // Not for Markov Chain or Transformer Model\r\n if (esc_attr(get_option('chatbot_ai_platform_choice', 'OpenAI') == 'OpenAI') && !$api_key || !$message) {\r\n // DIAG - Diagnostics\r\n // back_trace( 'ERROR', 'Invalid API Key or Message.');\r\n wp_send_json_error('Error: Invalid API key or Message. Please check the plugin settings.');\r\n }\r\n if (esc_attr(get_option('chatbot_ai_platform_choice', 'OpenAI') == 'NVIDIA') && !$api_key || !$message) {\r\n // DIAG - Diagnostics\r\n // back_trace( 'ERROR', 'Invalid API Key or Message.');\r\n wp_send_json_error('Error: Invalid API key or Message. Please check the plugin settings.');\r\n }\r\n if (esc_attr(get_option('chatbot_ai_platform_choice', 'OpenAI') == 'Anthropic') && !$api_key || !$message) {\r\n // DIAG - Diagnostics\r\n // back_trace( 'ERROR', 'Invalid API Key or Message.');\r\n wp_send_json_error('Error: Invalid API key or Message. Please check the plugin settings.');\r\n }\r\n }\r\n\r\n // Removed in Ver 1.8.6 - 2024 02 15\r\n // $thread_id = '';\r\n // $assistant_id = '';\r\n // $user_id = '';\r\n // $page_id = '';\r\n \r\n // Check the transient for the Assistant ID - Ver 1.7.2\r\n // $user_id = intval($_POST['user_id']); // REMOVED intval in Ver 2.0.8\r\n // $page_id = intval($_POST['page_id']); // REMOVED intval in Ver 2.0.8\r\n $user_id = $_POST['user_id'];\r\n $page_id = $_POST['page_id'];\r\n $session_id = $_POST['session_id'];\r\n\r\n // DIAG - Diagnostics - Ver 1.8.6\r\n // back_trace( 'NOTICE', '$user_id: ' . $user_id);\r\n // back_trace( 'NOTICE', '$page_id: ' . $page_id);\r\n // back_trace( 'NOTICE', '$session_id: ' . $session_id);\r\n\r\n $kchat_settings['chatbot_chatgpt_display_style'] = get_chatbot_chatgpt_transients( 'display_style', $user_id, $page_id, $session_id);\r\n $kchat_settings['chatbot_chatgpt_assistant_alias'] = get_chatbot_chatgpt_transients( 'assistant_alias', $user_id, $page_id, $session_id);\r\n $kchat_settings['assistant_id'] = get_chatbot_chatgpt_transients( 'assistant_id', $user_id, $page_id, $session_id);\r\n $kchat_settings['thread_id'] = get_chatbot_chatgpt_transients( 'thread_id', $user_id, $page_id, $session_id);\r\n $kchat_settings['chatbot_chatgpt_model'] = get_chatbot_chatgpt_transients( 'model', $user_id, $page_id, $session_id);\r\n $kchat_settings['model'] = $kchat_settings['chatbot_chatgpt_model'];\r\n $kchat_settings['chatbot_chatgpt_voice_option'] = get_chatbot_chatgpt_transients( 'voice', $user_id, $page_id, $session_id);\r\n $kchat_settings['additional_instructions'] = get_chatbot_chatgpt_transients( 'additional_instructions', $user_id, $page_id, $session_id);\r\n $voice = $kchat_settings['chatbot_chatgpt_voice_option'];\r\n $model = $kchat_settings['chatbot_chatgpt_model'];\r\n\r\n // FIXME - TESTING - Ver 2.1.8\r\n // back_trace( 'NOTICE', 'LINE 607 - $model: ' . $model);\r\n \r\n $additional_instructions = $kchat_settings['additional_instructions'];\r\n $chatbot_chatgpt_assistant_alias = $kchat_settings['chatbot_chatgpt_assistant_alias'];\r\n\r\n // Get the thread information - Ver 2.0.7\r\n $thread_id = get_chatbot_chatgpt_threads($user_id, $session_id, $page_id, $assistant_id);\r\n $kchat_settings['thread_id'] = $thread_id;\r\n // $kchat_settings = array_merge($kchat_settings, get_chatbot_chatgpt_threads($user_id, $page_id));\r\n\r\n $assistant_id = isset($kchat_settings['assistant_id']) ? $kchat_settings['assistant_id'] : '';\r\n $thread_Id = isset($kchat_settings['thread_id']) ? $kchat_settings['thread_id'] : '';\r\n $model = isset($kchat_settings['chatbot_chatgpt_model']) ? $kchat_settings['chatbot_chatgpt_model'] : '';\r\n\r\n // FIXME - TESTING - Ver 2.1.8\r\n // back_trace( 'NOTICE', 'LINE 681 - $model: ' . $model);\r\n\r\n $voice = isset($kchat_settings['chatbot_chatgpt_voice_option']) ? $kchat_settings['chatbot_chatgpt_voice_option'] : '';\r\n\r\n // DIAG - Diagnostics - Ver 1.8.6\r\n // back_trace( 'NOTICE', '========================================');\r\n // back_trace( 'NOTICE', '$user_id: ' . $user_id);\r\n // back_trace( 'NOTICE', '$page_id: ' . $page_id);\r\n // back_trace( 'NOTICE', '$session_id: ' . $session_id);\r\n // back_trace( 'NOTICE', '$thread_id: ' . $thread_id);\r\n // back_trace( 'NOTICE', '$assistant_id: ' . $assistant_id);\r\n // back_trace( 'NOTICE', '$chatbot_chatgpt_assistant_alias: ' . $chatbot_chatgpt_assistant_alias);\r\n // back_trace( 'NOTICE', '3 - $model: ' . $model);\r\n // back_trace( 'NOTICE', '$voice: ' . $voice);\r\n // DIAG - Diagnostics - Ver 2.0.9\r\n // back_trace( 'NOTICE', '========================================');\r\n // foreach ($kchat_settings as $key => $value) {\r\n // // back_trace( 'NOTICE', '$kchat_settings[' . $key . ']: ' . $value);\r\n // }\r\n\r\n // Assistants\r\n // $chatbot_chatgpt_assistant_alias == 'original'; // Default\r\n // $chatbot_chatgpt_assistant_alias == 'primary';\r\n // $chatbot_chatgpt_assistant_alias == 'alternate';\r\n // $chatbot_chatgpt_assistant_alias == 'asst_xxxxxxxxxxxxxxxxxxxxxxxx'; // GPT Assistant Id\r\n \r\n // Which Assistant ID to use - Ver 1.7.2\r\n if ($chatbot_chatgpt_assistant_alias == 'original') {\r\n\r\n $use_assistant_id = 'No';\r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE' , 'Using Original ChatGPT - $chatbot_chatgpt_assistant_alias: ' . $chatbot_chatgpt_assistant_alias);\r\n\r\n } elseif ($chatbot_chatgpt_assistant_alias == 'primary') {\r\n\r\n $assistant_id = esc_attr(get_option('assistant_id'));\r\n // $additional_instructions = esc_attr(get_option('chatbot_chatgpt_assistant_instructions', '')); // REMOVED VER 2.0.9\r\n $use_assistant_id = 'Yes';\r\n\r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE' , 'Using Primary Assistant - $assistant_id: ' . $assistant_id);\r\n \r\n // Check if the GPT Assistant ID is blank, null, or \"Please provide the GPT Assistant ID.\"\r\n if (empty($assistant_id) || $assistant_id == \"Please provide the GPT Assistant Id.\") {\r\n \r\n // Primary assistant_id not set\r\n $chatbot_chatgpt_assistant_alias = 'original';\r\n $use_assistant_id = 'No';\r\n \r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE' ,'Falling back to ChatGPT API - $assistant_id: ' . $assistant_id );\r\n }\r\n\r\n } elseif ($chatbot_chatgpt_assistant_alias == 'alternate') {\r\n\r\n $assistant_id = esc_attr(get_option('chatbot_chatgpt_assistant_id_alternate'));\r\n // $additional_instructions = esc_attr(get_option('chatbot_chatgpt_assistant_instructions_alternate', '')); // REMOVED VER 2.0.9\r\n $use_assistant_id = 'Yes';\r\n\r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE' , 'Using Alternate Assistant - $assistant_id: ' . $assistant_id);\r\n\r\n // Check if the GPT Assistant ID is blank, null, or \"Please provide the GPT Assistant ID.\"\r\n if (empty($assistant_id) || $assistant_id == \"Please provide the GPT Assistant Id.\") {\r\n\r\n /// Alternate assistant_id not set\r\n $chatbot_chatgpt_assistant_alias = 'original';\r\n $use_assistant_id = 'No';\r\n\r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE' ,'Falling back to ChatGPT API - $assistant_id: ' . $assistant_id );\r\n \r\n }\r\n\r\n } elseif (str_starts_with($assistant_id, 'asst_')) {\r\n\r\n $chatbot_chatgpt_assistant_alias = $assistant_id; // Belt & Suspenders\r\n $use_assistant_id = 'Yes';\r\n\r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE' ,'Assistant ID pass as a parameter - $assistant_id: ' . $assistant_id );\r\n\r\n } else {\r\n\r\n // Reference GPT Assistant IDs directly - Ver 1.7.3\r\n if (str_starts_with($chatbot_chatgpt_assistant_alias, 'asst_')) {\r\n\r\n // DIAG - Diagnostics - 2.0.5\r\n // back_trace( 'NOTICE', 'Using GPT Assistant ID: ' . $chatbot_chatgpt_assistant_alias);\r\n\r\n // Override the $assistant_id with the GPT Assistant ID\r\n $assistant_id = $chatbot_chatgpt_assistant_alias;\r\n $use_assistant_id = 'Yes';\r\n\r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE' , 'Using $assistant_id ' . $assistant_id);\r\n\r\n } else {\r\n\r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE', 'Using ChatGPT API: ' . $chatbot_chatgpt_assistant_alias);\r\n\r\n // Override the $use_assistant_id and set it to 'No'\r\n $use_assistant_id = 'No';\r\n \r\n // DIAG - Diagnostics - Ver 1.8.1\r\n // back_trace( 'NOTICE' , 'Falling back to ChatGPT API');\r\n\r\n }\r\n\r\n }\r\n\r\n // Get any additional instructions - Ver 2.0.9\r\n $additional_instructions = get_chatbot_chatgpt_transients( 'additional_instructions', $user_id, $page_id, $session_id);\r\n\r\n // Decide whether to use Flow, Assistant or Original ChatGPT\r\n if ($model == 'flow'){\r\n \r\n // DIAG - Diagnostics - Ver 2.1.1.1\r\n // back_trace( 'NOTICE', 'Using ChatGPT Flow');\r\n // back_trace( 'NOTICE', '$user_id ' . $user_id);\r\n // back_trace( 'NOTICE', '$page_id ' . $page_id);\r\n\r\n // Reload the model - BELT & SUSPENDERS\r\n $kchat_settings['model'] = $model;\r\n\r\n // Get the step from the transient\r\n $kflow_step = get_chatbot_chatgpt_transients( 'kflow_step', null, null, $session_id);\r\n if (empty($kflow_step)) {\r\n $kflow_step = 0; // FIXME - Set to 1 or to zero?\r\n }\r\n\r\n // $thread_id\r\n $thread_id = '[answer=' . $kflow_step + 1 . ']';\r\n \r\n // Add +1 to $kchat_settings['next_step']\r\n $kflow_step = $kflow_step + 1;\r\n\r\n // Set the next step\r\n set_chatbot_chatgpt_transients( 'kflow_step', $kflow_step, null, null, $session_id);\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', '$message: ' . $message);\r\n $thread_id = get_chatbot_chatgpt_threads($user_id, $session_id, $page_id, $assistant_id);\r\n // back_trace( 'NOTICE', '$thread_id ' . $thread_id);\r\n append_message_to_conversation_log($session_id, $user_id, $page_id, 'Visitor', $thread_id, $assistant_id, $message);\r\n\r\n // BELT & SUSPENDERS\r\n $thread_id = '';\r\n\r\n // Send message to ChatGPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_call_flow_api($api_key, $message);\r\n\r\n wp_send_json_success($response);\r\n\r\n } elseif ($use_assistant_id == 'Yes') {\r\n\r\n // DIAG - Diagnostics - Ver 2.1.1.1\r\n // back_trace( 'NOTICE', 'Using GPT Assistant ID: ' . $use_assistant_id);\r\n // back_trace( 'NOTICE', '$user_id ' . $user_id);\r\n // back_trace( 'NOTICE', '$page_id ' . $page_id);\r\n // back_trace( 'NOTICE', '$message ' . $message);\r\n\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', '$message ' . $message);\r\n $thread_id = get_chatbot_chatgpt_threads($user_id, $session_id, $page_id, $assistant_id);\r\n // back_trace( 'NOTICE', '$thread_id ' . $thread_id);\r\n append_message_to_conversation_log($session_id, $user_id, $page_id, 'Visitor', $thread_id, $assistant_id, $message);\r\n\r\n // DIAG - Diagnostics - Ver 2.0.9\r\n // back_trace( 'NOTICE', '========================================');\r\n // back_trace( 'NOTICE', 'BEFORE CALL TO MODULE $additional_instructions: ' . $additional_instructions);\r\n\r\n // Send message to Custom GPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_custom_gpt_call_api($api_key, $message, $assistant_id, $thread_id, $session_id, $user_id, $page_id);\r\n\r\n // Use TF-IDF to enhance response\r\n $chatbot_chatgpt_suppress_learnings = esc_attr(get_option('chatbot_chatgpt_suppress_learnings', 'Random'));\r\n if ( $chatbot_chatgpt_suppress_learnings != 'None') {\r\n $response = $response . '

' . chatbot_chatgpt_enhance_with_tfidf($message);\r\n }\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', '$response ' . print_r($response,true));\r\n $thread_id = get_chatbot_chatgpt_threads($user_id, $session_id, $page_id, $assistant_id);\r\n // back_trace( 'NOTICE', '$thread_id ' . $thread_id);\r\n append_message_to_conversation_log($session_id, $user_id, $page_id, 'Chatbot', $thread_id, $assistant_id, $response);\r\n\r\n // Clean (erase) the output buffer - Ver 1.6.8\r\n // Check if output buffering is active before attempting to clean it\r\n if (ob_get_level() > 0) {\r\n ob_clean();\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Output buffer cleaned');\r\n } else {\r\n // Optionally start output buffering if needed for your application\r\n // ob_start();\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Output buffer not cleaned');\r\n }\r\n\r\n if (str_starts_with($response, 'Error:') || str_starts_with($response, 'Failed:')) {\r\n // Return response\r\n // back_trace( 'NOTICE', '$response ' . print_r($response,true));\r\n wp_send_json_error('Oops! Something went wrong on our end. Please try again later!');\r\n } else {\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Check for links and images in response before returning');\r\n $response = chatbot_chatgpt_check_for_links_and_images($response);\r\n\r\n // FIXME - Append extra message - Ver 2.1.1.1.1\r\n // Danger Will Robinson! Danger!\r\n $extra_message = esc_attr(get_option('chatbot_chatgpt_extra_message', ''));\r\n $response = chatbot_chatgpt_append_extra_message($response, $extra_message);\r\n\r\n // Return response\r\n wp_send_json_success($response);\r\n }\r\n\r\n } else {\r\n\r\n // DIAG - Diagnostics - Ver 2.1.1.1\r\n // back_trace( 'NOTICE', 'Using ChatGPT');\r\n // back_trace( 'NOTICE', '$user_id ' . $user_id);\r\n // back_trace( 'NOTICE', '$page_id ' . $page_id);\r\n // back_trace( 'NOTICE', '$message ' . $message);\r\n\r\n // Belt & Suspenders - Ver 2.1.5.1\r\n if (!isset($kchat_settings['model'])) {\r\n $kchat_settings['model'] = $model;\r\n };\r\n\r\n // FIXME - TESTING - Ver 2.1.8\r\n // back_trace( 'NOTICE', 'LINE 856 - $model: ' . $model);\r\n // back_trace( 'NOTICE', 'LINE 857 - $kchat_settings[model]: ' . $kchat_settings['model']);\r\n\r\n // if (str_starts_with($model,'dall')) {\r\n // // back_trace ( 'NOTICE', 'Using Image API');\r\n // } else {\r\n // // back_trace ( 'NOTICE', 'Using ChatGPT API');\r\n // }\r\n\r\n $thread_id = get_chatbot_chatgpt_threads($user_id, $session_id, $page_id, $assistant_id);\r\n // back_trace( 'NOTICE', '$thread_id ' . $thread_id);\r\n append_message_to_conversation_log($session_id, $user_id, $page_id, 'Visitor', $thread_id, $assistant_id, $message);\r\n \r\n // If $model starts with 'gpt' then the chatbot_chatgpt_call_api or 'dall' then chatbot_chatgpt_call_image_api\r\n // TRY NOT TO FETCH MODEL AGAIN\r\n // $model = esc_attr(get_option('chatbot_chatgpt_model_choice', 'gpt-3.5-turbo'));\r\n $model = isset($kchat_settings['model']) ? $kchat_settings['model'] : null;\r\n $voice = isset($kchat_settings['voice']) ? $kchat_settings['voice'] : null;\r\n\r\n // FIXME - TESTING - Ver 2.1.8\r\n // back_trace( 'NOTICE', 'LINE 876 - $model: ' . $model);\r\n\r\n if (str_starts_with($model !== null && $model, 'gpt-4o') !== false) {\r\n // The string 'gpt-4o' is found in $model\r\n // Reload the model - BELT & SUSPENDERS\r\n $kchat_settings['model'] = $model;\r\n // DIAG - Diagnostics - Ver 2.1.8\r\n // back_trace( 'NOTICE', 'Calling ChatGPT Omni API');\r\n // Send message to ChatGPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_call_omni($api_key, $message);\r\n } elseif ($model !== null && str_starts_with($model, 'gpt')) {\r\n // Reload the model - BELT & SUSPENDERS\r\n $kchat_settings['model'] = $model;\r\n // DIAG - Diagnostics - Ver 2.1.8\r\n // back_trace( 'NOTICE', 'Calling ChatGPT API');\r\n // Send message to ChatGPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_call_api($api_key, $message);\r\n } elseif ($model !== null && str_starts_with($model, 'dall')) {\r\n // Reload the model - BELT & SUSPENDERS\r\n $kchat_settings['model'] = $model;\r\n // DIAG - Diagnostics - Ver 2.1.8\r\n // back_trace( 'NOTICE', 'Calling Dall E Image API');\r\n // Send message to Image API - Ver 1.9.4\r\n $response = chatbot_chatgpt_call_image_api($api_key, $message);\r\n } elseif ($model !== null && str_starts_with($model, 'tts')) {\r\n // Reload the model - BELT & SUSPENDERS\r\n $kchat_settings['model'] = $model;\r\n $kchat_settings['voice'] = $voice;\r\n // DIAG - Diagnostics - Ver 2.1.8\r\n // back_trace( 'NOTICE', 'Calling TTS API');\r\n // Send message to TTS API - Text-to-speech - Ver 1.9.5\r\n $response = chatbot_chatgpt_call_tts_api($api_key, $message, $voice, $user_id, $page_id, $session_id);\r\n } elseif ($model !== null && str_starts_with($model,'whisper')) {\r\n $kchat_settings['model'] = $model;\r\n // DIAG - Diagnostics - Ver 2.1.8\r\n // back_trace( 'NOTICE', 'Calling STT API');\r\n // Send message to STT API - Speech-to-text - Ver 1.9.6\r\n $response = chatbot_chatgpt_call_stt_api($api_key, $message);\r\n } elseif ($model !==null && str_starts_with($model,'nvidia')) {\r\n $kchat_settings['model'] = $model;\r\n // DIAG - Diagnostics - Ver 2.1.8\r\n // back_trace( 'NOTICE', 'Calling NVIDIA API');\r\n // Send message to NVIDIA API - Ver 2.1.8\r\n $response = chatbot_nvidia_call_api($api_key, $message);\r\n // back_trace( 'NOTICE', 'LINE 910 - NVIDIA API Response: ' . $response);\r\n } elseif ($model !== null && str_starts_with($model,'markov')) {\r\n $kchat_settings['model'] = $model;\r\n // DIAG - Diagnostics - Ver 2.1.8\r\n // back_trace( 'NOTICE', 'Calling Markov Chain API');\r\n // Send message to Markov API - Ver 1.9.7\r\n $response = chatbot_chatgpt_call_markov_chain_api($message);\r\n } elseif ($model !== null && str_contains($model,'context-model')) {\r\n $kchat_settings['model'] = $model;\r\n // DIAG - Diagnostics - Ver 2.2.0\r\n // back_trace( 'NOTICE', 'Calling Transformer Model API');\r\n // Send message to Transformer Model API - Ver 2.2.0\r\n $response = chatbot_chatgpt_call_transformer_model_api($message);\r\n } else {\r\n // Reload the model - BELT & SUSPENDERS\r\n $kchat_settings['model'] = $model;\r\n // Send message to ChatGPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_call_api($api_key, $message);\r\n }\r\n \r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', ['message' => 'BEFORE CALL TO ENHANCE TFIDF', 'response' => $response]);\r\n \r\n // Use TF-IDF to enhance response\r\n $chatbot_chatgpt_suppress_learnings = esc_attr(get_option('chatbot_chatgpt_suppress_learnings', 'Random'));\r\n if ( $chatbot_chatgpt_suppress_learnings != 'None') {\r\n $response = $response . '

' . chatbot_chatgpt_enhance_with_tfidf($message);\r\n }\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', ['message' => 'AFTER CALL TO ENHANCE TFIDF', 'response' => $response]);\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', '$response ' . print_r($response,true));\r\n $thread_id = get_chatbot_chatgpt_threads($user_id, $session_id, $page_id, $assistant_id);\r\n // back_trace( 'NOTICE', '$thread_id ' . $thread_id);\r\n append_message_to_conversation_log($session_id, $user_id, $page_id, 'Chatbot', $thread_id, $assistant_id, $response);\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Check for links and images in response before returning');\r\n $response = chatbot_chatgpt_check_for_links_and_images($response);\r\n\r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE', 'LINE 944 - Response: ' . $response);\r\n\r\n // FIXME - Append extra message - Ver 2.1.1.1.1\r\n // Danger Will Robinson! Danger!\r\n $extra_message = esc_attr(get_option('chatbot_chatgpt_extra_message', ''));\r\n $response = chatbot_chatgpt_append_extra_message($response, $extra_message);\r\n\r\n // DIAG - Diagnostics - Ver 2.1.8\r\n // back_trace( 'NOTICE', 'LINE 952 - $response: ' . $response);\r\n\r\n // Return response\r\n wp_send_json_success($response);\r\n\r\n }\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'ERROR', 'Oops! I fell through the cracks!');\r\n wp_send_json_error('Oops! I fell through the cracks!');\r\n\r\n}\r\n\r\n// Add action to send messages - Ver 1.0.0\r\nadd_action('wp_ajax_chatbot_chatgpt_send_message', 'chatbot_chatgpt_send_message');\r\nadd_action('wp_ajax_nopriv_chatbot_chatgpt_send_message', 'chatbot_chatgpt_send_message');\r\n\r\n// Add action to upload files - Ver 1.7.6\r\nadd_action('wp_ajax_chatbot_chatgpt_upload_files', 'chatbot_chatgpt_upload_files');\r\nadd_action('wp_ajax_nopriv_chatbot_chatgpt_upload_files', 'chatbot_chatgpt_upload_files');\r\n\r\n// Add action to upload files - Ver 1.7.6\r\nadd_action('wp_ajax_chatbot_chatgpt_upload_mp3', 'chatbot_chatgpt_upload_mp3');\r\nadd_action('wp_ajax_nopriv_chatbot_chatgpt_upload_mp3', 'chatbot_chatgpt_upload_mp3');\r\n\r\n// Add action to erase conversation - Ver 1.8.6\r\nadd_action('wp_ajax_chatbot_chatgpt_erase_conversation', 'chatbot_chatgpt_erase_conversation_handler');\r\nadd_action('wp_ajax_nopriv_chatbot_chatgpt_erase_conversation', 'chatbot_chatgpt_erase_conversation_handler'); // For logged-out users, if needed\r\n\r\n// Settings and Deactivation - Ver 1.5.0\r\nadd_filter('plugin_action_links_' . plugin_basename(__FILE__), 'chatbot_chatgpt_plugin_action_links');\r\n\r\n// Append an extra message to the response - Ver 2.0.9\r\nfunction chatbot_chatgpt_append_extra_message($response, $extra_message) {\r\n\r\n // Append the extra message to the response\r\n $response = $response . ' ' . $extra_message;\r\n return $response;\r\n\r\n}\r\n\r\n// Crawler aka Knowledge Navigator - Ver 1.6.1\r\nfunction chatbot_chatgpt_kn_status_activation() {\r\n\r\n add_option('chatbot_chatgpt_kn_status', 'Never Run');\r\n // clear any old scheduled runs\r\n\r\n if (wp_next_scheduled('crawl_scheduled_event_hook')) {\r\n wp_clear_scheduled_hook('crawl_scheduled_event_hook');\r\n }\r\n\r\n // clear the 'knowledge_navigator_scan_hook' hook on plugin activation - Ver 1.6.3\r\n if (wp_next_scheduled('knowledge_navigator_scan_hook')) {\r\n // BREAK/FIX - Do not unset the hook - Ver 1.8.5\r\n // wp_clear_scheduled_hook('knowledge_navigator_scan_hook'); // Clear scheduled runs\r\n }\r\n\r\n}\r\nregister_activation_hook(__FILE__, 'chatbot_chatgpt_kn_status_activation');\r\n\r\n// Clean Up in Aisle 4\r\nfunction chatbot_chatgpt_kn_status_deactivation() {\r\n\r\n delete_option('chatbot_chatgpt_kn_status');\r\n wp_clear_scheduled_hook('knowledge_navigator_scan_hook'); \r\n\r\n}\r\nregister_deactivation_hook(__FILE__, 'chatbot_chatgpt_kn_status_deactivation');\r\n\r\n// Markov Chain builder - Activation Hook - Ver 2.1.6\r\nfunction chatbot_markov_chain_status_activation() {\r\n\r\n // DIAG - Diagnostics - Ver 2.1.6\r\n // back_trace( 'NOTICE', 'Markov Chain Status Activation');\r\n\r\n // Add the option for build status with a default value of 'Never Run'\r\n add_option('chatbot_markov_chain_build_status', 'Never Run');\r\n\r\n // Clear any old scheduled runs, if present\r\n if (wp_next_scheduled('chatbot_markov_chain_scan_hook')) {\r\n // BREAK/FIX - Do not unset the hook - Ver 2.1.6\r\n // wp_clear_scheduled_hook('chatbot_markov_chain_scan_hook'); // Clear scheduled runs\r\n }\r\n\r\n}\r\nregister_activation_hook(__FILE__, 'chatbot_markov_chain_status_activation');\r\n\r\n// Clean up scheduled events and options - Deactivation Hook\r\nfunction chatbot_markov_chain_status_deactivation() {\r\n\r\n // DIAG - Diagnostics - Ver 2.1.6\r\n // back_trace( 'NOTICE', 'Markov Chain Status Deactivation');\r\n\r\n // Delete the build status option on deactivation\r\n delete_option('chatbot_markov_chain_build_status');\r\n\r\n // Clear any scheduled events related to the Markov Chain scan\r\n wp_clear_scheduled_hook('chatbot_markov_chain_scan_hook');\r\n\r\n}\r\nregister_deactivation_hook(__FILE__, 'chatbot_markov_chain_status_deactivation');\r\n\r\n// Transformer Model builder - Activation Hook - Ver 2.2.0\r\nfunction chatbot_transformer_model_status_activation() {\r\n\r\n // DIAG - Diagnostics - Ver 2.2.0\r\n // back_trace( 'NOTICE', 'Transformer Model Status Activation');\r\n\r\n // Add the option for build status with a default value of 'Never Run'\r\n add_option('chatbot_transformer_model_build_status', 'Never Run');\r\n\r\n // Clear any old scheduled runs, if present\r\n if (wp_next_scheduled('chatbot_transformer_model_scan_hook')) {\r\n // BREAK/FIX - Do not unset the hook - Ver 2.2.0\r\n // wp_clear_scheduled_hook('chatbot_transformer_model_scan_hook'); // Clear scheduled runs\r\n }\r\n\r\n}\r\nregister_activation_hook(__FILE__, 'chatbot_transformer_model_status_activation');\r\n\r\n// Clean up scheduled events and options - Deactivation Hook\r\nfunction chatbot_transformer_model_status_deactivation() {\r\n\r\n // DIAG - Diagnostics - Ver 2.2.0\r\n // back_trace( 'NOTICE', 'Transformer Model Status Deactivation');\r\n\r\n // Delete the build status option on deactivation\r\n delete_option('chatbot_transformer_model_build_status');\r\n\r\n // Clear any scheduled events related to the Transformer Model scan\r\n wp_clear_scheduled_hook('chatbot_transformer_model_scan_hook');\r\n\r\n}\r\nregister_deactivation_hook(__FILE__, 'chatbot_transformer_model_status_deactivation');\r\n\r\n// Function to add a new message and response, keeping only the last five - Ver 1.6.1\r\nfunction addEntry($transient_name, $newEntry) {\r\n\r\n $context_history = get_transient($transient_name);\r\n if (!$context_history) {\r\n $context_history = [];\r\n }\r\n\r\n // Determine the total length of all existing entries\r\n $totalLength = 0;\r\n foreach ($context_history as $entry) {\r\n if (is_string($entry)) {\r\n $totalLength += strlen($entry);\r\n } elseif (is_array($entry)) {\r\n $totalLength += strlen(json_encode($entry)); // Convert to string if an array\r\n }\r\n }\r\n\r\n // IDEA - How will the new threading option from OpenAI change how this works?\r\n // Define thresholds for the number of entries to keep\r\n $maxEntries = 30; // Default maximum number of entries\r\n if ($totalLength > 5000) { // Higher threshold\r\n $maxEntries = 20;\r\n }\r\n if ($totalLength > 10000) { // Lower threshold\r\n $maxEntries = 10;\r\n }\r\n\r\n while (count($context_history) >= $maxEntries) {\r\n array_shift($context_history); // Remove the oldest element\r\n }\r\n\r\n if (is_array($newEntry)) {\r\n $newEntry = json_encode($newEntry); // Convert the array to a string\r\n }\r\n\r\n array_push($context_history, $newEntry); // Append the new element\r\n set_transient($transient_name, $context_history); // Update the transient\r\n}\r\n\r\n// Function to return message and response - Ver 1.6.1\r\nfunction concatenateHistory($transient_name) {\r\n $context_history = get_transient($transient_name);\r\n if (!$context_history) {\r\n return ''; // Return an empty string if the transient does not exist\r\n }\r\n return implode(' ', $context_history); // Concatenate the array values into a single string\r\n}\r\n\r\n// FIXME - MOVE CORE FUNCTIONS TO A SEPARATE FILE, LEAVING ONLY THE HOOKS HERE\r\n// Initialize the Greetings - Ver 1.6.1\r\nfunction enqueue_greetings_script( $initial_greeting = null, $subsequent_greeting = null) {\r\n\r\n // If user is logged in, then modify greeting if greeting contains \"[...]\" or remove if not logged in - Ver 1.9.4\r\n if (is_user_logged_in()) {\r\n\r\n $current_user_id = get_current_user_id();\r\n $current_user = get_userdata($current_user_id);\r\n\r\n //Do this for Initial Greeting\r\n if ( empty($initial_greeting) ) {\r\n $initial_greeting = esc_attr(get_option('chatbot_chatgpt_initial_greeting', 'Hello! How can I help you today?'));\r\n }\r\n\r\n // Determine what the field name is between the brackets\r\n $user_field_name = '';\r\n $user_field_name = substr($initial_greeting, strpos($initial_greeting, '[') + 1, strpos($initial_greeting, ']') - strpos($initial_greeting, '[') - 1);\r\n // If $initial_greeting contains \"[$user_field_name]\" then replace with field from DB\r\n if (strpos($initial_greeting, '[' . $user_field_name . ']') !== false) {\r\n $initial_greeting = str_replace('[' . $user_field_name . ']', $current_user->$user_field_name, $initial_greeting);\r\n } else {\r\n $initial_greeting = str_replace('[' . $user_field_name . ']', '', $initial_greeting);\r\n // Remove the extra space when two spaces are present\r\n $initial_greeting = str_replace(' ', ' ', $initial_greeting);\r\n // Remove the extra space before punctuation including period, comma, exclamation mark, and question mark\r\n $initial_greeting = preg_replace('/\\s*([.,!?])/', '$1', $initial_greeting);\r\n }\r\n\r\n // Do this for Subsequent Greeting\r\n if ( empty($subsequent_greeting) ) {\r\n $subsequent_greeting = esc_attr(get_option('chatbot_chatgpt_subsequent_greeting', 'Hello again! How can I help you?'));\r\n }\r\n\r\n // Determine what the field name is between the brackets\r\n $user_field_name = '';\r\n $user_field_name = substr($subsequent_greeting, strpos($subsequent_greeting, '[') + 1, strpos($subsequent_greeting, ']') - strpos($subsequent_greeting, '[') - 1);\r\n // If $subsequent_greeting contains \"[$user_field_name]\" then replace with field from DB\r\n if (strpos($subsequent_greeting, '[' . $user_field_name . ']') !== false) {\r\n $subsequent_greeting = str_replace('[' . $user_field_name . ']', $current_user->$user_field_name, $subsequent_greeting);\r\n } else {\r\n $subsequent_greeting = str_replace('[' . $user_field_name . ']', '', $subsequent_greeting);\r\n // Remove the extra space when two spaces are present\r\n $subsequent_greeting = str_replace(' ', ' ', $subsequent_greeting);\r\n // Remove the extra space before punctuation including period, comma, exclamation mark, and question mark\r\n $subsequent_greeting = preg_replace('/\\s*([.,!?])/', '$1', $subsequent_greeting);\r\n }\r\n\r\n } else {\r\n\r\n //Do this for Initial Greeting\r\n if ( empty($initial_greeting) ) {\r\n $initial_greeting = esc_attr(get_option('chatbot_chatgpt_initial_greeting', 'Hello! How can I help you today?'));\r\n }\r\n\r\n $user_field_name = '';\r\n $user_field_name = substr($initial_greeting, strpos($initial_greeting, '[') + 1, strpos($initial_greeting, ']') - strpos($initial_greeting, '[') - 1 );\r\n\r\n // $initial_greeting = preg_replace('/\\s*\\[' . preg_quote($user_field_name, '/') . '\\]\\s*/', '', $initial_greeting);\r\n $initial_greeting = str_replace('[' . $user_field_name . ']', '', $initial_greeting);\r\n // Remove the extra space when two spaces are present\r\n $initial_greeting = str_replace(' ', ' ', $initial_greeting);\r\n // Remove the extra space before punctuation including period, comma, exclamation mark, and question mark\r\n $initial_greeting = preg_replace('/\\s*([.,!?])/', '$1', $initial_greeting);\r\n\r\n //Do this for Subsequent Greeting\r\n if ( empty($subsequent_greeting) ) {\r\n $subsequent_greeting = esc_attr(get_option('chatbot_chatgpt_subsequent_greeting', 'Hello again! How can I help you?'));\r\n }\r\n\r\n $user_field_name = '';\r\n $user_field_name = substr($subsequent_greeting, strpos($subsequent_greeting, '[') + 1, strpos($subsequent_greeting, ']') - strpos($subsequent_greeting, '[') - 1);\r\n\r\n // $subsequent_greeting = preg_replace('/\\s*\\[' . preg_quote($user_field_name, '/') . '\\]\\s*/', '', $subsequent_greeting);\r\n $subsequent_greeting = str_replace('[' . $user_field_name . ']', '', $subsequent_greeting);\r\n // Remove the extra space when two spaces are present\r\n $subsequent_greeting = str_replace(' ', ' ', $subsequent_greeting);\r\n // Remove the extra space before punctuation including period, comma, exclamation mark, and question mark\r\n $subsequent_greeting = preg_replace('/\\s*([.,!?])/', '$1', $subsequent_greeting);\r\n \r\n }\r\n\r\n $greetings = array(\r\n 'initial_greeting' => $initial_greeting,\r\n 'subsequent_greeting' => $subsequent_greeting,\r\n );\r\n\r\n return $greetings;\r\n\r\n}\r\n// \r\nadd_action('wp_enqueue_scripts', 'enqueue_greetings_script');\r\n\r\n// Add the color picker to the adaptive appearance settings section - Ver 1.8.1\r\nfunction enqueue_color_picker($hook_suffix) {\r\n\r\n global $chatbot_chatgpt_plugin_version;\r\n\r\n // first check that $hook_suffix is appropriate for your admin page\r\n wp_enqueue_style('wp-color-picker');\r\n wp_enqueue_script('my-script-handle', plugin_dir_url(__FILE__) . 'assets/js/chatbot-chatgpt-color-picker.js', array('wp-color-picker'), $chatbot_chatgpt_plugin_version, true);\r\n\r\n}\r\nadd_action('admin_enqueue_scripts', 'enqueue_color_picker');\r\n\r\n// Determine if the plugin is installed\r\nfunction kchat_get_plugin_version() {\r\n\r\n global $chatbot_chatgpt_plugin_version;\r\n\r\n if (!function_exists('get_plugin_data')) {\r\n require_once(ABSPATH . 'wp-admin/includes/plugin.php');\r\n }\r\n\r\n $plugin_data = get_plugin_data(plugin_dir_path(__FILE__) . 'chatbot-chatgpt.php');\r\n // DIAG - Print the plugin data\r\n // back_trace( 'NOTICE', 'Plugin data: ' . print_r($plugin_data, true));\r\n // $plugin_version = $plugin_data['chatbot_chatgpt_version'];\r\n $plugin_version = $plugin_data['Version'];\r\n // $plugin_version = $chatbot_chatgpt_plugin_version;\r\n update_option('chatbot_chatgpt_plugin_version', $plugin_version);\r\n // DIAG - Log the plugin version\r\n // back_trace( 'NOTICE', 'Plugin version ' . $plugin_version);\r\n\r\n return $plugin_version;\r\n\r\n}\r\n"}, "59557d101e594948af227c78eb676c94ea226503": {"t": 1785756408.1723387, "n": 62725, "h": "6b2648b0a9f97c2a", "c": " $user_id,\r\n 'page_id' => $page_id,\r\n 'session_id' => $session_id,\r\n 'thread_id' => $thread_id,\r\n 'assistant_id' => $assistant_id,\r\n 'additional_instructions' => $additional_instructions,\r\n 'model' => $model,\r\n 'voice' => $voice,\r\n ));\r\n\r\n // DIAG - Diagnostics - Ver 1.8.6\r\n // back_trace( 'NOTICE', '$user_id: ' . $user_id);\r\n // back_trace( 'NOTICE', '$page_id: ' . $page_id);\r\n // back_trace( 'NOTICE', '$session_id: ' . $session_id);\r\n // back_trace( 'NOTICE', '$thread_id: ' . $thread_id);\r\n // back_trace( 'NOTICE', '$assistant_id: ' . $assistant_id);\r\n // back_trace( 'NOTICE', '$additional_instructions: ' . $additional_instructions);\r\n // back_trace( 'NOTICE', '$model: ' . $model);\r\n \r\n // Set visitor and logged in user limits - Ver 2.0.1\r\n if (is_user_logged_in()) {\r\n // back_trace( 'NOTICE', 'User is logged in');\r\n $kchat_settings['chatbot_chatgpt_message_limit_setting'] = esc_attr(get_option('chatbot_chatgpt_user_message_limit_setting', '999'));\r\n $kchat_settings['chatbot_chatgpt_message_limit_period_setting'] = esc_attr(get_option('chatbot_chatgpt_user_message_limit_period_setting', 'Lifetime'));\r\n } else {\r\n // back_trace( 'NOTICE', 'User is NOT logged in');\r\n $kchat_settings['chatbot_chatgpt_message_limit_setting'] = esc_attr(get_option('chatbot_chatgpt_visitor_message_limit_setting', '999'));\r\n $kchat_settings['chatbot_chatgpt_message_limit_period_setting'] = esc_attr(get_option('chatbot_chatgpt_visitor_message_limit_period_setting', 'Lifetime'));\r\n }\r\n\r\n // Localize the data for the chatbot - Ver 2.1.1.1\r\n $kchat_settings = array_merge($kchat_settings, array(\r\n 'chatbot_chatgpt_display_style' => $chatbot_chatgpt_display_style,\r\n 'chatbot_chatgpt_version' => $chatbot_chatgpt_plugin_version,\r\n 'plugins_url' => $chatbot_chatgpt_plugin_dir_url,\r\n 'ajax_url' => admin_url('admin-ajax.php'),\r\n 'user_id' => $user_id,\r\n 'page_id' => $page_id,\r\n 'session_id' => $session_id,\r\n 'thread_id' => $thread_id,\r\n 'assistant_id' => $assistant_id,\r\n 'additional_instructions' => $additional_instructions,\r\n 'model' => $model,\r\n 'voice' => $voice,\r\n 'chatbot_chatgpt_timeout_setting' => esc_attr(get_option('chatbot_chatgpt_timeout_setting', '240')),\r\n 'chatbot_chatgpt_avatar_icon_setting' => esc_attr(get_option('chatbot_chatgpt_avatar_icon_setting', '')),\r\n 'chatbot_chatgpt_custom_avatar_icon_setting' => esc_attr(get_option('chatbot_chatgpt_custom_avatar_icon_setting', '')),\r\n '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?')),\r\n 'chatbot_chatgpt_force_page_reload' => esc_attr(get_option('chatbot_chatgpt_force_page_reload', 'No')),\r\n 'chatbot_chatgpt_custom_error_message' => esc_attr(get_option('chatbot_chatgpt_custom_error_message', 'Your custom error message goes here.')),\r\n ));\r\n \r\n $kchat_settings_json = wp_json_encode($kchat_settings);\r\n\r\n // Enqueue the main chatbot script - CHANGED TO LOAD ORDER IN V2.1.2\r\n wp_enqueue_script('chatbot-chatgpt-js', plugins_url('assets/js/chatbot-chatgpt.js', __FILE__), array(), $chatbot_chatgpt_plugin_version, true);\r\n\r\n // Add the inline script to define kchat_settings before the main script runs - CHANGED THE LOAD ORDER IN VER 2.1.2\r\n 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');\r\n // FIXME - REMOVED IN V2.1.2\r\n // 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');\r\n\r\n}\r\nadd_action('wp_enqueue_scripts', 'chatbot_chatgpt_enqueue_scripts');\r\n\r\n// Enqueue MathJax with custom configuration - Ver 2.1.2\r\n// https://docs.mathjax.org/en/latest/\r\n// https://github.com/mathjax/MathJax/blob/master/LICENSE\r\n// https://cdnjs.cloudflare.com/ajax/libs/mathjax/3.2.0/es5/tex-mml-chtml.js\r\n// https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js\r\nfunction enqueue_mathjax_with_custom_config() {\r\n\r\n global $chatbot_chatgpt_plugin_version;\r\n global $chatbot_chatgpt_plugin_dir_url;\r\n\r\n // Add the MathJax configuration script\r\n $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 \";\r\n\r\n // Enqueue the MathJax script\r\n // wp_enqueue_script( 'mathjax', plugin_dir_url(__FILE__) . 'assets/js/tex-chtml.js', array(), $chatbot_chatgpt_plugin_version, true );\r\n wp_enqueue_script( 'mathjax', $chatbot_chatgpt_plugin_dir_url . 'assets/js/tex-mml-chtml.js', array(), $chatbot_chatgpt_plugin_version, true );\r\n\r\n // Add the inline script before MathJax script\r\n wp_add_inline_script( 'mathjax', $mathjax_config, 'before' );\r\n\r\n}\r\nadd_action( 'wp_enqueue_scripts', 'enqueue_mathjax_with_custom_config' );\r\n\r\n// CORS - Cross Origin Resource Sharing - CAUTION: This allows all domains to access the end point - Ver 2.1.2\r\n// function allow_cross_domain_requests() {\r\n// header(\"Access-Control-Allow-Origin: *\");\r\n// header(\"Access-Control-Allow-Methods: GET, POST, OPTIONS\");\r\n// header(\"Access-Control-Allow-Headers: X-Requested-With\");\r\n// }\r\n// add_action('init', 'allow_cross_domain_requests');\r\n\r\n// Settings and Deactivation Links - Ver - 1.5.0\r\nif (!function_exists('enqueue_jquery_ui')) {\r\n function enqueue_jquery_ui() {\r\n wp_enqueue_style('wp-jquery-ui-dialog');\r\n wp_enqueue_script('jquery-ui-dialog');\r\n }\r\n add_action( 'admin_enqueue_scripts', 'enqueue_jquery_ui' );\r\n}\r\n\r\n// Schedule Cleanup of Expired Transients\r\nif (!wp_next_scheduled('chatbot_chatgpt_cleanup_event')) {\r\n wp_schedule_event(time(), 'daily', 'chatbot_chatgpt_cleanup_event');\r\n}\r\nadd_action('chatbot_chatgpt_cleanup_event', 'clean_specific_expired_transients');\r\n\r\n// Schedule Conversation Log Cleanup - Ver 1.6.7\r\nif (!wp_next_scheduled('chatbot_chatgpt_conversation_log_cleanup_event')) {\r\n wp_schedule_event(time(), 'daily', 'chatbot_chatgpt_conversation_log_cleanup_event');\r\n}\r\nadd_action('chatbot_chatgpt_conversation_log_cleanup_event', 'chatbot_chatgpt_conversation_log_cleanup');\r\n\r\n// Schedule the transcript file cleanup event if it's not already scheduled - Ver 1.9.9\r\n// Schedule the cleanup event if it's not already scheduled\r\nif (!wp_next_scheduled('chatbot_chatgpt_cleanup_transcript_files')) {\r\n wp_schedule_event(time(), 'hourly', 'chatbot_chatgpt_cleanup_transcript_files');\r\n}\r\n\r\n// Deactivate old hooks - Ver 2.0.1\r\nif(esc_attr(get_option('chatbot_chatgpt_cleanup_old_hooks') !== 'Completed')) {\r\n // Deactivate old hooks - Ver 2.0.1\r\n wp_clear_scheduled_hook('chatbot_chatgpt_cleanup_transcripts');\r\n // Then update the option\r\n update_option('chatbot_chatgpt_cleanup_old_hooks', 'Completed');\r\n}\r\n\r\n// Schedule the audio file cleanup event if it's not already scheduled - Ver 1.9.9\r\n// Schedule the cleanup event if it's not already scheduled\r\nif (!wp_next_scheduled('chatbot_chatgpt_cleanup_audio_files')) {\r\n wp_schedule_event(time(), 'hourly', 'chatbot_chatgpt_cleanup_audio_files');\r\n}\r\n\r\n// Schedule the upload file cleanup event if it's not already scheduled - Ver 1.9.9\r\n// Schedule the cleanup event if it's not already scheduled\r\nif (!wp_next_scheduled('chatbot_chatgpt_cleanup_upload_files')) {\r\n wp_schedule_event(time(), 'hourly', 'chatbot_chatgpt_cleanup_upload_files');\r\n}\r\n\r\n// Schedule the download file cleanup event if it's not already scheduled - Ver 2.0.3\r\n// Schedule the cleanup event if it's not already scheduled\r\nif (!wp_next_scheduled('chatbot_chatgpt_cleanup_download_files')) {\r\n wp_schedule_event(time(), 'hourly', 'chatbot_chatgpt_cleanup_download_files');\r\n}\r\n\r\n// Add the Assistant table to the database - Ver 2.0.4\r\ncreate_chatbot_chatgpt_assistants_table();\r\n\r\n// Handle Ajax requests\r\nfunction chatbot_chatgpt_send_message() {\r\n\r\n // Global variables\r\n global $session_id;\r\n global $user_id;\r\n global $page_id;\r\n global $thread_id;\r\n global $assistant_id;\r\n global $chatbot_chatgpt_assistant_alias;\r\n global $kchat_settings;\r\n global $additional_instructions;\r\n global $model;\r\n global $voice;\r\n\r\n global $flow_data;\r\n\r\n $api_key = '';\r\n\r\n // Retrieve the API key\r\n if (esc_attr(get_option('chatbot_nvidia_api_enabled')) == 'Yes') {\r\n $api_key = esc_attr(get_option('chatbot_nvidia_api_key'));\r\n $model = esc_attr(get_option('chatbot_nvidia_model_choice', 'nvidia/llama-3.1-nemotron-51b-instruct'));\r\n $kchat_settings['chatbot_chatgpt_model'] = $model;\r\n $kchat_settings['model'] = $model;\r\n // DIAG - Diagnostics - Ver 2.1.8\r\n // back_trace( 'NOTICE', 'LINE 537 - $model: ' . $model);\r\n } else if (esc_attr(get_option('chatbot_markov_chain_api_enabled')) == 'Yes') {\r\n $api_key = esc_attr(get_option('chatbot_markov_chain_api_key'));\r\n $model = esc_attr(get_option('chatbot_markov_chain_model_choice', 'markov-chain-2024-09-17'));\r\n $kchat_settings['chatbot_chatgpt_model'] = $model;\r\n $kchat_settings['model'] = $model;\r\n // DIAG - Diagnostics - Ver 2.1.8\r\n // back_trace( 'NOTICE', 'LINE 544 - $model: ' . $model);\r\n } else {\r\n $api_key = esc_attr(get_option('chatbot_chatgpt_api_key'));\r\n $model = esc_attr(get_option('chatbot_chatgpt_model_choice', 'gpt-3.5-turbo'));\r\n $kchat_settings['chatbot_chatgpt_model'] = $model;\r\n $kchat_settings['model'] = $model;\r\n // DIAG - Diagnostics - Ver 2.1.8\r\n // back_trace( 'NOTICE', 'LINE 551 - $model: ' . $model);\r\n }\r\n\r\n // DIAG - Diagnostics - Ver 2.1.8\r\n // back_trace( 'NOTICE', 'LINE 555 - $model: ' . $model);\r\n\r\n // Send only clean text via the API\r\n $message = sanitize_text_field($_POST['message']);\r\n\r\n // If Markov Chain is enabled, then process the message\r\n if (esc_attr(get_option('chatbot_markov_chain_api_enabled', 'No')) == 'Yes') {\r\n // Check for missing Message\r\n if (!$message) {\r\n // DIAG - Diagnostics\r\n // back_trace( 'ERROR', 'Invalid API Key or Message.');\r\n wp_send_json_error('Error: Invalid API key or Message. Please check the plugin settings.');\r\n }\r\n } else {\r\n // Check for missing API key or Message\r\n if (!$api_key || !$message) {\r\n // DIAG - Diagnostics\r\n // back_trace( 'ERROR', 'Invalid API Key or Message.');\r\n wp_send_json_error('Error: Invalid API key or Message. Please check the plugin settings.');\r\n }\r\n }\r\n\r\n // Removed in Ver 1.8.6 - 2024 02 15\r\n // $thread_id = '';\r\n // $assistant_id = '';\r\n // $user_id = '';\r\n // $page_id = '';\r\n \r\n // Check the transient for the Assistant ID - Ver 1.7.2\r\n // $user_id = intval($_POST['user_id']); // REMOVED intval in Ver 2.0.8\r\n // $page_id = intval($_POST['page_id']); // REMOVED intval in Ver 2.0.8\r\n $user_id = $_POST['user_id'];\r\n $page_id = $_POST['page_id'];\r\n $session_id = $_POST['session_id'];\r\n\r\n // DIAG - Diagnostics - Ver 1.8.6\r\n // back_trace( 'NOTICE', '$user_id: ' . $user_id);\r\n // back_trace( 'NOTICE', '$page_id: ' . $page_id);\r\n // back_trace( 'NOTICE', '$session_id: ' . $session_id);\r\n\r\n $kchat_settings['chatbot_chatgpt_display_style'] = get_chatbot_chatgpt_transients( 'display_style', $user_id, $page_id, $session_id);\r\n $kchat_settings['chatbot_chatgpt_assistant_alias'] = get_chatbot_chatgpt_transients( 'assistant_alias', $user_id, $page_id, $session_id);\r\n $kchat_settings['assistant_id'] = get_chatbot_chatgpt_transients( 'assistant_id', $user_id, $page_id, $session_id);\r\n $kchat_settings['thread_id'] = get_chatbot_chatgpt_transients( 'thread_id', $user_id, $page_id, $session_id);\r\n $kchat_settings['chatbot_chatgpt_model'] = get_chatbot_chatgpt_transients( 'model', $user_id, $page_id, $session_id);\r\n $kchat_settings['model'] = $kchat_settings['chatbot_chatgpt_model'];\r\n $kchat_settings['chatbot_chatgpt_voice_option'] = get_chatbot_chatgpt_transients( 'voice', $user_id, $page_id, $session_id);\r\n $kchat_settings['additional_instructions'] = get_chatbot_chatgpt_transients( 'additional_instructions', $user_id, $page_id, $session_id);\r\n $voice = $kchat_settings['chatbot_chatgpt_voice_option'];\r\n $model = $kchat_settings['chatbot_chatgpt_model'];\r\n\r\n // FIXME - TESTING - Ver 2.1.8\r\n // back_trace( 'NOTICE', 'LINE 607 - $model: ' . $model);\r\n \r\n $additional_instructions = $kchat_settings['additional_instructions'];\r\n $chatbot_chatgpt_assistant_alias = $kchat_settings['chatbot_chatgpt_assistant_alias'];\r\n\r\n // Get the thread information - Ver 2.0.7\r\n $thread_id = get_chatbot_chatgpt_threads($user_id, $session_id, $page_id, $assistant_id);\r\n $kchat_settings['thread_id'] = $thread_id;\r\n // $kchat_settings = array_merge($kchat_settings, get_chatbot_chatgpt_threads($user_id, $page_id));\r\n\r\n $assistant_id = isset($kchat_settings['assistant_id']) ? $kchat_settings['assistant_id'] : '';\r\n $thread_Id = isset($kchat_settings['thread_id']) ? $kchat_settings['thread_id'] : '';\r\n $model = isset($kchat_settings['chatbot_chatgpt_model']) ? $kchat_settings['chatbot_chatgpt_model'] : '';\r\n\r\n // FIXME - TESTING - Ver 2.1.8\r\n // back_trace( 'NOTICE', 'LINE 622 - $model: ' . $model);\r\n\r\n $voice = isset($kchat_settings['chatbot_chatgpt_voice_option']) ? $kchat_settings['chatbot_chatgpt_voice_option'] : '';\r\n\r\n // DIAG - Diagnostics - Ver 1.8.6\r\n // back_trace( 'NOTICE', '========================================');\r\n // back_trace( 'NOTICE', '$user_id: ' . $user_id);\r\n // back_trace( 'NOTICE', '$page_id: ' . $page_id);\r\n // back_trace( 'NOTICE', '$session_id: ' . $session_id);\r\n // back_trace( 'NOTICE', '$thread_id: ' . $thread_id);\r\n // back_trace( 'NOTICE', '$assistant_id: ' . $assistant_id);\r\n // back_trace( 'NOTICE', '$chatbot_chatgpt_assistant_alias: ' . $chatbot_chatgpt_assistant_alias);\r\n // back_trace( 'NOTICE', '3 - $model: ' . $model);\r\n // back_trace( 'NOTICE', '$voice: ' . $voice);\r\n // DIAG - Diagnostics - Ver 2.0.9\r\n // back_trace( 'NOTICE', '========================================');\r\n // foreach ($kchat_settings as $key => $value) {\r\n // back_trace( 'NOTICE', '$kchat_settings[' . $key . ']: ' . $value);\r\n // }\r\n\r\n // Assistants\r\n // $chatbot_chatgpt_assistant_alias == 'original'; // Default\r\n // $chatbot_chatgpt_assistant_alias == 'primary';\r\n // $chatbot_chatgpt_assistant_alias == 'alternate';\r\n // $chatbot_chatgpt_assistant_alias == 'asst_xxxxxxxxxxxxxxxxxxxxxxxx'; // GPT Assistant Id\r\n \r\n // Which Assistant ID to use - Ver 1.7.2\r\n if ($chatbot_chatgpt_assistant_alias == 'original') {\r\n\r\n $use_assistant_id = 'No';\r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE' , 'Using Original ChatGPT - $chatbot_chatgpt_assistant_alias: ' . $chatbot_chatgpt_assistant_alias);\r\n\r\n } elseif ($chatbot_chatgpt_assistant_alias == 'primary') {\r\n\r\n $assistant_id = esc_attr(get_option('assistant_id'));\r\n // $additional_instructions = esc_attr(get_option('chatbot_chatgpt_assistant_instructions', '')); // REMOVED VER 2.0.9\r\n $use_assistant_id = 'Yes';\r\n\r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE' , 'Using Primary Assistant - $assistant_id: ' . $assistant_id);\r\n \r\n // Check if the GPT Assistant ID is blank, null, or \"Please provide the GPT Assistant ID.\"\r\n if (empty($assistant_id) || $assistant_id == \"Please provide the GPT Assistant Id.\") {\r\n \r\n // Primary assistant_id not set\r\n $chatbot_chatgpt_assistant_alias = 'original';\r\n $use_assistant_id = 'No';\r\n \r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE' ,'Falling back to ChatGPT API - $assistant_id: ' . $assistant_id );\r\n }\r\n\r\n } elseif ($chatbot_chatgpt_assistant_alias == 'alternate') {\r\n\r\n $assistant_id = esc_attr(get_option('chatbot_chatgpt_assistant_id_alternate'));\r\n // $additional_instructions = esc_attr(get_option('chatbot_chatgpt_assistant_instructions_alternate', '')); // REMOVED VER 2.0.9\r\n $use_assistant_id = 'Yes';\r\n\r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE' , 'Using Alternate Assistant - $assistant_id: ' . $assistant_id);\r\n\r\n // Check if the GPT Assistant ID is blank, null, or \"Please provide the GPT Assistant ID.\"\r\n if (empty($assistant_id) || $assistant_id == \"Please provide the GPT Assistant Id.\") {\r\n\r\n /// Alternate assistant_id not set\r\n $chatbot_chatgpt_assistant_alias = 'original';\r\n $use_assistant_id = 'No';\r\n\r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE' ,'Falling back to ChatGPT API - $assistant_id: ' . $assistant_id );\r\n \r\n }\r\n\r\n } elseif (str_starts_with($assistant_id, 'asst_')) {\r\n\r\n $chatbot_chatgpt_assistant_alias = $assistant_id; // Belt & Suspenders\r\n $use_assistant_id = 'Yes';\r\n\r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE' ,'Assistant ID pass as a parameter - $assistant_id: ' . $assistant_id );\r\n\r\n } else {\r\n\r\n // Reference GPT Assistant IDs directly - Ver 1.7.3\r\n if (str_starts_with($chatbot_chatgpt_assistant_alias, 'asst_')) {\r\n\r\n // DIAG - Diagnostics - 2.0.5\r\n // back_trace( 'NOTICE', 'Using GPT Assistant ID: ' . $chatbot_chatgpt_assistant_alias);\r\n\r\n // Override the $assistant_id with the GPT Assistant ID\r\n $assistant_id = $chatbot_chatgpt_assistant_alias;\r\n $use_assistant_id = 'Yes';\r\n\r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE' , 'Using $assistant_id ' . $assistant_id);\r\n\r\n } else {\r\n\r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE', 'Using ChatGPT API: ' . $chatbot_chatgpt_assistant_alias);\r\n\r\n // Override the $use_assistant_id and set it to 'No'\r\n $use_assistant_id = 'No';\r\n \r\n // DIAG - Diagnostics - Ver 1.8.1\r\n // back_trace( 'NOTICE' , 'Falling back to ChatGPT API');\r\n\r\n }\r\n\r\n }\r\n\r\n // Get any additional instructions - Ver 2.0.9\r\n $additional_instructions = get_chatbot_chatgpt_transients( 'additional_instructions', $user_id, $page_id, $session_id);\r\n\r\n // Decide whether to use Flow, Assistant or Original ChatGPT\r\n if ($model == 'flow'){\r\n \r\n // DIAG - Diagnostics - Ver 2.1.1.1\r\n // back_trace( 'NOTICE', 'Using ChatGPT Flow');\r\n // back_trace( 'NOTICE', '$user_id ' . $user_id);\r\n // back_trace( 'NOTICE', '$page_id ' . $page_id);\r\n\r\n // Reload the model - BELT & SUSPENDERS\r\n $kchat_settings['model'] = $model;\r\n\r\n // Get the step from the transient\r\n $kflow_step = get_chatbot_chatgpt_transients( 'kflow_step', null, null, $session_id);\r\n if (empty($kflow_step)) {\r\n $kflow_step = 0; // FIXME - Set to 1 or to zero?\r\n }\r\n\r\n // $thread_id\r\n $thread_id = '[answer=' . $kflow_step + 1 . ']';\r\n \r\n // Add +1 to $kchat_settings['next_step']\r\n $kflow_step = $kflow_step + 1;\r\n\r\n // Set the next step\r\n set_chatbot_chatgpt_transients( 'kflow_step', $kflow_step, null, null, $session_id);\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', '$message: ' . $message);\r\n $thread_id = get_chatbot_chatgpt_threads($user_id, $session_id, $page_id, $assistant_id);\r\n // back_trace( 'NOTICE', '$thread_id ' . $thread_id);\r\n append_message_to_conversation_log($session_id, $user_id, $page_id, 'Visitor', $thread_id, $assistant_id, $message);\r\n\r\n // BELT & SUSPENDERS\r\n $thread_id = '';\r\n\r\n // Send message to ChatGPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_call_flow_api($api_key, $message);\r\n\r\n wp_send_json_success($response);\r\n\r\n } elseif ($use_assistant_id == 'Yes') {\r\n\r\n // DIAG - Diagnostics - Ver 2.1.1.1\r\n // back_trace( 'NOTICE', 'Using GPT Assistant ID: ' . $use_assistant_id);\r\n // back_trace( 'NOTICE', '$user_id ' . $user_id);\r\n // back_trace( 'NOTICE', '$page_id ' . $page_id);\r\n // back_trace( 'NOTICE', '$message ' . $message);\r\n\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', '$message ' . $message);\r\n $thread_id = get_chatbot_chatgpt_threads($user_id, $session_id, $page_id, $assistant_id);\r\n // back_trace( 'NOTICE', '$thread_id ' . $thread_id);\r\n append_message_to_conversation_log($session_id, $user_id, $page_id, 'Visitor', $thread_id, $assistant_id, $message);\r\n\r\n // DIAG - Diagnostics - Ver 2.0.9\r\n // back_trace( 'NOTICE', '========================================');\r\n // back_trace( 'NOTICE', 'BEFORE CALL TO MODULE $additional_instructions: ' . $additional_instructions);\r\n\r\n // Send message to Custom GPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_custom_gpt_call_api($api_key, $message, $assistant_id, $thread_id, $session_id, $user_id, $page_id);\r\n\r\n // Use TF-IDF to enhance response\r\n $chatbot_chatgpt_suppress_learnings = esc_attr(get_option('chatbot_chatgpt_suppress_learnings', 'Random'));\r\n if ( $chatbot_chatgpt_suppress_learnings != 'None') {\r\n $response = $response . '

' . chatbot_chatgpt_enhance_with_tfidf($message);\r\n }\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', '$response ' . print_r($response,true));\r\n $thread_id = get_chatbot_chatgpt_threads($user_id, $session_id, $page_id, $assistant_id);\r\n // back_trace( 'NOTICE', '$thread_id ' . $thread_id);\r\n append_message_to_conversation_log($session_id, $user_id, $page_id, 'Chatbot', $thread_id, $assistant_id, $response);\r\n\r\n // Clean (erase) the output buffer - Ver 1.6.8\r\n // Check if output buffering is active before attempting to clean it\r\n if (ob_get_level() > 0) {\r\n ob_clean();\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Output buffer cleaned');\r\n } else {\r\n // Optionally start output buffering if needed for your application\r\n // ob_start();\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Output buffer not cleaned');\r\n }\r\n\r\n if (str_starts_with($response, 'Error:') || str_starts_with($response, 'Failed:')) {\r\n // Return response\r\n // back_trace( 'NOTICE', '$response ' . print_r($response,true));\r\n wp_send_json_error('Oops! Something went wrong on our end. Please try again later!');\r\n } else {\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Check for links and images in response before returning');\r\n $response = chatbot_chatgpt_check_for_links_and_images($response);\r\n\r\n // FIXME - Append extra message - Ver 2.1.1.1.1\r\n // Danger Will Robinson! Danger!\r\n $extra_message = esc_attr(get_option('chatbot_chatgpt_extra_message', ''));\r\n $response = chatbot_chatgpt_append_extra_message($response, $extra_message);\r\n\r\n // Return response\r\n wp_send_json_success($response);\r\n }\r\n\r\n } else {\r\n\r\n // DIAG - Diagnostics - Ver 2.1.1.1\r\n // back_trace( 'NOTICE', 'Using ChatGPT');\r\n // back_trace( 'NOTICE', '$user_id ' . $user_id);\r\n // back_trace( 'NOTICE', '$page_id ' . $page_id);\r\n // back_trace( 'NOTICE', '$message ' . $message);\r\n\r\n // Belt & Suspenders - Ver 2.1.5.1\r\n if (!isset($kchat_settings['model'])) {\r\n $kchat_settings['model'] = $model;\r\n };\r\n\r\n // FIXME - TESTING - Ver 2.1.8\r\n // back_trace( 'NOTICE', 'LINE 856 - $model: ' . $model);\r\n // back_trace( 'NOTICE', 'LINE 857 - $kchat_settings[model]: ' . $kchat_settings['model']);\r\n\r\n // if (str_starts_with($model,'dall')) {\r\n // // back_trace ( 'NOTICE', 'Using Image API');\r\n // } else {\r\n // // back_trace ( 'NOTICE', 'Using ChatGPT API');\r\n // }\r\n\r\n $thread_id = get_chatbot_chatgpt_threads($user_id, $session_id, $page_id, $assistant_id);\r\n // back_trace( 'NOTICE', '$thread_id ' . $thread_id);\r\n append_message_to_conversation_log($session_id, $user_id, $page_id, 'Visitor', $thread_id, $assistant_id, $message);\r\n \r\n // If $model starts with 'gpt' then the chatbot_chatgpt_call_api or 'dall' then chatbot_chatgpt_call_image_api\r\n // TRY NOT TO FETCH MODEL AGAIN\r\n // $model = esc_attr(get_option('chatbot_chatgpt_model_choice', 'gpt-3.5-turbo'));\r\n $model = isset($kchat_settings['model']) ? $kchat_settings['model'] : null;\r\n $voice = isset($kchat_settings['voice']) ? $kchat_settings['voice'] : null;\r\n\r\n // FIXME - TESTING - Ver 2.1.8\r\n // back_trace( 'NOTICE', 'LINE 876 - $model: ' . $model);\r\n\r\n if (str_starts_with($model !== null && $model, 'gpt-4o') !== false) {\r\n // The string 'gpt-4o' is found in $model\r\n // Reload the model - BELT & SUSPENDERS\r\n $kchat_settings['model'] = $model;\r\n // DIAG - Diagnostics - Ver 2.1.8\r\n // back_trace( 'NOTICE', 'Calling ChatGPT Omni API');\r\n // Send message to ChatGPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_call_omni($api_key, $message);\r\n } elseif ($model !== null && str_starts_with($model, 'gpt')) {\r\n // Reload the model - BELT & SUSPENDERS\r\n $kchat_settings['model'] = $model;\r\n // DIAG - Diagnostics - Ver 2.1.8\r\n // back_trace( 'NOTICE', 'Calling ChatGPT API');\r\n // Send message to ChatGPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_call_api($api_key, $message);\r\n } elseif ($model !== null && str_starts_with($model, 'dall')) {\r\n // Reload the model - BELT & SUSPENDERS\r\n $kchat_settings['model'] = $model;\r\n // DIAG - Diagnostics - Ver 2.1.8\r\n // back_trace( 'NOTICE', 'Calling Dall E Image API');\r\n // Send message to Image API - Ver 1.9.4\r\n $response = chatbot_chatgpt_call_image_api($api_key, $message);\r\n } elseif ($model !== null && str_starts_with($model, 'tts')) {\r\n // Reload the model - BELT & SUSPENDERS\r\n $kchat_settings['model'] = $model;\r\n $kchat_settings['voice'] = $voice;\r\n // DIAG - Diagnostics - Ver 2.1.8\r\n // back_trace( 'NOTICE', 'Calling TTS API');\r\n // Send message to TTS API - Text-to-speech - Ver 1.9.5\r\n $response = chatbot_chatgpt_call_tts_api($api_key, $message, $voice, $user_id, $page_id, $session_id);\r\n } elseif ($model !== null && str_starts_with($model,'whisper')) {\r\n $kchat_settings['model'] = $model;\r\n // DIAG - Diagnostics - Ver 2.1.8\r\n // back_trace( 'NOTICE', 'Calling STT API');\r\n // Send message to STT API - Speech-to-text - Ver 1.9.6\r\n $response = chatbot_chatgpt_call_stt_api($api_key, $message);\r\n } elseif ($model !==null && str_starts_with($model,'nvidia')) {\r\n $kchat_settings['model'] = $model;\r\n // DIAG - Diagnostics - Ver 2.1.8\r\n // back_trace( 'NOTICE', 'Calling NVIDIA API');\r\n // Send message to NVIDIA API - Ver 2.1.8\r\n $response = chatbot_nvidia_call_api($api_key, $message);\r\n // back_trace( 'NOTICE', 'LINE 910 - NVIDIA API Response: ' . $response);\r\n } elseif ($model !== null && str_starts_with($model,'markov')) {\r\n $kchat_settings['model'] = $model;\r\n // DIAG - Diagnostics - Ver 2.1.8\r\n // back_trace( 'NOTICE', 'Calling Markov Chain API');\r\n // Send message to Markov API - Ver 1.9.7\r\n $response = chatbot_chatgpt_call_markov_chain_api($message); \r\n } else {\r\n // Reload the model - BELT & SUSPENDERS\r\n $kchat_settings['model'] = $model;\r\n // Send message to ChatGPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_call_api($api_key, $message);\r\n }\r\n \r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', ['message' => 'BEFORE CALL TO ENHANCE TFIDF', 'response' => $response]);\r\n \r\n // Use TF-IDF to enhance response\r\n $chatbot_chatgpt_suppress_learnings = esc_attr(get_option('chatbot_chatgpt_suppress_learnings', 'Random'));\r\n if ( $chatbot_chatgpt_suppress_learnings != 'None') {\r\n $response = $response . '

' . chatbot_chatgpt_enhance_with_tfidf($message);\r\n }\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', ['message' => 'AFTER CALL TO ENHANCE TFIDF', 'response' => $response]);\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', '$response ' . print_r($response,true));\r\n $thread_id = get_chatbot_chatgpt_threads($user_id, $session_id, $page_id, $assistant_id);\r\n // back_trace( 'NOTICE', '$thread_id ' . $thread_id);\r\n append_message_to_conversation_log($session_id, $user_id, $page_id, 'Chatbot', $thread_id, $assistant_id, $response);\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Check for links and images in response before returning');\r\n $response = chatbot_chatgpt_check_for_links_and_images($response);\r\n\r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE', 'LINE 944 - Response: ' . $response);\r\n\r\n // FIXME - Append extra message - Ver 2.1.1.1.1\r\n // Danger Will Robinson! Danger!\r\n $extra_message = esc_attr(get_option('chatbot_chatgpt_extra_message', ''));\r\n $response = chatbot_chatgpt_append_extra_message($response, $extra_message);\r\n\r\n // DIAG - Diagnostics - Ver 2.1.8\r\n // back_trace( 'NOTICE', 'LINE 952 - $response: ' . $response);\r\n\r\n // Return response\r\n wp_send_json_success($response);\r\n\r\n }\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'ERROR', 'Oops! I fell through the cracks!');\r\n wp_send_json_error('Oops! I fell through the cracks!');\r\n\r\n}\r\n\r\n// Add action to send messages - Ver 1.0.0\r\nadd_action('wp_ajax_chatbot_chatgpt_send_message', 'chatbot_chatgpt_send_message');\r\nadd_action('wp_ajax_nopriv_chatbot_chatgpt_send_message', 'chatbot_chatgpt_send_message');\r\n\r\n// Add action to upload files - Ver 1.7.6\r\nadd_action('wp_ajax_chatbot_chatgpt_upload_files', 'chatbot_chatgpt_upload_files');\r\nadd_action('wp_ajax_nopriv_chatbot_chatgpt_upload_files', 'chatbot_chatgpt_upload_files');\r\n\r\n// Add action to upload files - Ver 1.7.6\r\nadd_action('wp_ajax_chatbot_chatgpt_upload_mp3', 'chatbot_chatgpt_upload_mp3');\r\nadd_action('wp_ajax_nopriv_chatbot_chatgpt_upload_mp3', 'chatbot_chatgpt_upload_mp3');\r\n\r\n// Add action to erase conversation - Ver 1.8.6\r\nadd_action('wp_ajax_chatbot_chatgpt_erase_conversation', 'chatbot_chatgpt_erase_conversation_handler');\r\nadd_action('wp_ajax_nopriv_chatbot_chatgpt_erase_conversation', 'chatbot_chatgpt_erase_conversation_handler'); // For logged-out users, if needed\r\n\r\n// Settings and Deactivation - Ver 1.5.0\r\nadd_filter('plugin_action_links_' . plugin_basename(__FILE__), 'chatbot_chatgpt_plugin_action_links');\r\n\r\n// Append an extra message to the response - Ver 2.0.9\r\nfunction chatbot_chatgpt_append_extra_message($response, $extra_message) {\r\n\r\n // Append the extra message to the response\r\n $response = $response . ' ' . $extra_message;\r\n return $response;\r\n\r\n}\r\n\r\n// Crawler aka Knowledge Navigator - Ver 1.6.1\r\nfunction chatbot_chatgpt_kn_status_activation() {\r\n\r\n add_option('chatbot_chatgpt_kn_status', 'Never Run');\r\n // clear any old scheduled runs\r\n\r\n if (wp_next_scheduled('crawl_scheduled_event_hook')) {\r\n wp_clear_scheduled_hook('crawl_scheduled_event_hook');\r\n }\r\n\r\n // clear the 'knowledge_navigator_scan_hook' hook on plugin activation - Ver 1.6.3\r\n if (wp_next_scheduled('knowledge_navigator_scan_hook')) {\r\n // BREAK/FIX - Do not unset the hook - Ver 1.8.5\r\n // wp_clear_scheduled_hook('knowledge_navigator_scan_hook'); // Clear scheduled runs\r\n }\r\n\r\n}\r\nregister_activation_hook(__FILE__, 'chatbot_chatgpt_kn_status_activation');\r\n\r\n// Clean Up in Aisle 4\r\nfunction chatbot_chatgpt_kn_status_deactivation() {\r\n\r\n delete_option('chatbot_chatgpt_kn_status');\r\n wp_clear_scheduled_hook('knowledge_navigator_scan_hook'); \r\n\r\n}\r\nregister_deactivation_hook(__FILE__, 'chatbot_chatgpt_kn_status_deactivation');\r\n\r\n// Markov Chain builder - Activation Hook - Ver 2.1.6\r\nfunction chatbot_markov_chain_status_activation() {\r\n\r\n // DIAG - Diagnostics - Ver 2.1.6\r\n // back_trace( 'NOTICE', 'Markov Chain Status Activation');\r\n\r\n // Add the option for build status with a default value of 'Never Run'\r\n add_option('chatbot_markov_chain_build_status', 'Never Run');\r\n\r\n // Clear any old scheduled runs, if present\r\n if (wp_next_scheduled('chatbot_markov_chain_scan_hook')) {\r\n // BREAK/FIX - Do not unset the hook - Ver 2.1.6\r\n // wp_clear_scheduled_hook('chatbot_markov_chain_scan_hook'); // Clear scheduled runs\r\n }\r\n\r\n}\r\nregister_activation_hook(__FILE__, 'chatbot_markov_chain_status_activation');\r\n\r\n// Clean up scheduled events and options - Deactivation Hook\r\nfunction chatbot_markov_chain_status_deactivation() {\r\n\r\n // DIAG - Diagnostics - Ver 2.1.6\r\n // back_trace( 'NOTICE', 'Markov Chain Status Deactivation');\r\n\r\n // Delete the build status option on deactivation\r\n delete_option('chatbot_markov_chain_build_status');\r\n\r\n // Clear any scheduled events related to the Markov Chain scan\r\n wp_clear_scheduled_hook('chatbot_markov_chain_scan_hook');\r\n\r\n}\r\nregister_deactivation_hook(__FILE__, 'chatbot_markov_chain_status_deactivation');\r\n\r\n// Function to add a new message and response, keeping only the last five - Ver 1.6.1\r\nfunction addEntry($transient_name, $newEntry) {\r\n\r\n $context_history = get_transient($transient_name);\r\n if (!$context_history) {\r\n $context_history = [];\r\n }\r\n\r\n // Determine the total length of all existing entries\r\n $totalLength = 0;\r\n foreach ($context_history as $entry) {\r\n if (is_string($entry)) {\r\n $totalLength += strlen($entry);\r\n } elseif (is_array($entry)) {\r\n $totalLength += strlen(json_encode($entry)); // Convert to string if an array\r\n }\r\n }\r\n\r\n // IDEA - How will the new threading option from OpenAI change how this works?\r\n // Define thresholds for the number of entries to keep\r\n $maxEntries = 30; // Default maximum number of entries\r\n if ($totalLength > 5000) { // Higher threshold\r\n $maxEntries = 20;\r\n }\r\n if ($totalLength > 10000) { // Lower threshold\r\n $maxEntries = 10;\r\n }\r\n\r\n while (count($context_history) >= $maxEntries) {\r\n array_shift($context_history); // Remove the oldest element\r\n }\r\n\r\n if (is_array($newEntry)) {\r\n $newEntry = json_encode($newEntry); // Convert the array to a string\r\n }\r\n\r\n array_push($context_history, $newEntry); // Append the new element\r\n set_transient($transient_name, $context_history); // Update the transient\r\n}\r\n\r\n// Function to return message and response - Ver 1.6.1\r\nfunction concatenateHistory($transient_name) {\r\n $context_history = get_transient($transient_name);\r\n if (!$context_history) {\r\n return ''; // Return an empty string if the transient does not exist\r\n }\r\n return implode(' ', $context_history); // Concatenate the array values into a single string\r\n}\r\n\r\n// FIXME - MOVE CORE FUNCTIONS TO A SEPARATE FILE, LEAVING ONLY THE HOOKS HERE\r\n// Initialize the Greetings - Ver 1.6.1\r\nfunction enqueue_greetings_script( $initial_greeting = null, $subsequent_greeting = null) {\r\n\r\n // If user is logged in, then modify greeting if greeting contains \"[...]\" or remove if not logged in - Ver 1.9.4\r\n if (is_user_logged_in()) {\r\n\r\n $current_user_id = get_current_user_id();\r\n $current_user = get_userdata($current_user_id);\r\n\r\n //Do this for Initial Greeting\r\n if ( empty($initial_greeting) ) {\r\n $initial_greeting = esc_attr(get_option('chatbot_chatgpt_initial_greeting', 'Hello! How can I help you today?'));\r\n }\r\n\r\n // Determine what the field name is between the brackets\r\n $user_field_name = '';\r\n $user_field_name = substr($initial_greeting, strpos($initial_greeting, '[') + 1, strpos($initial_greeting, ']') - strpos($initial_greeting, '[') - 1);\r\n // If $initial_greeting contains \"[$user_field_name]\" then replace with field from DB\r\n if (strpos($initial_greeting, '[' . $user_field_name . ']') !== false) {\r\n $initial_greeting = str_replace('[' . $user_field_name . ']', $current_user->$user_field_name, $initial_greeting);\r\n } else {\r\n $initial_greeting = str_replace('[' . $user_field_name . ']', '', $initial_greeting);\r\n // Remove the extra space when two spaces are present\r\n $initial_greeting = str_replace(' ', ' ', $initial_greeting);\r\n // Remove the extra space before punctuation including period, comma, exclamation mark, and question mark\r\n $initial_greeting = preg_replace('/\\s*([.,!?])/', '$1', $initial_greeting);\r\n }\r\n\r\n // Do this for Subsequent Greeting\r\n if ( empty($subsequent_greeting) ) {\r\n $subsequent_greeting = esc_attr(get_option('chatbot_chatgpt_subsequent_greeting', 'Hello again! How can I help you?'));\r\n }\r\n\r\n // Determine what the field name is between the brackets\r\n $user_field_name = '';\r\n $user_field_name = substr($subsequent_greeting, strpos($subsequent_greeting, '[') + 1, strpos($subsequent_greeting, ']') - strpos($subsequent_greeting, '[') - 1);\r\n // If $subsequent_greeting contains \"[$user_field_name]\" then replace with field from DB\r\n if (strpos($subsequent_greeting, '[' . $user_field_name . ']') !== false) {\r\n $subsequent_greeting = str_replace('[' . $user_field_name . ']', $current_user->$user_field_name, $subsequent_greeting);\r\n } else {\r\n $subsequent_greeting = str_replace('[' . $user_field_name . ']', '', $subsequent_greeting);\r\n // Remove the extra space when two spaces are present\r\n $subsequent_greeting = str_replace(' ', ' ', $subsequent_greeting);\r\n // Remove the extra space before punctuation including period, comma, exclamation mark, and question mark\r\n $subsequent_greeting = preg_replace('/\\s*([.,!?])/', '$1', $subsequent_greeting);\r\n }\r\n\r\n } else {\r\n\r\n //Do this for Initial Greeting\r\n if ( empty($initial_greeting) ) {\r\n $initial_greeting = esc_attr(get_option('chatbot_chatgpt_initial_greeting', 'Hello! How can I help you today?'));\r\n }\r\n\r\n $user_field_name = '';\r\n $user_field_name = substr($initial_greeting, strpos($initial_greeting, '[') + 1, strpos($initial_greeting, ']') - strpos($initial_greeting, '[') - 1 );\r\n\r\n // $initial_greeting = preg_replace('/\\s*\\[' . preg_quote($user_field_name, '/') . '\\]\\s*/', '', $initial_greeting);\r\n $initial_greeting = str_replace('[' . $user_field_name . ']', '', $initial_greeting);\r\n // Remove the extra space when two spaces are present\r\n $initial_greeting = str_replace(' ', ' ', $initial_greeting);\r\n // Remove the extra space before punctuation including period, comma, exclamation mark, and question mark\r\n $initial_greeting = preg_replace('/\\s*([.,!?])/', '$1', $initial_greeting);\r\n\r\n //Do this for Subsequent Greeting\r\n if ( empty($subsequent_greeting) ) {\r\n $subsequent_greeting = esc_attr(get_option('chatbot_chatgpt_subsequent_greeting', 'Hello again! How can I help you?'));\r\n }\r\n\r\n $user_field_name = '';\r\n $user_field_name = substr($subsequent_greeting, strpos($subsequent_greeting, '[') + 1, strpos($subsequent_greeting, ']') - strpos($subsequent_greeting, '[') - 1);\r\n\r\n // $subsequent_greeting = preg_replace('/\\s*\\[' . preg_quote($user_field_name, '/') . '\\]\\s*/', '', $subsequent_greeting);\r\n $subsequent_greeting = str_replace('[' . $user_field_name . ']', '', $subsequent_greeting);\r\n // Remove the extra space when two spaces are present\r\n $subsequent_greeting = str_replace(' ', ' ', $subsequent_greeting);\r\n // Remove the extra space before punctuation including period, comma, exclamation mark, and question mark\r\n $subsequent_greeting = preg_replace('/\\s*([.,!?])/', '$1', $subsequent_greeting);\r\n \r\n }\r\n\r\n $greetings = array(\r\n 'initial_greeting' => $initial_greeting,\r\n 'subsequent_greeting' => $subsequent_greeting,\r\n );\r\n\r\n return $greetings;\r\n\r\n}\r\n// \r\nadd_action('wp_enqueue_scripts', 'enqueue_greetings_script');\r\n\r\n// Add the color picker to the adaptive appearance settings section - Ver 1.8.1\r\nfunction enqueue_color_picker($hook_suffix) {\r\n\r\n global $chatbot_chatgpt_plugin_version;\r\n\r\n // first check that $hook_suffix is appropriate for your admin page\r\n wp_enqueue_style('wp-color-picker');\r\n wp_enqueue_script('my-script-handle', plugin_dir_url(__FILE__) . 'assets/js/chatbot-chatgpt-color-picker.js', array('wp-color-picker'), $chatbot_chatgpt_plugin_version, true);\r\n\r\n}\r\nadd_action('admin_enqueue_scripts', 'enqueue_color_picker');\r\n\r\n// Determine if the plugin is installed\r\nfunction kchat_get_plugin_version() {\r\n\r\n global $chatbot_chatgpt_plugin_version;\r\n\r\n if (!function_exists('get_plugin_data')) {\r\n require_once(ABSPATH . 'wp-admin/includes/plugin.php');\r\n }\r\n\r\n $plugin_data = get_plugin_data(plugin_dir_path(__FILE__) . 'chatbot-chatgpt.php');\r\n // DIAG - Print the plugin data\r\n // back_trace( 'NOTICE', 'Plugin data: ' . print_r($plugin_data, true));\r\n // $plugin_version = $plugin_data['chatbot_chatgpt_version'];\r\n $plugin_version = $plugin_data['Version'];\r\n // $plugin_version = $chatbot_chatgpt_plugin_version;\r\n update_option('chatbot_chatgpt_plugin_version', $plugin_version);\r\n // DIAG - Log the plugin version\r\n // back_trace( 'NOTICE', 'Plugin version ' . $plugin_version);\r\n\r\n return $plugin_version;\r\n\r\n}\r\n"}, "771d22f58dfb56861b51c8711da96e8daea5b710": {"t": 1785756409.9004035, "n": 55151, "h": "8362924a7db28e28", "c": " $user_id,\r\n 'page_id' => $page_id,\r\n 'session_id' => $session_id,\r\n 'thread_id' => $thread_id,\r\n 'assistant_id' => $assistant_id,\r\n 'additional_instructions' => $additional_instructions,\r\n 'model' => $model,\r\n 'voice' => $voice,\r\n ));\r\n\r\n // DIAG - Diagnostics - Ver 1.8.6\r\n // back_trace( 'NOTICE', '$user_id: ' . $user_id);\r\n // back_trace( 'NOTICE', '$page_id: ' . $page_id);\r\n // back_trace( 'NOTICE', '$session_id: ' . $session_id);\r\n // back_trace( 'NOTICE', '$thread_id: ' . $thread_id);\r\n // back_trace( 'NOTICE', '$assistant_id: ' . $assistant_id);\r\n // back_trace( 'NOTICE', '$additional_instructions: ' . $additional_instructions);\r\n // back_trace( 'NOTICE', '$model: ' . $model);\r\n \r\n // Set visitor and logged in user limits - Ver 2.0.1\r\n if (is_user_logged_in()) {\r\n // back_trace( 'NOTICE', 'User is logged in');\r\n $kchat_settings['chatbot_chatgpt_message_limit_setting'] = esc_attr(get_option('chatbot_chatgpt_message_limit_setting', '999'));\r\n } else {\r\n // back_trace( 'NOTICE', 'User is NOT logged in');\r\n $kchat_settings['chatbot_chatgpt_message_limit_setting'] = esc_attr(get_option('chatbot_chatgpt_visitor_message_limit_setting', '999'));\r\n }\r\n\r\n // Localize the data for the chatbot - Ver 2.1.1.1\r\n $kchat_settings = array_merge($kchat_settings, array(\r\n 'chatbot_chatgpt_display_style' => $chatbot_chatgpt_display_style,\r\n 'chatbot_chatgpt_version' => $chatbot_chatgpt_plugin_version,\r\n 'plugins_url' => $chatbot_chatgpt_plugin_dir_url,\r\n 'ajax_url' => admin_url('admin-ajax.php'),\r\n 'user_id' => $user_id,\r\n 'page_id' => $page_id,\r\n 'session_id' => $session_id,\r\n 'thread_id' => $thread_id,\r\n 'assistant_id' => $assistant_id,\r\n 'additional_instructions' => $additional_instructions,\r\n 'model' => $model,\r\n 'voice' => $voice,\r\n 'chatbot_chatgpt_timeout_setting' => esc_attr(get_option('chatbot_chatgpt_timeout_setting', '240')),\r\n 'chatbot_chatgpt_avatar_icon_setting' => esc_attr(get_option('chatbot_chatgpt_avatar_icon_setting', '')),\r\n 'chatbot_chatgpt_custom_avatar_icon_setting' => esc_attr(get_option('chatbot_chatgpt_custom_avatar_icon_setting', '')),\r\n '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?')),\r\n 'chatbot_chatgpt_force_page_reload' => esc_attr(get_option('chatbot_chatgpt_force_page_reload', 'No')),\r\n 'chatbot_chatgpt_custom_error_message' => esc_attr(get_option('chatbot_chatgpt_custom_error_message', 'Your custom error message goes here.')),\r\n 'chatbot_chatgpt_message_limit_setting' => esc_attr(get_option('chatbot_chatgpt_message_limit_setting', '999')),\r\n ));\r\n \r\n $kchat_settings_json = wp_json_encode($kchat_settings);\r\n\r\n // Enqueue the main chatbot script - CHANGED TO LOAD ORDER IN V2.1.2\r\n wp_enqueue_script('chatbot-chatgpt-js', plugins_url('assets/js/chatbot-chatgpt.js', __FILE__), array(), $chatbot_chatgpt_plugin_version, true);\r\n\r\n // Add the inline script to define kchat_settings before the main script runs - CHANGED THE LOAD ORDER IN VER 2.1.2\r\n 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');\r\n // FIXME - REMOVED IN V2.1.2\r\n // 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');\r\n\r\n}\r\nadd_action('wp_enqueue_scripts', 'chatbot_chatgpt_enqueue_scripts');\r\n\r\n// Enqueue MathJax with custom configuration - Ver 2.1.2\r\n// https://docs.mathjax.org/en/latest/\r\n// https://github.com/mathjax/MathJax/blob/master/LICENSE\r\n// https://cdnjs.cloudflare.com/ajax/libs/mathjax/3.2.0/es5/tex-mml-chtml.js\r\n// https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js\r\nfunction enqueue_mathjax_with_custom_config() {\r\n\r\n global $chatbot_chatgpt_plugin_version;\r\n global $chatbot_chatgpt_plugin_dir_url;\r\n\r\n // Add the MathJax configuration script\r\n $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 \";\r\n\r\n // Enqueue the MathJax script\r\n // wp_enqueue_script( 'mathjax', plugin_dir_url(__FILE__) . 'assets/js/tex-chtml.js', array(), $chatbot_chatgpt_plugin_version, true );\r\n wp_enqueue_script( 'mathjax', $chatbot_chatgpt_plugin_dir_url . 'assets/js/tex-mml-chtml.js', array(), $chatbot_chatgpt_plugin_version, true );\r\n\r\n // Add the inline script before MathJax script\r\n wp_add_inline_script( 'mathjax', $mathjax_config, 'before' );\r\n\r\n}\r\nadd_action( 'wp_enqueue_scripts', 'enqueue_mathjax_with_custom_config' );\r\n\r\n// CORS - Cross Origin Resource Sharing - CAUTION: This allows all domains to access the end point - Ver 2.1.2\r\n// function allow_cross_domain_requests() {\r\n// header(\"Access-Control-Allow-Origin: *\");\r\n// header(\"Access-Control-Allow-Methods: GET, POST, OPTIONS\");\r\n// header(\"Access-Control-Allow-Headers: X-Requested-With\");\r\n// }\r\n// add_action('init', 'allow_cross_domain_requests');\r\n\r\n// Settings and Deactivation Links - Ver - 1.5.0\r\nif (!function_exists('enqueue_jquery_ui')) {\r\n function enqueue_jquery_ui() {\r\n wp_enqueue_style('wp-jquery-ui-dialog');\r\n wp_enqueue_script('jquery-ui-dialog');\r\n }\r\n add_action( 'admin_enqueue_scripts', 'enqueue_jquery_ui' );\r\n}\r\n\r\n// Schedule Cleanup of Expired Transients\r\nif (!wp_next_scheduled('chatbot_chatgpt_cleanup_event')) {\r\n wp_schedule_event(time(), 'daily', 'chatbot_chatgpt_cleanup_event');\r\n}\r\nadd_action('chatbot_chatgpt_cleanup_event', 'clean_specific_expired_transients');\r\n\r\n// Schedule Conversation Log Cleanup - Ver 1.6.7\r\nif (!wp_next_scheduled('chatbot_chatgpt_conversation_log_cleanup_event')) {\r\n wp_schedule_event(time(), 'daily', 'chatbot_chatgpt_conversation_log_cleanup_event');\r\n}\r\nadd_action('chatbot_chatgpt_conversation_log_cleanup_event', 'chatbot_chatgpt_conversation_log_cleanup');\r\n\r\n// Schedule the transcript file cleanup event if it's not already scheduled - Ver 1.9.9\r\n// Schedule the cleanup event if it's not already scheduled\r\nif (!wp_next_scheduled('chatbot_chatgpt_cleanup_transcript_files')) {\r\n wp_schedule_event(time(), 'hourly', 'chatbot_chatgpt_cleanup_transcript_files');\r\n}\r\n\r\n// Deactivate old hooks - Ver 2.0.1\r\nif(esc_attr(get_option('chatbot_chatgpt_cleanup_old_hooks') !== 'Completed')) {\r\n // Deactivate old hooks - Ver 2.0.1\r\n wp_clear_scheduled_hook('chatbot_chatgpt_cleanup_transcripts');\r\n // Then update the option\r\n update_option('chatbot_chatgpt_cleanup_old_hooks', 'Completed');\r\n}\r\n\r\n// Schedule the audio file cleanup event if it's not already scheduled - Ver 1.9.9\r\n// Schedule the cleanup event if it's not already scheduled\r\nif (!wp_next_scheduled('chatbot_chatgpt_cleanup_audio_files')) {\r\n wp_schedule_event(time(), 'hourly', 'chatbot_chatgpt_cleanup_audio_files');\r\n}\r\n\r\n// Schedule the upload file cleanup event if it's not already scheduled - Ver 1.9.9\r\n// Schedule the cleanup event if it's not already scheduled\r\nif (!wp_next_scheduled('chatbot_chatgpt_cleanup_upload_files')) {\r\n wp_schedule_event(time(), 'hourly', 'chatbot_chatgpt_cleanup_upload_files');\r\n}\r\n\r\n// Schedule the download file cleanup event if it's not already scheduled - Ver 2.0.3\r\n// Schedule the cleanup event if it's not already scheduled\r\nif (!wp_next_scheduled('chatbot_chatgpt_cleanup_download_files')) {\r\n wp_schedule_event(time(), 'hourly', 'chatbot_chatgpt_cleanup_download_files');\r\n}\r\n\r\n// Add the Assistant table to the database - Ver 2.0.4\r\ncreate_chatbot_chatgpt_assistants_table();\r\n\r\n// Handle Ajax requests\r\nfunction chatbot_chatgpt_send_message() {\r\n\r\n // Global variables\r\n global $session_id;\r\n global $user_id;\r\n global $page_id;\r\n global $thread_id;\r\n global $assistant_id;\r\n global $chatbot_chatgpt_assistant_alias;\r\n global $kchat_settings;\r\n global $additional_instructions;\r\n global $model;\r\n global $voice;\r\n\r\n global $flow_data;\r\n\r\n $api_key = '';\r\n\r\n // Retrieve the API key\r\n $api_key = esc_attr(get_option('chatbot_chatgpt_api_key'));\r\n\r\n // FIXME - STILL NEEDED - Ver 2.0.7 - 2024 07 25\r\n // Retrieve the GPT Model\r\n if (!empty($model)) {\r\n $model = esc_attr(get_option('chatbot_chatgpt_model_choice', 'gpt-3.5-turbo'));\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Model from options: ' . $model);\r\n } else {\r\n // SEE IF $kchat_settings HAS THE MODEL\r\n if ( isset($kchat_settings['model'])) {\r\n $model = $kchat_settings['model'];\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Model set in global: ' . $model);\r\n } else {\r\n // Set the model to the default\r\n $model = esc_attr(get_option('chatbot_chatgpt_model_choice', 'gpt-3.5-turbo'));\r\n // DIAG - Diagnostics\r\n // back_trace( 'ERROR', 'Invalid Model.');\r\n // wp_send_json_error('Error: Invalid Model. Please check the plugin settings.');\r\n }\r\n }\r\n\r\n // Send only clean text via the API\r\n $message = sanitize_text_field($_POST['message']);\r\n\r\n // Check for missing API key or Message\r\n if (!$api_key || !$message) {\r\n // DIAG - Diagnostics\r\n // back_trace( 'ERROR', 'Invalid API Key or Message.');\r\n wp_send_json_error('Error: Invalid API key or Message. Please check the plugin settings.');\r\n }\r\n\r\n // Removed in Ver 1.8.6 - 2024 02 15\r\n // $thread_id = '';\r\n // $assistant_id = '';\r\n // $user_id = '';\r\n // $page_id = '';\r\n \r\n // Check the transient for the Assistant ID - Ver 1.7.2\r\n // $user_id = intval($_POST['user_id']); // REMOVED intval in Ver 2.0.8\r\n // $page_id = intval($_POST['page_id']); // REMOVED intval in Ver 2.0.8\r\n $user_id = $_POST['user_id'];\r\n $page_id = $_POST['page_id'];\r\n $session_id = $_POST['session_id'];\r\n\r\n // DIAG - Diagnostics - Ver 1.8.6\r\n // back_trace( 'NOTICE', '$user_id: ' . $user_id);\r\n // back_trace( 'NOTICE', '$page_id: ' . $page_id);\r\n // back_trace( 'NOTICE', '$session_id: ' . $session_id);\r\n\r\n $kchat_settings['chatbot_chatgpt_display_style'] = get_chatbot_chatgpt_transients( 'display_style', $user_id, $page_id, $session_id);\r\n $kchat_settings['chatbot_chatgpt_assistant_alias'] = get_chatbot_chatgpt_transients( 'assistant_alias', $user_id, $page_id, $session_id);\r\n $kchat_settings['assistant_id'] = get_chatbot_chatgpt_transients( 'assistant_id', $user_id, $page_id, $session_id);\r\n $kchat_settings['thread_id'] = get_chatbot_chatgpt_transients( 'thread_id', $user_id, $page_id, $session_id);\r\n $kchat_settings['chatbot_chatgpt_model'] = get_chatbot_chatgpt_transients( 'model', $user_id, $page_id, $session_id);\r\n $kchat_settings['chatbot_chatgpt_voice_option'] = get_chatbot_chatgpt_transients( 'voice', $user_id, $page_id, $session_id);\r\n $kchat_settings['additional_instructions'] = get_chatbot_chatgpt_transients( 'additional_instructions', $user_id, $page_id, $session_id);\r\n $voice = $kchat_settings['chatbot_chatgpt_voice_option'];\r\n $model = $kchat_settings['chatbot_chatgpt_model'];\r\n $additional_instructions = $kchat_settings['additional_instructions'];\r\n $chatbot_chatgpt_assistant_alias = $kchat_settings['chatbot_chatgpt_assistant_alias'];\r\n\r\n // Get the thread information - Ver 2.0.7\r\n $thread_id = get_chatbot_chatgpt_threads($user_id, $session_id, $page_id, $assistant_id);\r\n $kchat_settings['thread_id'] = $thread_id;\r\n // $kchat_settings = array_merge($kchat_settings, get_chatbot_chatgpt_threads($user_id, $page_id));\r\n\r\n $assistant_id = isset($kchat_settings['assistant_id']) ? $kchat_settings['assistant_id'] : '';\r\n $thread_Id = isset($kchat_settings['thread_id']) ? $kchat_settings['thread_id'] : '';\r\n $model = isset($kchat_settings['chatbot_chatgpt_model']) ? $kchat_settings['chatbot_chatgpt_model'] : '';\r\n $voice = isset($kchat_settings['chatbot_chatgpt_voice_option']) ? $kchat_settings['chatbot_chatgpt_voice_option'] : '';\r\n\r\n // DIAG - Diagnostics - Ver 1.8.6\r\n // back_trace( 'NOTICE', '========================================');\r\n // back_trace( 'NOTICE', '$user_id: ' . $user_id);\r\n // back_trace( 'NOTICE', '$page_id: ' . $page_id);\r\n // back_trace( 'NOTICE', '$session_id: ' . $session_id);\r\n // back_trace( 'NOTICE', '$thread_id: ' . $thread_id);\r\n // back_trace( 'NOTICE', '$assistant_id: ' . $assistant_id);\r\n // back_trace( 'NOTICE', '$chatbot_chatgpt_assistant_alias: ' . $chatbot_chatgpt_assistant_alias);\r\n // back_trace( 'NOTICE', '$model: ' . $model);\r\n // back_trace( 'NOTICE', '$voice: ' . $voice);\r\n // DIAG - Diagnostics - Ver 2.0.9\r\n // back_trace( 'NOTICE', '========================================');\r\n // foreach ($kchat_settings as $key => $value) {\r\n // back_trace( 'NOTICE', '$kchat_settings[' . $key . ']: ' . $value);\r\n // }\r\n\r\n // Assistants\r\n // $chatbot_chatgpt_assistant_alias == 'original'; // Default\r\n // $chatbot_chatgpt_assistant_alias == 'primary';\r\n // $chatbot_chatgpt_assistant_alias == 'alternate';\r\n // $chatbot_chatgpt_assistant_alias == 'asst_xxxxxxxxxxxxxxxxxxxxxxxx'; // GPT Assistant Id\r\n \r\n // Which Assistant ID to use - Ver 1.7.2\r\n if ($chatbot_chatgpt_assistant_alias == 'original') {\r\n\r\n $use_assistant_id = 'No';\r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE' , 'Using Original ChatGPT - $chatbot_chatgpt_assistant_alias: ' . $chatbot_chatgpt_assistant_alias);\r\n\r\n } elseif ($chatbot_chatgpt_assistant_alias == 'primary') {\r\n\r\n $assistant_id = esc_attr(get_option('assistant_id'));\r\n // $additional_instructions = esc_attr(get_option('chatbot_chatgpt_assistant_instructions', '')); // REMOVED VER 2.0.9\r\n $use_assistant_id = 'Yes';\r\n\r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE' , 'Using Primary Assistant - $assistant_id: ' . $assistant_id);\r\n \r\n // Check if the GPT Assistant ID is blank, null, or \"Please provide the GPT Assistant ID.\"\r\n if (empty($assistant_id) || $assistant_id == \"Please provide the GPT Assistant Id.\") {\r\n \r\n // Primary assistant_id not set\r\n $chatbot_chatgpt_assistant_alias = 'original';\r\n $use_assistant_id = 'No';\r\n \r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE' ,'Falling back to ChatGPT API - $assistant_id: ' . $assistant_id );\r\n }\r\n\r\n } elseif ($chatbot_chatgpt_assistant_alias == 'alternate') {\r\n\r\n $assistant_id = esc_attr(get_option('chatbot_chatgpt_assistant_id_alternate'));\r\n // $additional_instructions = esc_attr(get_option('chatbot_chatgpt_assistant_instructions_alternate', '')); // REMOVED VER 2.0.9\r\n $use_assistant_id = 'Yes';\r\n\r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE' , 'Using Altrnate Assistant - $assistant_id: ' . $assistant_id);\r\n\r\n // Check if the GPT Assistant ID is blank, null, or \"Please provide the GPT Assistant ID.\"\r\n if (empty($assistant_id) || $assistant_id == \"Please provide the GPT Assistant Id.\") {\r\n\r\n /// Alternate assistant_id not set\r\n $chatbot_chatgpt_assistant_alias = 'original';\r\n $use_assistant_id = 'No';\r\n\r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE' ,'Falling back to ChatGPT API - $assistant_id: ' . $assistant_id );\r\n \r\n }\r\n\r\n } elseif (str_starts_with($assistant_id, 'asst_')) {\r\n\r\n $chatbot_chatgpt_assistant_alias = $assistant_id; // Belt & Suspenders\r\n $use_assistant_id = 'Yes';\r\n\r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE' ,'Assistant ID pass as a parameter - $assistant_id: ' . $assistant_id );\r\n\r\n } else {\r\n\r\n // Reference GPT Assistant IDs directly - Ver 1.7.3\r\n if (str_starts_with($chatbot_chatgpt_assistant_alias, 'asst_')) {\r\n\r\n // DIAG - Diagnostics - 2.0.5\r\n // back_trace( 'NOTICE', 'Using GPT Assistant ID: ' . $chatbot_chatgpt_assistant_alias);\r\n\r\n // Override the $assistant_id with the GPT Assistant ID\r\n $assistant_id = $chatbot_chatgpt_assistant_alias;\r\n $use_assistant_id = 'Yes';\r\n\r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE' , 'Using $assistant_id ' . $assistant_id);\r\n\r\n } else {\r\n\r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE', 'Using ChatGPT API: ' . $chatbot_chatgpt_assistant_alias);\r\n\r\n // Override the $use_assistant_id and set it to 'No'\r\n $use_assistant_id = 'No';\r\n \r\n // DIAG - Diagnostics - Ver 1.8.1\r\n // back_trace( 'NOTICE' , 'Falling back to ChatGPT API');\r\n\r\n }\r\n\r\n }\r\n\r\n // Get any additional instructions - Ver 2.0.9\r\n $additional_instructions = get_chatbot_chatgpt_transients( 'additional_instructions', $user_id, $page_id, $session_id);\r\n\r\n // Decide whether to use Flow, Assistant or Original ChatGPT\r\n if ($model == 'flow'){\r\n \r\n // DIAG - Diagnostics - Ver 2.1.1.1\r\n // back_trace( 'NOTICE', 'Using ChatGPT Flow');\r\n // back_trace( 'NOTICE', '$user_id ' . $user_id);\r\n // back_trace( 'NOTICE', '$page_id ' . $page_id);\r\n\r\n // Reload the model - BELT & SUSPENDERS\r\n $kchat_settings['model'] = $model;\r\n\r\n // Get the step from the transient\r\n $kflow_step = get_chatbot_chatgpt_transients( 'kflow_step', null, null, $session_id);\r\n if (empty($kflow_step)) {\r\n $kflow_step = 0; // FIXME - Set to 1 or to zero?\r\n }\r\n\r\n // $thread_id\r\n $thread_id = '[answer=' . $kflow_step + 1 . ']';\r\n \r\n // Add +1 to $kchat_settings['next_step']\r\n $kflow_step = $kflow_step + 1;\r\n\r\n // Set the next step\r\n set_chatbot_chatgpt_transients( 'kflow_step', $kflow_step, null, null, $session_id);\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', '$message: ' . $message);\r\n $thread_id = get_chatbot_chatgpt_threads($user_id, $session_id, $page_id, $assistant_id);\r\n // back_trace( 'NOTICE', '$thread_id ' . $thread_id);\r\n append_message_to_conversation_log($session_id, $user_id, $page_id, 'Visitor', $thread_id, $assistant_id, $message);\r\n\r\n // BELT & SUSPENDERS\r\n $thread_id = '';\r\n\r\n // Send message to ChatGPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_call_flow_api($api_key, $message);\r\n\r\n wp_send_json_success($response);\r\n\r\n } elseif ($use_assistant_id == 'Yes') {\r\n\r\n // DIAG - Diagnostics - Ver 2.1.1.1\r\n // back_trace( 'NOTICE', 'Using GPT Assistant ID: ' . $use_assistant_id);\r\n // back_trace( 'NOTICE', '$user_id ' . $user_id);\r\n // back_trace( 'NOTICE', '$page_id ' . $page_id);\r\n // back_trace( 'NOTICE', '$message ' . $message);\r\n\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', '$message ' . $message);\r\n $thread_id = get_chatbot_chatgpt_threads($user_id, $session_id, $page_id, $assistant_id);\r\n // back_trace( 'NOTICE', '$thread_id ' . $thread_id);\r\n append_message_to_conversation_log($session_id, $user_id, $page_id, 'Visitor', $thread_id, $assistant_id, $message);\r\n\r\n // DIAG - Diagnostics - Ver 2.0.9\r\n // back_trace( 'NOTICE', '========================================');\r\n // back_trace( 'NOTICE', 'BEFORE CALL TO MODULE $additional_instructions: ' . $additional_instructions);\r\n\r\n // Send message to Custom GPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_custom_gpt_call_api($api_key, $message, $assistant_id, $thread_id, $session_id, $user_id, $page_id);\r\n\r\n // Use TF-IDF to enhance response\r\n $chatbot_chatgpt_suppress_learnings = esc_attr(get_option('chatbot_chatgpt_suppress_learnings', 'Random'));\r\n if ( $chatbot_chatgpt_suppress_learnings != 'None') {\r\n $response = $response . chatbot_chatgpt_enhance_with_tfidf($message);\r\n }\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', '$response ' . print_r($response,true));\r\n $thread_id = get_chatbot_chatgpt_threads($user_id, $session_id, $page_id, $assistant_id);\r\n // back_trace( 'NOTICE', '$thread_id ' . $thread_id);\r\n append_message_to_conversation_log($session_id, $user_id, $page_id, 'Chatbot', $thread_id, $assistant_id, $response);\r\n\r\n // Clean (erase) the output buffer - Ver 1.6.8\r\n // Check if output buffering is active before attempting to clean it\r\n if (ob_get_level() > 0) {\r\n ob_clean();\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Output buffer cleaned');\r\n } else {\r\n // Optionally start output buffering if needed for your application\r\n // ob_start();\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Output buffer not cleaned');\r\n }\r\n\r\n if (str_starts_with($response, 'Error:') || str_starts_with($response, 'Failed:')) {\r\n // Return response\r\n // back_trace( 'NOTICE', '$response ' . print_r($response,true));\r\n wp_send_json_error('Oops! Something went wrong on our end. Please try again later!');\r\n } else {\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Check for links and images in response before returning');\r\n $response = chatbot_chatgpt_check_for_links_and_images($response);\r\n\r\n // FIXME - Append extra message - Ver 2.1.1.1.1\r\n // Danger Will Robinson! Danger!\r\n $extra_message = esc_attr(get_option('chatbot_chatgpt_extra_message', ''));\r\n $response = chatbot_chatgpt_append_extra_message($response, $extra_message);\r\n\r\n // Return response\r\n wp_send_json_success($response);\r\n }\r\n\r\n } else {\r\n\r\n // DIAG - Diagnostics - Ver 2.1.1.1\r\n // back_trace( 'NOTICE', 'Using ChatGPT');\r\n // back_trace( 'NOTICE', '$user_id ' . $user_id);\r\n // back_trace( 'NOTICE', '$page_id ' . $page_id);\r\n // back_trace( 'NOTICE', '$message ' . $message);\r\n\r\n // Belt & Suspenders - Ver 2.1.5.1\r\n if (!isset($kchat_settings['model'])) {\r\n $kchat_settings['model'] = $model;\r\n };\r\n // back_trace( 'NOTICE', '$model: ' . $model);\r\n // back_trace( 'NOTICE', '$kchat_settings[model]: ' . $kchat_settings['model']);\r\n // if (str_starts_with($model,'dall')) {\r\n // back_trace ( 'NOTICE', 'Using Image API');\r\n // } else {\r\n // back_trace ( 'NOTICE', 'Using ChatGPT API');\r\n // }\r\n\r\n $thread_id = get_chatbot_chatgpt_threads($user_id, $session_id, $page_id, $assistant_id);\r\n // back_trace( 'NOTICE', '$thread_id ' . $thread_id);\r\n append_message_to_conversation_log($session_id, $user_id, $page_id, 'Visitor', $thread_id, $assistant_id, $message);\r\n \r\n // If $model starts with 'gpt' then the chatbot_chatgpt_call_api or 'dall' then chatbot_chatgpt_call_image_api\r\n // TRY NOT TO FETCH MODEL AGAIN\r\n // $model = esc_attr(get_option('chatbot_chatgpt_model_choice', 'gpt-3.5-turbo'));\r\n $model = isset($kchat_settings['model']) ? $kchat_settings['model'] : null;\r\n $voice = isset($kchat_settings['voice']) ? $kchat_settings['voice'] : null;\r\n if (str_starts_with($model !== null && $model, 'gpt-4o') !== false) {\r\n // The string 'gpt-4o' is found in $model\r\n // Reload the model - BELT & SUSPENDERS\r\n $kchat_settings['model'] = $model;\r\n // Send message to ChatGPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_call_omni($api_key, $message);\r\n } elseif ($model !== null && str_starts_with($model, 'gpt')) {\r\n // Reload the model - BELT & SUSPENDERS\r\n $kchat_settings['model'] = $model;\r\n // Send message to ChatGPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_call_api($api_key, $message);\r\n } elseif ($model !== null && str_starts_with($model, 'dall')) {\r\n // Reload the model - BELT & SUSPENDERS\r\n $kchat_settings['model'] = $model;\r\n // Send message to Image API - Ver 1.9.4\r\n $response = chatbot_chatgpt_call_image_api($api_key, $message);\r\n } elseif ($model !== null && str_starts_with($model, 'tts')) {\r\n // Reload the model - BELT & SUSPENDERS\r\n $kchat_settings['model'] = $model;\r\n $kchat_settings['voice'] = $voice;\r\n // Send message to TTS API - Text-to-speech - Ver 1.9.5\r\n $response = chatbot_chatgpt_call_tts_api($api_key, $message, $voice, $user_id, $page_id, $session_id);\r\n } elseif ($model !== null && str_starts_with($model,'whisper')) {\r\n $kchat_settings['model'] = $model;\r\n // Send message to STT API - Speech-to-text - Ver 1.9.6\r\n $response = chatbot_chatgpt_call_stt_api($api_key, $message);\r\n } else {\r\n // Reload the model - BELT & SUSPENDERS\r\n $kchat_settings['model'] = $model;\r\n // Send message to ChatGPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_call_api($api_key, $message);\r\n }\r\n \r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', ['message' => 'BEFORE CALL TO ENHANCE TFIDF', 'response' => $response]);\r\n \r\n // Use TF-IDF to enhance response\r\n $chatbot_chatgpt_suppress_learnings = esc_attr(get_option('chatbot_chatgpt_suppress_learnings', 'Random'));\r\n if ( $chatbot_chatgpt_suppress_learnings != 'None') {\r\n $response = $response . chatbot_chatgpt_enhance_with_tfidf($message);\r\n }\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', ['message' => 'AFTER CALL TO ENHANCE TFIDF', 'response' => $response]);\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', '$response ' . print_r($response,true));\r\n $thread_id = get_chatbot_chatgpt_threads($user_id, $session_id, $page_id, $assistant_id);\r\n // back_trace( 'NOTICE', '$thread_id ' . $thread_id);\r\n append_message_to_conversation_log($session_id, $user_id, $page_id, 'Chatbot', $thread_id, $assistant_id, $response);\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Check for links and images in response before returning');\r\n $response = chatbot_chatgpt_check_for_links_and_images($response);\r\n\r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE', 'Response: ' . $response);\r\n\r\n // FIXME - Append extra message - Ver 2.1.1.1.1\r\n // Danger Will Robinson! Danger!\r\n $extra_message = esc_attr(get_option('chatbot_chatgpt_extra_message', ''));\r\n $response = chatbot_chatgpt_append_extra_message($response, $extra_message);\r\n\r\n // Return response\r\n wp_send_json_success($response);\r\n\r\n }\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'ERROR', 'Oops! I fell through the cracks!');\r\n wp_send_json_error('Oops! I fell through the cracks!');\r\n\r\n}\r\n\r\n// Add action to send messages - Ver 1.0.0\r\nadd_action('wp_ajax_chatbot_chatgpt_send_message', 'chatbot_chatgpt_send_message');\r\nadd_action('wp_ajax_nopriv_chatbot_chatgpt_send_message', 'chatbot_chatgpt_send_message');\r\n\r\n// Add action to upload files - Ver 1.7.6\r\nadd_action('wp_ajax_chatbot_chatgpt_upload_files', 'chatbot_chatgpt_upload_files');\r\nadd_action('wp_ajax_nopriv_chatbot_chatgpt_upload_files', 'chatbot_chatgpt_upload_files');\r\n\r\n// Add action to upload files - Ver 1.7.6\r\nadd_action('wp_ajax_chatbot_chatgpt_upload_mp3', 'chatbot_chatgpt_upload_mp3');\r\nadd_action('wp_ajax_nopriv_chatbot_chatgpt_upload_mp3', 'chatbot_chatgpt_upload_mp3');\r\n\r\n// Add action to erase conversation - Ver 1.8.6\r\nadd_action('wp_ajax_chatbot_chatgpt_erase_conversation', 'chatbot_chatgpt_erase_conversation_handler');\r\nadd_action('wp_ajax_nopriv_chatbot_chatgpt_erase_conversation', 'chatbot_chatgpt_erase_conversation_handler'); // For logged-out users, if needed\r\n\r\n// Settings and Deactivation - Ver 1.5.0\r\nadd_filter('plugin_action_links_' . plugin_basename(__FILE__), 'chatbot_chatgpt_plugin_action_links');\r\n\r\n// Append an extra message to the response - Ver 2.0.9\r\nfunction chatbot_chatgpt_append_extra_message($response, $extra_message) {\r\n\r\n // Append the extra message to the response\r\n $response = $response . ' ' . $extra_message;\r\n return $response;\r\n\r\n}\r\n\r\n// Crawler aka Knowledge Navigator - Ver 1.6.1\r\nfunction chatbot_chatgpt_kn_status_activation() {\r\n add_option('chatbot_chatgpt_kn_status', 'Never Run');\r\n // clear any old scheduled runs\r\n if (wp_next_scheduled('crawl_scheduled_event_hook')) {\r\n wp_clear_scheduled_hook('crawl_scheduled_event_hook');\r\n }\r\n // clear the 'knowledge_navigator_scan_hook' hook on plugin activation - Ver 1.6.3\r\n if (wp_next_scheduled('knowledge_navigator_scan_hook')) {\r\n // BREAK/FIX - Do not unset the hook - Ver 1.8.5\r\n // wp_clear_scheduled_hook('knowledge_navigator_scan_hook'); // Clear scheduled runs\r\n }\r\n}\r\nregister_activation_hook(__FILE__, 'chatbot_chatgpt_kn_status_activation');\r\n\r\n// Clean Up in Aisle 4\r\nfunction chatbot_chatgpt_kn_status_deactivation() {\r\n delete_option('chatbot_chatgpt_kn_status');\r\n wp_clear_scheduled_hook('knowledge_navigator_scan_hook'); \r\n}\r\nregister_deactivation_hook(__FILE__, 'chatbot_chatgpt_kn_status_deactivation');\r\n\r\n// Function to add a new message and response, keeping only the last five - Ver 1.6.1\r\nfunction addEntry($transient_name, $newEntry) {\r\n\r\n $context_history = get_transient($transient_name);\r\n if (!$context_history) {\r\n $context_history = [];\r\n }\r\n\r\n // Determine the total length of all existing entries\r\n $totalLength = 0;\r\n foreach ($context_history as $entry) {\r\n if (is_string($entry)) {\r\n $totalLength += strlen($entry);\r\n } elseif (is_array($entry)) {\r\n $totalLength += strlen(json_encode($entry)); // Convert to string if an array\r\n }\r\n }\r\n\r\n // IDEA - How will the new threading option from OpenAI change how this works?\r\n // Define thresholds for the number of entries to keep\r\n $maxEntries = 30; // Default maximum number of entries\r\n if ($totalLength > 5000) { // Higher threshold\r\n $maxEntries = 20;\r\n }\r\n if ($totalLength > 10000) { // Lower threshold\r\n $maxEntries = 10;\r\n }\r\n\r\n while (count($context_history) >= $maxEntries) {\r\n array_shift($context_history); // Remove the oldest element\r\n }\r\n\r\n if (is_array($newEntry)) {\r\n $newEntry = json_encode($newEntry); // Convert the array to a string\r\n }\r\n\r\n array_push($context_history, $newEntry); // Append the new element\r\n set_transient($transient_name, $context_history); // Update the transient\r\n}\r\n\r\n// Function to return message and response - Ver 1.6.1\r\nfunction concatenateHistory($transient_name) {\r\n $context_history = get_transient($transient_name);\r\n if (!$context_history) {\r\n return ''; // Return an empty string if the transient does not exist\r\n }\r\n return implode(' ', $context_history); // Concatenate the array values into a single string\r\n}\r\n\r\n// FIXME - MOVE CORE FUNCTIONS TO A SEPARATE FILE, LEAVING ONLY THE HOOKS HERE\r\n// Initialize the Greetings - Ver 1.6.1\r\nfunction enqueue_greetings_script( $initial_greeting = null, $subsequent_greeting = null) {\r\n\r\n // If user is logged in, then modify greeting if greeting contains \"[...]\" or remove if not logged in - Ver 1.9.4\r\n if (is_user_logged_in()) {\r\n\r\n $current_user_id = get_current_user_id();\r\n $current_user = get_userdata($current_user_id);\r\n\r\n //Do this for Initial Greeting\r\n if ( empty($initial_greeting) ) {\r\n $initial_greeting = esc_attr(get_option('chatbot_chatgpt_initial_greeting', 'Hello! How can I help you today?'));\r\n }\r\n\r\n // Determine what the field name is between the brackets\r\n $user_field_name = '';\r\n $user_field_name = substr($initial_greeting, strpos($initial_greeting, '[') + 1, strpos($initial_greeting, ']') - strpos($initial_greeting, '[') - 1);\r\n // If $initial_greeting contains \"[$user_field_name]\" then replace with field from DB\r\n if (strpos($initial_greeting, '[' . $user_field_name . ']') !== false) {\r\n $initial_greeting = str_replace('[' . $user_field_name . ']', $current_user->$user_field_name, $initial_greeting);\r\n } else {\r\n $initial_greeting = str_replace('[' . $user_field_name . ']', '', $initial_greeting);\r\n // Remove the extra space when two spaces are present\r\n $initial_greeting = str_replace(' ', ' ', $initial_greeting);\r\n // Remove the extra space before punctuation including period, comma, exclamation mark, and question mark\r\n $initial_greeting = preg_replace('/\\s*([.,!?])/', '$1', $initial_greeting);\r\n }\r\n\r\n // Do this for Subsequent Greeting\r\n if ( empty($subsequent_greeting) ) {\r\n $subsequent_greeting = esc_attr(get_option('chatbot_chatgpt_subsequent_greeting', 'Hello again! How can I help you?'));\r\n }\r\n\r\n // Determine what the field name is between the brackets\r\n $user_field_name = '';\r\n $user_field_name = substr($subsequent_greeting, strpos($subsequent_greeting, '[') + 1, strpos($subsequent_greeting, ']') - strpos($subsequent_greeting, '[') - 1);\r\n // If $subsequent_greeting contains \"[$user_field_name]\" then replace with field from DB\r\n if (strpos($subsequent_greeting, '[' . $user_field_name . ']') !== false) {\r\n $subsequent_greeting = str_replace('[' . $user_field_name . ']', $current_user->$user_field_name, $subsequent_greeting);\r\n } else {\r\n $subsequent_greeting = str_replace('[' . $user_field_name . ']', '', $subsequent_greeting);\r\n // Remove the extra space when two spaces are present\r\n $subsequent_greeting = str_replace(' ', ' ', $subsequent_greeting);\r\n // Remove the extra space before punctuation including period, comma, exclamation mark, and question mark\r\n $subsequent_greeting = preg_replace('/\\s*([.,!?])/', '$1', $subsequent_greeting);\r\n }\r\n\r\n } else {\r\n\r\n //Do this for Initial Greeting\r\n if ( empty($initial_greeting) ) {\r\n $initial_greeting = esc_attr(get_option('chatbot_chatgpt_initial_greeting', 'Hello! How can I help you today?'));\r\n }\r\n\r\n $user_field_name = '';\r\n $user_field_name = substr($initial_greeting, strpos($initial_greeting, '[') + 1, strpos($initial_greeting, ']') - strpos($initial_greeting, '[') - 1 );\r\n\r\n // $initial_greeting = preg_replace('/\\s*\\[' . preg_quote($user_field_name, '/') . '\\]\\s*/', '', $initial_greeting);\r\n $initial_greeting = str_replace('[' . $user_field_name . ']', '', $initial_greeting);\r\n // Remove the extra space when two spaces are present\r\n $initial_greeting = str_replace(' ', ' ', $initial_greeting);\r\n // Remove the extra space before punctuation including period, comma, exclamation mark, and question mark\r\n $initial_greeting = preg_replace('/\\s*([.,!?])/', '$1', $initial_greeting);\r\n\r\n //Do this for Subsequent Greeting\r\n if ( empty($subsequent_greeting) ) {\r\n $subsequent_greeting = esc_attr(get_option('chatbot_chatgpt_subsequent_greeting', 'Hello again! How can I help you?'));\r\n }\r\n\r\n $user_field_name = '';\r\n $user_field_name = substr($subsequent_greeting, strpos($subsequent_greeting, '[') + 1, strpos($subsequent_greeting, ']') - strpos($subsequent_greeting, '[') - 1);\r\n\r\n // $subsequent_greeting = preg_replace('/\\s*\\[' . preg_quote($user_field_name, '/') . '\\]\\s*/', '', $subsequent_greeting);\r\n $subsequent_greeting = str_replace('[' . $user_field_name . ']', '', $subsequent_greeting);\r\n // Remove the extra space when two spaces are present\r\n $subsequent_greeting = str_replace(' ', ' ', $subsequent_greeting);\r\n // Remove the extra space before punctuation including period, comma, exclamation mark, and question mark\r\n $subsequent_greeting = preg_replace('/\\s*([.,!?])/', '$1', $subsequent_greeting);\r\n \r\n }\r\n\r\n $greetings = array(\r\n 'initial_greeting' => $initial_greeting,\r\n 'subsequent_greeting' => $subsequent_greeting,\r\n );\r\n\r\n return $greetings;\r\n\r\n}\r\n// \r\nadd_action('wp_enqueue_scripts', 'enqueue_greetings_script');\r\n\r\n// Add the color picker to the adaptive appearance settings section - Ver 1.8.1\r\nfunction enqueue_color_picker($hook_suffix) {\r\n\r\n global $chatbot_chatgpt_plugin_version;\r\n\r\n // first check that $hook_suffix is appropriate for your admin page\r\n wp_enqueue_style('wp-color-picker');\r\n wp_enqueue_script('my-script-handle', plugin_dir_url(__FILE__) . 'assets/js/chatbot-chatgpt-color-picker.js', array('wp-color-picker'), $chatbot_chatgpt_plugin_version, true);\r\n\r\n}\r\nadd_action('admin_enqueue_scripts', 'enqueue_color_picker');\r\n\r\n// Determine if the plugin is installed\r\nfunction kchat_get_plugin_version() {\r\n\r\n global $chatbot_chatgpt_plugin_version;\r\n\r\n if (!function_exists('get_plugin_data')) {\r\n require_once(ABSPATH . 'wp-admin/includes/plugin.php');\r\n }\r\n\r\n // $plugin_data = get_plugin_data(plugin_dir_path(__FILE__) . 'chatbot-chatgpt.php');\r\n // $plugin_version = $plugin_data['chatbot_chatgpt_version'];\r\n $plugin_version = $chatbot_chatgpt_plugin_version;\r\n update_option('chatbot_chatgpt_plugin_version', $plugin_version);\r\n // DIAG - Log the plugin version\r\n // back_trace( 'NOTICE', 'Plugin version ' . $plugin_version);\r\n\r\n return $plugin_version;\r\n\r\n}\r\n"}, "9243ea9cff42972f09ca18c624e79eb656cce0fd": {"t": 1785756411.5452776, "n": 54646, "h": "70bdf3881d6658d4", "c": " $user_id,\r\n 'page_id' => $page_id,\r\n 'session_id' => $session_id,\r\n 'thread_id' => $thread_id,\r\n 'assistant_id' => $assistant_id,\r\n 'additional_instructions' => $additional_instructions,\r\n 'model' => $model,\r\n 'voice' => $voice,\r\n ));\r\n\r\n // DIAG - Diagnostics - Ver 1.8.6\r\n // back_trace( 'NOTICE', '$user_id: ' . $user_id);\r\n // back_trace( 'NOTICE', '$page_id: ' . $page_id);\r\n // back_trace( 'NOTICE', '$session_id: ' . $session_id);\r\n // back_trace( 'NOTICE', '$thread_id: ' . $thread_id);\r\n // back_trace( 'NOTICE', '$assistant_id: ' . $assistant_id);\r\n // back_trace( 'NOTICE', '$additional_instructions: ' . $additional_instructions);\r\n // back_trace( 'NOTICE', '$model: ' . $model);\r\n \r\n // Set visitor and logged in user limits - Ver 2.0.1\r\n if (is_user_logged_in()) {\r\n // back_trace( 'NOTICE', 'User is logged in');\r\n $kchat_settings['chatbot_chatgpt_message_limit_setting'] = esc_attr(get_option('chatbot_chatgpt_message_limit_setting', '999'));\r\n } else {\r\n // back_trace( 'NOTICE', 'User is NOT logged in');\r\n $kchat_settings['chatbot_chatgpt_message_limit_setting'] = esc_attr(get_option('chatbot_chatgpt_visitor_message_limit_setting', '999'));\r\n }\r\n\r\n // Localize the data for the chatbot - Ver 2.1.1.1\r\n $kchat_settings = array_merge($kchat_settings, array(\r\n 'chatbot_chatgpt_display_style' => $chatbot_chatgpt_display_style,\r\n 'chatbot_chatgpt_version' => $chatbot_chatgpt_plugin_version,\r\n 'plugins_url' => $chatbot_chatgpt_plugin_dir_url,\r\n 'ajax_url' => admin_url('admin-ajax.php'),\r\n 'user_id' => $user_id,\r\n 'page_id' => $page_id,\r\n 'session_id' => $session_id,\r\n 'thread_id' => $thread_id,\r\n 'assistant_id' => $assistant_id,\r\n 'additional_instructions' => $additional_instructions,\r\n 'model' => $model,\r\n 'voice' => $voice,\r\n 'chatbot_chatgpt_timeout_setting' => esc_attr(get_option('chatbot_chatgpt_timeout_setting', '240')),\r\n 'chatbot_chatgpt_avatar_icon_setting' => esc_attr(get_option('chatbot_chatgpt_avatar_icon_setting', '')),\r\n 'chatbot_chatgpt_custom_avatar_icon_setting' => esc_attr(get_option('chatbot_chatgpt_custom_avatar_icon_setting', '')),\r\n '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?')),\r\n 'chatbot_chatgpt_force_page_reload' => esc_attr(get_option('chatbot_chatgpt_force_page_reload', 'No')),\r\n 'chatbot_chatgpt_custom_error_message' => esc_attr(get_option('chatbot_chatgpt_custom_error_message', 'Your custom error message goes here.')),\r\n 'chatbot_chatgpt_message_limit_setting' => esc_attr(get_option('chatbot_chatgpt_message_limit_setting', '999')),\r\n ));\r\n \r\n $kchat_settings_json = wp_json_encode($kchat_settings);\r\n\r\n // Enqueue the main chatbot script - CHANGED TO LOAD ORDER IN V2.1.2\r\n wp_enqueue_script('chatbot-chatgpt-js', plugins_url('assets/js/chatbot-chatgpt.js', __FILE__), array(), $chatbot_chatgpt_plugin_version, true);\r\n\r\n // Add the inline script to define kchat_settings before the main script runs - CHANGED THE LOAD ORDER IN VER 2.1.2\r\n 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');\r\n // FIXME - REMOVED IN V2.1.2\r\n // 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');\r\n\r\n}\r\nadd_action('wp_enqueue_scripts', 'chatbot_chatgpt_enqueue_scripts');\r\n\r\n// Enqueue MathJax with custom configuration - Ver 2.1.2\r\n// https://docs.mathjax.org/en/latest/\r\n// https://github.com/mathjax/MathJax/blob/master/LICENSE\r\n// https://cdnjs.cloudflare.com/ajax/libs/mathjax/3.2.0/es5/tex-mml-chtml.js\r\n// https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js\r\nfunction enqueue_mathjax_with_custom_config() {\r\n\r\n global $chatbot_chatgpt_plugin_version;\r\n global $chatbot_chatgpt_plugin_dir_url;\r\n\r\n // Add the MathJax configuration script\r\n $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 \";\r\n\r\n // Enqueue the MathJax script\r\n // wp_enqueue_script( 'mathjax', plugin_dir_url(__FILE__) . 'assets/js/tex-chtml.js', array(), $chatbot_chatgpt_plugin_version, true );\r\n wp_enqueue_script( 'mathjax', $chatbot_chatgpt_plugin_dir_url . 'assets/js/tex-mml-chtml.js', array(), $chatbot_chatgpt_plugin_version, true );\r\n\r\n // Add the inline script before MathJax script\r\n wp_add_inline_script( 'mathjax', $mathjax_config, 'before' );\r\n\r\n}\r\nadd_action( 'wp_enqueue_scripts', 'enqueue_mathjax_with_custom_config' );\r\n\r\n// CORS - Cross Origin Resource Sharing - CAUTION: This allows all domains to access the end point - Ver 2.1.2\r\n// function allow_cross_domain_requests() {\r\n// header(\"Access-Control-Allow-Origin: *\");\r\n// header(\"Access-Control-Allow-Methods: GET, POST, OPTIONS\");\r\n// header(\"Access-Control-Allow-Headers: X-Requested-With\");\r\n// }\r\n// add_action('init', 'allow_cross_domain_requests');\r\n\r\n// Settings and Deactivation Links - Ver - 1.5.0\r\nif (!function_exists('enqueue_jquery_ui')) {\r\n function enqueue_jquery_ui() {\r\n wp_enqueue_style('wp-jquery-ui-dialog');\r\n wp_enqueue_script('jquery-ui-dialog');\r\n }\r\n add_action( 'admin_enqueue_scripts', 'enqueue_jquery_ui' );\r\n}\r\n\r\n// Schedule Cleanup of Expired Transients\r\nif (!wp_next_scheduled('chatbot_chatgpt_cleanup_event')) {\r\n wp_schedule_event(time(), 'daily', 'chatbot_chatgpt_cleanup_event');\r\n}\r\nadd_action('chatbot_chatgpt_cleanup_event', 'clean_specific_expired_transients');\r\n\r\n// Schedule Conversation Log Cleanup - Ver 1.6.7\r\nif (!wp_next_scheduled('chatbot_chatgpt_conversation_log_cleanup_event')) {\r\n wp_schedule_event(time(), 'daily', 'chatbot_chatgpt_conversation_log_cleanup_event');\r\n}\r\nadd_action('chatbot_chatgpt_conversation_log_cleanup_event', 'chatbot_chatgpt_conversation_log_cleanup');\r\n\r\n// Schedule the transcript file cleanup event if it's not already scheduled - Ver 1.9.9\r\n// Schedule the cleanup event if it's not already scheduled\r\nif (!wp_next_scheduled('chatbot_chatgpt_cleanup_transcript_files')) {\r\n wp_schedule_event(time(), 'hourly', 'chatbot_chatgpt_cleanup_transcript_files');\r\n}\r\n\r\n// Deactivate old hooks - Ver 2.0.1\r\nif(esc_attr(get_option('chatbot_chatgpt_cleanup_old_hooks') !== 'Completed')) {\r\n // Deactivate old hooks - Ver 2.0.1\r\n wp_clear_scheduled_hook('chatbot_chatgpt_cleanup_transcripts');\r\n // Then update the option\r\n update_option('chatbot_chatgpt_cleanup_old_hooks', 'Completed');\r\n}\r\n\r\n// Schedule the audio file cleanup event if it's not already scheduled - Ver 1.9.9\r\n// Schedule the cleanup event if it's not already scheduled\r\nif (!wp_next_scheduled('chatbot_chatgpt_cleanup_audio_files')) {\r\n wp_schedule_event(time(), 'hourly', 'chatbot_chatgpt_cleanup_audio_files');\r\n}\r\n\r\n// Schedule the upload file cleanup event if it's not already scheduled - Ver 1.9.9\r\n// Schedule the cleanup event if it's not already scheduled\r\nif (!wp_next_scheduled('chatbot_chatgpt_cleanup_upload_files')) {\r\n wp_schedule_event(time(), 'hourly', 'chatbot_chatgpt_cleanup_upload_files');\r\n}\r\n\r\n// Schedule the download file cleanup event if it's not already scheduled - Ver 2.0.3\r\n// Schedule the cleanup event if it's not already scheduled\r\nif (!wp_next_scheduled('chatbot_chatgpt_cleanup_download_files')) {\r\n wp_schedule_event(time(), 'hourly', 'chatbot_chatgpt_cleanup_download_files');\r\n}\r\n\r\n// Add the Assistant table to the database - Ver 2.0.4\r\ncreate_chatbot_chatgpt_assistants_table();\r\n\r\n// Handle Ajax requests\r\nfunction chatbot_chatgpt_send_message() {\r\n\r\n // Global variables\r\n global $session_id;\r\n global $user_id;\r\n global $page_id;\r\n global $thread_id;\r\n global $assistant_id;\r\n global $chatbot_chatgpt_assistant_alias;\r\n global $kchat_settings;\r\n global $additional_instructions;\r\n global $model;\r\n global $voice;\r\n\r\n global $flow_data;\r\n\r\n $api_key = '';\r\n\r\n // Retrieve the API key\r\n $api_key = esc_attr(get_option('chatbot_chatgpt_api_key'));\r\n\r\n // FIXME - STILL NEEDED - Ver 2.0.7 - 2024 07 25\r\n // Retrieve the GPT Model\r\n if (!empty($model)) {\r\n $model = esc_attr(get_option('chatbot_chatgpt_model_choice', 'gpt-3.5-turbo'));\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Model from options: ' . $model);\r\n } else {\r\n // SEE IF $kchat_settings HAS THE MODEL\r\n if ( isset($kchat_settings['model'])) {\r\n $model = $kchat_settings['model'];\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Model set in global: ' . $model);\r\n } else {\r\n // Set the model to the default\r\n $model = esc_attr(get_option('chatbot_chatgpt_model_choice', 'gpt-3.5-turbo'));\r\n // DIAG - Diagnostics\r\n // back_trace( 'ERROR', 'Invalid Model.');\r\n // wp_send_json_error('Error: Invalid Model. Please check the plugin settings.');\r\n }\r\n }\r\n\r\n // Send only clean text via the API\r\n $message = sanitize_text_field($_POST['message']);\r\n\r\n // Check for missing API key or Message\r\n if (!$api_key || !$message) {\r\n // DIAG - Diagnostics\r\n // back_trace( 'ERROR', 'Invalid API Key or Message.');\r\n wp_send_json_error('Error: Invalid API key or Message. Please check the plugin settings.');\r\n }\r\n\r\n // Removed in Ver 1.8.6 - 2024 02 15\r\n // $thread_id = '';\r\n // $assistant_id = '';\r\n // $user_id = '';\r\n // $page_id = '';\r\n \r\n // Check the transient for the Assistant ID - Ver 1.7.2\r\n // $user_id = intval($_POST['user_id']); // REMOVED intval in Ver 2.0.8\r\n // $page_id = intval($_POST['page_id']); // REMOVED intval in Ver 2.0.8\r\n $user_id = $_POST['user_id'];\r\n $page_id = $_POST['page_id'];\r\n $session_id = $_POST['session_id'];\r\n\r\n // DIAG - Diagnostics - Ver 1.8.6\r\n // back_trace( 'NOTICE', '$user_id: ' . $user_id);\r\n // back_trace( 'NOTICE', '$page_id: ' . $page_id);\r\n // back_trace( 'NOTICE', '$session_id: ' . $session_id);\r\n\r\n $kchat_settings['chatbot_chatgpt_display_style'] = get_chatbot_chatgpt_transients( 'display_style', $user_id, $page_id, $session_id);\r\n $kchat_settings['chatbot_chatgpt_assistant_alias'] = get_chatbot_chatgpt_transients( 'assistant_alias', $user_id, $page_id, $session_id);\r\n $kchat_settings['assistant_id'] = get_chatbot_chatgpt_transients( 'assistant_id', $user_id, $page_id, $session_id);\r\n $kchat_settings['thread_id'] = get_chatbot_chatgpt_transients( 'thread_id', $user_id, $page_id, $session_id);\r\n $kchat_settings['chatbot_chatgpt_model'] = get_chatbot_chatgpt_transients( 'model', $user_id, $page_id, $session_id);\r\n $kchat_settings['chatbot_chatgpt_voice_option'] = get_chatbot_chatgpt_transients( 'voice', $user_id, $page_id, $session_id);\r\n $kchat_settings['additional_instructions'] = get_chatbot_chatgpt_transients( 'additional_instructions', $user_id, $page_id, $session_id);\r\n $voice = $kchat_settings['chatbot_chatgpt_voice_option'];\r\n $model = $kchat_settings['chatbot_chatgpt_model'];\r\n $additional_instructions = $kchat_settings['additional_instructions'];\r\n $chatbot_chatgpt_assistant_alias = $kchat_settings['chatbot_chatgpt_assistant_alias'];\r\n\r\n // Get the thread information - Ver 2.0.7\r\n $thread_id = get_chatbot_chatgpt_threads($user_id, $session_id, $page_id, $assistant_id);\r\n $kchat_settings['thread_id'] = $thread_id;\r\n // $kchat_settings = array_merge($kchat_settings, get_chatbot_chatgpt_threads($user_id, $page_id));\r\n\r\n $assistant_id = isset($kchat_settings['assistant_id']) ? $kchat_settings['assistant_id'] : '';\r\n $thread_Id = isset($kchat_settings['thread_id']) ? $kchat_settings['thread_id'] : '';\r\n $model = isset($kchat_settings['chatbot_chatgpt_model']) ? $kchat_settings['chatbot_chatgpt_model'] : '';\r\n $voice = isset($kchat_settings['chatbot_chatgpt_voice_option']) ? $kchat_settings['chatbot_chatgpt_voice_option'] : '';\r\n\r\n // DIAG - Diagnostics - Ver 1.8.6\r\n // back_trace( 'NOTICE', '========================================');\r\n // back_trace( 'NOTICE', '$user_id: ' . $user_id);\r\n // back_trace( 'NOTICE', '$page_id: ' . $page_id);\r\n // back_trace( 'NOTICE', '$session_id: ' . $session_id);\r\n // back_trace( 'NOTICE', '$thread_id: ' . $thread_id);\r\n // back_trace( 'NOTICE', '$assistant_id: ' . $assistant_id);\r\n // back_trace( 'NOTICE', '$chatbot_chatgpt_assistant_alias: ' . $chatbot_chatgpt_assistant_alias);\r\n // back_trace( 'NOTICE', '$model: ' . $model);\r\n // back_trace( 'NOTICE', '$voice: ' . $voice);\r\n // DIAG - Diagnostics - Ver 2.0.9\r\n // back_trace( 'NOTICE', '========================================');\r\n // foreach ($kchat_settings as $key => $value) {\r\n // back_trace( 'NOTICE', '$kchat_settings[' . $key . ']: ' . $value);\r\n // }\r\n\r\n // Assistants\r\n // $chatbot_chatgpt_assistant_alias == 'original'; // Default\r\n // $chatbot_chatgpt_assistant_alias == 'primary';\r\n // $chatbot_chatgpt_assistant_alias == 'alternate';\r\n // $chatbot_chatgpt_assistant_alias == 'asst_xxxxxxxxxxxxxxxxxxxxxxxx'; // GPT Assistant Id\r\n \r\n // Which Assistant ID to use - Ver 1.7.2\r\n if ($chatbot_chatgpt_assistant_alias == 'original') {\r\n\r\n $use_assistant_id = 'No';\r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE' , 'Using Original ChatGPT - $chatbot_chatgpt_assistant_alias: ' . $chatbot_chatgpt_assistant_alias);\r\n\r\n } elseif ($chatbot_chatgpt_assistant_alias == 'primary') {\r\n\r\n $assistant_id = esc_attr(get_option('assistant_id'));\r\n // $additional_instructions = esc_attr(get_option('chatbot_chatgpt_assistant_instructions', '')); // REMOVED VER 2.0.9\r\n $use_assistant_id = 'Yes';\r\n\r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE' , 'Using Primary Assistant - $assistant_id: ' . $assistant_id);\r\n \r\n // Check if the GPT Assistant ID is blank, null, or \"Please provide the GPT Assistant ID.\"\r\n if (empty($assistant_id) || $assistant_id == \"Please provide the GPT Assistant Id.\") {\r\n \r\n // Primary assistant_id not set\r\n $chatbot_chatgpt_assistant_alias = 'original';\r\n $use_assistant_id = 'No';\r\n \r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE' ,'Falling back to ChatGPT API - $assistant_id: ' . $assistant_id );\r\n }\r\n\r\n } elseif ($chatbot_chatgpt_assistant_alias == 'alternate') {\r\n\r\n $assistant_id = esc_attr(get_option('chatbot_chatgpt_assistant_id_alternate'));\r\n // $additional_instructions = esc_attr(get_option('chatbot_chatgpt_assistant_instructions_alternate', '')); // REMOVED VER 2.0.9\r\n $use_assistant_id = 'Yes';\r\n\r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE' , 'Using Altrnate Assistant - $assistant_id: ' . $assistant_id);\r\n\r\n // Check if the GPT Assistant ID is blank, null, or \"Please provide the GPT Assistant ID.\"\r\n if (empty($assistant_id) || $assistant_id == \"Please provide the GPT Assistant Id.\") {\r\n\r\n /// Alternate assistant_id not set\r\n $chatbot_chatgpt_assistant_alias = 'original';\r\n $use_assistant_id = 'No';\r\n\r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE' ,'Falling back to ChatGPT API - $assistant_id: ' . $assistant_id );\r\n \r\n }\r\n\r\n } elseif (str_starts_with($assistant_id, 'asst_')) {\r\n\r\n $chatbot_chatgpt_assistant_alias = $assistant_id; // Belt & Suspenders\r\n $use_assistant_id = 'Yes';\r\n\r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE' ,'Assistant ID pass as a parameter - $assistant_id: ' . $assistant_id );\r\n\r\n } else {\r\n\r\n // Reference GPT Assistant IDs directly - Ver 1.7.3\r\n if (str_starts_with($chatbot_chatgpt_assistant_alias, 'asst_')) {\r\n\r\n // DIAG - Diagnostics - 2.0.5\r\n // back_trace( 'NOTICE', 'Using GPT Assistant ID: ' . $chatbot_chatgpt_assistant_alias);\r\n\r\n // Override the $assistant_id with the GPT Assistant ID\r\n $assistant_id = $chatbot_chatgpt_assistant_alias;\r\n $use_assistant_id = 'Yes';\r\n\r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE' , 'Using $assistant_id ' . $assistant_id);\r\n\r\n } else {\r\n\r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE', 'Using ChatGPT API: ' . $chatbot_chatgpt_assistant_alias);\r\n\r\n // Override the $use_assistant_id and set it to 'No'\r\n $use_assistant_id = 'No';\r\n \r\n // DIAG - Diagnostics - Ver 1.8.1\r\n // back_trace( 'NOTICE' , 'Falling back to ChatGPT API');\r\n\r\n }\r\n\r\n }\r\n\r\n // Get any additional instructions - Ver 2.0.9\r\n $additional_instructions = get_chatbot_chatgpt_transients( 'additional_instructions', $user_id, $page_id, $session_id);\r\n\r\n // Decide whether to use Flow, Assistant or Original ChatGPT\r\n if ($model == 'flow'){\r\n \r\n // DIAG - Diagnostics - Ver 2.1.1.1\r\n // back_trace( 'NOTICE', 'Using ChatGPT Flow');\r\n // back_trace( 'NOTICE', '$user_id ' . $user_id);\r\n // back_trace( 'NOTICE', '$page_id ' . $page_id);\r\n\r\n // Reload the model - BELT & SUSPENDERS\r\n $kchat_settings['model'] = $model;\r\n\r\n // Get the step from the transient\r\n $kflow_step = get_chatbot_chatgpt_transients( 'kflow_step', null, null, $session_id);\r\n if (empty($kflow_step)) {\r\n $kflow_step = 0; // FIXME - Set to 1 or to zero?\r\n }\r\n\r\n // $thread_id\r\n $thread_id = '[answer=' . $kflow_step + 1 . ']';\r\n \r\n // Add +1 to $kchat_settings['next_step']\r\n $kflow_step = $kflow_step + 1;\r\n\r\n // Set the next step\r\n set_chatbot_chatgpt_transients( 'kflow_step', $kflow_step, null, null, $session_id);\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', '$message: ' . $message);\r\n $thread_id = get_chatbot_chatgpt_threads($user_id, $session_id, $page_id, $assistant_id);\r\n // back_trace( 'NOTICE', '$thread_id ' . $thread_id);\r\n append_message_to_conversation_log($session_id, $user_id, $page_id, 'Visitor', $thread_id, $assistant_id, $message);\r\n\r\n // BELT & SUSPENDERS\r\n $thread_id = '';\r\n\r\n // Send message to ChatGPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_call_flow_api($api_key, $message);\r\n\r\n wp_send_json_success($response);\r\n\r\n } elseif ($use_assistant_id == 'Yes') {\r\n\r\n // DIAG - Diagnostics - Ver 2.1.1.1\r\n // back_trace( 'NOTICE', 'Using GPT Assistant ID: ' . $use_assistant_id);\r\n // back_trace( 'NOTICE', '$user_id ' . $user_id);\r\n // back_trace( 'NOTICE', '$page_id ' . $page_id);\r\n // back_trace( 'NOTICE', '$message ' . $message);\r\n\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', '$message ' . $message);\r\n $thread_id = get_chatbot_chatgpt_threads($user_id, $session_id, $page_id, $assistant_id);\r\n // back_trace( 'NOTICE', '$thread_id ' . $thread_id);\r\n append_message_to_conversation_log($session_id, $user_id, $page_id, 'Visitor', $thread_id, $assistant_id, $message);\r\n\r\n // DIAG - Diagnostics - Ver 2.0.9\r\n // back_trace( 'NOTICE', '========================================');\r\n // back_trace( 'NOTICE', 'BEFORE CALL TO MODULE $additional_instructions: ' . $additional_instructions);\r\n\r\n // Send message to Custom GPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_custom_gpt_call_api($api_key, $message, $assistant_id, $thread_id, $session_id, $user_id, $page_id);\r\n\r\n // Use TF-IDF to enhance response\r\n $chatbot_chatgpt_suppress_learnings = esc_attr(get_option('chatbot_chatgpt_suppress_learnings', 'Random'));\r\n if ( $chatbot_chatgpt_suppress_learnings != 'None') {\r\n $response = $response . chatbot_chatgpt_enhance_with_tfidf($message);\r\n }\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', '$response ' . print_r($response,true));\r\n $thread_id = get_chatbot_chatgpt_threads($user_id, $session_id, $page_id, $assistant_id);\r\n // back_trace( 'NOTICE', '$thread_id ' . $thread_id);\r\n append_message_to_conversation_log($session_id, $user_id, $page_id, 'Chatbot', $thread_id, $assistant_id, $response);\r\n\r\n // Clean (erase) the output buffer - Ver 1.6.8\r\n // Check if output buffering is active before attempting to clean it\r\n if (ob_get_level() > 0) {\r\n ob_clean();\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Output buffer cleaned');\r\n } else {\r\n // Optionally start output buffering if needed for your application\r\n // ob_start();\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Output buffer not cleaned');\r\n }\r\n\r\n if (str_starts_with($response, 'Error:') || str_starts_with($response, 'Failed:')) {\r\n // Return response\r\n // back_trace( 'NOTICE', '$response ' . print_r($response,true));\r\n wp_send_json_error('Oops! Something went wrong on our end. Please try again later!');\r\n } else {\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Check for links and images in response before returning');\r\n $response = chatbot_chatgpt_check_for_links_and_images($response);\r\n\r\n // FIXME - Append extra message - Ver 2.1.1.1.1\r\n // Danger Will Robinson! Danger!\r\n $extra_message = esc_attr(get_option('chatbot_chatgpt_extra_message', ''));\r\n $response = chatbot_chatgpt_append_extra_message($response, $extra_message);\r\n\r\n // Return response\r\n wp_send_json_success($response);\r\n }\r\n\r\n } else {\r\n\r\n // DIAG - Diagnostics - Ver 2.1.1.1\r\n // back_trace( 'NOTICE', 'Using ChatGPT');\r\n // back_trace( 'NOTICE', '$user_id ' . $user_id);\r\n // back_trace( 'NOTICE', '$page_id ' . $page_id);\r\n // back_trace( 'NOTICE', '$message ' . $message);\r\n\r\n $thread_id = get_chatbot_chatgpt_threads($user_id, $session_id, $page_id, $assistant_id);\r\n // back_trace( 'NOTICE', '$thread_id ' . $thread_id);\r\n append_message_to_conversation_log($session_id, $user_id, $page_id, 'Visitor', $thread_id, $assistant_id, $message);\r\n \r\n // If $model starts with 'gpt' then the chatbot_chatgpt_call_api or 'dall' then chatbot_chatgpt_call_image_api\r\n // TRY NOT TO FETCH MODEL AGAIN\r\n // $model = esc_attr(get_option('chatbot_chatgpt_model_choice', 'gpt-3.5-turbo'));\r\n $model = isset($kchat_settings['model']) ? $kchat_settings['model'] : null;\r\n $voice = isset($kchat_settings['voice']) ? $kchat_settings['voice'] : null;\r\n if (str_starts_with($model !== null && $model, 'gpt-4o') !== false) {\r\n // The string 'gpt-4o' is found in $model\r\n // Reload the model - BELT & SUSPENDERS\r\n $kchat_settings['model'] = $model;\r\n // Send message to ChatGPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_call_omni($api_key, $message);\r\n } elseif ($model !== null && str_starts_with($model, 'gpt')) {\r\n // Reload the model - BELT & SUSPENDERS\r\n $kchat_settings['model'] = $model;\r\n // Send message to ChatGPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_call_api($api_key, $message);\r\n } elseif ($model !== null && str_starts_with($model, 'dall')) {\r\n // Reload the model - BELT & SUSPENDERS\r\n $kchat_settings['model'] = $model;\r\n // Send message to Image API - Ver 1.9.4\r\n $response = chatbot_chatgpt_call_image_api($api_key, $message);\r\n } elseif ($model !== null && str_starts_with($model, 'tts')) {\r\n // Reload the model - BELT & SUSPENDERS\r\n $kchat_settings['model'] = $model;\r\n $kchat_settings['voice'] = $voice;\r\n // Send message to TTS API - Text-to-speech - Ver 1.9.5\r\n $response = chatbot_chatgpt_call_tts_api($api_key, $message, $voice, $user_id, $page_id, $session_id);\r\n } elseif ($model !== null && str_starts_with($model,'whisper')) {\r\n $kchat_settings['model'] = $model;\r\n // Send message to STT API - Speech-to-text - Ver 1.9.6\r\n $response = chatbot_chatgpt_call_stt_api($api_key, $message);\r\n } else {\r\n // Reload the model - BELT & SUSPENDERS\r\n $kchat_settings['model'] = $model;\r\n // Send message to ChatGPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_call_api($api_key, $message);\r\n }\r\n \r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', ['message' => 'BEFORE CALL TO ENHANCE TFIDF', 'response' => $response]);\r\n \r\n // Use TF-IDF to enhance response\r\n $chatbot_chatgpt_suppress_learnings = esc_attr(get_option('chatbot_chatgpt_suppress_learnings', 'Random'));\r\n if ( $chatbot_chatgpt_suppress_learnings != 'None') {\r\n $response = $response . chatbot_chatgpt_enhance_with_tfidf($message);\r\n }\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', ['message' => 'AFTER CALL TO ENHANCE TFIDF', 'response' => $response]);\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', '$response ' . print_r($response,true));\r\n $thread_id = get_chatbot_chatgpt_threads($user_id, $session_id, $page_id, $assistant_id);\r\n // back_trace( 'NOTICE', '$thread_id ' . $thread_id);\r\n append_message_to_conversation_log($session_id, $user_id, $page_id, 'Chatbot', $thread_id, $assistant_id, $response);\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Check for links and images in response before returning');\r\n $response = chatbot_chatgpt_check_for_links_and_images($response);\r\n\r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE', 'Response: ' . $response);\r\n\r\n // FIXME - Append extra message - Ver 2.1.1.1.1\r\n // Danger Will Robinson! Danger!\r\n $extra_message = esc_attr(get_option('chatbot_chatgpt_extra_message', ''));\r\n $response = chatbot_chatgpt_append_extra_message($response, $extra_message);\r\n\r\n // Return response\r\n wp_send_json_success($response);\r\n\r\n }\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'ERROR', 'Oops! I fell through the cracks!');\r\n wp_send_json_error('Oops! I fell through the cracks!');\r\n\r\n}\r\n\r\n// Add action to send messages - Ver 1.0.0\r\nadd_action('wp_ajax_chatbot_chatgpt_send_message', 'chatbot_chatgpt_send_message');\r\nadd_action('wp_ajax_nopriv_chatbot_chatgpt_send_message', 'chatbot_chatgpt_send_message');\r\n\r\n// Add action to upload files - Ver 1.7.6\r\nadd_action('wp_ajax_chatbot_chatgpt_upload_files', 'chatbot_chatgpt_upload_files');\r\nadd_action('wp_ajax_nopriv_chatbot_chatgpt_upload_files', 'chatbot_chatgpt_upload_files');\r\n\r\n// Add action to upload files - Ver 1.7.6\r\nadd_action('wp_ajax_chatbot_chatgpt_upload_mp3', 'chatbot_chatgpt_upload_mp3');\r\nadd_action('wp_ajax_nopriv_chatbot_chatgpt_upload_mp3', 'chatbot_chatgpt_upload_mp3');\r\n\r\n// Add action to erase conversation - Ver 1.8.6\r\nadd_action('wp_ajax_chatbot_chatgpt_erase_conversation', 'chatbot_chatgpt_erase_conversation_handler');\r\nadd_action('wp_ajax_nopriv_chatbot_chatgpt_erase_conversation', 'chatbot_chatgpt_erase_conversation_handler'); // For logged-out users, if needed\r\n\r\n// Settings and Deactivation - Ver 1.5.0\r\nadd_filter('plugin_action_links_' . plugin_basename(__FILE__), 'chatbot_chatgpt_plugin_action_links');\r\n\r\n// Append an extra message to the response - Ver 2.0.9\r\nfunction chatbot_chatgpt_append_extra_message($response, $extra_message) {\r\n\r\n // Append the extra message to the response\r\n $response = $response . ' ' . $extra_message;\r\n return $response;\r\n\r\n}\r\n\r\n// Crawler aka Knowledge Navigator - Ver 1.6.1\r\nfunction chatbot_chatgpt_kn_status_activation() {\r\n add_option('chatbot_chatgpt_kn_status', 'Never Run');\r\n // clear any old scheduled runs\r\n if (wp_next_scheduled('crawl_scheduled_event_hook')) {\r\n wp_clear_scheduled_hook('crawl_scheduled_event_hook');\r\n }\r\n // clear the 'knowledge_navigator_scan_hook' hook on plugin activation - Ver 1.6.3\r\n if (wp_next_scheduled('knowledge_navigator_scan_hook')) {\r\n // BREAK/FIX - Do not unset the hook - Ver 1.8.5\r\n // wp_clear_scheduled_hook('knowledge_navigator_scan_hook'); // Clear scheduled runs\r\n }\r\n}\r\nregister_activation_hook(__FILE__, 'chatbot_chatgpt_kn_status_activation');\r\n\r\n// Clean Up in Aisle 4\r\nfunction chatbot_chatgpt_kn_status_deactivation() {\r\n delete_option('chatbot_chatgpt_kn_status');\r\n wp_clear_scheduled_hook('knowledge_navigator_scan_hook'); \r\n}\r\nregister_deactivation_hook(__FILE__, 'chatbot_chatgpt_kn_status_deactivation');\r\n\r\n// Function to add a new message and response, keeping only the last five - Ver 1.6.1\r\nfunction addEntry($transient_name, $newEntry) {\r\n\r\n $context_history = get_transient($transient_name);\r\n if (!$context_history) {\r\n $context_history = [];\r\n }\r\n\r\n // Determine the total length of all existing entries\r\n $totalLength = 0;\r\n foreach ($context_history as $entry) {\r\n if (is_string($entry)) {\r\n $totalLength += strlen($entry);\r\n } elseif (is_array($entry)) {\r\n $totalLength += strlen(json_encode($entry)); // Convert to string if an array\r\n }\r\n }\r\n\r\n // IDEA - How will the new threading option from OpenAI change how this works?\r\n // Define thresholds for the number of entries to keep\r\n $maxEntries = 30; // Default maximum number of entries\r\n if ($totalLength > 5000) { // Higher threshold\r\n $maxEntries = 20;\r\n }\r\n if ($totalLength > 10000) { // Lower threshold\r\n $maxEntries = 10;\r\n }\r\n\r\n while (count($context_history) >= $maxEntries) {\r\n array_shift($context_history); // Remove the oldest element\r\n }\r\n\r\n if (is_array($newEntry)) {\r\n $newEntry = json_encode($newEntry); // Convert the array to a string\r\n }\r\n\r\n array_push($context_history, $newEntry); // Append the new element\r\n set_transient($transient_name, $context_history); // Update the transient\r\n}\r\n\r\n// Function to return message and response - Ver 1.6.1\r\nfunction concatenateHistory($transient_name) {\r\n $context_history = get_transient($transient_name);\r\n if (!$context_history) {\r\n return ''; // Return an empty string if the transient does not exist\r\n }\r\n return implode(' ', $context_history); // Concatenate the array values into a single string\r\n}\r\n\r\n// FIXME - MOVE CORE FUNCTIONS TO A SEPARATE FILE, LEAVING ONLY THE HOOKS HERE\r\n// Initialize the Greetings - Ver 1.6.1\r\nfunction enqueue_greetings_script( $initial_greeting = null, $subsequent_greeting = null) {\r\n\r\n // If user is logged in, then modify greeting if greeting contains \"[...]\" or remove if not logged in - Ver 1.9.4\r\n if (is_user_logged_in()) {\r\n\r\n $current_user_id = get_current_user_id();\r\n $current_user = get_userdata($current_user_id);\r\n\r\n //Do this for Initial Greeting\r\n if ( empty($initial_greeting) ) {\r\n $initial_greeting = esc_attr(get_option('chatbot_chatgpt_initial_greeting', 'Hello! How can I help you today?'));\r\n }\r\n\r\n // Determine what the field name is between the brackets\r\n $user_field_name = '';\r\n $user_field_name = substr($initial_greeting, strpos($initial_greeting, '[') + 1, strpos($initial_greeting, ']') - strpos($initial_greeting, '[') - 1);\r\n // If $initial_greeting contains \"[$user_field_name]\" then replace with field from DB\r\n if (strpos($initial_greeting, '[' . $user_field_name . ']') !== false) {\r\n $initial_greeting = str_replace('[' . $user_field_name . ']', $current_user->$user_field_name, $initial_greeting);\r\n } else {\r\n $initial_greeting = str_replace('[' . $user_field_name . ']', '', $initial_greeting);\r\n // Remove the extra space when two spaces are present\r\n $initial_greeting = str_replace(' ', ' ', $initial_greeting);\r\n // Remove the extra space before punctuation including period, comma, exclamation mark, and question mark\r\n $initial_greeting = preg_replace('/\\s*([.,!?])/', '$1', $initial_greeting);\r\n }\r\n\r\n // Do this for Subsequent Greeting\r\n if ( empty($subsequent_greeting) ) {\r\n $subsequent_greeting = esc_attr(get_option('chatbot_chatgpt_subsequent_greeting', 'Hello again! How can I help you?'));\r\n }\r\n\r\n // Determine what the field name is between the brackets\r\n $user_field_name = '';\r\n $user_field_name = substr($subsequent_greeting, strpos($subsequent_greeting, '[') + 1, strpos($subsequent_greeting, ']') - strpos($subsequent_greeting, '[') - 1);\r\n // If $subsequent_greeting contains \"[$user_field_name]\" then replace with field from DB\r\n if (strpos($subsequent_greeting, '[' . $user_field_name . ']') !== false) {\r\n $subsequent_greeting = str_replace('[' . $user_field_name . ']', $current_user->$user_field_name, $subsequent_greeting);\r\n } else {\r\n $subsequent_greeting = str_replace('[' . $user_field_name . ']', '', $subsequent_greeting);\r\n // Remove the extra space when two spaces are present\r\n $subsequent_greeting = str_replace(' ', ' ', $subsequent_greeting);\r\n // Remove the extra space before punctuation including period, comma, exclamation mark, and question mark\r\n $subsequent_greeting = preg_replace('/\\s*([.,!?])/', '$1', $subsequent_greeting);\r\n }\r\n\r\n } else {\r\n\r\n //Do this for Initial Greeting\r\n if ( empty($initial_greeting) ) {\r\n $initial_greeting = esc_attr(get_option('chatbot_chatgpt_initial_greeting', 'Hello! How can I help you today?'));\r\n }\r\n\r\n $user_field_name = '';\r\n $user_field_name = substr($initial_greeting, strpos($initial_greeting, '[') + 1, strpos($initial_greeting, ']') - strpos($initial_greeting, '[') - 1 );\r\n\r\n // $initial_greeting = preg_replace('/\\s*\\[' . preg_quote($user_field_name, '/') . '\\]\\s*/', '', $initial_greeting);\r\n $initial_greeting = str_replace('[' . $user_field_name . ']', '', $initial_greeting);\r\n // Remove the extra space when two spaces are present\r\n $initial_greeting = str_replace(' ', ' ', $initial_greeting);\r\n // Remove the extra space before punctuation including period, comma, exclamation mark, and question mark\r\n $initial_greeting = preg_replace('/\\s*([.,!?])/', '$1', $initial_greeting);\r\n\r\n //Do this for Subsequent Greeting\r\n if ( empty($subsequent_greeting) ) {\r\n $subsequent_greeting = esc_attr(get_option('chatbot_chatgpt_subsequent_greeting', 'Hello again! How can I help you?'));\r\n }\r\n\r\n $user_field_name = '';\r\n $user_field_name = substr($subsequent_greeting, strpos($subsequent_greeting, '[') + 1, strpos($subsequent_greeting, ']') - strpos($subsequent_greeting, '[') - 1);\r\n\r\n // $subsequent_greeting = preg_replace('/\\s*\\[' . preg_quote($user_field_name, '/') . '\\]\\s*/', '', $subsequent_greeting);\r\n $subsequent_greeting = str_replace('[' . $user_field_name . ']', '', $subsequent_greeting);\r\n // Remove the extra space when two spaces are present\r\n $subsequent_greeting = str_replace(' ', ' ', $subsequent_greeting);\r\n // Remove the extra space before punctuation including period, comma, exclamation mark, and question mark\r\n $subsequent_greeting = preg_replace('/\\s*([.,!?])/', '$1', $subsequent_greeting);\r\n \r\n }\r\n\r\n $greetings = array(\r\n 'initial_greeting' => $initial_greeting,\r\n 'subsequent_greeting' => $subsequent_greeting,\r\n );\r\n\r\n return $greetings;\r\n\r\n}\r\n// \r\nadd_action('wp_enqueue_scripts', 'enqueue_greetings_script');\r\n\r\n// Add the color picker to the adaptive appearance settings section - Ver 1.8.1\r\nfunction enqueue_color_picker($hook_suffix) {\r\n\r\n global $chatbot_chatgpt_plugin_version;\r\n\r\n // first check that $hook_suffix is appropriate for your admin page\r\n wp_enqueue_style('wp-color-picker');\r\n wp_enqueue_script('my-script-handle', plugin_dir_url(__FILE__) . 'assets/js/chatbot-chatgpt-color-picker.js', array('wp-color-picker'), $chatbot_chatgpt_plugin_version, true);\r\n\r\n}\r\nadd_action('admin_enqueue_scripts', 'enqueue_color_picker');\r\n\r\n// Determine if the plugin is installed\r\nfunction kchat_get_plugin_version() {\r\n\r\n global $chatbot_chatgpt_plugin_version;\r\n\r\n if (!function_exists('get_plugin_data')) {\r\n require_once(ABSPATH . 'wp-admin/includes/plugin.php');\r\n }\r\n\r\n // $plugin_data = get_plugin_data(plugin_dir_path(__FILE__) . 'chatbot-chatgpt.php');\r\n // $plugin_version = $plugin_data['chatbot_chatgpt_version'];\r\n $plugin_version = $chatbot_chatgpt_plugin_version;\r\n update_option('chatbot_chatgpt_plugin_version', $plugin_version);\r\n // DIAG - Log the plugin version\r\n // back_trace( 'NOTICE', 'Plugin version ' . $plugin_version);\r\n\r\n return $plugin_version;\r\n\r\n}\r\n"}, "53a4485ab6439d52457c55fb665257cade49b168": {"t": 1785756413.4845326, "n": 54646, "h": "70bdf3881d6658d4", "c": " $user_id,\r\n 'page_id' => $page_id,\r\n 'session_id' => $session_id,\r\n 'thread_id' => $thread_id,\r\n 'assistant_id' => $assistant_id,\r\n 'additional_instructions' => $additional_instructions,\r\n 'model' => $model,\r\n 'voice' => $voice,\r\n ));\r\n\r\n // DIAG - Diagnostics - Ver 1.8.6\r\n // back_trace( 'NOTICE', '$user_id: ' . $user_id);\r\n // back_trace( 'NOTICE', '$page_id: ' . $page_id);\r\n // back_trace( 'NOTICE', '$session_id: ' . $session_id);\r\n // back_trace( 'NOTICE', '$thread_id: ' . $thread_id);\r\n // back_trace( 'NOTICE', '$assistant_id: ' . $assistant_id);\r\n // back_trace( 'NOTICE', '$additional_instructions: ' . $additional_instructions);\r\n // back_trace( 'NOTICE', '$model: ' . $model);\r\n \r\n // Set visitor and logged in user limits - Ver 2.0.1\r\n if (is_user_logged_in()) {\r\n // back_trace( 'NOTICE', 'User is logged in');\r\n $kchat_settings['chatbot_chatgpt_message_limit_setting'] = esc_attr(get_option('chatbot_chatgpt_message_limit_setting', '999'));\r\n } else {\r\n // back_trace( 'NOTICE', 'User is NOT logged in');\r\n $kchat_settings['chatbot_chatgpt_message_limit_setting'] = esc_attr(get_option('chatbot_chatgpt_visitor_message_limit_setting', '999'));\r\n }\r\n\r\n // Localize the data for the chatbot - Ver 2.1.1.1\r\n $kchat_settings = array_merge($kchat_settings, array(\r\n 'chatbot_chatgpt_display_style' => $chatbot_chatgpt_display_style,\r\n 'chatbot_chatgpt_version' => $chatbot_chatgpt_plugin_version,\r\n 'plugins_url' => $chatbot_chatgpt_plugin_dir_url,\r\n 'ajax_url' => admin_url('admin-ajax.php'),\r\n 'user_id' => $user_id,\r\n 'page_id' => $page_id,\r\n 'session_id' => $session_id,\r\n 'thread_id' => $thread_id,\r\n 'assistant_id' => $assistant_id,\r\n 'additional_instructions' => $additional_instructions,\r\n 'model' => $model,\r\n 'voice' => $voice,\r\n 'chatbot_chatgpt_timeout_setting' => esc_attr(get_option('chatbot_chatgpt_timeout_setting', '240')),\r\n 'chatbot_chatgpt_avatar_icon_setting' => esc_attr(get_option('chatbot_chatgpt_avatar_icon_setting', '')),\r\n 'chatbot_chatgpt_custom_avatar_icon_setting' => esc_attr(get_option('chatbot_chatgpt_custom_avatar_icon_setting', '')),\r\n '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?')),\r\n 'chatbot_chatgpt_force_page_reload' => esc_attr(get_option('chatbot_chatgpt_force_page_reload', 'No')),\r\n 'chatbot_chatgpt_custom_error_message' => esc_attr(get_option('chatbot_chatgpt_custom_error_message', 'Your custom error message goes here.')),\r\n 'chatbot_chatgpt_message_limit_setting' => esc_attr(get_option('chatbot_chatgpt_message_limit_setting', '999')),\r\n ));\r\n \r\n $kchat_settings_json = wp_json_encode($kchat_settings);\r\n\r\n // Enqueue the main chatbot script - CHANGED TO LOAD ORDER IN V2.1.2\r\n wp_enqueue_script('chatbot-chatgpt-js', plugins_url('assets/js/chatbot-chatgpt.js', __FILE__), array(), $chatbot_chatgpt_plugin_version, true);\r\n\r\n // Add the inline script to define kchat_settings before the main script runs - CHANGED THE LOAD ORDER IN VER 2.1.2\r\n 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');\r\n // FIXME - REMOVED IN V2.1.2\r\n // 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');\r\n\r\n}\r\nadd_action('wp_enqueue_scripts', 'chatbot_chatgpt_enqueue_scripts');\r\n\r\n// Enqueue MathJax with custom configuration - Ver 2.1.2\r\n// https://docs.mathjax.org/en/latest/\r\n// https://github.com/mathjax/MathJax/blob/master/LICENSE\r\n// https://cdnjs.cloudflare.com/ajax/libs/mathjax/3.2.0/es5/tex-mml-chtml.js\r\n// https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js\r\nfunction enqueue_mathjax_with_custom_config() {\r\n\r\n global $chatbot_chatgpt_plugin_version;\r\n global $chatbot_chatgpt_plugin_dir_url;\r\n\r\n // Add the MathJax configuration script\r\n $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 \";\r\n\r\n // Enqueue the MathJax script\r\n // wp_enqueue_script( 'mathjax', plugin_dir_url(__FILE__) . 'assets/js/tex-chtml.js', array(), $chatbot_chatgpt_plugin_version, true );\r\n wp_enqueue_script( 'mathjax', $chatbot_chatgpt_plugin_dir_url . 'assets/js/tex-mml-chtml.js', array(), $chatbot_chatgpt_plugin_version, true );\r\n\r\n // Add the inline script before MathJax script\r\n wp_add_inline_script( 'mathjax', $mathjax_config, 'before' );\r\n\r\n}\r\nadd_action( 'wp_enqueue_scripts', 'enqueue_mathjax_with_custom_config' );\r\n\r\n// CORS - Cross Origin Resource Sharing - CAUTION: This allows all domains to access the end point - Ver 2.1.2\r\n// function allow_cross_domain_requests() {\r\n// header(\"Access-Control-Allow-Origin: *\");\r\n// header(\"Access-Control-Allow-Methods: GET, POST, OPTIONS\");\r\n// header(\"Access-Control-Allow-Headers: X-Requested-With\");\r\n// }\r\n// add_action('init', 'allow_cross_domain_requests');\r\n\r\n// Settings and Deactivation Links - Ver - 1.5.0\r\nif (!function_exists('enqueue_jquery_ui')) {\r\n function enqueue_jquery_ui() {\r\n wp_enqueue_style('wp-jquery-ui-dialog');\r\n wp_enqueue_script('jquery-ui-dialog');\r\n }\r\n add_action( 'admin_enqueue_scripts', 'enqueue_jquery_ui' );\r\n}\r\n\r\n// Schedule Cleanup of Expired Transients\r\nif (!wp_next_scheduled('chatbot_chatgpt_cleanup_event')) {\r\n wp_schedule_event(time(), 'daily', 'chatbot_chatgpt_cleanup_event');\r\n}\r\nadd_action('chatbot_chatgpt_cleanup_event', 'clean_specific_expired_transients');\r\n\r\n// Schedule Conversation Log Cleanup - Ver 1.6.7\r\nif (!wp_next_scheduled('chatbot_chatgpt_conversation_log_cleanup_event')) {\r\n wp_schedule_event(time(), 'daily', 'chatbot_chatgpt_conversation_log_cleanup_event');\r\n}\r\nadd_action('chatbot_chatgpt_conversation_log_cleanup_event', 'chatbot_chatgpt_conversation_log_cleanup');\r\n\r\n// Schedule the transcript file cleanup event if it's not already scheduled - Ver 1.9.9\r\n// Schedule the cleanup event if it's not already scheduled\r\nif (!wp_next_scheduled('chatbot_chatgpt_cleanup_transcript_files')) {\r\n wp_schedule_event(time(), 'hourly', 'chatbot_chatgpt_cleanup_transcript_files');\r\n}\r\n\r\n// Deactivate old hooks - Ver 2.0.1\r\nif(esc_attr(get_option('chatbot_chatgpt_cleanup_old_hooks') !== 'Completed')) {\r\n // Deactivate old hooks - Ver 2.0.1\r\n wp_clear_scheduled_hook('chatbot_chatgpt_cleanup_transcripts');\r\n // Then update the option\r\n update_option('chatbot_chatgpt_cleanup_old_hooks', 'Completed');\r\n}\r\n\r\n// Schedule the audio file cleanup event if it's not already scheduled - Ver 1.9.9\r\n// Schedule the cleanup event if it's not already scheduled\r\nif (!wp_next_scheduled('chatbot_chatgpt_cleanup_audio_files')) {\r\n wp_schedule_event(time(), 'hourly', 'chatbot_chatgpt_cleanup_audio_files');\r\n}\r\n\r\n// Schedule the upload file cleanup event if it's not already scheduled - Ver 1.9.9\r\n// Schedule the cleanup event if it's not already scheduled\r\nif (!wp_next_scheduled('chatbot_chatgpt_cleanup_upload_files')) {\r\n wp_schedule_event(time(), 'hourly', 'chatbot_chatgpt_cleanup_upload_files');\r\n}\r\n\r\n// Schedule the download file cleanup event if it's not already scheduled - Ver 2.0.3\r\n// Schedule the cleanup event if it's not already scheduled\r\nif (!wp_next_scheduled('chatbot_chatgpt_cleanup_download_files')) {\r\n wp_schedule_event(time(), 'hourly', 'chatbot_chatgpt_cleanup_download_files');\r\n}\r\n\r\n// Add the Assistant table to the database - Ver 2.0.4\r\ncreate_chatbot_chatgpt_assistants_table();\r\n\r\n// Handle Ajax requests\r\nfunction chatbot_chatgpt_send_message() {\r\n\r\n // Global variables\r\n global $session_id;\r\n global $user_id;\r\n global $page_id;\r\n global $thread_id;\r\n global $assistant_id;\r\n global $chatbot_chatgpt_assistant_alias;\r\n global $kchat_settings;\r\n global $additional_instructions;\r\n global $model;\r\n global $voice;\r\n\r\n global $flow_data;\r\n\r\n $api_key = '';\r\n\r\n // Retrieve the API key\r\n $api_key = esc_attr(get_option('chatbot_chatgpt_api_key'));\r\n\r\n // FIXME - STILL NEEDED - Ver 2.0.7 - 2024 07 25\r\n // Retrieve the GPT Model\r\n if (!empty($model)) {\r\n $model = esc_attr(get_option('chatbot_chatgpt_model_choice', 'gpt-3.5-turbo'));\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Model from options: ' . $model);\r\n } else {\r\n // SEE IF $kchat_settings HAS THE MODEL\r\n if ( isset($kchat_settings['model'])) {\r\n $model = $kchat_settings['model'];\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Model set in global: ' . $model);\r\n } else {\r\n // Set the model to the default\r\n $model = esc_attr(get_option('chatbot_chatgpt_model_choice', 'gpt-3.5-turbo'));\r\n // DIAG - Diagnostics\r\n // back_trace( 'ERROR', 'Invalid Model.');\r\n // wp_send_json_error('Error: Invalid Model. Please check the plugin settings.');\r\n }\r\n }\r\n\r\n // Send only clean text via the API\r\n $message = sanitize_text_field($_POST['message']);\r\n\r\n // Check for missing API key or Message\r\n if (!$api_key || !$message) {\r\n // DIAG - Diagnostics\r\n // back_trace( 'ERROR', 'Invalid API Key or Message.');\r\n wp_send_json_error('Error: Invalid API key or Message. Please check the plugin settings.');\r\n }\r\n\r\n // Removed in Ver 1.8.6 - 2024 02 15\r\n // $thread_id = '';\r\n // $assistant_id = '';\r\n // $user_id = '';\r\n // $page_id = '';\r\n \r\n // Check the transient for the Assistant ID - Ver 1.7.2\r\n // $user_id = intval($_POST['user_id']); // REMOVED intval in Ver 2.0.8\r\n // $page_id = intval($_POST['page_id']); // REMOVED intval in Ver 2.0.8\r\n $user_id = $_POST['user_id'];\r\n $page_id = $_POST['page_id'];\r\n $session_id = $_POST['session_id'];\r\n\r\n // DIAG - Diagnostics - Ver 1.8.6\r\n // back_trace( 'NOTICE', '$user_id: ' . $user_id);\r\n // back_trace( 'NOTICE', '$page_id: ' . $page_id);\r\n // back_trace( 'NOTICE', '$session_id: ' . $session_id);\r\n\r\n $kchat_settings['chatbot_chatgpt_display_style'] = get_chatbot_chatgpt_transients( 'display_style', $user_id, $page_id, $session_id);\r\n $kchat_settings['chatbot_chatgpt_assistant_alias'] = get_chatbot_chatgpt_transients( 'assistant_alias', $user_id, $page_id, $session_id);\r\n $kchat_settings['assistant_id'] = get_chatbot_chatgpt_transients( 'assistant_id', $user_id, $page_id, $session_id);\r\n $kchat_settings['thread_id'] = get_chatbot_chatgpt_transients( 'thread_id', $user_id, $page_id, $session_id);\r\n $kchat_settings['chatbot_chatgpt_model'] = get_chatbot_chatgpt_transients( 'model', $user_id, $page_id, $session_id);\r\n $kchat_settings['chatbot_chatgpt_voice_option'] = get_chatbot_chatgpt_transients( 'voice', $user_id, $page_id, $session_id);\r\n $kchat_settings['additional_instructions'] = get_chatbot_chatgpt_transients( 'additional_instructions', $user_id, $page_id, $session_id);\r\n $voice = $kchat_settings['chatbot_chatgpt_voice_option'];\r\n $model = $kchat_settings['chatbot_chatgpt_model'];\r\n $additional_instructions = $kchat_settings['additional_instructions'];\r\n $chatbot_chatgpt_assistant_alias = $kchat_settings['chatbot_chatgpt_assistant_alias'];\r\n\r\n // Get the thread information - Ver 2.0.7\r\n $thread_id = get_chatbot_chatgpt_threads($user_id, $session_id, $page_id, $assistant_id);\r\n $kchat_settings['thread_id'] = $thread_id;\r\n // $kchat_settings = array_merge($kchat_settings, get_chatbot_chatgpt_threads($user_id, $page_id));\r\n\r\n $assistant_id = isset($kchat_settings['assistant_id']) ? $kchat_settings['assistant_id'] : '';\r\n $thread_Id = isset($kchat_settings['thread_id']) ? $kchat_settings['thread_id'] : '';\r\n $model = isset($kchat_settings['chatbot_chatgpt_model']) ? $kchat_settings['chatbot_chatgpt_model'] : '';\r\n $voice = isset($kchat_settings['chatbot_chatgpt_voice_option']) ? $kchat_settings['chatbot_chatgpt_voice_option'] : '';\r\n\r\n // DIAG - Diagnostics - Ver 1.8.6\r\n // back_trace( 'NOTICE', '========================================');\r\n // back_trace( 'NOTICE', '$user_id: ' . $user_id);\r\n // back_trace( 'NOTICE', '$page_id: ' . $page_id);\r\n // back_trace( 'NOTICE', '$session_id: ' . $session_id);\r\n // back_trace( 'NOTICE', '$thread_id: ' . $thread_id);\r\n // back_trace( 'NOTICE', '$assistant_id: ' . $assistant_id);\r\n // back_trace( 'NOTICE', '$chatbot_chatgpt_assistant_alias: ' . $chatbot_chatgpt_assistant_alias);\r\n // back_trace( 'NOTICE', '$model: ' . $model);\r\n // back_trace( 'NOTICE', '$voice: ' . $voice);\r\n // DIAG - Diagnostics - Ver 2.0.9\r\n // back_trace( 'NOTICE', '========================================');\r\n // foreach ($kchat_settings as $key => $value) {\r\n // back_trace( 'NOTICE', '$kchat_settings[' . $key . ']: ' . $value);\r\n // }\r\n\r\n // Assistants\r\n // $chatbot_chatgpt_assistant_alias == 'original'; // Default\r\n // $chatbot_chatgpt_assistant_alias == 'primary';\r\n // $chatbot_chatgpt_assistant_alias == 'alternate';\r\n // $chatbot_chatgpt_assistant_alias == 'asst_xxxxxxxxxxxxxxxxxxxxxxxx'; // GPT Assistant Id\r\n \r\n // Which Assistant ID to use - Ver 1.7.2\r\n if ($chatbot_chatgpt_assistant_alias == 'original') {\r\n\r\n $use_assistant_id = 'No';\r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE' , 'Using Original ChatGPT - $chatbot_chatgpt_assistant_alias: ' . $chatbot_chatgpt_assistant_alias);\r\n\r\n } elseif ($chatbot_chatgpt_assistant_alias == 'primary') {\r\n\r\n $assistant_id = esc_attr(get_option('assistant_id'));\r\n // $additional_instructions = esc_attr(get_option('chatbot_chatgpt_assistant_instructions', '')); // REMOVED VER 2.0.9\r\n $use_assistant_id = 'Yes';\r\n\r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE' , 'Using Primary Assistant - $assistant_id: ' . $assistant_id);\r\n \r\n // Check if the GPT Assistant ID is blank, null, or \"Please provide the GPT Assistant ID.\"\r\n if (empty($assistant_id) || $assistant_id == \"Please provide the GPT Assistant Id.\") {\r\n \r\n // Primary assistant_id not set\r\n $chatbot_chatgpt_assistant_alias = 'original';\r\n $use_assistant_id = 'No';\r\n \r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE' ,'Falling back to ChatGPT API - $assistant_id: ' . $assistant_id );\r\n }\r\n\r\n } elseif ($chatbot_chatgpt_assistant_alias == 'alternate') {\r\n\r\n $assistant_id = esc_attr(get_option('chatbot_chatgpt_assistant_id_alternate'));\r\n // $additional_instructions = esc_attr(get_option('chatbot_chatgpt_assistant_instructions_alternate', '')); // REMOVED VER 2.0.9\r\n $use_assistant_id = 'Yes';\r\n\r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE' , 'Using Altrnate Assistant - $assistant_id: ' . $assistant_id);\r\n\r\n // Check if the GPT Assistant ID is blank, null, or \"Please provide the GPT Assistant ID.\"\r\n if (empty($assistant_id) || $assistant_id == \"Please provide the GPT Assistant Id.\") {\r\n\r\n /// Alternate assistant_id not set\r\n $chatbot_chatgpt_assistant_alias = 'original';\r\n $use_assistant_id = 'No';\r\n\r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE' ,'Falling back to ChatGPT API - $assistant_id: ' . $assistant_id );\r\n \r\n }\r\n\r\n } elseif (str_starts_with($assistant_id, 'asst_')) {\r\n\r\n $chatbot_chatgpt_assistant_alias = $assistant_id; // Belt & Suspenders\r\n $use_assistant_id = 'Yes';\r\n\r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE' ,'Assistant ID pass as a parameter - $assistant_id: ' . $assistant_id );\r\n\r\n } else {\r\n\r\n // Reference GPT Assistant IDs directly - Ver 1.7.3\r\n if (str_starts_with($chatbot_chatgpt_assistant_alias, 'asst_')) {\r\n\r\n // DIAG - Diagnostics - 2.0.5\r\n // back_trace( 'NOTICE', 'Using GPT Assistant ID: ' . $chatbot_chatgpt_assistant_alias);\r\n\r\n // Override the $assistant_id with the GPT Assistant ID\r\n $assistant_id = $chatbot_chatgpt_assistant_alias;\r\n $use_assistant_id = 'Yes';\r\n\r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE' , 'Using $assistant_id ' . $assistant_id);\r\n\r\n } else {\r\n\r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE', 'Using ChatGPT API: ' . $chatbot_chatgpt_assistant_alias);\r\n\r\n // Override the $use_assistant_id and set it to 'No'\r\n $use_assistant_id = 'No';\r\n \r\n // DIAG - Diagnostics - Ver 1.8.1\r\n // back_trace( 'NOTICE' , 'Falling back to ChatGPT API');\r\n\r\n }\r\n\r\n }\r\n\r\n // Get any additional instructions - Ver 2.0.9\r\n $additional_instructions = get_chatbot_chatgpt_transients( 'additional_instructions', $user_id, $page_id, $session_id);\r\n\r\n // Decide whether to use Flow, Assistant or Original ChatGPT\r\n if ($model == 'flow'){\r\n \r\n // DIAG - Diagnostics - Ver 2.1.1.1\r\n // back_trace( 'NOTICE', 'Using ChatGPT Flow');\r\n // back_trace( 'NOTICE', '$user_id ' . $user_id);\r\n // back_trace( 'NOTICE', '$page_id ' . $page_id);\r\n\r\n // Reload the model - BELT & SUSPENDERS\r\n $kchat_settings['model'] = $model;\r\n\r\n // Get the step from the transient\r\n $kflow_step = get_chatbot_chatgpt_transients( 'kflow_step', null, null, $session_id);\r\n if (empty($kflow_step)) {\r\n $kflow_step = 0; // FIXME - Set to 1 or to zero?\r\n }\r\n\r\n // $thread_id\r\n $thread_id = '[answer=' . $kflow_step + 1 . ']';\r\n \r\n // Add +1 to $kchat_settings['next_step']\r\n $kflow_step = $kflow_step + 1;\r\n\r\n // Set the next step\r\n set_chatbot_chatgpt_transients( 'kflow_step', $kflow_step, null, null, $session_id);\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', '$message: ' . $message);\r\n $thread_id = get_chatbot_chatgpt_threads($user_id, $session_id, $page_id, $assistant_id);\r\n // back_trace( 'NOTICE', '$thread_id ' . $thread_id);\r\n append_message_to_conversation_log($session_id, $user_id, $page_id, 'Visitor', $thread_id, $assistant_id, $message);\r\n\r\n // BELT & SUSPENDERS\r\n $thread_id = '';\r\n\r\n // Send message to ChatGPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_call_flow_api($api_key, $message);\r\n\r\n wp_send_json_success($response);\r\n\r\n } elseif ($use_assistant_id == 'Yes') {\r\n\r\n // DIAG - Diagnostics - Ver 2.1.1.1\r\n // back_trace( 'NOTICE', 'Using GPT Assistant ID: ' . $use_assistant_id);\r\n // back_trace( 'NOTICE', '$user_id ' . $user_id);\r\n // back_trace( 'NOTICE', '$page_id ' . $page_id);\r\n // back_trace( 'NOTICE', '$message ' . $message);\r\n\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', '$message ' . $message);\r\n $thread_id = get_chatbot_chatgpt_threads($user_id, $session_id, $page_id, $assistant_id);\r\n // back_trace( 'NOTICE', '$thread_id ' . $thread_id);\r\n append_message_to_conversation_log($session_id, $user_id, $page_id, 'Visitor', $thread_id, $assistant_id, $message);\r\n\r\n // DIAG - Diagnostics - Ver 2.0.9\r\n // back_trace( 'NOTICE', '========================================');\r\n // back_trace( 'NOTICE', 'BEFORE CALL TO MODULE $additional_instructions: ' . $additional_instructions);\r\n\r\n // Send message to Custom GPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_custom_gpt_call_api($api_key, $message, $assistant_id, $thread_id, $session_id, $user_id, $page_id);\r\n\r\n // Use TF-IDF to enhance response\r\n $chatbot_chatgpt_suppress_learnings = esc_attr(get_option('chatbot_chatgpt_suppress_learnings', 'Random'));\r\n if ( $chatbot_chatgpt_suppress_learnings != 'None') {\r\n $response = $response . chatbot_chatgpt_enhance_with_tfidf($message);\r\n }\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', '$response ' . print_r($response,true));\r\n $thread_id = get_chatbot_chatgpt_threads($user_id, $session_id, $page_id, $assistant_id);\r\n // back_trace( 'NOTICE', '$thread_id ' . $thread_id);\r\n append_message_to_conversation_log($session_id, $user_id, $page_id, 'Chatbot', $thread_id, $assistant_id, $response);\r\n\r\n // Clean (erase) the output buffer - Ver 1.6.8\r\n // Check if output buffering is active before attempting to clean it\r\n if (ob_get_level() > 0) {\r\n ob_clean();\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Output buffer cleaned');\r\n } else {\r\n // Optionally start output buffering if needed for your application\r\n // ob_start();\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Output buffer not cleaned');\r\n }\r\n\r\n if (str_starts_with($response, 'Error:') || str_starts_with($response, 'Failed:')) {\r\n // Return response\r\n // back_trace( 'NOTICE', '$response ' . print_r($response,true));\r\n wp_send_json_error('Oops! Something went wrong on our end. Please try again later!');\r\n } else {\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Check for links and images in response before returning');\r\n $response = chatbot_chatgpt_check_for_links_and_images($response);\r\n\r\n // FIXME - Append extra message - Ver 2.1.1.1.1\r\n // Danger Will Robinson! Danger!\r\n $extra_message = esc_attr(get_option('chatbot_chatgpt_extra_message', ''));\r\n $response = chatbot_chatgpt_append_extra_message($response, $extra_message);\r\n\r\n // Return response\r\n wp_send_json_success($response);\r\n }\r\n\r\n } else {\r\n\r\n // DIAG - Diagnostics - Ver 2.1.1.1\r\n // back_trace( 'NOTICE', 'Using ChatGPT');\r\n // back_trace( 'NOTICE', '$user_id ' . $user_id);\r\n // back_trace( 'NOTICE', '$page_id ' . $page_id);\r\n // back_trace( 'NOTICE', '$message ' . $message);\r\n\r\n $thread_id = get_chatbot_chatgpt_threads($user_id, $session_id, $page_id, $assistant_id);\r\n // back_trace( 'NOTICE', '$thread_id ' . $thread_id);\r\n append_message_to_conversation_log($session_id, $user_id, $page_id, 'Visitor', $thread_id, $assistant_id, $message);\r\n \r\n // If $model starts with 'gpt' then the chatbot_chatgpt_call_api or 'dall' then chatbot_chatgpt_call_image_api\r\n // TRY NOT TO FETCH MODEL AGAIN\r\n // $model = esc_attr(get_option('chatbot_chatgpt_model_choice', 'gpt-3.5-turbo'));\r\n $model = isset($kchat_settings['model']) ? $kchat_settings['model'] : null;\r\n $voice = isset($kchat_settings['voice']) ? $kchat_settings['voice'] : null;\r\n if (str_starts_with($model !== null && $model, 'gpt-4o') !== false) {\r\n // The string 'gpt-4o' is found in $model\r\n // Reload the model - BELT & SUSPENDERS\r\n $kchat_settings['model'] = $model;\r\n // Send message to ChatGPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_call_omni($api_key, $message);\r\n } elseif ($model !== null && str_starts_with($model, 'gpt')) {\r\n // Reload the model - BELT & SUSPENDERS\r\n $kchat_settings['model'] = $model;\r\n // Send message to ChatGPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_call_api($api_key, $message);\r\n } elseif ($model !== null && str_starts_with($model, 'dall')) {\r\n // Reload the model - BELT & SUSPENDERS\r\n $kchat_settings['model'] = $model;\r\n // Send message to Image API - Ver 1.9.4\r\n $response = chatbot_chatgpt_call_image_api($api_key, $message);\r\n } elseif ($model !== null && str_starts_with($model, 'tts')) {\r\n // Reload the model - BELT & SUSPENDERS\r\n $kchat_settings['model'] = $model;\r\n $kchat_settings['voice'] = $voice;\r\n // Send message to TTS API - Text-to-speech - Ver 1.9.5\r\n $response = chatbot_chatgpt_call_tts_api($api_key, $message, $voice, $user_id, $page_id, $session_id);\r\n } elseif ($model !== null && str_starts_with($model,'whisper')) {\r\n $kchat_settings['model'] = $model;\r\n // Send message to STT API - Speech-to-text - Ver 1.9.6\r\n $response = chatbot_chatgpt_call_stt_api($api_key, $message);\r\n } else {\r\n // Reload the model - BELT & SUSPENDERS\r\n $kchat_settings['model'] = $model;\r\n // Send message to ChatGPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_call_api($api_key, $message);\r\n }\r\n \r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', ['message' => 'BEFORE CALL TO ENHANCE TFIDF', 'response' => $response]);\r\n \r\n // Use TF-IDF to enhance response\r\n $chatbot_chatgpt_suppress_learnings = esc_attr(get_option('chatbot_chatgpt_suppress_learnings', 'Random'));\r\n if ( $chatbot_chatgpt_suppress_learnings != 'None') {\r\n $response = $response . chatbot_chatgpt_enhance_with_tfidf($message);\r\n }\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', ['message' => 'AFTER CALL TO ENHANCE TFIDF', 'response' => $response]);\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', '$response ' . print_r($response,true));\r\n $thread_id = get_chatbot_chatgpt_threads($user_id, $session_id, $page_id, $assistant_id);\r\n // back_trace( 'NOTICE', '$thread_id ' . $thread_id);\r\n append_message_to_conversation_log($session_id, $user_id, $page_id, 'Chatbot', $thread_id, $assistant_id, $response);\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Check for links and images in response before returning');\r\n $response = chatbot_chatgpt_check_for_links_and_images($response);\r\n\r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE', 'Response: ' . $response);\r\n\r\n // FIXME - Append extra message - Ver 2.1.1.1.1\r\n // Danger Will Robinson! Danger!\r\n $extra_message = esc_attr(get_option('chatbot_chatgpt_extra_message', ''));\r\n $response = chatbot_chatgpt_append_extra_message($response, $extra_message);\r\n\r\n // Return response\r\n wp_send_json_success($response);\r\n\r\n }\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'ERROR', 'Oops! I fell through the cracks!');\r\n wp_send_json_error('Oops! I fell through the cracks!');\r\n\r\n}\r\n\r\n// Add action to send messages - Ver 1.0.0\r\nadd_action('wp_ajax_chatbot_chatgpt_send_message', 'chatbot_chatgpt_send_message');\r\nadd_action('wp_ajax_nopriv_chatbot_chatgpt_send_message', 'chatbot_chatgpt_send_message');\r\n\r\n// Add action to upload files - Ver 1.7.6\r\nadd_action('wp_ajax_chatbot_chatgpt_upload_files', 'chatbot_chatgpt_upload_files');\r\nadd_action('wp_ajax_nopriv_chatbot_chatgpt_upload_files', 'chatbot_chatgpt_upload_files');\r\n\r\n// Add action to upload files - Ver 1.7.6\r\nadd_action('wp_ajax_chatbot_chatgpt_upload_mp3', 'chatbot_chatgpt_upload_mp3');\r\nadd_action('wp_ajax_nopriv_chatbot_chatgpt_upload_mp3', 'chatbot_chatgpt_upload_mp3');\r\n\r\n// Add action to erase conversation - Ver 1.8.6\r\nadd_action('wp_ajax_chatbot_chatgpt_erase_conversation', 'chatbot_chatgpt_erase_conversation_handler');\r\nadd_action('wp_ajax_nopriv_chatbot_chatgpt_erase_conversation', 'chatbot_chatgpt_erase_conversation_handler'); // For logged-out users, if needed\r\n\r\n// Settings and Deactivation - Ver 1.5.0\r\nadd_filter('plugin_action_links_' . plugin_basename(__FILE__), 'chatbot_chatgpt_plugin_action_links');\r\n\r\n// Append an extra message to the response - Ver 2.0.9\r\nfunction chatbot_chatgpt_append_extra_message($response, $extra_message) {\r\n\r\n // Append the extra message to the response\r\n $response = $response . ' ' . $extra_message;\r\n return $response;\r\n\r\n}\r\n\r\n// Crawler aka Knowledge Navigator - Ver 1.6.1\r\nfunction chatbot_chatgpt_kn_status_activation() {\r\n add_option('chatbot_chatgpt_kn_status', 'Never Run');\r\n // clear any old scheduled runs\r\n if (wp_next_scheduled('crawl_scheduled_event_hook')) {\r\n wp_clear_scheduled_hook('crawl_scheduled_event_hook');\r\n }\r\n // clear the 'knowledge_navigator_scan_hook' hook on plugin activation - Ver 1.6.3\r\n if (wp_next_scheduled('knowledge_navigator_scan_hook')) {\r\n // BREAK/FIX - Do not unset the hook - Ver 1.8.5\r\n // wp_clear_scheduled_hook('knowledge_navigator_scan_hook'); // Clear scheduled runs\r\n }\r\n}\r\nregister_activation_hook(__FILE__, 'chatbot_chatgpt_kn_status_activation');\r\n\r\n// Clean Up in Aisle 4\r\nfunction chatbot_chatgpt_kn_status_deactivation() {\r\n delete_option('chatbot_chatgpt_kn_status');\r\n wp_clear_scheduled_hook('knowledge_navigator_scan_hook'); \r\n}\r\nregister_deactivation_hook(__FILE__, 'chatbot_chatgpt_kn_status_deactivation');\r\n\r\n// Function to add a new message and response, keeping only the last five - Ver 1.6.1\r\nfunction addEntry($transient_name, $newEntry) {\r\n\r\n $context_history = get_transient($transient_name);\r\n if (!$context_history) {\r\n $context_history = [];\r\n }\r\n\r\n // Determine the total length of all existing entries\r\n $totalLength = 0;\r\n foreach ($context_history as $entry) {\r\n if (is_string($entry)) {\r\n $totalLength += strlen($entry);\r\n } elseif (is_array($entry)) {\r\n $totalLength += strlen(json_encode($entry)); // Convert to string if an array\r\n }\r\n }\r\n\r\n // IDEA - How will the new threading option from OpenAI change how this works?\r\n // Define thresholds for the number of entries to keep\r\n $maxEntries = 30; // Default maximum number of entries\r\n if ($totalLength > 5000) { // Higher threshold\r\n $maxEntries = 20;\r\n }\r\n if ($totalLength > 10000) { // Lower threshold\r\n $maxEntries = 10;\r\n }\r\n\r\n while (count($context_history) >= $maxEntries) {\r\n array_shift($context_history); // Remove the oldest element\r\n }\r\n\r\n if (is_array($newEntry)) {\r\n $newEntry = json_encode($newEntry); // Convert the array to a string\r\n }\r\n\r\n array_push($context_history, $newEntry); // Append the new element\r\n set_transient($transient_name, $context_history); // Update the transient\r\n}\r\n\r\n// Function to return message and response - Ver 1.6.1\r\nfunction concatenateHistory($transient_name) {\r\n $context_history = get_transient($transient_name);\r\n if (!$context_history) {\r\n return ''; // Return an empty string if the transient does not exist\r\n }\r\n return implode(' ', $context_history); // Concatenate the array values into a single string\r\n}\r\n\r\n// FIXME - MOVE CORE FUNCTIONS TO A SEPARATE FILE, LEAVING ONLY THE HOOKS HERE\r\n// Initialize the Greetings - Ver 1.6.1\r\nfunction enqueue_greetings_script( $initial_greeting = null, $subsequent_greeting = null) {\r\n\r\n // If user is logged in, then modify greeting if greeting contains \"[...]\" or remove if not logged in - Ver 1.9.4\r\n if (is_user_logged_in()) {\r\n\r\n $current_user_id = get_current_user_id();\r\n $current_user = get_userdata($current_user_id);\r\n\r\n //Do this for Initial Greeting\r\n if ( empty($initial_greeting) ) {\r\n $initial_greeting = esc_attr(get_option('chatbot_chatgpt_initial_greeting', 'Hello! How can I help you today?'));\r\n }\r\n\r\n // Determine what the field name is between the brackets\r\n $user_field_name = '';\r\n $user_field_name = substr($initial_greeting, strpos($initial_greeting, '[') + 1, strpos($initial_greeting, ']') - strpos($initial_greeting, '[') - 1);\r\n // If $initial_greeting contains \"[$user_field_name]\" then replace with field from DB\r\n if (strpos($initial_greeting, '[' . $user_field_name . ']') !== false) {\r\n $initial_greeting = str_replace('[' . $user_field_name . ']', $current_user->$user_field_name, $initial_greeting);\r\n } else {\r\n $initial_greeting = str_replace('[' . $user_field_name . ']', '', $initial_greeting);\r\n // Remove the extra space when two spaces are present\r\n $initial_greeting = str_replace(' ', ' ', $initial_greeting);\r\n // Remove the extra space before punctuation including period, comma, exclamation mark, and question mark\r\n $initial_greeting = preg_replace('/\\s*([.,!?])/', '$1', $initial_greeting);\r\n }\r\n\r\n // Do this for Subsequent Greeting\r\n if ( empty($subsequent_greeting) ) {\r\n $subsequent_greeting = esc_attr(get_option('chatbot_chatgpt_subsequent_greeting', 'Hello again! How can I help you?'));\r\n }\r\n\r\n // Determine what the field name is between the brackets\r\n $user_field_name = '';\r\n $user_field_name = substr($subsequent_greeting, strpos($subsequent_greeting, '[') + 1, strpos($subsequent_greeting, ']') - strpos($subsequent_greeting, '[') - 1);\r\n // If $subsequent_greeting contains \"[$user_field_name]\" then replace with field from DB\r\n if (strpos($subsequent_greeting, '[' . $user_field_name . ']') !== false) {\r\n $subsequent_greeting = str_replace('[' . $user_field_name . ']', $current_user->$user_field_name, $subsequent_greeting);\r\n } else {\r\n $subsequent_greeting = str_replace('[' . $user_field_name . ']', '', $subsequent_greeting);\r\n // Remove the extra space when two spaces are present\r\n $subsequent_greeting = str_replace(' ', ' ', $subsequent_greeting);\r\n // Remove the extra space before punctuation including period, comma, exclamation mark, and question mark\r\n $subsequent_greeting = preg_replace('/\\s*([.,!?])/', '$1', $subsequent_greeting);\r\n }\r\n\r\n } else {\r\n\r\n //Do this for Initial Greeting\r\n if ( empty($initial_greeting) ) {\r\n $initial_greeting = esc_attr(get_option('chatbot_chatgpt_initial_greeting', 'Hello! How can I help you today?'));\r\n }\r\n\r\n $user_field_name = '';\r\n $user_field_name = substr($initial_greeting, strpos($initial_greeting, '[') + 1, strpos($initial_greeting, ']') - strpos($initial_greeting, '[') - 1 );\r\n\r\n // $initial_greeting = preg_replace('/\\s*\\[' . preg_quote($user_field_name, '/') . '\\]\\s*/', '', $initial_greeting);\r\n $initial_greeting = str_replace('[' . $user_field_name . ']', '', $initial_greeting);\r\n // Remove the extra space when two spaces are present\r\n $initial_greeting = str_replace(' ', ' ', $initial_greeting);\r\n // Remove the extra space before punctuation including period, comma, exclamation mark, and question mark\r\n $initial_greeting = preg_replace('/\\s*([.,!?])/', '$1', $initial_greeting);\r\n\r\n //Do this for Subsequent Greeting\r\n if ( empty($subsequent_greeting) ) {\r\n $subsequent_greeting = esc_attr(get_option('chatbot_chatgpt_subsequent_greeting', 'Hello again! How can I help you?'));\r\n }\r\n\r\n $user_field_name = '';\r\n $user_field_name = substr($subsequent_greeting, strpos($subsequent_greeting, '[') + 1, strpos($subsequent_greeting, ']') - strpos($subsequent_greeting, '[') - 1);\r\n\r\n // $subsequent_greeting = preg_replace('/\\s*\\[' . preg_quote($user_field_name, '/') . '\\]\\s*/', '', $subsequent_greeting);\r\n $subsequent_greeting = str_replace('[' . $user_field_name . ']', '', $subsequent_greeting);\r\n // Remove the extra space when two spaces are present\r\n $subsequent_greeting = str_replace(' ', ' ', $subsequent_greeting);\r\n // Remove the extra space before punctuation including period, comma, exclamation mark, and question mark\r\n $subsequent_greeting = preg_replace('/\\s*([.,!?])/', '$1', $subsequent_greeting);\r\n \r\n }\r\n\r\n $greetings = array(\r\n 'initial_greeting' => $initial_greeting,\r\n 'subsequent_greeting' => $subsequent_greeting,\r\n );\r\n\r\n return $greetings;\r\n\r\n}\r\n// \r\nadd_action('wp_enqueue_scripts', 'enqueue_greetings_script');\r\n\r\n// Add the color picker to the adaptive appearance settings section - Ver 1.8.1\r\nfunction enqueue_color_picker($hook_suffix) {\r\n\r\n global $chatbot_chatgpt_plugin_version;\r\n\r\n // first check that $hook_suffix is appropriate for your admin page\r\n wp_enqueue_style('wp-color-picker');\r\n wp_enqueue_script('my-script-handle', plugin_dir_url(__FILE__) . 'assets/js/chatbot-chatgpt-color-picker.js', array('wp-color-picker'), $chatbot_chatgpt_plugin_version, true);\r\n\r\n}\r\nadd_action('admin_enqueue_scripts', 'enqueue_color_picker');\r\n\r\n// Determine if the plugin is installed\r\nfunction kchat_get_plugin_version() {\r\n\r\n global $chatbot_chatgpt_plugin_version;\r\n\r\n if (!function_exists('get_plugin_data')) {\r\n require_once(ABSPATH . 'wp-admin/includes/plugin.php');\r\n }\r\n\r\n // $plugin_data = get_plugin_data(plugin_dir_path(__FILE__) . 'chatbot-chatgpt.php');\r\n // $plugin_version = $plugin_data['chatbot_chatgpt_version'];\r\n $plugin_version = $chatbot_chatgpt_plugin_version;\r\n update_option('chatbot_chatgpt_plugin_version', $plugin_version);\r\n // DIAG - Log the plugin version\r\n // back_trace( 'NOTICE', 'Plugin version ' . $plugin_version);\r\n\r\n return $plugin_version;\r\n\r\n}\r\n"}, "f714b212a9a77bae93a1e7e925a7c263927b9afd": {"t": 1785756415.3341675, "n": 54998, "h": "9bd6fc9c9e4a89ba", "c": " $user_id,\r\n 'page_id' => $page_id,\r\n 'session_id' => $session_id,\r\n 'thread_id' => $thread_id,\r\n 'assistant_id' => $assistant_id,\r\n 'additional_instructions' => $additional_instructions,\r\n 'model' => $model,\r\n 'voice' => $voice,\r\n );\r\n\r\n // DIAG - Diagnostics - Ver 1.8.6\r\n // back_trace( 'NOTICE', '$user_id: ' . $user_id);\r\n // back_trace( 'NOTICE', '$page_id: ' . $page_id);\r\n // back_trace( 'NOTICE', '$session_id: ' . $session_id);\r\n // back_trace( 'NOTICE', '$thread_id: ' . $thread_id);\r\n // back_trace( 'NOTICE', '$assistant_id: ' . $assistant_id);\r\n // back_trace( 'NOTICE', '$additional_instructions: ' . $additional_instructions);\r\n // back_trace( 'NOTICE', '$model: ' . $model);\r\n \r\n // Defaults for Ver 1.6.1\r\n $defaults = array(\r\n 'chatbot_chatgpt_bot_name' => 'Kognetiks Chatbot',\r\n 'chatbot_chatgpt_bot_prompt' => 'Enter your question ...',\r\n 'chatbot_chatgpt_initial_greeting' => 'Hello! How can I help you today?',\r\n 'chatbot_chatgpt_subsequent_greeting' => 'Hello again! How can I help you?',\r\n 'chatbot_chatgpt_display_style' => 'floating',\r\n 'chatbot_chatgpt_assistant_alias' => 'primary',\r\n 'chatbot_chatgpt_start_status' => 'closed',\r\n 'chatbot_chatgpt_start_status_new_visitor' => 'closed',\r\n 'chatbot_chatgpt_disclaimer_setting' => 'No',\r\n 'chatbot_chatgpt_audience_choice' => 'all',\r\n 'chatbot_chatgpt_max_tokens_setting' => '150',\r\n 'chatbot_chatgpt_message_limit_setting' => '999',\r\n 'chatbot_chatgpt_width_setting' => 'Narrow',\r\n 'chatbot_chatgpt_diagnostics' => 'Off',\r\n 'chatbot_chatgpt_custom_error_message' => 'Your custom error message goes here.',\r\n 'chatbot_chatgpt_avatar_icon_setting' => 'icon-001.png',\r\n 'chatbot_chatgpt_avatar_icon_url_setting' => '',\r\n 'chatbot_chatgpt_custom_avatar_icon_setting' => '',\r\n 'chatbot_chatgpt_avatar_greeting_setting' => 'Howdy!!! Great to see you today! How can I help you?',\r\n 'chatbot_chatgpt_model_choice' => 'gpt-3.5-turbo',\r\n 'chatbot_chatgpt_conversation_context' => 'You are a versatile, friendly, and helpful assistant designed to support me in a variety of tasks that responds in Markdown.',\r\n 'chatbot_chatgpt_enable_custom_buttons' => 'Off',\r\n 'chatbot_chatgpt_custom_button_name_1' => '',\r\n 'chatbot_chatgpt_custom_button_url_1' => '',\r\n 'chatbot_chatgpt_custom_button_name_2' => '',\r\n 'chatbot_chatgpt_custom_button_url_2' => '',\r\n 'chatbot_chatgpt_custom_button_name_3' => '',\r\n 'chatbot_chatgpt_custom_button_url_3' => '',\r\n 'chatbot_chatgpt_custom_button_name_4' => '',\r\n 'chatbot_chatgpt_custom_button_url_4' => '',\r\n 'chatbot_chatgpt_allow_file_uploads' => 'No',\r\n 'chatbot_chatgpt_timeout_setting' => '240',\r\n 'chatbot_chatgpt_voice_option' => 'alloy',\r\n 'chatbot_chatgpt_audio_output_format' => 'mp3',\r\n 'chatbot_chatgpt_force_page_reload' => 'No',\r\n );\r\n\r\n // Revised for Ver 1.5.0 \r\n $option_keys = array(\r\n 'chatbot_chatgpt_bot_name',\r\n 'chatbot_chatgpt_bot_prompt',\r\n 'chatbot_chatgpt_initial_greeting',\r\n 'chatbot_chatgpt_subsequent_greeting',\r\n 'chatbot_chatgpt_display_style',\r\n 'chatbot_chatgpt_assistant_alias',\r\n 'chatbot_chatgpt_start_status',\r\n 'chatbot_chatgpt_start_status_new_visitor',\r\n 'chatbot_chatgpt_disclaimer_setting',\r\n 'chatbot_chatgpt_audience_choice',\r\n 'chatbot_chatgpt_max_tokens_setting',\r\n 'chatbot_chatgpt_message_limit_setting',\r\n 'chatbot_chatgpt_width_setting',\r\n 'chatbot_chatgpt_diagnostics',\r\n 'chatbot_chatgpt_custom_error_message',\r\n 'chatbot_chatgpt_avatar_icon_setting',\r\n 'chatbot_chatgpt_avatar_icon_url_setting',\r\n 'chatbot_chatgpt_custom_avatar_icon_setting',\r\n 'chatbot_chatgpt_avatar_greeting_setting',\r\n 'chatbot_chatgpt_enable_custom_buttons',\r\n 'chatbot_chatgpt_custom_button_name_1',\r\n 'chatbot_chatgpt_custom_button_url_1',\r\n 'chatbot_chatgpt_custom_button_name_2',\r\n 'chatbot_chatgpt_custom_button_url_2',\r\n 'chatbot_chatgpt_custom_button_name_3',\r\n 'chatbot_chatgpt_custom_button_url_3',\r\n 'chatbot_chatgpt_custom_button_name_4',\r\n 'chatbot_chatgpt_custom_button_url_4',\r\n 'chatbot_chatgpt_allow_file_uploads',\r\n 'chatbot_chatgpt_timeout_setting',\r\n 'chatbot_chatgpt_voice_option',\r\n 'chatbot_chatgpt_audio_output_format',\r\n 'chatbot_chatgpt_force_page_reload',\r\n );\r\n\r\n global $chatbot_settings;\r\n $chatbot_settings = array();\r\n foreach ($option_keys as $key) {\r\n $default_value = $defaults[$key] ?? '';\r\n $chatbot_settings[$key] = esc_attr(get_option($key, $default_value));\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Key: ' . $key . ', Value: ' . $chatbot_settings[$key]);\r\n }\r\n\r\n // Set visitor and logged in user limits - Ver 2.0.1\r\n if (is_user_logged_in()) {\r\n // back_trace( 'NOTICE', 'User is logged in');\r\n $chatbot_settings['chatbot_chatgpt_message_limit_setting'] = esc_attr(get_option('chatbot_chatgpt_message_limit_setting', '999'));\r\n } else {\r\n // back_trace( 'NOTICE', 'User is NOT logged in');\r\n $chatbot_settings['chatbot_chatgpt_message_limit_setting'] = esc_attr(get_option('chatbot_chatgpt_visitor_message_limit_setting', '999'));\r\n }\r\n \r\n $chatbot_settings['chatbot_chatgpt_icon_base_url'] = plugins_url( '/assets/icons/', __FILE__ );\r\n\r\n // Original wp_localize_script call\r\n // wp_localize_script('chatbot-chatgpt-js', 'php_vars', $script_data_array);\r\n // Refactored using wp_add_inline_script - Ver 2.0.5 - 2024 07 06\r\n $script_data_json = wp_json_encode($script_data_array);\r\n wp_add_inline_script('chatbot-chatgpt-js', 'if (typeof php_vars === \"undefined\") { var php_vars = ' . $script_data_json . '; } else { php_vars = ' . $script_data_json . '; }', 'before');\r\n \r\n // Original wp_localize_script call\r\n // wp_localize_script('chatbot-chatgpt-js', 'plugin_vars', array(\r\n // 'plugins_url' => plugins_url('', __FILE__ ),\r\n // ));\r\n // Refactored using wp_add_inline_script - Ver 2.0.5 - 2024 07 06\r\n $plugin_vars = array(\r\n 'plugins_url' => plugins_url('', __FILE__ ),\r\n );\r\n $plugin_vars_json = wp_json_encode($plugin_vars);\r\n wp_add_inline_script('chatbot-chatgpt-js', 'let plugin_vars = ' . $plugin_vars_json . ';', 'before');\r\n\r\n // Original wp_localize_script call\r\n // wp_localize_script('chatbot-chatgpt-local', 'chatbotSettings', $chatbot_settings);\r\n // Refactored using wp_add_inline_script - Ver 2.0.5 - 2024 07 06\r\n $chatbotSettings_json = wp_json_encode($chatbot_settings);\r\n wp_add_inline_script('chatbot-chatgpt-local', 'if (typeof chatbotSettings === \"undefined\") { var chatbotSettings = ' . $chatbotSettings_json . '; } else { chatbotSettings = ' . $chatbotSettings_json . '; }', 'before');\r\n \r\n // Original wp_localize_script call\r\n // wp_localize_script('chatbot-chatgpt-js', 'chatbot_chatgpt_params', array(\r\n // 'plugins_url' => plugins_url('', __FILE__ ),\r\n // 'ajax_url' => admin_url('admin-ajax.php'),\r\n // ));\r\n // Original wp_localize_script call\r\n // Upload files - Ver 1.7.6\r\n // wp_localize_script('chatbot-chatgpt-upload-trigger-js', 'chatbot_chatgpt_params', array(\r\n // 'plugins_url' => plugins_url('', __FILE__ ),\r\n // 'ajax_url' => admin_url('admin-ajax.php'),\r\n // ));\r\n // Refactored using wp_add_inline_script - Ver 2.0.5 - 2024 07 06\r\n $chatbot_chatgpt_params = array(\r\n 'plugins_url' => plugins_url('', __FILE__ ),\r\n 'ajax_url' => admin_url('admin-ajax.php'),\r\n );\r\n $chatbot_chatgpt_params_json = wp_json_encode($chatbot_chatgpt_params);\r\n wp_add_inline_script('chatbot-chatgpt-js', 'if (typeof chatbot_chatgpt_params === \"undefined\") { var chatbot_chatgpt_params = ' . $chatbot_chatgpt_params_json . '; } else { chatbot_chatgpt_params = ' . $chatbot_chatgpt_params_json . '; }', 'before');\r\n wp_add_inline_script('chatbot-chatgpt-upload-trigger-js', 'if (typeof chatbot_chatgpt_params === \"undefined\") { var chatbot_chatgpt_params = ' . $chatbot_chatgpt_params_json . '; } else { chatbot_chatgpt_params = ' . $chatbot_chatgpt_params_json . '; }', 'before');\r\n \r\n}\r\nadd_action('wp_enqueue_scripts', 'chatbot_chatgpt_enqueue_scripts');\r\n\r\n// Settings and Deactivation Links - Ver - 1.5.0\r\nif (!function_exists('enqueue_jquery_ui')) {\r\n function enqueue_jquery_ui() {\r\n wp_enqueue_style('wp-jquery-ui-dialog');\r\n wp_enqueue_script('jquery-ui-dialog');\r\n }\r\n add_action( 'admin_enqueue_scripts', 'enqueue_jquery_ui' );\r\n}\r\n\r\n// Schedule Cleanup of Expired Transients\r\nif (!wp_next_scheduled('chatbot_chatgpt_cleanup_event')) {\r\n wp_schedule_event(time(), 'daily', 'chatbot_chatgpt_cleanup_event');\r\n}\r\nadd_action('chatbot_chatgpt_cleanup_event', 'clean_specific_expired_transients');\r\n\r\n// Schedule Conversation Log Cleanup - Ver 1.6.7\r\nif (!wp_next_scheduled('chatbot_chatgpt_conversation_log_cleanup_event')) {\r\n wp_schedule_event(time(), 'daily', 'chatbot_chatgpt_conversation_log_cleanup_event');\r\n}\r\nadd_action('chatbot_chatgpt_conversation_log_cleanup_event', 'chatbot_chatgpt_conversation_log_cleanup');\r\n\r\n// Schedule the transcript file cleanup event if it's not already scheduled - Ver 1.9.9\r\n// Schedule the cleanup event if it's not already scheduled\r\nif (!wp_next_scheduled('chatbot_chatgpt_cleanup_transcript_files')) {\r\n wp_schedule_event(time(), 'hourly', 'chatbot_chatgpt_cleanup_transcript_files');\r\n}\r\n\r\n// Deactivate old hooks - Ver 2.0.1\r\nif(esc_attr(get_option('chatbot_chatgpt_cleanup_old_hooks') !== 'Completed')) {\r\n // Deactivate old hooks - Ver 2.0.1\r\n wp_clear_scheduled_hook('chatbot_chatgpt_cleanup_transcripts');\r\n // Then update the option\r\n update_option('chatbot_chatgpt_cleanup_old_hooks', 'Completed');\r\n}\r\n\r\n// Schedule the audio file cleanup event if it's not already scheduled - Ver 1.9.9\r\n// Schedule the cleanup event if it's not already scheduled\r\nif (!wp_next_scheduled('chatbot_chatgpt_cleanup_audio_files')) {\r\n wp_schedule_event(time(), 'hourly', 'chatbot_chatgpt_cleanup_audio_files');\r\n}\r\n\r\n// Schedule the upload file cleanup event if it's not already scheduled - Ver 1.9.9\r\n// Schedule the cleanup event if it's not already scheduled\r\nif (!wp_next_scheduled('chatbot_chatgpt_cleanup_upload_files')) {\r\n wp_schedule_event(time(), 'hourly', 'chatbot_chatgpt_cleanup_upload_files');\r\n}\r\n\r\n// Schedule the download file cleanup event if it's not already scheduled - Ver 2.0.3\r\n// Schedule the cleanup event if it's not already scheduled\r\nif (!wp_next_scheduled('chatbot_chatgpt_cleanup_download_files')) {\r\n wp_schedule_event(time(), 'hourly', 'chatbot_chatgpt_cleanup_download_files');\r\n}\r\n\r\n// Add the Assistant table to the database - Ver 2.0.4\r\ncreate_chatbot_chatgpt_assistants_table();\r\n\r\n// Handle Ajax requests\r\nfunction chatbot_chatgpt_send_message() {\r\n\r\n // Global variables\r\n global $session_id;\r\n global $user_id;\r\n global $page_id;\r\n global $thread_id;\r\n global $assistant_id;\r\n global $chatbot_chatgpt_display_style;\r\n global $chatbot_chatgpt_assistant_alias;\r\n global $script_data_array;\r\n global $additional_instructions;\r\n global $model;\r\n global $voice;\r\n\r\n global $flow_data;\r\n\r\n $api_key = '';\r\n\r\n // Retrieve the API key\r\n $api_key = esc_attr(get_option('chatbot_chatgpt_api_key'));\r\n\r\n // Retrieve the GPT Model\r\n if (!empty($model)) {\r\n $model = esc_attr(get_option('chatbot_chatgpt_model_choice', 'gpt-3.5-turbo'));\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Model from options: ' . $model);\r\n } else {\r\n // SEE IF $script_data_array HAS THE MODEL\r\n if ( isset($script_data_array['model'])) {\r\n $model = $script_data_array['model'];\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Model set in global: ' . $model);\r\n } else {\r\n // Set the model to the default\r\n $model = esc_attr(get_option('chatbot_chatgpt_model_choice', 'gpt-3.5-turbo'));\r\n // DIAG - Diagnostics\r\n // back_trace( 'ERROR', 'Model not set!!!');\r\n // wp_send_json_error('Invalid Model. Please set the model in the plugin settings.');\r\n }\r\n }\r\n\r\n // Retrieve the Max tokens - Ver 1.4.2\r\n $max_tokens = esc_attr(get_option('chatbot_chatgpt_max_tokens_setting', 150));\r\n\r\n // Send only clean text via the API\r\n $message = sanitize_text_field($_POST['message']);\r\n\r\n // Check for missing API key or Message\r\n if (!$api_key || !$message) {\r\n wp_send_json_error('Error: Invalid API key or Message. Please check the plugin settings.');\r\n }\r\n\r\n // Removed in Ver 1.8.6 - 2024 02 15\r\n // $thread_id = '';\r\n // $assistant_id = '';\r\n // $user_id = '';\r\n // $page_id = '';\r\n \r\n // Check the transient for the Assistant ID - Ver 1.7.2\r\n $user_id = intval($_POST['user_id']);\r\n $page_id = intval($_POST['page_id']);\r\n\r\n // DIAG - Diagnostics - Ver 1.8.6\r\n // back_trace( 'NOTICE', '$user_id: ' . $user_id);\r\n // back_trace( 'NOTICE', '$page_id: ' . $page_id);\r\n\r\n $chatbot_settings['display_style'] = get_chatbot_chatgpt_transients( 'display_style', $user_id, $page_id, $session_id);\r\n $chatbot_settings['assistant_alias'] = get_chatbot_chatgpt_transients( 'assistant_alias', $user_id, $page_id, $session_id);\r\n $chatbot_settings['assistant_id'] = get_chatbot_chatgpt_transients( 'assistant_id', $user_id, $page_id, $session_id);\r\n $chatbot_settings['thread_id'] = get_chatbot_chatgpt_transients( 'thread_id', $user_id, $page_id, $session_id);\r\n $chatbot_settings['model'] = get_chatbot_chatgpt_transients( 'model', $user_id, $page_id, $session_id);\r\n $chatbot_settings['voice'] = get_chatbot_chatgpt_transients( 'voice', $user_id, $page_id, $session_id);\r\n $voice = $chatbot_settings['voice'];\r\n $display_style = $chatbot_settings['display_style'];\r\n\r\n // DIAG - Diagnostics - Ver 2.0.6\r\n // back_trace( 'NOTICE', '$chatbot_settings[display_style]: ' . $chatbot_settings['display_style']);\r\n // back_trace( 'NOTICE', '$chatbot_settings[assistant_alias]: ' . $chatbot_settings['assistant_alias']);\r\n // back_trace( 'NOTICE', '$chatbot_settings[assistant_id]: ' . $chatbot_settings['assistant_id']);\r\n // back_trace( 'NOTICE', '$chatbot_settings[thread_id]: ' . $chatbot_settings['thread_id']);\r\n // back_trace( 'NOTICE', '$chatbot_settings[model]: ' . $chatbot_settings['model']);\r\n // back_trace( 'NOTICE', '$chatbot_settings[voice]: ' . $chatbot_settings['voice']);\r\n\r\n $display_style = isset($chatbot_settings['display_style']) ? $chatbot_settings['display_style'] : '';\r\n $chatbot_chatgpt_assistant_alias = isset($chatbot_settings['assistant_alias']) ? $chatbot_settings['assistant_alias'] : '';\r\n\r\n $temp_model = $chatbot_settings['model']; // Store the model in a temporary variable before overwriting $chatbot_settings\r\n\r\n $chatbot_settings = get_chatbot_chatgpt_threads($user_id, $page_id);\r\n\r\n $chatbot_settings['model'] = $temp_model; // Restore the model after overwriting $chatbot_settings\r\n\r\n // DIAG - Diagnostics - Ver 2.0.6\r\n // back_trace( 'NOTICE', '*********************************');\r\n // back_trace( 'NOTICE', '$chatbot_settings[assistant_id]: ' . $chatbot_settings['assistant_id']);\r\n // back_trace( 'NOTICE', '$chatbot_settings[thread_id]: ' . $chatbot_settings['thread_id']);\r\n // back_trace( 'NOTICE', '$chatbot_settings[model]: ' . $chatbot_settings['model']);\r\n\r\n $assistant_id = isset($chatbot_settings['assistant_id']) ? $chatbot_settings['assistant_id'] : '';\r\n $thread_Id = isset($chatbot_settings['thread_id']) ? $chatbot_settings['thread_id'] : '';\r\n $model = isset($chatbot_settings['model']) ? $chatbot_settings['model'] : '';\r\n\r\n // DIAG - Diagnostics - Ver 1.8.6\r\n // back_trace( 'NOTICE', '*********************************');\r\n // back_trace( 'NOTICE', '$user_id: ' . $user_id);\r\n // back_trace( 'NOTICE', '$page_id: ' . $page_id);\r\n // back_trace( 'NOTICE', '$session_id: ' . $session_id);\r\n // back_trace( 'NOTICE', '$thread_id: ' . $thread_id);\r\n // back_trace( 'NOTICE', '$assistant_id: ' . $assistant_id);\r\n // back_trace( 'NOTICE', '$chatbot_chatgpt_assistant_alias: ' . $chatbot_chatgpt_assistant_alias);\r\n // back_trace( 'NOTICE', '$model: ' . $model);\r\n // back_trace( 'NOTICE', '$voice: ' . $voice);\r\n\r\n // Assistants\r\n // $chatbot_chatgpt_assistant_alias == 'original'; // Default\r\n // $chatbot_chatgpt_assistant_alias == 'primary';\r\n // $chatbot_chatgpt_assistant_alias == 'alternate';\r\n // $chatbot_chatgpt_assistant_alias == 'asst_xxxxxxxxxxxxxxxxxxxxxxxx'; // GPT Assistant Id\r\n \r\n // Which Assistant ID to use - Ver 1.7.2\r\n if ($chatbot_chatgpt_assistant_alias == 'original') {\r\n\r\n $use_assistant_id = 'No';\r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE' , 'Using Original ChatGPT - $chatbot_chatgpt_assistant_alias: ' . $chatbot_chatgpt_assistant_alias);\r\n\r\n } elseif ($chatbot_chatgpt_assistant_alias == 'primary') {\r\n\r\n $assistant_id = esc_attr(get_option('chatbot_chatgpt_assistant_id'));\r\n $additional_instructions = esc_attr(get_option('chatbot_chatgpt_assistant_instructions', ''));\r\n $use_assistant_id = 'Yes';\r\n\r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE' , 'Using Primary Assistant - $assistant_id: ' . $assistant_id);\r\n \r\n // Check if the GPT Assistant ID is blank, null, or \"Please provide the GPT Assistant ID.\"\r\n if (empty($assistant_id) || $assistant_id == \"Please provide the GPT Assistant Id.\") {\r\n \r\n // Primary assistant_id not set\r\n $chatbot_chatgpt_assistant_alias = 'original';\r\n $use_assistant_id = 'No';\r\n \r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE' ,'Falling back to ChatGPT API - $assistant_id: ' . $assistant_id );\r\n }\r\n } elseif ($chatbot_chatgpt_assistant_alias == 'alternate') {\r\n\r\n $assistant_id = esc_attr(get_option('chatbot_chatgpt_assistant_id_alternate'));\r\n $additional_instructions = esc_attr(get_option('chatbot_chatgpt_assistant_instructions_alternate', ''));\r\n $use_assistant_id = 'Yes';\r\n\r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE' , 'Using Altrnate Assistant - $assistant_id: ' . $assistant_id);\r\n\r\n // Check if the GPT Assistant ID is blank, null, or \"Please provide the GPT Assistant ID.\"\r\n if (empty($assistant_id) || $assistant_id == \"Please provide the GPT Assistant Id.\") {\r\n\r\n /// Alternate assistant_id not set\r\n $chatbot_chatgpt_assistant_alias = 'original';\r\n $use_assistant_id = 'No';\r\n\r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE' ,'Falling back to ChatGPT API - $assistant_id: ' . $assistant_id );\r\n \r\n }\r\n } elseif (str_starts_with($assistant_id, 'asst_')) {\r\n\r\n $chatbot_chatgpt_assistant_alias = $assistant_id; // Belt & Suspenders\r\n $use_assistant_id = 'Yes';\r\n\r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE' ,'Assistant ID pass as a parameter - $assistant_id: ' . $assistant_id );\r\n\r\n } else {\r\n\r\n // Reference GPT Assistant IDs directly - Ver 1.7.3\r\n if (str_starts_with($chatbot_chatgpt_assistant_alias, 'asst_')) {\r\n\r\n // DIAG - Diagnostics - 2.0.5\r\n // back_trace( 'NOTICE', 'Using GPT Assistant ID: ' . $chatbot_chatgpt_assistant_alias);\r\n\r\n // Override the $assistant_id with the GPT Assistant ID\r\n $assistant_id = $chatbot_chatgpt_assistant_alias;\r\n $use_assistant_id = 'Yes';\r\n\r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE' , 'Using $assistant_id ' . $assistant_id);\r\n\r\n } else {\r\n\r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE', 'Using ChatGPT API: ' . $chatbot_chatgpt_assistant_alias);\r\n\r\n // Override the $use_assistant_id and set it to 'No'\r\n $use_assistant_id = 'No';\r\n \r\n // DIAG - Diagnostics - Ver 1.8.1\r\n // back_trace( 'NOTICE' , 'Falling back to ChatGPT API');\r\n\r\n }\r\n\r\n }\r\n\r\n // Decide whether to use Flow, Assistant or Original ChatGPT\r\n if ($model == 'flow'){\r\n \r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Using ChatGPT Flow');\r\n\r\n // Reload the model - BELT & SUSPENDERS\r\n $script_data_array['model'] = $model;\r\n\r\n // Get the step from the transient\r\n $kflow_step = get_chatbot_chatgpt_transients( 'kflow_step', null, null, $session_id);\r\n if (empty($kflow_step)) {\r\n $kflow_step = 0; // FIXME - Set to 1 or to zero?\r\n }\r\n\r\n // $thread_id\r\n $thread_id = '[answer=' . $kflow_step + 1 . ']';\r\n \r\n // Add +1 to $script_data_array['next_step']\r\n $kflow_step = $kflow_step + 1;\r\n\r\n // Set the next step\r\n set_chatbot_chatgpt_transients( 'kflow_step', $kflow_step, null, null, $session_id);\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', '$message: ' . $message);\r\n append_message_to_conversation_log($session_id, $user_id, $page_id, 'Visitor', $thread_id, $assistant_id, $message);\r\n\r\n // BELT & SUSPENDERS\r\n $thread_id = '';\r\n\r\n // Send message to ChatGPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_call_flow_api($api_key, $message);\r\n wp_send_json_success($response);\r\n\r\n } elseif ($use_assistant_id == 'Yes') {\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Using GPT Assistant ID: ' . $use_assistant_id);\r\n // back_trace( 'NOTICE', '$user_id ' . $user_id);\r\n // back_trace( 'NOTICE', '$page_id ' . $page_id);\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', '$message ' . $message);\r\n append_message_to_conversation_log($session_id, $user_id, $page_id, 'Visitor', $thread_id, $assistant_id, $message);\r\n \r\n // Send message to Custom GPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_custom_gpt_call_api($api_key, $message, $assistant_id, $thread_id, $user_id, $page_id);\r\n\r\n // Use TF-IDF to enhance response\r\n $chatbot_chatgpt_suppress_learnings = esc_attr(get_option('chatbot_chatgpt_suppress_learnings', 'Random'));\r\n if ( $chatbot_chatgpt_suppress_learnings != 'None') {\r\n $response = $response . chatbot_chatgpt_enhance_with_tfidf($message);\r\n }\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', '$response ' . print_r($response,true));\r\n append_message_to_conversation_log($session_id, $user_id, $page_id, 'Chatbot', $thread_id, $assistant_id, $response);\r\n\r\n // Clean (erase) the output buffer - Ver 1.6.8\r\n // Check if output buffering is active before attempting to clean it\r\n if (ob_get_level() > 0) {\r\n ob_clean();\r\n } else {\r\n // Optionally start output buffering if needed for your application\r\n // ob_start();\r\n }\r\n\r\n if (str_starts_with($response, 'Error:') || str_starts_with($response, 'Failed:')) {\r\n // Return response\r\n // back_trace( 'NOTICE', '$response ' . print_r($response,true));\r\n wp_send_json_error('Oops! Something went wrong on our end. Please try again later');\r\n } else {\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Check for links and images in response before returning');\r\n $response = chatbot_chatgpt_check_for_links_and_images($response);\r\n // Return response\r\n wp_send_json_success($response);\r\n }\r\n } else {\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Using ChatGPT');\r\n // back_trace( 'NOTICE', '$user_id ' . $user_id);\r\n // back_trace( 'NOTICE', '$page_id ' . $page_id);\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', '$message ' . $message);\r\n append_message_to_conversation_log($session_id, $user_id, $page_id, 'Visitor', $thread_id, $assistant_id, $message);\r\n \r\n // If $model starts with 'gpt' then the chatbot_chatgpt_call_api or 'dall' then chatbot_chatgpt_call_image_api\r\n // TRY NOT TO FETCH MODEL AGAIN\r\n // $model = esc_attr(get_option('chatbot_chatgpt_model_choice', 'gpt-3.5-turbo'));\r\n if (strpos($model, 'gpt-4o') !== false) {\r\n // The string 'gpt-4o' is found in $model\r\n // Reload the model - BELT & SUSPENDERS\r\n $script_data_array['model'] = $model;\r\n // Send message to ChatGPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_call_omni($api_key, $message);\r\n } elseif (str_starts_with($model, 'gpt')) {\r\n // Reload the model - BELT & SUSPENDERS\r\n $script_data_array['model'] = $model;\r\n // Send message to ChatGPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_call_api($api_key, $message);\r\n } elseif (str_starts_with($model, 'dall')) {\r\n // Reload the model - BELT & SUSPENDERS\r\n $script_data_array['model'] = $model;\r\n // Send message to Image API - Ver 1.9.4\r\n $response = chatbot_chatgpt_call_image_api($api_key, $message);\r\n } elseif (str_starts_with($model, 'tts')) {\r\n // Reload the model - BELT & SUSPENDERS\r\n $script_data_array['model'] = $model;\r\n $script_data_array['voice'] = $voice;\r\n // Send message to TTS API - Text-to-speech - Ver 1.9.5\r\n $response = chatbot_chatgpt_call_tts_api($api_key, $message, $voice, $user_id, $page_id, $session_id);\r\n } elseif (str_starts_with($model,'whisper')) {\r\n $script_data_array['model'] = $model;\r\n // Send message to STT API - Speech-to-text - Ver 1.9.6\r\n $response = chatbot_chatgpt_call_stt_api($api_key, $message);\r\n } else {\r\n // Reload the model - BELT & SUSPENDERS\r\n $script_data_array['model'] = $model;\r\n // Send message to ChatGPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_call_api($api_key, $message);\r\n }\r\n \r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', ['message' => 'BEFORE CALL TO ENHANCE TFIDF', 'response' => $response]);\r\n \r\n // Use TF-IDF to enhance response\r\n $chatbot_chatgpt_suppress_learnings = esc_attr(get_option('chatbot_chatgpt_suppress_learnings', 'Random'));\r\n if ( $chatbot_chatgpt_suppress_learnings != 'None') {\r\n $response = $response . chatbot_chatgpt_enhance_with_tfidf($message);\r\n }\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', ['message' => 'AFTER CALL TO ENHANCE TFIDF', 'response' => $response]);\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', '$response ' . print_r($response,true));\r\n append_message_to_conversation_log($session_id, $user_id, $page_id, 'Chatbot', $thread_id, $assistant_id, $response);\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Check for links and images in response before returning');\r\n $response = chatbot_chatgpt_check_for_links_and_images($response);\r\n\r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE', 'Response: ' . $response);\r\n\r\n // Return response\r\n wp_send_json_success($response);\r\n\r\n }\r\n\r\n wp_send_json_error('Oops, I fell through the cracks!');\r\n\r\n}\r\n\r\n// Add action to send messages - Ver 1.0.0\r\nadd_action('wp_ajax_chatbot_chatgpt_send_message', 'chatbot_chatgpt_send_message');\r\nadd_action('wp_ajax_nopriv_chatbot_chatgpt_send_message', 'chatbot_chatgpt_send_message');\r\n\r\n// Add action to upload files - Ver 1.7.6\r\nadd_action('wp_ajax_chatbot_chatgpt_upload_files', 'chatbot_chatgpt_upload_files');\r\nadd_action('wp_ajax_nopriv_chatbot_chatgpt_upload_files', 'chatbot_chatgpt_upload_files');\r\n\r\n// Add action to upload files - Ver 1.7.6\r\nadd_action('wp_ajax_chatbot_chatgpt_upload_mp3', 'chatbot_chatgpt_upload_mp3');\r\nadd_action('wp_ajax_nopriv_chatbot_chatgpt_upload_mp3', 'chatbot_chatgpt_upload_mp3');\r\n\r\n// Add action to erase conversation - Ver 1.8.6\r\nadd_action('wp_ajax_chatbot_chatgpt_erase_conversation', 'chatbot_chatgpt_erase_conversation_handler');\r\nadd_action('wp_ajax_nopriv_chatbot_chatgpt_erase_conversation', 'chatbot_chatgpt_erase_conversation_handler'); // For logged-out users, if needed\r\n\r\n// Settings and Deactivation - Ver 1.5.0\r\nadd_filter('plugin_action_links_' . plugin_basename(__FILE__), 'chatbot_chatgpt_plugin_action_links');\r\n\r\n// Crawler aka Knowledge Navigator - Ver 1.6.1\r\nfunction chatbot_chatgpt_kn_status_activation() {\r\n add_option('chatbot_chatgpt_kn_status', 'Never Run');\r\n // clear any old scheduled runs\r\n if (wp_next_scheduled('crawl_scheduled_event_hook')) {\r\n wp_clear_scheduled_hook('crawl_scheduled_event_hook');\r\n }\r\n // clear the 'knowledge_navigator_scan_hook' hook on plugin activation - Ver 1.6.3\r\n if (wp_next_scheduled('knowledge_navigator_scan_hook')) {\r\n // BREAK/FIX - Do not unset the hook - Ver 1.8.5\r\n // wp_clear_scheduled_hook('knowledge_navigator_scan_hook'); // Clear scheduled runs\r\n }\r\n}\r\nregister_activation_hook(__FILE__, 'chatbot_chatgpt_kn_status_activation');\r\n\r\n// Clean Up in Aisle 4\r\nfunction chatbot_chatgpt_kn_status_deactivation() {\r\n delete_option('chatbot_chatgpt_kn_status');\r\n wp_clear_scheduled_hook('knowledge_navigator_scan_hook'); \r\n}\r\nregister_deactivation_hook(__FILE__, 'chatbot_chatgpt_kn_status_deactivation');\r\n\r\n// Function to add a new message and response, keeping only the last five - Ver 1.6.1\r\nfunction addEntry($transient_name, $newEntry) {\r\n\r\n $context_history = get_transient($transient_name);\r\n if (!$context_history) {\r\n $context_history = [];\r\n }\r\n\r\n // Determine the total length of all existing entries\r\n $totalLength = 0;\r\n foreach ($context_history as $entry) {\r\n if (is_string($entry)) {\r\n $totalLength += strlen($entry);\r\n } elseif (is_array($entry)) {\r\n $totalLength += strlen(json_encode($entry)); // Convert to string if an array\r\n }\r\n }\r\n\r\n // IDEA - How will the new threading option from OpenAI change how this works?\r\n // Define thresholds for the number of entries to keep\r\n $maxEntries = 30; // Default maximum number of entries\r\n if ($totalLength > 5000) { // Higher threshold\r\n $maxEntries = 20;\r\n }\r\n if ($totalLength > 10000) { // Lower threshold\r\n $maxEntries = 10;\r\n }\r\n\r\n while (count($context_history) >= $maxEntries) {\r\n array_shift($context_history); // Remove the oldest element\r\n }\r\n\r\n if (is_array($newEntry)) {\r\n $newEntry = json_encode($newEntry); // Convert the array to a string\r\n }\r\n\r\n array_push($context_history, $newEntry); // Append the new element\r\n set_transient($transient_name, $context_history); // Update the transient\r\n}\r\n\r\n// Function to return message and response - Ver 1.6.1\r\nfunction concatenateHistory($transient_name) {\r\n $context_history = get_transient($transient_name);\r\n if (!$context_history) {\r\n return ''; // Return an empty string if the transient does not exist\r\n }\r\n return implode(' ', $context_history); // Concatenate the array values into a single string\r\n}\r\n\r\n// FIXME - MOVE CORE FUNCTIONS TO A SEPARATE FILE, LEAVING ONLY THE HOOKS HERE\r\n// Initialize the Greetings - Ver 1.6.1\r\nfunction enqueue_greetings_script( $initial_greeting = null, $subsequent_greeting = null) {\r\n\r\n // wp_enqueue_script('greetings', plugin_dir_url(__FILE__) . 'assets/js/greetings.js', array('jquery'), null, true);\r\n\r\n // If user is logged in, then modify greeting if greeting contains \"[...]\" or remove if not logged in - Ver 1.9.4\r\n if (is_user_logged_in()) {\r\n\r\n $current_user_id = get_current_user_id();\r\n $current_user = get_userdata($current_user_id);\r\n\r\n //Do this for Initial Greeting\r\n if ( empty($initial_greeting) ) {\r\n $initial_greeting = esc_attr(get_option('chatbot_chatgpt_initial_greeting', 'Hello! How can I help you today?'));\r\n }\r\n\r\n // Determine what the field name is between the brackets\r\n $user_field_name = '';\r\n $user_field_name = substr($initial_greeting, strpos($initial_greeting, '[') + 1, strpos($initial_greeting, ']') - strpos($initial_greeting, '[') - 1);\r\n // If $initial_greeting contains \"[$user_field_name]\" then replace with field from DB\r\n if (strpos($initial_greeting, '[' . $user_field_name . ']') !== false) {\r\n $initial_greeting = str_replace('[' . $user_field_name . ']', $current_user->$user_field_name, $initial_greeting);\r\n } else {\r\n $initial_greeting = str_replace('[' . $user_field_name . ']', '', $initial_greeting);\r\n // Remove the extra space when two spaces are present\r\n $initial_greeting = str_replace(' ', ' ', $initial_greeting);\r\n // Remove the extra space before punctuation including period, comma, exclamation mark, and question mark\r\n $initial_greeting = preg_replace('/\\s*([.,!?])/', '$1', $initial_greeting);\r\n }\r\n\r\n // Do this for Subsequent Greeting\r\n if ( empty($subsequent_greeting) ) {\r\n $subsequent_greeting = esc_attr(get_option('chatbot_chatgpt_subsequent_greeting', 'Hello again! How can I help you?'));\r\n }\r\n\r\n // Determine what the field name is between the brackets\r\n $user_field_name = '';\r\n $user_field_name = substr($subsequent_greeting, strpos($subsequent_greeting, '[') + 1, strpos($subsequent_greeting, ']') - strpos($subsequent_greeting, '[') - 1);\r\n // If $subsequent_greeting contains \"[$user_field_name]\" then replace with field from DB\r\n if (strpos($subsequent_greeting, '[' . $user_field_name . ']') !== false) {\r\n $subsequent_greeting = str_replace('[' . $user_field_name . ']', $current_user->$user_field_name, $subsequent_greeting);\r\n } else {\r\n $subsequent_greeting = str_replace('[' . $user_field_name . ']', '', $subsequent_greeting);\r\n // Remove the extra space when two spaces are present\r\n $subsequent_greeting = str_replace(' ', ' ', $subsequent_greeting);\r\n // Remove the extra space before punctuation including period, comma, exclamation mark, and question mark\r\n $subsequent_greeting = preg_replace('/\\s*([.,!?])/', '$1', $subsequent_greeting);\r\n }\r\n\r\n } else {\r\n\r\n //Do this for Initial Greeting\r\n if ( empty($initial_greeting) ) {\r\n $initial_greeting = esc_attr(get_option('chatbot_chatgpt_initial_greeting', 'Hello! How can I help you today?'));\r\n }\r\n\r\n $user_field_name = '';\r\n $user_field_name = substr($initial_greeting, strpos($initial_greeting, '[') + 1, strpos($initial_greeting, ']') - strpos($initial_greeting, '[') - 1 );\r\n\r\n // $initial_greeting = preg_replace('/\\s*\\[' . preg_quote($user_field_name, '/') . '\\]\\s*/', '', $initial_greeting);\r\n $initial_greeting = str_replace('[' . $user_field_name . ']', '', $initial_greeting);\r\n // Remove the extra space when two spaces are present\r\n $initial_greeting = str_replace(' ', ' ', $initial_greeting);\r\n // Remove the extra space before punctuation including period, comma, exclamation mark, and question mark\r\n $initial_greeting = preg_replace('/\\s*([.,!?])/', '$1', $initial_greeting);\r\n\r\n //Do this for Subsequent Greeting\r\n if ( empty($subsequent_greeting) ) {\r\n $subsequent_greeting = esc_attr(get_option('chatbot_chatgpt_subsequent_greeting', 'Hello again! How can I help you?'));\r\n }\r\n\r\n $user_field_name = '';\r\n $user_field_name = substr($subsequent_greeting, strpos($subsequent_greeting, '[') + 1, strpos($subsequent_greeting, ']') - strpos($subsequent_greeting, '[') - 1);\r\n\r\n // $subsequent_greeting = preg_replace('/\\s*\\[' . preg_quote($user_field_name, '/') . '\\]\\s*/', '', $subsequent_greeting);\r\n $subsequent_greeting = str_replace('[' . $user_field_name . ']', '', $subsequent_greeting);\r\n // Remove the extra space when two spaces are present\r\n $subsequent_greeting = str_replace(' ', ' ', $subsequent_greeting);\r\n // Remove the extra space before punctuation including period, comma, exclamation mark, and question mark\r\n $subsequent_greeting = preg_replace('/\\s*([.,!?])/', '$1', $subsequent_greeting); \r\n\r\n }\r\n\r\n $greetings = array(\r\n 'initial_greeting' => $initial_greeting,\r\n 'subsequent_greeting' => $subsequent_greeting,\r\n );\r\n\r\n // Original wp_localize_script call\r\n // wp_localize_script('greetings', 'greetings_data', $greetings);\r\n // Refactored using wp_add_inline_script - Ver 2.0.5 - 2024 07 06\r\n $greetings_json = wp_json_encode($greetings);\r\n // wp_add_inline_script('greetings', 'let greetings_data = ' . $greetings_json . ';', 'before');\r\n wp_add_inline_script('greetings', 'if (typeof greetings_data === \"undefined\") { var greetings_data = ' . $greetings_json . '; } else { greetings_data = ' . $greetings_json . '; }', 'before');\r\n\r\n return $greetings;\r\n\r\n}\r\n// \r\nadd_action('wp_enqueue_scripts', 'enqueue_greetings_script');\r\n\r\n// Add the color picker to the adaptive appearance settings section - Ver 1.8.1\r\nfunction enqueue_color_picker($hook_suffix) {\r\n // first check that $hook_suffix is appropriate for your admin page\r\n wp_enqueue_style('wp-color-picker');\r\n wp_enqueue_script('my-script-handle', plugin_dir_url(__FILE__) . 'assets/js/chatbot-chatgpt-color-picker.js', array('wp-color-picker'), false, true);\r\n}\r\nadd_action('admin_enqueue_scripts', 'enqueue_color_picker');\r\n\r\n// Determine if the plugin is installed\r\nfunction kchat_get_plugin_version() {\r\n\r\n if (!function_exists('get_plugin_data')) {\r\n require_once(ABSPATH . 'wp-admin/includes/plugin.php');\r\n }\r\n\r\n $plugin_data = get_plugin_data(plugin_dir_path(__FILE__) . 'chatbot-chatgpt.php');\r\n $plugin_version = $plugin_data['Version'];\r\n update_option('chatbot_chatgpt_plugin_version', $plugin_version);\r\n // DIAG - Log the plugin version\r\n // back_trace( 'NOTICE', 'Plugin version '. $plugin_version);\r\n\r\n return $plugin_version;\r\n\r\n}\r\n\r\n"}, "e6670437117240aa1e350cd1eaccbea61c6125d8": {"t": 1785756417.7615628, "n": 53887, "h": "300981938dd76ffb", "c": " $user_id,\r\n 'page_id' => $page_id,\r\n 'session_id' => $session_id,\r\n 'thread_id' => $thread_id,\r\n 'assistant_id' => $assistant_id,\r\n 'additional_instructions' => $additional_instructions,\r\n 'model' => $model,\r\n 'voice' => $voice,\r\n );\r\n\r\n // DIAG - Diagnostics - Ver 1.8.6\r\n // back_trace( 'NOTICE', '$user_id: ' . $user_id);\r\n // back_trace( 'NOTICE', '$page_id: ' . $page_id);\r\n // back_trace( 'NOTICE', '$session_id: ' . $session_id);\r\n // back_trace( 'NOTICE', '$thread_id: ' . $thread_id);\r\n // back_trace( 'NOTICE', '$assistant_id: ' . $assistant_id);\r\n // back_trace( 'NOTICE', '$additional_instructions: ' . $additional_instructions);\r\n // back_trace( 'NOTICE', '$model: ' . $model);\r\n \r\n // Defaults for Ver 1.6.1\r\n $defaults = array(\r\n 'chatbot_chatgpt_bot_name' => 'Kognetiks Chatbot',\r\n 'chatbot_chatgpt_bot_prompt' => 'Enter your question ...',\r\n 'chatbot_chatgpt_initial_greeting' => 'Hello! How can I help you today?',\r\n 'chatbot_chatgpt_subsequent_greeting' => 'Hello again! How can I help you?',\r\n 'chatbot_chatgpt_display_style' => 'floating',\r\n 'chatbot_chatgpt_assistant_alias' => 'primary',\r\n 'chatbot_chatgpt_start_status' => 'closed',\r\n 'chatbot_chatgpt_start_status_new_visitor' => 'closed',\r\n 'chatbot_chatgpt_disclaimer_setting' => 'No',\r\n 'chatbot_chatgpt_audience_choice' => 'all',\r\n 'chatbot_chatgpt_max_tokens_setting' => '150',\r\n 'chatbot_chatgpt_message_limit_setting' => '999',\r\n 'chatbot_chatgpt_width_setting' => 'Narrow',\r\n 'chatbot_chatgpt_diagnostics' => 'Off',\r\n 'chatbot_chatgpt_custom_error_message' => 'Your custom error message goes here.',\r\n 'chatbot_chatgpt_avatar_icon_setting' => 'icon-001.png',\r\n 'chatbot_chatgpt_avatar_icon_url_setting' => '',\r\n 'chatbot_chatgpt_custom_avatar_icon_setting' => '',\r\n 'chatbot_chatgpt_avatar_greeting_setting' => 'Howdy!!! Great to see you today! How can I help you?',\r\n 'chatbot_chatgpt_model_choice' => 'gpt-3.5-turbo',\r\n 'chatbot_chatgpt_conversation_context' => 'You are a versatile, friendly, and helpful assistant designed to support me in a variety of tasks that responds in Markdown.',\r\n 'chatbot_chatgpt_enable_custom_buttons' => 'Off',\r\n 'chatbot_chatgpt_custom_button_name_1' => '',\r\n 'chatbot_chatgpt_custom_button_url_1' => '',\r\n 'chatbot_chatgpt_custom_button_name_2' => '',\r\n 'chatbot_chatgpt_custom_button_url_2' => '',\r\n 'chatbot_chatgpt_custom_button_name_3' => '',\r\n 'chatbot_chatgpt_custom_button_url_3' => '',\r\n 'chatbot_chatgpt_custom_button_name_4' => '',\r\n 'chatbot_chatgpt_custom_button_url_4' => '',\r\n 'chatbot_chatgpt_allow_file_uploads' => 'No',\r\n 'chatbot_chatgpt_timeout_setting' => '240',\r\n 'chatbot_chatgpt_voice_option' => 'alloy',\r\n 'chatbot_chatgpt_audio_output_format' => 'mp3',\r\n 'chatbot_chatgpt_force_page_reload' => 'No',\r\n );\r\n\r\n // Revised for Ver 1.5.0 \r\n $option_keys = array(\r\n 'chatbot_chatgpt_bot_name',\r\n 'chatbot_chatgpt_bot_prompt',\r\n 'chatbot_chatgpt_initial_greeting',\r\n 'chatbot_chatgpt_subsequent_greeting',\r\n 'chatbot_chatgpt_display_style',\r\n 'chatbot_chatgpt_assistant_alias',\r\n 'chatbot_chatgpt_start_status',\r\n 'chatbot_chatgpt_start_status_new_visitor',\r\n 'chatbot_chatgpt_disclaimer_setting',\r\n 'chatbot_chatgpt_audience_choice',\r\n 'chatbot_chatgpt_max_tokens_setting',\r\n 'chatbot_chatgpt_message_limit_setting',\r\n 'chatbot_chatgpt_width_setting',\r\n 'chatbot_chatgpt_diagnostics',\r\n 'chatbot_chatgpt_custom_error_message',\r\n 'chatbot_chatgpt_avatar_icon_setting',\r\n 'chatbot_chatgpt_avatar_icon_url_setting',\r\n 'chatbot_chatgpt_custom_avatar_icon_setting',\r\n 'chatbot_chatgpt_avatar_greeting_setting',\r\n 'chatbot_chatgpt_enable_custom_buttons',\r\n 'chatbot_chatgpt_custom_button_name_1',\r\n 'chatbot_chatgpt_custom_button_url_1',\r\n 'chatbot_chatgpt_custom_button_name_2',\r\n 'chatbot_chatgpt_custom_button_url_2',\r\n 'chatbot_chatgpt_custom_button_name_3',\r\n 'chatbot_chatgpt_custom_button_url_3',\r\n 'chatbot_chatgpt_custom_button_name_4',\r\n 'chatbot_chatgpt_custom_button_url_4',\r\n 'chatbot_chatgpt_allow_file_uploads',\r\n 'chatbot_chatgpt_timeout_setting',\r\n 'chatbot_chatgpt_voice_option',\r\n 'chatbot_chatgpt_audio_output_format',\r\n 'chatbot_chatgpt_force_page_reload',\r\n );\r\n\r\n global $chatbot_settings;\r\n $chatbot_settings = array();\r\n foreach ($option_keys as $key) {\r\n $default_value = $defaults[$key] ?? '';\r\n $chatbot_settings[$key] = esc_attr(get_option($key, $default_value));\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'chatbot-chatgpt.php: Key: ' . $key . ', Value: ' . $chatbot_settings[$key]);\r\n }\r\n\r\n // Set visitor and logged in user limits - Ver 2.0.1\r\n if (is_user_logged_in()) {\r\n // back_trace( 'NOTICE', 'User is logged in');\r\n $chatbot_settings['chatbot_chatgpt_message_limit_setting'] = esc_attr(get_option('chatbot_chatgpt_message_limit_setting', '999'));\r\n } else {\r\n // back_trace( 'NOTICE', 'User is NOT logged in');\r\n $chatbot_settings['chatbot_chatgpt_message_limit_setting'] = esc_attr(get_option('chatbot_chatgpt_visitor_message_limit_setting', '999'));\r\n }\r\n \r\n $chatbot_settings['chatbot_chatgpt_icon_base_url'] = plugins_url( '/assets/icons/', __FILE__ );\r\n\r\n // Original wp_localize_script call\r\n // wp_localize_script('chatbot-chatgpt-js', 'php_vars', $script_data_array);\r\n // Refactored using wp_add_inline_script - Ver 2.0.5 - 2024 07 06\r\n $script_data_json = wp_json_encode($script_data_array);\r\n wp_add_inline_script('chatbot-chatgpt-js', 'if (typeof php_vars === \"undefined\") { var php_vars = ' . $script_data_json . '; } else { php_vars = ' . $script_data_json . '; }', 'before');\r\n \r\n // Original wp_localize_script call\r\n // wp_localize_script('chatbot-chatgpt-js', 'plugin_vars', array(\r\n // 'plugins_url' => plugins_url('', __FILE__ ),\r\n // ));\r\n // Refactored using wp_add_inline_script - Ver 2.0.5 - 2024 07 06\r\n $plugin_vars = array(\r\n 'plugins_url' => plugins_url('', __FILE__ ),\r\n );\r\n $plugin_vars_json = wp_json_encode($plugin_vars);\r\n wp_add_inline_script('chatbot-chatgpt-js', 'let plugin_vars = ' . $plugin_vars_json . ';', 'before');\r\n\r\n // Original wp_localize_script call\r\n // wp_localize_script('chatbot-chatgpt-local', 'chatbotSettings', $chatbot_settings);\r\n // Refactored using wp_add_inline_script - Ver 2.0.5 - 2024 07 06\r\n $chatbotSettings_json = wp_json_encode($chatbot_settings);\r\n wp_add_inline_script('chatbot-chatgpt-local', 'if (typeof chatbotSettings === \"undefined\") { var chatbotSettings = ' . $chatbotSettings_json . '; } else { chatbotSettings = ' . $chatbotSettings_json . '; }', 'before');\r\n \r\n // Original wp_localize_script call\r\n // wp_localize_script('chatbot-chatgpt-js', 'chatbot_chatgpt_params', array(\r\n // 'plugins_url' => plugins_url('', __FILE__ ),\r\n // 'ajax_url' => admin_url('admin-ajax.php'),\r\n // ));\r\n // Original wp_localize_script call\r\n // Upload files - Ver 1.7.6\r\n // wp_localize_script('chatbot-chatgpt-upload-trigger-js', 'chatbot_chatgpt_params', array(\r\n // 'plugins_url' => plugins_url('', __FILE__ ),\r\n // 'ajax_url' => admin_url('admin-ajax.php'),\r\n // ));\r\n // Refactored using wp_add_inline_script - Ver 2.0.5 - 2024 07 06\r\n $chatbot_chatgpt_params = array(\r\n 'plugins_url' => plugins_url('', __FILE__ ),\r\n 'ajax_url' => admin_url('admin-ajax.php'),\r\n );\r\n $chatbot_chatgpt_params_json = wp_json_encode($chatbot_chatgpt_params);\r\n wp_add_inline_script('chatbot-chatgpt-js', 'if (typeof chatbot_chatgpt_params === \"undefined\") { var chatbot_chatgpt_params = ' . $chatbot_chatgpt_params_json . '; } else { chatbot_chatgpt_params = ' . $chatbot_chatgpt_params_json . '; }', 'before');\r\n wp_add_inline_script('chatbot-chatgpt-upload-trigger-js', 'if (typeof chatbot_chatgpt_params === \"undefined\") { var chatbot_chatgpt_params = ' . $chatbot_chatgpt_params_json . '; } else { chatbot_chatgpt_params = ' . $chatbot_chatgpt_params_json . '; }', 'before');\r\n \r\n}\r\nadd_action('wp_enqueue_scripts', 'chatbot_chatgpt_enqueue_scripts');\r\n\r\n// Settings and Deactivation Links - Ver - 1.5.0\r\nif (!function_exists('enqueue_jquery_ui')) {\r\n function enqueue_jquery_ui() {\r\n wp_enqueue_style('wp-jquery-ui-dialog');\r\n wp_enqueue_script('jquery-ui-dialog');\r\n }\r\n add_action( 'admin_enqueue_scripts', 'enqueue_jquery_ui' );\r\n}\r\n\r\n// Schedule Cleanup of Expired Transients\r\nif (!wp_next_scheduled('chatbot_chatgpt_cleanup_event')) {\r\n wp_schedule_event(time(), 'daily', 'chatbot_chatgpt_cleanup_event');\r\n}\r\nadd_action('chatbot_chatgpt_cleanup_event', 'clean_specific_expired_transients');\r\n\r\n// Schedule Conversation Log Cleanup - Ver 1.6.7\r\nif (!wp_next_scheduled('chatbot_chatgpt_conversation_log_cleanup_event')) {\r\n wp_schedule_event(time(), 'daily', 'chatbot_chatgpt_conversation_log_cleanup_event');\r\n}\r\nadd_action('chatbot_chatgpt_conversation_log_cleanup_event', 'chatbot_chatgpt_conversation_log_cleanup');\r\n\r\n// Schedule the transcript file cleanup event if it's not already scheduled - Ver 1.9.9\r\n// Schedule the cleanup event if it's not already scheduled\r\nif (!wp_next_scheduled('chatbot_chatgpt_cleanup_transcript_files')) {\r\n wp_schedule_event(time(), 'hourly', 'chatbot_chatgpt_cleanup_transcript_files');\r\n}\r\n\r\n// Deactivate old hooks - Ver 2.0.1\r\nif(esc_attr(get_option('chatbot_chatgpt_cleanup_old_hooks') !== 'Completed')) {\r\n // Deactivate old hooks - Ver 2.0.1\r\n wp_clear_scheduled_hook('chatbot_chatgpt_cleanup_transcripts');\r\n // Then update the option\r\n update_option('chatbot_chatgpt_cleanup_old_hooks', 'Completed');\r\n}\r\n\r\n// Schedule the audio file cleanup event if it's not already scheduled - Ver 1.9.9\r\n// Schedule the cleanup event if it's not already scheduled\r\nif (!wp_next_scheduled('chatbot_chatgpt_cleanup_audio_files')) {\r\n wp_schedule_event(time(), 'hourly', 'chatbot_chatgpt_cleanup_audio_files');\r\n}\r\n\r\n// Schedule the upload file cleanup event if it's not already scheduled - Ver 1.9.9\r\n// Schedule the cleanup event if it's not already scheduled\r\nif (!wp_next_scheduled('chatbot_chatgpt_cleanup_upload_files')) {\r\n wp_schedule_event(time(), 'hourly', 'chatbot_chatgpt_cleanup_upload_files');\r\n}\r\n\r\n// Schedule the download file cleanup event if it's not already scheduled - Ver 2.0.3\r\n// Schedule the cleanup event if it's not already scheduled\r\nif (!wp_next_scheduled('chatbot_chatgpt_cleanup_download_files')) {\r\n wp_schedule_event(time(), 'hourly', 'chatbot_chatgpt_cleanup_download_files');\r\n}\r\n\r\n// Add the Assistant table to the database - Ver 2.0.4\r\ncreate_chatbot_chatgpt_assistants_table();\r\n\r\n// Handle Ajax requests\r\nfunction chatbot_chatgpt_send_message() {\r\n\r\n // Global variables\r\n global $session_id;\r\n global $user_id;\r\n global $page_id;\r\n global $thread_id;\r\n global $assistant_id;\r\n global $chatbot_chatgpt_display_style;\r\n global $chatbot_chatgpt_assistant_alias;\r\n global $script_data_array;\r\n global $additional_instructions;\r\n global $model;\r\n global $voice;\r\n\r\n global $flow_data;\r\n\r\n $api_key = '';\r\n\r\n // Retrieve the API key\r\n $api_key = esc_attr(get_option('chatbot_chatgpt_api_key'));\r\n\r\n // Retrieve the GPT Model\r\n if (!empty($model)) {\r\n $model = esc_attr(get_option('chatbot_chatgpt_model_choice', 'gpt-3.5-turbo'));\r\n // DIAG - Diagnostics\r\n // back_trace ( 'NOTICE', 'Model from options: ' . $model);\r\n } else {\r\n // SEE IF $script_data_array HAS THE MODEL\r\n if ( isset($script_data_array['model'])) {\r\n $model = $script_data_array['model'];\r\n // DIAG - Diagnostics\r\n // back_trace ( 'NOTICE', 'Model set in global: ' . $model);\r\n } else {\r\n // Set the model to the default\r\n $model = esc_attr(get_option('chatbot_chatgpt_model_choice', 'gpt-3.5-turbo'));\r\n // DIAG - Diagnostics\r\n // back_trace ( 'ERROR', 'Model not set!!!');\r\n // wp_send_json_error('Invalid Model. Please set the model in the plugin settings.');\r\n }\r\n }\r\n\r\n // Retrieve the Max tokens - Ver 1.4.2\r\n $max_tokens = esc_attr(get_option('chatbot_chatgpt_max_tokens_setting', 150));\r\n\r\n // Send only clean text via the API\r\n $message = sanitize_text_field($_POST['message']);\r\n\r\n // Check for missing API key or Message\r\n if (!$api_key || !$message) {\r\n wp_send_json_error('Error: Invalid API key or Message. Please check the plugin settings.');\r\n }\r\n\r\n // Removed in Ver 1.8.6 - 2024 02 15\r\n // $thread_id = '';\r\n // $assistant_id = '';\r\n // $user_id = '';\r\n // $page_id = '';\r\n \r\n // Check the transient for the Assistant ID - Ver 1.7.2\r\n $user_id = intval($_POST['user_id']);\r\n $page_id = intval($_POST['page_id']);\r\n\r\n // DIAG - Diagnostics - Ver 1.8.6\r\n // back_trace( 'NOTICE', 'chatbot_chatgpt_send_message $user_id: ' . $user_id);\r\n // back_trace( 'NOTICE', 'chatbot_chatgpt_send_message $page_id: ' . $page_id);\r\n\r\n $chatbot_settings['display_style'] = get_chatbot_chatgpt_transients( 'display_style', $user_id, $page_id);\r\n $chatbot_settings['assistant_alias'] = get_chatbot_chatgpt_transients( 'assistant_alias', $user_id, $page_id);\r\n $chatbot_settings['assistantID'] = get_chatbot_chatgpt_transients( 'assistant_id', $user_id, $page_id);\r\n // back_trace ( 'NOTICE', 'chatbot_chatgpt_send_message $chatbot_settings[assistantID]: ' . $chatbot_settings['assistantID']);\r\n $chatbot_settings['threadID'] = get_chatbot_chatgpt_transients( 'thread_id', $user_id, $page_id);\r\n // back_trace ( 'NOTICE', 'chatbot_chatgpt_send_message $chatbot_settings[threadID]: ' . $chatbot_settings['threadID']);\r\n $chatbot_settings['model'] = get_chatbot_chatgpt_transients( 'model', $user_id, $page_id);\r\n $chatbot_settings['voice'] = get_chatbot_chatgpt_transients( 'voice', $user_id, $page_id);\r\n $voice = $chatbot_settings['voice'];\r\n\r\n $display_style = isset($chatbot_settings['display_style']) ? $chatbot_settings['display_style'] : '';\r\n $chatbot_chatgpt_assistant_alias = isset($chatbot_settings['assistant_alias']) ? $chatbot_settings['assistant_alias'] : '';\r\n\r\n $temp_model = $chatbot_settings['model']; // Store the model in a temporary variable before overwriting $chatbot_settings\r\n\r\n $chatbot_settings = get_chatbot_chatgpt_threads($user_id, $page_id);\r\n\r\n $chatbot_settings['model'] = $temp_model; // Restore the model after overwriting $chatbot_settings\r\n\r\n $assistant_id = isset($chatbot_settings['assistantID']) ? $chatbot_settings['assistantID'] : '';\r\n $thread_Id = isset($chatbot_settings['threadID']) ? $chatbot_settings['threadID'] : '';\r\n $model = isset($chatbot_settings['model']) ? $chatbot_settings['model'] : '';\r\n\r\n // DIAG - Diagnostics - Ver 1.8.6\r\n // back_trace( 'NOTICE', '$user_id: ' . $user_id);\r\n // back_trace( 'NOTICE', '$page_id: ' . $page_id);\r\n // back_trace( 'NOTICE', '$session_id: ' . $session_id);\r\n // back_trace( 'NOTICE', '$thread_id: ' . $thread_id);\r\n // back_trace( 'NOTICE', '$assistant_id: ' . $assistant_id);\r\n // back_trace( 'NOTICE', '$model: ' . $model);\r\n\r\n // Assistants\r\n // $chatbot_chatgpt_assistant_alias == 'original'; // Default\r\n // $chatbot_chatgpt_assistant_alias == 'primary';\r\n // $chatbot_chatgpt_assistant_alias == 'alternate';\r\n // $chatbot_chatgpt_assistant_alias == 'asst_xxxxxxxxxxxxxxxxxxxxxxxx'; // GPT Assistant Id\r\n \r\n // Which Assistant ID to use - Ver 1.7.2\r\n if ($chatbot_chatgpt_assistant_alias == 'original') {\r\n\r\n $use_assistant_id = 'No';\r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE' , 'Using Original ChatGPT - $chatbot_chatgpt_assistant_alias: ' . $chatbot_chatgpt_assistant_alias);\r\n\r\n } elseif ($chatbot_chatgpt_assistant_alias == 'primary') {\r\n\r\n $assistant_id = esc_attr(get_option('chatbot_chatgpt_assistant_id'));\r\n $additional_instructions = esc_attr(get_option('chatbot_chatgpt_assistant_instructions', ''));\r\n $use_assistant_id = 'Yes';\r\n\r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE' , 'Using Primary Assistant - $assistant_id: ' . $assistant_id);\r\n \r\n // Check if the GPT Assistant ID is blank, null, or \"Please provide the GPT Assistant ID.\"\r\n if (empty($assistant_id) || $assistant_id == \"Please provide the GPT Assistant Id.\") {\r\n \r\n // Primary assistant_id not set\r\n $chatbot_chatgpt_assistant_alias = 'original';\r\n $use_assistant_id = 'No';\r\n \r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE' ,'Falling back to ChatGPT API - $assistant_id: ' . $assistant_id );\r\n }\r\n } elseif ($chatbot_chatgpt_assistant_alias == 'alternate') {\r\n\r\n $assistant_id = esc_attr(get_option('chatbot_chatgpt_assistant_id_alternate'));\r\n $additional_instructions = esc_attr(get_option('chatbot_chatgpt_assistant_instructions_alternate', ''));\r\n $use_assistant_id = 'Yes';\r\n\r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE' , 'Using Altrnate Assistant - $assistant_id: ' . $assistant_id);\r\n\r\n // Check if the GPT Assistant ID is blank, null, or \"Please provide the GPT Assistant ID.\"\r\n if (empty($assistant_id) || $assistant_id == \"Please provide the GPT Assistant Id.\") {\r\n\r\n /// Alternate assistant_id not set\r\n $chatbot_chatgpt_assistant_alias = 'original';\r\n $use_assistant_id = 'No';\r\n\r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE' ,'Falling back to ChatGPT API - $assistant_id: ' . $assistant_id );\r\n \r\n }\r\n } elseif (str_starts_with($assistant_id, 'asst_')) {\r\n\r\n $chatbot_chatgpt_assistant_alias = $assistant_id; // Belt & Suspenders\r\n $use_assistant_id = 'Yes';\r\n\r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE' ,'Assistant ID pass as a parameter - $assistant_id: ' . $assistant_id );\r\n\r\n } else {\r\n\r\n // Reference GPT Assistant IDs directly - Ver 1.7.3\r\n if (str_starts_with($chatbot_chatgpt_assistant_alias, 'asst_')) {\r\n\r\n // DIAG - Diagnostics - 2.0.5\r\n // back_trace( 'NOTICE', 'Using GPT Assistant ID: ' . $chatbot_chatgpt_assistant_alias);\r\n\r\n // Override the $assistant_id with the GPT Assistant ID\r\n $assistant_id = $chatbot_chatgpt_assistant_alias;\r\n $use_assistant_id = 'Yes';\r\n\r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE' , 'Using $assistant_id ' . $assistant_id);\r\n\r\n } else {\r\n\r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE', 'Using ChatGPT API: ' . $chatbot_chatgpt_assistant_alias);\r\n\r\n // Override the $use_assistant_id and set it to 'No'\r\n $use_assistant_id = 'No';\r\n \r\n // DIAG - Diagnostics - Ver 1.8.1\r\n // back_trace( 'NOTICE' , 'Falling back to ChatGPT API');\r\n\r\n }\r\n\r\n }\r\n\r\n // Decide whether to use Flow, Assistant or Original ChatGPT\r\n if ($model == 'flow'){\r\n \r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Using ChatGPT Flow');\r\n\r\n // Reload the model - BELT & SUSPENDERS\r\n $script_data_array['model'] = $model;\r\n\r\n // Get the step from the transient\r\n $kflow_step = get_chatbot_chatgpt_transients( 'kflow_step', null, null, $session_id);\r\n if (empty($kflow_step)) {\r\n $kflow_step = 0; // FIXME - Set to 1 or to zero?\r\n }\r\n\r\n // $thread_id\r\n $thread_id = '[answer=' . $kflow_step + 1 . ']';\r\n \r\n // Add +1 to $script_data_array['next_step']\r\n $kflow_step = $kflow_step + 1;\r\n\r\n // Set the next step\r\n set_chatbot_chatgpt_transients( 'kflow_step', $kflow_step, null, null, $session_id);\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', '$message: ' . $message);\r\n append_message_to_conversation_log($session_id, $user_id, $page_id, 'Visitor', $thread_id, $assistant_id, $message);\r\n\r\n // BELT & SUSPENDERS\r\n $thread_id = '';\r\n\r\n // Send message to ChatGPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_call_flow_api($api_key, $message);\r\n wp_send_json_success($response);\r\n\r\n } elseif ($use_assistant_id == 'Yes') {\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Using GPT Assistant ID: ' . $use_assistant_id);\r\n // back_trace( 'NOTICE', '$user_id ' . $user_id);\r\n // back_trace( 'NOTICE', '$page_id ' . $page_id);\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', '$message ' . $message);\r\n append_message_to_conversation_log($session_id, $user_id, $page_id, 'Visitor', $thread_id, $assistant_id, $message);\r\n \r\n // Send message to Custom GPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_custom_gpt_call_api($api_key, $message, $assistant_id, $thread_id, $user_id, $page_id);\r\n\r\n // Use TF-IDF to enhance response\r\n $chatbot_chatgpt_suppress_learnings = esc_attr(get_option('chatbot_chatgpt_suppress_learnings', 'Random'));\r\n if ( $chatbot_chatgpt_suppress_learnings != 'None') {\r\n $response = $response . chatbot_chatgpt_enhance_with_tfidf($message);\r\n }\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', '$response ' . print_r($response,true));\r\n append_message_to_conversation_log($session_id, $user_id, $page_id, 'Chatbot', $thread_id, $assistant_id, $response);\r\n\r\n // Clean (erase) the output buffer - Ver 1.6.8\r\n // Check if output buffering is active before attempting to clean it\r\n if (ob_get_level() > 0) {\r\n ob_clean();\r\n } else {\r\n // Optionally start output buffering if needed for your application\r\n // ob_start();\r\n }\r\n\r\n if (str_starts_with($response, 'Error:') || str_starts_with($response, 'Failed:')) {\r\n // Return response\r\n // back_trace( 'NOTICE', '$response ' . print_r($response,true));\r\n wp_send_json_error('Oops! Something went wrong on our end. Please try again later');\r\n } else {\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Check for links and images in response before returning');\r\n $response = chatbot_chatgpt_check_for_links_and_images($response);\r\n // Return response\r\n wp_send_json_success($response);\r\n }\r\n } else {\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Using ChatGPT');\r\n // back_trace( 'NOTICE', '$user_id ' . $user_id);\r\n // back_trace( 'NOTICE', '$page_id ' . $page_id);\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', '$message ' . $message);\r\n append_message_to_conversation_log($session_id, $user_id, $page_id, 'Visitor', $thread_id, $assistant_id, $message);\r\n \r\n // If $model starts with 'gpt' then the chatbot_chatgpt_call_api or 'dall' then chatbot_chatgpt_call_image_api\r\n // TRY NOT TO FETCH MODEL AGAIN\r\n // $model = esc_attr(get_option('chatbot_chatgpt_model_choice', 'gpt-3.5-turbo'));\r\n if (strpos($model, 'gpt-4o') !== false) {\r\n // The string 'gpt-4o' is found in $model\r\n // Reload the model - BELT & SUSPENDERS\r\n $script_data_array['model'] = $model;\r\n // Send message to ChatGPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_call_omni($api_key, $message);\r\n } elseif (str_starts_with($model, 'gpt')) {\r\n // Reload the model - BELT & SUSPENDERS\r\n $script_data_array['model'] = $model;\r\n // Send message to ChatGPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_call_api($api_key, $message);\r\n } elseif (str_starts_with($model, 'dall')) {\r\n // Reload the model - BELT & SUSPENDERS\r\n $script_data_array['model'] = $model;\r\n // Send message to Image API - Ver 1.9.4\r\n $response = chatbot_chatgpt_call_image_api($api_key, $message);\r\n } elseif (str_starts_with($model, 'tts')) {\r\n // Reload the model - BELT & SUSPENDERS\r\n $script_data_array['model'] = $model;\r\n $script_data_array['voice'] = $voice;\r\n // Send message to TTS API - Text-to-speech - Ver 1.9.5\r\n $response = chatbot_chatgpt_call_tts_api($api_key, $message, $voice, $user_id, $page_id, $session_id);\r\n } elseif (str_starts_with($model,'whisper')) {\r\n $script_data_array['model'] = $model;\r\n // Send message to STT API - Speech-to-text - Ver 1.9.6\r\n $response = chatbot_chatgpt_call_stt_api($api_key, $message);\r\n } else {\r\n // Reload the model - BELT & SUSPENDERS\r\n $script_data_array['model'] = $model;\r\n // Send message to ChatGPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_call_api($api_key, $message);\r\n }\r\n \r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', ['message' => 'BEFORE CALL TO ENHANCE TFIDF', 'response' => $response]);\r\n \r\n // Use TF-IDF to enhance response\r\n $chatbot_chatgpt_suppress_learnings = esc_attr(get_option('chatbot_chatgpt_suppress_learnings', 'Random'));\r\n if ( $chatbot_chatgpt_suppress_learnings != 'None') {\r\n $response = $response . chatbot_chatgpt_enhance_with_tfidf($message);\r\n }\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', ['message' => 'AFTER CALL TO ENHANCE TFIDF', 'response' => $response]);\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', '$response ' . print_r($response,true));\r\n append_message_to_conversation_log($session_id, $user_id, $page_id, 'Chatbot', $thread_id, $assistant_id, $response);\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Check for links and images in response before returning');\r\n $response = chatbot_chatgpt_check_for_links_and_images($response);\r\n\r\n // DIAG - Diagnostics - Ver 2.0.5\r\n // back_trace( 'NOTICE', 'Response: ' . $response);\r\n\r\n // Return response\r\n wp_send_json_success($response);\r\n\r\n }\r\n\r\n wp_send_json_error('Oops, I fell through the cracks!');\r\n\r\n}\r\n\r\n// Add action to send messages - Ver 1.0.0\r\nadd_action('wp_ajax_chatbot_chatgpt_send_message', 'chatbot_chatgpt_send_message');\r\nadd_action('wp_ajax_nopriv_chatbot_chatgpt_send_message', 'chatbot_chatgpt_send_message');\r\n\r\n// Add action to upload files - Ver 1.7.6\r\nadd_action('wp_ajax_chatbot_chatgpt_upload_files', 'chatbot_chatgpt_upload_files');\r\nadd_action('wp_ajax_nopriv_chatbot_chatgpt_upload_files', 'chatbot_chatgpt_upload_files');\r\n\r\n// Add action to upload files - Ver 1.7.6\r\nadd_action('wp_ajax_chatbot_chatgpt_upload_mp3', 'chatbot_chatgpt_upload_mp3');\r\nadd_action('wp_ajax_nopriv_chatbot_chatgpt_upload_mp3', 'chatbot_chatgpt_upload_mp3');\r\n\r\n// Add action to erase conversation - Ver 1.8.6\r\nadd_action('wp_ajax_chatbot_chatgpt_erase_conversation', 'chatbot_chatgpt_erase_conversation_handler');\r\nadd_action('wp_ajax_nopriv_chatbot_chatgpt_erase_conversation', 'chatbot_chatgpt_erase_conversation_handler'); // For logged-out users, if needed\r\n\r\n// Settings and Deactivation - Ver 1.5.0\r\nadd_filter('plugin_action_links_' . plugin_basename(__FILE__), 'chatbot_chatgpt_plugin_action_links');\r\n\r\n// Crawler aka Knowledge Navigator - Ver 1.6.1\r\nfunction chatbot_chatgpt_kn_status_activation() {\r\n add_option('chatbot_chatgpt_kn_status', 'Never Run');\r\n // clear any old scheduled runs\r\n if (wp_next_scheduled('crawl_scheduled_event_hook')) {\r\n wp_clear_scheduled_hook('crawl_scheduled_event_hook');\r\n }\r\n // clear the 'knowledge_navigator_scan_hook' hook on plugin activation - Ver 1.6.3\r\n if (wp_next_scheduled('knowledge_navigator_scan_hook')) {\r\n // BREAK/FIX - Do not unset the hook - Ver 1.8.5\r\n // wp_clear_scheduled_hook('knowledge_navigator_scan_hook'); // Clear scheduled runs\r\n }\r\n}\r\nregister_activation_hook(__FILE__, 'chatbot_chatgpt_kn_status_activation');\r\n\r\n// Clean Up in Aisle 4\r\nfunction chatbot_chatgpt_kn_status_deactivation() {\r\n delete_option('chatbot_chatgpt_kn_status');\r\n wp_clear_scheduled_hook('knowledge_navigator_scan_hook'); \r\n}\r\nregister_deactivation_hook(__FILE__, 'chatbot_chatgpt_kn_status_deactivation');\r\n\r\n// Function to add a new message and response, keeping only the last five - Ver 1.6.1\r\nfunction addEntry($transient_name, $newEntry) {\r\n\r\n $context_history = get_transient($transient_name);\r\n if (!$context_history) {\r\n $context_history = [];\r\n }\r\n\r\n // Determine the total length of all existing entries\r\n $totalLength = 0;\r\n foreach ($context_history as $entry) {\r\n if (is_string($entry)) {\r\n $totalLength += strlen($entry);\r\n } elseif (is_array($entry)) {\r\n $totalLength += strlen(json_encode($entry)); // Convert to string if an array\r\n }\r\n }\r\n\r\n // IDEA - How will the new threading option from OpenAI change how this works?\r\n // Define thresholds for the number of entries to keep\r\n $maxEntries = 30; // Default maximum number of entries\r\n if ($totalLength > 5000) { // Higher threshold\r\n $maxEntries = 20;\r\n }\r\n if ($totalLength > 10000) { // Lower threshold\r\n $maxEntries = 10;\r\n }\r\n\r\n while (count($context_history) >= $maxEntries) {\r\n array_shift($context_history); // Remove the oldest element\r\n }\r\n\r\n if (is_array($newEntry)) {\r\n $newEntry = json_encode($newEntry); // Convert the array to a string\r\n }\r\n\r\n array_push($context_history, $newEntry); // Append the new element\r\n set_transient($transient_name, $context_history); // Update the transient\r\n}\r\n\r\n\r\n// Function to return message and response - Ver 1.6.1\r\nfunction concatenateHistory($transient_name) {\r\n $context_history = get_transient($transient_name);\r\n if (!$context_history) {\r\n return ''; // Return an empty string if the transient does not exist\r\n }\r\n return implode(' ', $context_history); // Concatenate the array values into a single string\r\n}\r\n\r\n// FIXME - MOVE CORE FUNCTIONS TO A SEPARATE FILE, LEAVING ONLY THE HOOKS HERE\r\n// Initialize the Greetings - Ver 1.6.1\r\nfunction enqueue_greetings_script( $initial_greeting = null, $subsequent_greeting = null) {\r\n\r\n // wp_enqueue_script('greetings', plugin_dir_url(__FILE__) . 'assets/js/greetings.js', array('jquery'), null, true);\r\n\r\n // If user is logged in, then modify greeting if greeting contains \"[...]\" or remove if not logged in - Ver 1.9.4\r\n if (is_user_logged_in()) {\r\n\r\n $current_user_id = get_current_user_id();\r\n $current_user = get_userdata($current_user_id);\r\n\r\n //Do this for Initial Greeting\r\n if ( empty($initial_greeting) ) {\r\n $initial_greeting = esc_attr(get_option('chatbot_chatgpt_initial_greeting', 'Hello! How can I help you today?'));\r\n }\r\n\r\n // Determine what the field name is between the brackets\r\n $user_field_name = '';\r\n $user_field_name = substr($initial_greeting, strpos($initial_greeting, '[') + 1, strpos($initial_greeting, ']') - strpos($initial_greeting, '[') - 1);\r\n // If $initial_greeting contains \"[$user_field_name]\" then replace with field from DB\r\n if (strpos($initial_greeting, '[' . $user_field_name . ']') !== false) {\r\n $initial_greeting = str_replace('[' . $user_field_name . ']', $current_user->$user_field_name, $initial_greeting);\r\n } else {\r\n $initial_greeting = str_replace('[' . $user_field_name . ']', '', $initial_greeting);\r\n // Remove the extra space when two spaces are present\r\n $initial_greeting = str_replace(' ', ' ', $initial_greeting);\r\n // Remove the extra space before punctuation including period, comma, exclamation mark, and question mark\r\n $initial_greeting = preg_replace('/\\s*([.,!?])/', '$1', $initial_greeting);\r\n }\r\n\r\n // Do this for Subsequent Greeting\r\n if ( empty($subsequent_greeting) ) {\r\n $subsequent_greeting = esc_attr(get_option('chatbot_chatgpt_subsequent_greeting', 'Hello again! How can I help you?'));\r\n }\r\n\r\n // Determine what the field name is between the brackets\r\n $user_field_name = '';\r\n $user_field_name = substr($subsequent_greeting, strpos($subsequent_greeting, '[') + 1, strpos($subsequent_greeting, ']') - strpos($subsequent_greeting, '[') - 1);\r\n // If $subsequent_greeting contains \"[$user_field_name]\" then replace with field from DB\r\n if (strpos($subsequent_greeting, '[' . $user_field_name . ']') !== false) {\r\n $subsequent_greeting = str_replace('[' . $user_field_name . ']', $current_user->$user_field_name, $subsequent_greeting);\r\n } else {\r\n $subsequent_greeting = str_replace('[' . $user_field_name . ']', '', $subsequent_greeting);\r\n // Remove the extra space when two spaces are present\r\n $subsequent_greeting = str_replace(' ', ' ', $subsequent_greeting);\r\n // Remove the extra space before punctuation including period, comma, exclamation mark, and question mark\r\n $subsequent_greeting = preg_replace('/\\s*([.,!?])/', '$1', $subsequent_greeting);\r\n }\r\n\r\n } else {\r\n\r\n //Do this for Initial Greeting\r\n if ( empty($initial_greeting) ) {\r\n $initial_greeting = esc_attr(get_option('chatbot_chatgpt_initial_greeting', 'Hello! How can I help you today?'));\r\n }\r\n\r\n $user_field_name = '';\r\n $user_field_name = substr($initial_greeting, strpos($initial_greeting, '[') + 1, strpos($initial_greeting, ']') - strpos($initial_greeting, '[') - 1 );\r\n\r\n // $initial_greeting = preg_replace('/\\s*\\[' . preg_quote($user_field_name, '/') . '\\]\\s*/', '', $initial_greeting);\r\n $initial_greeting = str_replace('[' . $user_field_name . ']', '', $initial_greeting);\r\n // Remove the extra space when two spaces are present\r\n $initial_greeting = str_replace(' ', ' ', $initial_greeting);\r\n // Remove the extra space before punctuation including period, comma, exclamation mark, and question mark\r\n $initial_greeting = preg_replace('/\\s*([.,!?])/', '$1', $initial_greeting);\r\n\r\n //Do this for Subsequent Greeting\r\n if ( empty($subsequent_greeting) ) {\r\n $subsequent_greeting = esc_attr(get_option('chatbot_chatgpt_subsequent_greeting', 'Hello again! How can I help you?'));\r\n }\r\n\r\n $user_field_name = '';\r\n $user_field_name = substr($subsequent_greeting, strpos($subsequent_greeting, '[') + 1, strpos($subsequent_greeting, ']') - strpos($subsequent_greeting, '[') - 1);\r\n\r\n // $subsequent_greeting = preg_replace('/\\s*\\[' . preg_quote($user_field_name, '/') . '\\]\\s*/', '', $subsequent_greeting);\r\n $subsequent_greeting = str_replace('[' . $user_field_name . ']', '', $subsequent_greeting);\r\n // Remove the extra space when two spaces are present\r\n $subsequent_greeting = str_replace(' ', ' ', $subsequent_greeting);\r\n // Remove the extra space before punctuation including period, comma, exclamation mark, and question mark\r\n $subsequent_greeting = preg_replace('/\\s*([.,!?])/', '$1', $subsequent_greeting); \r\n\r\n }\r\n\r\n $greetings = array(\r\n 'initial_greeting' => $initial_greeting,\r\n 'subsequent_greeting' => $subsequent_greeting,\r\n );\r\n\r\n // Original wp_localize_script call\r\n // wp_localize_script('greetings', 'greetings_data', $greetings);\r\n // Refactored using wp_add_inline_script - Ver 2.0.5 - 2024 07 06\r\n $greetings_json = wp_json_encode($greetings);\r\n // wp_add_inline_script('greetings', 'let greetings_data = ' . $greetings_json . ';', 'before');\r\n wp_add_inline_script('greetings', 'if (typeof greetings_data === \"undefined\") { var greetings_data = ' . $greetings_json . '; } else { greetings_data = ' . $greetings_json . '; }', 'before');\r\n\r\n return $greetings;\r\n\r\n}\r\n// \r\nadd_action('wp_enqueue_scripts', 'enqueue_greetings_script');\r\n\r\n// Add the color picker to the adaptive appearance settings section - Ver 1.8.1\r\nfunction enqueue_color_picker($hook_suffix) {\r\n // first check that $hook_suffix is appropriate for your admin page\r\n wp_enqueue_style('wp-color-picker');\r\n wp_enqueue_script('my-script-handle', plugin_dir_url(__FILE__) . 'assets/js/chatbot-chatgpt-color-picker.js', array('wp-color-picker'), false, true);\r\n}\r\nadd_action('admin_enqueue_scripts', 'enqueue_color_picker');\r\n\r\n// Determine if the plugin is installed\r\nfunction kchat_get_plugin_version() {\r\n\r\n if (!function_exists('get_plugin_data')) {\r\n require_once(ABSPATH . 'wp-admin/includes/plugin.php');\r\n }\r\n\r\n $plugin_data = get_plugin_data(plugin_dir_path(__FILE__) . 'chatbot-chatgpt.php');\r\n $plugin_version = $plugin_data['Version'];\r\n update_option('chatbot_chatgpt_plugin_version', $plugin_version);\r\n // DIAG - Log the plugin version\r\n // back_trace( 'NOTICE', 'Plugin version '. $plugin_version);\r\n\r\n return $plugin_version;\r\n\r\n}"}, "90a9c7011b8a1182502ede5263a6a8ce054636cf": {"t": 1785756421.4178486, "n": 47645, "h": "e7920befad924cf8", "c": " $user_id,\r\n 'page_id' => $page_id,\r\n 'session_id' => $session_id,\r\n 'thread_id' => $thread_id,\r\n 'assistant_id' => $assistant_id,\r\n 'additional_instructions' => $additional_instructions,\r\n 'model' => $model,\r\n 'voice' => 'alloy',\r\n );\r\n\r\n // DIAG - Diagnostics - Ver 1.8.6\r\n // back_trace( 'NOTICE', '$user_id: ' . $user_id);\r\n // back_trace( 'NOTICE', '$page_id: ' . $page_id);\r\n // back_trace( 'NOTICE', '$session_id: ' . $session_id);\r\n // back_trace( 'NOTICE', '$thread_id: ' . $thread_id);\r\n // back_trace( 'NOTICE', '$assistant_id: ' . $assistant_id);\r\n // back_trace( 'NOTICE', '$additional_instructions: ' . $additional_instructions);\r\n // back_trace( 'NOTICE', '$model: ' . $model);\r\n \r\n // Defaults for Ver 1.6.1\r\n $defaults = array(\r\n 'chatbot_chatgpt_bot_name' => 'Kognetiks Chatbot',\r\n // TODO IDEA - Add a setting to fix or randomize the bot prompt\r\n 'chatbot_chatgpt_bot_prompt' => 'Enter your question ...',\r\n 'chatbot_chatgpt_initial_greeting' => 'Hello! How can I help you today?',\r\n 'chatbot_chatgpt_subsequent_greeting' => 'Hello again! How can I help you?',\r\n 'chatbot_chatgpt_display_style' => 'floating',\r\n 'chatbot_chatgpt_assistant_alias' => 'primary',\r\n 'chatbot_chatgpt_start_status' => 'closed',\r\n 'chatbot_chatgpt_start_status_new_visitor' => 'closed',\r\n 'chatbot_chatgpt_disclaimer_setting' => 'No',\r\n 'chatbot_chatgpt_audience_choice' => 'all',\r\n 'chatbot_chatgpt_max_tokens_setting' => '150',\r\n 'chatbot_chatgpt_message_limit_setting' => '999',\r\n 'chatbot_chatgpt_width_setting' => 'Narrow',\r\n 'chatbot_chatgpt_diagnostics' => 'Off',\r\n 'chatbot_chatgpt_custom_error_message' => 'Your custom error message goes here.',\r\n 'chatbot_chatgpt_avatar_icon_setting' => 'icon-001.png',\r\n 'chatbot_chatgpt_avatar_icon_url_setting' => '',\r\n 'chatbot_chatgpt_custom_avatar_icon_setting' => '',\r\n 'chatbot_chatgpt_avatar_greeting_setting' => 'Howdy!!! Great to see you today! How can I help you?',\r\n 'chatbot_chatgpt_model_choice' => 'gpt-3.5-turbo',\r\n 'chatbot_chatgpt_conversation_context' => 'You are a versatile, friendly, and helpful assistant designed to support me in a variety of tasks that responds in Markdown.',\r\n 'chatbot_chatgpt_enable_custom_buttons' => 'Off',\r\n 'chatbot_chatgpt_custom_button_name_1' => '',\r\n 'chatbot_chatgpt_custom_button_url_1' => '',\r\n 'chatbot_chatgpt_custom_button_name_2' => '',\r\n 'chatbot_chatgpt_custom_button_url_2' => '',\r\n 'chatbot_chatgpt_allow_file_uploads' => 'No',\r\n 'chatbot_chatgpt_timeout_setting' => '240',\r\n 'chatbot_chatgpt_voice_option' => 'alloy',\r\n 'chatbot_chatgpt_audio_output_format' => 'mp3',\r\n );\r\n\r\n // Revised for Ver 1.5.0 \r\n $option_keys = array(\r\n 'chatbot_chatgpt_bot_name',\r\n 'chatbot_chatgpt_bot_prompt',\r\n 'chatbot_chatgpt_initial_greeting',\r\n 'chatbot_chatgpt_subsequent_greeting',\r\n 'chatbot_chatgpt_display_style',\r\n 'chatbot_chatgpt_assistant_alias',\r\n 'chatbot_chatgpt_start_status',\r\n 'chatbot_chatgpt_start_status_new_visitor',\r\n 'chatbot_chatgpt_disclaimer_setting',\r\n 'chatbot_chatgpt_audience_choice',\r\n 'chatbot_chatgpt_max_tokens_setting',\r\n 'chatbot_chatgpt_message_limit_setting',\r\n 'chatbot_chatgpt_width_setting',\r\n 'chatbot_chatgpt_diagnostics',\r\n 'chatbot_chatgpt_custom_error_message',\r\n 'chatbot_chatgpt_avatar_icon_setting',\r\n 'chatbot_chatgpt_avatar_icon_url_setting',\r\n 'chatbot_chatgpt_custom_avatar_icon_setting',\r\n 'chatbot_chatgpt_avatar_greeting_setting',\r\n 'chatbot_chatgpt_enable_custom_buttons',\r\n 'chatbot_chatgpt_custom_button_name_1',\r\n 'chatbot_chatgpt_custom_button_url_1',\r\n 'chatbot_chatgpt_custom_button_name_2',\r\n 'chatbot_chatgpt_custom_button_url_2',\r\n 'chatbot_chatgpt_allow_file_uploads',\r\n 'chatbot_chatgpt_timeout_setting',\r\n 'chatbot_chatgpt_voice_option',\r\n 'chatbot_chatgpt_audio_output_format',\r\n );\r\n\r\n $chatbot_settings = array();\r\n foreach ($option_keys as $key) {\r\n $default_value = $defaults[$key] ?? '';\r\n $chatbot_settings[$key] = esc_attr(get_option($key, $default_value));\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'chatbot-chatgpt.php: Key: ' . $key . ', Value: ' . $chatbot_settings[$key]);\r\n }\r\n\r\n // Set visitor and logged in user limits - Ver 2.0.1\r\n if (is_user_logged_in()) {\r\n // back_trace( 'NOTICE', 'User is logged in');\r\n $chatbot_settings['chatbot_chatgpt_message_limit_setting'] = esc_attr(get_option('chatbot_chatgpt_message_limit_setting', '999'));\r\n } else {\r\n // back_trace( 'NOTICE', 'User is NOT logged in');\r\n $chatbot_settings['chatbot_chatgpt_message_limit_setting'] = esc_attr(get_option('chatbot_chatgpt_visitor_message_limit_setting', '999'));\r\n }\r\n\r\n $chatbot_settings['chatbot_chatgpt_icon_base_url'] = plugins_url( '/assets/icons/', __FILE__ );\r\n\r\n // Localize the data for javascript\r\n wp_localize_script('chatbot-chatgpt-js', 'php_vars', $script_data_array);\r\n\r\n wp_localize_script('chatbot-chatgpt-js', 'plugin_vars', array(\r\n 'plugins_url' => plugins_url('', __FILE__ ),\r\n ));\r\n\r\n wp_localize_script('chatbot-chatgpt-local', 'chatbotSettings', $chatbot_settings);\r\n\r\n wp_localize_script('chatbot-chatgpt-js', 'chatbot_chatgpt_params', array(\r\n 'plugins_url' => plugins_url('', __FILE__ ),\r\n 'ajax_url' => admin_url('admin-ajax.php'),\r\n ));\r\n\r\n // Upload files - Ver 1.7.6\r\n wp_localize_script('chatbot-chatgpt-upload-trigger-js', 'chatbot_chatgpt_params', array(\r\n 'plugins_url' => plugins_url('', __FILE__ ),\r\n 'ajax_url' => admin_url('admin-ajax.php'),\r\n ));\r\n\r\n}\r\nadd_action('wp_enqueue_scripts', 'chatbot_chatgpt_enqueue_scripts');\r\n\r\n// Settings and Deactivation Links - Ver - 1.5.0\r\nif (!function_exists('enqueue_jquery_ui')) {\r\n function enqueue_jquery_ui() {\r\n wp_enqueue_style('wp-jquery-ui-dialog');\r\n wp_enqueue_script('jquery-ui-dialog');\r\n }\r\n add_action( 'admin_enqueue_scripts', 'enqueue_jquery_ui' );\r\n}\r\n\r\n// Schedule Cleanup of Expired Transients\r\nif (!wp_next_scheduled('chatbot_chatgpt_cleanup_event')) {\r\n wp_schedule_event(time(), 'daily', 'chatbot_chatgpt_cleanup_event');\r\n}\r\nadd_action('chatbot_chatgpt_cleanup_event', 'clean_specific_expired_transients');\r\n\r\n// Schedule Conversation Log Cleanup - Ver 1.6.7\r\nif (!wp_next_scheduled('chatbot_chatgpt_conversation_log_cleanup_event')) {\r\n wp_schedule_event(time(), 'daily', 'chatbot_chatgpt_conversation_log_cleanup_event');\r\n}\r\nadd_action('chatbot_chatgpt_conversation_log_cleanup_event', 'chatbot_chatgpt_conversation_log_cleanup');\r\n\r\n// Schedule the transcript file cleanup event if it's not already scheduled - Ver 1.9.9\r\n// Schedule the cleanup event if it's not already scheduled\r\nif (!wp_next_scheduled('chatbot_chatgpt_cleanup_transcript_files')) {\r\n wp_schedule_event(time(), 'hourly', 'chatbot_chatgpt_cleanup_transcript_files');\r\n}\r\n\r\n// Deactivate old hooks - Ver 2.0.1\r\nif(esc_attr(get_option('chatbot_chatgpt_cleanup_old_hooks') !== 'Completed')) {\r\n // Deactivate old hooks - Ver 2.0.1\r\n wp_clear_scheduled_hook('chatbot_chatgpt_cleanup_transcripts');\r\n // Then update the option\r\n update_option('chatbot_chatgpt_cleanup_old_hooks', 'Completed');\r\n}\r\n\r\n// Schedule the audio file cleanup event if it's not already scheduled - Ver 1.9.9\r\n// Schedule the cleanup event if it's not already scheduled\r\nif (!wp_next_scheduled('chatbot_chatgpt_cleanup_audio_files')) {\r\n wp_schedule_event(time(), 'hourly', 'chatbot_chatgpt_cleanup_audio_files');\r\n}\r\n\r\n// Schedule the upload file cleanup event if it's not already scheduled - Ver 1.9.9\r\n// Schedule the cleanup event if it's not already scheduled\r\nif (!wp_next_scheduled('chatbot_chatgpt_cleanup_upload_files')) {\r\n wp_schedule_event(time(), 'hourly', 'chatbot_chatgpt_cleanup_upload_files');\r\n}\r\n\r\n// Schedule the download file cleanup event if it's not already scheduled - Ver 2.0.3\r\n// Schedule the cleanup event if it's not already scheduled\r\nif (!wp_next_scheduled('chatbot_chatgpt_cleanup_download_files')) {\r\n wp_schedule_event(time(), 'hourly', 'chatbot_chatgpt_cleanup_download_files');\r\n}\r\n\r\n// Handle Ajax requests\r\nfunction chatbot_chatgpt_send_message() {\r\n\r\n // Global variables\r\n global $session_id;\r\n global $user_id;\r\n global $page_id;\r\n global $thread_id;\r\n global $assistant_id;\r\n global $chatbot_chatgpt_display_style;\r\n global $chatbot_chatgpt_assistant_alias;\r\n global $script_data_array;\r\n global $additional_instructions;\r\n global $model;\r\n global $voice;\r\n\r\n global $flow_data;\r\n\r\n $api_key = '';\r\n\r\n // Retrieve the API key\r\n $api_key = esc_attr(get_option('chatbot_chatgpt_api_key'));\r\n\r\n // Retrieve the GPT Model\r\n if (!empty($model)) {\r\n $model = esc_attr(get_option('chatbot_chatgpt_model_choice', 'gpt-3.5-turbo'));\r\n // DIAG - Diagnostics\r\n // back_trace ( 'NOTICE', 'Model from options: ' . $model);\r\n } else {\r\n // SEE IF $script_data_array HAS THE MODEL\r\n if ( isset($script_data_array['model'])) {\r\n $model = $script_data_array['model'];\r\n // DIAG - Diagnostics\r\n // back_trace ( 'NOTICE', 'Model set in global: ' . $model);\r\n } else {\r\n // Set the model to the default\r\n $model = esc_attr(get_option('chatbot_chatgpt_model_choice', 'gpt-3.5-turbo'));\r\n // DIAG - Diagnostics\r\n // back_trace ( 'ERROR', 'Model not set!!!');\r\n // wp_send_json_error('Invalid Model. Please set the model in the plugin settings.');\r\n }\r\n }\r\n\r\n // Retrieve the Max tokens - Ver 1.4.2\r\n $max_tokens = esc_attr(get_option('chatbot_chatgpt_max_tokens_setting', 150));\r\n\r\n // Send only clean text via the API\r\n $message = sanitize_text_field($_POST['message']);\r\n\r\n // Check for missing API key or Message\r\n if (!$api_key || !$message) {\r\n wp_send_json_error('Error: Invalid API key or Message. Please check the plugin settings.');\r\n }\r\n\r\n // Removed in Ver 1.8.6 - 2024 02 15\r\n // $thread_id = '';\r\n // $assistant_id = '';\r\n // $user_id = '';\r\n // $page_id = '';\r\n \r\n // Check the transient for the Assistant ID - Ver 1.7.2\r\n $user_id = intval($_POST['user_id']);\r\n $page_id = intval($_POST['page_id']);\r\n\r\n // DIAG - Diagnostics - Ver 1.8.6\r\n // back_trace( 'NOTICE', 'chatbot_chatgpt_send_message $user_id: ' . $user_id);\r\n // back_trace( 'NOTICE', 'chatbot_chatgpt_send_message $page_id: ' . $page_id);\r\n\r\n $chatbot_settings['display_style'] = get_chatbot_chatgpt_transients( 'display_style', $user_id, $page_id);\r\n $chatbot_settings['assistant_alias'] = get_chatbot_chatgpt_transients( 'assistant_alias', $user_id, $page_id);\r\n $chatbot_settings['assistantID'] = get_chatbot_chatgpt_transients( 'assistant_id', $user_id, $page_id);\r\n // back_trace ( 'NOTICE', 'chatbot_chatgpt_send_message $chatbot_settings[assistantID]: ' . $chatbot_settings['assistantID']);\r\n $chatbot_settings['threadID'] = get_chatbot_chatgpt_transients( 'thread_id', $user_id, $page_id);\r\n // back_trace ( 'NOTICE', 'chatbot_chatgpt_send_message $chatbot_settings[threadID]: ' . $chatbot_settings['threadID']);\r\n $chatbot_settings['model'] = get_chatbot_chatgpt_transients( 'model', $user_id, $page_id);\r\n $chatbot_settings['voice'] = get_chatbot_chatgpt_transients( 'voice', $user_id, $page_id);\r\n\r\n $display_style = isset($chatbot_settings['display_style']) ? $chatbot_settings['display_style'] : '';\r\n $chatbot_chatgpt_assistant_alias = isset($chatbot_settings['assistant_alias']) ? $chatbot_settings['assistant_alias'] : '';\r\n\r\n $temp_model = $chatbot_settings['model']; // Store the model in a temporary variable before overwriting $chatbot_settings\r\n\r\n $chatbot_settings = get_chatbot_chatgpt_threads($user_id, $page_id);\r\n\r\n $chatbot_settings['model'] = $temp_model; // Restore the model after overwriting $chatbot_settings\r\n\r\n $assistant_id = isset($chatbot_settings['assistantID']) ? $chatbot_settings['assistantID'] : '';\r\n $thread_Id = isset($chatbot_settings['threadID']) ? $chatbot_settings['threadID'] : '';\r\n $model = isset($chatbot_settings['model']) ? $chatbot_settings['model'] : '';\r\n\r\n // DIAG - Diagnostics - Ver 1.8.6\r\n // back_trace( 'NOTICE', '$user_id: ' . $user_id);\r\n // back_trace( 'NOTICE', '$page_id: ' . $page_id);\r\n // back_trace( 'NOTICE', '$session_id: ' . $session_id);\r\n // back_trace( 'NOTICE', '$thread_id: ' . $thread_id);\r\n // back_trace( 'NOTICE', '$assistant_id: ' . $assistant_id);\r\n // back_trace( 'NOTICE', '$model: ' . $model);\r\n\r\n // Assistants\r\n // $chatbot_chatgpt_assistant_alias == 'original'; // Default\r\n // $chatbot_chatgpt_assistant_alias == 'primary';\r\n // $chatbot_chatgpt_assistant_alias == 'alternate';\r\n // $chatbot_chatgpt_assistant_alias == 'asst_xxxxxxxxxxxxxxxxxxxxxxxx'; // GPT Assistant Id\r\n \r\n // Which Assistant ID to use - Ver 1.7.2\r\n if ($chatbot_chatgpt_assistant_alias == 'original') {\r\n $use_assistant_id = 'No';\r\n // DIAG - Diagnostics - Ver 1.8.1\r\n // back_trace( 'NOTICE' , 'Using Original GPT Assistant ID');\r\n } elseif ($chatbot_chatgpt_assistant_alias == 'primary') {\r\n $assistant_id = esc_attr(get_option('chatbot_chatgpt_assistant_id'));\r\n $additional_instructions = esc_attr(get_option('chatbot_chatgpt_assistant_instructions', ''));\r\n $use_assistant_id = 'Yes';\r\n // DIAG - Diagnostics - Ver 1.8.1\r\n // back_trace( 'NOTICE' , 'Using Primary GPT Assistant ID ' . $assistant_id);\r\n // Check if the GPT Assistant ID is blank, null, or \"Please provide the GPT Assistant ID.\"\r\n if (empty($assistant_id) || $assistant_id == \"Please provide the GPT Assistant Id.\") {\r\n // Override the $use_assistant_id and set it to 'No'\r\n $use_assistant_id = 'No';\r\n // DIAG - Diagnostics - Ver 1.8.1\r\n // back_trace( 'NOTICE' ,'Falling back to ChatGPT API' );\r\n }\r\n } elseif ($chatbot_chatgpt_assistant_alias == 'alternate') {\r\n $assistant_id = esc_attr(get_option('chatbot_chatgpt_assistant_id_alternate'));\r\n $additional_instructions = esc_attr(get_option('chatbot_chatgpt_assistant_instructions_alternate', ''));\r\n $use_assistant_id = 'Yes';\r\n // DIAG - Diagnostics - Ver 1.8.1\r\n // back_trace( 'NOTICE' , 'Using Alternate GPT Assistant ID ' . $assistant_id);\r\n // Check if the GPT Assistant ID is blank, null, or \"Please provide the GPT Assistant ID.\"\r\n if (empty($assistant_id) || $assistant_id == \"Please provide the GPT Assistant Id.\") {\r\n // Override the $use_assistant_id and set it to 'No'\r\n $use_assistant_id = 'No';\r\n // DIAG - Diagnostics - Ver 1.8.1\r\n // back_trace( 'NOTICE' ,'Falling back to ChatGPT API' );\r\n }\r\n } else {\r\n // Reference GPT Assistant IDs directly - Ver 1.7.3\r\n if (str_starts_with($chatbot_chatgpt_assistant_alias, 'asst_')) {\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Using GPT Assistant ID: ' . $chatbot_chatgpt_assistant_alias);\r\n // Override the $assistant_id with the GPT Assistant ID\r\n $assistant_id = $chatbot_chatgpt_assistant_alias;\r\n $use_assistant_id = 'Yes';\r\n // DIAG - Diagnostics - Ver 1.8.1\r\n // back_trace( 'NOTICE' , 'Using $assistant_id ' . $assistant_id);\r\n } else {\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Using ChatGPT API: ' . $chatbot_chatgpt_assistant_alias);\r\n // Override the $use_assistant_id and set it to 'No'\r\n $use_assistant_id = 'No';\r\n // DIAG - Diagnostics - Ver 1.8.1\r\n // back_trace( 'NOTICE' , 'Falling back to ChatGPT API');\r\n }\r\n }\r\n\r\n // Decide whether to use Flow, Assistant or Original ChatGPT\r\n if ($model == 'flow'){\r\n \r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Using ChatGPT Flow');\r\n\r\n // Reload the model - BELT & SUSPENDERS\r\n $script_data_array['model'] = $model;\r\n\r\n // Get the step from the transient\r\n $kflow_step = get_chatbot_chatgpt_transients( 'kflow_step', null, null, $session_id);\r\n if (empty($kflow_step)) {\r\n $kflow_step = 0; // FIXME - Set to 1 or to zero?\r\n }\r\n\r\n // $thread_id\r\n $thread_id = '[answer=' . $kflow_step + 1 . ']';\r\n \r\n // Add +1 to $script_data_array['next_step']\r\n $kflow_step = $kflow_step + 1;\r\n\r\n // Set the next step\r\n set_chatbot_chatgpt_transients( 'kflow_step', $kflow_step, null, null, $session_id);\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', '$message: ' . $message);\r\n append_message_to_conversation_log($session_id, $user_id, $page_id, 'Visitor', $thread_id, $assistant_id, $message);\r\n\r\n // BELT & SUSPENDERS\r\n $thread_id = '';\r\n\r\n // Send message to ChatGPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_call_flow_api($api_key, $message);\r\n wp_send_json_success($response);\r\n\r\n } elseif ($use_assistant_id == 'Yes') {\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Using GPT Assistant ID: ' . $use_assistant_id);\r\n // back_trace( 'NOTICE', '$user_id ' . $user_id);\r\n // back_trace( 'NOTICE', '$page_id ' . $page_id);\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', '$message ' . $message);\r\n append_message_to_conversation_log($session_id, $user_id, $page_id, 'Visitor', $thread_id, $assistant_id, $message);\r\n \r\n // Send message to Custom GPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_custom_gpt_call_api($api_key, $message, $assistant_id, $thread_id, $user_id, $page_id);\r\n\r\n // Use TF-IDF to enhance response\r\n $chatbot_chatgpt_suppress_learnings = esc_attr(get_option('chatbot_chatgpt_suppress_learnings', 'Random'));\r\n if ( $chatbot_chatgpt_suppress_learnings != 'None') {\r\n $response = $response . chatbot_chatgpt_enhance_with_tfidf($message);\r\n }\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', '$response ' . print_r($response,true));\r\n append_message_to_conversation_log($session_id, $user_id, $page_id, 'Chatbot', $thread_id, $assistant_id, $response);\r\n\r\n // Clean (erase) the output buffer - Ver 1.6.8\r\n ob_clean();\r\n if (str_starts_with($response, 'Error:') || str_starts_with($response, 'Failed:')) {\r\n // Return response\r\n // back_trace( 'NOTICE', '$response ' . print_r($response,true));\r\n wp_send_json_error('Oops! Something went wrong on our end. Please try again later');\r\n } else {\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Check for links and images in response before returning');\r\n $response = chatbot_chatgpt_check_for_links_and_images($response);\r\n // Return response\r\n wp_send_json_success($response);\r\n }\r\n } else {\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Using ChatGPT');\r\n // back_trace( 'NOTICE', '$user_id ' . $user_id);\r\n // back_trace( 'NOTICE', '$page_id ' . $page_id);\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', '$message ' . $message);\r\n append_message_to_conversation_log($session_id, $user_id, $page_id, 'Visitor', $thread_id, $assistant_id, $message);\r\n \r\n // If $model starts with 'gpt' then the chatbot_chatgpt_call_api or 'dall' then chatbot_chatgpt_call_image_api\r\n // TRY NOT TO FETCH MODEL AGAIN\r\n // $model = esc_attr(get_option('chatbot_chatgpt_model_choice', 'gpt-3.5-turbo'));\r\n if (strpos($model, 'gpt-4o') !== false) {\r\n // The string 'gpt-4o' is found in $model\r\n // Reload the model - BELT & SUSPENDERS\r\n $script_data_array['model'] = $model;\r\n // Send message to ChatGPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_call_omni($api_key, $message);\r\n } elseif (str_starts_with($model, 'gpt')) {\r\n // Reload the model - BELT & SUSPENDERS\r\n $script_data_array['model'] = $model;\r\n // Send message to ChatGPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_call_api($api_key, $message);\r\n } elseif (str_starts_with($model, 'dall')) {\r\n // Reload the model - BELT & SUSPENDERS\r\n $script_data_array['model'] = $model;\r\n // Send message to Image API - Ver 1.9.4\r\n $response = chatbot_chatgpt_call_image_api($api_key, $message);\r\n } elseif (str_starts_with($model, 'tts')) {\r\n // Reload the model - BELT & SUSPENDERS\r\n $script_data_array['model'] = $model;\r\n // Send message to TTS API - Text-to-speech - Ver 1.9.5\r\n $response = chatbot_chatgpt_call_tts_api($api_key, $message);\r\n } elseif (str_starts_with($model,'whisper')) {\r\n $script_data_array['model'] = $model;\r\n // Send message to STT API - Speech-to-text - Ver 1.9.6\r\n $response = chatbot_chatgpt_call_stt_api($api_key, $message);\r\n } else {\r\n // Reload the model - BELT & SUSPENDERS\r\n $script_data_array['model'] = $model;\r\n // Send message to ChatGPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_call_api($api_key, $message);\r\n }\r\n \r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', ['message' => 'BEFORE CALL TO ENHANCE TFIDF', 'response' => $response]);\r\n \r\n // Use TF-IDF to enhance response\r\n $chatbot_chatgpt_suppress_learnings = esc_attr(get_option('chatbot_chatgpt_suppress_learnings', 'Random'));\r\n if ( $chatbot_chatgpt_suppress_learnings != 'None') {\r\n $response = $response . chatbot_chatgpt_enhance_with_tfidf($message);\r\n }\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', ['message' => 'AFTER CALL TO ENHANCE TFIDF', 'response' => $response]);\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', '$response ' . print_r($response,true));\r\n append_message_to_conversation_log($session_id, $user_id, $page_id, 'Chatbot', $thread_id, $assistant_id, $response);\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Check for links and images in response before returning');\r\n $response = chatbot_chatgpt_check_for_links_and_images($response);\r\n\r\n // Return response\r\n wp_send_json_success($response);\r\n }\r\n\r\n wp_send_json_error('Oops, I fell through the cracks!');\r\n\r\n}\r\n\r\n// Add action to send messages - Ver 1.0.0\r\nadd_action('wp_ajax_chatbot_chatgpt_send_message', 'chatbot_chatgpt_send_message');\r\nadd_action('wp_ajax_nopriv_chatbot_chatgpt_send_message', 'chatbot_chatgpt_send_message');\r\n\r\n// Add action to upload files - Ver 1.7.6\r\nadd_action('wp_ajax_chatbot_chatgpt_upload_files', 'chatbot_chatgpt_upload_files');\r\nadd_action('wp_ajax_nopriv_chatbot_chatgpt_upload_files', 'chatbot_chatgpt_upload_files');\r\n\r\n// Add action to upload files - Ver 1.7.6\r\nadd_action('wp_ajax_chatbot_chatgpt_upload_mp3', 'chatbot_chatgpt_upload_mp3');\r\nadd_action('wp_ajax_nopriv_chatbot_chatgpt_upload_mp3', 'chatbot_chatgpt_upload_mp3');\r\n\r\n// Add action to erase conversation - Ver 1.8.6\r\nadd_action('wp_ajax_chatbot_chatgpt_erase_conversation', 'chatbot_chatgpt_erase_conversation_handler');\r\nadd_action('wp_ajax_nopriv_chatbot_chatgpt_erase_conversation', 'chatbot_chatgpt_erase_conversation_handler'); // For logged-out users, if needed\r\n\r\n// Settings and Deactivation - Ver 1.5.0\r\nadd_filter('plugin_action_links_' . plugin_basename(__FILE__), 'chatbot_chatgpt_plugin_action_links');\r\n\r\n// Crawler aka Knowledge Navigator - Ver 1.6.1\r\nfunction chatbot_chatgpt_kn_status_activation() {\r\n add_option('chatbot_chatgpt_kn_status', 'Never Run');\r\n // clear any old scheduled runs\r\n if (wp_next_scheduled('crawl_scheduled_event_hook')) {\r\n wp_clear_scheduled_hook('crawl_scheduled_event_hook');\r\n }\r\n // clear the 'knowledge_navigator_scan_hook' hook on plugin activation - Ver 1.6.3\r\n if (wp_next_scheduled('knowledge_navigator_scan_hook')) {\r\n // BREAK/FIX - Do not unset the hook - Ver 1.8.5\r\n // wp_clear_scheduled_hook('knowledge_navigator_scan_hook'); // Clear scheduled runs\r\n }\r\n}\r\nregister_activation_hook(__FILE__, 'chatbot_chatgpt_kn_status_activation');\r\n\r\n// Clean Up in Aisle 4\r\nfunction chatbot_chatgpt_kn_status_deactivation() {\r\n delete_option('chatbot_chatgpt_kn_status');\r\n wp_clear_scheduled_hook('knowledge_navigator_scan_hook'); \r\n}\r\nregister_deactivation_hook(__FILE__, 'chatbot_chatgpt_kn_status_deactivation');\r\n\r\n// Function to add a new message and response, keeping only the last five - Ver 1.6.1\r\nfunction addEntry($transient_name, $newEntry) {\r\n\r\n $context_history = get_transient($transient_name);\r\n if (!$context_history) {\r\n $context_history = [];\r\n }\r\n\r\n // Determine the total length of all existing entries\r\n $totalLength = 0;\r\n foreach ($context_history as $entry) {\r\n if (is_string($entry)) {\r\n $totalLength += strlen($entry);\r\n } elseif (is_array($entry)) {\r\n $totalLength += strlen(json_encode($entry)); // Convert to string if an array\r\n }\r\n }\r\n\r\n // IDEA - How will the new threading option from OpenAI change how this works?\r\n // Define thresholds for the number of entries to keep\r\n $maxEntries = 30; // Default maximum number of entries\r\n if ($totalLength > 5000) { // Higher threshold\r\n $maxEntries = 20;\r\n }\r\n if ($totalLength > 10000) { // Lower threshold\r\n $maxEntries = 10;\r\n }\r\n\r\n while (count($context_history) >= $maxEntries) {\r\n array_shift($context_history); // Remove the oldest element\r\n }\r\n\r\n if (is_array($newEntry)) {\r\n $newEntry = json_encode($newEntry); // Convert the array to a string\r\n }\r\n\r\n array_push($context_history, $newEntry); // Append the new element\r\n set_transient($transient_name, $context_history); // Update the transient\r\n}\r\n\r\n\r\n// Function to return message and response - Ver 1.6.1\r\nfunction concatenateHistory($transient_name) {\r\n $context_history = get_transient($transient_name);\r\n if (!$context_history) {\r\n return ''; // Return an empty string if the transient does not exist\r\n }\r\n return implode(' ', $context_history); // Concatenate the array values into a single string\r\n}\r\n\r\n// Initialize the Greetings - Ver 1.6.1\r\nfunction enqueue_greetings_script() {\r\n\r\n // DIAG - Diagnostics - Ver 1.6.1\r\n // back_trace( 'NOTICE', \"enqueue_greetings_script() called\");\r\n\r\n wp_enqueue_script('greetings', plugin_dir_url(__FILE__) . 'assets/js/greetings.js', array('jquery'), null, true);\r\n\r\n // If user is logged in, then modify greeting if greeting contains \"[...]\" or remove if not logged in - Ver 1.9.4\r\n if (is_user_logged_in()) {\r\n\r\n $current_user_id = get_current_user_id();\r\n $current_user = get_userdata($current_user_id);\r\n\r\n //Do this for Initial Greeting\r\n $initial_greeting = esc_attr(get_option('chatbot_chatgpt_initial_greeting', 'Hello! How can I help you today?'));\r\n\r\n // Determine what the field name is between the brackets\r\n $user_field_name = '';\r\n $user_field_name = substr($initial_greeting, strpos($initial_greeting, '[') + 1, strpos($initial_greeting, ']') - strpos($initial_greeting, '[') - 1);\r\n // If $initial_greeting contains \"[$user_field_name]\" then replace with field from DB\r\n if (strpos($initial_greeting, '[' . $user_field_name . ']') !== false) {\r\n $initial_greeting = str_replace('[' . $user_field_name . ']', $current_user->$user_field_name, $initial_greeting);\r\n // back_trace ( 'NOTICE', 'User Field Name: ' . $user_field_name . ', User Field Value: ' . $current_user->$user_field_name);\r\n // back_trace ( 'NOTICE', 'Initial Greeting: ' . $initial_greeting);\r\n } else {\r\n $initial_greeting = str_replace('[' . $user_field_name . ']', '', $initial_greeting);\r\n }\r\n\r\n // Do this for Subsequent Greeting\r\n $subsequent_greeting = esc_attr(get_option('chatbot_chatgpt_subsequent_greeting', 'Hello again! How can I help you?'));\r\n\r\n // Determine what the field name is between the brackets\r\n $user_field_name = '';\r\n $user_field_name = substr($subsequent_greeting, strpos($subsequent_greeting, '[') + 1, strpos($subsequent_greeting, ']') - strpos($subsequent_greeting, '[') - 1);\r\n // If $subsequent_greeting contains \"[$user_field_name]\" then replace with field from DB\r\n if (strpos($subsequent_greeting, '[' . $user_field_name . ']') !== false) {\r\n $subsequent_greeting = str_replace('[' . $user_field_name . ']', $current_user->$user_field_name, $subsequent_greeting);\r\n // back_trace ( 'NOTICE', 'User Field Name: ' . $user_field_name . ', User Field Value: ' . $current_user->$user_field_name);\r\n // back_trace ( 'NOTICE', 'Subsequent Greeting: ' . $subsequent_greeting);\r\n } else {\r\n $subsequent_greeting = str_replace('[' . $user_field_name . ']', '', $subsequent_greeting);\r\n }\r\n\r\n } else {\r\n\r\n $initial_greeting = esc_attr(get_option('chatbot_chatgpt_initial_greeting', 'Hello! How can I help you today?'));\r\n\r\n $user_field_name = '';\r\n $user_field_name = substr($initial_greeting, strpos($initial_greeting, '[') + 1, strpos($initial_greeting, ']') - strpos($initial_greeting, '[') - 1 );\r\n\r\n // $initial_greeting = str_replace('[' . $user_field_name . ']', '', $initial_greeting);\r\n $initial_greeting = preg_replace('/\\s*\\[' . preg_quote($user_field_name, '/') . '\\]\\s*/', '', $initial_greeting);\r\n\r\n $subsequent_greeting = esc_attr(get_option('chatbot_chatgpt_subsequent_greeting', 'Hello again! How can I help you?'));\r\n\r\n $user_field_name = '';\r\n $user_field_name = substr($subsequent_greeting, strpos($subsequent_greeting, '[') + 1, strpos($subsequent_greeting, ']') - strpos($subsequent_greeting, '[') - 1);\r\n\r\n // $subsequent_greeting = str_replace('[' . $user_field_name . ']', '', $subsequent_greeting);\r\n $subsequent_greeting = preg_replace('/\\s*\\[' . preg_quote($user_field_name, '/') . '\\]\\s*/', '', $subsequent_greeting);\r\n\r\n }\r\n\r\n $greetings = array(\r\n 'initial_greeting' => $initial_greeting,\r\n 'subsequent_greeting' => $subsequent_greeting,\r\n );\r\n\r\n wp_localize_script('greetings', 'greetings_data', $greetings);\r\n\r\n}\r\nadd_action('wp_enqueue_scripts', 'enqueue_greetings_script');\r\n\r\n\r\n// Function to add the adaptive appearance settings to the Chatbot settings page\r\nfunction chatbot_chatgpt_settings_appearance() {\r\n\r\n // Register the settings\r\n register_setting('chatbot_chatgpt_settings_appearance', 'chatbot_chatgpt_appearance');\r\n\r\n // Add the adaptive appearance settings section\r\n add_settings_section(\r\n 'chatbot_chatgpt_settings_appearance_section',\r\n 'Adaptive Appearance Settings',\r\n 'chatbot_chatgpt_settings_appearance_section_callback',\r\n 'chatbot_chatgpt_settings_appearance'\r\n );\r\n\r\n // Add the adaptive appearance settings fields\r\n add_settings_field(\r\n 'chatbot_chatgpt_settings_appearance_field',\r\n 'Adaptive Appearance Settings',\r\n 'chatbot_chatgpt_settings_appearance_field_callback',\r\n 'chatbot_chatgpt_settings_appearance',\r\n 'chatbot_chatgpt_settings_appearance_section'\r\n );\r\n\r\n}\r\n\r\n// Add the color picker to the adaptive appearance settings section - Ver 1.8.1\r\nfunction enqueue_color_picker($hook_suffix) {\r\n // first check that $hook_suffix is appropriate for your admin page\r\n wp_enqueue_style('wp-color-picker');\r\n wp_enqueue_script('my-script-handle', plugin_dir_url(__FILE__) . 'assets/js/chatbot-chatgpt-color-picker.js', array('wp-color-picker'), false, true);\r\n}\r\nadd_action('admin_enqueue_scripts', 'enqueue_color_picker');\r\n\r\n// Determine if the plugin is installed\r\nfunction kchat_get_plugin_version() {\r\n\r\n if (!function_exists('get_plugin_data')) {\r\n require_once(ABSPATH . 'wp-admin/includes/plugin.php');\r\n }\r\n\r\n $plugin_data = get_plugin_data(plugin_dir_path(__FILE__) . 'chatbot-chatgpt.php');\r\n $plugin_version = $plugin_data['Version'];\r\n update_option('chatbot_chatgpt_plugin_version', $plugin_version);\r\n // DIAG - Log the plugin version\r\n // back_trace( 'NOTICE', 'Plugin version '. $plugin_version);\r\n\r\n return $plugin_version;\r\n\r\n}\r\n"}, "052efc504048a4ba155ea15e3a4ab7777b82eeed": {"t": 1785756423.024603, "n": 46959, "h": "0462e7387eafa283", "c": " 0,\r\n 'cookie_path' => '/',\r\n 'cookie_domain' => $_SERVER['HTTP_HOST'],\r\n 'cookie_secure' => true,\r\n 'cookie_httponly' => true,\r\n 'cookie_samesite' => 'Strict'\r\n ]);\r\n }\r\n $session_id = session_id();\r\n session_write_close(); // Close the session after setting the session id\r\n\r\n}\r\n\r\nob_end_flush(); // End output buffering and send the buffer to the browser\r\n\r\n// Include necessary files - Main files\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/chatbot-call-gpt-api.php'; // ChatGPT API - Ver 1.6.9\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/chatbot-call-gpt-assistant.php'; // Custom GPT Assistants - Ver 1.6.9\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/chatbot-call-gpt-omni.php'; // ChatGPT API - Ver 2.0.2.1\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/chatbot-call-image-api.php'; // Image API - Ver 1.9.4\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/chatbot-call-tts-api.php'; // TTS API - Ver 1.9.4\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/chatbot-call-stt-api.php'; // STT API - Ver 2.0.1\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/chatbot-globals.php'; // Globals - Ver 1.6.5\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/chatbot-shortcode.php';\r\n\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/chatbot-call-flow-api.php'; // ChatGPT API - Ver 1.9.5\r\n\r\n// Include necessary files - Appearance - Ver 1.8.1\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/appearance/chatbot-settings-appearance-body.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/appearance/chatbot-settings-appearance-dimensions.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/appearance/chatbot-settings-appearance-text.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/appearance/chatbot-settings-appearance-user-css.php';\r\n\r\n// Include necessary files - Knowledge Navigator\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/knowledge-navigator/chatbot-kn-acquire.php'; // Knowledge Navigator Acquisition - Ver 1.6.3\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/knowledge-navigator/chatbot-kn-acquire-controller.php'; // Knowledge Navigator Acquisition - Ver 1.9.6\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/knowledge-navigator/chatbot-kn-acquire-words.php'; // Knowledge Navigator Acquisition - Ver 1.9.6\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/knowledge-navigator/chatbot-kn-analysis.php'; // Knowledge Navigator Analysis- Ver 1.6.2\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/knowledge-navigator/chatbot-kn-db.php'; // Knowledge Navigator - Database Management - Ver 1.6.3\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/knowledge-navigator/chatbot-kn-enhance-context.php'; // Knowledge Navigator - Enhance Context - Ver 1.6.9\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/knowledge-navigator/chatbot-kn-enhance-response.php'; // Knowledge Navigator - TD-IDF Response Enhancement - Ver 1.6.9\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/knowledge-navigator/chatbot-kn-scheduler.php'; // Knowledge Navigator - Scheduler - Ver 1.6.3\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/knowledge-navigator/chatbot-kn-settings.php'; // Knowledge Navigator - Settings - Ver 1.6.1\r\n\r\n// Include necessary files - Settings\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-api-model.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-api-test.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-appearance.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-avatar.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-buttons.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-custom-gpts.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-diagnostics.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-links.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-localization.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-localize.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-notices.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-premium.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-registration-api.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-registration-kn.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-registration.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-reporting.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-setup.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-support.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings.php';\r\n\r\n// Include necessary files - Utilities - Ver 1.9.0\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/utilities/chatbot-conversation-history.php'; // Ver 1.9.2\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/utilities/chatbot-db-management.php'; // Database Management for Reporting - Ver 1.6.3\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/utilities/chatbot-deactivate.php'; // Deactivation - Ver 1.9.9\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/utilities/chatbot-download-transcript.php'; // Functions - Ver 1.9.9\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/utilities/chatbot-erase-conversation.php'; // Functions - Ver 1.8.6\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/utilities/chatbot-file-download.php'; // Download a file via the API - Ver 2.0.3\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/utilities/chatbot-file-helper.php'; // Functions - Ver 2.0.3\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/utilities/chatbot-file-upload.php'; // Functions - Ver 1.7.6\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/utilities/chatbot-filter-out-html-tags.php'; // Functions - Ver 1.9.6\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/utilities/chatbot-link-and-image-handling.php'; // Globals - Ver 1.9.1\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/utilities/chatbot-models.php'; // Functions - Ver 1.9.4\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/utilities/chatbot-names.php'; // Functions - Ver 1.9.4\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/utilities/chatbot-threads.php'; // Ver 1.7.2.1\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/utilities/chatbot-transients-file.php'; // Ver 1.9.2\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/utilities/chatbot-transients.php'; // Ver 1.7.2\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/utilities/chatbot-upgrade.php'; // Ver 1.6.7\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/utilities/chatbot-utilities.php'; // Ver 1.8.6\r\n\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/utilities/parsedown.php'; // Version 2.0.2.1\r\n\r\nadd_action('init', 'my_custom_buffer_start');\r\nfunction my_custom_buffer_start() {\r\n ob_start();\r\n}\r\n\r\n// Check for Upgrades - Ver 1.7.7\r\nif (!esc_attr(get_option('chatbot_chatgpt_upgraded'))) {\r\n chatbot_chatgpt_upgrade();\r\n update_option('chatbot_chatgpt_upgraded', 'Yes');\r\n}\r\n\r\n// Diagnotics on/off setting can be found on the Settings tab - Ver 1.5.0\r\n$chatbot_chatgpt_diagnostics = esc_attr(get_option('chatbot_chatgpt_diagnostics', 'Off'));\r\n\r\n// Model choice - Ver 1.9.4\r\nglobal $model;\r\n// Starting with V1.9.4 the model choice \"gpt-4-turbo\" is replaced with \"gpt-4-1106-preview\"\r\nif (get_option('chatbot_chatgpt_model_choice') == 'gpt-4-turbo') {\r\n $model = 'gpt-4-1106-preview';\r\n update_option('chatbot_chatgpt_model_choice', $model);\r\n // DIAG - Diagnostics\r\n // back_trace ( 'NOTICE', 'Model upgraded: ' . $model);\r\n}\r\n\r\n// Voice choice - Ver 1.9.5\r\nglobal $voice;\r\nif (get_option('chatbot_chatgpt_voice_option') == 'alloy') {\r\n $voice = 'alloy';\r\n update_option('chatbot_chatgpt_voice_option', $voice);\r\n // DIAG - Diagnostics\r\n // back_trace ( 'NOTICE', 'Voice upgraded: ' . $voice);\r\n}\r\n\r\n// Custom buttons on/off setting can be found on the Settings tab - Ver 1.6.5\r\n$chatbot_chatgpt_enable_custom_buttons = esc_attr(get_option('chatbot_chatgpt_enable_custom_buttons', 'Off'));\r\n\r\n// Allow file uploads on/off setting can be found on the Settings tab - Ver 1.7.6\r\nglobal $chatbot_chatgpt_allow_file_uploads;\r\n// TEMP OVERRIDE - Ver 1.7.6\r\n// update_option('chatbot_chatgpt_allow_file_uploads', 'No');\r\n$chatbot_chatgpt_allow_file_uploads = esc_attr(get_option('chatbot_chatgpt_allow_file_uploads', 'No'));\r\n\r\n// Suppress Notices on/off setting can be found on the Settings tab - Ver 1.6.5\r\nglobal $chatbot_chatgpt_suppress_notices;\r\n$chatbot_chatgpt_suppress_notices = esc_attr(get_option('chatbot_chatgpt_suppress_notices', 'Off'));\r\n\r\n// Suppress Attribution on/off setting can be found on the Settings tab - Ver 1.6.5\r\nglobal $chatbot_chatgpt_suppress_attribution;\r\n$chatbot_chatgpt_suppress_attribution = esc_attr(get_option('chatbot_chatgpt_suppress_attribution', 'Off'));\r\n\r\n// Suppress Learnings Message - Ver 1.7.1\r\nglobal $chatbot_chatgpt_suppress_learnings;\r\n$chatbot_chatgpt_suppress_learnings = esc_attr(get_option('chatbot_chatgpt_suppress_learnings', 'Random'));\r\n\r\n// Context History - Ver 1.6.1\r\n$context_history = [];\r\n\r\nfunction chatbot_chatgpt_enqueue_admin_scripts() {\r\n wp_enqueue_script('chatbot_chatgpt_admin', plugins_url('assets/js/chatbot-chatgpt-admin.js', __FILE__), array('jquery'), '1.0.0', true);\r\n}\r\nadd_action('admin_enqueue_scripts', 'chatbot_chatgpt_enqueue_admin_scripts');\r\n\r\n// Activation, deactivation, and uninstall functions\r\nregister_activation_hook(__FILE__, 'chatbot_chatgpt_activate');\r\nregister_deactivation_hook(__FILE__, 'chatbot_chatgpt_deactivate');\r\nregister_uninstall_hook(__FILE__, 'chatbot_chatgpt_uninstall');\r\nadd_action('upgrader_process_complete', 'chatbot_chatgpt_upgrade_completed', 10, 2);\r\n\r\n// Enqueue plugin scripts and styles\r\nfunction chatbot_chatgpt_enqueue_scripts() {\r\n\r\n global $session_id;\r\n global $user_id;\r\n global $page_id;\r\n global $thread_id;\r\n global $assistant_id;\r\n global $script_data_array;\r\n global $additional_instructions;\r\n global $model;\r\n global $voice;\r\n\r\n // Enqueue the styles\r\n wp_enqueue_style('dashicons');\r\n wp_enqueue_style('chatbot-chatgpt-css', plugins_url('assets/css/chatbot-chatgpt.css', __FILE__));\r\n\r\n // Now override the default styles with the custom styles - Ver 1.8.1\r\n chatbot_chatgpt_appearance_custom_css_settings();\r\n\r\n // Custom css overrides - Ver 1.8.1\r\n // $customer_css_path = plugins_url(assets/css/chatbot-chatgpt-custom.css', __FILE__));\r\n // if ( file_exists ( $customer_css_path )) {\r\n // wp_enqueue_style('chatbot-chatgpt-custom-css', plugins_url('assets/css/chatbot-chatgpt-custom.css', __FILE__));\r\n // }\r\n\r\n // Enqueue the scripts\r\n wp_enqueue_script('chatbot-chatgpt-js', plugins_url('assets/js/chatbot-chatgpt.js', __FILE__), array('jquery'), '1.0', true);\r\n wp_enqueue_script('chatbot-chatgpt-local', plugins_url('assets/js/chatbot-chatgpt-local.js', __FILE__), array('jquery'), '1.0', true);\r\n\r\n // Enqueue DOMPurify - Ver 1.8.1\r\n // https://raw.githubusercontent.com/cure53/DOMPurify/main/dist/purify.min.js\r\n // https://chat.openai.com/c/275770c1-fa72-404b-97c2-2dad2e8a0230\r\n wp_enqueue_script( 'dompurify', plugin_dir_url(__FILE__) . 'assets/js/purify.min.js', array(), '1.0.0', true );\r\n\r\n // Localize the data for user id and page id\r\n $user_id = get_current_user_id();\r\n $page_id = get_the_id();\r\n\r\n $script_data_array = array(\r\n 'user_id' => $user_id,\r\n 'page_id' => $page_id,\r\n 'session_id' => $session_id,\r\n 'thread_id' => $thread_id,\r\n 'assistant_id' => $assistant_id,\r\n 'additional_instructions' => $additional_instructions,\r\n 'model' => $model,\r\n 'voice' => 'alloy',\r\n );\r\n\r\n // DIAG - Diagnostics - Ver 1.8.6\r\n // back_trace( 'NOTICE', '$user_id: ' . $user_id);\r\n // back_trace( 'NOTICE', '$page_id: ' . $page_id);\r\n // back_trace( 'NOTICE', '$session_id: ' . $session_id);\r\n // back_trace( 'NOTICE', '$thread_id: ' . $thread_id);\r\n // back_trace( 'NOTICE', '$assistant_id: ' . $assistant_id);\r\n // back_trace( 'NOTICE', '$additional_instructions: ' . $additional_instructions);\r\n // back_trace( 'NOTICE', '$model: ' . $model);\r\n \r\n // Defaults for Ver 1.6.1\r\n $defaults = array(\r\n 'chatbot_chatgpt_bot_name' => 'Kognetiks Chatbot',\r\n // TODO IDEA - Add a setting to fix or randomize the bot prompt\r\n 'chatbot_chatgpt_bot_prompt' => 'Enter your question ...',\r\n 'chatbot_chatgpt_initial_greeting' => 'Hello! How can I help you today?',\r\n 'chatbot_chatgpt_subsequent_greeting' => 'Hello again! How can I help you?',\r\n 'chatbot_chatgpt_display_style' => 'floating',\r\n 'chatbot_chatgpt_assistant_alias' => 'primary',\r\n 'chatbot_chatgpt_start_status' => 'closed',\r\n 'chatbot_chatgpt_start_status_new_visitor' => 'closed',\r\n 'chatbot_chatgpt_disclaimer_setting' => 'No',\r\n 'chatbot_chatgpt_audience_choice' => 'all',\r\n 'chatbot_chatgpt_max_tokens_setting' => '150',\r\n 'chatbot_chatgpt_message_limit_setting' => '999',\r\n 'chatbot_chatgpt_width_setting' => 'Narrow',\r\n 'chatbot_chatgpt_diagnostics' => 'Off',\r\n 'chatbot_chatgpt_custom_error_message' => 'Your custom error message goes here.',\r\n 'chatbot_chatgpt_avatar_icon_setting' => 'icon-001.png',\r\n 'chatbot_chatgpt_avatar_icon_url_setting' => '',\r\n 'chatbot_chatgpt_custom_avatar_icon_setting' => '',\r\n 'chatbot_chatgpt_avatar_greeting_setting' => 'Howdy!!! Great to see you today! How can I help you?',\r\n 'chatbot_chatgpt_model_choice' => 'gpt-3.5-turbo',\r\n 'chatbot_chatgpt_conversation_context' => 'You are a versatile, friendly, and helpful assistant designed to support me in a variety of tasks that responds in Markdown.',\r\n 'chatbot_chatgpt_enable_custom_buttons' => 'Off',\r\n 'chatbot_chatgpt_custom_button_name_1' => '',\r\n 'chatbot_chatgpt_custom_button_url_1' => '',\r\n 'chatbot_chatgpt_custom_button_name_2' => '',\r\n 'chatbot_chatgpt_custom_button_url_2' => '',\r\n 'chatbot_chatgpt_allow_file_uploads' => 'No',\r\n 'chatbot_chatgpt_timeout_setting' => '240',\r\n 'chatbot_chatgpt_voice_option' => 'alloy',\r\n 'chatbot_chatgpt_audio_output_format' => 'mp3',\r\n );\r\n\r\n // Revised for Ver 1.5.0 \r\n $option_keys = array(\r\n 'chatbot_chatgpt_bot_name',\r\n 'chatbot_chatgpt_bot_prompt',\r\n 'chatbot_chatgpt_initial_greeting',\r\n 'chatbot_chatgpt_subsequent_greeting',\r\n 'chatbot_chatgpt_display_style',\r\n 'chatbot_chatgpt_assistant_alias',\r\n 'chatbot_chatgpt_start_status',\r\n 'chatbot_chatgpt_start_status_new_visitor',\r\n 'chatbot_chatgpt_disclaimer_setting',\r\n 'chatbot_chatgpt_audience_choice',\r\n 'chatbot_chatgpt_max_tokens_setting',\r\n 'chatbot_chatgpt_message_limit_setting',\r\n 'chatbot_chatgpt_width_setting',\r\n 'chatbot_chatgpt_diagnostics',\r\n 'chatbot_chatgpt_custom_error_message',\r\n 'chatbot_chatgpt_avatar_icon_setting',\r\n 'chatbot_chatgpt_avatar_icon_url_setting',\r\n 'chatbot_chatgpt_custom_avatar_icon_setting',\r\n 'chatbot_chatgpt_avatar_greeting_setting',\r\n 'chatbot_chatgpt_enable_custom_buttons',\r\n 'chatbot_chatgpt_custom_button_name_1',\r\n 'chatbot_chatgpt_custom_button_url_1',\r\n 'chatbot_chatgpt_custom_button_name_2',\r\n 'chatbot_chatgpt_custom_button_url_2',\r\n 'chatbot_chatgpt_allow_file_uploads',\r\n 'chatbot_chatgpt_timeout_setting',\r\n 'chatbot_chatgpt_voice_option',\r\n 'chatbot_chatgpt_audio_output_format',\r\n );\r\n\r\n $chatbot_settings = array();\r\n foreach ($option_keys as $key) {\r\n $default_value = $defaults[$key] ?? '';\r\n $chatbot_settings[$key] = esc_attr(get_option($key, $default_value));\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'chatbot-chatgpt.php: Key: ' . $key . ', Value: ' . $chatbot_settings[$key]);\r\n }\r\n\r\n // Set visitor and logged in user limits - Ver 2.0.1\r\n if (is_user_logged_in()) {\r\n // back_trace( 'NOTICE', 'User is logged in');\r\n $chatbot_settings['chatbot_chatgpt_message_limit_setting'] = esc_attr(get_option('chatbot_chatgpt_message_limit_setting', '999'));\r\n } else {\r\n // back_trace( 'NOTICE', 'User is NOT logged in');\r\n $chatbot_settings['chatbot_chatgpt_message_limit_setting'] = esc_attr(get_option('chatbot_chatgpt_visitor_message_limit_setting', '999'));\r\n }\r\n\r\n $chatbot_settings['chatbot_chatgpt_icon_base_url'] = plugins_url( '/assets/icons/', __FILE__ );\r\n\r\n // Localize the data for javascript\r\n wp_localize_script('chatbot-chatgpt-js', 'php_vars', $script_data_array);\r\n\r\n wp_localize_script('chatbot-chatgpt-js', 'plugin_vars', array(\r\n 'plugins_url' => plugins_url('', __FILE__ ),\r\n ));\r\n\r\n wp_localize_script('chatbot-chatgpt-local', 'chatbotSettings', $chatbot_settings);\r\n\r\n wp_localize_script('chatbot-chatgpt-js', 'chatbot_chatgpt_params', array(\r\n 'plugins_url' => plugins_url('', __FILE__ ),\r\n 'ajax_url' => admin_url('admin-ajax.php'),\r\n ));\r\n\r\n // Upload files - Ver 1.7.6\r\n wp_localize_script('chatbot-chatgpt-upload-trigger-js', 'chatbot_chatgpt_params', array(\r\n 'plugins_url' => plugins_url('', __FILE__ ),\r\n 'ajax_url' => admin_url('admin-ajax.php'),\r\n ));\r\n\r\n}\r\nadd_action('wp_enqueue_scripts', 'chatbot_chatgpt_enqueue_scripts');\r\n\r\n// Settings and Deactivation Links - Ver - 1.5.0\r\nif (!function_exists('enqueue_jquery_ui')) {\r\n function enqueue_jquery_ui() {\r\n wp_enqueue_style('wp-jquery-ui-dialog');\r\n wp_enqueue_script('jquery-ui-dialog');\r\n }\r\n add_action( 'admin_enqueue_scripts', 'enqueue_jquery_ui' );\r\n}\r\n\r\n// Schedule Cleanup of Expired Transients\r\nif (!wp_next_scheduled('chatbot_chatgpt_cleanup_event')) {\r\n wp_schedule_event(time(), 'daily', 'chatbot_chatgpt_cleanup_event');\r\n}\r\nadd_action('chatbot_chatgpt_cleanup_event', 'clean_specific_expired_transients');\r\n\r\n// Schedule Conversation Log Cleanup - Ver 1.6.7\r\nif (!wp_next_scheduled('chatbot_chatgpt_conversation_log_cleanup_event')) {\r\n wp_schedule_event(time(), 'daily', 'chatbot_chatgpt_conversation_log_cleanup_event');\r\n}\r\nadd_action('chatbot_chatgpt_conversation_log_cleanup_event', 'chatbot_chatgpt_conversation_log_cleanup');\r\n\r\n// Schedule the transcript file cleanup event if it's not already scheduled - Ver 1.9.9\r\n// Schedule the cleanup event if it's not already scheduled\r\nif (!wp_next_scheduled('chatbot_chatgpt_cleanup_transcript_files')) {\r\n wp_schedule_event(time(), 'hourly', 'chatbot_chatgpt_cleanup_transcript_files');\r\n}\r\n\r\n// Deactivate old hooks - Ver 2.0.1\r\nif(esc_attr(get_option('chatbot_chatgpt_cleanup_old_hooks') !== 'Completed')) {\r\n // Deactivate old hooks - Ver 2.0.1\r\n wp_clear_scheduled_hook('chatbot_chatgpt_cleanup_transcripts');\r\n // Then update the option\r\n update_option('chatbot_chatgpt_cleanup_old_hooks', 'Completed');\r\n}\r\n\r\n// Schedule the audio file cleanup event if it's not already scheduled - Ver 1.9.9\r\n// Schedule the cleanup event if it's not already scheduled\r\nif (!wp_next_scheduled('chatbot_chatgpt_cleanup_audio_files')) {\r\n wp_schedule_event(time(), 'hourly', 'chatbot_chatgpt_cleanup_audio_files');\r\n}\r\n\r\n// Schedule the upload file cleanup event if it's not already scheduled - Ver 1.9.9\r\n// Schedule the cleanup event if it's not already scheduled\r\nif (!wp_next_scheduled('chatbot_chatgpt_cleanup_upload_files')) {\r\n wp_schedule_event(time(), 'hourly', 'chatbot_chatgpt_cleanup_upload_files');\r\n}\r\n\r\n// Schedule the download file cleanup event if it's not already scheduled - Ver 2.0.3\r\n// Schedule the cleanup event if it's not already scheduled\r\nif (!wp_next_scheduled('chatbot_chatgpt_cleanup_download_files')) {\r\n wp_schedule_event(time(), 'hourly', 'chatbot_chatgpt_cleanup_download_files');\r\n}\r\n\r\n// Handle Ajax requests\r\nfunction chatbot_chatgpt_send_message() {\r\n\r\n // Global variables\r\n global $session_id;\r\n global $user_id;\r\n global $page_id;\r\n global $thread_id;\r\n global $assistant_id;\r\n global $chatbot_chatgpt_display_style;\r\n global $chatbot_chatgpt_assistant_alias;\r\n global $script_data_array;\r\n global $additional_instructions;\r\n global $model;\r\n global $voice;\r\n\r\n global $flow_data;\r\n\r\n $api_key = '';\r\n\r\n // Retrieve the API key\r\n $api_key = esc_attr(get_option('chatbot_chatgpt_api_key'));\r\n\r\n // Retrieve the GPT Model\r\n if (!empty($model)) {\r\n $model = esc_attr(get_option('chatbot_chatgpt_model_choice', 'gpt-3.5-turbo'));\r\n // DIAG - Diagnostics\r\n // back_trace ( 'NOTICE', 'Model from options: ' . $model);\r\n } else {\r\n // SEE IF $script_data_array HAS THE MODEL\r\n if ( isset($script_data_array['model'])) {\r\n $model = $script_data_array['model'];\r\n // DIAG - Diagnostics\r\n // back_trace ( 'NOTICE', 'Model set in global: ' . $model);\r\n } else {\r\n // Set the model to the default\r\n $model = esc_attr(get_option('chatbot_chatgpt_model_choice', 'gpt-3.5-turbo'));\r\n // DIAG - Diagnostics\r\n // back_trace ( 'ERROR', 'Model not set!!!');\r\n // wp_send_json_error('Invalid Model. Please set the model in the plugin settings.');\r\n }\r\n }\r\n\r\n // Retrieve the Max tokens - Ver 1.4.2\r\n $max_tokens = esc_attr(get_option('chatbot_chatgpt_max_tokens_setting', 150));\r\n\r\n // Send only clean text via the API\r\n $message = sanitize_text_field($_POST['message']);\r\n\r\n // Check for missing API key or Message\r\n if (!$api_key || !$message) {\r\n wp_send_json_error('Error: Invalid API key or Message. Please check the plugin settings.');\r\n }\r\n\r\n // Removed in Ver 1.8.6 - 2024 02 15\r\n // $thread_id = '';\r\n // $assistant_id = '';\r\n // $user_id = '';\r\n // $page_id = '';\r\n \r\n // Check the transient for the Assistant ID - Ver 1.7.2\r\n $user_id = intval($_POST['user_id']);\r\n $page_id = intval($_POST['page_id']);\r\n\r\n // DIAG - Diagnostics - Ver 1.8.6\r\n // back_trace( 'NOTICE', 'chatbot_chatgpt_send_message $user_id: ' . $user_id);\r\n // back_trace( 'NOTICE', 'chatbot_chatgpt_send_message $page_id: ' . $page_id);\r\n\r\n $chatbot_settings['display_style'] = get_chatbot_chatgpt_transients( 'display_style', $user_id, $page_id);\r\n $chatbot_settings['assistant_alias'] = get_chatbot_chatgpt_transients( 'assistant_alias', $user_id, $page_id);\r\n $chatbot_settings['model'] = get_chatbot_chatgpt_transients( 'model', $user_id, $page_id);\r\n $chatbot_settings['voice'] = get_chatbot_chatgpt_transients( 'voice', $user_id, $page_id);\r\n\r\n $display_style = isset($chatbot_settings['display_style']) ? $chatbot_settings['display_style'] : '';\r\n $chatbot_chatgpt_assistant_alias = isset($chatbot_settings['assistant_alias']) ? $chatbot_settings['assistant_alias'] : '';\r\n\r\n $temp_model = $chatbot_settings['model']; // Store the model in a temporary variable before overwriting $chatbot_settings\r\n\r\n $chatbot_settings = get_chatbot_chatgpt_threads($user_id, $page_id);\r\n\r\n $chatbot_settings['model'] = $temp_model; // Restore the model after overwriting $chatbot_settings\r\n\r\n $assistant_id = isset($chatbot_settings['assistantID']) ? $chatbot_settings['assistantID'] : '';\r\n $thread_Id = isset($chatbot_settings['threadID']) ? $chatbot_settings['threadID'] : '';\r\n $model = isset($chatbot_settings['model']) ? $chatbot_settings['model'] : '';\r\n\r\n // DIAG - Diagnostics - Ver 1.8.6\r\n // back_trace( 'NOTICE', '$user_id: ' . $user_id);\r\n // back_trace( 'NOTICE', '$page_id: ' . $page_id);\r\n // back_trace( 'NOTICE', '$session_id: ' . $session_id);\r\n // back_trace( 'NOTICE', '$thread_id: ' . $thread_id);\r\n // back_trace( 'NOTICE', '$assistant_id: ' . $assistant_id);\r\n // back_trace( 'NOTICE', '$model: ' . $model);\r\n\r\n // Assistants\r\n // $chatbot_chatgpt_assistant_alias == 'original'; // Default\r\n // $chatbot_chatgpt_assistant_alias == 'primary';\r\n // $chatbot_chatgpt_assistant_alias == 'alternate';\r\n // $chatbot_chatgpt_assistant_alias == 'asst_xxxxxxxxxxxxxxxxxxxxxxxx'; // GPT Assistant Id\r\n \r\n // Which Assistant ID to use - Ver 1.7.2\r\n if ($chatbot_chatgpt_assistant_alias == 'original') {\r\n $use_assistant_id = 'No';\r\n // DIAG - Diagnostics - Ver 1.8.1\r\n // back_trace( 'NOTICE' , 'Using Original GPT Assistant ID');\r\n } elseif ($chatbot_chatgpt_assistant_alias == 'primary') {\r\n $assistant_id = esc_attr(get_option('chatbot_chatgpt_assistant_id'));\r\n $additional_instructions = esc_attr(get_option('chatbot_chatgpt_assistant_instructions', ''));\r\n $use_assistant_id = 'Yes';\r\n // DIAG - Diagnostics - Ver 1.8.1\r\n // back_trace( 'NOTICE' , 'Using Primary GPT Assistant ID ' . $assistant_id);\r\n // Check if the GPT Assistant ID is blank, null, or \"Please provide the GPT Assistant ID.\"\r\n if (empty($assistant_id) || $assistant_id == \"Please provide the GPT Assistant Id.\") {\r\n // Override the $use_assistant_id and set it to 'No'\r\n $use_assistant_id = 'No';\r\n // DIAG - Diagnostics - Ver 1.8.1\r\n // back_trace( 'NOTICE' ,'Falling back to ChatGPT API' );\r\n }\r\n } elseif ($chatbot_chatgpt_assistant_alias == 'alternate') {\r\n $assistant_id = esc_attr(get_option('chatbot_chatgpt_assistant_id_alternate'));\r\n $additional_instructions = esc_attr(get_option('chatbot_chatgpt_assistant_instructions_alternate', ''));\r\n $use_assistant_id = 'Yes';\r\n // DIAG - Diagnostics - Ver 1.8.1\r\n // back_trace( 'NOTICE' , 'Using Alternate GPT Assistant ID ' . $assistant_id);\r\n // Check if the GPT Assistant ID is blank, null, or \"Please provide the GPT Assistant ID.\"\r\n if (empty($assistant_id) || $assistant_id == \"Please provide the GPT Assistant Id.\") {\r\n // Override the $use_assistant_id and set it to 'No'\r\n $use_assistant_id = 'No';\r\n // DIAG - Diagnostics - Ver 1.8.1\r\n // back_trace( 'NOTICE' ,'Falling back to ChatGPT API' );\r\n }\r\n } else {\r\n // Reference GPT Assistant IDs directly - Ver 1.7.3\r\n if (str_starts_with($chatbot_chatgpt_assistant_alias, 'asst_')) {\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Using GPT Assistant ID: ' . $chatbot_chatgpt_assistant_alias);\r\n // Override the $assistant_id with the GPT Assistant ID\r\n $assistant_id = $chatbot_chatgpt_assistant_alias;\r\n $use_assistant_id = 'Yes';\r\n // DIAG - Diagnostics - Ver 1.8.1\r\n // back_trace( 'NOTICE' , 'Using $assistant_id ' . $assistant_id);\r\n } else {\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Using ChatGPT API: ' . $chatbot_chatgpt_assistant_alias);\r\n // Override the $use_assistant_id and set it to 'No'\r\n $use_assistant_id = 'No';\r\n // DIAG - Diagnostics - Ver 1.8.1\r\n // back_trace( 'NOTICE' , 'Falling back to ChatGPT API');\r\n }\r\n }\r\n\r\n // Decide whether to use Flow, Assistant or Original ChatGPT\r\n if ($model == 'flow'){\r\n \r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Using ChatGPT Flow');\r\n\r\n // Reload the model - BELT & SUSPENDERS\r\n $script_data_array['model'] = $model;\r\n\r\n // Get the step from the transient\r\n $kflow_step = get_chatbot_chatgpt_transients( 'kflow_step', null, null, $session_id);\r\n if (empty($kflow_step)) {\r\n $kflow_step = 0; // FIXME - Set to 1 or to zero?\r\n }\r\n\r\n // $thread_id\r\n $thread_id = '[answer=' . $kflow_step + 1 . ']';\r\n \r\n // Add +1 to $script_data_array['next_step']\r\n $kflow_step = $kflow_step + 1;\r\n\r\n // Set the next step\r\n set_chatbot_chatgpt_transients( 'kflow_step', $kflow_step, null, null, $session_id);\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', '$message: ' . $message);\r\n append_message_to_conversation_log($session_id, $user_id, $page_id, 'Visitor', $thread_id, $assistant_id, $message);\r\n\r\n // BELT & SUSPENDERS\r\n $thread_id = '';\r\n\r\n // Send message to ChatGPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_call_flow_api($api_key, $message);\r\n wp_send_json_success($response);\r\n\r\n } elseif ($use_assistant_id == 'Yes') {\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Using GPT Assistant ID: ' . $use_assistant_id);\r\n // back_trace( 'NOTICE', '$user_id ' . $user_id);\r\n // back_trace( 'NOTICE', '$page_id ' . $page_id);\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', '$message ' . $message);\r\n append_message_to_conversation_log($session_id, $user_id, $page_id, 'Visitor', $thread_id, $assistant_id, $message);\r\n \r\n // Send message to Custom GPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_custom_gpt_call_api($api_key, $message, $assistant_id, $thread_id, $user_id, $page_id);\r\n\r\n // Use TF-IDF to enhance response\r\n $chatbot_chatgpt_suppress_learnings = esc_attr(get_option('chatbot_chatgpt_suppress_learnings', 'Random'));\r\n if ( $chatbot_chatgpt_suppress_learnings != 'None') {\r\n $response = $response . chatbot_chatgpt_enhance_with_tfidf($message);\r\n }\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', '$response ' . print_r($response,true));\r\n append_message_to_conversation_log($session_id, $user_id, $page_id, 'Chatbot', $thread_id, $assistant_id, $response);\r\n\r\n // Clean (erase) the output buffer - Ver 1.6.8\r\n ob_clean();\r\n if (str_starts_with($response, 'Error:') || str_starts_with($response, 'Failed:')) {\r\n // Return response\r\n // back_trace( 'NOTICE', '$response ' . print_r($response,true));\r\n wp_send_json_error('Oops! Something went wrong on our end. Please try again later');\r\n } else {\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Check for links and images in response before returning');\r\n $response = chatbot_chatgpt_check_for_links_and_images($response);\r\n // Return response\r\n wp_send_json_success($response);\r\n }\r\n } else {\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Using ChatGPT');\r\n // back_trace( 'NOTICE', '$user_id ' . $user_id);\r\n // back_trace( 'NOTICE', '$page_id ' . $page_id);\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', '$message ' . $message);\r\n append_message_to_conversation_log($session_id, $user_id, $page_id, 'Visitor', $thread_id, $assistant_id, $message);\r\n \r\n // If $model starts with 'gpt' then the chatbot_chatgpt_call_api or 'dall' then chatbot_chatgpt_call_image_api\r\n // TRY NOT TO FETCH MODEL AGAIN\r\n // $model = esc_attr(get_option('chatbot_chatgpt_model_choice', 'gpt-3.5-turbo'));\r\n if (strpos($model, 'gpt-4o') !== false) {\r\n // The string 'gpt-4o' is found in $model\r\n // Reload the model - BELT & SUSPENDERS\r\n $script_data_array['model'] = $model;\r\n // Send message to ChatGPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_call_omni($api_key, $message);\r\n } elseif (str_starts_with($model, 'gpt')) {\r\n // Reload the model - BELT & SUSPENDERS\r\n $script_data_array['model'] = $model;\r\n // Send message to ChatGPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_call_api($api_key, $message);\r\n } elseif (str_starts_with($model, 'dall')) {\r\n // Reload the model - BELT & SUSPENDERS\r\n $script_data_array['model'] = $model;\r\n // Send message to Image API - Ver 1.9.4\r\n $response = chatbot_chatgpt_call_image_api($api_key, $message);\r\n } elseif (str_starts_with($model, 'tts')) {\r\n // Reload the model - BELT & SUSPENDERS\r\n $script_data_array['model'] = $model;\r\n // Send message to TTS API - Text-to-speech - Ver 1.9.5\r\n $response = chatbot_chatgpt_call_tts_api($api_key, $message);\r\n } elseif (str_starts_with($model,'whisper')) {\r\n $script_data_array['model'] = $model;\r\n // Send message to STT API - Speech-to-text - Ver 1.9.6\r\n $response = chatbot_chatgpt_call_stt_api($api_key, $message);\r\n } else {\r\n // Reload the model - BELT & SUSPENDERS\r\n $script_data_array['model'] = $model;\r\n // Send message to ChatGPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_call_api($api_key, $message);\r\n }\r\n \r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', ['message' => 'BEFORE CALL TO ENHANCE TFIDF', 'response' => $response]);\r\n \r\n // Use TF-IDF to enhance response\r\n $chatbot_chatgpt_suppress_learnings = esc_attr(get_option('chatbot_chatgpt_suppress_learnings', 'Random'));\r\n if ( $chatbot_chatgpt_suppress_learnings != 'None') {\r\n $response = $response . chatbot_chatgpt_enhance_with_tfidf($message);\r\n }\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', ['message' => 'AFTER CALL TO ENHANCE TFIDF', 'response' => $response]);\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', '$response ' . print_r($response,true));\r\n append_message_to_conversation_log($session_id, $user_id, $page_id, 'Chatbot', $thread_id, $assistant_id, $response);\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Check for links and images in response before returning');\r\n $response = chatbot_chatgpt_check_for_links_and_images($response);\r\n\r\n // Return response\r\n wp_send_json_success($response);\r\n }\r\n\r\n wp_send_json_error('Oops, I fell through the cracks!');\r\n\r\n}\r\n\r\n// Add action to send messages - Ver 1.0.0\r\nadd_action('wp_ajax_chatbot_chatgpt_send_message', 'chatbot_chatgpt_send_message');\r\nadd_action('wp_ajax_nopriv_chatbot_chatgpt_send_message', 'chatbot_chatgpt_send_message');\r\n\r\n// Add action to upload files - Ver 1.7.6\r\nadd_action('wp_ajax_chatbot_chatgpt_upload_files', 'chatbot_chatgpt_upload_files');\r\nadd_action('wp_ajax_nopriv_chatbot_chatgpt_upload_files', 'chatbot_chatgpt_upload_files');\r\n\r\n// Add action to upload files - Ver 1.7.6\r\nadd_action('wp_ajax_chatbot_chatgpt_upload_mp3', 'chatbot_chatgpt_upload_mp3');\r\nadd_action('wp_ajax_nopriv_chatbot_chatgpt_upload_mp3', 'chatbot_chatgpt_upload_mp3');\r\n\r\n// Add action to erase conversation - Ver 1.8.6\r\nadd_action('wp_ajax_chatbot_chatgpt_erase_conversation', 'chatbot_chatgpt_erase_conversation_handler');\r\nadd_action('wp_ajax_nopriv_chatbot_chatgpt_erase_conversation', 'chatbot_chatgpt_erase_conversation_handler'); // For logged-out users, if needed\r\n\r\n// Settings and Deactivation - Ver 1.5.0\r\nadd_filter('plugin_action_links_' . plugin_basename(__FILE__), 'chatbot_chatgpt_plugin_action_links');\r\n\r\n// Crawler aka Knowledge Navigator - Ver 1.6.1\r\nfunction chatbot_chatgpt_kn_status_activation() {\r\n add_option('chatbot_chatgpt_kn_status', 'Never Run');\r\n // clear any old scheduled runs\r\n if (wp_next_scheduled('crawl_scheduled_event_hook')) {\r\n wp_clear_scheduled_hook('crawl_scheduled_event_hook');\r\n }\r\n // clear the 'knowledge_navigator_scan_hook' hook on plugin activation - Ver 1.6.3\r\n if (wp_next_scheduled('knowledge_navigator_scan_hook')) {\r\n // BREAK/FIX - Do not unset the hook - Ver 1.8.5\r\n // wp_clear_scheduled_hook('knowledge_navigator_scan_hook'); // Clear scheduled runs\r\n }\r\n}\r\nregister_activation_hook(__FILE__, 'chatbot_chatgpt_kn_status_activation');\r\n\r\n// Clean Up in Aisle 4\r\nfunction chatbot_chatgpt_kn_status_deactivation() {\r\n delete_option('chatbot_chatgpt_kn_status');\r\n wp_clear_scheduled_hook('knowledge_navigator_scan_hook'); \r\n}\r\nregister_deactivation_hook(__FILE__, 'chatbot_chatgpt_kn_status_deactivation');\r\n\r\n// Function to add a new message and response, keeping only the last five - Ver 1.6.1\r\nfunction addEntry($transient_name, $newEntry) {\r\n\r\n $context_history = get_transient($transient_name);\r\n if (!$context_history) {\r\n $context_history = [];\r\n }\r\n\r\n // Determine the total length of all existing entries\r\n $totalLength = 0;\r\n foreach ($context_history as $entry) {\r\n if (is_string($entry)) {\r\n $totalLength += strlen($entry);\r\n } elseif (is_array($entry)) {\r\n $totalLength += strlen(json_encode($entry)); // Convert to string if an array\r\n }\r\n }\r\n\r\n // IDEA - How will the new threading option from OpenAI change how this works?\r\n // Define thresholds for the number of entries to keep\r\n $maxEntries = 30; // Default maximum number of entries\r\n if ($totalLength > 5000) { // Higher threshold\r\n $maxEntries = 20;\r\n }\r\n if ($totalLength > 10000) { // Lower threshold\r\n $maxEntries = 10;\r\n }\r\n\r\n while (count($context_history) >= $maxEntries) {\r\n array_shift($context_history); // Remove the oldest element\r\n }\r\n\r\n if (is_array($newEntry)) {\r\n $newEntry = json_encode($newEntry); // Convert the array to a string\r\n }\r\n\r\n array_push($context_history, $newEntry); // Append the new element\r\n set_transient($transient_name, $context_history); // Update the transient\r\n}\r\n\r\n\r\n// Function to return message and response - Ver 1.6.1\r\nfunction concatenateHistory($transient_name) {\r\n $context_history = get_transient($transient_name);\r\n if (!$context_history) {\r\n return ''; // Return an empty string if the transient does not exist\r\n }\r\n return implode(' ', $context_history); // Concatenate the array values into a single string\r\n}\r\n\r\n// Initialize the Greetings - Ver 1.6.1\r\nfunction enqueue_greetings_script() {\r\n\r\n // DIAG - Diagnostics - Ver 1.6.1\r\n // back_trace( 'NOTICE', \"enqueue_greetings_script() called\");\r\n\r\n wp_enqueue_script('greetings', plugin_dir_url(__FILE__) . 'assets/js/greetings.js', array('jquery'), null, true);\r\n\r\n // If user is logged in, then modify greeting if greeting contains \"[...]\" or remove if not logged in - Ver 1.9.4\r\n if (is_user_logged_in()) {\r\n\r\n $current_user_id = get_current_user_id();\r\n $current_user = get_userdata($current_user_id);\r\n\r\n //Do this for Initial Greeting\r\n $initial_greeting = esc_attr(get_option('chatbot_chatgpt_initial_greeting', 'Hello! How can I help you today?'));\r\n\r\n // Determine what the field name is between the brackets\r\n $user_field_name = '';\r\n $user_field_name = substr($initial_greeting, strpos($initial_greeting, '[') + 1, strpos($initial_greeting, ']') - strpos($initial_greeting, '[') - 1);\r\n // If $initial_greeting contains \"[$user_field_name]\" then replace with field from DB\r\n if (strpos($initial_greeting, '[' . $user_field_name . ']') !== false) {\r\n $initial_greeting = str_replace('[' . $user_field_name . ']', $current_user->$user_field_name, $initial_greeting);\r\n // back_trace ( 'NOTICE', 'User Field Name: ' . $user_field_name . ', User Field Value: ' . $current_user->$user_field_name);\r\n // back_trace ( 'NOTICE', 'Initial Greeting: ' . $initial_greeting);\r\n } else {\r\n $initial_greeting = str_replace('[' . $user_field_name . ']', '', $initial_greeting);\r\n }\r\n\r\n // Do this for Subsequent Greeting\r\n $subsequent_greeting = esc_attr(get_option('chatbot_chatgpt_subsequent_greeting', 'Hello again! How can I help you?'));\r\n\r\n // Determine what the field name is between the brackets\r\n $user_field_name = '';\r\n $user_field_name = substr($subsequent_greeting, strpos($subsequent_greeting, '[') + 1, strpos($subsequent_greeting, ']') - strpos($subsequent_greeting, '[') - 1);\r\n // If $subsequent_greeting contains \"[$user_field_name]\" then replace with field from DB\r\n if (strpos($subsequent_greeting, '[' . $user_field_name . ']') !== false) {\r\n $subsequent_greeting = str_replace('[' . $user_field_name . ']', $current_user->$user_field_name, $subsequent_greeting);\r\n // back_trace ( 'NOTICE', 'User Field Name: ' . $user_field_name . ', User Field Value: ' . $current_user->$user_field_name);\r\n // back_trace ( 'NOTICE', 'Subsequent Greeting: ' . $subsequent_greeting);\r\n } else {\r\n $subsequent_greeting = str_replace('[' . $user_field_name . ']', '', $subsequent_greeting);\r\n }\r\n\r\n } else {\r\n\r\n $initial_greeting = esc_attr(get_option('chatbot_chatgpt_initial_greeting', 'Hello! How can I help you today?'));\r\n\r\n $user_field_name = '';\r\n $user_field_name = substr($initial_greeting, strpos($initial_greeting, '[') + 1, strpos($initial_greeting, ']') - strpos($initial_greeting, '[') - 1 );\r\n\r\n // $initial_greeting = str_replace('[' . $user_field_name . ']', '', $initial_greeting);\r\n $initial_greeting = preg_replace('/\\s*\\[' . preg_quote($user_field_name, '/') . '\\]\\s*/', '', $initial_greeting);\r\n\r\n $subsequent_greeting = esc_attr(get_option('chatbot_chatgpt_subsequent_greeting', 'Hello again! How can I help you?'));\r\n\r\n $user_field_name = '';\r\n $user_field_name = substr($subsequent_greeting, strpos($subsequent_greeting, '[') + 1, strpos($subsequent_greeting, ']') - strpos($subsequent_greeting, '[') - 1);\r\n\r\n // $subsequent_greeting = str_replace('[' . $user_field_name . ']', '', $subsequent_greeting);\r\n $subsequent_greeting = preg_replace('/\\s*\\[' . preg_quote($user_field_name, '/') . '\\]\\s*/', '', $subsequent_greeting);\r\n\r\n }\r\n\r\n $greetings = array(\r\n 'initial_greeting' => $initial_greeting,\r\n 'subsequent_greeting' => $subsequent_greeting,\r\n );\r\n\r\n wp_localize_script('greetings', 'greetings_data', $greetings);\r\n\r\n}\r\nadd_action('wp_enqueue_scripts', 'enqueue_greetings_script');\r\n\r\n\r\n// Function to add the adaptive appearance settings to the Chatbot settings page\r\nfunction chatbot_chatgpt_settings_appearance() {\r\n\r\n // Register the settings\r\n register_setting('chatbot_chatgpt_settings_appearance', 'chatbot_chatgpt_appearance');\r\n\r\n // Add the adaptive appearance settings section\r\n add_settings_section(\r\n 'chatbot_chatgpt_settings_appearance_section',\r\n 'Adaptive Appearance Settings',\r\n 'chatbot_chatgpt_settings_appearance_section_callback',\r\n 'chatbot_chatgpt_settings_appearance'\r\n );\r\n\r\n // Add the adaptive appearance settings fields\r\n add_settings_field(\r\n 'chatbot_chatgpt_settings_appearance_field',\r\n 'Adaptive Appearance Settings',\r\n 'chatbot_chatgpt_settings_appearance_field_callback',\r\n 'chatbot_chatgpt_settings_appearance',\r\n 'chatbot_chatgpt_settings_appearance_section'\r\n );\r\n\r\n}\r\n\r\n// Add the color picker to the adaptive appearance settings section - Ver 1.8.1\r\nfunction enqueue_color_picker($hook_suffix) {\r\n // first check that $hook_suffix is appropriate for your admin page\r\n wp_enqueue_style('wp-color-picker');\r\n wp_enqueue_script('my-script-handle', plugin_dir_url(__FILE__) . 'assets/js/chatbot-chatgpt-color-picker.js', array('wp-color-picker'), false, true);\r\n}\r\nadd_action('admin_enqueue_scripts', 'enqueue_color_picker');\r\n\r\n// Determine if the plugin is installed\r\nfunction kchat_get_plugin_version() {\r\n\r\n if (!function_exists('get_plugin_data')) {\r\n require_once(ABSPATH . 'wp-admin/includes/plugin.php');\r\n }\r\n\r\n $plugin_data = get_plugin_data(plugin_dir_path(__FILE__) . 'chatbot-chatgpt.php');\r\n $plugin_version = $plugin_data['Version'];\r\n update_option('chatbot_chatgpt_plugin_version', $plugin_version);\r\n // DIAG - Log the plugin version\r\n // back_trace( 'NOTICE', 'Plugin version '. $plugin_version);\r\n\r\n return $plugin_version;\r\n\r\n}\r\n"}, "fe1cbaeb9f6126f9da1c690b2cf6fed483e6d7b9": {"t": 1785756424.6921911, "n": 44291, "h": "625299253475e919", "c": " 0,\r\n 'cookie_path' => '/',\r\n 'cookie_domain' => $_SERVER['HTTP_HOST'],\r\n 'cookie_secure' => true,\r\n 'cookie_httponly' => true,\r\n 'cookie_samesite' => 'Strict'\r\n ]);\r\n }\r\n $session_id = session_id();\r\n session_write_close(); // Close the session after setting the session id\r\n\r\n}\r\n\r\nob_end_flush(); // End output buffering and send the buffer to the browser\r\n\r\n// Include necessary files - Main files\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/chatbot-call-gpt-api.php'; // ChatGPT API - Ver 1.6.9\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/chatbot-call-gpt-assistant.php'; // Custom GPT Assistants - Ver 1.6.9\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/chatbot-call-image-api.php'; // Image API - Ver 1.9.4\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/chatbot-call-tts-api.php'; // TTS API - Ver 1.9.4\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/chatbot-globals.php'; // Globals - Ver 1.6.5\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/chatbot-shortcode.php';\r\n\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/chatbot-call-flow-api.php'; // ChatGPT API - Ver 1.9.5\r\n\r\n// Include necessary files - Appearance - Ver 1.8.1\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/appearance/chatbot-settings-appearance-body.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/appearance/chatbot-settings-appearance-dimensions.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/appearance/chatbot-settings-appearance-text.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/appearance/chatbot-settings-appearance-user-css.php';\r\n\r\n// Include necessary files - Knowledge Navigator\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/knowledge-navigator/chatbot-kn-acquire.php'; // Knowledge Navigator Acquisition - Ver 1.6.3\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/knowledge-navigator/chatbot-kn-acquire-controller.php'; // Knowledge Navigator Acquisition - Ver 1.9.6\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/knowledge-navigator/chatbot-kn-acquire-words.php'; // Knowledge Navigator Acquisition - Ver 1.9.6\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/knowledge-navigator/chatbot-kn-analysis.php'; // Knowledge Navigator Analysis- Ver 1.6.2\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/knowledge-navigator/chatbot-kn-db.php'; // Knowledge Navigator - Database Management - Ver 1.6.3\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/knowledge-navigator/chatbot-kn-enhance-context.php'; // Knowledge Navigator - Enhance Context - Ver 1.6.9\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/knowledge-navigator/chatbot-kn-enhance-response.php'; // Knowledge Navigator - TD-IDF Response Enhancement - Ver 1.6.9\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/knowledge-navigator/chatbot-kn-scheduler.php'; // Knowledge Navigator - Scheduler - Ver 1.6.3\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/knowledge-navigator/chatbot-kn-settings.php'; // Knowledge Navigator - Settings - Ver 1.6.1\r\n\r\n// Include necessary files - Settings\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-api-model.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-api-test.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-appearance.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-avatar.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-buttons.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-custom-gpts.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-diagnostics.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-links.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-localization.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-localize.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-notices.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-premium.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-registration-api.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-registration.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-reporting.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-setup.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-support.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings.php';\r\n\r\n// Include necessary files - Utilities - Ver 1.9.0\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/utilities/chatbot-conversation-history.php'; // Ver 1.9.2\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/utilities/chatbot-db-management.php'; // Database Management for Reporting - Ver 1.6.3\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/utilities/chatbot-deactivate.php'; // Deactivation - Ver 1.9.9\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/utilities/chatbot-download-transcript.php'; // Functions - Ver 1.9.9\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/utilities/chatbot-erase-conversation.php'; // Functions - Ver 1.8.6\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/utilities/chatbot-file-upload.php'; // Functions - Ver 1.7.6\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/utilities/chatbot-filter-out-html-tags.php'; // Functions - Ver 1.9.6\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/utilities/chatbot-link-and-image-handling.php'; // Globals - Ver 1.9.1\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/utilities/chatbot-models.php'; // Functions - Ver 1.9.4\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/utilities/chatbot-names.php'; // Functions - Ver 1.9.4\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/utilities/chatbot-threads.php'; // Ver 1.7.2.1\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/utilities/chatbot-transients-file.php'; // Ver 1.9.2\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/utilities/chatbot-transients.php'; // Ver 1.7.2\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/utilities/chatbot-upgrade.php'; // Ver 1.6.7\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/utilities/chatbot-utilities.php'; // Ver 1.8.6\r\n\r\nadd_action('init', 'my_custom_buffer_start');\r\nfunction my_custom_buffer_start(): void {\r\n ob_start();\r\n}\r\n\r\n// Check for Upgrades - Ver 1.7.7\r\nif (!esc_attr(get_option('chatbot_chatgpt_upgraded'))) {\r\n chatbot_chatgpt_upgrade();\r\n update_option('chatbot_chatgpt_upgraded', 'Yes');\r\n}\r\n\r\n// Diagnotics on/off setting can be found on the Settings tab - Ver 1.5.0\r\n$chatbot_chatgpt_diagnostics = esc_attr(get_option('chatbot_chatgpt_diagnostics', 'Off'));\r\n\r\n// Dump the chatbot settings - Ver 1.8.6\r\n// DIAG - Diagnostics\r\n// back_trace('NOTICE', 'chatbot-chatgpt.php: Dump Options to File is ON');\r\n// chatbot_chatgpt_dump_options_to_file();\r\n\r\n// Model choice - Ver 1.9.4\r\nglobal $model;\r\n// Starting with V1.9.4 the model choice \"gpt-4-turbo\" is replaced with \"gpt-4-1106-preview\"\r\nif (get_option('chatbot_chatgpt_model_choice') == 'gpt-4-turbo') {\r\n $model = 'gpt-4-1106-preview';\r\n update_option('chatbot_chatgpt_model_choice', $model);\r\n // DIAG - Diagnostics\r\n // back_trace ( 'NOTICE', 'Model upgraded: ' . $model);\r\n}\r\n\r\n// Voice choice - Ver 1.9.5\r\nglobal $voice;\r\nif (get_option('chatbot_chatgpt_voice_option') == 'alloy') {\r\n $voice = 'alloy';\r\n update_option('chatbot_chatgpt_voice_option', $voice);\r\n // DIAG - Diagnostics\r\n // back_trace ( 'NOTICE', 'Voice upgraded: ' . $voice);\r\n}\r\n\r\n// Custom buttons on/off setting can be found on the Settings tab - Ver 1.6.5\r\n$chatbot_chatgpt_enable_custom_buttons = esc_attr(get_option('chatbot_chatgpt_enable_custom_buttons', 'Off'));\r\n\r\n// Allow file uploads on/off setting can be found on the Settings tab - Ver 1.7.6\r\nglobal $chatbot_chatgpt_allow_file_uploads;\r\n// TEMP OVERRIDE - Ver 1.7.6\r\n// update_option('chatbot_chatgpt_allow_file_uploads', 'No');\r\n$chatbot_chatgpt_allow_file_uploads = esc_attr(get_option('chatbot_chatgpt_allow_file_uploads', 'No'));\r\n\r\n// Suppress Notices on/off setting can be found on the Settings tab - Ver 1.6.5\r\nglobal $chatbot_chatgpt_suppress_notices;\r\n$chatbot_chatgpt_suppress_notices = esc_attr(get_option('chatbot_chatgpt_suppress_notices', 'Off'));\r\n\r\n// Suppress Attribution on/off setting can be found on the Settings tab - Ver 1.6.5\r\nglobal $chatbot_chatgpt_suppress_attribution;\r\n$chatbot_chatgpt_suppress_attribution = esc_attr(get_option('chatbot_chatgpt_suppress_attribution', 'Off'));\r\n\r\n// Suppress Learnings Message - Ver 1.7.1\r\nglobal $chatbot_chatgpt_suppress_learnings;\r\n$chatbot_chatgpt_suppress_learnings = esc_attr(get_option('chatbot_chatgpt_suppress_learnings', 'Random'));\r\n\r\n// Context History - Ver 1.6.1\r\n$context_history = [];\r\n\r\nfunction chatbot_chatgpt_enqueue_admin_scripts(): void {\r\n wp_enqueue_script('chatbot_chatgpt_admin', plugins_url('assets/js/chatbot-chatgpt-admin.js', __FILE__), array('jquery'), '1.0.0', true);\r\n}\r\nadd_action('admin_enqueue_scripts', 'chatbot_chatgpt_enqueue_admin_scripts');\r\n\r\n// Activation, deactivation, and uninstall functions\r\nregister_activation_hook(__FILE__, 'chatbot_chatgpt_activate');\r\nregister_deactivation_hook(__FILE__, 'chatbot_chatgpt_deactivate');\r\nregister_uninstall_hook(__FILE__, 'chatbot_chatgpt_uninstall');\r\nadd_action('upgrader_process_complete', 'chatbot_chatgpt_upgrade_completed', 10, 2);\r\n\r\n// Enqueue plugin scripts and styles\r\nfunction chatbot_chatgpt_enqueue_scripts(): void {\r\n\r\n global $session_id;\r\n global $user_id;\r\n global $page_id;\r\n global $thread_id;\r\n global $assistant_id;\r\n global $script_data_array;\r\n global $additional_instructions;\r\n global $model;\r\n global $voice;\r\n\r\n // Enqueue the styles\r\n wp_enqueue_style('dashicons');\r\n wp_enqueue_style('chatbot-chatgpt-css', plugins_url('assets/css/chatbot-chatgpt.css', __FILE__));\r\n\r\n // Now override the default styles with the custom styles - Ver 1.8.1\r\n chatbot_chatgpt_appearance_custom_css_settings();\r\n\r\n // Custom css overrides - Ver 1.8.1\r\n // $customer_css_path = plugins_url(assets/css/chatbot-chatgpt-custom.css', __FILE__));\r\n // if ( file_exists ( $customer_css_path )) {\r\n // wp_enqueue_style('chatbot-chatgpt-custom-css', plugins_url('assets/css/chatbot-chatgpt-custom.css', __FILE__));\r\n // }\r\n\r\n // Enqueue the scripts\r\n wp_enqueue_script('chatbot-chatgpt-js', plugins_url('assets/js/chatbot-chatgpt.js', __FILE__), array('jquery'), '1.0', true);\r\n wp_enqueue_script('chatbot-chatgpt-local', plugins_url('assets/js/chatbot-chatgpt-local.js', __FILE__), array('jquery'), '1.0', true);\r\n\r\n // Enqueue DOMPurify - Ver 1.8.1\r\n // https://raw.githubusercontent.com/cure53/DOMPurify/main/dist/purify.min.js\r\n // https://chat.openai.com/c/275770c1-fa72-404b-97c2-2dad2e8a0230\r\n wp_enqueue_script( 'dompurify', plugin_dir_url(__FILE__) . 'assets/js/purify.min.js', array(), '1.0.0', true );\r\n\r\n // Localize the data for user id and page id\r\n $user_id = get_current_user_id();\r\n $page_id = get_the_id();\r\n\r\n $script_data_array = array(\r\n 'user_id' => $user_id,\r\n 'page_id' => $page_id,\r\n 'session_id' => $session_id,\r\n 'thread_id' => $thread_id,\r\n 'assistant_id' => $assistant_id,\r\n 'additional_instructions' => $additional_instructions,\r\n 'model' => $model,\r\n 'voice' => 'alloy',\r\n );\r\n\r\n // DIAG - Diagnostics - Ver 1.8.6\r\n // back_trace( 'NOTICE', '$user_id: ' . $user_id);\r\n // back_trace( 'NOTICE', '$page_id: ' . $page_id);\r\n // back_trace( 'NOTICE', '$session_id: ' . $session_id);\r\n // back_trace( 'NOTICE', '$thread_id: ' . $thread_id);\r\n // back_trace( 'NOTICE', '$assistant_id: ' . $assistant_id);\r\n // back_trace( 'NOTICE', '$additional_instructions: ' . $additional_instructions);\r\n // back_trace( 'NOTICE', '$model: ' . $model);\r\n \r\n // Defaults for Ver 1.6.1\r\n $defaults = array(\r\n 'chatbot_chatgpt_bot_name' => 'Kognetiks Chatbot',\r\n // TODO IDEA - Add a setting to fix or randomize the bot prompt\r\n 'chatbot_chatgpt_bot_prompt' => 'Enter your question ...',\r\n 'chatbot_chatgpt_initial_greeting' => 'Hello! How can I help you today?',\r\n 'chatbot_chatgpt_subsequent_greeting' => 'Hello again! How can I help you?',\r\n 'chatbot_chatgpt_display_style' => 'floating',\r\n 'chatbot_chatgpt_assistant_alias' => 'primary',\r\n 'chatbot_chatgpt_start_status' => 'closed',\r\n 'chatbot_chatgpt_start_status_new_visitor' => 'closed',\r\n 'chatbot_chatgpt_disclaimer_setting' => 'No',\r\n 'chatbot_chatgpt_audience_choice' => 'all',\r\n 'chatbot_chatgpt_max_tokens_setting' => '150',\r\n 'chatbot_chatgpt_message_limit_setting' => '999',\r\n 'chatbot_chatgpt_width_setting' => 'Narrow',\r\n 'chatbot_chatgpt_diagnostics' => 'Off',\r\n 'chatbot_chatgpt_avatar_icon_setting' => 'icon-001.png',\r\n 'chatbot_chatgpt_avatar_icon_url_setting' => '',\r\n 'chatbot_chatgpt_custom_avatar_icon_setting' => '',\r\n 'chatbot_chatgpt_avatar_greeting_setting' => 'Howdy!!! Great to see you today! How can I help you?',\r\n 'chatbot_chatgpt_model_choice' => 'gpt-3.5-turbo',\r\n 'chatbot_chatgpt_conversation_context' => 'You are a versatile, friendly, and helpful assistant designed to support me in a variety of tasks.',\r\n 'chatbot_chatgpt_enable_custom_buttons' => 'Off',\r\n 'chatbot_chatgpt_custom_button_name_1' => '',\r\n 'chatbot_chatgpt_custom_button_url_1' => '',\r\n 'chatbot_chatgpt_custom_button_name_2' => '',\r\n 'chatbot_chatgpt_custom_button_url_2' => '',\r\n 'chatbot_chatgpt_allow_file_uploads' => 'No',\r\n 'chatbot_chatgpt_timeout_setting' => '240',\r\n 'chatbot_chatgpt_voice_option' => 'alloy',\r\n 'chatbot_chatgpt_audio_output_format' => 'mp3',\r\n );\r\n\r\n // Revised for Ver 1.5.0 \r\n $option_keys = array(\r\n 'chatbot_chatgpt_bot_name',\r\n 'chatbot_chatgpt_bot_prompt', // Added in Ver 1.6.6\r\n 'chatbot_chatgpt_initial_greeting',\r\n 'chatbot_chatgpt_subsequent_greeting',\r\n 'chatbot_chatgpt_display_style',\r\n 'chatbot_chatgpt_assistant_alias',\r\n 'chatbot_chatgpt_start_status',\r\n 'chatbot_chatgpt_start_status_new_visitor',\r\n 'chatbot_chatgpt_disclaimer_setting',\r\n 'chatbot_chatgpt_audience_choice',\r\n 'chatbot_chatgpt_max_tokens_setting',\r\n 'chatbot_chatgpt_message_limit_setting',\r\n 'chatbot_chatgpt_width_setting',\r\n 'chatbot_chatgpt_diagnostics',\r\n 'chatbot_chatgpt_avatar_icon_setting',\r\n 'chatbot_chatgpt_avatar_icon_url_setting',\r\n 'chatbot_chatgpt_custom_avatar_icon_setting',\r\n 'chatbot_chatgpt_avatar_greeting_setting',\r\n 'chatbot_chatgpt_enable_custom_buttons',\r\n 'chatbot_chatgpt_custom_button_name_1',\r\n 'chatbot_chatgpt_custom_button_url_1',\r\n 'chatbot_chatgpt_custom_button_name_2',\r\n 'chatbot_chatgpt_custom_button_url_2',\r\n 'chatbot_chatgpt_allow_file_uploads',\r\n 'chatbot_chatgpt_timeout_setting',\r\n 'chatbot_chatgpt_voice_option',\r\n 'chatbot_chatgpt_audio_output_format',\r\n );\r\n\r\n $chatbot_settings = array();\r\n foreach ($option_keys as $key) {\r\n $default_value = $defaults[$key] ?? '';\r\n $chatbot_settings[$key] = esc_attr(get_option($key, $default_value));\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'chatbot-chatgpt.php: Key: ' . $key . ', Value: ' . $chatbot_settings[$key]);\r\n }\r\n\r\n $chatbot_settings['chatbot_chatgpt_icon_base_url'] = plugins_url( '/assets/icons/', __FILE__ );\r\n\r\n // Localize the data for javascript\r\n wp_localize_script('chatbot-chatgpt-js', 'php_vars', $script_data_array);\r\n\r\n wp_localize_script('chatbot-chatgpt-js', 'plugin_vars', array(\r\n 'plugins_url' => plugins_url('', __FILE__ ),\r\n ));\r\n\r\n wp_localize_script('chatbot-chatgpt-local', 'chatbotSettings', $chatbot_settings);\r\n\r\n wp_localize_script('chatbot-chatgpt-js', 'chatbot_chatgpt_params', array(\r\n 'plugins_url' => plugins_url('', __FILE__ ),\r\n 'ajax_url' => admin_url('admin-ajax.php'),\r\n ));\r\n\r\n // Upload files - Ver 1.7.6\r\n wp_localize_script('chatbot-chatgpt-upload-trigger-js', 'chatbot_chatgpt_params', array(\r\n 'plugins_url' => plugins_url('', __FILE__ ),\r\n 'ajax_url' => admin_url('admin-ajax.php'),\r\n ));\r\n\r\n}\r\nadd_action('wp_enqueue_scripts', 'chatbot_chatgpt_enqueue_scripts');\r\n\r\n// Settings and Deactivation Links - Ver - 1.5.0\r\nif (!function_exists('enqueue_jquery_ui')) {\r\n function enqueue_jquery_ui(): void {\r\n wp_enqueue_style('wp-jquery-ui-dialog');\r\n wp_enqueue_script('jquery-ui-dialog');\r\n }\r\n add_action( 'admin_enqueue_scripts', 'enqueue_jquery_ui' );\r\n}\r\n\r\n// Schedule Cleanup of Expired Transients\r\nif (!wp_next_scheduled('chatbot_chatgpt_cleanup_event')) {\r\n wp_schedule_event(time(), 'daily', 'chatbot_chatgpt_cleanup_event');\r\n}\r\nadd_action('chatbot_chatgpt_cleanup_event', 'clean_specific_expired_transients');\r\n\r\n// Schedule Conversation Log Cleanup - Ver 1.6.7\r\nif (!wp_next_scheduled('chatbot_chatgpt_conversation_log_cleanup_event')) {\r\n wp_schedule_event(time(), 'daily', 'chatbot_chatgpt_conversation_log_cleanup_event');\r\n}\r\nadd_action('chatbot_chatgpt_conversation_log_cleanup_event', 'chatbot_chatgpt_conversation_log_cleanup');\r\n\r\n// Schedule the transcript file cleanup event if it's not already scheduled - Ver 1.9.9\r\n// Schedule the cleanup event if it's not already scheduled\r\nif (!wp_next_scheduled('chatbot_chatgpt_cleanup_transcripts')) {\r\n wp_schedule_event(time(), 'hourly', 'chatbot_chatgpt_cleanup_transcripts');\r\n}\r\n\r\n// Schedule the audio file cleanup event if it's not already scheduled - Ver 1.9.9\r\n// Schedule the cleanup event if it's not already scheduled\r\nif (!wp_next_scheduled('chatbot_chatgpt_cleanup_audio_files')) {\r\n wp_schedule_event(time(), 'hourly', 'chatbot_chatgpt_cleanup_audio_files');\r\n}\r\n\r\n// Schedule the upload file cleanup event if it's not already scheduled - Ver 1.9.9\r\n// Schedule the cleanup event if it's not already scheduled\r\nif (!wp_next_scheduled('chatbot_chatgpt_cleanup_upload_files')) {\r\n wp_schedule_event(time(), 'hourly', 'chatbot_chatgpt_cleanup_upload_files');\r\n}\r\n\r\n// Handle Ajax requests\r\nfunction chatbot_chatgpt_send_message(): void {\r\n\r\n // Global variables\r\n global $session_id;\r\n global $user_id;\r\n global $page_id;\r\n global $thread_id;\r\n global $assistant_id;\r\n global $chatbot_chatgpt_display_style;\r\n global $chatbot_chatgpt_assistant_alias;\r\n global $script_data_array;\r\n global $additional_instructions;\r\n global $model;\r\n global $voice;\r\n\r\n global $flow_data;\r\n\r\n $api_key = '';\r\n\r\n // Retrieve the API key\r\n $api_key = esc_attr(get_option('chatbot_chatgpt_api_key'));\r\n\r\n // Retrieve the GPT Model\r\n if (!empty($model)) {\r\n $model = esc_attr(get_option('chatbot_chatgpt_model_choice', 'gpt-3.5-turbo'));\r\n // DIAG - Diagnostics\r\n // back_trace ( 'NOTICE', 'Model from options: ' . $model);\r\n } else {\r\n // SEE IF $script_data_array HAS THE MODEL\r\n if ( isset($script_data_array['model'])) {\r\n $model = $script_data_array['model'];\r\n // DIAG - Diagnostics\r\n // back_trace ( 'NOTICE', 'Model set in global: ' . $model);\r\n } else {\r\n // Set the model to the default\r\n $model = esc_attr(get_option('chatbot_chatgpt_model_choice', 'gpt-3.5-turbo'));\r\n // DIAG - Diagnostics\r\n // back_trace ( 'ERROR', 'Model not set!!!');\r\n // wp_send_json_error('Invalid Model. Please set the model in the plugin settings.');\r\n }\r\n }\r\n\r\n // Retrieve the Max tokens - Ver 1.4.2\r\n $max_tokens = esc_attr(get_option('chatbot_chatgpt_max_tokens_setting', 150));\r\n\r\n // Send only clean text via the API\r\n $message = sanitize_text_field($_POST['message']);\r\n\r\n // Check for missing API key or Message\r\n if (!$api_key || !$message) {\r\n wp_send_json_error('Invalid API key or Message. Please check the plugin settings.');\r\n }\r\n\r\n // Removed in Ver 1.8.6 - 2024 02 15\r\n // $thread_id = '';\r\n // $assistant_id = '';\r\n // $user_id = '';\r\n // $page_id = '';\r\n \r\n // Check the transient for the Assistant ID - Ver 1.7.2\r\n $user_id = intval($_POST['user_id']);\r\n $page_id = intval($_POST['page_id']);\r\n\r\n // DIAG - Diagnostics - Ver 1.8.6\r\n // back_trace( 'NOTICE', 'chatbot_chatgpt_send_message $user_id: ' . $user_id);\r\n // back_trace( 'NOTICE', 'chatbot_chatgpt_send_message $page_id: ' . $page_id);\r\n\r\n $chatbot_settings['display_style'] = get_chatbot_chatgpt_transients( 'display_style', $user_id, $page_id);\r\n $chatbot_settings['assistant_alias'] = get_chatbot_chatgpt_transients( 'assistant_alias', $user_id, $page_id);\r\n $chatbot_settings['model'] = get_chatbot_chatgpt_transients( 'model', $user_id, $page_id);\r\n $chatbot_settings['voice'] = get_chatbot_chatgpt_transients( 'voice', $user_id, $page_id);\r\n\r\n $display_style = isset($chatbot_settings['display_style']) ? $chatbot_settings['display_style'] : '';\r\n $chatbot_chatgpt_assistant_alias = isset($chatbot_settings['assistant_alias']) ? $chatbot_settings['assistant_alias'] : '';\r\n\r\n $temp_model = $chatbot_settings['model']; // Store the model in a temporary variable before overwriting $chatbot_settings\r\n\r\n $chatbot_settings = get_chatbot_chatgpt_threads($user_id, $page_id);\r\n\r\n $chatbot_settings['model'] = $temp_model; // Restore the model after overwriting $chatbot_settings\r\n\r\n $assistant_id = isset($chatbot_settings['assistantID']) ? $chatbot_settings['assistantID'] : '';\r\n $thread_Id = isset($chatbot_settings['threadID']) ? $chatbot_settings['threadID'] : '';\r\n $model = isset($chatbot_settings['model']) ? $chatbot_settings['model'] : '';\r\n\r\n // DIAG - Diagnostics - Ver 1.8.6\r\n // back_trace( 'NOTICE', '$user_id: ' . $user_id);\r\n // back_trace( 'NOTICE', '$page_id: ' . $page_id);\r\n // back_trace( 'NOTICE', '$session_id: ' . $session_id);\r\n // back_trace( 'NOTICE', '$thread_id: ' . $thread_id);\r\n // back_trace( 'NOTICE', '$assistant_id: ' . $assistant_id);\r\n // back_trace( 'NOTICE', '$model: ' . $model);\r\n\r\n // Assistants\r\n // $chatbot_chatgpt_assistant_alias == 'original'; // Default\r\n // $chatbot_chatgpt_assistant_alias == 'primary';\r\n // $chatbot_chatgpt_assistant_alias == 'alternate';\r\n // $chatbot_chatgpt_assistant_alias == 'asst_xxxxxxxxxxxxxxxxxxxxxxxx'; // GPT Assistant Id\r\n \r\n // Which Assistant ID to use - Ver 1.7.2\r\n if ($chatbot_chatgpt_assistant_alias == 'original') {\r\n $use_assistant_id = 'No';\r\n // DIAG - Diagnostics - Ver 1.8.1\r\n // back_trace( 'NOTICE' , 'Using Original GPT Assistant ID');\r\n } elseif ($chatbot_chatgpt_assistant_alias == 'primary') {\r\n $assistant_id = esc_attr(get_option('chatbot_chatgpt_assistant_id'));\r\n $additional_instructions = esc_attr(get_option('chatbot_chatgpt_assistant_instructions', ''));\r\n $use_assistant_id = 'Yes';\r\n // DIAG - Diagnostics - Ver 1.8.1\r\n // back_trace( 'NOTICE' , 'Using Primary GPT Assistant ID ' . $assistant_id);\r\n // Check if the GPT Assistant ID is blank, null, or \"Please provide the GPT Assistant ID.\"\r\n if (empty($assistant_id) || $assistant_id == \"Please provide the GPT Assistant Id.\") {\r\n // Override the $use_assistant_id and set it to 'No'\r\n $use_assistant_id = 'No';\r\n // DIAG - Diagnostics - Ver 1.8.1\r\n // back_trace( 'NOTICE' ,'Falling back to ChatGPT API' );\r\n }\r\n } elseif ($chatbot_chatgpt_assistant_alias == 'alternate') {\r\n $assistant_id = esc_attr(get_option('chatbot_chatgpt_assistant_id_alternate'));\r\n $additional_instructions = esc_attr(get_option('chatbot_chatgpt_assistant_instructions_alternate', ''));\r\n $use_assistant_id = 'Yes';\r\n // DIAG - Diagnostics - Ver 1.8.1\r\n // back_trace( 'NOTICE' , 'Using Alternate GPT Assistant ID ' . $assistant_id);\r\n // Check if the GPT Assistant ID is blank, null, or \"Please provide the GPT Assistant ID.\"\r\n if (empty($assistant_id) || $assistant_id == \"Please provide the GPT Assistant Id.\") {\r\n // Override the $use_assistant_id and set it to 'No'\r\n $use_assistant_id = 'No';\r\n // DIAG - Diagnostics - Ver 1.8.1\r\n // back_trace( 'NOTICE' ,'Falling back to ChatGPT API' );\r\n }\r\n } else {\r\n // Reference GPT Assistant IDs directly - Ver 1.7.3\r\n if (str_starts_with($chatbot_chatgpt_assistant_alias, 'asst_')) {\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Using GPT Assistant ID: ' . $chatbot_chatgpt_assistant_alias);\r\n // Override the $assistant_id with the GPT Assistant ID\r\n $assistant_id = $chatbot_chatgpt_assistant_alias;\r\n $use_assistant_id = 'Yes';\r\n // DIAG - Diagnostics - Ver 1.8.1\r\n // back_trace( 'NOTICE' , 'Using $assistant_id ' . $assistant_id);\r\n } else {\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Using ChatGPT API: ' . $chatbot_chatgpt_assistant_alias);\r\n // Override the $use_assistant_id and set it to 'No'\r\n $use_assistant_id = 'No';\r\n // DIAG - Diagnostics - Ver 1.8.1\r\n // back_trace( 'NOTICE' , 'Falling back to ChatGPT API');\r\n }\r\n }\r\n\r\n // Decide whether to use Flow, Assistant or Original ChatGPT\r\n if ($model == 'flow'){\r\n \r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Using ChatGPT Flow');\r\n\r\n // Reload the model - BELT & SUSPENDERS\r\n $script_data_array['model'] = $model;\r\n\r\n // Get the step from the transient\r\n $kflow_step = get_chatbot_chatgpt_transients( 'kflow_step', null, null, $session_id);\r\n if (empty($kflow_step)) {\r\n $kflow_step = 0; // FIXME - Set to 1 or to zero?\r\n }\r\n\r\n // $thread_id\r\n $thread_id = '[answer=' . $kflow_step + 1 . ']';\r\n \r\n // Add +1 to $script_data_array['next_step']\r\n $kflow_step = $kflow_step + 1;\r\n\r\n // Set the next step\r\n set_chatbot_chatgpt_transients( 'kflow_step', $kflow_step, null, null, $session_id);\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', '$message: ' . $message);\r\n append_message_to_conversation_log($session_id, $user_id, $page_id, 'Visitor', $thread_id, $assistant_id, $message);\r\n\r\n // BELT & SUSPENDERS\r\n $thread_id = '';\r\n\r\n // Send message to ChatGPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_call_flow_api($api_key, $message);\r\n wp_send_json_success($response);\r\n\r\n } elseif ($use_assistant_id == 'Yes') {\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Using GPT Assistant ID: ' . $use_assistant_id);\r\n // back_trace( 'NOTICE', '$user_id ' . $user_id);\r\n // back_trace( 'NOTICE', '$page_id ' . $page_id);\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', '$message ' . $message);\r\n append_message_to_conversation_log($session_id, $user_id, $page_id, 'Visitor', $thread_id, $assistant_id, $message);\r\n \r\n // Send message to Custom GPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_custom_gpt_call_api($api_key, $message, $assistant_id, $thread_id, $user_id, $page_id);\r\n\r\n // Use TF-IDF to enhance response\r\n $chatbot_chatgpt_suppress_learnings = esc_attr(get_option('chatbot_chatgpt_suppress_learnings', 'Random'));\r\n if ( $chatbot_chatgpt_suppress_learnings != 'None') {\r\n $response = $response . chatbot_chatgpt_enhance_with_tfidf($message);\r\n }\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', '$response ' . print_r($response,true));\r\n append_message_to_conversation_log($session_id, $user_id, $page_id, 'Chatbot', $thread_id, $assistant_id, $response);\r\n\r\n // Clean (erase) the output buffer - Ver 1.6.8\r\n ob_clean();\r\n if (str_starts_with($response, 'Error:') || str_starts_with($response, 'Failed:')) {\r\n // Return response\r\n // back_trace( 'NOTICE', '$response ' . print_r($response,true));\r\n wp_send_json_error('Oops! Something went wrong on our end. Please try again later');\r\n } else {\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Check for links and images in response before returning');\r\n $response = chatbot_chatgpt_check_for_links_and_images($response);\r\n // Return response\r\n wp_send_json_success($response);\r\n }\r\n } else {\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Using ChatGPT');\r\n // back_trace( 'NOTICE', '$user_id ' . $user_id);\r\n // back_trace( 'NOTICE', '$page_id ' . $page_id);\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', '$message ' . $message);\r\n append_message_to_conversation_log($session_id, $user_id, $page_id, 'Visitor', $thread_id, $assistant_id, $message);\r\n \r\n // If $model starts with 'gpt' then the chatbot_chatgpt_call_api or 'dall' then chatbot_chatgpt_call_image_api\r\n // TRY NOT TO FETCH MODEL AGAIN\r\n // $model = esc_attr(get_option('chatbot_chatgpt_model_choice', 'gpt-3.5-turbo'));\r\n if (str_starts_with($model, 'gpt')) {\r\n // Reload the model - BELT & SUSPENDERS\r\n $script_data_array['model'] = $model;\r\n // Send message to ChatGPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_call_api($api_key, $message);\r\n } elseif (str_starts_with($model, 'dall')) {\r\n // Reload the model - BELT & SUSPENDERS\r\n $script_data_array['model'] = $model;\r\n // Send message to Image API - Ver 1.9.4\r\n $response = chatbot_chatgpt_call_image_api($api_key, $message);\r\n } elseif (str_starts_with($model, 'tts')) {\r\n // Reload the model - BELT & SUSPENDERS\r\n $script_data_array['model'] = $model;\r\n // Send message to TTS API - Text-to-speech - Ver 1.9.5\r\n $response = chatbot_chatgpt_call_tts_api($api_key, $message);\r\n } elseif (str_starts_with($model,\"whisper\")) {\r\n $script_data_array['model'] = $model;\r\n // Send message to STT API - Speech-to-text - Ver 1.9.6\r\n $response = chatbot_chatgpt_call_stt_api($api_key, $message);\r\n } else {\r\n // Reload the model - BELT & SUSPENDERS\r\n $script_data_array['model'] = $model;\r\n // Send message to ChatGPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_call_api($api_key, $message);\r\n }\r\n \r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', ['message' => 'BEFORE CALL TO ENHANCE TFIDF', 'response' => $response]);\r\n \r\n // Use TF-IDF to enhance response\r\n $chatbot_chatgpt_suppress_learnings = esc_attr(get_option('chatbot_chatgpt_suppress_learnings', 'Random'));\r\n if ( $chatbot_chatgpt_suppress_learnings != 'None') {\r\n $response = $response . chatbot_chatgpt_enhance_with_tfidf($message);\r\n }\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', ['message' => 'AFTER CALL TO ENHANCE TFIDF', 'response' => $response]);\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', '$response ' . print_r($response,true));\r\n append_message_to_conversation_log($session_id, $user_id, $page_id, 'Chatbot', $thread_id, $assistant_id, $response);\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Check for links and images in response before returning');\r\n $response = chatbot_chatgpt_check_for_links_and_images($response);\r\n\r\n // Return response\r\n wp_send_json_success($response);\r\n }\r\n\r\n wp_send_json_error('Oops, I fell through the cracks!');\r\n\r\n}\r\n\r\n// Add action to send messages - Ver 1.0.0\r\nadd_action('wp_ajax_chatbot_chatgpt_send_message', 'chatbot_chatgpt_send_message');\r\nadd_action('wp_ajax_nopriv_chatbot_chatgpt_send_message', 'chatbot_chatgpt_send_message');\r\n\r\n// Add action to upload files - Ver 1.7.6\r\nadd_action('wp_ajax_chatbot_chatgpt_upload_file_to_assistant', 'chatbot_chatgpt_upload_file_to_assistant');\r\nadd_action('wp_ajax_nopriv_chatbot_chatgpt_upload_file_to_assistant', 'chatbot_chatgpt_upload_file_to_assistant');\r\n\r\n// Add action to erase conversation - Ver 1.8.6\r\nadd_action('wp_ajax_chatbot_chatgpt_erase_conversation', 'chatbot_chatgpt_erase_conversation_handler');\r\nadd_action('wp_ajax_nopriv_chatbot_chatgpt_erase_conversation', 'chatbot_chatgpt_erase_conversation_handler'); // For logged-out users, if needed\r\n\r\n// Settings and Deactivation - Ver 1.5.0\r\nadd_filter('plugin_action_links_' . plugin_basename(__FILE__), 'chatbot_chatgpt_plugin_action_links');\r\n\r\n// Crawler aka Knowledge Navigator - Ver 1.6.1\r\nfunction chatbot_chatgpt_kn_status_activation(): void {\r\n add_option('chatbot_chatgpt_kn_status', 'Never Run');\r\n // clear any old scheduled runs\r\n if (wp_next_scheduled('crawl_scheduled_event_hook')) {\r\n wp_clear_scheduled_hook('crawl_scheduled_event_hook');\r\n }\r\n // clear the 'knowledge_navigator_scan_hook' hook on plugin activation - Ver 1.6.3\r\n if (wp_next_scheduled('knowledge_navigator_scan_hook')) {\r\n // BREAK/FIX - Do not unset the hook - Ver 1.8.5\r\n // wp_clear_scheduled_hook('knowledge_navigator_scan_hook'); // Clear scheduled runs\r\n }\r\n}\r\nregister_activation_hook(__FILE__, 'chatbot_chatgpt_kn_status_activation');\r\n\r\n// Clean Up in Aisle 4\r\nfunction chatbot_chatgpt_kn_status_deactivation(): void {\r\n delete_option('chatbot_chatgpt_kn_status');\r\n wp_clear_scheduled_hook('knowledge_navigator_scan_hook'); \r\n}\r\nregister_deactivation_hook(__FILE__, 'chatbot_chatgpt_kn_status_deactivation');\r\n\r\n// Function to add a new message and response, keeping only the last five - Ver 1.6.1\r\nfunction addEntry($transient_name, $newEntry): void {\r\n\r\n $context_history = get_transient($transient_name);\r\n if (!$context_history) {\r\n $context_history = [];\r\n }\r\n\r\n // Determine the total length of all existing entries\r\n $totalLength = 0;\r\n foreach ($context_history as $entry) {\r\n if (is_string($entry)) {\r\n $totalLength += strlen($entry);\r\n } elseif (is_array($entry)) {\r\n $totalLength += strlen(json_encode($entry)); // Convert to string if an array\r\n }\r\n }\r\n\r\n // IDEA - How will the new threading option from OpenAI change how this works?\r\n // Define thresholds for the number of entries to keep\r\n $maxEntries = 30; // Default maximum number of entries\r\n if ($totalLength > 5000) { // Higher threshold\r\n $maxEntries = 20;\r\n }\r\n if ($totalLength > 10000) { // Lower threshold\r\n $maxEntries = 10;\r\n }\r\n\r\n while (count($context_history) >= $maxEntries) {\r\n array_shift($context_history); // Remove the oldest element\r\n }\r\n\r\n if (is_array($newEntry)) {\r\n $newEntry = json_encode($newEntry); // Convert the array to a string\r\n }\r\n\r\n array_push($context_history, $newEntry); // Append the new element\r\n set_transient($transient_name, $context_history); // Update the transient\r\n}\r\n\r\n\r\n// Function to return message and response - Ver 1.6.1\r\nfunction concatenateHistory($transient_name): string {\r\n $context_history = get_transient($transient_name);\r\n if (!$context_history) {\r\n return ''; // Return an empty string if the transient does not exist\r\n }\r\n return implode(' ', $context_history); // Concatenate the array values into a single string\r\n}\r\n\r\n// Initialize the Greetings - Ver 1.6.1\r\nfunction enqueue_greetings_script(): void {\r\n\r\n // DIAG - Diagnostics - Ver 1.6.1\r\n // back_trace( 'NOTICE', \"enqueue_greetings_script() called\");\r\n\r\n wp_enqueue_script('greetings', plugin_dir_url(__FILE__) . 'assets/js/greetings.js', array('jquery'), null, true);\r\n\r\n // If user is logged in, then modify greeting if greeting contains \"[...]\" or remove if not logged in - Ver 1.9.4\r\n if (is_user_logged_in()) {\r\n\r\n $current_user_id = get_current_user_id();\r\n $current_user = get_userdata($current_user_id);\r\n\r\n //Do this for Initial Greeting\r\n $initial_greeting = esc_attr(get_option('chatbot_chatgpt_initial_greeting', 'Hello! How can I help you today?'));\r\n\r\n // Determine what the field name is between the brackets\r\n $user_field_name = '';\r\n $user_field_name = substr($initial_greeting, strpos($initial_greeting, '[') + 1, strpos($initial_greeting, ']') - strpos($initial_greeting, '[') - 1);\r\n\r\n // If $initial_greeting contains \"[$user_field_name]\" then replace with field from DB\r\n if (strpos($initial_greeting, '[' . $user_field_name . ']') !== false) {\r\n $initial_greeting = str_replace('[' . $user_field_name . ']', $current_user->$user_field_name, $initial_greeting);\r\n } else {\r\n $initial_greeting = str_replace('[' . $user_field_name . ']', '', $initial_greeting);\r\n }\r\n\r\n // Do this for Subsequent Greeting\r\n $subsequent_greeting = esc_attr(get_option('chatbot_chatgpt_subsequent_greeting', 'Hello again! How can I help you?'));\r\n\r\n // Determine what the field name is between the brackets\r\n $user_field_name = '';\r\n $user_field_name = substr($subsequent_greeting, strpos($subsequent_greeting, '[') + 1, strpos($subsequent_greeting, ']') - strpos($subsequent_greeting, '[') - 1);\r\n\r\n // If $subsequent_greeting contains \"[$user_field_name]\" then replace with field from DB\r\n if (strpos($subsequent_greeting, '[' . $user_field_name . ']') !== false) {\r\n $subsequent_greeting = str_replace('[' . $user_field_name . ']', $current_user->$user_field_name, $subsequent_greeting);\r\n } else {\r\n $subsequent_greeting = str_replace('[' . $user_field_name . ']', '', $subsequent_greeting);\r\n }\r\n\r\n } else {\r\n\r\n $initial_greeting = esc_attr(get_option('chatbot_chatgpt_initial_greeting', 'Hello! How can I help you today?'));\r\n\r\n $user_field_name = '';\r\n $user_field_name = substr($initial_greeting, strpos($initial_greeting, '[') + 1, strpos($initial_greeting, ']') - strpos($initial_greeting, '[') - 1 );\r\n\r\n // $initial_greeting = str_replace('[' . $user_field_name . ']', '', $initial_greeting);\r\n $initial_greeting = preg_replace('/\\s*\\[' . preg_quote($user_field_name, '/') . '\\]\\s*/', '', $initial_greeting);\r\n\r\n $subsequent_greeting = esc_attr(get_option('chatbot_chatgpt_subsequent_greeting', 'Hello again! How can I help you?'));\r\n\r\n $user_field_name = '';\r\n $user_field_name = substr($subsequent_greeting, strpos($subsequent_greeting, '[') + 1, strpos($subsequent_greeting, ']') - strpos($subsequent_greeting, '[') - 1);\r\n\r\n // $subsequent_greeting = str_replace('[' . $user_field_name . ']', '', $subsequent_greeting);\r\n $subsequent_greeting = preg_replace('/\\s*\\[' . preg_quote($user_field_name, '/') . '\\]\\s*/', '', $subsequent_greeting);\r\n }\r\n\r\n $greetings = array(\r\n 'initial_greeting' => $initial_greeting,\r\n 'subsequent_greeting' => $subsequent_greeting,\r\n );\r\n\r\n wp_localize_script('greetings', 'greetings_data', $greetings);\r\n\r\n}\r\nadd_action('wp_enqueue_scripts', 'enqueue_greetings_script');\r\n\r\n\r\n// Function to add the adaptive appearance settings to the Chatbot settings page\r\nfunction chatbot_chatgpt_settings_appearance(): void {\r\n\r\n // Register the settings\r\n register_setting('chatbot_chatgpt_settings_appearance', 'chatbot_chatgpt_appearance');\r\n\r\n // Add the adaptive appearance settings section\r\n add_settings_section(\r\n 'chatbot_chatgpt_settings_appearance_section',\r\n 'Adaptive Appearance Settings',\r\n 'chatbot_chatgpt_settings_appearance_section_callback',\r\n 'chatbot_chatgpt_settings_appearance'\r\n );\r\n\r\n // Add the adaptive appearance settings fields\r\n add_settings_field(\r\n 'chatbot_chatgpt_settings_appearance_field',\r\n 'Adaptive Appearance Settings',\r\n 'chatbot_chatgpt_settings_appearance_field_callback',\r\n 'chatbot_chatgpt_settings_appearance',\r\n 'chatbot_chatgpt_settings_appearance_section'\r\n );\r\n\r\n}\r\n\r\n// Add the color picker to the adaptive appearance settings section - Ver 1.8.1\r\nfunction enqueue_color_picker($hook_suffix): void {\r\n // first check that $hook_suffix is appropriate for your admin page\r\n wp_enqueue_style('wp-color-picker');\r\n wp_enqueue_script('my-script-handle', plugin_dir_url(__FILE__) . 'assets/js/chatbot-chatgpt-color-picker.js', array('wp-color-picker'), false, true);\r\n}\r\nadd_action('admin_enqueue_scripts', 'enqueue_color_picker');\r\n\r\n// Determine if the plugin is installed\r\nfunction kchat_get_plugin_version() {\r\n\r\n if (!function_exists('get_plugin_data')) {\r\n require_once(ABSPATH . 'wp-admin/includes/plugin.php');\r\n }\r\n\r\n $plugin_data = get_plugin_data(plugin_dir_path(__FILE__) . 'chatbot-chatgpt.php');\r\n $plugin_version = $plugin_data['Version'];\r\n update_option('chatbot_chatgpt_plugin_version', $plugin_version);\r\n // DIAG - Log the plugin version\r\n // back_trace( 'NOTICE', 'Plugin version '. $plugin_version);\r\n\r\n return $plugin_version;\r\n\r\n}\r\n"}, "7360609efbfca6902539f38cd3d99864bd62e5e7": {"t": 1785756426.2893257, "n": 43040, "h": "f7de1439a151fce0", "c": " 0,\r\n 'cookie_path' => '/',\r\n 'cookie_domain' => $_SERVER['HTTP_HOST'],\r\n 'cookie_secure' => true,\r\n 'cookie_httponly' => true,\r\n 'cookie_samesite' => 'Strict'\r\n ]);\r\n }\r\n $session_id = session_id();\r\n session_write_close(); // Close the session after setting the session id\r\n\r\n}\r\n\r\nob_end_flush(); // End output buffering and send the buffer to the browser\r\n\r\n// Include necessary files - Main files\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/chatbot-call-gpt-api.php'; // ChatGPT API - Ver 1.6.9\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/chatbot-call-gpt-assistant.php'; // Custom GPT Assistants - Ver 1.6.9\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/chatbot-call-image-api.php'; // Image API - Ver 1.9.4\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/chatbot-call-tts-api.php'; // TTS API - Ver 1.9.4\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/chatbot-globals.php'; // Globals - Ver 1.6.5\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/chatbot-shortcode.php';\r\n\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/chatbot-call-flow-api.php'; // ChatGPT API - Ver 1.9.5\r\n\r\n// Include necessary files - Appearance - Ver 1.8.1\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/appearance/chatbot-settings-appearance-body.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/appearance/chatbot-settings-appearance-dimensions.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/appearance/chatbot-settings-appearance-text.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/appearance/chatbot-settings-appearance-user-css.php';\r\n\r\n// Include necessary files - Knowledge Navigator\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/knowledge-navigator/chatbot-kn-acquire.php'; // Knowledge Navigator Acquisition - Ver 1.6.3\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/knowledge-navigator/chatbot-kn-acquire-controller.php'; // Knowledge Navigator Acquisition - Ver 1.9.6\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/knowledge-navigator/chatbot-kn-acquire-words.php'; // Knowledge Navigator Acquisition - Ver 1.9.6\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/knowledge-navigator/chatbot-kn-analysis.php'; // Knowledge Navigator Analysis- Ver 1.6.2\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/knowledge-navigator/chatbot-kn-db.php'; // Knowledge Navigator - Database Management - Ver 1.6.3\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/knowledge-navigator/chatbot-kn-enhance-context.php'; // Knowledge Navigator - Enhance Context - Ver 1.6.9\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/knowledge-navigator/chatbot-kn-enhance-response.php'; // Knowledge Navigator - TD-IDF Response Enhancement - Ver 1.6.9\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/knowledge-navigator/chatbot-kn-scheduler.php'; // Knowledge Navigator - Scheduler - Ver 1.6.3\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/knowledge-navigator/chatbot-kn-settings.php'; // Knowledge Navigator - Settings - Ver 1.6.1\r\n\r\n// Include necessary files - Settings\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-api-model.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-api-test.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-appearance.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-avatar.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-buttons.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-custom-gpts.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-diagnostics.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-links.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-localization.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-localize.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-notices.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-premium.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-registration-api.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-registration.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-reporting.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-setup.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-support.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings.php';\r\n\r\n// Include necessary files - Utilities - Ver 1.9.0\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/utilities/chatbot-conversation-history.php'; // Ver 1.9.2\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/utilities/chatbot-db-management.php'; // Database Management for Reporting - Ver 1.6.3\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/utilities/chatbot-erase-conversation.php'; // Functions - Ver 1.8.6\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/utilities/chatbot-file-upload.php'; // Functions - Ver 1.7.6\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/utilities/chatbot-filter-out-html-tags.php'; // Functions - Ver 1.9.6\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/utilities/chatbot-link-and-image-handling.php'; // Globals - Ver 1.9.1\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/utilities/chatbot-models.php'; // Functions - Ver 1.9.4\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/utilities/chatbot-names.php'; // Functions - Ver 1.9.4\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/utilities/chatbot-threads.php'; // Ver 1.7.2.1\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/utilities/chatbot-transients-file.php'; // Ver 1.9.2\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/utilities/chatbot-transients.php'; // Ver 1.7.2\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/utilities/chatbot-upgrade.php'; // Ver 1.6.7\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/utilities/chatbot-utilities.php'; // Ver 1.8.6\r\n\r\nadd_action('init', 'my_custom_buffer_start');\r\nfunction my_custom_buffer_start(): void {\r\n ob_start();\r\n}\r\n\r\n// Check for Upgrades - Ver 1.7.7\r\nif (!esc_attr(get_option('chatbot_chatgpt_upgraded'))) {\r\n chatbot_chatgpt_upgrade();\r\n update_option('chatbot_chatgpt_upgraded', 'Yes');\r\n}\r\n\r\n// Diagnotics on/off setting can be found on the Settings tab - Ver 1.5.0\r\n$chatbot_chatgpt_diagnostics = esc_attr(get_option('chatbot_chatgpt_diagnostics', 'Off'));\r\n\r\n// Dump the chatbot settings - Ver 1.8.6\r\n// DIAG - Diagnostics\r\n// back_trace('NOTICE', 'chatbot-chatgpt.php: Dump Options to File is ON');\r\n// chatbot_chatgpt_dump_options_to_file();\r\n\r\n// Model choice - Ver 1.9.4\r\nglobal $model;\r\n// Starting with V1.9.4 the model choice \"gpt-4-turbo\" is replaced with \"gpt-4-1106-preview\"\r\nif (get_option('chatbot_chatgpt_model_choice') == 'gpt-4-turbo') {\r\n $model = 'gpt-4-1106-preview';\r\n update_option('chatbot_chatgpt_model_choice', $model);\r\n // DIAG - Diagnostics\r\n // back_trace ( 'NOTICE', 'Model upgraded: ' . $model);\r\n}\r\n\r\n// Voice choice - Ver 1.9.5\r\nglobal $voice;\r\nif (get_option('chatbot_chatgpt_voice_option') == 'alloy') {\r\n $voice = 'alloy';\r\n update_option('chatbot_chatgpt_voice_option', $voice);\r\n // DIAG - Diagnostics\r\n // back_trace ( 'NOTICE', 'Voice upgraded: ' . $voice);\r\n}\r\n\r\n// Custom buttons on/off setting can be found on the Settings tab - Ver 1.6.5\r\n$chatbot_chatgpt_enable_custom_buttons = esc_attr(get_option('chatbot_chatgpt_enable_custom_buttons', 'Off'));\r\n\r\n// Allow file uploads on/off setting can be found on the Settings tab - Ver 1.7.6\r\nglobal $chatbot_chatgpt_allow_file_uploads;\r\n// TEMP OVERRIDE - Ver 1.7.6\r\n// update_option('chatbot_chatgpt_allow_file_uploads', 'No');\r\n$chatbot_chatgpt_allow_file_uploads = esc_attr(get_option('chatbot_chatgpt_allow_file_uploads', 'No'));\r\n\r\n// Suppress Notices on/off setting can be found on the Settings tab - Ver 1.6.5\r\nglobal $chatbot_chatgpt_suppress_notices;\r\n$chatbot_chatgpt_suppress_notices = esc_attr(get_option('chatbot_chatgpt_suppress_notices', 'Off'));\r\n\r\n// Suppress Attribution on/off setting can be found on the Settings tab - Ver 1.6.5\r\nglobal $chatbot_chatgpt_suppress_attribution;\r\n$chatbot_chatgpt_suppress_attribution = esc_attr(get_option('chatbot_chatgpt_suppress_attribution', 'Off'));\r\n\r\n// Suppress Learnings Message - Ver 1.7.1\r\nglobal $chatbot_chatgpt_suppress_learnings;\r\n$chatbot_chatgpt_suppress_learnings = esc_attr(get_option('chatbot_chatgpt_suppress_learnings', 'Random'));\r\n\r\n// Context History - Ver 1.6.1\r\n$context_history = [];\r\n\r\nfunction chatbot_chatgpt_enqueue_admin_scripts(): void {\r\n wp_enqueue_script('chatbot_chatgpt_admin', plugins_url('assets/js/chatbot-chatgpt-admin.js', __FILE__), array('jquery'), '1.0.0', true);\r\n}\r\nadd_action('admin_enqueue_scripts', 'chatbot_chatgpt_enqueue_admin_scripts');\r\n\r\n// Activation, deactivation, and uninstall functions\r\nregister_activation_hook(__FILE__, 'chatbot_chatgpt_activate');\r\nregister_deactivation_hook(__FILE__, 'chatbot_chatgpt_deactivate');\r\nregister_uninstall_hook(__FILE__, 'chatbot_chatgpt_uninstall');\r\nadd_action('upgrader_process_complete', 'chatbot_chatgpt_upgrade_completed', 10, 2);\r\n\r\n// Enqueue plugin scripts and styles\r\nfunction chatbot_chatgpt_enqueue_scripts(): void {\r\n\r\n global $session_id;\r\n global $user_id;\r\n global $page_id;\r\n global $thread_id;\r\n global $assistant_id;\r\n global $script_data_array;\r\n global $additional_instructions;\r\n global $model;\r\n global $voice;\r\n\r\n // Enqueue the styles\r\n wp_enqueue_style('dashicons');\r\n wp_enqueue_style('chatbot-chatgpt-css', plugins_url('assets/css/chatbot-chatgpt.css', __FILE__));\r\n\r\n // Now override the default styles with the custom styles - Ver 1.8.1\r\n chatbot_chatgpt_appearance_custom_css_settings();\r\n\r\n // Custom css overrides - Ver 1.8.1\r\n // $customer_css_path = plugins_url(assets/css/chatbot-chatgpt-custom.css', __FILE__));\r\n // if ( file_exists ( $customer_css_path )) {\r\n // wp_enqueue_style('chatbot-chatgpt-custom-css', plugins_url('assets/css/chatbot-chatgpt-custom.css', __FILE__));\r\n // }\r\n\r\n // Enqueue the scripts\r\n wp_enqueue_script('chatbot-chatgpt-js', plugins_url('assets/js/chatbot-chatgpt.js', __FILE__), array('jquery'), '1.0', true);\r\n wp_enqueue_script('chatbot-chatgpt-local', plugins_url('assets/js/chatbot-chatgpt-local.js', __FILE__), array('jquery'), '1.0', true);\r\n\r\n // Enqueue DOMPurify - Ver 1.8.1\r\n // https://raw.githubusercontent.com/cure53/DOMPurify/main/dist/purify.min.js\r\n // https://chat.openai.com/c/275770c1-fa72-404b-97c2-2dad2e8a0230\r\n wp_enqueue_script( 'dompurify', plugin_dir_url(__FILE__) . 'assets/js/purify.min.js', array(), '1.0.0', true );\r\n\r\n // Localize the data for user id and page id\r\n $user_id = get_current_user_id();\r\n $page_id = get_the_id();\r\n\r\n $script_data_array = array(\r\n 'user_id' => $user_id,\r\n 'page_id' => $page_id,\r\n 'session_id' => $session_id,\r\n 'thread_id' => $thread_id,\r\n 'assistant_id' => $assistant_id,\r\n 'additional_instructions' => $additional_instructions,\r\n 'model' => $model,\r\n 'voice' => 'alloy',\r\n );\r\n\r\n // DIAG - Diagnostics - Ver 1.8.6\r\n // back_trace( 'NOTICE', '$user_id: ' . $user_id);\r\n // back_trace( 'NOTICE', '$page_id: ' . $page_id);\r\n // back_trace( 'NOTICE', '$session_id: ' . $session_id);\r\n // back_trace( 'NOTICE', '$thread_id: ' . $thread_id);\r\n // back_trace( 'NOTICE', '$assistant_id: ' . $assistant_id);\r\n // back_trace( 'NOTICE', '$additional_instructions: ' . $additional_instructions);\r\n // back_trace( 'NOTICE', '$model: ' . $model);\r\n \r\n // Defaults for Ver 1.6.1\r\n $defaults = array(\r\n 'chatbot_chatgpt_bot_name' => 'Kognetiks Chatbot',\r\n // TODO IDEA - Add a setting to fix or randomize the bot prompt\r\n 'chatbot_chatgpt_bot_prompt' => 'Enter your question ...',\r\n 'chatbot_chatgpt_initial_greeting' => 'Hello! How can I help you today?',\r\n 'chatbot_chatgpt_subsequent_greeting' => 'Hello again! How can I help you?',\r\n 'chatbot_chatgpt_display_style' => 'floating',\r\n 'chatbot_chatgpt_assistant_alias' => 'primary',\r\n 'chatbot_chatgpt_start_status' => 'closed',\r\n 'chatbot_chatgpt_start_status_new_visitor' => 'closed',\r\n 'chatbot_chatgpt_disclaimer_setting' => 'No',\r\n 'chatbot_chatgpt_audience_choice' => 'all',\r\n 'chatbot_chatgpt_max_tokens_setting' => '150',\r\n 'chatbot_chatgpt_message_limit_setting' => '999',\r\n 'chatbot_chatgpt_width_setting' => 'Narrow',\r\n 'chatbot_chatgpt_diagnostics' => 'Off',\r\n 'chatbot_chatgpt_avatar_icon_setting' => 'icon-001.png',\r\n 'chatbot_chatgpt_avatar_icon_url_setting' => '',\r\n 'chatbot_chatgpt_custom_avatar_icon_setting' => '',\r\n 'chatbot_chatgpt_avatar_greeting_setting' => 'Howdy!!! Great to see you today! How can I help you?',\r\n 'chatbot_chatgpt_model_choice' => 'gpt-3.5-turbo',\r\n 'chatbot_chatgpt_conversation_context' => 'You are a versatile, friendly, and helpful assistant designed to support me in a variety of tasks.',\r\n 'chatbot_chatgpt_enable_custom_buttons' => 'Off',\r\n 'chatbot_chatgpt_custom_button_name_1' => '',\r\n 'chatbot_chatgpt_custom_button_url_1' => '',\r\n 'chatbot_chatgpt_custom_button_name_2' => '',\r\n 'chatbot_chatgpt_custom_button_url_2' => '',\r\n 'chatbot_chatgpt_allow_file_uploads' => 'No',\r\n 'chatbot_chatgpt_timeout_setting' => '240',\r\n 'chatbot_chatgpt_voice_option' => 'alloy',\r\n 'chatbot_chatgpt_audio_output_format' => 'mp3',\r\n );\r\n\r\n // Revised for Ver 1.5.0 \r\n $option_keys = array(\r\n 'chatbot_chatgpt_bot_name',\r\n 'chatbot_chatgpt_bot_prompt', // Added in Ver 1.6.6\r\n 'chatbot_chatgpt_initial_greeting',\r\n 'chatbot_chatgpt_subsequent_greeting',\r\n 'chatbot_chatgpt_display_style',\r\n 'chatbot_chatgpt_assistant_alias',\r\n 'chatbot_chatgpt_start_status',\r\n 'chatbot_chatgpt_start_status_new_visitor',\r\n 'chatbot_chatgpt_disclaimer_setting',\r\n 'chatbot_chatgpt_audience_choice',\r\n 'chatbot_chatgpt_max_tokens_setting',\r\n 'chatbot_chatgpt_message_limit_setting',\r\n 'chatbot_chatgpt_width_setting',\r\n 'chatbot_chatgpt_diagnostics',\r\n 'chatbot_chatgpt_avatar_icon_setting',\r\n 'chatbot_chatgpt_avatar_icon_url_setting',\r\n 'chatbot_chatgpt_custom_avatar_icon_setting',\r\n 'chatbot_chatgpt_avatar_greeting_setting',\r\n 'chatbot_chatgpt_enable_custom_buttons',\r\n 'chatbot_chatgpt_custom_button_name_1',\r\n 'chatbot_chatgpt_custom_button_url_1',\r\n 'chatbot_chatgpt_custom_button_name_2',\r\n 'chatbot_chatgpt_custom_button_url_2',\r\n 'chatbot_chatgpt_allow_file_uploads',\r\n 'chatbot_chatgpt_timeout_setting',\r\n 'chatbot_chatgpt_voice_option',\r\n 'chatbot_chatgpt_audio_output_format',\r\n );\r\n\r\n $chatbot_settings = array();\r\n foreach ($option_keys as $key) {\r\n $default_value = $defaults[$key] ?? '';\r\n $chatbot_settings[$key] = esc_attr(get_option($key, $default_value));\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'chatbot-chatgpt.php: Key: ' . $key . ', Value: ' . $chatbot_settings[$key]);\r\n }\r\n\r\n $chatbot_settings['chatbot_chatgpt_icon_base_url'] = plugins_url( '/assets/icons/', __FILE__ );\r\n\r\n // Localize the data for javascript\r\n wp_localize_script('chatbot-chatgpt-js', 'php_vars', $script_data_array);\r\n\r\n wp_localize_script('chatbot-chatgpt-js', 'plugin_vars', array(\r\n 'plugins_url' => plugins_url('', __FILE__ ),\r\n ));\r\n\r\n wp_localize_script('chatbot-chatgpt-local', 'chatbotSettings', $chatbot_settings);\r\n\r\n wp_localize_script('chatbot-chatgpt-js', 'chatbot_chatgpt_params', array(\r\n 'plugins_url' => plugins_url('', __FILE__ ),\r\n 'ajax_url' => admin_url('admin-ajax.php'),\r\n ));\r\n\r\n // Upload files - Ver 1.7.6\r\n wp_localize_script('chatbot-chatgpt-upload-trigger-js', 'chatbot_chatgpt_params', array(\r\n 'plugins_url' => plugins_url('', __FILE__ ),\r\n 'ajax_url' => admin_url('admin-ajax.php'),\r\n ));\r\n\r\n}\r\nadd_action('wp_enqueue_scripts', 'chatbot_chatgpt_enqueue_scripts');\r\n\r\n// Settings and Deactivation Links - Ver - 1.5.0\r\nif (!function_exists('enqueue_jquery_ui')) {\r\n function enqueue_jquery_ui(): void {\r\n wp_enqueue_style('wp-jquery-ui-dialog');\r\n wp_enqueue_script('jquery-ui-dialog');\r\n }\r\n add_action( 'admin_enqueue_scripts', 'enqueue_jquery_ui' );\r\n}\r\n\r\n// Schedule Cleanup of Expired Transients\r\nif (!wp_next_scheduled('chatbot_chatgpt_cleanup_event')) {\r\n wp_schedule_event(time(), 'daily', 'chatbot_chatgpt_cleanup_event');\r\n}\r\nadd_action('chatbot_chatgpt_cleanup_event', 'clean_specific_expired_transients');\r\n\r\n// Schedule Conversation Log Cleanup - Ver 1.6.7\r\nif (!wp_next_scheduled('chatbot_chatgpt_conversation_log_cleanup_event')) {\r\n wp_schedule_event(time(), 'daily', 'chatbot_chatgpt_conversation_log_cleanup_event');\r\n}\r\nadd_action('chatbot_chatgpt_conversation_log_cleanup_event', 'chatbot_chatgpt_conversation_log_cleanup');\r\n\r\n\r\n// Handle Ajax requests\r\nfunction chatbot_chatgpt_send_message(): void {\r\n\r\n // Global variables\r\n global $session_id;\r\n global $user_id;\r\n global $page_id;\r\n global $thread_id;\r\n global $assistant_id;\r\n global $chatbot_chatgpt_display_style;\r\n global $chatbot_chatgpt_assistant_alias;\r\n global $script_data_array;\r\n global $additional_instructions;\r\n global $model;\r\n global $voice;\r\n\r\n global $flow_data;\r\n\r\n $api_key = '';\r\n\r\n // Retrieve the API key\r\n $api_key = esc_attr(get_option('chatbot_chatgpt_api_key'));\r\n\r\n // Retrieve the GPT Model\r\n if (!empty($model)) {\r\n $model = esc_attr(get_option('chatbot_chatgpt_model_choice', 'gpt-3.5-turbo'));\r\n // DIAG - Diagnostics\r\n // back_trace ( 'NOTICE', 'Model from options: ' . $model);\r\n } else {\r\n // SEE IF $script_data_array HAS THE MODEL\r\n if ( isset($script_data_array['model'])) {\r\n $model = $script_data_array['model'];\r\n // DIAG - Diagnostics\r\n // back_trace ( 'NOTICE', 'Model set in global: ' . $model);\r\n } else {\r\n // FIXME - I SHOULDN'T BE FALLING THRU HERE - DO NOTHING\r\n // DIAG - Diagnostics\r\n // back_trace ( 'ERROR', 'Model not set!!!');\r\n }\r\n }\r\n\r\n // Retrieve the Max tokens - Ver 1.4.2\r\n $max_tokens = esc_attr(get_option('chatbot_chatgpt_max_tokens_setting', 150));\r\n\r\n // Send only clean text via the API\r\n $message = sanitize_text_field($_POST['message']);\r\n\r\n // FIXME - ADD THIS BACK IN AFTER DECIDING WHAT TO DO ABOUT MISSING OR BAD API KEYS\r\n // Check API key and message\r\n if (!$api_key || !$message) {\r\n wp_send_json_error('Invalid API key or message');\r\n }\r\n\r\n // Removed in Ver 1.8.6 - 2024 02 15\r\n // $thread_id = '';\r\n // $assistant_id = '';\r\n // $user_id = '';\r\n // $page_id = '';\r\n \r\n // Check the transient for the Assistant ID - Ver 1.7.2\r\n $user_id = intval($_POST['user_id']);\r\n $page_id = intval($_POST['page_id']);\r\n\r\n // DIAG - Diagnostics - Ver 1.8.6\r\n // back_trace( 'NOTICE', 'chatbot_chatgpt_send_message $user_id: ' . $user_id);\r\n // back_trace( 'NOTICE', 'chatbot_chatgpt_send_message $page_id: ' . $page_id);\r\n\r\n $chatbot_settings['display_style'] = get_chatbot_chatgpt_transients( 'display_style', $user_id, $page_id);\r\n $chatbot_settings['assistant_alias'] = get_chatbot_chatgpt_transients( 'assistant_alias', $user_id, $page_id);\r\n $chatbot_settings['model'] = get_chatbot_chatgpt_transients( 'model', $user_id, $page_id);\r\n $chatbot_settings['voice'] = get_chatbot_chatgpt_transients( 'voice', $user_id, $page_id);\r\n\r\n $display_style = isset($chatbot_settings['display_style']) ? $chatbot_settings['display_style'] : '';\r\n $chatbot_chatgpt_assistant_alias = isset($chatbot_settings['assistant_alias']) ? $chatbot_settings['assistant_alias'] : '';\r\n\r\n $temp_model = $chatbot_settings['model']; // Store the model in a temporary variable before overwriting $chatbot_settings\r\n\r\n $chatbot_settings = get_chatbot_chatgpt_threads($user_id, $page_id);\r\n\r\n $chatbot_settings['model'] = $temp_model; // Restore the model after overwriting $chatbot_settings\r\n\r\n $assistant_id = isset($chatbot_settings['assistantID']) ? $chatbot_settings['assistantID'] : '';\r\n $thread_Id = isset($chatbot_settings['threadID']) ? $chatbot_settings['threadID'] : '';\r\n $model = isset($chatbot_settings['model']) ? $chatbot_settings['model'] : '';\r\n\r\n // DIAG - Diagnostics - Ver 1.8.6\r\n // back_trace( 'NOTICE', '$user_id: ' . $user_id);\r\n // back_trace( 'NOTICE', '$page_id: ' . $page_id);\r\n // back_trace( 'NOTICE', '$session_id: ' . $session_id);\r\n // back_trace( 'NOTICE', '$thread_id: ' . $thread_id);\r\n // back_trace( 'NOTICE', '$assistant_id: ' . $assistant_id);\r\n // back_trace( 'NOTICE', '$model: ' . $model);\r\n\r\n // Assistants\r\n // $chatbot_chatgpt_assistant_alias == 'original'; // Default\r\n // $chatbot_chatgpt_assistant_alias == 'primary';\r\n // $chatbot_chatgpt_assistant_alias == 'alternate';\r\n // $chatbot_chatgpt_assistant_alias == 'asst_xxxxxxxxxxxxxxxxxxxxxxxx'; // GPT Assistant Id\r\n \r\n // Which Assistant ID to use - Ver 1.7.2\r\n if ($chatbot_chatgpt_assistant_alias == 'original') {\r\n $use_assistant_id = 'No';\r\n // DIAG - Diagnostics - Ver 1.8.1\r\n // back_trace( 'NOTICE' , 'Using Original GPT Assistant ID');\r\n } elseif ($chatbot_chatgpt_assistant_alias == 'primary') {\r\n $assistant_id = esc_attr(get_option('chatbot_chatgpt_assistant_id'));\r\n $additional_instructions = esc_attr(get_option('chatbot_chatgpt_assistant_instructions'), '');\r\n $use_assistant_id = 'Yes';\r\n // DIAG - Diagnostics - Ver 1.8.1\r\n // back_trace( 'NOTICE' , 'Using Primary GPT Assistant ID ' . $assistant_id);\r\n // Check if the GPT Assistant ID is blank, null, or \"Please provide the GPT Assistant ID.\"\r\n if (empty($assistant_id) || $assistant_id == \"Please provide the GPT Assistant Id.\") {\r\n // Override the $use_assistant_id and set it to 'No'\r\n $use_assistant_id = 'No';\r\n // DIAG - Diagnostics - Ver 1.8.1\r\n // back_trace( 'NOTICE' ,'Falling back to ChatGPT API' );\r\n }\r\n } elseif ($chatbot_chatgpt_assistant_alias == 'alternate') {\r\n $assistant_id = esc_attr(get_option('chatbot_chatgpt_assistant_id_alternate'));\r\n $additional_instructions = esc_attr(get_option('chatbot_chatgpt_assistant_instructions_alternate'), '');\r\n $use_assistant_id = 'Yes';\r\n // DIAG - Diagnostics - Ver 1.8.1\r\n // back_trace( 'NOTICE' , 'Using Alternate GPT Assistant ID ' . $assistant_id);\r\n // Check if the GPT Assistant ID is blank, null, or \"Please provide the GPT Assistant ID.\"\r\n if (empty($assistant_id) || $assistant_id == \"Please provide the GPT Assistant Id.\") {\r\n // Override the $use_assistant_id and set it to 'No'\r\n $use_assistant_id = 'No';\r\n // DIAG - Diagnostics - Ver 1.8.1\r\n // back_trace( 'NOTICE' ,'Falling back to ChatGPT API' );\r\n }\r\n } else {\r\n // Reference GPT Assistant IDs directly - Ver 1.7.3\r\n if (str_starts_with($chatbot_chatgpt_assistant_alias, 'asst_')) {\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Using GPT Assistant ID: ' . $chatbot_chatgpt_assistant_alias);\r\n // Override the $assistant_id with the GPT Assistant ID\r\n $assistant_id = $chatbot_chatgpt_assistant_alias;\r\n $use_assistant_id = 'Yes';\r\n // DIAG - Diagnostics - Ver 1.8.1\r\n // back_trace( 'NOTICE' , 'Using GPT Assistant Id ' . $assistant_id);\r\n } else {\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Using ChatGPT API: ' . $chatbot_chatgpt_assistant_alias);\r\n // Override the $use_assistant_id and set it to 'No'\r\n $use_assistant_id = 'No';\r\n // DIAG - Diagnostics - Ver 1.8.1\r\n // back_trace( 'NOTICE' , 'Falling back to ChatGPT API');\r\n }\r\n }\r\n\r\n // Decide whether to use an Flow, Assistant or original ChatGPT\r\n if ($model == 'flow'){\r\n \r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Using ChatGPT Flow');\r\n\r\n // Reload the model - BELT & SUSPENDERS\r\n $script_data_array['model'] = $model;\r\n\r\n // Get the step from the transient\r\n $kflow_step = get_chatbot_chatgpt_transients( 'kflow_step', null, null, $session_id);\r\n if (empty($kflow_step)) {\r\n $kflow_step = 0; // FIXME - Set to 1 or to zero?\r\n }\r\n\r\n // $thread_id\r\n $thread_id = '[answer=' . $kflow_step + 1 . ']';\r\n \r\n // Add +1 to $script_data_array['next_step']\r\n $kflow_step = $kflow_step + 1;\r\n\r\n // Set the next step\r\n set_chatbot_chatgpt_transients( 'kflow_step', $kflow_step, null, null, $session_id);\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', '$message: ' . $message);\r\n append_message_to_conversation_log($session_id, $user_id, $page_id, 'Visitor', $thread_id, $assistant_id, $message);\r\n\r\n // BELT & SUSPENDERS\r\n $thread_id = '';\r\n\r\n // Send message to ChatGPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_call_flow_api($api_key, $message);\r\n wp_send_json_success($response);\r\n\r\n } elseif ($use_assistant_id == 'Yes') {\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Using GPT Assistant ID: ' . $use_assistant_id);\r\n // back_trace( 'NOTICE', '$user_id ' . $user_id);\r\n // back_trace( 'NOTICE', '$page_id ' . $page_id);\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', '$message ' . $message);\r\n append_message_to_conversation_log($session_id, $user_id, $page_id, 'Visitor', $thread_id, $assistant_id, $message);\r\n \r\n // Send message to Custom GPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_custom_gpt_call_api($api_key, $message, $assistant_id, $thread_id, $user_id, $page_id);\r\n\r\n // Use TF-IDF to enhance response\r\n $chatbot_chatgpt_suppress_learnings = esc_attr(get_option('chatbot_chatgpt_suppress_learnings', 'Random'));\r\n if ( $chatbot_chatgpt_suppress_learnings != 'None') {\r\n $response = $response . chatbot_chatgpt_enhance_with_tfidf($message);\r\n }\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', '$response ' . print_r($response,true));\r\n append_message_to_conversation_log($session_id, $user_id, $page_id, 'Chatbot', $thread_id, $assistant_id, $response);\r\n\r\n // Clean (erase) the output buffer - Ver 1.6.8\r\n ob_clean();\r\n if (str_starts_with($response, 'Error:') || str_starts_with($response, 'Failed:')) {\r\n // Return response\r\n // back_trace( 'NOTICE', '$response ' . print_r($response,true));\r\n wp_send_json_error('Oops! Something went wrong on our end. Please try again later');\r\n } else {\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Check for links and images in response before returning');\r\n $response = chatbot_chatgpt_check_for_links_and_images($response);\r\n // Return response\r\n wp_send_json_success($response);\r\n }\r\n } else {\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Using ChatGPT');\r\n // back_trace( 'NOTICE', '$user_id ' . $user_id);\r\n // back_trace( 'NOTICE', '$page_id ' . $page_id);\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', '$message ' . $message);\r\n append_message_to_conversation_log($session_id, $user_id, $page_id, 'Visitor', $thread_id, $assistant_id, $message);\r\n \r\n // If $model starts with 'gpt' then the chatbot_chatgpt_call_api or 'dall' then chatbot_chatgpt_call_image_api\r\n // TRY NOT TO FETCH MODEL AGAIN\r\n // $model = esc_attr(get_option('chatbot_chatgpt_model_choice', 'gpt-3.5-turbo'));\r\n if (str_starts_with($model, 'gpt')) {\r\n // Reload the model - BELT & SUSPENDERS\r\n $script_data_array['model'] = $model;\r\n // Send message to ChatGPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_call_api($api_key, $message);\r\n } elseif (str_starts_with($model, 'dall')) {\r\n // Reload the model - BELT & SUSPENDERS\r\n $script_data_array['model'] = $model;\r\n // Send message to Image API - Ver 1.9.4\r\n $response = chatbot_chatgpt_call_image_api($api_key, $message);\r\n } elseif (str_starts_with($model, 'tts')) {\r\n // Reload the model - BELT & SUSPENDERS\r\n $script_data_array['model'] = $model;\r\n // Send message to TTS API - Text-to-speech - Ver 1.9.5\r\n $response = chatbot_chatgpt_call_tts_api($api_key, $message);\r\n } elseif (str_starts_with($model,\"whisper\")) {\r\n $script_data_array['model'] = $model;\r\n // Send message to STT API - Speech-to-text - Ver 1.9.6\r\n $response = chatbot_chatgpt_call_stt_api($api_key, $message);\r\n } else {\r\n // Reload the model - BELT & SUSPENDERS\r\n $script_data_array['model'] = $model;\r\n // Send message to ChatGPT API - Ver 1.6.7\r\n $response = chatbot_chatgpt_call_api($api_key, $message);\r\n }\r\n \r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', ['message' => 'BEFORE CALL TO ENHANCE TFIDF', 'response' => $response]);\r\n \r\n // Use TF-IDF to enhance response\r\n $chatbot_chatgpt_suppress_learnings = esc_attr(get_option('chatbot_chatgpt_suppress_learnings', 'Random'));\r\n if ( $chatbot_chatgpt_suppress_learnings != 'None') {\r\n $response = $response . chatbot_chatgpt_enhance_with_tfidf($message);\r\n }\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', ['message' => 'AFTER CALL TO ENHANCE TFIDF', 'response' => $response]);\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', '$response ' . print_r($response,true));\r\n append_message_to_conversation_log($session_id, $user_id, $page_id, 'Chatbot', $thread_id, $assistant_id, $response);\r\n\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Check for links and images in response before returning');\r\n $response = chatbot_chatgpt_check_for_links_and_images($response);\r\n\r\n // Return response\r\n wp_send_json_success($response);\r\n }\r\n\r\n wp_send_json_error('Oops, I fell through the cracks!');\r\n\r\n}\r\n\r\n// Add action to send messages - Ver 1.0.0\r\nadd_action('wp_ajax_chatbot_chatgpt_send_message', 'chatbot_chatgpt_send_message');\r\nadd_action('wp_ajax_nopriv_chatbot_chatgpt_send_message', 'chatbot_chatgpt_send_message');\r\n\r\n// Add action to upload files - Ver 1.7.6\r\nadd_action('wp_ajax_chatbot_chatgpt_upload_file_to_assistant', 'chatbot_chatgpt_upload_file_to_assistant');\r\nadd_action('wp_ajax_nopriv_chatbot_chatgpt_upload_file_to_assistant', 'chatbot_chatgpt_upload_file_to_assistant');\r\n\r\n// Add action to erase conversation - Ver 1.8.6\r\nadd_action('wp_ajax_chatbot_chatgpt_erase_conversation', 'chatbot_chatgpt_erase_conversation_handler');\r\nadd_action('wp_ajax_nopriv_chatbot_chatgpt_erase_conversation', 'chatbot_chatgpt_erase_conversation_handler'); // For logged-out users, if needed\r\n\r\n// Settings and Deactivation - Ver 1.5.0\r\nadd_filter('plugin_action_links_' . plugin_basename(__FILE__), 'chatbot_chatgpt_plugin_action_links');\r\n\r\n// Crawler aka Knowledge Navigator - Ver 1.6.1\r\nfunction chatbot_chatgpt_kn_status_activation(): void {\r\n add_option('chatbot_chatgpt_kn_status', 'Never Run');\r\n // clear any old scheduled runs\r\n if (wp_next_scheduled('crawl_scheduled_event_hook')) {\r\n wp_clear_scheduled_hook('crawl_scheduled_event_hook');\r\n }\r\n // clear the 'knowledge_navigator_scan_hook' hook on plugin activation - Ver 1.6.3\r\n if (wp_next_scheduled('knowledge_navigator_scan_hook')) {\r\n // BREAK/FIX - Do not unset the hook - Ver 1.8.5\r\n // wp_clear_scheduled_hook('knowledge_navigator_scan_hook'); // Clear scheduled runs\r\n }\r\n}\r\nregister_activation_hook(__FILE__, 'chatbot_chatgpt_kn_status_activation');\r\n\r\n// Clean Up in Aisle 4\r\nfunction chatbot_chatgpt_kn_status_deactivation(): void {\r\n delete_option('chatbot_chatgpt_kn_status');\r\n wp_clear_scheduled_hook('knowledge_navigator_scan_hook'); \r\n}\r\nregister_deactivation_hook(__FILE__, 'chatbot_chatgpt_kn_status_deactivation');\r\n\r\n// Function to add a new message and response, keeping only the last five - Ver 1.6.1\r\nfunction addEntry($transient_name, $newEntry): void {\r\n\r\n $context_history = get_transient($transient_name);\r\n if (!$context_history) {\r\n $context_history = [];\r\n }\r\n\r\n // Determine the total length of all existing entries\r\n $totalLength = 0;\r\n foreach ($context_history as $entry) {\r\n if (is_string($entry)) {\r\n $totalLength += strlen($entry);\r\n } elseif (is_array($entry)) {\r\n $totalLength += strlen(json_encode($entry)); // Convert to string if an array\r\n }\r\n }\r\n\r\n // IDEA - How will the new threading option from OpenAI change how this works?\r\n // Define thresholds for the number of entries to keep\r\n $maxEntries = 30; // Default maximum number of entries\r\n if ($totalLength > 5000) { // Higher threshold\r\n $maxEntries = 20;\r\n }\r\n if ($totalLength > 10000) { // Lower threshold\r\n $maxEntries = 10;\r\n }\r\n\r\n while (count($context_history) >= $maxEntries) {\r\n array_shift($context_history); // Remove the oldest element\r\n }\r\n\r\n if (is_array($newEntry)) {\r\n $newEntry = json_encode($newEntry); // Convert the array to a string\r\n }\r\n\r\n array_push($context_history, $newEntry); // Append the new element\r\n set_transient($transient_name, $context_history); // Update the transient\r\n}\r\n\r\n\r\n// Function to return message and response - Ver 1.6.1\r\nfunction concatenateHistory($transient_name): string {\r\n $context_history = get_transient($transient_name);\r\n if (!$context_history) {\r\n return ''; // Return an empty string if the transient does not exist\r\n }\r\n return implode(' ', $context_history); // Concatenate the array values into a single string\r\n}\r\n\r\n// Initialize the Greetings - Ver 1.6.1\r\nfunction enqueue_greetings_script(): void {\r\n\r\n // DIAG - Diagnostics - Ver 1.6.1\r\n // back_trace( 'NOTICE', \"enqueue_greetings_script() called\");\r\n\r\n wp_enqueue_script('greetings', plugin_dir_url(__FILE__) . 'assets/js/greetings.js', array('jquery'), null, true);\r\n\r\n // If user is logged in, then modify greeting if greeting contains \"[...]\" or remove if not logged in - Ver 1.9.4\r\n if (is_user_logged_in()) {\r\n\r\n $current_user_id = get_current_user_id();\r\n $current_user = get_userdata($current_user_id);\r\n\r\n //Do this for Initial Greeting\r\n $initial_greeting = esc_attr(get_option('chatbot_chatgpt_initial_greeting', 'Hello! How can I help you today?'));\r\n\r\n // Determine what the field name is between the brackets\r\n $user_field_name = '';\r\n $user_field_name = substr($initial_greeting, strpos($initial_greeting, '[') + 1, strpos($initial_greeting, ']') - strpos($initial_greeting, '[') - 1);\r\n\r\n // If $initial_greeting contains \"[$user_field_name]\" then replace with field from DB\r\n if (strpos($initial_greeting, '[' . $user_field_name . ']') !== false) {\r\n $initial_greeting = str_replace('[' . $user_field_name . ']', $current_user->$user_field_name, $initial_greeting);\r\n } else {\r\n $initial_greeting = str_replace('[' . $user_field_name . ']', '', $initial_greeting);\r\n }\r\n\r\n // Do this for Subsequent Greeting\r\n $subsequent_greeting = esc_attr(get_option('chatbot_chatgpt_subsequent_greeting', 'Hello again! How can I help you?'));\r\n\r\n // Determine what the field name is between the brackets\r\n $user_field_name = '';\r\n $user_field_name = substr($subsequent_greeting, strpos($subsequent_greeting, '[') + 1, strpos($subsequent_greeting, ']') - strpos($subsequent_greeting, '[') - 1);\r\n\r\n // If $subsequent_greeting contains \"[$user_field_name]\" then replace with field from DB\r\n if (strpos($subsequent_greeting, '[' . $user_field_name . ']') !== false) {\r\n $subsequent_greeting = str_replace('[' . $user_field_name . ']', $current_user->$user_field_name, $subsequent_greeting);\r\n } else {\r\n $subsequent_greeting = str_replace('[' . $user_field_name . ']', '', $subsequent_greeting);\r\n }\r\n\r\n } else {\r\n\r\n $initial_greeting = esc_attr(get_option('chatbot_chatgpt_initial_greeting', 'Hello! How can I help you today?'));\r\n\r\n $user_field_name = '';\r\n $user_field_name = substr($initial_greeting, strpos($initial_greeting, '[') + 1, strpos($initial_greeting, ']') - strpos($initial_greeting, '[') - 1 );\r\n\r\n // $initial_greeting = str_replace('[' . $user_field_name . ']', '', $initial_greeting);\r\n $initial_greeting = preg_replace('/\\s*\\[' . preg_quote($user_field_name, '/') . '\\]\\s*/', '', $initial_greeting);\r\n\r\n $subsequent_greeting = esc_attr(get_option('chatbot_chatgpt_subsequent_greeting', 'Hello again! How can I help you?'));\r\n\r\n $user_field_name = '';\r\n $user_field_name = substr($subsequent_greeting, strpos($subsequent_greeting, '[') + 1, strpos($subsequent_greeting, ']') - strpos($subsequent_greeting, '[') - 1);\r\n\r\n // $subsequent_greeting = str_replace('[' . $user_field_name . ']', '', $subsequent_greeting);\r\n $subsequent_greeting = preg_replace('/\\s*\\[' . preg_quote($user_field_name, '/') . '\\]\\s*/', '', $subsequent_greeting);\r\n }\r\n\r\n $greetings = array(\r\n 'initial_greeting' => $initial_greeting,\r\n 'subsequent_greeting' => $subsequent_greeting,\r\n );\r\n\r\n wp_localize_script('greetings', 'greetings_data', $greetings);\r\n\r\n}\r\nadd_action('wp_enqueue_scripts', 'enqueue_greetings_script');\r\n\r\n\r\n// Function to add the adaptive appearance settings to the Chatbot settings page\r\nfunction chatbot_chatgpt_settings_appearance(): void {\r\n\r\n // Register the settings\r\n register_setting('chatbot_chatgpt_settings_appearance', 'chatbot_chatgpt_appearance');\r\n\r\n // Add the adaptive appearance settings section\r\n add_settings_section(\r\n 'chatbot_chatgpt_settings_appearance_section',\r\n 'Adaptive Appearance Settings',\r\n 'chatbot_chatgpt_settings_appearance_section_callback',\r\n 'chatbot_chatgpt_settings_appearance'\r\n );\r\n\r\n // Add the adaptive appearance settings fields\r\n add_settings_field(\r\n 'chatbot_chatgpt_settings_appearance_field',\r\n 'Adaptive Appearance Settings',\r\n 'chatbot_chatgpt_settings_appearance_field_callback',\r\n 'chatbot_chatgpt_settings_appearance',\r\n 'chatbot_chatgpt_settings_appearance_section'\r\n );\r\n\r\n}\r\n\r\n// Add the color picker to the adaptive appearance settings section - Ver 1.8.1\r\nfunction enqueue_color_picker($hook_suffix): void {\r\n // first check that $hook_suffix is appropriate for your admin page\r\n wp_enqueue_style('wp-color-picker');\r\n wp_enqueue_script('my-script-handle', plugin_dir_url(__FILE__) . 'assets/js/chatbot-chatgpt-color-picker.js', array('wp-color-picker'), false, true);\r\n}\r\nadd_action('admin_enqueue_scripts', 'enqueue_color_picker');\r\n\r\n// Determine if the plugin is installed\r\nfunction kchat_get_plugin_version() {\r\n\r\n if (!function_exists('get_plugin_data')) {\r\n require_once(ABSPATH . 'wp-admin/includes/plugin.php');\r\n }\r\n\r\n $plugin_data = get_plugin_data(plugin_dir_path(__FILE__) . 'chatbot-chatgpt.php');\r\n $plugin_version = $plugin_data['Version'];\r\n update_option('chatbot_chatgpt_plugin_version', $plugin_version);\r\n // DIAG - Log the plugin version\r\n // back_trace( 'NOTICE', 'Plugin version '. $plugin_version);\r\n\r\n return $plugin_version;\r\n\r\n}\r\n"}}, "wp-content/plugins/chatbot-chatgpt/includes/utilities/chatbot-api-endpoints.php": {"de6c3bda23246fe11f7d20255df14f55b5865b77": {"t": 1785746147.9500942, "n": 6173, "h": "0af78d19bbdc4339", "c": "