Files
OpenCode 68a9071cf1 feat: reconcile local master with origin (exa/hot-platform hunters, leaks ledger, latest results)
Local branch had diverged from origin/master (sibling commits on the same base). Rewrote local history linearly on top of origin/master, folding in all local content: exa/hot-platform discovery hunters, leaks ledger, nightly sweep orchestrator, updated .gitignore and skill docs, plus the latest hunt output and vault state. Remote-only files (vault keys, channel scripts) were restored rather than dropped, so the resulting tree is a full union of both sides.
2026-08-07 12:53:47 +08:00

1 line
1.5 MiB
Plaintext

{"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": "<?php\n/**\n * Kognetiks Chatbot - Settings - API/DeepSeek Page\n *\n * This file contains the code for the DeepSeek settings page.\n * It allows users to configure the API key and other parameters\n * required to access the ChatGPT API from their own account.\n *\n * @package chatbot-chatgpt\n */\n\n// If this file is called directly, abort.\nif ( ! defined( 'WPINC' ) ) {\n die();\n}\n\n// API/DeepSeek settings section callback - Ver 2.1.8\nfunction chatbot_deepseek_model_settings_section_callback($args) {\n ?>\n <p>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.</p>\n <p>More information about DeepSeek models and their capability can be found at <a href=\"https://api-docs.deepseek.com/quick_start/pricing\" target=\"_blank\">https://api-docs.deepseek.com/quick_start/pricing</a>.</p>\n <p><b><i>Don't forget to click </i><code>Save Settings</code><i> to save any changes your might make.</i></b></p>\n <p style=\"background-color: #e0f7fa; padding: 10px;\"><b>For an explanation of the API/DeepSeek settings and additional documentation please click <a href=\"?page=chatbot-chatgpt&tab=support&dir=api-deepseek-settings&file=api-deepseek-model-settings.md\">here</a>.</b></p>\n <?php\n}\n\nfunction chatbot_deepseek_api_model_general_section_callback($args) {\n ?>\n <p>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 <a href=\"https://platform.deepseek.com/sign_in\" target=\"_blank\">https://platform.deepseek.com/sign_in</a>.</p>\n <?php\n}\n\n// API key field callback\nfunction chatbot_deepseek_api_key_callback($args) {\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 <input type=\"password\" id=\"chatbot_deepseek_api_key\" name=\"chatbot_deepseek_api_key\" value=\"<?php echo esc_attr( $api_key ); ?>\" class=\"regular-text\" autocomplete=\"off\">\n <?php\n}\n\nfunction chatbot_deepseek_api_model_chat_settings_section_callback($args) {\n ?>\n <p>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 <a href=\"https://api-docs.deepseek.com/quick_start/pricing\" target=\"_blank\">https://api-docs.deepseek.com/quick_start/pricing</a>. Enter a conversation context to help the model understand the conversation. See the default for ideas. Some example shortcodes include:</p>\n <p><b>NOTE:</b> Enter your API key (above), click <code>Save Settings</code> at the bottom of this page, in order to retrieve the full list of available models.</p>\n <ul style=\"list-style-type: disc; list-style-position: inside; padding-left: 1em;\">\n <li><code>&#91;chatbot&#93;</code> - Default chat model, style is floating</li>\n <li><code>&#91;chatbot style=\"floating\" model=\"deepseek-chat\"&#93;</code> - Style is floating, specific model</li>\n <li><code>&#91;chatbot style=\"embedded\" model=\"deepseek-chat\"&#93;</code> - Style is embedded, default chat model</li>\n </ul>\n <?php\n}\n\n// DeepSeek Model Settings Callback - Ver 2.1.8\nfunction chatbot_deepseek_chat_model_choice_callback($args) {\n\n $model_choice = esc_attr(get_option('chatbot_deepseek_model_choice', 'deepseek-chat'));\n $deepseek_api_enabled = esc_attr(get_option('chatbot_deepseek_api_enabled', 'Yes'));\n\n // Fetch models from the API\n $models = chatbot_deepseek_get_models();\n\n // Remove the models not owned by DeepSeek\n $models = array_filter($models, function($model) {\n return $model['owned_by'] === 'deepseek';\n });\n\n // Check for errors\n if (is_string($models) && strpos($models, 'Error:') === 0) {\n // If there's an error, display the hardcoded list\n $model_choice = esc_attr(get_option('chatbot_deepseek_model_choice', 'deepseek-chat'));\n ?>\n <select id=\"chatbot_chatgpt_model_choice\" name=\"chatbot_chatgpt_model_choice\">\n <option value=\"<?php echo esc_attr( 'deepseek-chat' ); ?>\" <?php selected( $model_choice, 'deepseek-chat' ); ?>><?php echo esc_html( 'deepseek-chat' ); ?></option>\n </select>\n <?php\n } else {\n // If models are fetched successfully, display them dynamically\n ?>\n <select id=\"chatbot_deepseek_model_choice\" name=\"chatbot_deepseek_model_choice\">\n <?php foreach ($models as $model): ?>\n <option value=\"<?php echo esc_attr($model['id']); ?>\" <?php selected(esc_attr(get_option('chatbot_deepseek_model_choice')), $model['id']); ?>><?php echo esc_html($model['id']); ?></option>\n <?php endforeach; ?>\n ?>\n </select>\n <?php\n }\n\n}\n\n// Max Tokens choice - Ver 2.1.8\nfunction chatbot_deepseek_max_tokens_setting_callback($args) {\n\n // Get the saved chatbot_deepseek_max_tokens_setting or default to 1000\n $max_tokens = esc_attr(get_option('chatbot_deepseek_max_tokens_setting', '1000'));\n // Allow for a range of tokens between 100 and 10000 in 100-step increments - Ver 2.0.4\n ?>\n <select id=\"chatbot_deepseek_max_tokens_setting\" name=\"chatbot_deepseek_max_tokens_setting\">\n <?php\n for ($i=100; $i<=10000; $i+=100) {\n echo '<option value=\"' . esc_attr($i) . '\" ' . selected($max_tokens, (string)$i, false) . '>' . esc_html($i) . '</option>';\n }\n ?>\n </select>\n <?php\n\n}\n\n// Conversation Context\nfunction chatbot_deepseek_conversation_context_callback($args) {\n\n // Get the value of the setting we've registered with register_setting()\n $chatbot_deepseek_conversation_context = esc_attr(get_option('chatbot_deepseek_conversation_context'));\n\n // Check if the option has been set, if not, use a default value\n if (empty($chatbot_deepseek_conversation_context)) {\n $chatbot_deepseek_conversation_context = \"You are a versatile, friendly, and helpful assistant designed to support me in a variety of tasks that responds in Markdown.\";\n // Save the default value into the option\n update_option('chatbot_deepseek_conversation_context', $chatbot_deepseek_conversation_context);\n }\n\n ?>\n <!-- Define the textarea field. -->\n <textarea id='chatbot_deepseek_conversation_context' name='chatbot_deepseek_conversation_context' rows='5' cols='50' maxlength='12500'><?php echo esc_html(stripslashes($chatbot_deepseek_conversation_context)); ?></textarea>\n <?php\n\n}\n\n// Set chatbot_deepseek_temperature\nfunction chatbot_deepseek_temperature_callback($args) {\n \n $temperature = esc_attr(get_option('chatbot_deepseek_temperature', 0.5));\n ?>\n <select id=\"chatbot_deepseek_temperature\" name=\"chatbot_deepseek_temperature\">\n <?php\n for ($i = 0.01; $i <= 2.01; $i += 0.01) {\n echo '<option value=\"' . esc_attr( $i ) . '\" ' . selected($temperature, (string)$i) . '>' . esc_html( $i ) . '</option>';\n }\n ?>\n </select>\n <?php\n\n}\n\n// Set chatbot_deepseek_top_p\nfunction chatbot_deepseek_top_p_callback($args) {\n\n $top_p = esc_attr(get_option('chatbot_deepseek_top_p', 1.00));\n ?>\n <select id=\"chatbot_deepseek_top_p\" name=\"chatbot_deepseek_top_p\">\n <?php\n for ($i = 0.01; $i <= 1.01; $i += 0.01) {\n echo '<option value=\"' . esc_attr( $i ) . '\" ' . selected($top_p, (string)$i) . '>' . esc_html( $i ) . '</option>';\n }\n ?>\n </select>\n <?php\n\n}\n\n// API Advanced settings section callback\nfunction chatbot_deepseek_api_model_advanced_section_callback($args) {\n\n ?>\n <p><strong>CAUTION</strong>: Configure the advanced settings for the plugin. Enter the base URL for the DeepSeek API. The default is <code>https://api.deepseek.com</code>.</p>\n <?php\n\n}\n\n// Base URL for the DeepSeek API\nfunction chatbot_deepseek_base_url_callback($args) {\n\n $chatbot_deepseek_base_url = esc_attr(get_option('chatbot_deepseek_base_url', 'https://api.deepseek.com'));\n ?>\n <input type=\"text\" id=\"chatbot_deepseek_base_url\" name=\"chatbot_deepseek_base_url\" value=\"<?php echo esc_attr( $chatbot_deepseek_base_url ); ?>\" class=\"regular-text\">\n <?php\n\n}\n\n// Timeout Settings Callback\nfunction chatbot_deepseek_timeout_setting_callback($args) {\n\n // Get the saved chatbot_deepseek_timeout value or default to 240\n $timeout = esc_attr(get_option('chatbot_deepseek_timeout_setting', 240));\n\n // Allow for a range of tokens between 5 and 500 in 5-step increments - Ver 1.8.8\n ?>\n <select id=\"chatbot_deepseek_timeout_setting\" name=\"chatbot_deepseek_timeout_setting\">\n <?php\n for ($i=5; $i<=500; $i+=5) {\n echo '<option value=\"' . esc_attr($i) . '\" ' . selected($timeout, (string)$i, false) . '>' . esc_html($i) . '</option>';\n }\n ?>\n </select>\n <?php\n\n}\n\n// Register API settings\nfunction chatbot_deepseek_api_settings_init() {\n\n add_settings_section(\n 'chatbot_deepseek_settings_section',\n 'API/DeepSeek Settings',\n 'chatbot_deepseek_model_settings_section_callback',\n 'chatbot_deepseek_model_settings_general'\n );\n\n // API/DeepSeek settings tab - Ver 2.1.8\n register_setting('chatbot_deepseek_api_model', 'chatbot_deepseek_api_enabled');\n register_setting('chatbot_deepseek_api_model', 'chatbot_deepseek_api_key', 'chatbot_chatgpt_sanitize_api_key');\n register_setting('chatbot_deepseek_api_model', 'chatbot_deepseek_max_tokens_setting'); // Max Tokens setting options\n register_setting('chatbot_deepseek_api_model', 'chatbot_deepseek_conversation_context'); // Conversation Context\n register_setting('chatbot_deepseek_api_model', 'chatbot_deepseek_temperature'); // Temperature\n register_setting('chatbot_deepseek_api_model', 'chatbot_deepseek_top_p'); // Top P\n\n add_settings_section(\n 'chatbot_deepseek_api_model_general_section',\n 'DeepSeek API Settings',\n 'chatbot_deepseek_api_model_general_section_callback',\n 'chatbot_deepseek_api_model_general'\n );\n\n add_settings_field(\n 'chatbot_deepseek_api_key',\n 'DeepSeek API Key',\n 'chatbot_deepseek_api_key_callback',\n 'chatbot_deepseek_api_model_general',\n 'chatbot_deepseek_api_model_general_section'\n );\n\n register_setting(\n 'chatbot_deepseek_api_model',\n 'chatbot_deepseek_model_choice',\n array(\n 'type' => '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": "<?php\n/**\n * Kognetiks Chatbot - Settings - API/DeepSeek Page\n *\n * This file contains the code for the DeepSeek settings page.\n * It allows users to configure the API key and other parameters\n * required to access the ChatGPT API from their own account.\n *\n * @package chatbot-chatgpt\n */\n\n// If this file is called directly, abort.\nif ( ! defined( 'WPINC' ) ) {\n die();\n}\n\n// API/DeepSeek settings section callback - Ver 2.1.8\nfunction chatbot_deepseek_model_settings_section_callback($args) {\n ?>\n <p>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.</p>\n <p>More information about DeepSeek models and their capability can be found at <a href=\"https://api-docs.deepseek.com/quick_start/pricing\" target=\"_blank\">https://api-docs.deepseek.com/quick_start/pricing</a>.</p>\n <p><b><i>Don't forget to click </i><code>Save Settings</code><i> to save any changes your might make.</i></b></p>\n <p style=\"background-color: #e0f7fa; padding: 10px;\"><b>For an explanation of the API/DeepSeek settings and additional documentation please click <a href=\"?page=chatbot-chatgpt&tab=support&dir=api-deepseek-settings&file=api-deepseek-model-settings.md\">here</a>.</b></p>\n <?php\n}\n\nfunction chatbot_deepseek_api_model_general_section_callback($args) {\n ?>\n <p>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 <a href=\"https://platform.deepseek.com/sign_in\" target=\"_blank\">https://platform.deepseek.com/sign_in</a>.</p>\n <?php\n}\n\n// API key field callback\nfunction chatbot_deepseek_api_key_callback($args) {\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 <input type=\"password\" id=\"chatbot_deepseek_api_key\" name=\"chatbot_deepseek_api_key\" value=\"<?php echo esc_attr( $api_key ); ?>\" class=\"regular-text\" autocomplete=\"off\">\n <?php\n}\n\nfunction chatbot_deepseek_api_model_chat_settings_section_callback($args) {\n ?>\n <p>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 <a href=\"https://api-docs.deepseek.com/quick_start/pricing\" target=\"_blank\">https://api-docs.deepseek.com/quick_start/pricing</a>. Enter a conversation context to help the model understand the conversation. See the default for ideas. Some example shortcodes include:</p>\n <p><b>NOTE:</b> Enter your API key (above), click <code>Save Settings</code> at the bottom of this page, in order to retrieve the full list of available models.</p>\n <ul style=\"list-style-type: disc; list-style-position: inside; padding-left: 1em;\">\n <li><code>&#91;chatbot&#93;</code> - Default chat model, style is floating</li>\n <li><code>&#91;chatbot style=\"floating\" model=\"deepseek-chat\"&#93;</code> - Style is floating, specific model</li>\n <li><code>&#91;chatbot style=\"embedded\" model=\"deepseek-chat\"&#93;</code> - Style is embedded, default chat model</li>\n </ul>\n <?php\n}\n\n// DeepSeek Model Settings Callback - Ver 2.1.8\nfunction chatbot_deepseek_chat_model_choice_callback($args) {\n\n $model_choice = esc_attr(get_option('chatbot_deepseek_model_choice', 'deepseek-chat'));\n $deepseek_api_enabled = esc_attr(get_option('chatbot_deepseek_api_enabled', 'Yes'));\n\n // Fetch models from the API\n $models = chatbot_deepseek_get_models();\n\n // Remove the models not owned by DeepSeek\n $models = array_filter($models, function($model) {\n return $model['owned_by'] === 'deepseek';\n });\n\n // Check for errors\n if (is_string($models) && strpos($models, 'Error:') === 0) {\n // If there's an error, display the hardcoded list\n $model_choice = esc_attr(get_option('chatbot_deepseek_model_choice', 'deepseek-chat'));\n ?>\n <select id=\"chatbot_chatgpt_model_choice\" name=\"chatbot_chatgpt_model_choice\">\n <option value=\"<?php echo esc_attr( 'deepseek-chat' ); ?>\" <?php selected( $model_choice, 'deepseek-chat' ); ?>><?php echo esc_html( 'deepseek-chat' ); ?></option>\n </select>\n <?php\n } else {\n // If models are fetched successfully, display them dynamically\n ?>\n <select id=\"chatbot_deepseek_model_choice\" name=\"chatbot_deepseek_model_choice\">\n <?php foreach ($models as $model): ?>\n <option value=\"<?php echo esc_attr($model['id']); ?>\" <?php selected(esc_attr(get_option('chatbot_deepseek_model_choice')), $model['id']); ?>><?php echo esc_html($model['id']); ?></option>\n <?php endforeach; ?>\n ?>\n </select>\n <?php\n }\n\n}\n\n// Max Tokens choice - Ver 2.1.8\nfunction chatbot_deepseek_max_tokens_setting_callback($args) {\n\n // Get the saved chatbot_deepseek_max_tokens_setting or default to 1000\n $max_tokens = esc_attr(get_option('chatbot_deepseek_max_tokens_setting', '1000'));\n // Allow for a range of tokens between 100 and 10000 in 100-step increments - Ver 2.0.4\n ?>\n <select id=\"chatbot_deepseek_max_tokens_setting\" name=\"chatbot_deepseek_max_tokens_setting\">\n <?php\n for ($i=100; $i<=10000; $i+=100) {\n echo '<option value=\"' . esc_attr($i) . '\" ' . selected($max_tokens, (string)$i, false) . '>' . esc_html($i) . '</option>';\n }\n ?>\n </select>\n <?php\n\n}\n\n// Conversation Context\nfunction chatbot_deepseek_conversation_context_callback($args) {\n\n // Get the value of the setting we've registered with register_setting()\n $chatbot_deepseek_conversation_context = esc_attr(get_option('chatbot_deepseek_conversation_context'));\n\n // Check if the option has been set, if not, use a default value\n if (empty($chatbot_deepseek_conversation_context)) {\n $chatbot_deepseek_conversation_context = \"You are a versatile, friendly, and helpful assistant designed to support me in a variety of tasks that responds in Markdown.\";\n // Save the default value into the option\n update_option('chatbot_deepseek_conversation_context', $chatbot_deepseek_conversation_context);\n }\n\n ?>\n <!-- Define the textarea field. -->\n <textarea id='chatbot_deepseek_conversation_context' name='chatbot_deepseek_conversation_context' rows='5' cols='50' maxlength='12500'><?php echo esc_html(stripslashes($chatbot_deepseek_conversation_context)); ?></textarea>\n <?php\n\n}\n\n// Set chatbot_deepseek_temperature\nfunction chatbot_deepseek_temperature_callback($args) {\n \n $temperature = esc_attr(get_option('chatbot_deepseek_temperature', 0.5));\n ?>\n <select id=\"chatbot_deepseek_temperature\" name=\"chatbot_deepseek_temperature\">\n <?php\n for ($i = 0.01; $i <= 2.01; $i += 0.01) {\n echo '<option value=\"' . esc_attr( $i ) . '\" ' . selected($temperature, (string)$i) . '>' . esc_html( $i ) . '</option>';\n }\n ?>\n </select>\n <?php\n\n}\n\n// Set chatbot_deepseek_top_p\nfunction chatbot_deepseek_top_p_callback($args) {\n\n $top_p = esc_attr(get_option('chatbot_deepseek_top_p', 1.00));\n ?>\n <select id=\"chatbot_deepseek_top_p\" name=\"chatbot_deepseek_top_p\">\n <?php\n for ($i = 0.01; $i <= 1.01; $i += 0.01) {\n echo '<option value=\"' . esc_attr( $i ) . '\" ' . selected($top_p, (string)$i) . '>' . esc_html( $i ) . '</option>';\n }\n ?>\n </select>\n <?php\n\n}\n\n// API Advanced settings section callback\nfunction chatbot_deepseek_api_model_advanced_section_callback($args) {\n\n ?>\n <p><strong>CAUTION</strong>: Configure the advanced settings for the plugin. Enter the base URL for the DeepSeek API. The default is <code>https://api.deepseek.com</code>.</p>\n <?php\n\n}\n\n// Base URL for the DeepSeek API\nfunction chatbot_deepseek_base_url_callback($args) {\n\n $chatbot_deepseek_base_url = esc_attr(get_option('chatbot_deepseek_base_url', 'https://api.deepseek.com'));\n ?>\n <input type=\"text\" id=\"chatbot_deepseek_base_url\" name=\"chatbot_deepseek_base_url\" value=\"<?php echo esc_attr( $chatbot_deepseek_base_url ); ?>\" class=\"regular-text\">\n <?php\n\n}\n\n// Timeout Settings Callback\nfunction chatbot_deepseek_timeout_setting_callback($args) {\n\n // Get the saved chatbot_deepseek_timeout value or default to 240\n $timeout = esc_attr(get_option('chatbot_deepseek_timeout_setting', 240));\n\n // Allow for a range of tokens between 5 and 500 in 5-step increments - Ver 1.8.8\n ?>\n <select id=\"chatbot_deepseek_timeout_setting\" name=\"chatbot_deepseek_timeout_setting\">\n <?php\n for ($i=5; $i<=500; $i+=5) {\n echo '<option value=\"' . esc_attr($i) . '\" ' . selected($timeout, (string)$i, false) . '>' . esc_html($i) . '</option>';\n }\n ?>\n </select>\n <?php\n\n}\n\n// Register API settings\nfunction chatbot_deepseek_api_settings_init() {\n\n add_settings_section(\n 'chatbot_deepseek_settings_section',\n 'API/DeepSeek Settings',\n 'chatbot_deepseek_model_settings_section_callback',\n 'chatbot_deepseek_model_settings_general'\n );\n\n // API/DeepSeek settings tab - Ver 2.1.8\n register_setting('chatbot_deepseek_api_model', 'chatbot_deepseek_api_enabled');\n register_setting('chatbot_deepseek_api_model', 'chatbot_deepseek_api_key', 'chatbot_chatgpt_sanitize_api_key');\n register_setting('chatbot_deepseek_api_model', 'chatbot_deepseek_max_tokens_setting'); // Max Tokens setting options\n register_setting('chatbot_deepseek_api_model', 'chatbot_deepseek_conversation_context'); // Conversation Context\n register_setting('chatbot_deepseek_api_model', 'chatbot_deepseek_temperature'); // Temperature\n register_setting('chatbot_deepseek_api_model', 'chatbot_deepseek_top_p'); // Top P\n\n add_settings_section(\n 'chatbot_deepseek_api_model_general_section',\n 'DeepSeek API Settings',\n 'chatbot_deepseek_api_model_general_section_callback',\n 'chatbot_deepseek_api_model_general'\n );\n\n add_settings_field(\n 'chatbot_deepseek_api_key',\n 'DeepSeek API Key',\n 'chatbot_deepseek_api_key_callback',\n 'chatbot_deepseek_api_model_general',\n 'chatbot_deepseek_api_model_general_section'\n );\n\n register_setting(\n 'chatbot_deepseek_api_model',\n 'chatbot_deepseek_model_choice',\n array(\n 'type' => '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"}, "2dd08585d8f97d7e6063f081a2c8af9f1d2a898b": {"t": 1786067462.4704058, "n": 13736, "h": "577bf92e0a4ab916", "c": "<?php\n/**\n * Kognetiks Chatbot - Settings - API/DeepSeek Page\n *\n * This file contains the code for the DeepSeek settings page.\n * It allows users to configure the API key and other parameters\n * required to access the ChatGPT API from their own account.\n *\n * @package chatbot-chatgpt\n */\n\n// If this file is called directly, abort.\nif ( ! defined( 'WPINC' ) ) {\n die();\n}\n\n// API/DeepSeek settings section callback - Ver 2.1.8\nfunction chatbot_deepseek_model_settings_section_callback($args) {\n ?>\n <p>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.</p>\n <p>More information about DeepSeek models and their capability can be found at <a href=\"https://api-docs.deepseek.com/quick_start/pricing\" target=\"_blank\">https://api-docs.deepseek.com/quick_start/pricing</a>.</p>\n <p><b><i>Don't forget to click </i><code>Save Settings</code><i> to save any changes your might make.</i></b></p>\n <p style=\"background-color: #e0f7fa; padding: 10px;\"><b>For an explanation of the API/DeepSeek settings and additional documentation please click <a href=\"?page=chatbot-chatgpt&tab=support&dir=api-deepseek-settings&file=api-deepseek-model-settings.md\">here</a>.</b></p>\n <?php\n}\n\nfunction chatbot_deepseek_api_model_general_section_callback($args) {\n ?>\n <p>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 <a href=\"https://platform.deepseek.com/sign_in\" target=\"_blank\">https://platform.deepseek.com/sign_in</a>.</p>\n <?php\n}\n\n// API key field callback\nfunction chatbot_deepseek_api_key_callback($args) {\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 <input type=\"password\" id=\"chatbot_deepseek_api_key\" name=\"chatbot_deepseek_api_key\" value=\"<?php echo esc_attr( $api_key ); ?>\" class=\"regular-text\" autocomplete=\"off\">\n <?php\n}\n\nfunction chatbot_deepseek_api_model_chat_settings_section_callback($args) {\n ?>\n <p>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 <a href=\"https://api-docs.deepseek.com/quick_start/pricing\" target=\"_blank\">https://api-docs.deepseek.com/quick_start/pricing</a>. Enter a conversation context to help the model understand the conversation. See the default for ideas. Some example shortcodes include:</p>\n <p><b>NOTE:</b> Enter your API key (above), click <code>Save Settings</code> at the bottom of this page, in order to retrieve the full list of available models.</p>\n <ul style=\"list-style-type: disc; list-style-position: inside; padding-left: 1em;\">\n <li><code>&#91;chatbot&#93;</code> - Default chat model, style is floating</li>\n <li><code>&#91;chatbot style=\"floating\" model=\"deepseek-chat\"&#93;</code> - Style is floating, specific model</li>\n <li><code>&#91;chatbot style=\"embedded\" model=\"deepseek-chat\"&#93;</code> - Style is embedded, default chat model</li>\n </ul>\n <?php\n}\n\n// DeepSeek Model Settings Callback - Ver 2.1.8\nfunction chatbot_deepseek_chat_model_choice_callback($args) {\n\n $model_choice = esc_attr(get_option('chatbot_deepseek_model_choice', 'deepseek-chat'));\n $deepseek_api_enabled = esc_attr(get_option('chatbot_deepseek_api_enabled', 'Yes'));\n\n // Fetch models from the API\n $models = chatbot_deepseek_get_models();\n\n // Remove the models not owned by DeepSeek\n $models = array_filter($models, function($model) {\n return $model['owned_by'] === 'deepseek';\n });\n\n // Check for errors\n if (is_string($models) && strpos($models, 'Error:') === 0) {\n // If there's an error, display the hardcoded list\n $model_choice = esc_attr(get_option('chatbot_deepseek_model_choice', 'deepseek-chat'));\n ?>\n <select id=\"chatbot_chatgpt_model_choice\" name=\"chatbot_chatgpt_model_choice\">\n <option value=\"<?php echo esc_attr( 'deepseek-chat' ); ?>\" <?php selected( $model_choice, 'deepseek-chat' ); ?>><?php echo esc_html( 'deepseek-chat' ); ?></option>\n </select>\n <?php\n } else {\n // If models are fetched successfully, display them dynamically\n ?>\n <select id=\"chatbot_deepseek_model_choice\" name=\"chatbot_deepseek_model_choice\">\n <?php foreach ($models as $model): ?>\n <option value=\"<?php echo esc_attr($model['id']); ?>\" <?php selected(esc_attr(get_option('chatbot_deepseek_model_choice')), $model['id']); ?>><?php echo esc_html($model['id']); ?></option>\n <?php endforeach; ?>\n ?>\n </select>\n <?php\n }\n\n}\n\n// Max Tokens choice - Ver 2.1.8\nfunction chatbot_deepseek_max_tokens_setting_callback($args) {\n\n // Get the saved chatbot_deepseek_max_tokens_setting or default to 1000\n $max_tokens = esc_attr(get_option('chatbot_deepseek_max_tokens_setting', '1000'));\n // Allow for a range of tokens between 100 and 10000 in 100-step increments - Ver 2.0.4\n ?>\n <select id=\"chatbot_deepseek_max_tokens_setting\" name=\"chatbot_deepseek_max_tokens_setting\">\n <?php\n for ($i=100; $i<=10000; $i+=100) {\n echo '<option value=\"' . esc_attr($i) . '\" ' . selected($max_tokens, (string)$i, false) . '>' . esc_html($i) . '</option>';\n }\n ?>\n </select>\n <?php\n\n}\n\n// Conversation Context\nfunction chatbot_deepseek_conversation_context_callback($args) {\n\n // Get the value of the setting we've registered with register_setting()\n $chatbot_deepseek_conversation_context = esc_attr(get_option('chatbot_deepseek_conversation_context'));\n\n // Check if the option has been set, if not, use a default value\n if (empty($chatbot_deepseek_conversation_context)) {\n $chatbot_deepseek_conversation_context = \"You are a versatile, friendly, and helpful assistant designed to support me in a variety of tasks that responds in Markdown.\";\n // Save the default value into the option\n update_option('chatbot_deepseek_conversation_context', $chatbot_deepseek_conversation_context);\n }\n\n ?>\n <!-- Define the textarea field. -->\n <textarea id='chatbot_deepseek_conversation_context' name='chatbot_deepseek_conversation_context' rows='5' cols='50' maxlength='12500'><?php echo esc_html(stripslashes($chatbot_deepseek_conversation_context)); ?></textarea>\n <?php\n\n}\n\n// Set chatbot_deepseek_temperature\nfunction chatbot_deepseek_temperature_callback($args) {\n \n $temperature = esc_attr(get_option('chatbot_deepseek_temperature', 0.5));\n ?>\n <select id=\"chatbot_deepseek_temperature\" name=\"chatbot_deepseek_temperature\">\n <?php\n for ($i = 0.01; $i <= 2.01; $i += 0.01) {\n echo '<option value=\"' . esc_attr( $i ) . '\" ' . selected($temperature, (string)$i) . '>' . esc_html( $i ) . '</option>';\n }\n ?>\n </select>\n <?php\n\n}\n\n// Set chatbot_deepseek_top_p\nfunction chatbot_deepseek_top_p_callback($args) {\n\n $top_p = esc_attr(get_option('chatbot_deepseek_top_p', 1.00));\n ?>\n <select id=\"chatbot_deepseek_top_p\" name=\"chatbot_deepseek_top_p\">\n <?php\n for ($i = 0.01; $i <= 1.01; $i += 0.01) {\n echo '<option value=\"' . esc_attr( $i ) . '\" ' . selected($top_p, (string)$i) . '>' . esc_html( $i ) . '</option>';\n }\n ?>\n </select>\n <?php\n\n}\n\n// API Advanced settings section callback\nfunction chatbot_deepseek_api_model_advanced_section_callback($args) {\n\n ?>\n <p><strong>CAUTION</strong>: Configure the advanced settings for the plugin. Enter the base URL for the DeepSeek API. The default is <code>https://api.deepseek.com</code>.</p>\n <?php\n\n}\n\n// Base URL for the DeepSeek API\nfunction chatbot_deepseek_base_url_callback($args) {\n\n $chatbot_deepseek_base_url = esc_attr(get_option('chatbot_deepseek_base_url', 'https://api.deepseek.com'));\n ?>\n <input type=\"text\" id=\"chatbot_deepseek_base_url\" name=\"chatbot_deepseek_base_url\" value=\"<?php echo esc_attr( $chatbot_deepseek_base_url ); ?>\" class=\"regular-text\">\n <?php\n\n}\n\n// Timeout Settings Callback\nfunction chatbot_deepseek_timeout_setting_callback($args) {\n\n // Get the saved chatbot_deepseek_timeout value or default to 240\n $timeout = esc_attr(get_option('chatbot_deepseek_timeout_setting', 240));\n\n // Allow for a range of tokens between 5 and 500 in 5-step increments - Ver 1.8.8\n ?>\n <select id=\"chatbot_deepseek_timeout_setting\" name=\"chatbot_deepseek_timeout_setting\">\n <?php\n for ($i=5; $i<=500; $i+=5) {\n echo '<option value=\"' . esc_attr($i) . '\" ' . selected($timeout, (string)$i, false) . '>' . esc_html($i) . '</option>';\n }\n ?>\n </select>\n <?php\n\n}\n\n// Register API settings\nfunction chatbot_deepseek_api_settings_init() {\n\n add_settings_section(\n 'chatbot_deepseek_settings_section',\n 'API/DeepSeek Settings',\n 'chatbot_deepseek_model_settings_section_callback',\n 'chatbot_deepseek_model_settings_general'\n );\n\n // API/DeepSeek settings tab - Ver 2.1.8\n register_setting('chatbot_deepseek_api_model', 'chatbot_deepseek_api_enabled');\n register_setting('chatbot_deepseek_api_model', 'chatbot_deepseek_api_key', 'chatbot_chatgpt_sanitize_api_key');\n register_setting('chatbot_deepseek_api_model', 'chatbot_deepseek_max_tokens_setting'); // Max Tokens setting options\n register_setting('chatbot_deepseek_api_model', 'chatbot_deepseek_conversation_context'); // Conversation Context\n register_setting('chatbot_deepseek_api_model', 'chatbot_deepseek_temperature'); // Temperature\n register_setting('chatbot_deepseek_api_model', 'chatbot_deepseek_top_p'); // Top P\n\n add_settings_section(\n 'chatbot_deepseek_api_model_general_section',\n 'DeepSeek API Settings',\n 'chatbot_deepseek_api_model_general_section_callback',\n 'chatbot_deepseek_api_model_general'\n );\n\n add_settings_field(\n 'chatbot_deepseek_api_key',\n 'DeepSeek API Key',\n 'chatbot_deepseek_api_key_callback',\n 'chatbot_deepseek_api_model_general',\n 'chatbot_deepseek_api_model_general_section'\n );\n\n register_setting(\n 'chatbot_deepseek_api_model',\n 'chatbot_deepseek_model_choice',\n array(\n 'type' => '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"}, "ae7fbc5e985e140c07301be8d4a2c9d6214c9b31": {"t": 1786067605.8583455, "n": 13736, "h": "577bf92e0a4ab916", "c": "<?php\n/**\n * Kognetiks Chatbot - Settings - API/DeepSeek Page\n *\n * This file contains the code for the DeepSeek settings page.\n * It allows users to configure the API key and other parameters\n * required to access the ChatGPT API from their own account.\n *\n * @package chatbot-chatgpt\n */\n\n// If this file is called directly, abort.\nif ( ! defined( 'WPINC' ) ) {\n die();\n}\n\n// API/DeepSeek settings section callback - Ver 2.1.8\nfunction chatbot_deepseek_model_settings_section_callback($args) {\n ?>\n <p>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.</p>\n <p>More information about DeepSeek models and their capability can be found at <a href=\"https://api-docs.deepseek.com/quick_start/pricing\" target=\"_blank\">https://api-docs.deepseek.com/quick_start/pricing</a>.</p>\n <p><b><i>Don't forget to click </i><code>Save Settings</code><i> to save any changes your might make.</i></b></p>\n <p style=\"background-color: #e0f7fa; padding: 10px;\"><b>For an explanation of the API/DeepSeek settings and additional documentation please click <a href=\"?page=chatbot-chatgpt&tab=support&dir=api-deepseek-settings&file=api-deepseek-model-settings.md\">here</a>.</b></p>\n <?php\n}\n\nfunction chatbot_deepseek_api_model_general_section_callback($args) {\n ?>\n <p>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 <a href=\"https://platform.deepseek.com/sign_in\" target=\"_blank\">https://platform.deepseek.com/sign_in</a>.</p>\n <?php\n}\n\n// API key field callback\nfunction chatbot_deepseek_api_key_callback($args) {\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 <input type=\"password\" id=\"chatbot_deepseek_api_key\" name=\"chatbot_deepseek_api_key\" value=\"<?php echo esc_attr( $api_key ); ?>\" class=\"regular-text\" autocomplete=\"off\">\n <?php\n}\n\nfunction chatbot_deepseek_api_model_chat_settings_section_callback($args) {\n ?>\n <p>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 <a href=\"https://api-docs.deepseek.com/quick_start/pricing\" target=\"_blank\">https://api-docs.deepseek.com/quick_start/pricing</a>. Enter a conversation context to help the model understand the conversation. See the default for ideas. Some example shortcodes include:</p>\n <p><b>NOTE:</b> Enter your API key (above), click <code>Save Settings</code> at the bottom of this page, in order to retrieve the full list of available models.</p>\n <ul style=\"list-style-type: disc; list-style-position: inside; padding-left: 1em;\">\n <li><code>&#91;chatbot&#93;</code> - Default chat model, style is floating</li>\n <li><code>&#91;chatbot style=\"floating\" model=\"deepseek-chat\"&#93;</code> - Style is floating, specific model</li>\n <li><code>&#91;chatbot style=\"embedded\" model=\"deepseek-chat\"&#93;</code> - Style is embedded, default chat model</li>\n </ul>\n <?php\n}\n\n// DeepSeek Model Settings Callback - Ver 2.1.8\nfunction chatbot_deepseek_chat_model_choice_callback($args) {\n\n $model_choice = esc_attr(get_option('chatbot_deepseek_model_choice', 'deepseek-chat'));\n $deepseek_api_enabled = esc_attr(get_option('chatbot_deepseek_api_enabled', 'Yes'));\n\n // Fetch models from the API\n $models = chatbot_deepseek_get_models();\n\n // Remove the models not owned by DeepSeek\n $models = array_filter($models, function($model) {\n return $model['owned_by'] === 'deepseek';\n });\n\n // Check for errors\n if (is_string($models) && strpos($models, 'Error:') === 0) {\n // If there's an error, display the hardcoded list\n $model_choice = esc_attr(get_option('chatbot_deepseek_model_choice', 'deepseek-chat'));\n ?>\n <select id=\"chatbot_chatgpt_model_choice\" name=\"chatbot_chatgpt_model_choice\">\n <option value=\"<?php echo esc_attr( 'deepseek-chat' ); ?>\" <?php selected( $model_choice, 'deepseek-chat' ); ?>><?php echo esc_html( 'deepseek-chat' ); ?></option>\n </select>\n <?php\n } else {\n // If models are fetched successfully, display them dynamically\n ?>\n <select id=\"chatbot_deepseek_model_choice\" name=\"chatbot_deepseek_model_choice\">\n <?php foreach ($models as $model): ?>\n <option value=\"<?php echo esc_attr($model['id']); ?>\" <?php selected(esc_attr(get_option('chatbot_deepseek_model_choice')), $model['id']); ?>><?php echo esc_html($model['id']); ?></option>\n <?php endforeach; ?>\n ?>\n </select>\n <?php\n }\n\n}\n\n// Max Tokens choice - Ver 2.1.8\nfunction chatbot_deepseek_max_tokens_setting_callback($args) {\n\n // Get the saved chatbot_deepseek_max_tokens_setting or default to 1000\n $max_tokens = esc_attr(get_option('chatbot_deepseek_max_tokens_setting', '1000'));\n // Allow for a range of tokens between 100 and 10000 in 100-step increments - Ver 2.0.4\n ?>\n <select id=\"chatbot_deepseek_max_tokens_setting\" name=\"chatbot_deepseek_max_tokens_setting\">\n <?php\n for ($i=100; $i<=10000; $i+=100) {\n echo '<option value=\"' . esc_attr($i) . '\" ' . selected($max_tokens, (string)$i, false) . '>' . esc_html($i) . '</option>';\n }\n ?>\n </select>\n <?php\n\n}\n\n// Conversation Context\nfunction chatbot_deepseek_conversation_context_callback($args) {\n\n // Get the value of the setting we've registered with register_setting()\n $chatbot_deepseek_conversation_context = esc_attr(get_option('chatbot_deepseek_conversation_context'));\n\n // Check if the option has been set, if not, use a default value\n if (empty($chatbot_deepseek_conversation_context)) {\n $chatbot_deepseek_conversation_context = \"You are a versatile, friendly, and helpful assistant designed to support me in a variety of tasks that responds in Markdown.\";\n // Save the default value into the option\n update_option('chatbot_deepseek_conversation_context', $chatbot_deepseek_conversation_context);\n }\n\n ?>\n <!-- Define the textarea field. -->\n <textarea id='chatbot_deepseek_conversation_context' name='chatbot_deepseek_conversation_context' rows='5' cols='50' maxlength='12500'><?php echo esc_html(stripslashes($chatbot_deepseek_conversation_context)); ?></textarea>\n <?php\n\n}\n\n// Set chatbot_deepseek_temperature\nfunction chatbot_deepseek_temperature_callback($args) {\n \n $temperature = esc_attr(get_option('chatbot_deepseek_temperature', 0.5));\n ?>\n <select id=\"chatbot_deepseek_temperature\" name=\"chatbot_deepseek_temperature\">\n <?php\n for ($i = 0.01; $i <= 2.01; $i += 0.01) {\n echo '<option value=\"' . esc_attr( $i ) . '\" ' . selected($temperature, (string)$i) . '>' . esc_html( $i ) . '</option>';\n }\n ?>\n </select>\n <?php\n\n}\n\n// Set chatbot_deepseek_top_p\nfunction chatbot_deepseek_top_p_callback($args) {\n\n $top_p = esc_attr(get_option('chatbot_deepseek_top_p', 1.00));\n ?>\n <select id=\"chatbot_deepseek_top_p\" name=\"chatbot_deepseek_top_p\">\n <?php\n for ($i = 0.01; $i <= 1.01; $i += 0.01) {\n echo '<option value=\"' . esc_attr( $i ) . '\" ' . selected($top_p, (string)$i) . '>' . esc_html( $i ) . '</option>';\n }\n ?>\n </select>\n <?php\n\n}\n\n// API Advanced settings section callback\nfunction chatbot_deepseek_api_model_advanced_section_callback($args) {\n\n ?>\n <p><strong>CAUTION</strong>: Configure the advanced settings for the plugin. Enter the base URL for the DeepSeek API. The default is <code>https://api.deepseek.com</code>.</p>\n <?php\n\n}\n\n// Base URL for the DeepSeek API\nfunction chatbot_deepseek_base_url_callback($args) {\n\n $chatbot_deepseek_base_url = esc_attr(get_option('chatbot_deepseek_base_url', 'https://api.deepseek.com'));\n ?>\n <input type=\"text\" id=\"chatbot_deepseek_base_url\" name=\"chatbot_deepseek_base_url\" value=\"<?php echo esc_attr( $chatbot_deepseek_base_url ); ?>\" class=\"regular-text\">\n <?php\n\n}\n\n// Timeout Settings Callback\nfunction chatbot_deepseek_timeout_setting_callback($args) {\n\n // Get the saved chatbot_deepseek_timeout value or default to 240\n $timeout = esc_attr(get_option('chatbot_deepseek_timeout_setting', 240));\n\n // Allow for a range of tokens between 5 and 500 in 5-step increments - Ver 1.8.8\n ?>\n <select id=\"chatbot_deepseek_timeout_setting\" name=\"chatbot_deepseek_timeout_setting\">\n <?php\n for ($i=5; $i<=500; $i+=5) {\n echo '<option value=\"' . esc_attr($i) . '\" ' . selected($timeout, (string)$i, false) . '>' . esc_html($i) . '</option>';\n }\n ?>\n </select>\n <?php\n\n}\n\n// Register API settings\nfunction chatbot_deepseek_api_settings_init() {\n\n add_settings_section(\n 'chatbot_deepseek_settings_section',\n 'API/DeepSeek Settings',\n 'chatbot_deepseek_model_settings_section_callback',\n 'chatbot_deepseek_model_settings_general'\n );\n\n // API/DeepSeek settings tab - Ver 2.1.8\n register_setting('chatbot_deepseek_api_model', 'chatbot_deepseek_api_enabled');\n register_setting('chatbot_deepseek_api_model', 'chatbot_deepseek_api_key', 'chatbot_chatgpt_sanitize_api_key');\n register_setting('chatbot_deepseek_api_model', 'chatbot_deepseek_max_tokens_setting'); // Max Tokens setting options\n register_setting('chatbot_deepseek_api_model', 'chatbot_deepseek_conversation_context'); // Conversation Context\n register_setting('chatbot_deepseek_api_model', 'chatbot_deepseek_temperature'); // Temperature\n register_setting('chatbot_deepseek_api_model', 'chatbot_deepseek_top_p'); // Top P\n\n add_settings_section(\n 'chatbot_deepseek_api_model_general_section',\n 'DeepSeek API Settings',\n 'chatbot_deepseek_api_model_general_section_callback',\n 'chatbot_deepseek_api_model_general'\n );\n\n add_settings_field(\n 'chatbot_deepseek_api_key',\n 'DeepSeek API Key',\n 'chatbot_deepseek_api_key_callback',\n 'chatbot_deepseek_api_model_general',\n 'chatbot_deepseek_api_model_general_section'\n );\n\n register_setting(\n 'chatbot_deepseek_api_model',\n 'chatbot_deepseek_model_choice',\n array(\n 'type' => '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"}, "941929cdd6bc0a430d5e812b462d1714164d49bf": {"t": 1786068314.293482, "n": 13736, "h": "577bf92e0a4ab916", "c": "<?php\n/**\n * Kognetiks Chatbot - Settings - API/DeepSeek Page\n *\n * This file contains the code for the DeepSeek settings page.\n * It allows users to configure the API key and other parameters\n * required to access the ChatGPT API from their own account.\n *\n * @package chatbot-chatgpt\n */\n\n// If this file is called directly, abort.\nif ( ! defined( 'WPINC' ) ) {\n die();\n}\n\n// API/DeepSeek settings section callback - Ver 2.1.8\nfunction chatbot_deepseek_model_settings_section_callback($args) {\n ?>\n <p>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.</p>\n <p>More information about DeepSeek models and their capability can be found at <a href=\"https://api-docs.deepseek.com/quick_start/pricing\" target=\"_blank\">https://api-docs.deepseek.com/quick_start/pricing</a>.</p>\n <p><b><i>Don't forget to click </i><code>Save Settings</code><i> to save any changes your might make.</i></b></p>\n <p style=\"background-color: #e0f7fa; padding: 10px;\"><b>For an explanation of the API/DeepSeek settings and additional documentation please click <a href=\"?page=chatbot-chatgpt&tab=support&dir=api-deepseek-settings&file=api-deepseek-model-settings.md\">here</a>.</b></p>\n <?php\n}\n\nfunction chatbot_deepseek_api_model_general_section_callback($args) {\n ?>\n <p>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 <a href=\"https://platform.deepseek.com/sign_in\" target=\"_blank\">https://platform.deepseek.com/sign_in</a>.</p>\n <?php\n}\n\n// API key field callback\nfunction chatbot_deepseek_api_key_callback($args) {\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 <input type=\"password\" id=\"chatbot_deepseek_api_key\" name=\"chatbot_deepseek_api_key\" value=\"<?php echo esc_attr( $api_key ); ?>\" class=\"regular-text\" autocomplete=\"off\">\n <?php\n}\n\nfunction chatbot_deepseek_api_model_chat_settings_section_callback($args) {\n ?>\n <p>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 <a href=\"https://api-docs.deepseek.com/quick_start/pricing\" target=\"_blank\">https://api-docs.deepseek.com/quick_start/pricing</a>. Enter a conversation context to help the model understand the conversation. See the default for ideas. Some example shortcodes include:</p>\n <p><b>NOTE:</b> Enter your API key (above), click <code>Save Settings</code> at the bottom of this page, in order to retrieve the full list of available models.</p>\n <ul style=\"list-style-type: disc; list-style-position: inside; padding-left: 1em;\">\n <li><code>&#91;chatbot&#93;</code> - Default chat model, style is floating</li>\n <li><code>&#91;chatbot style=\"floating\" model=\"deepseek-chat\"&#93;</code> - Style is floating, specific model</li>\n <li><code>&#91;chatbot style=\"embedded\" model=\"deepseek-chat\"&#93;</code> - Style is embedded, default chat model</li>\n </ul>\n <?php\n}\n\n// DeepSeek Model Settings Callback - Ver 2.1.8\nfunction chatbot_deepseek_chat_model_choice_callback($args) {\n\n $model_choice = esc_attr(get_option('chatbot_deepseek_model_choice', 'deepseek-chat'));\n $deepseek_api_enabled = esc_attr(get_option('chatbot_deepseek_api_enabled', 'Yes'));\n\n // Fetch models from the API\n $models = chatbot_deepseek_get_models();\n\n // Remove the models not owned by DeepSeek\n $models = array_filter($models, function($model) {\n return $model['owned_by'] === 'deepseek';\n });\n\n // Check for errors\n if (is_string($models) && strpos($models, 'Error:') === 0) {\n // If there's an error, display the hardcoded list\n $model_choice = esc_attr(get_option('chatbot_deepseek_model_choice', 'deepseek-chat'));\n ?>\n <select id=\"chatbot_chatgpt_model_choice\" name=\"chatbot_chatgpt_model_choice\">\n <option value=\"<?php echo esc_attr( 'deepseek-chat' ); ?>\" <?php selected( $model_choice, 'deepseek-chat' ); ?>><?php echo esc_html( 'deepseek-chat' ); ?></option>\n </select>\n <?php\n } else {\n // If models are fetched successfully, display them dynamically\n ?>\n <select id=\"chatbot_deepseek_model_choice\" name=\"chatbot_deepseek_model_choice\">\n <?php foreach ($models as $model): ?>\n <option value=\"<?php echo esc_attr($model['id']); ?>\" <?php selected(esc_attr(get_option('chatbot_deepseek_model_choice')), $model['id']); ?>><?php echo esc_html($model['id']); ?></option>\n <?php endforeach; ?>\n ?>\n </select>\n <?php\n }\n\n}\n\n// Max Tokens choice - Ver 2.1.8\nfunction chatbot_deepseek_max_tokens_setting_callback($args) {\n\n // Get the saved chatbot_deepseek_max_tokens_setting or default to 1000\n $max_tokens = esc_attr(get_option('chatbot_deepseek_max_tokens_setting', '1000'));\n // Allow for a range of tokens between 100 and 10000 in 100-step increments - Ver 2.0.4\n ?>\n <select id=\"chatbot_deepseek_max_tokens_setting\" name=\"chatbot_deepseek_max_tokens_setting\">\n <?php\n for ($i=100; $i<=10000; $i+=100) {\n echo '<option value=\"' . esc_attr($i) . '\" ' . selected($max_tokens, (string)$i, false) . '>' . esc_html($i) . '</option>';\n }\n ?>\n </select>\n <?php\n\n}\n\n// Conversation Context\nfunction chatbot_deepseek_conversation_context_callback($args) {\n\n // Get the value of the setting we've registered with register_setting()\n $chatbot_deepseek_conversation_context = esc_attr(get_option('chatbot_deepseek_conversation_context'));\n\n // Check if the option has been set, if not, use a default value\n if (empty($chatbot_deepseek_conversation_context)) {\n $chatbot_deepseek_conversation_context = \"You are a versatile, friendly, and helpful assistant designed to support me in a variety of tasks that responds in Markdown.\";\n // Save the default value into the option\n update_option('chatbot_deepseek_conversation_context', $chatbot_deepseek_conversation_context);\n }\n\n ?>\n <!-- Define the textarea field. -->\n <textarea id='chatbot_deepseek_conversation_context' name='chatbot_deepseek_conversation_context' rows='5' cols='50' maxlength='12500'><?php echo esc_html(stripslashes($chatbot_deepseek_conversation_context)); ?></textarea>\n <?php\n\n}\n\n// Set chatbot_deepseek_temperature\nfunction chatbot_deepseek_temperature_callback($args) {\n \n $temperature = esc_attr(get_option('chatbot_deepseek_temperature', 0.5));\n ?>\n <select id=\"chatbot_deepseek_temperature\" name=\"chatbot_deepseek_temperature\">\n <?php\n for ($i = 0.01; $i <= 2.01; $i += 0.01) {\n echo '<option value=\"' . esc_attr( $i ) . '\" ' . selected($temperature, (string)$i) . '>' . esc_html( $i ) . '</option>';\n }\n ?>\n </select>\n <?php\n\n}\n\n// Set chatbot_deepseek_top_p\nfunction chatbot_deepseek_top_p_callback($args) {\n\n $top_p = esc_attr(get_option('chatbot_deepseek_top_p', 1.00));\n ?>\n <select id=\"chatbot_deepseek_top_p\" name=\"chatbot_deepseek_top_p\">\n <?php\n for ($i = 0.01; $i <= 1.01; $i += 0.01) {\n echo '<option value=\"' . esc_attr( $i ) . '\" ' . selected($top_p, (string)$i) . '>' . esc_html( $i ) . '</option>';\n }\n ?>\n </select>\n <?php\n\n}\n\n// API Advanced settings section callback\nfunction chatbot_deepseek_api_model_advanced_section_callback($args) {\n\n ?>\n <p><strong>CAUTION</strong>: Configure the advanced settings for the plugin. Enter the base URL for the DeepSeek API. The default is <code>https://api.deepseek.com</code>.</p>\n <?php\n\n}\n\n// Base URL for the DeepSeek API\nfunction chatbot_deepseek_base_url_callback($args) {\n\n $chatbot_deepseek_base_url = esc_attr(get_option('chatbot_deepseek_base_url', 'https://api.deepseek.com'));\n ?>\n <input type=\"text\" id=\"chatbot_deepseek_base_url\" name=\"chatbot_deepseek_base_url\" value=\"<?php echo esc_attr( $chatbot_deepseek_base_url ); ?>\" class=\"regular-text\">\n <?php\n\n}\n\n// Timeout Settings Callback\nfunction chatbot_deepseek_timeout_setting_callback($args) {\n\n // Get the saved chatbot_deepseek_timeout value or default to 240\n $timeout = esc_attr(get_option('chatbot_deepseek_timeout_setting', 240));\n\n // Allow for a range of tokens between 5 and 500 in 5-step increments - Ver 1.8.8\n ?>\n <select id=\"chatbot_deepseek_timeout_setting\" name=\"chatbot_deepseek_timeout_setting\">\n <?php\n for ($i=5; $i<=500; $i+=5) {\n echo '<option value=\"' . esc_attr($i) . '\" ' . selected($timeout, (string)$i, false) . '>' . esc_html($i) . '</option>';\n }\n ?>\n </select>\n <?php\n\n}\n\n// Register API settings\nfunction chatbot_deepseek_api_settings_init() {\n\n add_settings_section(\n 'chatbot_deepseek_settings_section',\n 'API/DeepSeek Settings',\n 'chatbot_deepseek_model_settings_section_callback',\n 'chatbot_deepseek_model_settings_general'\n );\n\n // API/DeepSeek settings tab - Ver 2.1.8\n register_setting('chatbot_deepseek_api_model', 'chatbot_deepseek_api_enabled');\n register_setting('chatbot_deepseek_api_model', 'chatbot_deepseek_api_key', 'chatbot_chatgpt_sanitize_api_key');\n register_setting('chatbot_deepseek_api_model', 'chatbot_deepseek_max_tokens_setting'); // Max Tokens setting options\n register_setting('chatbot_deepseek_api_model', 'chatbot_deepseek_conversation_context'); // Conversation Context\n register_setting('chatbot_deepseek_api_model', 'chatbot_deepseek_temperature'); // Temperature\n register_setting('chatbot_deepseek_api_model', 'chatbot_deepseek_top_p'); // Top P\n\n add_settings_section(\n 'chatbot_deepseek_api_model_general_section',\n 'DeepSeek API Settings',\n 'chatbot_deepseek_api_model_general_section_callback',\n 'chatbot_deepseek_api_model_general'\n );\n\n add_settings_field(\n 'chatbot_deepseek_api_key',\n 'DeepSeek API Key',\n 'chatbot_deepseek_api_key_callback',\n 'chatbot_deepseek_api_model_general',\n 'chatbot_deepseek_api_model_general_section'\n );\n\n register_setting(\n 'chatbot_deepseek_api_model',\n 'chatbot_deepseek_model_choice',\n array(\n 'type' => '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": "<?php\n/**\n * Kognetiks Chatbot - Keyguard Support - Ver 2.2.6\n *\n * This file contains the code for managing the Keyguard functions.\n * \n *\n * @package chatbot-chatgpt\n */\n\n// If this file is called directly, abort.\nif ( ! defined( 'WPINC' ) ) {\n die();\n}\n\n// One-time upgrade to encrypted keys using the old secret key - Ver 2.2.6\n// chatbot_chatgpt_upgrade_encrypted_api_keys('chatbot_chatgpt_fetch_stored_api_keys', 'chatbot_chatgpt_update_stored_api_key', $old_keyguard);\n\n// XORs the given key with a salt key and returns the base64-encoded result - Ver 2.2.6\nfunction chatbot_chatgpt_obfuscate_keyguard($key) {\n\n // Ensure AUTH_KEY is defined.\n if ( ! defined('AUTH_KEY') ) {\n trigger_error('AUTH_KEY must be defined in wp-config.php for secure obfuscation.', E_USER_ERROR);\n }\n $salt = AUTH_KEY;\n // Derive a 32-byte binary salt key.\n $salt_key = hash('sha256', $salt, true);\n // Convert the hex key to binary.\n $binary_key = hex2bin($key);\n // XOR the binary key with the salt key.\n $obfuscated_binary = $binary_key ^ $salt_key;\n // Return the result base64-encoded.\n return base64_encode($obfuscated_binary);\n\n}\n\n// XORs the given obfuscated key with a salt key and returns the hex-encoded result - Ver 2.2.6\nfunction chatbot_chatgpt_deobfuscate_keyguard($obfuscated_key) {\n\n // Ensure AUTH_KEY is defined.\n if ( ! defined('AUTH_KEY') ) {\n trigger_error('AUTH_KEY must be defined in wp-config.php for secure obfuscation.', E_USER_ERROR);\n }\n $salt = AUTH_KEY;\n // Derive a 32-byte binary salt key.\n $salt_key = hash('sha256', $salt, true);\n // Convert the hex key to binary.\n $obfuscated_binary = base64_decode($obfuscated_key);\n // XOR the binary key with the salt key.\n $binary_key = $obfuscated_binary ^ $salt_key;\n // Return the result base64-decoded.\n return bin2hex($binary_key);\n\n}\n\n// Retrieves the chatbot secret key and if it doesn't exist, a new key is generated and stored - Ver 2.2.6\nfunction chatbot_chatgpt_generate_and_store_keyguard() {\n\n $option_name = 'kognetiks_keyguard';\n \n // Retrieve the obfuscated key from the DB.\n $obfuscated_key = get_option($option_name);\n \n if (empty($obfuscated_key)) {\n // Generate a new 256-bit (32-byte) key and convert it to a hex string.\n $key = bin2hex(random_bytes(32));\n // Obfuscate the key.\n $obfuscated_key = chatbot_chatgpt_obfuscate_keyguard($key);\n // Store in the DB. Disable autoload to prevent it from loading on every page load.\n update_option($option_name, $obfuscated_key, '', 'no');\n return $key;\n }\n \n // Deobfuscate to retrieve the original key.\n return chatbot_chatgpt_deobfuscate_keyguard($obfuscated_key);\n\n}\n\n// Encrypts the given plaintext using AES-256-CBC with the provided secret key - Ver 2.2.6\n//\n// Returns a JSON string containing the base64-encoded IV and the encrypted data,\n//\nfunction chatbot_chatgpt_encrypt_api_key_with_key($plaintext, $keyguard) {\n\n $cipher = 'aes-256-cbc';\n $iv_length = openssl_cipher_iv_length($cipher);\n $iv = openssl_random_pseudo_bytes($iv_length);\n // Convert the hex-encoded keyguard to binary.\n $binary_key = hex2bin($keyguard);\n $encrypted = openssl_encrypt($plaintext, $cipher, $binary_key, 0, $iv);\n if ($encrypted === false) {\n return false;\n }\n $data = [\n 'iv' => 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": "<?php\n/**\n * Kognetiks Chatbot - Keyguard Support - Ver 2.2.6\n *\n * This file contains the code for managing the Keyguard functions.\n * \n *\n * @package chatbot-chatgpt\n */\n\n// If this file is called directly, abort.\nif ( ! defined( 'WPINC' ) ) {\n die();\n}\n\n// One-time upgrade to encrypted keys using the old secret key - Ver 2.2.6\n// chatbot_chatgpt_upgrade_encrypted_api_keys('chatbot_chatgpt_fetch_stored_api_keys', 'chatbot_chatgpt_update_stored_api_key', $old_keyguard);\n\n// XORs the given key with a salt key and returns the base64-encoded result - Ver 2.2.6\nfunction chatbot_chatgpt_obfuscate_keyguard($key) {\n\n // Ensure AUTH_KEY is defined.\n if ( ! defined('AUTH_KEY') ) {\n trigger_error('AUTH_KEY must be defined in wp-config.php for secure obfuscation.', E_USER_ERROR);\n }\n $salt = AUTH_KEY;\n // Derive a 32-byte binary salt key.\n $salt_key = hash('sha256', $salt, true);\n // Convert the hex key to binary.\n $binary_key = hex2bin($key);\n // XOR the binary key with the salt key.\n $obfuscated_binary = $binary_key ^ $salt_key;\n // Return the result base64-encoded.\n return base64_encode($obfuscated_binary);\n\n}\n\n// XORs the given obfuscated key with a salt key and returns the hex-encoded result - Ver 2.2.6\nfunction chatbot_chatgpt_deobfuscate_keyguard($obfuscated_key) {\n\n // Ensure AUTH_KEY is defined.\n if ( ! defined('AUTH_KEY') ) {\n trigger_error('AUTH_KEY must be defined in wp-config.php for secure obfuscation.', E_USER_ERROR);\n }\n $salt = AUTH_KEY;\n // Derive a 32-byte binary salt key.\n $salt_key = hash('sha256', $salt, true);\n // Convert the hex key to binary.\n $obfuscated_binary = base64_decode($obfuscated_key);\n // XOR the binary key with the salt key.\n $binary_key = $obfuscated_binary ^ $salt_key;\n // Return the result base64-decoded.\n return bin2hex($binary_key);\n\n}\n\n// Retrieves the chatbot secret key and if it doesn't exist, a new key is generated and stored - Ver 2.2.6\nfunction chatbot_chatgpt_generate_and_store_keyguard() {\n\n $option_name = 'kognetiks_keyguard';\n \n // Retrieve the obfuscated key from the DB.\n $obfuscated_key = get_option($option_name);\n \n if (empty($obfuscated_key)) {\n // Generate a new 256-bit (32-byte) key and convert it to a hex string.\n $key = bin2hex(random_bytes(32));\n // Obfuscate the key.\n $obfuscated_key = chatbot_chatgpt_obfuscate_keyguard($key);\n // Store in the DB. Disable autoload to prevent it from loading on every page load.\n update_option($option_name, $obfuscated_key, '', 'no');\n return $key;\n }\n \n // Deobfuscate to retrieve the original key.\n return chatbot_chatgpt_deobfuscate_keyguard($obfuscated_key);\n\n}\n\n// Encrypts the given plaintext using AES-256-CBC with the provided secret key - Ver 2.2.6\n//\n// Returns a JSON string containing the base64-encoded IV and the encrypted data,\n//\nfunction chatbot_chatgpt_encrypt_api_key_with_key($plaintext, $keyguard) {\n\n $cipher = 'aes-256-cbc';\n $iv_length = openssl_cipher_iv_length($cipher);\n $iv = openssl_random_pseudo_bytes($iv_length);\n // Convert the hex-encoded keyguard to binary.\n $binary_key = hex2bin($keyguard);\n $encrypted = openssl_encrypt($plaintext, $cipher, $binary_key, 0, $iv);\n if ($encrypted === false) {\n return false;\n }\n $data = [\n 'iv' => 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"}, "2dd08585d8f97d7e6063f081a2c8af9f1d2a898b": {"t": 1786067464.8685193, "n": 14569, "h": "0fccf40841c37e5d", "c": "<?php\n/**\n * Kognetiks Chatbot - Keyguard Support - Ver 2.2.6\n *\n * This file contains the code for managing the Keyguard functions.\n * \n *\n * @package chatbot-chatgpt\n */\n\n// If this file is called directly, abort.\nif ( ! defined( 'WPINC' ) ) {\n die();\n}\n\n// One-time upgrade to encrypted keys using the old secret key - Ver 2.2.6\n// chatbot_chatgpt_upgrade_encrypted_api_keys('chatbot_chatgpt_fetch_stored_api_keys', 'chatbot_chatgpt_update_stored_api_key', $old_keyguard);\n\n// XORs the given key with a salt key and returns the base64-encoded result - Ver 2.2.6\nfunction chatbot_chatgpt_obfuscate_keyguard($key) {\n\n // Ensure AUTH_KEY is defined.\n if ( ! defined('AUTH_KEY') ) {\n trigger_error('AUTH_KEY must be defined in wp-config.php for secure obfuscation.', E_USER_ERROR);\n }\n $salt = AUTH_KEY;\n // Derive a 32-byte binary salt key.\n $salt_key = hash('sha256', $salt, true);\n // Convert the hex key to binary.\n $binary_key = hex2bin($key);\n // XOR the binary key with the salt key.\n $obfuscated_binary = $binary_key ^ $salt_key;\n // Return the result base64-encoded.\n return base64_encode($obfuscated_binary);\n\n}\n\n// XORs the given obfuscated key with a salt key and returns the hex-encoded result - Ver 2.2.6\nfunction chatbot_chatgpt_deobfuscate_keyguard($obfuscated_key) {\n\n // Ensure AUTH_KEY is defined.\n if ( ! defined('AUTH_KEY') ) {\n trigger_error('AUTH_KEY must be defined in wp-config.php for secure obfuscation.', E_USER_ERROR);\n }\n $salt = AUTH_KEY;\n // Derive a 32-byte binary salt key.\n $salt_key = hash('sha256', $salt, true);\n // Convert the hex key to binary.\n $obfuscated_binary = base64_decode($obfuscated_key);\n // XOR the binary key with the salt key.\n $binary_key = $obfuscated_binary ^ $salt_key;\n // Return the result base64-decoded.\n return bin2hex($binary_key);\n\n}\n\n// Retrieves the chatbot secret key and if it doesn't exist, a new key is generated and stored - Ver 2.2.6\nfunction chatbot_chatgpt_generate_and_store_keyguard() {\n\n $option_name = 'kognetiks_keyguard';\n \n // Retrieve the obfuscated key from the DB.\n $obfuscated_key = get_option($option_name);\n \n if (empty($obfuscated_key)) {\n // Generate a new 256-bit (32-byte) key and convert it to a hex string.\n $key = bin2hex(random_bytes(32));\n // Obfuscate the key.\n $obfuscated_key = chatbot_chatgpt_obfuscate_keyguard($key);\n // Store in the DB. Disable autoload to prevent it from loading on every page load.\n update_option($option_name, $obfuscated_key, '', 'no');\n return $key;\n }\n \n // Deobfuscate to retrieve the original key.\n return chatbot_chatgpt_deobfuscate_keyguard($obfuscated_key);\n\n}\n\n// Encrypts the given plaintext using AES-256-CBC with the provided secret key - Ver 2.2.6\n//\n// Returns a JSON string containing the base64-encoded IV and the encrypted data,\n//\nfunction chatbot_chatgpt_encrypt_api_key_with_key($plaintext, $keyguard) {\n\n $cipher = 'aes-256-cbc';\n $iv_length = openssl_cipher_iv_length($cipher);\n $iv = openssl_random_pseudo_bytes($iv_length);\n // Convert the hex-encoded keyguard to binary.\n $binary_key = hex2bin($keyguard);\n $encrypted = openssl_encrypt($plaintext, $cipher, $binary_key, 0, $iv);\n if ($encrypted === false) {\n return false;\n }\n $data = [\n 'iv' => 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"}, "941929cdd6bc0a430d5e812b462d1714164d49bf": {"t": 1786068314.9645793, "n": 14569, "h": "0fccf40841c37e5d", "c": "<?php\n/**\n * Kognetiks Chatbot - Keyguard Support - Ver 2.2.6\n *\n * This file contains the code for managing the Keyguard functions.\n * \n *\n * @package chatbot-chatgpt\n */\n\n// If this file is called directly, abort.\nif ( ! defined( 'WPINC' ) ) {\n die();\n}\n\n// One-time upgrade to encrypted keys using the old secret key - Ver 2.2.6\n// chatbot_chatgpt_upgrade_encrypted_api_keys('chatbot_chatgpt_fetch_stored_api_keys', 'chatbot_chatgpt_update_stored_api_key', $old_keyguard);\n\n// XORs the given key with a salt key and returns the base64-encoded result - Ver 2.2.6\nfunction chatbot_chatgpt_obfuscate_keyguard($key) {\n\n // Ensure AUTH_KEY is defined.\n if ( ! defined('AUTH_KEY') ) {\n trigger_error('AUTH_KEY must be defined in wp-config.php for secure obfuscation.', E_USER_ERROR);\n }\n $salt = AUTH_KEY;\n // Derive a 32-byte binary salt key.\n $salt_key = hash('sha256', $salt, true);\n // Convert the hex key to binary.\n $binary_key = hex2bin($key);\n // XOR the binary key with the salt key.\n $obfuscated_binary = $binary_key ^ $salt_key;\n // Return the result base64-encoded.\n return base64_encode($obfuscated_binary);\n\n}\n\n// XORs the given obfuscated key with a salt key and returns the hex-encoded result - Ver 2.2.6\nfunction chatbot_chatgpt_deobfuscate_keyguard($obfuscated_key) {\n\n // Ensure AUTH_KEY is defined.\n if ( ! defined('AUTH_KEY') ) {\n trigger_error('AUTH_KEY must be defined in wp-config.php for secure obfuscation.', E_USER_ERROR);\n }\n $salt = AUTH_KEY;\n // Derive a 32-byte binary salt key.\n $salt_key = hash('sha256', $salt, true);\n // Convert the hex key to binary.\n $obfuscated_binary = base64_decode($obfuscated_key);\n // XOR the binary key with the salt key.\n $binary_key = $obfuscated_binary ^ $salt_key;\n // Return the result base64-decoded.\n return bin2hex($binary_key);\n\n}\n\n// Retrieves the chatbot secret key and if it doesn't exist, a new key is generated and stored - Ver 2.2.6\nfunction chatbot_chatgpt_generate_and_store_keyguard() {\n\n $option_name = 'kognetiks_keyguard';\n \n // Retrieve the obfuscated key from the DB.\n $obfuscated_key = get_option($option_name);\n \n if (empty($obfuscated_key)) {\n // Generate a new 256-bit (32-byte) key and convert it to a hex string.\n $key = bin2hex(random_bytes(32));\n // Obfuscate the key.\n $obfuscated_key = chatbot_chatgpt_obfuscate_keyguard($key);\n // Store in the DB. Disable autoload to prevent it from loading on every page load.\n update_option($option_name, $obfuscated_key, '', 'no');\n return $key;\n }\n \n // Deobfuscate to retrieve the original key.\n return chatbot_chatgpt_deobfuscate_keyguard($obfuscated_key);\n\n}\n\n// Encrypts the given plaintext using AES-256-CBC with the provided secret key - Ver 2.2.6\n//\n// Returns a JSON string containing the base64-encoded IV and the encrypted data,\n//\nfunction chatbot_chatgpt_encrypt_api_key_with_key($plaintext, $keyguard) {\n\n $cipher = 'aes-256-cbc';\n $iv_length = openssl_cipher_iv_length($cipher);\n $iv = openssl_random_pseudo_bytes($iv_length);\n // Convert the hex-encoded keyguard to binary.\n $binary_key = hex2bin($keyguard);\n $encrypted = openssl_encrypt($plaintext, $cipher, $binary_key, 0, $iv);\n if ($encrypted === false) {\n return false;\n }\n $data = [\n 'iv' => 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": "<?php\n/**\n * Kognetiks Chatbot - Chatbot Models\n *\n * This file contains the code to retrieve the list of available models\n * from OpenAI API and display them in the settings page.\n *\n * @package chatbot-chatgpt\n */\n\n// If this file is called directly, abort.\nif ( ! defined( 'WPINC' ) ) {\n die();\n}\n\n// Function to get the Model names from OpenAI API\nfunction chatbot_openai_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_chatgpt_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' => 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": "<?php\n/**\n * Kognetiks Chatbot - Chatbot Models\n *\n * This file contains the code to retrieve the list of available models\n * from OpenAI API and display them in the settings page.\n *\n * @package chatbot-chatgpt\n */\n\n// If this file is called directly, abort.\nif ( ! defined( 'WPINC' ) ) {\n die();\n}\n\n// Function to get the Model names from OpenAI API\nfunction chatbot_openai_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_chatgpt_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' => 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": "<?php\n/**\n * Kognetiks Chatbot for WordPress - Chatbot Models\n *\n * This file contains the code to retrieve the list of available models\n * from OpenAI API and display them in the settings page.\n *\n * @package chatbot-chatgpt\n */\n\n// If this file is called directly, abort.\nif ( ! defined( 'WPINC' ) ) {\n die();\n}\n\n// Function to get the Model names from OpenAI API\nfunction chatbot_openai_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_chatgpt_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' => 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": "<?php\n/**\n * Kognetiks Chatbot for WordPress - Chatbot Models\n *\n * This file contains the code to retrieve the list of available models\n * from OpenAI API and display them in the settings page.\n *\n * @package chatbot-chatgpt\n */\n\n// If this file is called directly, abort.\nif ( ! defined( 'WPINC' ) ) {\n die();\n}\n\n// Function to get the Assistant's name\nfunction chatbot_chatgpt_get_openai_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_chatgpt_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' => 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": "<?php\n/**\n * Kognetiks Chatbot for WordPress - Chatbot Models\n *\n * This file contains the code to retrieve the list of available models\n * from OpenAI API and display them in the settings page.\n *\n * @package chatbot-chatgpt\n */\n\n// If this file is called directly, abort.\nif ( ! defined( 'WPINC' ) ) {\n die();\n}\n\n// Function to get the Assistant's name\nfunction chatbot_chatgpt_get_openai_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_chatgpt_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' => 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": "<?php\n/**\n * Kognetiks Chatbot for WordPress - Chatbot Models\n *\n * This file contains the code to retrieve the list of available models\n * from OpenAI API and display them in the settings page.\n *\n * @package chatbot-chatgpt\n */\n\n// If this file is called directly, abort.\nif ( ! defined( 'WPINC' ) ) {\n die();\n}\n\n// Function to get the Assistant's name\nfunction chatbot_chatgpt_get_openai_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_chatgpt_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' => 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": "<?php\n/**\n * Kognetiks Chatbot for WordPress - Chatbot Models\n *\n * This file contains the code to retrieve the list of available models\n * from OpenAI API and display them in the settings page.\n *\n * @package chatbot-chatgpt\n */\n\n// If this file is called directly, abort.\nif ( ! defined( 'WPINC' ) ) {\n die;\n}\n\n// Function to get the Assistant's name\nfunction get_openai_models() {\n\n // Global variables\n global $session_id;\n global $user_id;\n global $page_id;\n global $thread_id;\n global $assistant_id;\n global $script_data_array;\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_chatgpt_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' => 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": "<?php\n/**\n * Kognetiks Chatbot for WordPress - Chatbot Models\n *\n * This file contains the code to retrieve the list of available models\n * from OpenAI API and display them in the settings page.\n *\n * @package chatbot-chatgpt\n */\n\n// If this file is called directly, abort.\nif ( ! defined( 'WPINC' ) ) {\n die;\n}\n\n// Function to get the Assistant's name\nfunction get_openai_models() {\n\n // Global variables\n global $session_id;\n global $user_id;\n global $page_id;\n global $thread_id;\n global $assistant_id;\n global $script_data_array;\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_chatgpt_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' => 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": "<?php\n/**\n * Kognetiks Chatbot for WordPress - Chatbot Models\n *\n * This file contains the code to retrieve the list of available models\n * from OpenAI API and display them in the settings page.\n *\n * @package chatbot-chatgpt\n */\n\n// If this file is called directly, abort.\nif ( ! defined( 'WPINC' ) ) {\n die;\n}\n\n// Function to get the Assistant's name\nfunction get_openai_models() {\n\n // Global variables\n global $session_id;\n global $user_id;\n global $page_id;\n global $thread_id;\n global $assistant_id;\n global $script_data_array;\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_chatgpt_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' => 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": "<?php\n/**\n * Kognetiks Chatbot for WordPress - Chatbot Models\n *\n * This file contains the code to retrieve the list of available models\n * from OpenAI API and display them in the settings page.\n *\n * @package chatbot-chatgpt\n */\n\n// If this file is called directly, abort.\nif ( ! defined( 'WPINC' ) ) {\n die;\n}\n\n// Function to get the Assistant's name\nfunction get_openai_models() {\n\n // Global variables\n global $session_id;\n global $user_id;\n global $page_id;\n global $thread_id;\n global $assistant_id;\n global $script_data_array;\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_chatgpt_api_key'));\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 $data = '';\n\n $data = array(\n array(\n 'id' => '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"}, "2dd08585d8f97d7e6063f081a2c8af9f1d2a898b": {"t": 1786067466.2262082, "n": 24184, "h": "f0f82e61f23673e0", "c": "<?php\n/**\n * Kognetiks Chatbot - Chatbot Models\n *\n * This file contains the code to retrieve the list of available models\n * from OpenAI API and display them in the settings page.\n *\n * @package chatbot-chatgpt\n */\n\n// If this file is called directly, abort.\nif ( ! defined( 'WPINC' ) ) {\n die();\n}\n\n// Function to get the Model names from OpenAI API\nfunction chatbot_openai_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_chatgpt_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' => 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"}, "ae7fbc5e985e140c07301be8d4a2c9d6214c9b31": {"t": 1786067607.2095509, "n": 24184, "h": "f0f82e61f23673e0", "c": "<?php\n/**\n * Kognetiks Chatbot - Chatbot Models\n *\n * This file contains the code to retrieve the list of available models\n * from OpenAI API and display them in the settings page.\n *\n * @package chatbot-chatgpt\n */\n\n// If this file is called directly, abort.\nif ( ! defined( 'WPINC' ) ) {\n die();\n}\n\n// Function to get the Model names from OpenAI API\nfunction chatbot_openai_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_chatgpt_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' => 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"}, "941929cdd6bc0a430d5e812b462d1714164d49bf": {"t": 1786068315.3078196, "n": 24184, "h": "f0f82e61f23673e0", "c": "<?php\n/**\n * Kognetiks Chatbot - Chatbot Models\n *\n * This file contains the code to retrieve the list of available models\n * from OpenAI API and display them in the settings page.\n *\n * @package chatbot-chatgpt\n */\n\n// If this file is called directly, abort.\nif ( ! defined( 'WPINC' ) ) {\n die();\n}\n\n// Function to get the Model names from OpenAI API\nfunction chatbot_openai_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_chatgpt_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' => 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"}}, "wp-content/plugins/chatbot-chatgpt/chatbot-chatgpt.php": {"de6c3bda23246fe11f7d20255df14f55b5865b77": {"t": 1785745785.7580836, "n": 167437, "h": "8b902d1831b1c4d5", "c": "<?php\r\n\r\n/*\r\n * Plugin Name: Kognetiks Chatbot\r\n * Plugin URI: https://github.com/kognetiks/kognetiks-chatbot\r\n * Description: This simple plugin adds an AI powered chatbot to your WordPress website.\r\n * Version: 2.4.6\r\n * Author: Kognetiks.com\r\n * Author URI: https://www.kognetiks.com\r\n * License: GPLv3 or later\r\n * License URI: https://www.gnu.org/licenses/gpl-30.html\r\n * \r\n * Copyright (c) 2023-2025 Stephen Howell\r\n * \r\n * This program is free software; you can redistribute it and/or modify it under the terms of the GNU\r\n * General Public License version 3, as published by the Free Software Foundation. You may NOT assume\r\n * that you can use any other version of the GPL.\r\n * \r\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without\r\n * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\r\n * \r\n * You should have received a copy of the GNU General Public License\r\n * along with Kognetiks Chatbot. If not, see https://www.gnu.org/licenses/gpl-3.0.html.\r\n * \r\n * @package chatbot-chatgpt\r\n * @version 2.4.6\r\n * @author Kognetiks.com\r\n */\r\nif ( !defined( 'ABSPATH' ) ) {\r\n exit;\r\n}\r\n// Load vendor management early so it can register for chatbot_chatgpt_freemius_loaded (before do_action runs)\r\n// require_once plugin_dir_path(__FILE__) . 'includes/utilities/chatbot-vendor-management.php';\r\nif ( function_exists( 'chatbot_chatgpt_freemius' ) ) {\r\n chatbot_chatgpt_freemius()->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 . '<br><br>' . 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 . '<br><br>' . 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 '<div class=\"notice notice-success\"><p>Visitor locks cleared successfully!</p></div>';\r\n }\r\n echo '<div class=\"wrap\">';\r\n echo '<h1>Clear Visitor Locks</h1>';\r\n echo '<p>This tool clears stuck conversation locks that may be preventing visitors from using the chatbot.</p>';\r\n echo '<p><strong>Use this if visitors are getting \"system is busy processing requests\" messages.</strong></p>';\r\n echo '<form method=\"post\">';\r\n wp_nonce_field( 'clear_visitor_locks' );\r\n echo '<p><input type=\"submit\" name=\"clear_locks\" class=\"button-primary\" value=\"Clear All Visitor Locks\" onclick=\"return confirm(\\'Are you sure you want to clear all visitor locks?\\')\"></p>';\r\n echo '</form>';\r\n echo '</div>';\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": "<?php\r\n\r\n/*\r\n * Plugin Name: Kognetiks Chatbot\r\n * Plugin URI: https://github.com/kognetiks/kognetiks-chatbot\r\n * Description: This simple plugin adds an AI powered chatbot to your WordPress website.\r\n * Version: 2.4.6\r\n * Author: Kognetiks.com\r\n * Author URI: https://www.kognetiks.com\r\n * License: GPLv3 or later\r\n * License URI: https://www.gnu.org/licenses/gpl-30.html\r\n * \r\n * Copyright (c) 2023-2025 Stephen Howell\r\n * \r\n * This program is free software; you can redistribute it and/or modify it under the terms of the GNU\r\n * General Public License version 3, as published by the Free Software Foundation. You may NOT assume\r\n * that you can use any other version of the GPL.\r\n * \r\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without\r\n * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\r\n * \r\n * You should have received a copy of the GNU General Public License\r\n * along with Kognetiks Chatbot. If not, see https://www.gnu.org/licenses/gpl-3.0.html.\r\n * \r\n * @package chatbot-chatgpt\r\n * @version 2.4.6\r\n * @author Kognetiks.com\r\n */\r\nif ( !defined( 'ABSPATH' ) ) {\r\n exit;\r\n}\r\n// Load vendor management early so it can register for chatbot_chatgpt_freemius_loaded (before do_action runs)\r\n// require_once plugin_dir_path(__FILE__) . 'includes/utilities/chatbot-vendor-management.php';\r\nif ( function_exists( 'chatbot_chatgpt_freemius' ) ) {\r\n chatbot_chatgpt_freemius()->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 . '<br><br>' . 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 . '<br><br>' . 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 '<div class=\"notice notice-success\"><p>Visitor locks cleared successfully!</p></div>';\r\n }\r\n echo '<div class=\"wrap\">';\r\n echo '<h1>Clear Visitor Locks</h1>';\r\n echo '<p>This tool clears stuck conversation locks that may be preventing visitors from using the chatbot.</p>';\r\n echo '<p><strong>Use this if visitors are getting \"system is busy processing requests\" messages.</strong></p>';\r\n echo '<form method=\"post\">';\r\n wp_nonce_field( 'clear_visitor_locks' );\r\n echo '<p><input type=\"submit\" name=\"clear_locks\" class=\"button-primary\" value=\"Clear All Visitor Locks\" onclick=\"return confirm(\\'Are you sure you want to clear all visitor locks?\\')\"></p>';\r\n echo '</form>';\r\n echo '</div>';\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": "<?php\r\n/*\r\n * Plugin Name: Kognetiks Chatbot\r\n * Plugin URI: https://github.com/kognetiks/kognetiks-chatbot\r\n * Description: This simple plugin adds an AI powered chatbot to your WordPress website.\r\n * Version: 2.2.0\r\n * Author: Kognetiks.com\r\n * Author URI: https://www.kognetiks.com\r\n * License: GPLv3 or later\r\n * License URI: https://www.gnu.org/licenses/gpl-30.html\r\n * \r\n * Copyright (c) 2024 Stephen Howell\r\n * \r\n * This program is free software; you can redistribute it and/or modify it under the terms of the GNU\r\n * General Public License version 3, as published by the Free Software Foundation. You may NOT assume\r\n * that you can use any other version of the GPL.\r\n * \r\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without\r\n * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\r\n * \r\n * You should have received a copy of the GNU General Public License\r\n * along with Kognetiks Chatbot for WordPress. If not, see https://www.gnu.org/licenses/gpl-3.0.html.\r\n */\r\n\r\n// If this file is called directly, die.\r\ndefined( 'WPINC' ) || die();\r\n\r\n// Start output buffering earlier to prevent \"headers already sent\" issues - Ver 2.1.8\r\nob_start();\r\n\r\n// Plugin version\r\nglobal $chatbot_chatgpt_plugin_version;\r\n$chatbot_chatgpt_plugin_version = '2.2.0';\r\n\r\n// Plugin directory path\r\nglobal $chatbot_chatgpt_plugin_dir_path;\r\n$chatbot_chatgpt_plugin_dir_path = plugin_dir_path( __FILE__ );\r\n\r\n// Plugin directory URL\r\nglobal $chatbot_chatgpt_plugin_dir_url;\r\n$chatbot_chatgpt_plugin_dir_url = plugins_url( '/', __FILE__ );\r\n\r\n// Declare Globals\r\nglobal $wpdb;\r\n\r\n// Uniquely Identify the Visitor\r\nglobal $session_id;\r\nglobal $user_id;\r\n\r\n// Assign a unique ID to the visitor and logged-in users - Ver 2.0.4\r\nfunction kognetiks_assign_unique_id() {\r\n if (!isset($_COOKIE['kognetiks_unique_id'])) {\r\n $unique_id = uniqid('kognetiks_', true);\r\n \r\n // Set a cookie using the built-in setcookie function\r\n setcookie('kognetiks_unique_id', $unique_id, time() + (86400 * 30), \"/\", \"\", true, true); // HttpOnly and Secure flags set to true\r\n \r\n // Ensure the cookie is set for the current request\r\n $_COOKIE['kognetiks_unique_id'] = $unique_id;\r\n }\r\n}\r\nadd_action('init', 'kognetiks_assign_unique_id', 1); // Set higher priority\r\n\r\n// Get the unique ID of the visitor or logged-in user - Ver 2.0.4\r\nfunction kognetiks_get_unique_id() {\r\n if (isset($_COOKIE['kognetiks_unique_id'])) {\r\n // error_log('Unique ID found: ' . $_COOKIE['kognetiks_unique_id']);\r\n return sanitize_text_field($_COOKIE['kognetiks_unique_id']);\r\n }\r\n // error_log('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\nif (empty($user_id) || $user_id == 0) {\r\n $user_id = $session_id;\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-ant-api.php'; // ANT API - Ver 2.0.7\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'; // 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-mc-api.php'; // Markov Chain API - Ver 2.1.6\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/chatbot-call-nvi-api.php'; // NVIDIA API - Ver 2.1.8\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-tm-api.php'; // Transformer Model API - Ver 2.2.0\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-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 - Markov Chain - Ver 2.1.9\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/markov-chain/chatbot-markov-chain-decode.php'; // Functions - Ver 2.1.9\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/markov-chain/chatbot-markov-chain-encode.php'; // Functions - Ver 2.1.9\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/markov-chain/chatbot-markov-chain-scheduler.php'; // Functions - Ver 2.1.9\r\n\r\n// Include necessary files - Transformer Model - Ver 2.2.0\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/transformers/lexical-context-model.php'; // Functions - Ver 2.2.0\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/transformers/sentential-context-model.php'; // Functions - Ver 2.2.0\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/transformers/transformer-model-scheduler.php'; // Functions - Ver 2.2.0\r\n\r\n// Include necessary files - Settings\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-api-chatgpt.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-api-nvidia.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-markov-chain.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-tools.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-transformer-model.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-assistants.php'; // Assistants Management - Ver 2.0.4\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-options-helper.php'; // Functions - Ver 2.0.5\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\n// Include necessary files - Tools - Ver 2.0.6\r\nrequire_once plugin_dir_path(__FILE__) . 'tools/chatbot-capability-tester.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'tools/chatbot-manage-error-logs.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'tools/chatbot-options-exporter.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'tools/chatbot-shortcode-tester.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'tools/chatbot-shortcode-tester-tool.php';\r\n\r\n// Include necessary files - Widgets - Ver 2.1.3\r\nrequire_once plugin_dir_path(__FILE__) . 'widgets/chatbot-manage-widget-logs.php';\r\n\r\n// Log the User ID and Session ID - Ver 2.0.6 - 2024 07 11\r\n// back_trace( 'NOTICE', '$user_id: ' . $user_id);\r\n// back_trace( 'NOTICE', '$session_id: ' . $session_id);\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\nglobal $chatbot_ai_platform_choice;\r\nglobal $model;\r\nglobal $voice;\r\n\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\r\n// OpenAI ChatGPT API Enabled - Ver 2.1.8\r\nif ($chatbot_ai_platform_choice == 'OpenAI' || $chatbot_ai_platform_choice === null) {\r\n\r\n $chatbot_chatgpt_api_enabled = 'Yes';\r\n update_option('chatbot_chatgpt_api_enabled', 'Yes');\r\n update_option('chatbot_ai_platform_choice', 'OpenAI');\r\n\r\n $chatbot_nvidia_api_enabled = 'No';\r\n update_option('chatbot_nvidia_api_enabled', 'No');\r\n\r\n $chatbot_markov_chain_api_enabled = 'No';\r\n update_option('chatbot_markov_chain_api_enabled', 'No');\r\n\r\n $chatbot_transformer_model_api_enabled = 'No';\r\n update_option('chatbot_transformer_model_api_enabled', 'No');\r\n\r\n $chatbot_anthropic_api_enabled = 'No';\r\n update_option('chatbot_anthropic_api_enabled', 'No');\r\n\r\n // Model choice - Ver 1.9.4\r\n if (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 // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Model upgraded: ' . $model);\r\n } elseif (empty($model)) {\r\n $model = 'gpt-4-1106-preview';\r\n }\r\n\r\n // Voice choice - Ver 1.9.5\r\n if (get_option('chatbot_chatgpt_voice_option') === null) {\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// NVIDIA NIM API Enabled - Ver 2.1.8\r\n} elseif ($chatbot_ai_platform_choice == 'NVIDIA') {\r\n\r\n $chatbot_nvidia_api_enabled = 'Yes';\r\n update_option('chatbot_nvidia_api_enabled', 'Yes');\r\n update_option('chatbot_ai_platform_choice', 'NVIDIA');\r\n\r\n $chatbot_chatgpt_api_enabled = 'No';\r\n update_option('chatbot_chatgpt_api_enabled', 'No');\r\n\r\n $chatbot_markov_chain_api_enabled = 'No';\r\n update_option('chatbot_markov_chain_api_enabled', 'No');\r\n\r\n // Model choice - Ver 2.1.8\r\n if (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 // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Model upgraded: ' . $model);\r\n } elseif (empty($model)) {\r\n $model = 'nvidia/llama-3.1-nemotron-51b-instruct';\r\n }\r\n\r\n// Markov Chain API Enabled - Ver 2.1.8\r\n} elseif ($chatbot_ai_platform_choice == 'Markov Chain') {\r\n\r\n $chatbot_markov_chain_api_enabled = 'Yes';\r\n update_option('chatbot_markov_chain_api_enabled', 'Yes');\r\n update_option('chatbot_ai_platform_choice', 'Markov Chain');\r\n\r\n $chatbot_nvidia_api_enabled = 'No';\r\n update_option('chatbot_nvidia_api_enabled', 'No');\r\n\r\n $chatbot_chatgpt_api_enabled = 'No';\r\n update_option('chatbot_chatgpt_api_enabled', 'No');\r\n\r\n // Model choice - Ver 2.1.8\r\n if (get_option('chatbot_markov_chain_model_choice') === null) {\r\n $model = 'markov-chain-2024-09-17';\r\n update_option('chatbot_markov_chain_model_choice', $model);\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Model upgraded: ' . $model);\r\n } elseif (empty($model)) {\r\n $model = 'markov-chain-2024-09-17';\r\n }\r\n \r\n} elseif ($chatbot_ai_platform_choice == 'Transformer') {\r\n\r\n $chatbot_transformer_model_api_enabled = 'Yes';\r\n update_option('chatbot_transformer_model_api_enabled', 'Yes');\r\n update_option('chatbot_ai_platform_choice', 'Transformer');\r\n\r\n $chatbot_nvidia_api_enabled = 'No';\r\n update_option('chatbot_nvidia_api_enabled', 'No');\r\n\r\n $chatbot_chatgpt_api_enabled = 'No';\r\n update_option('chatbot_chatgpt_api_enabled', 'No');\r\n\r\n $chatbot_markov_chain_api_enabled = 'No';\r\n update_option('chatbot_markov_chain_api_enabled', 'No');\r\n\r\n // Model choice - Ver 2.2.0\r\n if (get_option('chatbot_transformer_model_choice') === null) {\r\n $model = 'sentential-context-model';\r\n update_option('chatbot_transformer_model_choice', $model);\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Model upgraded: ' . $model);\r\n } elseif (empty($model)) {\r\n $model = 'sentential-context-model';\r\n }\r\n\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$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', 'On'));\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\r\n global $chatbot_chatgpt_plugin_version;\r\n\r\n wp_enqueue_script('jquery'); // Ensure jQuery is enqueued\r\n wp_enqueue_script('chatbot_chatgpt_admin', plugins_url('assets/js/chatbot-chatgpt-admin.js', __FILE__), array('jquery'), $chatbot_chatgpt_plugin_version, true);\r\n\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 $chatbot_chatgpt_plugin_dir_url;\r\n global $chatbot_chatgpt_plugin_version;\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 $kchat_settings;\r\n global $additional_instructions;\r\n global $model;\r\n global $voice;\r\n\r\n global $chatbot_chatgpt_display_style;\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__), array(), $chatbot_chatgpt_plugin_version, '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\r\n // Enqueue the scripts\r\n wp_enqueue_script('jquery');\r\n wp_enqueue_script('chatbot-chatgpt-js', plugins_url('assets/js/chatbot-chatgpt.js', __FILE__), array('jquery'), $chatbot_chatgpt_plugin_version, 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(), $chatbot_chatgpt_plugin_version, 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 // 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 // back_trace( 'NOTICE', '$user_id: ' . $user_id);\r\n // back_trace( 'NOTICE', '$session_id: ' . $session_id);\r\n\r\n // Check if the $kchat_settings array is empty\r\n if (is_null($kchat_settings)) {\r\n $kchat_settings = [];\r\n }\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 ));\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 . '<br><br>' . 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 . '<br><br>' . 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": "<?php\r\n/*\r\n * Plugin Name: Kognetiks Chatbot\r\n * Plugin URI: https://github.com/kognetiks/kognetiks-chatbot\r\n * Description: This simple plugin adds an AI powered chatbot to your WordPress website.\r\n * Version: 2.1.9\r\n * Author: Kognetiks.com\r\n * Author URI: https://www.kognetiks.com\r\n * License: GPLv3 or later\r\n * License URI: https://www.gnu.org/licenses/gpl-30.html\r\n * \r\n * Copyright (c) 2024 Stephen Howell\r\n * \r\n * This program is free software; you can redistribute it and/or modify it under the terms of the GNU\r\n * General Public License version 3, as published by the Free Software Foundation. You may NOT assume\r\n * that you can use any other version of the GPL.\r\n * \r\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without\r\n * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\r\n * \r\n * You should have received a copy of the GNU General Public License\r\n * along with Kognetiks Chatbot for WordPress. If not, see https://www.gnu.org/licenses/gpl-3.0.html.\r\n */\r\n\r\n// If this file is called directly, die.\r\ndefined( 'WPINC' ) || die();\r\n\r\n// Start output buffering earlier to prevent \"headers already sent\" issues - Ver 2.1.8\r\nob_start();\r\n\r\n// Plugin version\r\nglobal $chatbot_chatgpt_plugin_version;\r\n$chatbot_chatgpt_plugin_version = '2.1.9';\r\n\r\n// Plugin directory path\r\nglobal $chatbot_chatgpt_plugin_dir_path;\r\n$chatbot_chatgpt_plugin_dir_path = plugin_dir_path( __FILE__ );\r\n\r\n// Plugin directory URL\r\nglobal $chatbot_chatgpt_plugin_dir_url;\r\n$chatbot_chatgpt_plugin_dir_url = plugins_url( '/', __FILE__ );\r\n\r\n// Declare Globals\r\nglobal $wpdb;\r\n\r\n// Uniquely Identify the Visitor\r\nglobal $session_id;\r\nglobal $user_id;\r\n\r\n// Assign a unique ID to the visitor and logged-in users - Ver 2.0.4\r\nfunction kognetiks_assign_unique_id() {\r\n if (!isset($_COOKIE['kognetiks_unique_id'])) {\r\n $unique_id = uniqid('kognetiks_', true);\r\n \r\n // Set a cookie using the built-in setcookie function\r\n setcookie('kognetiks_unique_id', $unique_id, time() + (86400 * 30), \"/\", \"\", true, true); // HttpOnly and Secure flags set to true\r\n \r\n // Ensure the cookie is set for the current request\r\n $_COOKIE['kognetiks_unique_id'] = $unique_id;\r\n }\r\n}\r\nadd_action('init', 'kognetiks_assign_unique_id', 1); // Set higher priority\r\n\r\n// Get the unique ID of the visitor or logged-in user - Ver 2.0.4\r\nfunction kognetiks_get_unique_id() {\r\n if (isset($_COOKIE['kognetiks_unique_id'])) {\r\n // error_log('Unique ID found: ' . $_COOKIE['kognetiks_unique_id']);\r\n return sanitize_text_field($_COOKIE['kognetiks_unique_id']);\r\n }\r\n // error_log('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\nif (empty($user_id) || $user_id == 0) {\r\n $user_id = $session_id;\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-ant-api.php'; // ANT API - Ver 2.0.7\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'; // 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-mc-api.php'; // Markov Chain API - Ver 2.1.6\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/chatbot-call-nvi-api.php'; // NVIDIA API - Ver 2.1.8\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-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 - Markov Chain - Ver 2.1.9\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/markov-chain/chatbot-markov-chain-decode.php'; // Functions - Ver 2.1.9\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/markov-chain/chatbot-markov-chain-encode.php'; // Functions - Ver 2.1.9\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/markov-chain/chatbot-markov-chain-scheduler.php'; // Functions - Ver 2.1.9\r\n\r\n// Include necessary files - Settings\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-api-chatgpt.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'includes/settings/chatbot-settings-api-nvidia.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-markov-chain.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-tools.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-assistants.php'; // Assistants Management - Ver 2.0.4\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-options-helper.php'; // Functions - Ver 2.0.5\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\n// Include necessary files - Tools - Ver 2.0.6\r\nrequire_once plugin_dir_path(__FILE__) . 'tools/chatbot-capability-tester.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'tools/chatbot-manage-error-logs.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'tools/chatbot-options-exporter.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'tools/chatbot-shortcode-tester.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'tools/chatbot-shortcode-tester-tool.php';\r\n\r\n// Include necessary files - Widgets - Ver 2.1.3\r\nrequire_once plugin_dir_path(__FILE__) . 'widgets/chatbot-manage-widget-logs.php';\r\n\r\n// Log the User ID and Session ID - Ver 2.0.6 - 2024 07 11\r\n// back_trace( 'NOTICE', '$user_id: ' . $user_id);\r\n// back_trace( 'NOTICE', '$session_id: ' . $session_id);\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\nglobal $chatbot_ai_platform_choice;\r\nglobal $model;\r\nglobal $voice;\r\n\r\n// FIXME - SEE AI Platform Selection setting - Ver 2.1.8\r\nif (esc_attr(get_option('chatbot_ai_platform_choice')) === null) {\r\n\r\n $chatbot_ai_platform_choice = 'OpenAI';\r\n update_option('chatbot_ai_platform_choice', 'OpenAI');\r\n update_option('chatbot_chatgpt_api_enabled', 'Yes');\r\n $chatbot_chatgpt_api_enabled = 'Yes';\r\n\r\n update_option('chatbot_nvidia_api_enabled', 'No');\r\n $chatbot_nvidia_api_enabled = 'No';\r\n\r\n update_option('chatbot_markov_chain_api_enabled', 'No');\r\n $chatbot_nvidia_api_enabled = 'No';\r\n \r\n update_option('chatbot_anthropic_api_enabled', 'No');\r\n $chatbot_anthropic_api_enabled = 'No';\r\n\r\n}\r\n\r\n$chatbot_ai_platform_choice = esc_attr(get_option('chatbot_ai_platform_choice', 'OpenAI'));\r\n\r\n// OpenAI ChatGPT API Enabled - Ver 2.1.8\r\nif ($chatbot_ai_platform_choice == 'OpenAI') {\r\n\r\n $chatbot_chatgpt_api_enabled = 'Yes';\r\n update_option('chatbot_chatgpt_api_enabled', 'Yes');\r\n update_option('chatbot_ai_platform_choice', 'OpenAI');\r\n\r\n $chatbot_nvidia_api_enabled = 'No';\r\n update_option('chatbot_nvidia_api_enabled', 'No');\r\n\r\n $chatbot_markov_chain_api_enabled = 'No';\r\n update_option('chatbot_markov_chain_api_enabled', 'No');\r\n\r\n // Model choice - Ver 1.9.4\r\n if (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 // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Model upgraded: ' . $model);\r\n }\r\n\r\n // Voice choice - Ver 1.9.5\r\n if (get_option('chatbot_chatgpt_voice_option') === null) {\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// NVIDIA NIM API Enabled - Ver 2.1.8\r\n} elseif ($chatbot_ai_platform_choice == 'NVIDIA') {\r\n\r\n $chatbot_nvidia_api_enabled = 'Yes';\r\n update_option('chatbot_nvidia_api_enabled', 'Yes');\r\n update_option('chatbot_ai_platform_choice', 'NVIDIA');\r\n\r\n $chatbot_chatgpt_api_enabled = 'No';\r\n update_option('chatbot_chatgpt_api_enabled', 'No');\r\n\r\n $chatbot_markov_chain_api_enabled = 'No';\r\n update_option('chatbot_markov_chain_api_enabled', 'No');\r\n\r\n // Model choice - Ver 2.1.8\r\n if (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 // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Model upgraded: ' . $model);\r\n }\r\n\r\n// Markov Chain API Enabled - Ver 2.1.8\r\n} elseif ($chatbot_ai_platform_choice == 'Markov Chain') {\r\n\r\n $chatbot_markov_chain_api_enabled = 'Yes';\r\n update_option('chatbot_markov_chain_api_enabled', 'Yes');\r\n update_option('chatbot_ai_platform_choice', 'Markov Chain');\r\n\r\n $chatbot_nvidia_api_enabled = 'No';\r\n update_option('chatbot_nvidia_api_enabled', 'No');\r\n\r\n $chatbot_chatgpt_api_enabled = 'No';\r\n update_option('chatbot_chatgpt_api_enabled', 'No');\r\n\r\n // Model choice - Ver 2.1.8\r\n if (get_option('chatbot_markov_chain_model_choice') === null) {\r\n $model = 'markov-chain-2024-09-17';\r\n update_option('chatbot_markov_chain_model_choice', $model);\r\n // DIAG - Diagnostics\r\n // back_trace( 'NOTICE', 'Model upgraded: ' . $model);\r\n }\r\n \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$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', 'On'));\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\r\n global $chatbot_chatgpt_plugin_version;\r\n\r\n wp_enqueue_script('jquery'); // Ensure jQuery is enqueued\r\n wp_enqueue_script('chatbot_chatgpt_admin', plugins_url('assets/js/chatbot-chatgpt-admin.js', __FILE__), array('jquery'), $chatbot_chatgpt_plugin_version, true);\r\n\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 $chatbot_chatgpt_plugin_dir_url;\r\n global $chatbot_chatgpt_plugin_version;\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 $kchat_settings;\r\n global $additional_instructions;\r\n global $model;\r\n global $voice;\r\n\r\n global $chatbot_chatgpt_display_style;\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__), array(), $chatbot_chatgpt_plugin_version, '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\r\n // Enqueue the scripts\r\n wp_enqueue_script('jquery');\r\n wp_enqueue_script('chatbot-chatgpt-js', plugins_url('assets/js/chatbot-chatgpt.js', __FILE__), array('jquery'), $chatbot_chatgpt_plugin_version, 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(), $chatbot_chatgpt_plugin_version, 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 // 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 // back_trace( 'NOTICE', '$user_id: ' . $user_id);\r\n // back_trace( 'NOTICE', '$session_id: ' . $session_id);\r\n\r\n // Check if the $kchat_settings array is empty\r\n if (is_null($kchat_settings)) {\r\n $kchat_settings = [];\r\n }\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 ));\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 . '<br><br>' . 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 . '<br><br>' . 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": "<?php\r\n/*\r\n * Plugin Name: Kognetiks Chatbot\r\n * Plugin URI: https://github.com/kognetiks/kognetiks-chatbot\r\n * Description: This simple plugin adds an AI powered chatbot to your WordPress website.\r\n * Version: 2.1.5\r\n * Author: Kognetiks.com\r\n * Author URI: https://www.kognetiks.com\r\n * License: GPLv3 or later\r\n * License URI: https://www.gnu.org/licenses/gpl-30.html\r\n * \r\n * Copyright (c) 2024 Stephen Howell\r\n * \r\n * This program is free software; you can redistribute it and/or modify it under the terms of the GNU\r\n * General Public License version 3, as published by the Free Software Foundation. You may NOT assume\r\n * that you can use any other version of the GPL.\r\n * \r\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without\r\n * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\r\n * \r\n * You should have received a copy of the GNU General Public License\r\n * along with Kognetiks Chatbot for WordPress. If not, see https://www.gnu.org/licenses/gpl-3.0.html.\r\n * \r\n*/\r\n\r\n// If this file is called directly, die.\r\ndefined( 'WPINC' ) || die();\r\n\r\nif ( ! defined( 'ABSPATH' ) ) {\r\n\tdie();\r\n}\r\n\r\n// Plugin version\r\nglobal $chatbot_chatgpt_plugin_version;\r\n$chatbot_chatgpt_plugin_version = '2.1.5';\r\n\r\n// Plugin directory path\r\nglobal $chatbot_chatgpt_plugin_dir_path;\r\n$chatbot_chatgpt_plugin_dir_path = plugin_dir_path( __FILE__ );\r\n\r\n// Plugin directory URL\r\nglobal $chatbot_chatgpt_plugin_dir_url;\r\n$chatbot_chatgpt_plugin_dir_url = plugins_url( '/', __FILE__ );\r\n\r\n// Declare Globals\r\nglobal $wpdb;\r\n\r\n// Uniquely Identify the Visitor\r\nglobal $session_id;\r\nglobal $user_id;\r\n\r\n// Start output buffering to prevent \"headers already sent\" issues - Ver 1.8.5\r\nob_start();\r\n\r\n// Assign a unique ID to the visitor and logged-in users - Ver 2.0.4\r\nfunction kognetiks_assign_unique_id() {\r\n if (!isset($_COOKIE['kognetiks_unique_id'])) {\r\n $unique_id = uniqid('kognetiks_', true);\r\n \r\n // Use the build-in setcookie function\r\n // setcookie('kognetiks_unique_id', $unique_id, time() + (86400 * 30), \"/\"); // Cookie expires in 30 days\r\n\r\n // Use the build-in setcookie function - Sets HttpOnly and Secure flags\r\n // setcookie('kognetiks_unique_id', $unique_id, time() + (86400 * 30), \"/\", \"\", true, true); // HttpOnly and Secure flags set to true\r\n \r\n // Set SameSite attribute manually\r\n // Sets HttpOnly, Secure, and SameSite = Strict, Lax or None\r\n header('Set-Cookie: kognetiks_unique_id=' . $unique_id . '; expires=' . gmdate('D, d M Y H:i:s T', time() + (86400 * 30)) . '; path=/; HttpOnly; Secure; SameSite=Lax');\r\n \r\n // Ensure the cookie is set for the current request\r\n $_COOKIE['kognetiks_unique_id'] = $unique_id;\r\n }\r\n}\r\nadd_action('init', 'kognetiks_assign_unique_id');\r\n\r\n// Get the unique ID of the visitor or logged-in user - Ver 2.0.4\r\nfunction kognetiks_get_unique_id() {\r\n if (isset($_COOKIE['kognetiks_unique_id'])) {\r\n // error_log('Unique ID found: ' . $_COOKIE['kognetiks_unique_id']);\r\n return sanitize_text_field($_COOKIE['kognetiks_unique_id']);\r\n }\r\n // error_log('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\nif (empty($user_id) || $user_id == 0) {\r\n $user_id = $session_id;\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-ant-api.php'; // ANT API - Ver 2.0.7\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'; // 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-tools.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-assistants.php'; // Assistants Management - Ver 2.0.4\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-options-helper.php'; // Functions - Ver 2.0.5\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\n// Include necessary files - Tools - Ver 2.0.6\r\nrequire_once plugin_dir_path(__FILE__) . 'tools/chatbot-capability-tester.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'tools/chatbot-manage-error-logs.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'tools/chatbot-options-exporter.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'tools/chatbot-shortcode-tester.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'tools/chatbot-shortcode-tester-tool.php';\r\n\r\n// Include necessary files - Widgets - Ver 2.1.3\r\nrequire_once plugin_dir_path(__FILE__) . 'widgets/chatbot-manage-widget-logs.php';\r\n\r\n// Log the User ID and Session ID - Ver 2.0.6 - 2024 07 11\r\n// back_trace( 'NOTICE', '$user_id: ' . $user_id);\r\n// back_trace( 'NOTICE', '$session_id: ' . $session_id);\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$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', 'On'));\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\r\n global $chatbot_chatgpt_plugin_version;\r\n\r\n wp_enqueue_script('jquery'); // Ensure jQuery is enqueued\r\n wp_enqueue_script('chatbot_chatgpt_admin', plugins_url('assets/js/chatbot-chatgpt-admin.js', __FILE__), array('jquery'), $chatbot_chatgpt_plugin_version, 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 $chatbot_chatgpt_plugin_dir_url;\r\n global $chatbot_chatgpt_plugin_version;\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 $kchat_settings;\r\n global $additional_instructions;\r\n global $model;\r\n global $voice;\r\n\r\n global $chatbot_chatgpt_display_style;\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__), array(), $chatbot_chatgpt_plugin_version, '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\r\n // Enqueue the scripts\r\n wp_enqueue_script('jquery');\r\n wp_enqueue_script('chatbot-chatgpt-js', plugins_url('assets/js/chatbot-chatgpt.js', __FILE__), array('jquery'), $chatbot_chatgpt_plugin_version, 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(), $chatbot_chatgpt_plugin_version, 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 // 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 // back_trace( 'NOTICE', '$user_id: ' . $user_id);\r\n // back_trace( 'NOTICE', '$session_id: ' . $session_id);\r\n\r\n // Check if the $kchat_settings array is empty\r\n if (is_null($kchat_settings)) {\r\n $kchat_settings = [];\r\n }\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 ));\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": "<?php\r\n/*\r\n * Plugin Name: Kognetiks Chatbot\r\n * Plugin URI: https://github.com/kognetiks/kognetiks-chatbot\r\n * Description: This simple plugin adds an AI powered chatbot to your WordPress website.\r\n * Version: 2.1.4\r\n * Author: Kognetiks.com\r\n * Author URI: https://www.kognetiks.com\r\n * License: GPLv3 or later\r\n * License URI: https://www.gnu.org/licenses/gpl-30.html\r\n * \r\n * Copyright (c) 2024 Stephen Howell\r\n * \r\n * This program is free software; you can redistribute it and/or modify it under the terms of the GNU\r\n * General Public License version 3, as published by the Free Software Foundation. You may NOT assume\r\n * that you can use any other version of the GPL.\r\n * \r\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without\r\n * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\r\n * \r\n * You should have received a copy of the GNU General Public License\r\n * along with Kognetiks Chatbot for WordPress. If not, see https://www.gnu.org/licenses/gpl-3.0.html.\r\n * \r\n*/\r\n\r\n// If this file is called directly, die.\r\ndefined( 'WPINC' ) || die();\r\n\r\nif ( ! defined( 'ABSPATH' ) ) {\r\n\tdie();\r\n}\r\n\r\n// Plugin version\r\nglobal $chatbot_chatgpt_plugin_version;\r\n$chatbot_chatgpt_plugin_version = '2.1.4';\r\n\r\n// Plugin directory path\r\nglobal $chatbot_chatgpt_plugin_dir_path;\r\n$chatbot_chatgpt_plugin_dir_path = plugin_dir_path( __FILE__ );\r\n\r\n// Plugin directory URL\r\nglobal $chatbot_chatgpt_plugin_dir_url;\r\n$chatbot_chatgpt_plugin_dir_url = plugins_url( '/', __FILE__ );\r\n\r\n// Declare Globals\r\nglobal $wpdb;\r\n\r\n// Uniquely Identify the Visitor\r\nglobal $session_id;\r\nglobal $user_id;\r\n\r\n// Start output buffering to prevent \"headers already sent\" issues - Ver 1.8.5\r\nob_start();\r\n\r\n// Assign a unique ID to the visitor and logged-in users - Ver 2.0.4\r\nfunction kognetiks_assign_unique_id() {\r\n if (!isset($_COOKIE['kognetiks_unique_id'])) {\r\n $unique_id = uniqid('kognetiks_', true);\r\n \r\n // Use the build-in setcookie function\r\n // setcookie('kognetiks_unique_id', $unique_id, time() + (86400 * 30), \"/\"); // Cookie expires in 30 days\r\n\r\n // Use the build-in setcookie function - Sets HttpOnly and Secure flags\r\n // setcookie('kognetiks_unique_id', $unique_id, time() + (86400 * 30), \"/\", \"\", true, true); // HttpOnly and Secure flags set to true\r\n \r\n // Set SameSite attribute manually\r\n // Sets HttpOnly, Secure, and SameSite = Strict, Lax or None\r\n header('Set-Cookie: kognetiks_unique_id=' . $unique_id . '; expires=' . gmdate('D, d M Y H:i:s T', time() + (86400 * 30)) . '; path=/; HttpOnly; Secure; SameSite=Lax');\r\n \r\n // Ensure the cookie is set for the current request\r\n $_COOKIE['kognetiks_unique_id'] = $unique_id;\r\n }\r\n}\r\nadd_action('init', 'kognetiks_assign_unique_id');\r\n\r\n// Get the unique ID of the visitor or logged-in user - Ver 2.0.4\r\nfunction kognetiks_get_unique_id() {\r\n if (isset($_COOKIE['kognetiks_unique_id'])) {\r\n // error_log('Unique ID found: ' . $_COOKIE['kognetiks_unique_id']);\r\n return sanitize_text_field($_COOKIE['kognetiks_unique_id']);\r\n }\r\n // error_log('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\nif (empty($user_id) || $user_id == 0) {\r\n $user_id = $session_id;\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-ant-api.php'; // ANT API - Ver 2.0.7\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'; // 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-tools.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-assistants.php'; // Assistants Management - Ver 2.0.4\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-options-helper.php'; // Functions - Ver 2.0.5\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\n// Include necessary files - Tools - Ver 2.0.6\r\nrequire_once plugin_dir_path(__FILE__) . 'tools/chatbot-capability-tester.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'tools/chatbot-manage-error-logs.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'tools/chatbot-options-exporter.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'tools/chatbot-shortcode-tester.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'tools/chatbot-shortcode-tester-tool.php';\r\n\r\n// Include necessary files - Widgets - Ver 2.1.3\r\nrequire_once plugin_dir_path(__FILE__) . 'widgets/chatbot-manage-widget-logs.php';\r\n\r\n// Log the User ID and Session ID - Ver 2.0.6 - 2024 07 11\r\n// back_trace( 'NOTICE', '$user_id: ' . $user_id);\r\n// back_trace( 'NOTICE', '$session_id: ' . $session_id);\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$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\r\n global $chatbot_chatgpt_plugin_version;\r\n\r\n wp_enqueue_script('jquery'); // Ensure jQuery is enqueued\r\n wp_enqueue_script('chatbot_chatgpt_admin', plugins_url('assets/js/chatbot-chatgpt-admin.js', __FILE__), array('jquery'), $chatbot_chatgpt_plugin_version, 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 $chatbot_chatgpt_plugin_dir_url;\r\n global $chatbot_chatgpt_plugin_version;\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 $kchat_settings;\r\n global $additional_instructions;\r\n global $model;\r\n global $voice;\r\n\r\n global $chatbot_chatgpt_display_style;\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__), array(), $chatbot_chatgpt_plugin_version, '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\r\n // Enqueue the scripts\r\n wp_enqueue_script('jquery');\r\n wp_enqueue_script('chatbot-chatgpt-js', plugins_url('assets/js/chatbot-chatgpt.js', __FILE__), array('jquery'), $chatbot_chatgpt_plugin_version, 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(), $chatbot_chatgpt_plugin_version, 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 // 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 // back_trace( 'NOTICE', '$user_id: ' . $user_id);\r\n // back_trace( 'NOTICE', '$session_id: ' . $session_id);\r\n\r\n // Check if the $kchat_settings array is empty\r\n if (is_null($kchat_settings)) {\r\n $kchat_settings = [];\r\n }\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 ));\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": "<?php\r\n/*\r\n * Plugin Name: Kognetiks Chatbot\r\n * Plugin URI: https://github.com/kognetiks/kognetiks-chatbot\r\n * Description: This simple plugin adds an AI powered chatbot to your WordPress website.\r\n * Version: 2.1.4\r\n * Author: Kognetiks.com\r\n * Author URI: https://www.kognetiks.com\r\n * License: GPLv3 or later\r\n * License URI: https://www.gnu.org/licenses/gpl-30.html\r\n * \r\n * Copyright (c) 2024 Stephen Howell\r\n * \r\n * This program is free software; you can redistribute it and/or modify it under the terms of the GNU\r\n * General Public License version 3, as published by the Free Software Foundation. You may NOT assume\r\n * that you can use any other version of the GPL.\r\n * \r\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without\r\n * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\r\n * \r\n * You should have received a copy of the GNU General Public License\r\n * along with Kognetiks Chatbot for WordPress. If not, see https://www.gnu.org/licenses/gpl-3.0.html.\r\n * \r\n*/\r\n\r\n// If this file is called directly, die.\r\ndefined( 'WPINC' ) || die();\r\n\r\nif ( ! defined( 'ABSPATH' ) ) {\r\n\tdie();\r\n}\r\n\r\n// Plugin version\r\nglobal $chatbot_chatgpt_plugin_version;\r\n$chatbot_chatgpt_plugin_version = '2.1.4';\r\n\r\n// Plugin directory path\r\nglobal $chatbot_chatgpt_plugin_dir_path;\r\n$chatbot_chatgpt_plugin_dir_path = plugin_dir_path( __FILE__ );\r\n\r\n// Plugin directory URL\r\nglobal $chatbot_chatgpt_plugin_dir_url;\r\n$chatbot_chatgpt_plugin_dir_url = plugins_url( '/', __FILE__ );\r\n\r\n// Declare Globals\r\nglobal $wpdb;\r\n\r\n// Uniquely Identify the Visitor\r\nglobal $session_id;\r\nglobal $user_id;\r\n\r\n// Start output buffering to prevent \"headers already sent\" issues - Ver 1.8.5\r\nob_start();\r\n\r\n// Assign a unique ID to the visitor and logged-in users - Ver 2.0.4\r\nfunction kognetiks_assign_unique_id() {\r\n if (!isset($_COOKIE['kognetiks_unique_id'])) {\r\n $unique_id = uniqid('kognetiks_', true);\r\n \r\n // Use the build-in setcookie function\r\n // setcookie('kognetiks_unique_id', $unique_id, time() + (86400 * 30), \"/\"); // Cookie expires in 30 days\r\n\r\n // Use the build-in setcookie function - Sets HttpOnly and Secure flags\r\n // setcookie('kognetiks_unique_id', $unique_id, time() + (86400 * 30), \"/\", \"\", true, true); // HttpOnly and Secure flags set to true\r\n \r\n // Set SameSite attribute manually\r\n // Sets HttpOnly, Secure, and SameSite = Strict, Lax or None\r\n header('Set-Cookie: kognetiks_unique_id=' . $unique_id . '; expires=' . gmdate('D, d M Y H:i:s T', time() + (86400 * 30)) . '; path=/; HttpOnly; Secure; SameSite=Lax');\r\n \r\n // Ensure the cookie is set for the current request\r\n $_COOKIE['kognetiks_unique_id'] = $unique_id;\r\n }\r\n}\r\nadd_action('init', 'kognetiks_assign_unique_id');\r\n\r\n// Get the unique ID of the visitor or logged-in user - Ver 2.0.4\r\nfunction kognetiks_get_unique_id() {\r\n if (isset($_COOKIE['kognetiks_unique_id'])) {\r\n // error_log('Unique ID found: ' . $_COOKIE['kognetiks_unique_id']);\r\n return sanitize_text_field($_COOKIE['kognetiks_unique_id']);\r\n }\r\n // error_log('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\nif (empty($user_id) || $user_id == 0) {\r\n $user_id = $session_id;\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-ant-api.php'; // ANT API - Ver 2.0.7\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'; // 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-tools.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-assistants.php'; // Assistants Management - Ver 2.0.4\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-options-helper.php'; // Functions - Ver 2.0.5\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\n// Include necessary files - Tools - Ver 2.0.6\r\nrequire_once plugin_dir_path(__FILE__) . 'tools/chatbot-capability-tester.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'tools/chatbot-manage-error-logs.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'tools/chatbot-options-exporter.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'tools/chatbot-shortcode-tester.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'tools/chatbot-shortcode-tester-tool.php';\r\n\r\n// Include necessary files - Widgets - Ver 2.1.3\r\nrequire_once plugin_dir_path(__FILE__) . 'widgets/chatbot-manage-widget-logs.php';\r\n\r\n// Log the User ID and Session ID - Ver 2.0.6 - 2024 07 11\r\n// back_trace( 'NOTICE', '$user_id: ' . $user_id);\r\n// back_trace( 'NOTICE', '$session_id: ' . $session_id);\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$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\r\n global $chatbot_chatgpt_plugin_version;\r\n\r\n wp_enqueue_script('jquery'); // Ensure jQuery is enqueued\r\n wp_enqueue_script('chatbot_chatgpt_admin', plugins_url('assets/js/chatbot-chatgpt-admin.js', __FILE__), array('jquery'), $chatbot_chatgpt_plugin_version, 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 $chatbot_chatgpt_plugin_dir_url;\r\n global $chatbot_chatgpt_plugin_version;\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 $kchat_settings;\r\n global $additional_instructions;\r\n global $model;\r\n global $voice;\r\n\r\n global $chatbot_chatgpt_display_style;\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__), array(), $chatbot_chatgpt_plugin_version, '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\r\n // Enqueue the scripts\r\n wp_enqueue_script('jquery');\r\n wp_enqueue_script('chatbot-chatgpt-js', plugins_url('assets/js/chatbot-chatgpt.js', __FILE__), array('jquery'), $chatbot_chatgpt_plugin_version, 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(), $chatbot_chatgpt_plugin_version, 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 // 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 // back_trace( 'NOTICE', '$user_id: ' . $user_id);\r\n // back_trace( 'NOTICE', '$session_id: ' . $session_id);\r\n\r\n // Check if the $kchat_settings array is empty\r\n if (is_null($kchat_settings)) {\r\n $kchat_settings = [];\r\n }\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 ));\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": "<?php\r\n/*\r\n * Plugin Name: Kognetiks Chatbot\r\n * Plugin URI: https://github.com/kognetiks/kognetiks-chatbot\r\n * Description: A simple plugin to add an AI powered chatbot to your WordPress website.\r\n * Version: 2.0.6\r\n * Author: Kognetiks.com\r\n * Author URI: https://www.kognetiks.com\r\n * License: GPLv3 or later\r\n * License URI: https://www.gnu.org/licenses/gpl-30.html\r\n * \r\n * Copyright (c) 2024 Stephen Howell\r\n * \r\n * This program is free software; you can redistribute it and/or modify it under the terms of the GNU\r\n * General Public License version 3, as published by the Free Software Foundation. You may NOT assume\r\n * that you can use any other version of the GPL.\r\n * \r\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without\r\n * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\r\n * \r\n * You should have received a copy of the GNU General Public License\r\n * along with Kognetiks Chatbot for WordPress. If not, see https://www.gnu.org/licenses/gpl-3.0.html.\r\n * \r\n*/\r\n\r\n// If this file is called directly, die.\r\ndefined( 'WPINC' ) || die;\r\n\r\nif ( ! defined( 'ABSPATH' ) ) {\r\n\tdie();\r\n}\r\n\r\n// Define the plugin version\r\ndefined ('CHATBOT_CHATGPT_VERSION') || define ('CHATBOT_CHATGPT_VERSION', '2.0.6');\r\n\r\n// Main plugin file\r\ndefine('CHATBOT_CHATGPT_PLUGIN_DIR_PATH', plugin_dir_path(__FILE__));\r\n\r\n// Declare Globals\r\nglobal $wpdb;\r\n\r\n// Uniquely Identify the Visitor\r\nglobal $session_id;\r\nglobal $user_id;\r\n\r\n// Start output buffering to prevent \"headers already sent\" issues - Ver 1.8.5\r\nob_start();\r\n\r\n// Assign a unique ID to the visitor and logged-in users - Ver 2.0.4\r\nfunction kognetiks_assign_unique_id() {\r\n if (!isset($_COOKIE['kognetiks_unique_id'])) {\r\n $unique_id = uniqid('kognetiks_', true);\r\n \r\n // Use the build-in setcookie function\r\n // setcookie('kognetiks_unique_id', $unique_id, time() + (86400 * 30), \"/\"); // Cookie expires in 30 days\r\n\r\n // Use the build-in setcookie function - Sets HttpOnly and Secure flags\r\n // setcookie('kognetiks_unique_id', $unique_id, time() + (86400 * 30), \"/\", \"\", true, true); // HttpOnly and Secure flags set to true\r\n \r\n // Set SameSite attribute manually\r\n // Sets HttpOnly, Secure, and SameSite = Strict, Lax or None\r\n header('Set-Cookie: kognetiks_unique_id=' . $unique_id . '; expires=' . gmdate('D, d M Y H:i:s T', time() + (86400 * 30)) . '; path=/; HttpOnly; Secure; SameSite=Lax');\r\n \r\n // Ensure the cookie is set for the current request\r\n $_COOKIE['kognetiks_unique_id'] = $unique_id;\r\n }\r\n}\r\nadd_action('init', 'kognetiks_assign_unique_id');\r\n\r\n// Get the unique ID of the visitor or logged-in user - Ver 2.0.4\r\nfunction kognetiks_get_unique_id() {\r\n if (isset($_COOKIE['kognetiks_unique_id'])) {\r\n // error_log('Unique ID found: ' . $_COOKIE['kognetiks_unique_id']);\r\n return sanitize_text_field($_COOKIE['kognetiks_unique_id']);\r\n }\r\n // error_log('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\nif (empty($user_id) || $user_id == 0) {\r\n $user_id = $session_id;\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'; // 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-tools.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-assistants.php'; // Assistants Management - Ver 2.0.4\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-options-helper.php'; // Functions - Ver 2.0.5\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\nrequire_once plugin_dir_path(__FILE__) . 'tools/chatbot-capability-tester.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'tools/chatbot-options-exporter.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'tools/chatbot-shortcode-tester.php';\r\nrequire_once plugin_dir_path(__FILE__) . 'tools/chatbot-shortcode-tester-tool.php';\r\n\r\n// Log the User ID and Session ID - Ver 2.0.6 - 2024 07 11\r\n// back_trace( 'NOTICE', '$user_id: ' . $user_id);\r\n// back_trace( 'NOTICE', '$session_id: ' . $session_id);\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-local', plugins_url('assets/js/chatbot-chatgpt-local.js', __FILE__), array('jquery'), '1.0', true);\r\n wp_enqueue_script('greetings', plugins_url('assets/js/greetings.js', __FILE__), array('jquery'), '1.0', true);\r\n wp_enqueue_script('chatbot-chatgpt-js', plugins_url('assets/js/chatbot-chatgpt.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 // 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 // back_trace( 'NOTICE', '$user_id: ' . $user_id);\r\n // back_trace( 'NOTICE', '$session_id: ' . $session_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' => $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": "<?php\r\n/*\r\n * Plugin Name: Kognetiks Chatbot\r\n * Plugin URI: https://github.com/kognetiks/kognetiks-chatbot\r\n * Description: A simple plugin to add an AI powered chatbot to your WordPress website.\r\n * Version: 2.0.5\r\n * Author: Kognetiks.com\r\n * Author URI: https://www.kognetiks.com\r\n * License: GPLv3 or later\r\n * License URI: https://www.gnu.org/licenses/gpl-30.html\r\n * \r\n * Copyright (c) 2024 Stephen Howell\r\n * \r\n * This program is free software; you can redistribute it and/or modify it under the terms of the GNU\r\n * General Public License version 3, as published by the Free Software Foundation. You may NOT assume\r\n * that you can use any other version of the GPL.\r\n * \r\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without\r\n * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\r\n * \r\n * You should have received a copy of the GNU General Public License\r\n * along with Kognetiks Chatbot for WordPress. If not, see https://www.gnu.org/licenses/gpl-3.0.html.\r\n * \r\n*/\r\n\r\n// If this file is called directly, die.\r\ndefined( 'WPINC' ) || die;\r\n\r\nif ( ! defined( 'ABSPATH' ) ) {\r\n\tdie();\r\n}\r\n\r\n// Define the plugin version\r\ndefined ('CHATBOT_CHATGPT_VERSION') || define ('CHATBOT_CHATGPT_VERSION', '2.0.5');\r\n\r\n// Main plugin file\r\ndefine('CHATBOT_CHATGPT_PLUGIN_DIR_PATH', plugin_dir_path(__FILE__));\r\n\r\n// Declare Globals\r\nglobal $wpdb;\r\n\r\n// Uniquely Identify the Visitor\r\nglobal $session_id;\r\nglobal $user_id;\r\n\r\n// Start output buffering to prevent \"headers already sent\" issues - Ver 1.8.5\r\nob_start();\r\n\r\n// Assign a unique ID to the visitor and logged-in users - Ver 2.0.4\r\nfunction kognetiks_assign_unique_id() {\r\n if (!isset($_COOKIE['kognetiks_unique_id'])) {\r\n $unique_id = uniqid('kognetiks_', true);\r\n \r\n // Use the build-in setcookie function\r\n // setcookie('kognetiks_unique_id', $unique_id, time() + (86400 * 30), \"/\"); // Cookie expires in 30 days\r\n\r\n // Use the build-in setcookie function - Sets HttpOnly and Secure flags\r\n // setcookie('kognetiks_unique_id', $unique_id, time() + (86400 * 30), \"/\", \"\", true, true); // HttpOnly and Secure flags set to true\r\n \r\n // Set SameSite attribute manually\r\n // Sets HttpOnly, Secure, and SameSite = Strict, Lax or None\r\n header('Set-Cookie: kognetiks_unique_id=' . $unique_id . '; expires=' . gmdate('D, d M Y H:i:s T', time() + (86400 * 30)) . '; path=/; HttpOnly; Secure; SameSite=Lax');\r\n \r\n // Ensure the cookie is set for the current request\r\n $_COOKIE['kognetiks_unique_id'] = $unique_id;\r\n }\r\n}\r\nadd_action('init', 'kognetiks_assign_unique_id');\r\n\r\n// Get the unique ID of the visitor or logged-in user - Ver 2.0.4\r\nfunction kognetiks_get_unique_id() {\r\n if (isset($_COOKIE['kognetiks_unique_id'])) {\r\n // error_log('Unique ID found: ' . $_COOKIE['kognetiks_unique_id']);\r\n return sanitize_text_field($_COOKIE['kognetiks_unique_id']);\r\n }\r\n // error_log('Unique ID not found');\r\n return null;\r\n}\r\n\r\n// Fetch the unique ID of the visitor or logged-in user - Ver 2.0.4\r\n\r\n$session_id = kognetiks_get_unique_id();\r\n\r\n// Store the unique ID in a global variable - Ver 2.0.4\r\nif (empty($session_id)) {\r\n $session_id = kognetiks_get_unique_id();\r\n}\r\n\r\n$user_id = get_current_user_id();\r\n\r\nif ($user_id == 0) {\r\n $user_id = $session_id;\r\n}\r\n// error_log('Session ID: ' . $session_id);\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'; // 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-assistants.php'; // Assistants Management - Ver 2.0.4\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-options-helper.php'; // Functions - Ver 2.0.5\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\n// User Capability Check - Ver 2.0.5\r\n// function chatbot_chatgpt_check_user_capability() {\r\n\r\n// $capabilities = array(\r\n// 'read',\r\n// 'edit_posts',\r\n// 'publish_posts',\r\n// 'manage_options'\r\n// );\r\n\r\n// foreach ($capabilities as $capability) {\r\n// if (current_user_can($capability)) {\r\n// // back_trace('NOTICE', 'User has the capability: ' . $capability);\r\n// } else {\r\n// // back_trace('ERROR', 'User does not have the capability: ' . $capability);\r\n// }\r\n// }\r\n\r\n// }\r\n// add_action('init', 'chatbot_chatgpt_check_user_capability');\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-local', plugins_url('assets/js/chatbot-chatgpt-local.js', __FILE__), array('jquery'), '1.0', true);\r\n wp_enqueue_script('greetings', plugins_url('assets/js/greetings.js', __FILE__), array('jquery'), '1.0', true);\r\n wp_enqueue_script('chatbot-chatgpt-js', plugins_url('assets/js/chatbot-chatgpt.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 // if user is not logged in, then set user_id to $session_id\r\n if (!is_user_logged_in()) {\r\n $user_id = $session_id;\r\n }\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' => $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": "<?php\r\n/*\r\n * Plugin Name: Kognetiks Chatbot\r\n * Plugin URI: https://github.com/kognetiks/kognetiks-chatbot\r\n * Description: A simple plugin to add an AI powered chatbot to your WordPress website.\r\n * Version: 2.0.4\r\n * Author: Kognetiks.com\r\n * Author URI: https://www.kognetiks.com\r\n * License: GPLv3 or later\r\n * License URI: https://www.gnu.org/licenses/gpl-30.html\r\n * \r\n * Copyright (c) 2024 Stephen Howell\r\n * \r\n * This program is free software; you can redistribute it and/or modify it under the terms of the GNU\r\n * General Public License version 3, as published by the Free Software Foundation. You may NOT assume\r\n * that you can use any other version of the GPL.\r\n * \r\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without\r\n * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\r\n * \r\n * You should have received a copy of the GNU General Public License\r\n * along with Kognetiks Chatbot for WordPress. If not, see https://www.gnu.org/licenses/gpl-3.0.html.\r\n * \r\n*/\r\n\r\n// If this file is called directly, die.\r\ndefined( 'WPINC' ) || die;\r\n\r\nif ( ! defined( 'ABSPATH' ) ) {\r\n\tdie();\r\n}\r\n\r\n// Define the plugin version\r\ndefined ('CHATBOT_CHATGPT_VERSION') || define ('CHATBOT_CHATGPT_VERSION', '2.0.4');\r\n\r\n// Main plugin file\r\ndefine('CHATBOT_CHATGPT_PLUGIN_DIR_PATH', plugin_dir_path(__FILE__));\r\n\r\n// Declare Globals\r\nglobal $wpdb;\r\n\r\n// Uniquely Identify the Visitor\r\nglobal $session_id;\r\nglobal $user_id;\r\n\r\n// Start output buffering to prevent \"headers already sent\" issues - Ver 1.8.5\r\nob_start();\r\n\r\n// Assign a unique ID to the visitor and logged in users - Ver 2.0.4\r\nfunction kognetiks_assign_unique_id() {\r\n if (!isset($_COOKIE['kognetiks_unique_id'])) {\r\n $unique_id = uniqid('kognetiks_', true);\r\n setcookie('kognetiks_unique_id', $unique_id, time() + (86400 * 30), \"/\"); // Cookie expires in 30 days\r\n // Ensure the cookie is set for the current request\r\n $_COOKIE['kognetiks_unique_id'] = $unique_id;\r\n }\r\n}\r\nadd_action('init', 'kognetiks_assign_unique_id');\r\n\r\n// Get the unique ID of the visitor or logged in user - Ver 2.0.4\r\nfunction kognetiks_get_unique_id() {\r\n if (isset($_COOKIE['kognetiks_unique_id'])) {\r\n return sanitize_text_field($_COOKIE['kognetiks_unique_id']);\r\n }\r\n error_log('Unique ID not found');\r\n return null;\r\n}\r\n\r\n// Fetch the unique ID of the visitor or logged in user - Ver 2.0.4\r\n$session_id = kognetiks_get_unique_id();\r\n\r\n// Store the unique ID in a global variable - Ver 2.0.4\r\nif (empty($session_id)) {\r\n $session_id = kognetiks_get_unique_id();\r\n}\r\n$user_id = get_current_user_id();\r\nif ($user_id == 0) {\r\n $user_id = $session_id;\r\n}\r\n// error_log('Session ID: ' . $session_id);\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 // if user is not logged in, then set user_id to $session_id\r\n if (!is_user_logged_in()) {\r\n $user_id = $session_id;\r\n }\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['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": "<?php\r\n/*\r\n * Plugin Name: Kognetiks Chatbot\r\n * Plugin URI: https://github.com/kognetiks/kognetiks-chatbot\r\n * Description: A simple plugin to add an AI powered chatbot to your WordPress website.\r\n * Version: 2.0.3\r\n * Author: Kognetiks.com\r\n * Author URI: https://www.kognetiks.com\r\n * License: GPLv3 or later\r\n * License URI: https://www.gnu.org/licenses/gpl-30.html\r\n * \r\n * Copyright (c) 2024 Stephen Howell\r\n * \r\n * This program is free software; you can redistribute it and/or modify it under the terms of the GNU\r\n * General Public License version 3, as published by the Free Software Foundation. You may NOT assume\r\n * that you can use any other version of the GPL.\r\n * \r\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without\r\n * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\r\n * \r\n * You should have received a copy of the GNU General Public License\r\n * along with Kognetiks Chatbot for WordPress. If not, see https://www.gnu.org/licenses/gpl-3.0.html.\r\n * \r\n*/\r\n\r\n// If this file is called directly, die.\r\ndefined( 'WPINC' ) || die;\r\n\r\nif ( ! defined( 'ABSPATH' ) ) {\r\n\tdie();\r\n}\r\n\r\n// Define the plugin version\r\ndefined ('CHATBOT_CHATGPT_VERSION') || define ('CHATBOT_CHATGPT_VERSION', '2.0.3');\r\n\r\n// Main plugin file\r\ndefine('CHATBOT_CHATGPT_PLUGIN_DIR_PATH', plugin_dir_path(__FILE__));\r\n\r\n// Declare Globals\r\nglobal $wpdb;\r\n\r\n// Uniquely Identify the Visitor\r\nglobal $session_id;\r\n\r\n// Start output buffering to prevent \"headers already sent\" issues - Ver 1.8.5\r\nob_start();\r\n\r\n// Updated for Ver 1.8.5\r\n// Cookie \"PHPSESSID\" does not have a proper \"SameSite\" attribute value. Soon, cookies \r\n// without the \"SameSite\" attribute or with an invalid value will be treated as “Lax”. \r\n// This means that the cookie will no longer be sent in third-party contexts. If your \r\n// application depends on this cookie being available in such contexts, please add the \r\n// \"SameSite=None\" attribute to it. To know more about the \"SameSite\" attribute, \r\n// read https://developer.mozilla.org/docs/Web/HTTP/Headers/Set-Cookie/SameSite\r\n\r\n// Start the session if it has not been started, set the global, then close the session\r\nif (empty($session_id)) {\r\n if (session_status() == PHP_SESSION_NONE) {\r\n session_start([\r\n 'cookie_lifetime' => 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": "<?php\r\n/*\r\n * Plugin Name: Kognetiks Chatbot\r\n * Plugin URI: https://github.com/kognetiks/kognetiks-chatbot\r\n * Description: A simple plugin to add an AI powered chatbot to your WordPress website.\r\n * Version: 1.9.9\r\n * Author: Kognetiks.com\r\n * Author URI: https://www.kognetiks.com\r\n * License: GPLv3 or later\r\n * License URI: https://www.gnu.org/licenses/gpl-30.html\r\n * \r\n * Copyright (c) 2024 Stephen Howell\r\n * \r\n * This program is free software; you can redistribute it and/or modify it under the terms of the GNU\r\n * General Public License version 3, as published by the Free Software Foundation. You may NOT assume\r\n * that you can use any other version of the GPL.\r\n * \r\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without\r\n * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\r\n * \r\n * You should have received a copy of the GNU General Public License\r\n * along with Kognetiks Chatbot for WordPress. If not, see https://www.gnu.org/licenses/gpl-3.0.html.\r\n * \r\n*/\r\n\r\n// If this file is called directly, die.\r\ndefined( 'WPINC' ) || die;\r\n\r\nif ( ! defined( 'ABSPATH' ) ) {\r\n\tdie();\r\n}\r\n\r\n// Define the plugin version\r\ndefined ('CHATBOT_CHATGPT_VERSION') || define ('CHATBOT_CHATGPT_VERSION', '1.9.9');\r\n\r\n// Main plugin file\r\ndefine('CHATBOT_CHATGPT_PLUGIN_DIR_PATH', plugin_dir_path(__FILE__));\r\n\r\n// Declare Globals\r\nglobal $wpdb;\r\n\r\n// Uniquely Identify the Visitor\r\nglobal $session_id;\r\n\r\n// Start output buffering to prevent \"headers already sent\" issues - Ver 1.8.5\r\nob_start();\r\n\r\n// Updated for Ver 1.8.5\r\n// Cookie \"PHPSESSID\" does not have a proper \"SameSite\" attribute value. Soon, cookies \r\n// without the \"SameSite\" attribute or with an invalid value will be treated as “Lax”. \r\n// This means that the cookie will no longer be sent in third-party contexts. If your \r\n// application depends on this cookie being available in such contexts, please add the \r\n// \"SameSite=None\" attribute to it. To know more about the \"SameSite\" attribute, \r\n// read https://developer.mozilla.org/docs/Web/HTTP/Headers/Set-Cookie/SameSite\r\n\r\n// Start the session if it has not been started, set the global, then close the session\r\nif (empty($session_id)) {\r\n if (session_status() == PHP_SESSION_NONE) {\r\n session_start([\r\n 'cookie_lifetime' => 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": "<?php\r\n/*\r\n * Plugin Name: Kognetiks Chatbot\r\n * Plugin URI: https://github.com/kognetiks/kognetiks-chatbot\r\n * Description: A simple plugin to add an AI powered chatbot to your WordPress website.\r\n * Version: 1.9.8\r\n * Author: Kognetiks.com\r\n * Author URI: https://www.kognetiks.com\r\n * License: GPLv3 or later\r\n * License URI: https://www.gnu.org/licenses/gpl-30.html\r\n * \r\n * Copyright (c) 2024 Stephen Howell\r\n * \r\n * This program is free software; you can redistribute it and/or modify it under the terms of the GNU\r\n * General Public License version 3, as published by the Free Software Foundation. You may NOT assume\r\n * that you can use any other version of the GPL.\r\n * \r\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without\r\n * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\r\n * \r\n * You should have received a copy of the GNU General Public License\r\n * along with Kognetiks Chatbot for WordPress. If not, see https://www.gnu.org/licenses/gpl-3.0.html.\r\n * \r\n*/\r\n\r\n// If this file is called directly, die.\r\ndefined( 'WPINC' ) || die;\r\n\r\nif ( ! defined( 'ABSPATH' ) ) {\r\n\tdie();\r\n}\r\n\r\n// Define the plugin version\r\ndefined ('CHATBOT_CHATGPT_VERSION') || define ('CHATBOT_CHATGPT_VERSION', '1.9.8');\r\n\r\n// Main plugin file\r\ndefine('CHATBOT_CHATGPT_PLUGIN_DIR_PATH', plugin_dir_path(__FILE__));\r\n\r\n// Declare Globals\r\nglobal $wpdb;\r\n\r\n// Uniquely Identify the Visitor\r\nglobal $session_id;\r\n\r\n// Start output buffering to prevent \"headers already sent\" issues - Ver 1.8.5\r\nob_start();\r\n\r\n// Updated for Ver 1.8.5\r\n// Cookie \"PHPSESSID\" does not have a proper \"SameSite\" attribute value. Soon, cookies \r\n// without the \"SameSite\" attribute or with an invalid value will be treated as “Lax”. \r\n// This means that the cookie will no longer be sent in third-party contexts. If your \r\n// application depends on this cookie being available in such contexts, please add the \r\n// \"SameSite=None\" attribute to it. To know more about the \"SameSite\" attribute, \r\n// read https://developer.mozilla.org/docs/Web/HTTP/Headers/Set-Cookie/SameSite\r\n\r\n// Start the session if it has not been started, set the global, then close the session\r\nif (empty($session_id)) {\r\n if (session_status() == PHP_SESSION_NONE) {\r\n session_start([\r\n 'cookie_lifetime' => 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"}, "2dd08585d8f97d7e6063f081a2c8af9f1d2a898b": {"t": 1786067466.2029643, "n": 167437, "h": "8b902d1831b1c4d5", "c": "<?php\r\n\r\n/*\r\n * Plugin Name: Kognetiks Chatbot\r\n * Plugin URI: https://github.com/kognetiks/kognetiks-chatbot\r\n * Description: This simple plugin adds an AI powered chatbot to your WordPress website.\r\n * Version: 2.4.6\r\n * Author: Kognetiks.com\r\n * Author URI: https://www.kognetiks.com\r\n * License: GPLv3 or later\r\n * License URI: https://www.gnu.org/licenses/gpl-30.html\r\n * \r\n * Copyright (c) 2023-2025 Stephen Howell\r\n * \r\n * This program is free software; you can redistribute it and/or modify it under the terms of the GNU\r\n * General Public License version 3, as published by the Free Software Foundation. You may NOT assume\r\n * that you can use any other version of the GPL.\r\n * \r\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without\r\n * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\r\n * \r\n * You should have received a copy of the GNU General Public License\r\n * along with Kognetiks Chatbot. If not, see https://www.gnu.org/licenses/gpl-3.0.html.\r\n * \r\n * @package chatbot-chatgpt\r\n * @version 2.4.6\r\n * @author Kognetiks.com\r\n */\r\nif ( !defined( 'ABSPATH' ) ) {\r\n exit;\r\n}\r\n// Load vendor management early so it can register for chatbot_chatgpt_freemius_loaded (before do_action runs)\r\n// require_once plugin_dir_path(__FILE__) . 'includes/utilities/chatbot-vendor-management.php';\r\nif ( function_exists( 'chatbot_chatgpt_freemius' ) ) {\r\n chatbot_chatgpt_freemius()->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 . '<br><br>' . 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 . '<br><br>' . 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 '<div class=\"notice notice-success\"><p>Visitor locks cleared successfully!</p></div>';\r\n }\r\n echo '<div class=\"wrap\">';\r\n echo '<h1>Clear Visitor Locks</h1>';\r\n echo '<p>This tool clears stuck conversation locks that may be preventing visitors from using the chatbot.</p>';\r\n echo '<p><strong>Use this if visitors are getting \"system is busy processing requests\" messages.</strong></p>';\r\n echo '<form method=\"post\">';\r\n wp_nonce_field( 'clear_visitor_locks' );\r\n echo '<p><input type=\"submit\" name=\"clear_locks\" class=\"button-primary\" value=\"Clear All Visitor Locks\" onclick=\"return confirm(\\'Are you sure you want to clear all visitor locks?\\')\"></p>';\r\n echo '</form>';\r\n echo '</div>';\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}"}, "941929cdd6bc0a430d5e812b462d1714164d49bf": {"t": 1786068315.7997708, "n": 167437, "h": "8b902d1831b1c4d5", "c": "<?php\r\n\r\n/*\r\n * Plugin Name: Kognetiks Chatbot\r\n * Plugin URI: https://github.com/kognetiks/kognetiks-chatbot\r\n * Description: This simple plugin adds an AI powered chatbot to your WordPress website.\r\n * Version: 2.4.6\r\n * Author: Kognetiks.com\r\n * Author URI: https://www.kognetiks.com\r\n * License: GPLv3 or later\r\n * License URI: https://www.gnu.org/licenses/gpl-30.html\r\n * \r\n * Copyright (c) 2023-2025 Stephen Howell\r\n * \r\n * This program is free software; you can redistribute it and/or modify it under the terms of the GNU\r\n * General Public License version 3, as published by the Free Software Foundation. You may NOT assume\r\n * that you can use any other version of the GPL.\r\n * \r\n * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without\r\n * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\r\n * \r\n * You should have received a copy of the GNU General Public License\r\n * along with Kognetiks Chatbot. If not, see https://www.gnu.org/licenses/gpl-3.0.html.\r\n * \r\n * @package chatbot-chatgpt\r\n * @version 2.4.6\r\n * @author Kognetiks.com\r\n */\r\nif ( !defined( 'ABSPATH' ) ) {\r\n exit;\r\n}\r\n// Load vendor management early so it can register for chatbot_chatgpt_freemius_loaded (before do_action runs)\r\n// require_once plugin_dir_path(__FILE__) . 'includes/utilities/chatbot-vendor-management.php';\r\nif ( function_exists( 'chatbot_chatgpt_freemius' ) ) {\r\n chatbot_chatgpt_freemius()->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 . '<br><br>' . 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 . '<br><br>' . 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 '<div class=\"notice notice-success\"><p>Visitor locks cleared successfully!</p></div>';\r\n }\r\n echo '<div class=\"wrap\">';\r\n echo '<h1>Clear Visitor Locks</h1>';\r\n echo '<p>This tool clears stuck conversation locks that may be preventing visitors from using the chatbot.</p>';\r\n echo '<p><strong>Use this if visitors are getting \"system is busy processing requests\" messages.</strong></p>';\r\n echo '<form method=\"post\">';\r\n wp_nonce_field( 'clear_visitor_locks' );\r\n echo '<p><input type=\"submit\" name=\"clear_locks\" class=\"button-primary\" value=\"Clear All Visitor Locks\" onclick=\"return confirm(\\'Are you sure you want to clear all visitor locks?\\')\"></p>';\r\n echo '</form>';\r\n echo '</div>';\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}"}}, "wp-content/plugins/chatbot-chatgpt/includes/utilities/chatbot-api-endpoints.php": {"de6c3bda23246fe11f7d20255df14f55b5865b77": {"t": 1785746147.9500942, "n": 6173, "h": "0af78d19bbdc4339", "c": "<?php\n/**\n * Kognetiks Chatbot - API Endpoints - Ver 2.2.2 - Revised - Ver 2.2.6\n *\n * This file contains the code for managing the API endpoints.\n *\n *\n * @package chatbot-chatgpt\n */\n\n// If this file is called directly, abort.\nif ( ! defined( 'WPINC' ) ) {\n die();\n}\n\n// Base URL for the API calls - Ver 2.2.6\nfunction get_api_base_url() {\n\n $chatbot_ai_platform_choice = esc_attr(get_option('chatbot_ai_platform_choice'), 'OpenAI');\n\n switch ($chatbot_ai_platform_choice) {\n\n // Base URL for the OpenAI API calls - Ver 1.8.1\n case 'OpenAI':\n\n return esc_attr(get_option('chatbot_chatgpt_base_url', 'https://api.openai.com/v1'));\n break;\n\n // Base URL for the Azure OpenAI API calls - Ver 2.2.6\n case 'Azure OpenAI':\n\n return esc_attr(get_option('chatbot_azure_base_url', 'https://YOUR_RESOURCE_NAME.openai.azure.com/DEPLOYMENT_NAME/MODEL/chat/completions?api-version=YYYY-MM-DD'));\n break;\n\n // Base URL for the NVIDIA API calls - Ver 2.1.8\n case 'NVIDIA':\n\n return esc_attr(get_option('chatbot_nvidia_base_url', 'https://integrate.api.nvidia.com/v1'));\n break;\n\n // Base URL for the Anthropic API calls - Ver 2.2.1\n case 'Anthropic':\n\n return esc_attr(get_option('chatbot_anthropic_base_url', 'https://api.anthropic.com/v1'));\n break;\n\n // Base URL for the DeepSeek API calls - Ver 2.2.2\n case 'DeepSeek':\n\n return esc_attr(get_option('chatbot_deepseek_base_url', 'https://api.deepseek.com'));\n break;\n\n // Base URL for the Google API calls - Ver 2.3.9\n case 'Google':\n \n // Get the base URL from settings, default to base URL without /models/\n $google_base_url = esc_attr(get_option('chatbot_google_base_url', 'https://generativelanguage.googleapis.com/v1beta'));\n\n return $google_base_url;\n break;\n\n // Base URL for the Mistral API calls - Ver 2.3.0\n case 'Mistral':\n\n return esc_attr(get_option('chatbot_mistral_base_url', 'https://api.mistral.ai/v1'));\n break;\n\n // Base URL for the Local API calls - Ver 2.2.6\n case 'Local Server':\n\n return esc_attr(get_option('chatbot_local_base_url', 'http://127.0.0.1:1337/v1'));\n break;\n\n default:\n\n return get_api_base_url();\n break;\n\n }\n\n}\n\n// Base URL for the ChatGPT API calls - Ver 2.2.2\nfunction get_threads_api_url() {\n\n return get_api_base_url() . \"/threads\";\n\n}\n\n// Base URL for the ChatGPT API calls - Ver 2.2.2\nfunction get_files_api_url() {\n\n $chatbot_ai_platform_choice = esc_attr(get_option('chatbot_ai_platform_choice'), 'OpenAI');\n\n if ($chatbot_ai_platform_choice == 'OpenAI') {\n\n return get_api_base_url() . \"/files\";\n\n } elseif ($chatbot_ai_platform_choice == 'Azure OpenAI') {\n\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 // Assemble the URL\n // $url = 'https://RESOURCE_NAME_GOES_HERE.openai.azure.com/openai/files?api-version=2024-03-01-preview';\n $url = 'https://' . $chatbot_azure_resource_name . '.openai.azure.com/openai/files?api-version=' . $chatbot_azure_api_version;\n\n return $url;\n\n }\n\n return 'ERROR: No file API URL found!';\n\n}\n\n// Base URL for the ChatGPT API calls - Ver 2.2.2 - Revised - Ver 2.2.6\nfunction get_chat_completions_api_url() {\n\n $chatbot_ai_platform_choice = esc_attr(get_option('chatbot_ai_platform_choice'), 'OpenAI');\n\n switch ($chatbot_ai_platform_choice) {\n\n // Base URL for the OpenAI API calls - Ver 1.8.1\n case 'OpenAI':\n\n return get_api_base_url() . \"/chat/completions\";\n break;\n\n // Base URL for the Azure OpenAI API calls - Ver 2.2.6\n case 'Azure OpenAI':\n\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', 'YYYY-MM-DD'));\n\n // Assemble the URL\n return 'https://' . $chatbot_azure_resource_name . '.openai.azure.com/openai/deployments/' . $chatbot_azure_deployment_name . '/chat/completions?api-version=' . $chatbot_azure_api_version;\n break;\n\n // Base URL for the NVIDIA API calls - Ver 2.1.8\n case 'NVIDIA':\n\n return get_api_base_url() . \"/chat/completions\";\n break;\n\n // Base URL for the Anthropic API calls - Ver 2.2.1\n case 'Anthropic':\n\n return get_api_base_url() . \"/messages\";\n break;\n\n // Base URL for the DeepSeek API calls - Ver 2.2.2\n case 'DeepSeek':\n\n return get_api_base_url() . \"/chat/completions\";\n break;\n\n // Base URL for the Google API calls - Ver 2.3.9\n // Note: Google API uses /models/{model}:generateContent format, not /chat/completions\n // This function returns a base URL that can be used to construct the full endpoint\n case 'Google':\n\n // Google API endpoint format: {base}/models/{model}:generateContent\n // This function returns the base, caller must append /models/{model}:generateContent\n return get_api_base_url() . \"/models\";\n break;\n\n // Base URL for the Mistral API calls - Ver 2.3.0\n case 'Mistral':\n\n return get_api_base_url() . \"/chat/completions\";\n break;\n\n // Base URL for the Local API calls - Ver 2.2.6\n case 'Local Server':\n\n return get_api_base_url() . \"/chat/completions\";\n break;\n\n default:\n\n return get_api_base_url() . \"/chat/completions\";\n break;\n }\n\n}\n"}, "81133d2416ab2ca1d8784ec5469d49357805af5a": {"t": 1785756403.085184, "n": 6173, "h": "0af78d19bbdc4339", "c": "<?php\n/**\n * Kognetiks Chatbot - API Endpoints - Ver 2.2.2 - Revised - Ver 2.2.6\n *\n * This file contains the code for managing the API endpoints.\n *\n *\n * @package chatbot-chatgpt\n */\n\n// If this file is called directly, abort.\nif ( ! defined( 'WPINC' ) ) {\n die();\n}\n\n// Base URL for the API calls - Ver 2.2.6\nfunction get_api_base_url() {\n\n $chatbot_ai_platform_choice = esc_attr(get_option('chatbot_ai_platform_choice'), 'OpenAI');\n\n switch ($chatbot_ai_platform_choice) {\n\n // Base URL for the OpenAI API calls - Ver 1.8.1\n case 'OpenAI':\n\n return esc_attr(get_option('chatbot_chatgpt_base_url', 'https://api.openai.com/v1'));\n break;\n\n // Base URL for the Azure OpenAI API calls - Ver 2.2.6\n case 'Azure OpenAI':\n\n return esc_attr(get_option('chatbot_azure_base_url', 'https://YOUR_RESOURCE_NAME.openai.azure.com/DEPLOYMENT_NAME/MODEL/chat/completions?api-version=YYYY-MM-DD'));\n break;\n\n // Base URL for the NVIDIA API calls - Ver 2.1.8\n case 'NVIDIA':\n\n return esc_attr(get_option('chatbot_nvidia_base_url', 'https://integrate.api.nvidia.com/v1'));\n break;\n\n // Base URL for the Anthropic API calls - Ver 2.2.1\n case 'Anthropic':\n\n return esc_attr(get_option('chatbot_anthropic_base_url', 'https://api.anthropic.com/v1'));\n break;\n\n // Base URL for the DeepSeek API calls - Ver 2.2.2\n case 'DeepSeek':\n\n return esc_attr(get_option('chatbot_deepseek_base_url', 'https://api.deepseek.com'));\n break;\n\n // Base URL for the Google API calls - Ver 2.3.9\n case 'Google':\n \n // Get the base URL from settings, default to base URL without /models/\n $google_base_url = esc_attr(get_option('chatbot_google_base_url', 'https://generativelanguage.googleapis.com/v1beta'));\n\n return $google_base_url;\n break;\n\n // Base URL for the Mistral API calls - Ver 2.3.0\n case 'Mistral':\n\n return esc_attr(get_option('chatbot_mistral_base_url', 'https://api.mistral.ai/v1'));\n break;\n\n // Base URL for the Local API calls - Ver 2.2.6\n case 'Local Server':\n\n return esc_attr(get_option('chatbot_local_base_url', 'http://127.0.0.1:1337/v1'));\n break;\n\n default:\n\n return get_api_base_url();\n break;\n\n }\n\n}\n\n// Base URL for the ChatGPT API calls - Ver 2.2.2\nfunction get_threads_api_url() {\n\n return get_api_base_url() . \"/threads\";\n\n}\n\n// Base URL for the ChatGPT API calls - Ver 2.2.2\nfunction get_files_api_url() {\n\n $chatbot_ai_platform_choice = esc_attr(get_option('chatbot_ai_platform_choice'), 'OpenAI');\n\n if ($chatbot_ai_platform_choice == 'OpenAI') {\n\n return get_api_base_url() . \"/files\";\n\n } elseif ($chatbot_ai_platform_choice == 'Azure OpenAI') {\n\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 // Assemble the URL\n // $url = 'https://RESOURCE_NAME_GOES_HERE.openai.azure.com/openai/files?api-version=2024-03-01-preview';\n $url = 'https://' . $chatbot_azure_resource_name . '.openai.azure.com/openai/files?api-version=' . $chatbot_azure_api_version;\n\n return $url;\n\n }\n\n return 'ERROR: No file API URL found!';\n\n}\n\n// Base URL for the ChatGPT API calls - Ver 2.2.2 - Revised - Ver 2.2.6\nfunction get_chat_completions_api_url() {\n\n $chatbot_ai_platform_choice = esc_attr(get_option('chatbot_ai_platform_choice'), 'OpenAI');\n\n switch ($chatbot_ai_platform_choice) {\n\n // Base URL for the OpenAI API calls - Ver 1.8.1\n case 'OpenAI':\n\n return get_api_base_url() . \"/chat/completions\";\n break;\n\n // Base URL for the Azure OpenAI API calls - Ver 2.2.6\n case 'Azure OpenAI':\n\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', 'YYYY-MM-DD'));\n\n // Assemble the URL\n return 'https://' . $chatbot_azure_resource_name . '.openai.azure.com/openai/deployments/' . $chatbot_azure_deployment_name . '/chat/completions?api-version=' . $chatbot_azure_api_version;\n break;\n\n // Base URL for the NVIDIA API calls - Ver 2.1.8\n case 'NVIDIA':\n\n return get_api_base_url() . \"/chat/completions\";\n break;\n\n // Base URL for the Anthropic API calls - Ver 2.2.1\n case 'Anthropic':\n\n return get_api_base_url() . \"/messages\";\n break;\n\n // Base URL for the DeepSeek API calls - Ver 2.2.2\n case 'DeepSeek':\n\n return get_api_base_url() . \"/chat/completions\";\n break;\n\n // Base URL for the Google API calls - Ver 2.3.9\n // Note: Google API uses /models/{model}:generateContent format, not /chat/completions\n // This function returns a base URL that can be used to construct the full endpoint\n case 'Google':\n\n // Google API endpoint format: {base}/models/{model}:generateContent\n // This function returns the base, caller must append /models/{model}:generateContent\n return get_api_base_url() . \"/models\";\n break;\n\n // Base URL for the Mistral API calls - Ver 2.3.0\n case 'Mistral':\n\n return get_api_base_url() . \"/chat/completions\";\n break;\n\n // Base URL for the Local API calls - Ver 2.2.6\n case 'Local Server':\n\n return get_api_base_url() . \"/chat/completions\";\n break;\n\n default:\n\n return get_api_base_url() . \"/chat/completions\";\n break;\n }\n\n}\n"}, "ae7fbc5e985e140c07301be8d4a2c9d6214c9b31": {"t": 1786067603.778642, "n": 6173, "h": "0af78d19bbdc4339", "c": "<?php\n/**\n * Kognetiks Chatbot - API Endpoints - Ver 2.2.2 - Revised - Ver 2.2.6\n *\n * This file contains the code for managing the API endpoints.\n *\n *\n * @package chatbot-chatgpt\n */\n\n// If this file is called directly, abort.\nif ( ! defined( 'WPINC' ) ) {\n die();\n}\n\n// Base URL for the API calls - Ver 2.2.6\nfunction get_api_base_url() {\n\n $chatbot_ai_platform_choice = esc_attr(get_option('chatbot_ai_platform_choice'), 'OpenAI');\n\n switch ($chatbot_ai_platform_choice) {\n\n // Base URL for the OpenAI API calls - Ver 1.8.1\n case 'OpenAI':\n\n return esc_attr(get_option('chatbot_chatgpt_base_url', 'https://api.openai.com/v1'));\n break;\n\n // Base URL for the Azure OpenAI API calls - Ver 2.2.6\n case 'Azure OpenAI':\n\n return esc_attr(get_option('chatbot_azure_base_url', 'https://YOUR_RESOURCE_NAME.openai.azure.com/DEPLOYMENT_NAME/MODEL/chat/completions?api-version=YYYY-MM-DD'));\n break;\n\n // Base URL for the NVIDIA API calls - Ver 2.1.8\n case 'NVIDIA':\n\n return esc_attr(get_option('chatbot_nvidia_base_url', 'https://integrate.api.nvidia.com/v1'));\n break;\n\n // Base URL for the Anthropic API calls - Ver 2.2.1\n case 'Anthropic':\n\n return esc_attr(get_option('chatbot_anthropic_base_url', 'https://api.anthropic.com/v1'));\n break;\n\n // Base URL for the DeepSeek API calls - Ver 2.2.2\n case 'DeepSeek':\n\n return esc_attr(get_option('chatbot_deepseek_base_url', 'https://api.deepseek.com'));\n break;\n\n // Base URL for the Google API calls - Ver 2.3.9\n case 'Google':\n \n // Get the base URL from settings, default to base URL without /models/\n $google_base_url = esc_attr(get_option('chatbot_google_base_url', 'https://generativelanguage.googleapis.com/v1beta'));\n\n return $google_base_url;\n break;\n\n // Base URL for the Mistral API calls - Ver 2.3.0\n case 'Mistral':\n\n return esc_attr(get_option('chatbot_mistral_base_url', 'https://api.mistral.ai/v1'));\n break;\n\n // Base URL for the Local API calls - Ver 2.2.6\n case 'Local Server':\n\n return esc_attr(get_option('chatbot_local_base_url', 'http://127.0.0.1:1337/v1'));\n break;\n\n default:\n\n return get_api_base_url();\n break;\n\n }\n\n}\n\n// Base URL for the ChatGPT API calls - Ver 2.2.2\nfunction get_threads_api_url() {\n\n return get_api_base_url() . \"/threads\";\n\n}\n\n// Base URL for the ChatGPT API calls - Ver 2.2.2\nfunction get_files_api_url() {\n\n $chatbot_ai_platform_choice = esc_attr(get_option('chatbot_ai_platform_choice'), 'OpenAI');\n\n if ($chatbot_ai_platform_choice == 'OpenAI') {\n\n return get_api_base_url() . \"/files\";\n\n } elseif ($chatbot_ai_platform_choice == 'Azure OpenAI') {\n\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 // Assemble the URL\n // $url = 'https://RESOURCE_NAME_GOES_HERE.openai.azure.com/openai/files?api-version=2024-03-01-preview';\n $url = 'https://' . $chatbot_azure_resource_name . '.openai.azure.com/openai/files?api-version=' . $chatbot_azure_api_version;\n\n return $url;\n\n }\n\n return 'ERROR: No file API URL found!';\n\n}\n\n// Base URL for the ChatGPT API calls - Ver 2.2.2 - Revised - Ver 2.2.6\nfunction get_chat_completions_api_url() {\n\n $chatbot_ai_platform_choice = esc_attr(get_option('chatbot_ai_platform_choice'), 'OpenAI');\n\n switch ($chatbot_ai_platform_choice) {\n\n // Base URL for the OpenAI API calls - Ver 1.8.1\n case 'OpenAI':\n\n return get_api_base_url() . \"/chat/completions\";\n break;\n\n // Base URL for the Azure OpenAI API calls - Ver 2.2.6\n case 'Azure OpenAI':\n\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', 'YYYY-MM-DD'));\n\n // Assemble the URL\n return 'https://' . $chatbot_azure_resource_name . '.openai.azure.com/openai/deployments/' . $chatbot_azure_deployment_name . '/chat/completions?api-version=' . $chatbot_azure_api_version;\n break;\n\n // Base URL for the NVIDIA API calls - Ver 2.1.8\n case 'NVIDIA':\n\n return get_api_base_url() . \"/chat/completions\";\n break;\n\n // Base URL for the Anthropic API calls - Ver 2.2.1\n case 'Anthropic':\n\n return get_api_base_url() . \"/messages\";\n break;\n\n // Base URL for the DeepSeek API calls - Ver 2.2.2\n case 'DeepSeek':\n\n return get_api_base_url() . \"/chat/completions\";\n break;\n\n // Base URL for the Google API calls - Ver 2.3.9\n // Note: Google API uses /models/{model}:generateContent format, not /chat/completions\n // This function returns a base URL that can be used to construct the full endpoint\n case 'Google':\n\n // Google API endpoint format: {base}/models/{model}:generateContent\n // This function returns the base, caller must append /models/{model}:generateContent\n return get_api_base_url() . \"/models\";\n break;\n\n // Base URL for the Mistral API calls - Ver 2.3.0\n case 'Mistral':\n\n return get_api_base_url() . \"/chat/completions\";\n break;\n\n // Base URL for the Local API calls - Ver 2.2.6\n case 'Local Server':\n\n return get_api_base_url() . \"/chat/completions\";\n break;\n\n default:\n\n return get_api_base_url() . \"/chat/completions\";\n break;\n }\n\n}\n"}, "941929cdd6bc0a430d5e812b462d1714164d49bf": {"t": 1786068381.172737, "n": 6173, "h": "0af78d19bbdc4339", "c": "<?php\n/**\n * Kognetiks Chatbot - API Endpoints - Ver 2.2.2 - Revised - Ver 2.2.6\n *\n * This file contains the code for managing the API endpoints.\n *\n *\n * @package chatbot-chatgpt\n */\n\n// If this file is called directly, abort.\nif ( ! defined( 'WPINC' ) ) {\n die();\n}\n\n// Base URL for the API calls - Ver 2.2.6\nfunction get_api_base_url() {\n\n $chatbot_ai_platform_choice = esc_attr(get_option('chatbot_ai_platform_choice'), 'OpenAI');\n\n switch ($chatbot_ai_platform_choice) {\n\n // Base URL for the OpenAI API calls - Ver 1.8.1\n case 'OpenAI':\n\n return esc_attr(get_option('chatbot_chatgpt_base_url', 'https://api.openai.com/v1'));\n break;\n\n // Base URL for the Azure OpenAI API calls - Ver 2.2.6\n case 'Azure OpenAI':\n\n return esc_attr(get_option('chatbot_azure_base_url', 'https://YOUR_RESOURCE_NAME.openai.azure.com/DEPLOYMENT_NAME/MODEL/chat/completions?api-version=YYYY-MM-DD'));\n break;\n\n // Base URL for the NVIDIA API calls - Ver 2.1.8\n case 'NVIDIA':\n\n return esc_attr(get_option('chatbot_nvidia_base_url', 'https://integrate.api.nvidia.com/v1'));\n break;\n\n // Base URL for the Anthropic API calls - Ver 2.2.1\n case 'Anthropic':\n\n return esc_attr(get_option('chatbot_anthropic_base_url', 'https://api.anthropic.com/v1'));\n break;\n\n // Base URL for the DeepSeek API calls - Ver 2.2.2\n case 'DeepSeek':\n\n return esc_attr(get_option('chatbot_deepseek_base_url', 'https://api.deepseek.com'));\n break;\n\n // Base URL for the Google API calls - Ver 2.3.9\n case 'Google':\n \n // Get the base URL from settings, default to base URL without /models/\n $google_base_url = esc_attr(get_option('chatbot_google_base_url', 'https://generativelanguage.googleapis.com/v1beta'));\n\n return $google_base_url;\n break;\n\n // Base URL for the Mistral API calls - Ver 2.3.0\n case 'Mistral':\n\n return esc_attr(get_option('chatbot_mistral_base_url', 'https://api.mistral.ai/v1'));\n break;\n\n // Base URL for the Local API calls - Ver 2.2.6\n case 'Local Server':\n\n return esc_attr(get_option('chatbot_local_base_url', 'http://127.0.0.1:1337/v1'));\n break;\n\n default:\n\n return get_api_base_url();\n break;\n\n }\n\n}\n\n// Base URL for the ChatGPT API calls - Ver 2.2.2\nfunction get_threads_api_url() {\n\n return get_api_base_url() . \"/threads\";\n\n}\n\n// Base URL for the ChatGPT API calls - Ver 2.2.2\nfunction get_files_api_url() {\n\n $chatbot_ai_platform_choice = esc_attr(get_option('chatbot_ai_platform_choice'), 'OpenAI');\n\n if ($chatbot_ai_platform_choice == 'OpenAI') {\n\n return get_api_base_url() . \"/files\";\n\n } elseif ($chatbot_ai_platform_choice == 'Azure OpenAI') {\n\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 // Assemble the URL\n // $url = 'https://RESOURCE_NAME_GOES_HERE.openai.azure.com/openai/files?api-version=2024-03-01-preview';\n $url = 'https://' . $chatbot_azure_resource_name . '.openai.azure.com/openai/files?api-version=' . $chatbot_azure_api_version;\n\n return $url;\n\n }\n\n return 'ERROR: No file API URL found!';\n\n}\n\n// Base URL for the ChatGPT API calls - Ver 2.2.2 - Revised - Ver 2.2.6\nfunction get_chat_completions_api_url() {\n\n $chatbot_ai_platform_choice = esc_attr(get_option('chatbot_ai_platform_choice'), 'OpenAI');\n\n switch ($chatbot_ai_platform_choice) {\n\n // Base URL for the OpenAI API calls - Ver 1.8.1\n case 'OpenAI':\n\n return get_api_base_url() . \"/chat/completions\";\n break;\n\n // Base URL for the Azure OpenAI API calls - Ver 2.2.6\n case 'Azure OpenAI':\n\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', 'YYYY-MM-DD'));\n\n // Assemble the URL\n return 'https://' . $chatbot_azure_resource_name . '.openai.azure.com/openai/deployments/' . $chatbot_azure_deployment_name . '/chat/completions?api-version=' . $chatbot_azure_api_version;\n break;\n\n // Base URL for the NVIDIA API calls - Ver 2.1.8\n case 'NVIDIA':\n\n return get_api_base_url() . \"/chat/completions\";\n break;\n\n // Base URL for the Anthropic API calls - Ver 2.2.1\n case 'Anthropic':\n\n return get_api_base_url() . \"/messages\";\n break;\n\n // Base URL for the DeepSeek API calls - Ver 2.2.2\n case 'DeepSeek':\n\n return get_api_base_url() . \"/chat/completions\";\n break;\n\n // Base URL for the Google API calls - Ver 2.3.9\n // Note: Google API uses /models/{model}:generateContent format, not /chat/completions\n // This function returns a base URL that can be used to construct the full endpoint\n case 'Google':\n\n // Google API endpoint format: {base}/models/{model}:generateContent\n // This function returns the base, caller must append /models/{model}:generateContent\n return get_api_base_url() . \"/models\";\n break;\n\n // Base URL for the Mistral API calls - Ver 2.3.0\n case 'Mistral':\n\n return get_api_base_url() . \"/chat/completions\";\n break;\n\n // Base URL for the Local API calls - Ver 2.2.6\n case 'Local Server':\n\n return get_api_base_url() . \"/chat/completions\";\n break;\n\n default:\n\n return get_api_base_url() . \"/chat/completions\";\n break;\n }\n\n}\n"}}}}