PluginProbe
WPBot – AI ChatBot for Live Support, Lead Generation, WordPress Automation, AI Services / 8.8.1
WPBot – AI ChatBot for Live Support, Lead Generation, WordPress Automation, AI Services v8.8.1
8.8.1 8.8.0 8.7.9 8.7.8 8.7.7 8.7.6 8.7.5 8.7.4 8.7.3 8.7.2 8.7.1 8.7.0 8.6.9 8.6.8 8.6.7 8.6.6 8.6.5 8.6.4 8.6.2 8.6.1 8.6.0 8.5.9 8.5.8 8.5.7 8.5.6 All 537 releases
chatbot / addons / automator / includes / actions / wordpress-actions.php

wordpress-actions.php in WPBot – AI ChatBot for Live Support, Lead Generation, WordPress Automation, AI Services 8.8.1, at addons/automator/includes/actions/wordpress-actions.php

867 lines 29.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * WordPress Actions
4 *
5 * @package WPbot_Automator
6 */
7
8 namespace WPbot_Automator\Actions;
9
10 if ( ! defined( 'ABSPATH' ) ) {
11 exit;
12 }
13
14 /**
15 * Class WordPress_Actions
16 */
17 class WordPress_Actions extends Action {
18
19 /**
20 * Constructor
21 */
22 public function __construct() {
23 $this->id = 'wordpress';
24 $this->group = __( 'WordPress', 'wpbot-automator' );
25 }
26
27 /**
28 * Execute the action
29 *
30 * @param array $action_data Configuration for this action from the workflow.
31 * @param array $trigger_data Data passed from the trigger.
32 * @return bool|array
33 */
34 public function execute( $action_data, $trigger_data ) {
35 $action_id = isset( $action_data['actionId'] ) ? $action_data['actionId'] : '';
36
37 if ( empty( $action_id ) ) {
38 return false;
39 }
40
41 switch ( $action_id ) {
42 case 'wp_create_user':
43 case 'wp_user_register':
44 return $this->create_user( $action_data, $trigger_data );
45 case 'wp_update_user':
46 return $this->update_user( $action_data, $trigger_data );
47 case 'wp_delete_user':
48 return $this->delete_user( $action_data, $trigger_data );
49 case 'wp_create_post':
50 case 'wp_create_page':
51 return $this->create_post( $action_data, $trigger_data );
52 case 'wp_update_post':
53 return $this->update_post( $action_data, $trigger_data );
54 case 'wp_create_comment':
55 return $this->create_comment( $action_data, $trigger_data );
56 case 'wp_reply_comment':
57 return $this->reply_comment( $action_data, $trigger_data );
58 case 'wp_ai_generated_post':
59 return $this->ai_generated_post( $action_data, $trigger_data );
60 case 'wp_ai_reply_comment':
61 return $this->ai_reply_comment( $action_data, $trigger_data );
62 case 'wp_ai_generate_social_posts':
63 case 'wp_ai_generate_social_posts_pro':
64 return $this->ai_generate_social_posts( $action_data, $trigger_data );
65 // Add more cases here as needed...
66 default:
67 // Fallback for actions not yet fully implemented
68 return array( 'success' => true, 'message' => "Action {$action_id} executed (simulated)" );
69 }
70 }
71
72 /**
73 * Reply to a comment
74 */
75 private function reply_comment( $config, $trigger_data ) {
76 $config_values = isset( $config['config'] ) ? $config['config'] : array();
77 $parent_id = isset( $config_values['parent_id'] ) ? $this->parse_tokens( $config_values['parent_id'], $trigger_data ) : 0;
78 $comment_content = isset( $config_values['comment_content'] ) ? $this->parse_tokens( $config_values['comment_content'], $trigger_data ) : '';
79
80 // Fallback for parent_id: use comment_id from trigger if available
81 if ( empty( $parent_id ) && isset( $trigger_data['comment_id'] ) ) {
82 $parent_id = is_scalar( $trigger_data['comment_id'] ) ? $trigger_data['comment_id'] : 0;
83 //error_log( "WPbot Automator - reply_comment: Used fallback parent_id: " . $parent_id );
84 }
85
86 // Fallback for content: use 'response' or 'content' from trigger (AI output)
87 if ( empty( $comment_content ) ) {
88 if ( isset( $trigger_data['response'] ) ) {
89 $comment_content = is_scalar( $trigger_data['response'] ) ? (string) $trigger_data['response'] : wp_json_encode( $trigger_data['response'] );
90 //error_log( "WPbot Automator - reply_comment: Used fallback content from {response}" );
91 } elseif ( isset( $trigger_data['content'] ) ) {
92 $comment_content = is_scalar( $trigger_data['content'] ) ? (string) $trigger_data['content'] : wp_json_encode( $trigger_data['content'] );
93 //error_log( "WPbot Automator - reply_comment: Used fallback content from {content}" );
94 }
95 }
96
97 if ( empty( $parent_id ) ) {
98 return array( 'success' => false, 'message' => 'Parent Comment ID is required.' );
99 }
100
101 if ( empty( $comment_content ) ) {
102 return array( 'success' => false, 'message' => 'Reply Content is required.' );
103 }
104
105 $parent_comment = get_comment( $parent_id );
106 if ( ! $parent_comment ) {
107 return array(
108 'success' => false,
109 'message' => 'Parent comment not found for ID: ' . $parent_id,
110 );
111 }
112
113 $comment_id = wp_insert_comment( array(
114 'comment_post_ID' => $parent_comment->comment_post_ID,
115 'comment_parent' => absint( $parent_id ),
116 'comment_content' => $comment_content,
117 'comment_type' => 'comment',
118 'comment_approved' => 1,
119 ) );
120
121 if ( ! $comment_id ) {
122 return array(
123 'success' => false,
124 'message' => 'Failed to create reply.',
125 );
126 }
127
128 return array(
129 'success' => true,
130 'comment_id' => $comment_id,
131 'message' => 'Reply created successfully.',
132 );
133 }
134
135 /**
136 * Create a new user
137 */
138 private function create_user( $config, $trigger_data ) {
139 $config_values = isset( $config['config'] ) ? $config['config'] : array();
140 $user_login = isset( $config_values['user_login'] ) ? $this->parse_tokens( $config_values['user_login'], $trigger_data ) : '';
141 $user_email = isset( $config_values['user_email'] ) ? $this->parse_tokens( $config_values['user_email'], $trigger_data ) : '';
142
143 // Smart Mapping Fallback: If not provided, try to find in trigger_data.
144 if ( empty( $user_email ) ) {
145 $user_email = $this->find_email_in_data( $trigger_data );
146 }
147
148 if ( empty( $user_login ) ) {
149 // Try to find a name or use first part of email.
150 $name = $this->find_name_in_data( $trigger_data );
151 $user_login = ! empty( $name ) ? sanitize_user( strtolower( str_replace( ' ', '.', $name ) ) ) : ( ! empty( $user_email ) ? explode( '@', $user_email )[0] : '' );
152
153 // Safety: WordPress usernames have a 60 character limit.
154 if ( strlen( $user_login ) > 60 ) {
155 $user_login = substr( $user_login, 0, 60 );
156 }
157 }
158
159 $user_pass = isset( $config_values['user_pass'] ) ? $this->parse_tokens( $config_values['user_pass'], $trigger_data ) : wp_generate_password();
160 $role = isset( $config_values['role'] ) ? $config_values['role'] : 'subscriber';
161
162 if ( empty( $user_login ) || empty( $user_email ) ) {
163 return array(
164 'success' => false,
165 'message' => sprintf( 'User login and email are required. Found Login: "%s", Email: "%s"', $user_login, $user_email ),
166 );
167 }
168
169 if ( username_exists( $user_login ) ) {
170 return array(
171 'success' => false,
172 'message' => "Username already exists: $user_login",
173 );
174 }
175
176 if ( email_exists( $user_email ) ) {
177 return array(
178 'success' => false,
179 'message' => "Email already exists: $user_email",
180 );
181 }
182
183 $user_id = wp_insert_user( array(
184 'user_login' => $user_login,
185 'user_email' => $user_email,
186 'user_pass' => $user_pass,
187 'role' => $role,
188 ) );
189
190 if ( is_wp_error( $user_id ) ) {
191 return array(
192 'success' => false,
193 'message' => $user_id->get_error_message(),
194 );
195 }
196
197 return array(
198 'success' => true,
199 'user_id' => $user_id,
200 'message' => 'User created successfully.',
201 );
202 }
203
204 /**
205 * Helper: Find email in trigger data
206 */
207 private function find_email_in_data( $data ) {
208 if ( ! is_array( $data ) ) return '';
209
210 // Flatten and look for keys containing 'email'.
211 $flattened = $this->flatten_array_recursive( $data );
212 foreach ( $flattened as $key => $val ) {
213 if ( is_string( $val ) && is_email( $val ) ) {
214 return $val;
215 }
216 }
217 return '';
218 }
219
220 /**
221 * Helper: Find name in trigger data
222 */
223 private function find_name_in_data( $data ) {
224 if ( ! is_array( $data ) ) return '';
225
226 $flattened = $this->flatten_array_recursive( $data );
227
228 $firstName = '';
229 $lastName = '';
230 $fullName = '';
231
232 foreach ( $flattened as $key => $val ) {
233 if ( ! is_string( $val ) || empty( $val ) ) continue;
234 $low_key = strtolower( $key );
235
236 // Priority 1: Explicit sub-fields (common in WPForms, etc).
237 if ( strpos( $low_key, '.first' ) !== false || strpos( $low_key, 'first_name' ) !== false ) {
238 $firstName = $val;
239 }
240 if ( strpos( $low_key, '.last' ) !== false || strpos( $low_key, 'last_name' ) !== false ) {
241 $lastName = $val;
242 }
243
244 // Priority 2: Generic name field.
245 if ( $low_key === 'fullname' || $low_key === 'full_name' || ( strpos( $low_key, 'name' ) !== false && strpos( $low_key, '.value' ) !== false ) ) {
246 $fullName = $val;
247 }
248 }
249
250 if ( ! empty( $firstName ) || ! empty( $lastName ) ) {
251 return trim( $firstName . ' ' . $lastName );
252 }
253
254 if ( ! empty( $fullName ) ) {
255 return $fullName;
256 }
257
258 // Fallback: Just the FIRST thing that looks like a name.
259 foreach ( $flattened as $key => $val ) {
260 $low_key = strtolower( $key );
261 if ( strpos( $low_key, 'name' ) !== false ) {
262 // Avoid labels.
263 if ( is_string( $val ) && strlen( $val ) > 2 && strlen( $val ) < 50 ) {
264 $low_val = strtolower( trim( $val ) );
265 if ( ! in_array( $low_val, array( 'name', 'first name', 'last name', 'full name', 'email', 'message', 'subject' ) ) ) {
266 return $val;
267 }
268 }
269 }
270 }
271
272 return '';
273 }
274
275 /**
276 * Helper to flatten array recursively
277 */
278 private function flatten_array_recursive( $array, $prefix = '' ) {
279 $result = array();
280 foreach ( $array as $key => $value ) {
281 $new_key = $prefix ? $prefix . '.' . $key : $key;
282 if ( is_array( $value ) ) {
283 $result = array_merge( $result, $this->flatten_array_recursive( $value, $new_key ) );
284 } else {
285 $result[ $new_key ] = $value;
286 }
287 }
288 return $result;
289 }
290
291 /**
292 * Update a user
293 */
294 private function update_user( $config, $trigger_data ) {
295 // Implementation logic...
296 return array( 'success' => true );
297 }
298
299 /**
300 * Delete a user
301 */
302 private function delete_user( $config, $trigger_data ) {
303 // Implementation logic...
304 return array( 'success' => true );
305 }
306
307 /**
308 * Create a new post
309 */
310 private function create_post( $config, $trigger_data ) {
311 $config_values = isset( $config['config'] ) ? $config['config'] : array();
312 $action_id = isset( $config['actionId'] ) ? $config['actionId'] : 'wp_create_post';
313
314 $post_title = isset( $config_values['post_title'] ) ? $this->parse_tokens( $config_values['post_title'], $trigger_data ) : '';
315 $post_content = isset( $config_values['post_content'] ) ? $this->parse_tokens( $config_values['post_content'], $trigger_data ) : '';
316 $post_type = isset( $config_values['post_type'] ) ? $config_values['post_type'] : ( $action_id === 'wp_create_page' ? 'page' : 'post' );
317 $post_status = isset( $config_values['post_status'] ) ? $config_values['post_status'] : 'publish';
318 $categories = isset( $config_values['categories'] ) ? $this->parse_tokens( $config_values['categories'], $trigger_data ) : '';
319
320 if ( empty( $post_title ) || empty( $post_content ) ) {
321 return array(
322 'success' => false,
323 'message' => 'Post Title and Content are required.',
324 );
325 }
326
327 $post_data = array(
328 'post_title' => $post_title,
329 'post_content' => $post_content,
330 'post_status' => $post_status,
331 'post_type' => $post_type,
332 );
333
334 $post_id = wp_insert_post( $post_data );
335
336 if ( is_wp_error( $post_id ) ) {
337 return array(
338 'success' => false,
339 'message' => $post_id->get_error_message(),
340 );
341 }
342
343 // Handle categories/topics if provided.
344 if ( ! empty( $categories ) ) {
345 $cat_ids = array_map( 'trim', explode( ',', $categories ) );
346 wp_set_object_terms( $post_id, $cat_ids, 'category' );
347 }
348
349 return array(
350 'success' => true,
351 'post_id' => $post_id,
352 'message' => sprintf( '%s created successfully.', ucfirst( $post_type ) ),
353 );
354 }
355
356 /**
357 * Update a post
358 */
359 private function update_post( $config, $trigger_data ) {
360 // Implementation logic...
361 return array( 'success' => true );
362 }
363
364 /**
365 * Create a new comment
366 */
367 private function create_comment( $config, $trigger_data ) {
368 $config_values = isset( $config['config'] ) ? $config['config'] : array();
369 $post_id = isset( $config_values['post_id'] ) ? $this->parse_tokens( $config_values['post_id'], $trigger_data ) : 0;
370 $comment_content = isset( $config_values['comment_content'] ) ? $this->parse_tokens( $config_values['comment_content'], $trigger_data ) : '';
371
372 if ( empty( $post_id ) ) {
373 // Try to find a post ID in trigger data if not provided
374 if ( isset( $trigger_data['post_id'] ) ) {
375 $post_id = is_scalar( $trigger_data['post_id'] ) ? $trigger_data['post_id'] : 0;
376 } elseif ( isset( $trigger_data['id'] ) && ( isset( $trigger_data['post_type'] ) || isset( $trigger_data['post_title'] ) ) ) {
377 $post_id = is_scalar( $trigger_data['id'] ) ? $trigger_data['id'] : 0;
378 }
379 }
380
381 // Fallback for content: use 'response' or 'content' from trigger (AI output)
382 if ( empty( $comment_content ) ) {
383 if ( isset( $trigger_data['response'] ) ) {
384 $comment_content = is_scalar( $trigger_data['response'] ) ? (string) $trigger_data['response'] : wp_json_encode( $trigger_data['response'] );
385 //error_log( "WPbot Automator - create_comment: Used fallback content from {response}" );
386 } elseif ( isset( $trigger_data['content'] ) ) {
387 $comment_content = is_scalar( $trigger_data['content'] ) ? (string) $trigger_data['content'] : wp_json_encode( $trigger_data['content'] );
388 //error_log( "WPbot Automator - create_comment: Used fallback content from {content}" );
389 }
390 }
391
392 if ( empty( $post_id ) ) {
393 return array( 'success' => false, 'message' => 'Post ID is required.' );
394 }
395
396 if ( empty( $comment_content ) ) {
397 return array( 'success' => false, 'message' => 'Comment Content is required.' );
398 }
399
400 $comment_id = wp_insert_comment( array(
401 'comment_post_ID' => absint( $post_id ),
402 'comment_content' => $comment_content,
403 'comment_type' => 'comment',
404 'comment_approved' => 1, // Auto-approve for now, or make configurable
405 ) );
406
407 if ( ! $comment_id ) {
408 return array(
409 'success' => false,
410 'message' => 'Failed to create comment.',
411 );
412 }
413
414 return array(
415 'success' => true,
416 'comment_id' => $comment_id,
417 'message' => 'Comment created successfully.',
418 );
419 }
420
421 /**
422 * AI Generated Post
423 */
424 private function ai_generated_post( $config, $trigger_data ) {
425 $config_values = isset( $config['config'] ) ? $config['config'] : array();
426 $instructions = isset( $config_values['prompt_instructions'] ) ? $this->parse_tokens( $config_values['prompt_instructions'], $trigger_data ) : '';
427 $post_title = isset( $config_values['post_title'] ) ? $this->parse_tokens( $config_values['post_title'], $trigger_data ) : '';
428
429 if ( empty( $instructions ) ) {
430 return array( 'success' => false, 'message' => 'Instructions for AI are required.' );
431 }
432
433 // If title is empty, ask AI to generate one.
434 if ( empty( $post_title ) ) {
435 $prompt = "Generate a catchy title and a comprehensive blog post based on these instructions: {$instructions}. Return it in this format: [TITLE]Your Title[/TITLE][CONTENT]Your Content[/CONTENT]";
436 } else {
437 $prompt = "Generate a comprehensive blog post based on these instructions: {$instructions}. The title is already set to: {$post_title}";
438 }
439
440 $ai_response = $this->call_ai( $config_values, $trigger_data, $prompt, "You are a professional WordPress content creator." );
441
442 if ( ! $ai_response['success'] ) {
443 return $ai_response;
444 }
445
446 $content = $ai_response['content'];
447
448 if ( empty( $post_title ) ) {
449 if ( preg_match( '/\[TITLE\](.*?)\[\/TITLE\]/s', $content, $matches ) ) {
450 $post_title = trim( $matches[1] );
451 }
452 if ( preg_match( '/\[CONTENT\](.*?)\[\/CONTENT\]/s', $content, $matches ) ) {
453 $content = trim( $matches[1] );
454 }
455 }
456
457 // Re-use create_post logic.
458 $config['config']['post_title'] = $post_title;
459 $config['config']['post_content'] = $content;
460
461 return $this->create_post( $config, $trigger_data );
462 }
463
464 /**
465 * AI Comment Reply
466 */
467 private function ai_reply_comment( $config, $trigger_data ) {
468 $config_values = isset( $config['config'] ) ? $config['config'] : array();
469 $parent_id = isset( $config_values['parent_id'] ) ? $this->parse_tokens( $config_values['parent_id'], $trigger_data ) : 0;
470 $instructions = isset( $config_values['prompt_instructions'] ) ? $this->parse_tokens( $config_values['prompt_instructions'], $trigger_data ) : '';
471
472 if ( empty( $parent_id ) && isset( $trigger_data['comment_id'] ) ) {
473 $parent_id = $trigger_data['comment_id'];
474 }
475
476 if ( empty( $parent_id ) ) {
477 return array( 'success' => false, 'message' => 'Parent Comment ID is required.' );
478 }
479
480 $parent_comment = get_comment( $parent_id );
481 if ( ! $parent_comment ) {
482 return array( 'success' => false, 'message' => 'Parent comment not found.' );
483 }
484
485 $parent_content = $parent_comment->comment_content;
486 $prompt = "A user commented: \"{$parent_content}\". Generate a reply based on these instructions: {$instructions}";
487
488 $ai_response = $this->call_ai( $config_values, $trigger_data, $prompt, "You are a helpful and polite WordPress site administrator." );
489
490 if ( ! $ai_response['success'] ) {
491 return $ai_response;
492 }
493
494 // Re-use reply_comment logic.
495 $config['config']['parent_id'] = $parent_id;
496 $config['config']['comment_content'] = $ai_response['content'];
497
498 return $this->reply_comment( $config, $trigger_data );
499 }
500
501 /**
502 * AI Generate Social Media Posts
503 */
504 private function ai_generate_social_posts( $config, $trigger_data ) {
505 $config_values = isset( $config['config'] ) ? $config['config'] : array();
506 $action_id = isset( $config['actionId'] ) ? $config['actionId'] : 'wp_ai_generate_social_posts';
507 $source_content = isset( $config_values['source_content'] ) ? $this->parse_tokens( $config_values['source_content'], $trigger_data ) : '';
508 $instructions = isset( $config_values['additional_instructions'] ) ? $this->parse_tokens( $config_values['additional_instructions'], $trigger_data ) : '';
509
510 if ( empty( $source_content ) ) {
511 // Fallback: try to find post content in trigger data.
512 if ( isset( $trigger_data['post_content'] ) ) {
513 $source_content = $trigger_data['post_content'];
514 } else {
515 return array( 'success' => false, 'message' => 'Source Content is required.' );
516 }
517 }
518
519 $is_pro = ( $action_id === 'wp_ai_generate_social_posts_pro' );
520
521 if ( $is_pro ) {
522 $prompt = "You are a social media expert. Based on the following content, generate three optimized posts for Instagram, WhatsApp, and LinkedIn.
523 Additional Instructions: {$instructions}
524
525 Content:
526 \"{$source_content}\"
527
528 IMPORTANT: You MUST return the output in EXACTLY this format:
529 [INSTAGRAM]
530 (Your Instagram post content here)
531 [/INSTAGRAM]
532 [WHATSAPP]
533 (Your WhatsApp post content here)
534 [/WHATSAPP]
535 [LINKEDIN]
536 (Your LinkedIn post content here)
537 [/LINKEDIN]";
538 } else {
539 $prompt = "You are a social media expert. Based on the following content, generate two optimized posts for Facebook and Telegram.
540 Additional Instructions: {$instructions}
541
542 Content:
543 \"{$source_content}\"
544
545 IMPORTANT: You MUST return the output in EXACTLY this format:
546 [FACEBOOK]
547 (Your Facebook post content here)
548 [/FACEBOOK]
549 [TELEGRAM]
550 (Your Telegram post content here)
551 [/TELEGRAM]";
552 }
553
554 $ai_response = $this->call_ai( $config_values, $trigger_data, $prompt, "You are a helpful social media manager." );
555
556 if ( ! $ai_response['success'] ) {
557 return $ai_response;
558 }
559
560 $content = $ai_response['content'];
561 $results = array(
562 'success' => true,
563 'fb_post' => '',
564 'telegram_post' => '',
565 'insta_post' => '',
566 'whatsapp_post' => '',
567 'linkedin_post' => '',
568 'content' => $content, // Store full response just in case
569 );
570
571 if ( preg_match( '/\[FACEBOOK\](.*?)\[\/FACEBOOK\]/s', $content, $matches ) ) {
572 $results['fb_post'] = trim( $matches[1] );
573 }
574 if ( preg_match( '/\[TELEGRAM\](.*?)\[\/TELEGRAM\]/s', $content, $matches ) ) {
575 $results['telegram_post'] = trim( $matches[1] );
576 }
577 if ( preg_match( '/\[INSTAGRAM\](.*?)\[\/INSTAGRAM\]/s', $content, $matches ) ) {
578 $results['insta_post'] = trim( $matches[1] );
579 }
580 if ( preg_match( '/\[WHATSAPP\](.*?)\[\/WHATSAPP\]/s', $content, $matches ) ) {
581 $results['whatsapp_post'] = trim( $matches[1] );
582 }
583 if ( preg_match( '/\[LINKEDIN\](.*?)\[\/LINKEDIN\]/s', $content, $matches ) ) {
584 $results['linkedin_post'] = trim( $matches[1] );
585 }
586
587 // AI Image Generation
588 if ( ! empty( $config_values['generate_image'] ) && $config_values['generate_image'] !== "false" ) {
589 // 1. Generate an image prompt using the text AI
590 $image_prompt_request = "Based on the following content, generate a concise, high-quality image generation prompt (max 100 words) that would be suitable for a social media post. Focus on visual details.
591
592 Content:
593 \"{$source_content}\"";
594
595 $image_prompt_response = $this->call_ai( $config_values, $trigger_data, $image_prompt_request, "You are a creative visual designer." );
596
597 if ( $image_prompt_response['success'] ) {
598 $image_prompt = $image_prompt_response['content'];
599
600 // 2. Call OpenAI DALL-E
601 $image_result = $this->call_openai_image( $config_values, $trigger_data, $image_prompt );
602
603 if ( $image_result['success'] ) {
604 $results['generated_image_url'] = $image_result['url'];
605 } else {
606 $results['image_error'] = $image_result['message'];
607 }
608 }
609 }
610
611 return $results;
612 }
613
614 /**
615 * Call OpenAI Image (DALL-E) API helper
616 */
617 private function call_openai_image( $config_values, $trigger_data, $prompt ) {
618 $api_key = isset( $config_values['api_key'] ) ? $this->parse_tokens( $config_values['api_key'], $trigger_data ) : '';
619 $model = isset( $config_values['image_model'] ) ? $config_values['image_model'] : 'dall-e-3';
620 $size = isset( $config_values['image_size'] ) ? $config_values['image_size'] : '1024x1024';
621 $style = isset( $config_values['image_style'] ) ? $config_values['image_style'] : 'vivid';
622
623 if ( empty( $api_key ) ) {
624 return array( 'success' => false, 'message' => 'API Key is required for image generation.' );
625 }
626
627 $url = 'https://api.openai.com/v1/images/generations';
628
629 $body = array(
630 'model' => $model,
631 'prompt' => $prompt,
632 'n' => 1,
633 'size' => $size,
634 );
635
636 if ( $model === 'dall-e-3' ) {
637 $body['style'] = $style;
638 }
639
640 $args = array(
641 'method' => 'POST',
642 'headers' => array(
643 'Content-Type' => 'application/json',
644 'Authorization' => 'Bearer ' . $api_key,
645 ),
646 'body' => wp_json_encode( $body ),
647 'timeout' => 90,
648 );
649
650 $response = wp_remote_request( $url, $args );
651
652 if ( is_wp_error( $response ) ) {
653 return array( 'success' => false, 'message' => $response->get_error_message() );
654 }
655
656 $response_code = wp_remote_retrieve_response_code( $response );
657 $response_body = wp_remote_retrieve_body( $response );
658 $data = json_decode( $response_body, true );
659
660 if ( $response_code >= 200 && $response_code < 300 ) {
661 return array(
662 'success' => true,
663 'url' => isset( $data['data'][0]['url'] ) ? $data['data'][0]['url'] : '',
664 'data' => $data,
665 );
666 } else {
667 $err = isset( $data['error']['message'] ) ? $data['error']['message'] : 'Unknown OpenAI Image error';
668 return array( 'success' => false, 'message' => $err, 'code' => $response_code );
669 }
670 }
671
672 /**
673 * Call AI Provider helper
674 */
675 private function call_ai( $config_values, $trigger_data, $prompt, $system_prompt = '' ) {
676 $provider = isset( $config_values['ai_provider'] ) ? $config_values['ai_provider'] : 'openai';
677
678 switch ( $provider ) {
679 case 'gemini':
680 return $this->call_gemini( $config_values, $trigger_data, $prompt, $system_prompt );
681 case 'claude':
682 return $this->call_claude( $config_values, $trigger_data, $prompt, $system_prompt );
683 case 'openai':
684 default:
685 return $this->call_openai( $config_values, $trigger_data, $prompt, $system_prompt );
686 }
687 }
688
689 /**
690 * Call OpenAI API helper
691 */
692 private function call_openai( $config_values, $trigger_data, $prompt, $system_prompt = '' ) {
693 $api_key = isset( $config_values['api_key'] ) ? $this->parse_tokens( $config_values['api_key'], $trigger_data ) : '';
694 $model = isset( $config_values['model'] ) ? $config_values['model'] : 'gpt-3.5-turbo';
695 $max_tokens = isset( $config_values['max_tokens'] ) ? intval( $config_values['max_tokens'] ) : 1500;
696 $temperature = isset( $config_values['temperature'] ) ? floatval( $config_values['temperature'] ) : 0.7;
697
698 if ( empty( $api_key ) ) {
699 return array( 'success' => false, 'message' => 'OpenAI API Key is required.' );
700 }
701
702 $messages = array();
703 if ( ! empty( $system_prompt ) ) {
704 $messages[] = array( 'role' => 'system', 'content' => $system_prompt );
705 }
706 $messages[] = array( 'role' => 'user', 'content' => $prompt );
707
708 $url = 'https://api.openai.com/v1/chat/completions';
709 $args = array(
710 'method' => 'POST',
711 'headers' => array(
712 'Content-Type' => 'application/json',
713 'Authorization' => 'Bearer ' . $api_key,
714 ),
715 'body' => wp_json_encode( array(
716 'model' => $model,
717 'messages' => $messages,
718 'max_tokens' => $max_tokens,
719 'temperature' => $temperature,
720 ) ),
721 'timeout' => 60,
722 );
723
724 $response = wp_remote_request( $url, $args );
725
726 if ( is_wp_error( $response ) ) {
727 return array( 'success' => false, 'message' => $response->get_error_message() );
728 }
729
730 $response_code = wp_remote_retrieve_response_code( $response );
731 $response_body = wp_remote_retrieve_body( $response );
732 $data = json_decode( $response_body, true );
733
734 if ( $response_code >= 200 && $response_code < 300 ) {
735 return array(
736 'success' => true,
737 'content' => isset( $data['choices'][0]['message']['content'] ) ? $data['choices'][0]['message']['content'] : '',
738 'data' => $data,
739 );
740 } else {
741 $err = isset( $data['error']['message'] ) ? $data['error']['message'] : 'Unknown OpenAI error';
742 return array( 'success' => false, 'message' => $err, 'code' => $response_code );
743 }
744 }
745
746 /**
747 * Call Gemini API helper
748 */
749 private function call_gemini( $config_values, $trigger_data, $prompt, $system_prompt = '' ) {
750 $api_key = isset( $config_values['api_key'] ) ? $this->parse_tokens( $config_values['api_key'], $trigger_data ) : '';
751 $model = isset( $config_values['model'] ) ? $config_values['model'] : 'gemini-1.5-flash';
752 $temperature = isset( $config_values['temperature'] ) ? floatval( $config_values['temperature'] ) : 0.7;
753
754 if ( empty( $api_key ) ) {
755 return array( 'success' => false, 'message' => 'Gemini API Key is required.' );
756 }
757
758 $full_prompt = $system_prompt ? $system_prompt . "\n\n" . $prompt : $prompt;
759
760 $url = 'https://generativelanguage.googleapis.com/v1/models/' . $model . ':generateContent?key=' . $api_key;
761
762 $body = array(
763 'contents' => array(
764 array(
765 'parts' => array(
766 array( 'text' => $full_prompt ),
767 ),
768 ),
769 ),
770 'generationConfig' => array(
771 'temperature' => $temperature,
772 ),
773 );
774
775 $args = array(
776 'method' => 'POST',
777 'headers' => array( 'Content-Type' => 'application/json' ),
778 'body' => wp_json_encode( $body ),
779 'timeout' => 60,
780 );
781
782 $response = wp_remote_request( $url, $args );
783
784 if ( is_wp_error( $response ) ) {
785 return array( 'success' => false, 'message' => $response->get_error_message() );
786 }
787
788 $response_code = wp_remote_retrieve_response_code( $response );
789 $response_body = wp_remote_retrieve_body( $response );
790 $data = json_decode( $response_body, true );
791
792 if ( $response_code >= 200 && $response_code < 300 ) {
793 $content = isset( $data['candidates'][0]['content']['parts'][0]['text'] ) ? $data['candidates'][0]['content']['parts'][0]['text'] : '';
794 return array(
795 'success' => true,
796 'content' => $content,
797 'data' => $data,
798 );
799 } else {
800 $err = isset( $data['error']['message'] ) ? $data['error']['message'] : 'Unknown Gemini error';
801 return array( 'success' => false, 'message' => $err, 'code' => $response_code );
802 }
803 }
804
805 /**
806 * Call Claude API helper
807 */
808 private function call_claude( $config_values, $trigger_data, $prompt, $system_prompt = '' ) {
809 $api_key = isset( $config_values['api_key'] ) ? $this->parse_tokens( $config_values['api_key'], $trigger_data ) : '';
810 $model = isset( $config_values['model'] ) ? $config_values['model'] : 'claude-3-5-sonnet-20240620';
811 $max_tokens = isset( $config_values['max_tokens'] ) ? intval( $config_values['max_tokens'] ) : 1500;
812 $temperature = isset( $config_values['temperature'] ) ? floatval( $config_values['temperature'] ) : 0.7;
813
814 if ( empty( $api_key ) ) {
815 return array( 'success' => false, 'message' => 'Claude API Key is required.' );
816 }
817
818 $url = 'https://api.anthropic.com/v1/messages';
819
820 $body = array(
821 'model' => $model,
822 'messages' => array(
823 array( 'role' => 'user', 'content' => $prompt ),
824 ),
825 'max_tokens' => $max_tokens,
826 'temperature' => $temperature,
827 );
828
829 if ( ! empty( $system_prompt ) ) {
830 $body['system'] = $system_prompt;
831 }
832
833 $args = array(
834 'method' => 'POST',
835 'headers' => array(
836 'Content-Type' => 'application/json',
837 'x-api-key' => $api_key,
838 'anthropic-version' => '2023-06-01',
839 ),
840 'body' => wp_json_encode( $body ),
841 'timeout' => 60,
842 );
843
844 $response = wp_remote_request( $url, $args );
845
846 if ( is_wp_error( $response ) ) {
847 return array( 'success' => false, 'message' => $response->get_error_message() );
848 }
849
850 $response_code = wp_remote_retrieve_response_code( $response );
851 $response_body = wp_remote_retrieve_body( $response );
852 $data = json_decode( $response_body, true );
853
854 if ( $response_code >= 200 && $response_code < 300 ) {
855 $content = isset( $data['content'][0]['text'] ) ? $data['content'][0]['text'] : '';
856 return array(
857 'success' => true,
858 'content' => $content,
859 'data' => $data,
860 );
861 } else {
862 $err = isset( $data['error']['message'] ) ? $data['error']['message'] : 'Unknown Claude error';
863 return array( 'success' => false, 'message' => $err, 'code' => $response_code );
864 }
865 }
866 }
867