PluginProbe ʕ •ᴥ•ʔ
AI Engine – The Chatbot, AI Framework & MCP for WordPress / 2.1.1
AI Engine – The Chatbot, AI Framework & MCP for WordPress v2.1.1
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 / modules / chatbot.php
ai-engine / classes / modules Last commit date
chatbot.php 2 years ago discussions.php 2 years ago files.php 2 years ago security.php 2 years ago utilities.php 2 years ago
chatbot.php
504 lines
1 <?php
2
3 // Params for the chatbot (front and server)
4
5 define( 'MWAI_CHATBOT_FRONT_PARAMS', [ 'id', 'customId', 'aiName', 'userName', 'guestName',
6 'textSend', 'textClear', 'imageUpload',
7 'textInputPlaceholder', 'textInputMaxLength', 'textCompliance', 'startSentence', 'localMemory',
8 'themeId', 'window', 'icon', 'iconText', 'iconAlt', 'iconPosition', 'fullscreen', 'copyButton'
9 ] );
10 // TODO: Actually, 'env' is being replaced by 'scope', so we need to really remove it from here
11 // after, February 2024.
12 define( 'MWAI_CHATBOT_SERVER_PARAMS', [ 'id', 'envId', 'env', 'scope', 'mode', 'contentAware', 'context',
13 'embeddingsEnvId', 'embeddingsIndex', 'embeddingsNamespace', 'assistantId',
14 'model', 'temperature', 'maxTokens', 'contextMaxLength', 'maxResults', 'apiKey'
15 ] );
16
17 // Params for the discussions (front and server)
18
19 define( 'MWAI_DISCUSSIONS_FRONT_PARAMS', [ 'themeId', 'textNewChat' ] );
20 define( 'MWAI_DISCUSSIONS_SERVER_PARAMS', [ 'customId' ] );
21
22 class Meow_MWAI_Modules_Chatbot {
23 private $core = null;
24 private $namespace = 'mwai-ui/v1';
25 private $siteWideChatId = null;
26
27 public function __construct() {
28 global $mwai_core;
29 $this->core = $mwai_core;
30 add_shortcode( 'mwai_chatbot', array( $this, 'chat_shortcode' ) );
31 add_shortcode( 'mwai_chatbot_v2', array( $this, 'chat_shortcode' ) );
32 add_action( 'rest_api_init', array( $this, 'rest_api_init' ) );
33 $this->siteWideChatId = $this->core->get_option( 'botId' );
34 add_action( 'wp_enqueue_scripts', array( $this, 'register_scripts' ) );
35
36 if ( $this->core->get_option( 'shortcode_chat_discussions' ) ) {
37 add_shortcode( 'mwai_discussions', [ $this, 'shortcode_chat_discussions' ] );
38 }
39 }
40
41 public function register_scripts() {
42 $physical_file = trailingslashit( MWAI_PATH ) . 'app/chatbot.js';
43 $cache_buster = file_exists( $physical_file ) ? filemtime( $physical_file ) : MWAI_VERSION;
44 wp_register_script( 'mwai_chatbot', trailingslashit( MWAI_URL ) . 'app/chatbot.js',
45 [ 'wp-element' ], $cache_buster, false );
46 if ( !empty( $this->siteWideChatId ) && $this->siteWideChatId !== 'none' ) {
47 $this->enqueue_scripts();
48 add_action( 'wp_footer', array( $this, 'inject_chat' ) );
49 }
50 }
51
52 public function enqueue_scripts() {
53 wp_enqueue_script( "mwai_chatbot" );
54 if ( $this->core->get_option( 'shortcode_chat_syntax_highlighting' ) ) {
55 wp_enqueue_script( "mwai_highlight" );
56 }
57 }
58
59 public function rest_api_init() {
60 register_rest_route( $this->namespace, '/chats/submit', array(
61 'methods' => 'POST',
62 'callback' => [ $this, 'rest_chat' ],
63 'permission_callback' => array( $this->core, 'check_rest_nonce' )
64 ) );
65 }
66
67 public function basics_security_check( $botId, $customId, $newMessage ) {
68 if ( empty( $newMessage ) ) {
69 error_log("AI Engine: The query was rejected - message was empty.");
70 return false;
71 }
72 if ( !$botId && !$customId ) {
73 error_log("AI Engine: The query was rejected - no botId nor id was specified.");
74 return false;
75 }
76
77 $length = strlen( $newMessage );
78 if ( $length < 1 || $length > ( 4096 * 16 ) ) {
79 error_log("AI Engine: The query was rejected - message was too short or too long.");
80 return false;
81 }
82 return true;
83 }
84
85 public function rest_chat( $request ) {
86 $params = $request->get_json_params();
87 $botId = $params['botId'] ?? null;
88 $customId = $params['customId'] ?? null;
89 $stream = $params['stream'] ?? false;
90 $newMessage = trim( $params['newMessage'] ?? '' );
91 $newImageId = $params['newImageId'] ?? null;
92
93 if ( !$this->basics_security_check( $botId, $customId, $newMessage )) {
94 return new WP_REST_Response( [
95 'success' => false,
96 'message' => apply_filters( 'mwai_ai_exception', 'Sorry, your query has been rejected.' )
97 ], 403 );
98 }
99
100 try {
101 $data = $this->chat_submit( $botId, $newMessage, $newImageId, $params, $stream );
102 return new WP_REST_Response( [
103 'success' => true,
104 'reply' => $data['reply'],
105 'images' => $data['images'],
106 'usage' => $data['usage']
107 ], 200 );
108 }
109 catch ( Exception $e ) {
110 $message = apply_filters( 'mwai_ai_exception', $e->getMessage() );
111 return new WP_REST_Response( [
112 'success' => false,
113 'message' => $message
114 ], 500 );
115 }
116 }
117
118 public function chat_submit( $botId, $newMessage, $newImageId, $params = [], $stream = false ) {
119 try {
120 $chatbot = null;
121 $customId = $params['customId'] ?? null;
122
123 // Custom Chatbot
124 if ( $customId ) {
125 $chatbot = get_transient( 'mwai_custom_chatbot_' . $customId );
126 }
127 // Registered Chatbot
128 if ( !$chatbot && $botId ) {
129 $chatbot = $this->core->get_chatbot( $botId );
130 }
131
132 if ( !$chatbot ) {
133 error_log("AI Engine: No chatbot was found for this query.");
134 throw new Exception( 'Sorry, your query has been rejected.' );
135 }
136
137 // Create QueryText
138 $context = null;
139 $mode = $chatbot['mode'] ?? 'chat';
140
141 if ( $mode === 'images' ) {
142 $query = new Meow_MWAI_Query_Image( $newMessage );
143
144 // Handle Params
145 $newParams = [];
146 foreach ( $chatbot as $key => $value ) {
147 $newParams[$key] = $value;
148 }
149 foreach ( $params as $key => $value ) {
150 $newParams[$key] = $value;
151 }
152 $params = apply_filters( 'mwai_chatbot_params', $newParams );
153 $params['scope'] = empty( $params['scope'] ) ? 'chatbot' : $params['scope'];
154 $query->inject_params( $params );
155 }
156 else {
157 $query = $mode === 'assistant' ? new Meow_MWAI_Query_Assistant( $newMessage ) :
158 new Meow_MWAI_Query_Text( $newMessage, 1024 );
159 $streamCallback = null;
160
161 // Handle Params
162 $newParams = [];
163 foreach ( $chatbot as $key => $value ) {
164 $newParams[$key] = $value;
165 }
166 foreach ( $params as $key => $value ) {
167 $newParams[$key] = $value;
168 }
169 $params = apply_filters( 'mwai_chatbot_params', $newParams );
170 $params['scope'] = empty( $params['scope'] ) ? 'chatbot' : $params['scope'];
171 $query->inject_params( $params );
172
173 // Support for Uploaded Image
174 if ( !empty( $newImageId ) ) {
175 $remote_upload = $this->core->get_option( 'image_remote_upload' );
176 if ( $remote_upload === 'data' ) {
177 $data = $this->core->files->get_base64_data( $newImageId );
178 $query->set_image_data( $data );
179 }
180 else {
181 $url = $this->core->files->get_url( $newImageId );
182 $query->set_image( $url );
183 }
184 }
185
186 // Takeover
187 $takeoverAnswer = apply_filters( 'mwai_chatbot_takeover', null, $query, $params );
188 if ( !empty( $takeoverAnswer ) ) {
189 return [
190 'reply' => $takeoverAnswer,
191 'images' => null,
192 'usage' => null
193 ];
194 }
195
196 // Moderation
197 if ( $this->core->get_option( 'shortcode_chat_moderation' ) ) {
198 global $mwai;
199 $isFlagged = $mwai->moderationCheck( $query->get_message() );
200 if ( $isFlagged ) {
201 throw new Exception( 'Sorry, your message has been rejected by moderation.' );
202 }
203 }
204
205 // Awareness & Embeddings
206 // TODO: We probably don't need to limit the context...
207 //if ( $query->mode === 'chat' || $query->mode === 'assistant' ) {
208 $context = $this->core->retrieve_context( $params, $query );
209 if ( !empty( $context ) ) {
210 $query->set_context( $context['content'] );
211 }
212 //}
213 }
214
215 // Process Query
216 if ( $stream ) {
217 $streamCallback = function( $reply ) {
218 $raw = $reply;
219 $this->stream_push( [ 'type' => 'live', 'data' => $raw ] );
220 if ( ob_get_level() > 0 ) {
221 ob_flush();
222 }
223 flush();
224 };
225 header( 'Cache-Control: no-cache' );
226 header( 'Content-Type: text/event-stream' );
227 // This is useful to disable buffering in nginx through headers.
228 header( 'X-Accel-Buffering: no' );
229 ob_implicit_flush( true );
230 ob_end_flush();
231 }
232
233 $reply = $this->core->run_query( $query, $streamCallback );
234 $rawText = $reply->result;
235 $extra = [];
236 if ( $context ) {
237 $extra = [ 'embeddings' => $context['embeddings'] ];
238 }
239 $rawText = apply_filters( 'mwai_chatbot_reply', $rawText, $query, $params, $extra );
240
241 $restRes = [
242 'reply' => $rawText,
243 'images' => $reply->get_type() === 'images' ? $reply->results : null,
244 'usage' => $reply->usage
245 ];
246
247 // Process Reply
248 if ( $stream ) {
249 $this->stream_push( [
250 'type' => 'end',
251 'data' => json_encode([
252 'success' => true,
253 'reply' => $restRes['reply'],
254 'images' => $restRes['images'],
255 'usage' => $restRes['usage']
256 ])
257 ] );
258 die();
259 }
260 else {
261 return $restRes;
262 }
263
264 }
265 catch ( Exception $e ) {
266 $message = apply_filters( 'mwai_ai_exception', $e->getMessage() );
267 if ( $stream ) {
268 $this->stream_push( [ 'type' => 'error', 'data' => $message ] );
269 die();
270 }
271 else {
272 throw $e;
273 }
274 }
275 }
276
277 public function stream_push( $data ) {
278 $out = "data: " . json_encode( $data );
279 echo $out;
280 echo "\n\n";
281 if (ob_get_level() > 0) {
282 ob_end_flush();
283 }
284 flush();
285 }
286
287 public function inject_chat() {
288 $params = $this->core->get_chatbot( $this->siteWideChatId );
289 $clean_params = [];
290 if ( !empty( $params ) ) {
291 $clean_params['window'] = true;
292 $clean_params['id'] = $this->siteWideChatId;
293 echo $this->chat_shortcode( $clean_params );
294 }
295 return null;
296 }
297
298 public function build_front_params( $botId, $customId ) {
299 $frontSystem = [
300 'botId' => $customId ? null : $botId,
301 'customId' => $customId,
302 'userData' => $this->core->get_user_data(),
303 'sessionId' => $this->core->get_session_id(),
304 'restNonce' => $this->core->get_nonce(),
305 'contextId' => get_the_ID(),
306 'pluginUrl' => MWAI_URL,
307 'restUrl' => untrailingslashit( get_rest_url() ),
308 'debugMode' => $this->core->get_option( 'debug_mode' ),
309 'typewriter' => $this->core->get_option( 'shortcode_chat_typewriter' ),
310 'speech_recognition' => $this->core->get_option( 'speech_recognition' ),
311 'speech_synthesis' => $this->core->get_option( 'speech_synthesis' ),
312 'stream' => $this->core->get_option( 'shortcode_chat_stream' ),
313 ];
314 return $frontSystem;
315 }
316
317 public function resolveBotInfo( &$atts )
318 {
319 $chatbot = null;
320 $botId = $atts['id'] ?? null;
321 $customId = $atts['custom_id'] ?? null;
322 if (!$botId && !$customId) {
323 $botId = "default";
324 }
325 if ( $botId ) {
326 $chatbot = $this->core->get_chatbot( $botId );
327 if (!$chatbot) {
328 $botId = $botId ?: 'N/A';
329 return [
330 'error' => "AI Engine: Chatbot '{$botId}' not found. If you meant to set an ID for your custom chatbot, please use 'custom_id' instead of 'id'.",
331 ];
332 }
333 }
334 $chatbot = $chatbot ?: $this->core->get_chatbot( 'default' );
335 if ( !empty( $customId ) ) {
336 $botId = null;
337 }
338 unset( $atts['id'] );
339 return [
340 'chatbot' => $chatbot,
341 'botId' => $botId,
342 'customId' => $customId,
343 ];
344 }
345
346 public function chat_shortcode( $atts ) {
347 $atts = empty( $atts ) ? [] : $atts;
348
349 // Let the user override the chatbot params
350 $atts = apply_filters( 'mwai_chatbot_params', $atts );
351
352 // Resolve the bot info
353 $resolvedBot = $this->resolveBotInfo( $atts, 'chatbot' );
354 if ( isset( $resolvedBot['error'] ) ) {
355 return $resolvedBot['error'];
356 }
357 $chatbot = $resolvedBot['chatbot'];
358 $botId = $resolvedBot['botId'];
359 $customId = $resolvedBot['customId'];
360
361 // Rename the keys of the atts into camelCase to match the internal params system.
362 $atts = array_map( function( $key, $value ) {
363 $key = str_replace( '_', ' ', $key );
364 $key = ucwords( $key );
365 $key = str_replace( ' ', '', $key );
366 $key = lcfirst( $key );
367 return [ $key => $value ];
368 }, array_keys( $atts ), $atts );
369 $atts = array_merge( ...$atts );
370
371 $frontParams = [];
372 foreach ( MWAI_CHATBOT_FRONT_PARAMS as $param ) {
373 if ( isset( $atts[$param] ) ) {
374 if ( $param === 'localMemory' ) {
375 $frontParams[$param] = $atts[$param] === 'true';
376 }
377 else {
378 $frontParams[$param] = $atts[$param];
379 }
380 }
381 else if ( isset( $chatbot[$param] ) ) {
382 $frontParams[$param] = $chatbot[$param];
383 }
384 }
385
386 // Server Params
387 // NOTE: We don't need the server params for the chatbot if there are no overrides, it means
388 // we are using the default or a specific chatbot.
389 $hasServerOverrides = count( array_intersect( array_keys( $atts ), MWAI_CHATBOT_SERVER_PARAMS ) ) > 0;
390 $serverParams = [];
391 if ( $hasServerOverrides ) {
392 foreach ( MWAI_CHATBOT_SERVER_PARAMS as $param ) {
393 if ( isset( $atts[$param] ) ) {
394 $serverParams[$param] = $atts[$param];
395 }
396 else {
397 $serverParams[$param] = $chatbot[$param] ?? null;
398 }
399 }
400 }
401
402 // Front Params
403 $frontSystem = $this->build_front_params( $botId, $customId );
404
405 // Clean Params
406 $frontParams = $this->clean_params( $frontParams );
407 $frontSystem = $this->clean_params( $frontSystem );
408 $serverParams = $this->clean_params( $serverParams );
409
410 // Server-side: Keep the System Params
411 if ( $hasServerOverrides ) {
412 if ( empty( $customId ) ) {
413 $customId = md5( json_encode( $serverParams ) );
414 $frontSystem['customId'] = $customId;
415 }
416 set_transient( 'mwai_custom_chatbot_' . $customId, $serverParams, 60 * 60 * 24 );
417 }
418
419 // Client-side: Prepare JSON for Front Params and System Params
420 $theme = isset( $frontParams['themeId'] ) ? $this->core->get_theme( $frontParams['themeId'] ) : null;
421 $jsonFrontParams = htmlspecialchars( json_encode( $frontParams ), ENT_QUOTES, 'UTF-8' );
422 $jsonFrontSystem = htmlspecialchars( json_encode( $frontSystem ), ENT_QUOTES, 'UTF-8' );
423 $jsonFrontTheme = htmlspecialchars( json_encode( $theme ), ENT_QUOTES, 'UTF-8' );
424 //$jsonAttributes = htmlspecialchars(json_encode($atts), ENT_QUOTES, 'UTF-8');
425
426 $this->enqueue_scripts();
427 return "<div class='mwai-chatbot-container' data-params='{$jsonFrontParams}' data-system='{$jsonFrontSystem}' data-theme='{$jsonFrontTheme}'></div>";
428 }
429
430 function shortcode_chat_discussions( $atts ) {
431 $atts = empty($atts) ? [] : $atts;
432
433 // Resolve the bot info
434 $resolvedBot = $this->resolveBotInfo( $atts );
435 if ( isset( $resolvedBot['error'] ) ) {
436 return $resolvedBot['error'];
437 }
438 $chatbot = $resolvedBot['chatbot'];
439 $botId = $resolvedBot['botId'];
440 $customId = $resolvedBot['customId'];
441
442 // Rename the keys of the atts into camelCase to match the internal params system.
443 $atts = array_map( function( $key, $value ) {
444 $key = str_replace( '_', ' ', $key );
445 $key = ucwords( $key );
446 $key = str_replace( ' ', '', $key );
447 $key = lcfirst( $key );
448 return [ $key => $value ];
449 }, array_keys( $atts ), $atts );
450 $atts = array_merge( ...$atts );
451
452 // Front Params
453 $frontParams = [];
454 foreach ( MWAI_DISCUSSIONS_FRONT_PARAMS as $param ) {
455 if ( isset( $atts[$param] ) ) {
456 $frontParams[$param] = $atts[$param];
457 }
458 else if ( isset( $chatbot[$param] ) ) {
459 $frontParams[$param] = $chatbot[$param];
460 }
461 }
462
463 // Server Params
464 $serverParams = [];
465 foreach ( MWAI_DISCUSSIONS_SERVER_PARAMS as $param ) {
466 if ( isset( $atts[$param] ) ) {
467 $serverParams[$param] = $atts[$param];
468 }
469 }
470
471 // Front System
472 $frontSystem = $this->build_front_params( $botId, $customId );
473
474 // Clean Params
475 $frontParams = $this->clean_params( $frontParams );
476 $frontSystem = $this->clean_params( $frontSystem );
477 $serverParams = $this->clean_params( $serverParams );
478
479 $theme = isset( $frontParams['themeId'] ) ? $this->core->get_theme( $frontParams['themeId'] ) : null;
480 $jsonFrontParams = htmlspecialchars( json_encode( $frontParams ), ENT_QUOTES, 'UTF-8' );
481 $jsonFrontSystem = htmlspecialchars( json_encode( $frontSystem ), ENT_QUOTES, 'UTF-8' );
482 $jsonFrontTheme = htmlspecialchars( json_encode( $theme ), ENT_QUOTES, 'UTF-8' );
483
484 return "<div class='mwai-discussions-container' data-params='{$jsonFrontParams}' data-system='{$jsonFrontSystem}' data-theme='{$jsonFrontTheme}'></div>";
485 }
486
487 function clean_params( &$params ) {
488 foreach ( $params as $param => $value ) {
489 if ( empty( $value ) || is_array( $value ) ) {
490 continue;
491 }
492 $lowerCaseValue = strtolower( $value );
493 if ( $lowerCaseValue === 'true' || $lowerCaseValue === 'false' || is_bool( $value ) ) {
494 $params[$param] = filter_var( $value, FILTER_VALIDATE_BOOLEAN );
495 }
496 else if ( is_numeric( $value ) ) {
497 $params[$param] = filter_var( $value, FILTER_VALIDATE_FLOAT );
498 }
499 }
500 return $params;
501 }
502
503 }
504