| 1 |
<?php |
| 2 |
namespace BBlocks\Inc; |
| 3 |
if( !class_exists( 'BBlocksAi' ) ){ |
| 4 |
class BBlocksAi{ |
| 5 |
|
| 6 |
public static $_instance = null; |
| 7 |
|
| 8 |
function __construct(){ |
| 9 |
add_action( 'wp_ajax_generate_ai_content', [ $this, 'handle_open_ai_generation' ] ); |
| 10 |
add_action( 'enqueue_block_editor_assets', [ $this, 'editorContentGenerateAiAssets' ] ); |
| 11 |
} |
| 12 |
|
| 13 |
public static function get_instance(){ |
| 14 |
if(self::$_instance === null){ |
| 15 |
self::$_instance = new self(); |
| 16 |
} |
| 17 |
return self::$_instance; |
| 18 |
|
| 19 |
} |
| 20 |
|
| 21 |
function editorContentGenerateAiAssets(){ |
| 22 |
|
| 23 |
wp_enqueue_style( 'b-blocks-ai-generate-content-style', B_BLOCKS_BUILD . 'b-blocks-ai/content-generate-ai.css', ['wp-components','wp-edit-blocks','wp-block-editor'], B_BLOCKS_VERSION ); |
| 24 |
|
| 25 |
wp_enqueue_script('b-blocks-ai-generate-content-script', B_BLOCKS_BUILD . 'b-blocks-ai/content-generate-ai.js',['react'],B_BLOCKS_VERSION, true); |
| 26 |
wp_localize_script( 'b-blocks-ai-generate-content-script', 'aiContentGenerator', [ |
| 27 |
'ajax_url' => admin_url( 'admin-ajax.php' ), |
| 28 |
'nonce' => wp_create_nonce( 'wp_ajax' ) |
| 29 |
] ); |
| 30 |
wp_enqueue_script( 'b-blocks-ai-generate-content-script'); |
| 31 |
} |
| 32 |
|
| 33 |
public function test_api_key( $api_key ) { |
| 34 |
if ( empty( $api_key ) ) { |
| 35 |
return [ 'valid' => false, 'message' => 'No API key provided' ]; |
| 36 |
} |
| 37 |
|
| 38 |
$response = wp_remote_post( 'https://api.openai.com/v1/chat/completions', [ |
| 39 |
'timeout' => 10, |
| 40 |
'headers' => [ |
| 41 |
'Authorization' => 'Bearer ' . $api_key, |
| 42 |
'Content-Type' => 'application/json' |
| 43 |
], |
| 44 |
'body' => json_encode( [ |
| 45 |
'model' => 'gpt-3.5-turbo', |
| 46 |
'messages' => [ |
| 47 |
[ |
| 48 |
'role' => 'user', |
| 49 |
'content' => 'Say "test"' |
| 50 |
] |
| 51 |
], |
| 52 |
'max_tokens' => 5 |
| 53 |
] ) |
| 54 |
] ); |
| 55 |
|
| 56 |
if ( is_wp_error( $response ) ) { |
| 57 |
return [ 'valid' => false, 'message' => 'Connection failed: ' . $response->get_error_message() ]; |
| 58 |
} |
| 59 |
|
| 60 |
$response_code = wp_remote_retrieve_response_code( $response ); |
| 61 |
|
| 62 |
if ( $response_code === 401 ) { |
| 63 |
return [ 'valid' => false, 'message' => 'Invalid API key' ]; |
| 64 |
} |
| 65 |
elseif ( $response_code === 429 ) { |
| 66 |
return [ 'valid' => true, 'message' => 'Valid key (rate limit exceeded)' ]; |
| 67 |
} elseif ( $response_code === 200 ) { |
| 68 |
return [ 'valid' => true, 'message' => 'Valid API key' ]; |
| 69 |
} |
| 70 |
else { |
| 71 |
return [ 'valid' => false, 'message' => 'API error (HTTP ' . $response_code . ')' ]; |
| 72 |
} |
| 73 |
} |
| 74 |
|
| 75 |
public function handle_open_ai_generation() { |
| 76 |
// Verify nonce |
| 77 |
if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['nonce'] ?? '' ) ), 'wp_ajax' ) ) { |
| 78 |
wp_send_json_error( [ 'message' => 'Security check failed' ] ); |
| 79 |
return; |
| 80 |
} |
| 81 |
|
| 82 |
// Check if user has permissions |
| 83 |
if ( ! current_user_can( 'edit_posts' ) ) { |
| 84 |
wp_send_json_error( [ 'message' => 'Insufficient permissions' ] ); |
| 85 |
return; |
| 86 |
} |
| 87 |
|
| 88 |
$prompt = sanitize_text_field( wp_unslash( $_POST['prompt'] ?? '' ) ); |
| 89 |
|
| 90 |
if ( empty( $prompt ) ) { |
| 91 |
wp_send_json_error( [ 'message' => 'Prompt is required' ] ); |
| 92 |
return; |
| 93 |
} |
| 94 |
|
| 95 |
$generated_content = $this->call_ai_service( $prompt ); |
| 96 |
|
| 97 |
if ( is_wp_error( $generated_content ) ) { |
| 98 |
// wp_send_json_success( ['conteddnt' => $generated_content] ); |
| 99 |
wp_send_json_error( [ |
| 100 |
'message' => $generated_content->get_error_message() |
| 101 |
] ); |
| 102 |
return; |
| 103 |
} |
| 104 |
|
| 105 |
wp_send_json_success( [ |
| 106 |
'content' => $generated_content |
| 107 |
] ); |
| 108 |
} |
| 109 |
|
| 110 |
private function call_ai_service( $prompt ) { |
| 111 |
$api_data = get_option( 'bBlocksApiKeys', [] ); |
| 112 |
$openAi = isset( $api_data['openAi'] ) && is_array( $api_data['openAi'] ) ? $api_data['openAi'] : []; |
| 113 |
$api_key = $openAi['key'] ?? ''; |
| 114 |
|
| 115 |
// Check if API key is set |
| 116 |
if ( empty( $api_key ) ) { |
| 117 |
wp_send_json_error( [ 'message' => 'OpenAI API key is not configured. Please set it in Settings.' ] ); |
| 118 |
// return new WP_Error( 'missing_api_key', 'OpenAI API key is not configured. Please set it in Settings > AI Content Generator.' ); |
| 119 |
} |
| 120 |
|
| 121 |
// Remove strict validation - just check if it's not empty |
| 122 |
if ( empty( trim( $api_key ) )) { |
| 123 |
wp_send_json_error( [ 'message' => 'API key appears to be empty. Please check your settings.' ] ); |
| 124 |
// return new WP_Error( 'invalid_api_key', 'API key appears to be empty. Please check your settings.' ); |
| 125 |
} |
| 126 |
|
| 127 |
$newPrompt = "You are a professional content writer.\n" . |
| 128 |
"Topic: $prompt\n" . |
| 129 |
"Tone: professional, informative, and persuasive.\n" . |
| 130 |
"Target Audience: Web Readers\n". |
| 131 |
"Length: approximately 150-200 words, formatted with headings and bullet points.\n" . |
| 132 |
"Constraints & Requirements:\n". |
| 133 |
"- Length: 150-200 words.\n". |
| 134 |
"- Optimization: Content must be engaging, well-structured, and optimized for online readability (scannable content).\n". |
| 135 |
"Output Instructions:\n". |
| 136 |
"- Provide only the generated content.\n". |
| 137 |
"- Do not include any meta-text, introductions, or post-generation explanations.\n"; |
| 138 |
|
| 139 |
$response = wp_remote_post( 'https://api.openai.com/v1/chat/completions', [ |
| 140 |
'timeout' => 30, |
| 141 |
'headers' => [ |
| 142 |
'Authorization' => 'Bearer ' . $api_key, |
| 143 |
'Content-Type' => 'application/json' |
| 144 |
], |
| 145 |
'body' => json_encode( [ |
| 146 |
'model' => 'gpt-3.5-turbo', |
| 147 |
'messages' => [ |
| 148 |
[ |
| 149 |
'role' => 'user', |
| 150 |
'content' => $newPrompt |
| 151 |
] |
| 152 |
], |
| 153 |
'max_tokens' => 1000, |
| 154 |
'temperature' => 0.7 |
| 155 |
] ) |
| 156 |
] ); |
| 157 |
|
| 158 |
if ( is_wp_error( $response ) ) { |
| 159 |
wp_send_json_error( [ 'message' => 'Failed to connect to OpenAI API: ' . $response->get_error_message()] ); |
| 160 |
// return new WP_Error( 'api_connection_error', 'Failed to connect to OpenAI API: ' . $response->get_error_message() ); |
| 161 |
} |
| 162 |
|
| 163 |
$response_code = wp_remote_retrieve_response_code( $response ); |
| 164 |
$response_body = wp_remote_retrieve_body( $response ); |
| 165 |
$data = json_decode( $response_body, true ); |
| 166 |
|
| 167 |
if ( $response_code === 401 ) { |
| 168 |
wp_send_json_error( [ 'message' => 'Invalid OpenAI API key. Please check your API key in the dashboard settings.' ] ); |
| 169 |
// return new WP_Error( 'invalid_api_key', 'Invalid OpenAI API key. Please check your API key in the plugin settings.' ); |
| 170 |
} |
| 171 |
|
| 172 |
if ( $response_code === 429 ) { |
| 173 |
$error_message = 'OpenAI API rate limit exceeded. You may have exceeded your quota or are making too many requests.'; |
| 174 |
if ( isset( $data['error']['message'] ) ) { |
| 175 |
$error_message = $data['error']['message']; |
| 176 |
} |
| 177 |
wp_send_json_error( [ 'message' => $error_message ] ); |
| 178 |
// return new WP_Error( 'rate_limit', $error_message ); |
| 179 |
} |
| 180 |
|
| 181 |
if ( $response_code !== 200 ) { |
| 182 |
$error_message = isset( $data['error']['message'] ) ? $data['error']['message'] : 'Unknown API error (HTTP ' . $response_code . ')'; |
| 183 |
wp_send_json_error( [ 'message' => $error_message ] ); |
| 184 |
// return new \WP_Error( 'api_error', $error_message ); |
| 185 |
} |
| 186 |
|
| 187 |
if ( isset( $data['choices'][0]['message']['content'] ) ) { |
| 188 |
wp_send_json_success( [ 'content' => $data['choices'][0]['message']['content'] ] ); |
| 189 |
// return trim( $data['choices'][0]['message']['content'] ); |
| 190 |
} |
| 191 |
wp_send_json_error( [ 'message' => 'Invalid response format from AI service' ] ); |
| 192 |
// return new WP_Error( 'invalid_response', 'Invalid response format from AI service' ); |
| 193 |
} |
| 194 |
} |
| 195 |
new BBlocksAi(); |
| 196 |
} |