PluginProbe ʕ •ᴥ•ʔ
AI Engine – The Chatbot, AI Framework & MCP for WordPress / 1.5.3
AI Engine – The Chatbot, AI Framework & MCP for WordPress v1.5.3
3.5.7 3.5.6 3.5.5 3.5.4 3.5.3 3.5.2 3.5.1 3.5.0 3.4.9 3.4.8 3.4.7 0.2.1 1.6.91 0.2.2 1.6.92 0.2.3 1.6.93 0.2.4 1.6.94 0.2.5 1.6.95 0.2.6 1.6.96 0.2.7 1.6.97 0.2.8 1.6.98 0.2.9 1.6.99 0.3.0 1.7.0 0.3.1 1.7.1 0.3.2 1.7.2 0.3.3 1.7.3 0.3.4 1.7.4 0.3.5 1.7.5 0.3.6 1.7.6 0.4.0 1.7.7 0.4.1 1.7.8 0.4.2 1.7.9 0.4.3 1.8.0 0.4.4 1.8.1 0.4.5 1.8.2 0.4.6 1.8.3 0.4.7 1.8.4 0.4.8 1.8.5 0.4.9 1.8.6 0.5.0 1.8.7 0.5.1 1.8.8 0.5.2 1.8.9 0.5.3 1.9.0 0.5.4 1.9.1 0.5.5 1.9.2 0.5.6 1.9.3 0.5.7 1.9.4 0.5.8 1.9.5 0.5.9 1.9.6 0.6.0 1.9.7 0.6.1 1.9.8 0.6.2 1.9.81 0.6.3 1.9.82 0.6.4 1.9.83 0.6.5 1.9.84 0.6.6 1.9.85 0.6.7 1.9.86 0.6.8 1.9.87 0.6.9 1.9.88 0.7.0 1.9.89 0.7.1 1.9.90 0.7.2 1.9.91 0.7.3 1.9.92 0.7.4 1.9.93 0.7.5 1.9.94 0.7.6 1.9.95 0.7.7 1.9.96 0.7.8 1.9.97 0.7.9 1.9.98 0.8.0 1.9.99 0.8.1 2.0.0 0.8.2 2.0.1 0.8.3 2.0.2 0.8.4 2.0.3 0.8.5 2.0.4 0.8.6 2.0.5 0.8.7 2.0.6 0.8.8 2.0.7 0.8.9 2.0.8 0.9.0 2.0.9 0.9.2 2.1.0 0.9.3 2.1.1 0.9.4 2.1.2 0.9.5 2.1.3 0.9.6 2.1.4 0.9.7 2.1.5 0.9.8 2.1.6 0.9.81 2.1.7 0.9.82 2.1.8 0.9.83 2.1.9 0.9.84 2.2.0 0.9.85 2.2.1 0.9.86 2.2.2 0.9.87 2.2.3 0.9.88 2.2.4 0.9.89 2.2.5 0.9.9 2.2.51 0.9.91 2.2.52 0.9.92 2.2.53 0.9.93 2.2.54 0.9.94 2.2.56 0.9.95 2.2.57 0.9.96 2.2.6 0.9.97 2.2.60 0.9.98 2.2.61 0.9.99 2.2.62 1.0.0 2.2.63 1.0.01 2.2.70 1.0.1 2.2.80 1.0.2 2.2.81 1.0.3 2.2.90 1.0.4 2.2.91 1.0.5 2.2.92 1.0.6 2.2.93 1.0.7 2.2.94 1.0.8 2.2.95 1.0.9 2.3.0 1.1.0 2.3.1 1.1.1 2.3.2 1.1.2 2.3.3 1.1.3 2.3.4 1.1.4 2.3.5 1.1.5 2.3.6 1.1.6 2.3.7 1.1.7 2.3.8 1.1.8 2.3.9 1.1.9 2.4.0 1.2.0 2.4.1 1.2.1 2.4.2 1.2.2 2.4.3 1.2.21 2.4.4 1.2.3 2.4.5 1.2.30 2.4.6 1.3.0 2.4.7 1.3.1 2.4.8 1.3.2 2.4.9 1.3.3 2.5.0 1.3.31 2.5.1 1.3.32 2.5.2 1.3.33 2.5.3 1.3.34 2.5.4 1.3.35 2.5.5 1.3.36 2.5.6 1.3.37 2.5.7 1.3.38 2.5.8 1.3.39 2.5.9 1.3.40 2.6.0 1.3.41 2.6.1 1.3.42 2.6.2 1.3.43 2.6.3 1.3.44 2.6.5 1.3.45 2.6.6 1.3.46 2.6.7 1.3.47 2.6.8 1.3.48 2.6.9 1.3.49 2.7.0 1.3.50 2.7.1 1.3.51 2.7.2 1.3.52 2.7.3 1.3.53 2.7.4 1.3.54 2.7.5 1.3.56 2.7.6 1.3.57 2.7.7 1.3.58 2.7.8 1.3.59 2.7.9 1.3.60 2.8.0 1.3.61 2.8.1 1.3.62 2.8.2 1.3.63 2.8.3 1.3.64 2.8.4 1.3.65 2.8.5 1.3.66 2.8.6 1.3.67 2.8.7 1.3.68 2.8.8 1.3.69 2.8.9 1.3.70 2.9.0 1.3.71 2.9.1 1.3.72 2.9.2 1.3.73 2.9.3 1.3.74 2.9.4 1.3.75 2.9.5 1.3.76 2.9.6 1.3.77 2.9.7 1.3.78 2.9.8 1.3.79 2.9.9 1.3.80 3.0.0 1.3.81 3.0.1 1.3.82 3.0.2 1.3.83 3.0.3 1.3.84 3.0.4 1.3.85 3.0.5 1.3.86 3.0.6 1.3.87 3.0.7 1.3.88 3.0.8 1.3.89 3.0.9 1.3.90 3.1.0 1.3.91 3.1.1 1.3.92 3.1.2 1.3.93 3.1.3 1.3.94 3.1.4 1.3.95 3.1.5 1.3.96 3.1.6 1.3.97 3.1.7 1.3.98 3.1.8 1.3.99 3.1.9 1.4.0 3.2.0 1.4.1 3.2.1 1.4.2 3.2.2 1.4.3 3.2.3 1.4.4 3.2.4 1.4.5 3.2.5 1.4.6 3.2.6 1.4.7 3.2.7 1.4.8 3.2.8 1.4.9 3.2.9 1.5.0 3.3.0 1.5.1 3.3.1 1.5.2 3.3.2 1.5.3 3.3.3 1.5.4 3.3.4 1.5.5 3.3.5 1.5.6 3.3.6 1.5.7 3.3.7 1.5.8 3.3.8 1.5.9 3.3.9 1.6.0 3.4.0 1.6.1 3.4.1 1.6.2 3.4.2 1.6.3 3.4.3 1.6.5 3.4.4 1.6.51 3.4.5 1.6.52 3.4.6 1.6.53 1.6.54 1.6.55 1.6.56 1.6.57 1.6.58 1.6.59 1.6.60 1.6.61 1.6.62 1.6.63 1.6.64 1.6.65 1.6.66 1.6.67 1.6.68 trunk 1.6.69 0.0.1 1.6.70 0.0.2 1.6.71 0.0.3 1.6.72 0.0.4 1.6.73 0.0.5 1.6.74 0.0.6 1.6.75 0.0.7 1.6.76 0.0.8 1.6.77 0.0.9 1.6.78 0.1.0 1.6.79 0.1.1 1.6.81 0.1.2 1.6.82 0.1.3 1.6.83 0.1.4 1.6.84 0.1.5 1.6.85 0.1.6 1.6.86 0.1.7 1.6.87 0.1.8 1.6.88 0.1.9 1.6.89 0.2.0 1.6.90
ai-engine / classes / core.php
ai-engine / classes Last commit date
modules 3 years ago admin.php 3 years ago ai.php 3 years ago answer.php 3 years ago api.php 3 years ago core.php 3 years ago init.php 3 years ago openai.php 3 years ago query.php 3 years ago queryembed.php 3 years ago queryimage.php 3 years ago querytext.php 3 years ago querytranscribe.php 3 years ago rest.php 3 years ago security.php 3 years ago
core.php
489 lines
1 <?php
2
3 require_once( MWAI_PATH . '/vendor/autoload.php' );
4 require_once( MWAI_PATH . '/constants/init.php' );
5
6 use Rahul900day\Gpt3Encoder\Encoder;
7
8 define( 'MWAI_IMG_WAND', MWAI_URL . '/images/wand.png' );
9 define( 'MWAI_IMG_WAND_HTML', "<img style='height: 22px; margin-bottom: -5px; margin-right: 8px;'
10 src='" . MWAI_IMG_WAND . "' alt='AI Wand' />" );
11 define( 'MWAI_IMG_WAND_HTML_XS', "<img style='height: 16px; margin-bottom: -2px;'
12 src='" . MWAI_IMG_WAND . "' alt='AI Wand' />" );
13 class Meow_MWAI_Core
14 {
15 public $admin = null;
16 public $is_rest = false;
17 public $is_cli = false;
18 public $site_url = null;
19 public $ai = null;
20 private $option_name = 'mwai_options';
21 private $themes_option_name = 'mwai_themes';
22 private $chatbots_option_name = 'mwai_chatbots';
23 public $defaultChatbotParams = MWAI_CHATBOT_PARAMS;
24
25 public function __construct() {
26 $this->site_url = get_site_url();
27 $this->is_rest = MeowCommon_Helpers::is_rest();
28 $this->is_cli = defined( 'WP_CLI' );
29 $this->ai = new Meow_MWAI_AI( $this );
30 add_action( 'plugins_loaded', array( $this, 'init' ) );
31 }
32
33 function init() {
34 global $mwai;
35 $mwai = new Meow_MWAI_API();
36 new Meow_MWAI_Security( $this );
37 if ( $this->is_rest ) {
38 new Meow_MWAI_Rest( $this );
39 }
40 if ( is_admin() ) {
41 new Meow_MWAI_Admin( $this );
42 new Meow_MWAI_Modules_Assistants( $this );
43 }
44 if ( $this->get_option( 'shortcode_chat' ) ) {
45 new Meow_MWAI_Modules_Chatbot();
46 new Meow_MWAI_Modules_Chatbot_Legacy();
47 new Meow_MWAI_Modules_Discussions();
48 }
49
50 // Advanced core
51 if ( class_exists( 'MeowPro_MWAI_Core' ) ) {
52 new MeowPro_MWAI_Core( $this );
53 }
54
55 // Dynamic max tokens
56 if ( $this->get_option( 'dynamic_max_tokens' ) ) {
57 add_filter( 'mwai_estimate_tokens', array( $this, 'dynamic_max_tokens' ), 10, 2 );
58 }
59 }
60
61 #region Roles & Capabilities
62
63 function can_access_settings() {
64 return apply_filters( 'mwai_allow_setup', current_user_can( 'manage_options' ) );
65 }
66
67 function can_access_features() {
68 $editor_or_admin = current_user_can( 'editor' ) || current_user_can( 'administrator' );
69 return apply_filters( 'mwai_allow_usage', $editor_or_admin );
70 }
71
72 #endregion
73
74 #region Text-Related Helpers
75
76 // Clean the text perfectly, resolve shortcodes, etc, etc.
77 function cleanText( $rawText = "" ) {
78 $text = html_entity_decode( $rawText );
79 $text = wp_strip_all_tags( $text );
80 $text = preg_replace( '/[\r\n]+/', "\n", $text );
81 return $text . " ";
82
83 // Before simplification:
84 // $text = strip_tags( $rawText );
85 // $text = strip_shortcodes( $text );
86 // $text = html_entity_decode( $text );
87 // $text = preg_replace( '/[\r\n]+/', "\n", $text );
88 // $sentences = preg_split( '/(?<=[.?!])(?=[a-zA-Z ])/', $text );
89 // foreach ( $sentences as $key => $sentence ) {
90 // $sentences[$key] = trim( $sentence );
91 // }
92 // $text = implode( " ", $sentences );
93 // $text = preg_replace( '/^[\pZ\pC]+|[\pZ\pC]+$/u', '', $text );
94 // return $text . " ";
95 }
96
97 // Make sure there are no duplicate sentences, and keep the length under a maximum length.
98 function cleanSentences( $text, $maxTokens = null ) {
99 //$sentences = preg_split( '/(?<=[.?!])(?=[a-zA-Z ])/', $text );
100 $maxTokens = $maxTokens ? $maxTokens : $this->get_option( 'context_max_tokens', 1024 );
101 $sentences = preg_split('/(?<=[.?!。.!?])+/u', $text);
102 $hashes = array();
103 $uniqueSentences = array();
104 $length = 0;
105 foreach ( $sentences as $sentence ) {
106 $sentence = preg_replace( '/^[\pZ\pC]+|[\pZ\pC]+$/u', '', $sentence );
107 $hash = md5( $sentence );
108 if ( !in_array( $hash, $hashes ) ) {
109 $tokensCount = apply_filters( 'mwai_estimate_tokens', 0, $sentence );
110 if ( $length + $tokensCount > $maxTokens ) {
111 continue;
112 }
113 $hashes[] = $hash;
114 $uniqueSentences[] = $sentence;
115 $length += $tokensCount;
116 }
117 }
118 $freshText = implode( " ", $uniqueSentences );
119 $freshText = preg_replace( '/^[\pZ\pC]+|[\pZ\pC]+$/u', '', $freshText );
120 return $freshText;
121 }
122
123 function getCleanPostContent( $postId ) {
124 $post = get_post( $postId );
125 if ( !$post ) {
126 return false;
127 }
128 $text = $post->post_content;
129 $pattern = '/\[mwai_.*?\]/';
130 $text = preg_replace( $pattern, '', $text );
131 if ( $this->get_option( 'resolve_shortcodes' ) ) {
132 $text = apply_filters( 'the_content', $text );
133 }
134 $text = $this->cleanText( $text );
135 $text = $this->cleanSentences( $text );
136 return $text;
137 }
138
139 function markdown_to_html( $content ) {
140 $Parsedown = new Parsedown();
141 $content = $Parsedown->text( $content );
142 return $content;
143 }
144
145 function get_post_language( $postId ) {
146 $locale = get_locale();
147 $code = strtolower( substr( $locale, 0, 2 ) );
148 $humanLanguage = strtr( $code, MWAI_ALL_LANGUAGES );
149 $lang = apply_filters( 'wpml_post_language_details', null, $postId );
150 if ( !empty( $lang ) ) {
151 $locale = $lang['locale'];
152 $humanLanguage = $lang['display_name'];
153 }
154 return strtolower( "$locale ($humanLanguage)" );
155 }
156 #endregion
157
158 #region Users/Sessions Helpers
159
160 function get_session_id() {
161 if ( isset( $_COOKIE['mwai_session_id'] ) ) {
162 return $_COOKIE['mwai_session_id'];
163 }
164 return "N/A";
165 }
166
167 // Get the UserID from the data, or from the current user
168 function get_user_id( $data = null ) {
169 if ( isset( $data ) && isset( $data['userId'] ) ) {
170 return (int)$data['userId'];
171 }
172 if ( is_user_logged_in() ) {
173 $current_user = wp_get_current_user();
174 if ( $current_user->ID > 0 ) {
175 return $current_user->ID;
176 }
177 }
178 return null;
179 }
180
181 function getUserData() {
182 $user = wp_get_current_user();
183 $placeholders = array(
184 'FIRST_NAME' => get_user_meta( $user->ID, 'first_name', true ),
185 'LAST_NAME' => get_user_meta( $user->ID, 'last_name', true ),
186 'USER_LOGIN' => $user && $user->data ? $user->data->user_login : null,
187 'DISPLAY_NAME' => $user && $user->data ? $user->data->display_name : null,
188 'AVATAR_URL' => get_avatar_url( get_current_user_id() ),
189 );
190 return $placeholders;
191 }
192
193 function get_ip_address( $data = null ) {
194 if ( isset( $data ) && isset( $data['ip'] ) ) {
195 $data['ip'] = (string)$data['ip'];
196 }
197 else {
198 if ( isset( $_SERVER['REMOTE_ADDR'] ) ) {
199 $data['ip'] = sanitize_text_field( $_SERVER['REMOTE_ADDR'] );
200 }
201 else if ( isset( $_SERVER['HTTP_CLIENT_IP'] ) ) {
202 $data['ip'] = sanitize_text_field( $_SERVER['HTTP_CLIENT_IP'] );
203 }
204 else if ( isset( $_SERVER['HTTP_X_FORWARDED_ FOR'] ) ) {
205 $data['ip'] = sanitize_text_field( $_SERVER['HTTP_X_FORWARDED_FOR'] );
206 }
207 }
208 $ip = apply_filters( 'mwai_get_ip_address', $data['ip'] );
209 return $ip;
210 }
211
212 #endregion
213
214 #region Other Helpers
215
216 function isUrl( $url ) {
217 return strpos( $url, 'http' ) === 0 ? true : false;
218 }
219
220 function getPostTypes() {
221 $excluded = array( 'attachment', 'revision', 'nav_menu_item' );
222 $post_types = array();
223 $types = get_post_types( array( 'public' => true ), 'objects' );
224 foreach ( $types as $type ) {
225 if ( in_array( $type->name, $excluded ) ) {
226 continue;
227 }
228 $post_types[] = array(
229 'name' => $type->labels->name,
230 'type' => $type->name,
231 );
232 }
233 return $post_types;
234 }
235
236 function getCleanPost( $post ) {
237 if ( is_object( $post ) ) {
238 $post = (array)$post;
239 }
240 $language = $this->get_post_language( $post['ID'] );
241 $content = apply_filters( 'mwai_pre_post_content', $post['post_content'], $post['ID'] );
242 $content = $this->cleanText( $content );
243 $content = apply_filters( 'mwai_post_content', $content, $post['ID'] );
244 $title = $post['post_title'];
245 $excerpt = $post['post_excerpt'];
246 $url = get_permalink( $post['ID'] );
247 $checksum = wp_hash( $content . $title . $url );
248 return [
249 'postId' => $post['ID'],
250 'title' => $title,
251 'content' => $content,
252 'excerpt' => $excerpt,
253 'url' => $url,
254 'language' => $language,
255 'checksum' => $checksum,
256 ];
257 }
258
259 #endregion
260
261 #region Usage & Costs
262
263 public function dynamic_max_tokens( $tokens, $text ) {
264 // Approximation (fast, no lib)
265 $asciiCount = 0;
266 $nonAsciiCount = 0;
267 for ( $i = 0; $i < mb_strlen( $text ); $i++ ) {
268 $char = mb_substr( $text, $i, 1 );
269 if ( ord( $char ) < 128 ) {
270 $asciiCount++;
271 }
272 else {
273 $nonAsciiCount++;
274 }
275 }
276 $asciiTokens = $asciiCount / 3.5;
277 $nonAsciiTokens = $nonAsciiCount * 2.5;
278 $tokens = $asciiTokens + $nonAsciiTokens;
279
280 // More exact (slower, and lib)
281 if ( PHP_VERSION_ID >= 70400 && function_exists( 'mb_convert_encoding' ) ) {
282 try {
283 $token_array = Encoder::encode( $text );
284 if ( !empty( $token_array ) ) {
285 $tokens = count( $token_array );
286 }
287 }
288 catch ( Exception $e ) {
289 error_log( $e->getMessage() );
290 }
291 }
292
293 $tokens = $tokens;
294 return (int)$tokens;
295 }
296
297 public function record_tokens_usage( $model, $prompt_tokens, $completion_tokens = 0 ) {
298 if ( !is_numeric( $prompt_tokens ) ) {
299 throw new Exception( 'Record usage: prompt_tokens is not a number.' );
300 }
301 if ( !is_numeric( $completion_tokens ) ) {
302 $completion_tokens = 0;
303 }
304 if ( !$model ) {
305 throw new Exception( 'Record usage: model is missing.' );
306 }
307 $usage = $this->get_option( 'openai_usage' );
308 $month = date( 'Y-m' );
309 if ( !isset( $usage[$month] ) ) {
310 $usage[$month] = array();
311 }
312 if ( !isset( $usage[$month][$model] ) ) {
313 $usage[$month][$model] = array(
314 'prompt_tokens' => 0,
315 'completion_tokens' => 0,
316 'total_tokens' => 0
317 );
318 }
319 $usage[$month][$model]['prompt_tokens'] += $prompt_tokens;
320 $usage[$month][$model]['completion_tokens'] += $completion_tokens;
321 $usage[$month][$model]['total_tokens'] += $prompt_tokens + $completion_tokens;
322 $this->update_option( 'openai_usage', $usage );
323 return [
324 'prompt_tokens' => $prompt_tokens,
325 'completion_tokens' => $completion_tokens,
326 'total_tokens' => $prompt_tokens + $completion_tokens
327 ];
328 }
329
330 public function record_images_usage( $model, $resolution, $images ) {
331 if ( !$model || !$resolution || !$images ) {
332 throw new Exception( 'Missing parameters for record_image_usage.' );
333 }
334 $usage = $this->get_option( 'openai_usage' );
335 $month = date( 'Y-m' );
336 if ( !isset( $usage[$month] ) ) {
337 $usage[$month] = array();
338 }
339 if ( !isset( $usage[$month][$model] ) ) {
340 $usage[$month][$model] = array(
341 'resolution' => array(),
342 'images' => 0
343 );
344 }
345 if ( !isset( $usage[$month][$model]['resolution'][$resolution] ) ) {
346 $usage[$month][$model]['resolution'][$resolution] = 0;
347 }
348 $usage[$month][$model]['resolution'][$resolution] += $images;
349 $usage[$month][$model]['images'] += $images;
350 $this->update_option( 'openai_usage', $usage );
351 return [
352 'resolution' => $resolution,
353 'images' => $images
354 ];
355 }
356
357 #endregion
358
359 #region Options
360 function getThemes()
361 {
362 $themes = get_option( $this->themes_option_name, [] );
363 $themes = empty( $themes ) ? [] : $themes;
364
365 $internalThemes = [
366 'chatgpt' => [
367 'type' => 'internal', 'name' => 'ChatGPT', 'themeId' => 'chatgpt',
368 'settings' => [], 'style' => ""
369 ],
370 'messages' => [
371 'type' => 'internal', 'name' => 'Messages', 'themeId' => 'messages',
372 'settings' => [], 'style' => ""
373 ],
374 ];
375 $customThemes = [];
376 foreach ( $themes as $theme ) {
377 if ( isset( $internalThemes[$theme['themeId']] ) ) {
378 $internalThemes[$theme['themeId']] = $theme;
379 continue;
380 }
381 $customThemes[] = $theme;
382 }
383 return array_merge(array_values($internalThemes), $customThemes);
384 }
385
386 function updateThemes( $themes ) {
387 update_option( $this->themes_option_name, $themes );
388 return $themes;
389 }
390
391 function getChatbots() {
392 $chatbots = get_option( $this->chatbots_option_name, [] );
393 if ( empty( $chatbots ) ) {
394 $chatbots = [ array_merge( MWAI_CHATBOT_DEFAULT_PARAMS, ['name' => 'Default', 'chatId' => 'default' ] ) ];
395 }
396 foreach ( $chatbots as $chatbot ) {
397 foreach ( MWAI_CHATBOT_DEFAULT_PARAMS as $key => $value ) {
398 if ( !isset( $chatbot[$key] ) ) {
399 $chatbot[$key] = $value;
400 }
401 }
402 }
403 return $chatbots;
404 }
405
406 function getChatbot( $chatId ) {
407 $chatbots = $this->getChatbots();
408 foreach ( $chatbots as $chatbot ) {
409 if ( $chatbot['chatId'] === $chatId ) {
410 // Somehow, the default was set to "openai" when creating a new chatbot, but that overrided
411 // the default value in the Settings. It should be always empty here (except if we add this
412 // into the Settings of the chatbot).
413 $chatbot['service'] = null;
414 return $chatbot;
415 }
416 }
417 return null;
418 }
419
420 function getTheme( $themeId ) {
421 $themes = $this->getThemes();
422 foreach ( $themes as $theme ) {
423 if ( $theme['themeId'] === $themeId ) {
424 return $theme;
425 }
426 }
427 return null;
428 }
429
430 function updateChatbots( $chatbots ) {
431 update_option( $this->chatbots_option_name, $chatbots );
432 return $chatbots;
433 }
434
435 function get_all_options() {
436 $options = get_option( $this->option_name, null );
437 foreach ( MWAI_OPTIONS as $key => $value ) {
438 if ( !isset( $options[$key] ) ) {
439 $options[$key] = $value;
440 }
441 if ( $key === 'languages' ) {
442 // TODO: If we decide to make a set of options for languages, we can keep it in the settings
443 $options[$key] = MWAI_LANGUAGES;
444 $options[$key] = apply_filters( 'mwai_languages', $options[$key] );
445 }
446 }
447 $options['shortcode_chat_default_params'] = MWAI_CHATBOT_PARAMS;
448 $options['chatbot_defaults'] = MWAI_CHATBOT_DEFAULT_PARAMS;
449 $options['default_limits'] = MWAI_LIMITS;
450 $options['openai_models'] = MWAI_OPENAI_MODELS;
451 return $options;
452 }
453
454 // Validate and keep the options clean and logical.
455 function sanitize_options() {
456 $options = $this->get_all_options();
457 $needs_update = false;
458
459 // We can sanitize our future options here, let's always remember it.
460 // Now, it is empty...
461
462 if ( $needs_update ) {
463 update_option( $this->option_name, $options, false );
464 }
465 return $options;
466 }
467
468 function update_options( $options ) {
469 if ( !update_option( $this->option_name, $options, false ) ) {
470 return false;
471 }
472 $options = $this->sanitize_options();
473 return $options;
474 }
475
476 function update_option( $option, $value ) {
477 $options = $this->get_all_options();
478 $options[$option] = $value;
479 return $this->update_options( $options );
480 }
481
482 function get_option( $option, $default = null ) {
483 $options = $this->get_all_options();
484 return $options[$option] ?? $default;
485 }
486 #endregion
487 }
488
489 ?>