From 8002e45b395b26e314961571198f8c1ab5270bf9 Mon Sep 17 00:00:00 2001 From: berchj Date: Fri, 19 Jul 2024 00:11:17 -0300 Subject: [PATCH 1/5] fix error function each 6 hours --- ai-entries/includes/class-ai-entries-cron.php | 89 ++++++------------- ai-entries/includes/class-ai-entries.php | 3 +- ai-entries/includes/settings-page.php | 2 +- .../tests/classes/AIEntriesCronTest.php | 17 +--- 4 files changed, 34 insertions(+), 77 deletions(-) diff --git a/ai-entries/includes/class-ai-entries-cron.php b/ai-entries/includes/class-ai-entries-cron.php index f6d7f7d..49937eb 100644 --- a/ai-entries/includes/class-ai-entries-cron.php +++ b/ai-entries/includes/class-ai-entries-cron.php @@ -2,27 +2,7 @@ class AIEntries_Cron { - // Function to check and run the function every 5 minutes - public static function my_six_hour_function() - { - - AIEntries_Cron::daily_task(); // Execute the function - - } - - // Function to check and run the function every 6 hours - public static function check_six_hour_function() - { - $last_executed_time = get_transient('last_six_hour_execution'); - - // Check if it's time to run the function (6 hours have passed) - if (!$last_executed_time || $last_executed_time < strtotime('-6 hours')) { - AIEntries_Cron::my_six_hour_function(); // Execute the function - set_transient('last_six_hour_execution', strtotime('now')); // Update the last execution time - } - } - - public function daily_task() + public static function daily_task() { $question = get_option('AIEntries_question', ''); $num_calls = get_option('AIEntries_num_calls', 1); @@ -44,54 +24,43 @@ public static function show_all_cron_tasks() if (empty($cron)) { return 'No tasks scheduled.'; } - - $output = ''; - $output .= ''; - foreach ($cron as $timestamp => $cronhooks) { - foreach ((array) $cronhooks as $hook => $events) { - if ($hook == 'AIEntries_daily_cron_job') { - $callbacks = array(); - foreach ((array) $events as $event) { - if (isset($GLOBALS['wp_filter'][$hook])) { - $callbacks[] = $GLOBALS['wp_filter'][$hook]; - } - } - //print_r($callbacks); - foreach ($callbacks as $priority => $callback) { - foreach ($callback->callbacks as $function_data) { - foreach ($function_data as $function_parts) { - $output .= ''; - $output .= ''; - $output .= ''; - $output .= ''; - $output .= ''; + if (wp_next_scheduled('AIEntries_daily_cron_job')) { + $output = '

Next Excecution

Hook Name

Function Name

' . esc_html(gmdate('Y-m-d H:i:s', $timestamp)) . '

' . esc_html($hook) . '

' . esc_html(strval($function_parts['function'][1] ? $function_parts['function'][1] : $function_parts['function'][0])) . '

'; + $output .= ''; + foreach ($cron as $timestamp => $cronhooks) { + foreach ((array) $cronhooks as $hook => $events) { + if ($hook == 'AIEntries_daily_cron_job') { + $callbacks = array(); + foreach ((array) $events as $event) { + if (isset($GLOBALS['wp_filter'][$hook])) { + $callbacks[] = $GLOBALS['wp_filter'][$hook]; } - } - } - /* // Suponiendo que $array contiene el array proporcionado - foreach ($callbacks as $priority => $callbacks) { - foreach ($callbacks as $callback_name => $callback_info) { - $function_info = $callback_info['function']; - - // Obtener el objeto/clase y el nombre de la función - $function_object = $function_info[0]; - $function_name = $function_info[1]; + //print_r($callbacks); + foreach ($callbacks as $priority => $callback) { + foreach ($callback->callbacks as $function_data) { + foreach ($function_data as $function_parts) { + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + } - echo 'Prioridad: ' . $priority . '
'; - echo 'Función: ' . $function_object . '::' . $function_name . '
'; + } + } - } - } */ + } } - - } + } + echo wp_kses_post($output); } + if (!wp_next_scheduled('AIEntries_daily_cron_job')) { - echo "\n \n No excecutions scheduled for: " . esc_html($hook_name); + return "\n \n No excecutions scheduled"; } - echo esc_html($output); + } } diff --git a/ai-entries/includes/class-ai-entries.php b/ai-entries/includes/class-ai-entries.php index 7575007..d1a2b94 100644 --- a/ai-entries/includes/class-ai-entries.php +++ b/ai-entries/includes/class-ai-entries.php @@ -33,8 +33,7 @@ private function includes() private function init_hooks() { - add_action('admin_menu', ['AIEntries_Settings', 'add_menu_page']); - add_action('wp', ['AIEntries_Cron', 'check_six_hour_function']); + add_action('admin_menu', ['AIEntries_Settings', 'add_menu_page']); add_action('AIEntries_daily_cron_job', ['AIEntries_Cron', 'daily_task']); } diff --git a/ai-entries/includes/settings-page.php b/ai-entries/includes/settings-page.php index 2a07ac0..8aa950c 100644 --- a/ai-entries/includes/settings-page.php +++ b/ai-entries/includes/settings-page.php @@ -52,6 +52,6 @@

mantain and scale this plugin

Wordpress Cron tasks scheduled by this plugin:

diff --git a/ai-entries/tests/classes/AIEntriesCronTest.php b/ai-entries/tests/classes/AIEntriesCronTest.php index e822531..5574ec0 100644 --- a/ai-entries/tests/classes/AIEntriesCronTest.php +++ b/ai-entries/tests/classes/AIEntriesCronTest.php @@ -2,25 +2,14 @@ require_once __DIR__ . '/../../includes/class-ai-entries-cron.php'; - class AIEntriesCronTest extends WP_Mock\Tools\TestCase { - - public function test_my_six_hour_function() + public function test_daily_task() { - // Call the method to test - $this->assertNull(AIEntries_Cron::my_six_hour_function()); - } + WP_Mock::userFunction('_get_cron_array'); + $this->assertNull(AIEntries_Cron::daily_task()); - public function test_check_six_hour_function() - { - - // Call the method to test - WP_Mock::userFunction('get_transient'); - WP_Mock::userFunction('set_transient'); - $this->assertNull(AIEntries_Cron::check_six_hour_function()); } - public function test_show_all_cron_tasks() { WP_Mock::userFunction('_get_cron_array'); From 845ae31e30d14e4034ac61372cc37a5ce44f6da8 Mon Sep 17 00:00:00 2001 From: berchj Date: Fri, 19 Jul 2024 13:43:17 -0300 Subject: [PATCH 2/5] feature/r30IeqdX --- ai-entries/includes/class-ai-entries-api.php | 28 ++++++++++++++++++- .../includes/class-ai-entries-settings.php | 4 ++- ai-entries/includes/settings-page.php | 5 ++++ 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/ai-entries/includes/class-ai-entries-api.php b/ai-entries/includes/class-ai-entries-api.php index ac81793..0706b99 100644 --- a/ai-entries/includes/class-ai-entries-api.php +++ b/ai-entries/includes/class-ai-entries-api.php @@ -2,6 +2,32 @@ class AIEntries_API { + public function fetch_news() + { + $api_base_url = 'https://newsapi.org/v2/everything'; + $api_key = 'ec81de69de28413bbff755cca38940e5'; + // Construir la URL completa con los parámetros + $url = add_query_arg(array( + 'q' => get_option('AIEntries_question', ''), + 'apiKey' => $this->api_key, + ), $this->api_base_url); + + // Realizar la solicitud GET utilizando wp_remote_get + $response = wp_remote_get($url); + + // Verificar si la solicitud fue exitosa + if (is_wp_error($response)) { + return "Error: " . $response->get_error_message(); + } + + $body = wp_remote_retrieve_body($response); + + // Decodificar el cuerpo de la respuesta JSON + $data = json_decode($body, true); + + // Devolver los datos decodificados + return $data; + } public static function call($question, $api_key, $category_name, $iterator = "") { @@ -91,7 +117,7 @@ private static function create_new_entry($title, $content, $category_name) wp_clear_scheduled_hook('AIEntries_daily_cron_job'); - wp_schedule_event(strtotime('now') + (1 * 60 * 60) , 'hourly', 'AIEntries_daily_cron_job'); + wp_schedule_event(strtotime('now') + (1 * 60 * 60), 'hourly', 'AIEntries_daily_cron_job'); return get_post($post_id); } diff --git a/ai-entries/includes/class-ai-entries-settings.php b/ai-entries/includes/class-ai-entries-settings.php index 1560214..9d9a885 100644 --- a/ai-entries/includes/class-ai-entries-settings.php +++ b/ai-entries/includes/class-ai-entries-settings.php @@ -30,6 +30,7 @@ public static function settings_page() if (isset($_POST['submit'])) { update_option('AIEntries_question', sanitize_text_field($_POST['question'])); update_option('AIEntries_num_calls', intval($_POST['num_calls'])); + update_option('AIEntries_news_api_key', sanitize_text_field($_POST['news_api_key'])); update_option('AIEntries_api_key', sanitize_text_field($_POST['api_key'])); update_option('AIEntries_category', sanitize_text_field($_POST['category'])); update_option('AIEntries_api_key_stable_diffusion', sanitize_text_field($_POST['api_key_stable_diffusion'])); @@ -52,7 +53,8 @@ public static function settings_page() $question = get_option('AIEntries_question', ''); $num_calls = get_option('AIEntries_num_calls', 1); $api_key = get_option('AIEntries_api_key', ''); - $category = get_option('AIEntries_category', ''); + $news_api_key = get_option('AIEntries_news_api_key',''); + $category = get_option('AIEntries_category', ''); $api_key_stable_diffusion = get_option('AIEntries_api_key_stable_diffusion', ''); include plugin_dir_path(__FILE__) . 'settings-page.php'; diff --git a/ai-entries/includes/settings-page.php b/ai-entries/includes/settings-page.php index 2a07ac0..fd8bfdb 100644 --- a/ai-entries/includes/settings-page.php +++ b/ai-entries/includes/settings-page.php @@ -16,6 +16,11 @@

Number of posts created based on GEMINI API Call (we recommend 5 because possible errors calling the API):


+ +
+

Note: You can get one for free here

From 1eb70211ea7d4057e495603284745339319dd3eb Mon Sep 17 00:00:00 2001 From: berchj Date: Sat, 20 Jul 2024 17:02:56 -0300 Subject: [PATCH 3/5] integrated with news api to generate content based on real content articles --- .wp-env.json | 4 +- ai-entries/includes/class-ai-entries-api.php | 133 +++++++++--------- .../includes/class-ai-entries-settings.php | 18 +-- ai-entries/includes/settings-page.php | 7 +- ai-entries/tests/classes/AIEntriesAPITest.php | 75 ++++++---- .../tests/classes/AIEntriesSettingsTest.php | 22 +++ 6 files changed, 153 insertions(+), 106 deletions(-) diff --git a/.wp-env.json b/.wp-env.json index 9e14b52..13c7430 100644 --- a/.wp-env.json +++ b/.wp-env.json @@ -1,4 +1,6 @@ { "plugins": ["./ai-entries/"], - "phpVersion": "7.4" + "phpVersion": "7.4", + "core": "WordPress/WordPress#master" + } diff --git a/ai-entries/includes/class-ai-entries-api.php b/ai-entries/includes/class-ai-entries-api.php index 0706b99..f7cdfe4 100644 --- a/ai-entries/includes/class-ai-entries-api.php +++ b/ai-entries/includes/class-ai-entries-api.php @@ -2,18 +2,21 @@ class AIEntries_API { - public function fetch_news() + public static $responses = array(); + public static function fetch_news() { $api_base_url = 'https://newsapi.org/v2/everything'; - $api_key = 'ec81de69de28413bbff755cca38940e5'; + // Construir la URL completa con los parámetros $url = add_query_arg(array( 'q' => get_option('AIEntries_question', ''), - 'apiKey' => $this->api_key, - ), $this->api_base_url); + 'apiKey' => get_option('AIEntries_news_api_key', ''), + 'pageSize' => get_option('AIEntries_num_calls', 1), + 'lenguage' => 'en', + ), $api_base_url); // Realizar la solicitud GET utilizando wp_remote_get - $response = wp_remote_get($url); + $response = wp_remote_get($url, array('headers' => array('User-Agent' => get_option('AIEntries_news_api_key', '')))); // Verificar si la solicitud fue exitosa if (is_wp_error($response)) { @@ -26,64 +29,67 @@ public function fetch_news() $data = json_decode($body, true); // Devolver los datos decodificados - return $data; + return $data['articles']; } public static function call($question, $api_key, $category_name, $iterator = "") { - // URL for the API call - $url = 'https://generativelanguage.googleapis.com/v1/models/gemini-pro:generateContent?key=' . $api_key; - - // Request arguments - $args = array( - 'timeout' => 60, - 'body' => wp_json_encode(array( - "contents" => array( - array( - "parts" => array( - array( - "text" => "List 1 " . $iterator . " article about " . $question . ". Using this JSON schema :{'title': str,'content':str} (Return only the JSON String without spaces) the title must be good for SEO and the content must be in html string", + $news_articles = self::fetch_news(); + + foreach ($news_articles as $key => $value) { + // URL for the API call + $url = 'https://generativelanguage.googleapis.com/v1/models/gemini-pro:generateContent?key=' . $api_key; + + // Request arguments + $args = array( + 'timeout' => 60, + 'body' => wp_json_encode(array( + "contents" => array( + array( + "parts" => array( + array( + "text" => "Analize this article : {'title':'" . wp_json_encode($value['title']) . "','description':'" . wp_json_encode($value['description']) . "','content':'" . wp_json_encode($value['content']) . "'} . Now write 1 related original article in english using this JSON schema : {'title': str,'content':str} (Return only the JSON String without spaces) the title must be good for SEO and the content must be in html string", + ), ), ), ), + )), + 'headers' => array( + 'Content-Type' => 'application/json', ), - )), - 'headers' => array( - 'Content-Type' => 'application/json', - ), - 'method' => 'POST', - ); - - // Response - $response = wp_remote_post($url, $args); - - // If anything goes wrong - if (is_wp_error($response)) { - return new WP_Error('api_error', $response->get_error_message()); - } + 'method' => 'POST', + ); - // Retrieve body - $body = wp_remote_retrieve_body($response); + // Response + $response = wp_remote_post($url, $args); - // Format data - if (empty($body)) { - return new WP_Error('api_error', 'Empty response from API.'); - } + // If anything goes wrong + if (is_wp_error($response)) { + return new WP_Error('api_error', $response->get_error_message()); + } - $data = json_decode($body, true); + // Retrieve body + $body = wp_remote_retrieve_body($response); + // Format data + if (empty($body)) { + return new WP_Error('api_error', 'Empty response from API.'); + } - if (!isset($data['candidates'][0]['content']['parts'][0]['text'])) { - return new WP_Error('api_error', 'Invalid API response structure.'); - } + $data = json_decode($body, true); - // AI Post - $article = json_decode($data['candidates'][0]['content']['parts'][0]['text'], true); + if (!isset($data['candidates'][0]['content']['parts'][0]['text'])) { + return new WP_Error('api_error', 'Invalid API response structure.'); + } - if (!isset($article['title']) || !isset($article['content'])) { - return new WP_Error('api_error', 'API response does not contain title or content.'); + // AI Post + $article = json_decode($data['candidates'][0]['content']['parts'][0]['text'], true); + + if (!isset($article['title']) || !isset($article['content'])) { + return new WP_Error('api_error', 'API response does not contain title or content.'); + } + + self::create_new_entry($article['title'], $article['content'], $category_name); } - - return self::create_new_entry($article['title'], $article['content'], $category_name); } private static function create_new_entry($title, $content, $category_name) @@ -112,27 +118,29 @@ private static function create_new_entry($title, $content, $category_name) if (is_wp_error($post_id)) { return new WP_Error('insert_error', $post_id->get_error_message()); } else { - $base64_image = self::generate_post_image_with_AI($title); - self::set_featured_image_from_base64($base64_image, $post_id); + + self::generate_post_image_with_AI($title, $post_id); + //self::set_featured_image_from_base64($base64_image, $post_id); wp_clear_scheduled_hook('AIEntries_daily_cron_job'); wp_schedule_event(strtotime('now') + (1 * 60 * 60), 'hourly', 'AIEntries_daily_cron_job'); - return get_post($post_id); + array_push(self::$responses,get_post($post_id)); + } } return new WP_Error('permission_error', 'You do not have permission to publish posts.'); } - private static function generate_post_image_with_AI($title) + private static function generate_post_image_with_AI($title, $post_id) { $base_url = 'https://api.stability.ai'; $url = "$base_url/v1/generation/stable-diffusion-v1-6/text-to-image"; $api_key_stable_diffusion = get_option('AIEntries_api_key_stable_diffusion', ''); $body = wp_json_encode(array( - "text_prompts" => array(array("text" => $title)), + "text_prompts" => array(array("text" => $title .'. without texts in the image.')), "cfg_scale" => 7, "height" => 1024, "width" => 1024, @@ -140,8 +148,8 @@ private static function generate_post_image_with_AI($title) "steps" => 30, )); - $response = wp_remote_post($url, array( - 'timeout' => 600, + $response = wp_remote_post($url, array( + 'timeout'=>600, 'method' => 'POST', 'headers' => array( 'Content-Type' => 'application/json', @@ -150,17 +158,15 @@ private static function generate_post_image_with_AI($title) ), 'body' => $body, )); - + if (is_wp_error($response)) { return ''; } - + $body_request = json_decode($response['body'], true); - return $body_request['artifacts'][0]['base64']; - } + + $base64_image = $body_request['artifacts'][0]['base64']; - private static function set_featured_image_from_base64($base64_image, $post_id) - { if (!is_int($post_id)) { return false; } @@ -199,10 +205,9 @@ private static function set_featured_image_from_base64($base64_image, $post_id) require_once ABSPATH . 'wp-admin/includes/image.php'; $attach_data = wp_generate_attachment_metadata($attach_id, $file_path); + wp_update_attachment_metadata($attach_id, $attach_data); - set_post_thumbnail($post_id, $attach_id); - return true; + set_post_thumbnail($post_id, $attach_id); } - } diff --git a/ai-entries/includes/class-ai-entries-settings.php b/ai-entries/includes/class-ai-entries-settings.php index 9d9a885..313f486 100644 --- a/ai-entries/includes/class-ai-entries-settings.php +++ b/ai-entries/includes/class-ai-entries-settings.php @@ -37,14 +37,14 @@ public static function settings_page() $responses = []; $errors = []; - for ($i = 0; $i < intval($_POST['num_calls']); $i++) { - $response = AIEntries_API::call($_POST['question'], $_POST['api_key'], $_POST['category'], $i > 0 ? '' : 'more distinct'); - if (!is_wp_error($response)) { - $responses[] = $response; - } else { - $errors[] = $response->get_error_message(); - } + + $response = AIEntries_API::call($_POST['question'], $_POST['api_key'], $_POST['category']); + if (!is_wp_error($response)) { + $responses[] = $response; + } else { + $errors[] = $response->get_error_message(); } + } else { $responses = []; $errors = []; @@ -53,8 +53,8 @@ public static function settings_page() $question = get_option('AIEntries_question', ''); $num_calls = get_option('AIEntries_num_calls', 1); $api_key = get_option('AIEntries_api_key', ''); - $news_api_key = get_option('AIEntries_news_api_key',''); - $category = get_option('AIEntries_category', ''); + $news_api_key = get_option('AIEntries_news_api_key', ''); + $category = get_option('AIEntries_category', ''); $api_key_stable_diffusion = get_option('AIEntries_api_key_stable_diffusion', ''); include plugin_dir_path(__FILE__) . 'settings-page.php'; diff --git a/ai-entries/includes/settings-page.php b/ai-entries/includes/settings-page.php index 318e49a..55b9534 100644 --- a/ai-entries/includes/settings-page.php +++ b/ai-entries/includes/settings-page.php @@ -1,5 +1,6 @@

AIEntries Settings

@@ -15,7 +16,7 @@ -
+
@@ -47,9 +48,9 @@ - +

Posts Created by GEMINI's API Call:

- +
ID)); ?>
diff --git a/ai-entries/tests/classes/AIEntriesAPITest.php b/ai-entries/tests/classes/AIEntriesAPITest.php index 5d1c378..8196e48 100644 --- a/ai-entries/tests/classes/AIEntriesAPITest.php +++ b/ai-entries/tests/classes/AIEntriesAPITest.php @@ -1,30 +1,27 @@ (object)['term_id' => 1] + 'return' => (object) ['term_id' => 1], ]); WP_Mock::userFunction('current_user_can', [ - 'return' => true + 'return' => true, ]); WP_Mock::userFunction('wp_insert_post', [ - 'return' => 123 + 'return' => 123, ]); WP_Mock::userFunction('get_option', [ - 'return' => 'api_key_stable_diffusion_value' + 'return' => 'api_key_stable_diffusion_value', ]); WP_Mock::userFunction('wp_upload_dir'); @@ -67,11 +64,11 @@ public function testCallSuccess() { WP_Mock::userFunction('WP_Filesystem'); WP_Mock::userFunction('wp_insert_attachment', [ - 'return' => 456 + 'return' => 456, ]); WP_Mock::userFunction('wp_generate_attachment_metadata', [ - 'return' => [] + 'return' => [], ]); WP_Mock::userFunction('wp_update_attachment_metadata'); @@ -79,24 +76,24 @@ public function testCallSuccess() { WP_Mock::userFunction('set_post_thumbnail'); WP_Mock::userFunction('get_post', [ - 'return' => (object)[ + 'return' => (object) [ 'ID' => 123, 'post_title' => 'Test Title', - 'post_content' => '

Test Content

' - ] + 'post_content' => '

Test Content

', + ], ]); - WP_Mock::userFunction('wp_json_encode'); + WP_Mock::userFunction('wp_json_encode'); WP_Mock::userFunction('is_wp_error'); - WP_Mock::userFunction('wp_remote_retrieve_body'); - + WP_Mock::userFunction('wp_remote_retrieve_body'); // Assert that the returned result is as expected - - $this->assertSame( true, true ); + + $this->assertSame(true, true); } - public function testCallError() { + public function testCallError() + { $question = 'example question'; $api_key = 'test_api_key'; $category_name = 'Test Category'; @@ -104,12 +101,32 @@ public function testCallError() { // Simulate an error response from wp_remote_post WP_Mock::userFunction('wp_remote_post', [ - 'return' => new WP_Error( 'api_error', 'Something went wrong' ), + 'return' => new WP_Error('api_error', 'Something went wrong'), ]); - - $result = AIEntries_API::call( $question, $api_key, $category_name, $iterator ); + WP_Mock::userFunction('add_query_arg'); + WP_Mock::userFunction('wp_remote_get', + ['return' => '[{ + "status": "ok", + "totalResults": 268, + "articles": [ + { + "source": { + "id": null, + "name": "Hotnews.ro" + }, + "author": "Mihai Bianca", + "title": "fanatik.ro: I se spune Maldive de Europa. Se ajunge ușor din România și e de 3 ori mai ieftină decât Grecia sau Turcia", + "description": "Descoperă țara din Balcani cu cea mai impetuoasă dezvoltare la nivel de turism. Este catalogată ca având plaje la fel ca în Maldive. Maldive de Europa, adică un joc frumos de cuvinte, dar și un…", + "url": "http://hotnews.ro/fanatik-ro-i-se-spune-maldive-de-europa-se-ajunge-usor-din-romania-si-e-de-3-ori-mai-ieftina-decat-grecia-sau-turcia-1532267", + "urlToImage": "https://hotnews.ro/wp-content/uploads/2024/06/Screenshot-2024-06-29-105522.png", + "publishedAt": "2024-06-29T07:56:14Z", + "content": "Descoper ara din Balcani cu cea mai impetuoas dezvoltare la nivel de turism. Este catalogat ca având plaje la fel ca în Maldive.\r\nMaldive de Europa, adic un joc frumos de cuvinte, dar i un loc pentru… [+310 chars]" + } + ] + }]']); + $result = AIEntries_API::call($question, $api_key, $category_name, $iterator); // Verify that the result is an instance of WP_Error - $this->assertInstanceOf( 'WP_Error', $result ); + $this->assertInstanceOf('WP_Error', $result); } } diff --git a/ai-entries/tests/classes/AIEntriesSettingsTest.php b/ai-entries/tests/classes/AIEntriesSettingsTest.php index bbdbe46..187cd12 100644 --- a/ai-entries/tests/classes/AIEntriesSettingsTest.php +++ b/ai-entries/tests/classes/AIEntriesSettingsTest.php @@ -56,6 +56,28 @@ public function testSettingsPageSubmit() WP_Mock::userFunction('get_post_permalink'); WP_Mock::userFunction('get_the_title'); WP_Mock::userFunction('_get_cron_array'); + WP_Mock::userFunction('add_query_arg'); + WP_Mock::userFunction('add_query_arg'); + WP_Mock::userFunction('wp_remote_get', + ['return' => '[{ + "status": "ok", + "totalResults": 268, + "articles": [ + { + "source": { + "id": null, + "name": "Hotnews.ro" + }, + "author": "Mihai Bianca", + "title": "fanatik.ro: I se spune Maldive de Europa. Se ajunge ușor din România și e de 3 ori mai ieftină decât Grecia sau Turcia", + "description": "Descoperă țara din Balcani cu cea mai impetuoasă dezvoltare la nivel de turism. Este catalogată ca având plaje la fel ca în Maldive. Maldive de Europa, adică un joc frumos de cuvinte, dar și un…", + "url": "http://hotnews.ro/fanatik-ro-i-se-spune-maldive-de-europa-se-ajunge-usor-din-romania-si-e-de-3-ori-mai-ieftina-decat-grecia-sau-turcia-1532267", + "urlToImage": "https://hotnews.ro/wp-content/uploads/2024/06/Screenshot-2024-06-29-105522.png", + "publishedAt": "2024-06-29T07:56:14Z", + "content": "Descoper ara din Balcani cu cea mai impetuoas dezvoltare la nivel de turism. Este catalogat ca având plaje la fel ca în Maldive.\r\nMaldive de Europa, adic un joc frumos de cuvinte, dar i un loc pentru… [+310 chars]" + } + ] + }]']); // Mock POST request with submit $_POST = [ 'submit' => true, From 8730150513f8271f09b7ee046d0349db825a6ae0 Mon Sep 17 00:00:00 2001 From: berchj Date: Sat, 20 Jul 2024 18:12:24 -0300 Subject: [PATCH 4/5] integrated with new api --- .wp-env.json | 8 +-- ai-entries/README.md | 2 +- ai-entries/ai-entries.php | 2 +- ai-entries/includes/class-ai-entries-api.php | 1 - .../includes/class-ai-entries-settings.php | 3 +- ai-entries/tests/classes/AIEntriesAPITest.php | 48 ++++++++--------- .../tests/classes/AIEntriesSettingsTest.php | 51 ++++++++++--------- readme.md | 43 ++++++++++++++-- 8 files changed, 99 insertions(+), 59 deletions(-) diff --git a/.wp-env.json b/.wp-env.json index 13c7430..ac0c3ea 100644 --- a/.wp-env.json +++ b/.wp-env.json @@ -1,6 +1,8 @@ { - "plugins": ["./ai-entries/"], + "plugins": [ + "./ai-entries/", + "https://downloads.wordpress.org/plugin/plugin-check.zip" + ], "phpVersion": "7.4", - "core": "WordPress/WordPress#master" - + "core": null } diff --git a/ai-entries/README.md b/ai-entries/README.md index b9d1b6f..2e1d24d 100644 --- a/ai-entries/README.md +++ b/ai-entries/README.md @@ -2,7 +2,7 @@ Contributors: Julio Bermúdez Tested up to: 6.6 -Stable tag: 1.0.3 +Stable tag: 1.0.7 License: GPLv2 or later License URI: https://www.gnu.org/licenses/gpl-2.0.html Tags: plugin best practices, accessibility, performance, security, automation diff --git a/ai-entries/ai-entries.php b/ai-entries/ai-entries.php index 785d0e8..c015c45 100644 --- a/ai-entries/ai-entries.php +++ b/ai-entries/ai-entries.php @@ -2,7 +2,7 @@ /** * Plugin Name: AI Entries * Description: Automates the creation of standard WordPress posts. - * Version: 1.0.3 + * Version: 1.0.7 * Requires at least: 5.2 * Requires PHP: 7.2 * Author: Julio Bermúdez diff --git a/ai-entries/includes/class-ai-entries-api.php b/ai-entries/includes/class-ai-entries-api.php index f7cdfe4..8ecbf1f 100644 --- a/ai-entries/includes/class-ai-entries-api.php +++ b/ai-entries/includes/class-ai-entries-api.php @@ -12,7 +12,6 @@ public static function fetch_news() 'q' => get_option('AIEntries_question', ''), 'apiKey' => get_option('AIEntries_news_api_key', ''), 'pageSize' => get_option('AIEntries_num_calls', 1), - 'lenguage' => 'en', ), $api_base_url); // Realizar la solicitud GET utilizando wp_remote_get diff --git a/ai-entries/includes/class-ai-entries-settings.php b/ai-entries/includes/class-ai-entries-settings.php index 313f486..7a10170 100644 --- a/ai-entries/includes/class-ai-entries-settings.php +++ b/ai-entries/includes/class-ai-entries-settings.php @@ -10,7 +10,8 @@ public static function add_menu_page() 'AIEntries', 'manage_options', 'AIEntries-settings', - [self::class, 'settings_page'] + [self::class, 'settings_page'], + 'dashicons-visibility' ); return true; } diff --git a/ai-entries/tests/classes/AIEntriesAPITest.php b/ai-entries/tests/classes/AIEntriesAPITest.php index 8196e48..7f0db07 100644 --- a/ai-entries/tests/classes/AIEntriesAPITest.php +++ b/ai-entries/tests/classes/AIEntriesAPITest.php @@ -98,32 +98,32 @@ public function testCallError() $api_key = 'test_api_key'; $category_name = 'Test Category'; $iterator = '1'; - + + WP_Mock::userFunction('add_query_arg'); + WP_Mock::userFunction('wp_remote_get'); + WP_Mock::userFunction('wp_remote_post'); // Simulate an error response from wp_remote_post - WP_Mock::userFunction('wp_remote_post', [ - 'return' => new WP_Error('api_error', 'Something went wrong'), + WP_Mock::userFunction('wp_remote_retrieve_body', [ + 'return' => '{ + "status": "ok", + "totalResults": 268, + "articles": [ + { + "source": { + "id": null, + "name": "Hotnews.ro" + }, + "author": "Mihai Bianca", + "title": "fanatik.ro: I se spune Maldive de Europa. Se ajunge ușor din România și e de 3 ori mai ieftină decât Grecia sau Turcia", + "description": "Descoperă țara din Balcani cu cea mai impetuoasă dezvoltare la nivel de turism. Este catalogată ca având plaje la fel ca în Maldive. Maldive de Europa, adică un joc frumos de cuvinte, dar și un…", + "url": "http://hotnews.ro/fanatik-ro-i-se-spune-maldive-de-europa-se-ajunge-usor-din-romania-si-e-de-3-ori-mai-ieftina-decat-grecia-sau-turcia-1532267", + "urlToImage": "https://hotnews.ro/wp-content/uploads/2024/06/Screenshot-2024-06-29-105522.png", + "publishedAt": "2024-06-29T07:56:14Z", + "content": "Descoper ara din Balcani cu cea mai impetuoas dezvoltare la nivel de turism. Este catalogat ca având plaje la fel ca în Maldive.\r\nMaldive de Europa, adic un joc frumos de cuvinte, dar i un loc pentru… [+310 chars]" + } + ] + }', ]); - WP_Mock::userFunction('add_query_arg'); - WP_Mock::userFunction('wp_remote_get', - ['return' => '[{ - "status": "ok", - "totalResults": 268, - "articles": [ - { - "source": { - "id": null, - "name": "Hotnews.ro" - }, - "author": "Mihai Bianca", - "title": "fanatik.ro: I se spune Maldive de Europa. Se ajunge ușor din România și e de 3 ori mai ieftină decât Grecia sau Turcia", - "description": "Descoperă țara din Balcani cu cea mai impetuoasă dezvoltare la nivel de turism. Este catalogată ca având plaje la fel ca în Maldive. Maldive de Europa, adică un joc frumos de cuvinte, dar și un…", - "url": "http://hotnews.ro/fanatik-ro-i-se-spune-maldive-de-europa-se-ajunge-usor-din-romania-si-e-de-3-ori-mai-ieftina-decat-grecia-sau-turcia-1532267", - "urlToImage": "https://hotnews.ro/wp-content/uploads/2024/06/Screenshot-2024-06-29-105522.png", - "publishedAt": "2024-06-29T07:56:14Z", - "content": "Descoper ara din Balcani cu cea mai impetuoas dezvoltare la nivel de turism. Este catalogat ca având plaje la fel ca în Maldive.\r\nMaldive de Europa, adic un joc frumos de cuvinte, dar i un loc pentru… [+310 chars]" - } - ] - }]']); $result = AIEntries_API::call($question, $api_key, $category_name, $iterator); // Verify that the result is an instance of WP_Error diff --git a/ai-entries/tests/classes/AIEntriesSettingsTest.php b/ai-entries/tests/classes/AIEntriesSettingsTest.php index 187cd12..1ca926e 100644 --- a/ai-entries/tests/classes/AIEntriesSettingsTest.php +++ b/ai-entries/tests/classes/AIEntriesSettingsTest.php @@ -48,40 +48,41 @@ public function testSettingsPageNoSubmit() public function testSettingsPageSubmit() { WP_Mock::userFunction('sanitize_text_field'); - WP_Mock::userFunction('wp_json_encode'); - WP_Mock::userFunction('wp_remote_post'); - WP_Mock::userFunction('is_wp_error'); - WP_Mock::userFunction('wp_remote_retrieve_body'); + WP_Mock::userFunction('wp_json_encode'); + WP_Mock::userFunction('is_wp_error'); Mockery::mock('WP_Error'); WP_Mock::userFunction('get_post_permalink'); WP_Mock::userFunction('get_the_title'); WP_Mock::userFunction('_get_cron_array'); WP_Mock::userFunction('add_query_arg'); WP_Mock::userFunction('add_query_arg'); - WP_Mock::userFunction('wp_remote_get', - ['return' => '[{ - "status": "ok", - "totalResults": 268, - "articles": [ - { - "source": { - "id": null, - "name": "Hotnews.ro" - }, - "author": "Mihai Bianca", - "title": "fanatik.ro: I se spune Maldive de Europa. Se ajunge ușor din România și e de 3 ori mai ieftină decât Grecia sau Turcia", - "description": "Descoperă țara din Balcani cu cea mai impetuoasă dezvoltare la nivel de turism. Este catalogată ca având plaje la fel ca în Maldive. Maldive de Europa, adică un joc frumos de cuvinte, dar și un…", - "url": "http://hotnews.ro/fanatik-ro-i-se-spune-maldive-de-europa-se-ajunge-usor-din-romania-si-e-de-3-ori-mai-ieftina-decat-grecia-sau-turcia-1532267", - "urlToImage": "https://hotnews.ro/wp-content/uploads/2024/06/Screenshot-2024-06-29-105522.png", - "publishedAt": "2024-06-29T07:56:14Z", - "content": "Descoper ara din Balcani cu cea mai impetuoas dezvoltare la nivel de turism. Este catalogat ca având plaje la fel ca în Maldive.\r\nMaldive de Europa, adic un joc frumos de cuvinte, dar i un loc pentru… [+310 chars]" - } - ] - }]']); + WP_Mock::userFunction('wp_remote_post'); + // Simulate an error response from wp_remote_post + WP_Mock::userFunction('wp_remote_retrieve_body', [ + 'return' => '{ + "status": "ok", + "totalResults": 268, + "articles": [ + { + "source": { + "id": null, + "name": "Hotnews.ro" + }, + "author": "Mihai Bianca", + "title": "fanatik.ro: I se spune Maldive de Europa. Se ajunge ușor din România și e de 3 ori mai ieftină decât Grecia sau Turcia", + "description": "Descoperă țara din Balcani cu cea mai impetuoasă dezvoltare la nivel de turism. Este catalogată ca având plaje la fel ca în Maldive. Maldive de Europa, adică un joc frumos de cuvinte, dar și un…", + "url": "http://hotnews.ro/fanatik-ro-i-se-spune-maldive-de-europa-se-ajunge-usor-din-romania-si-e-de-3-ori-mai-ieftina-decat-grecia-sau-turcia-1532267", + "urlToImage": "https://hotnews.ro/wp-content/uploads/2024/06/Screenshot-2024-06-29-105522.png", + "publishedAt": "2024-06-29T07:56:14Z", + "content": "Descoper ara din Balcani cu cea mai impetuoas dezvoltare la nivel de turism. Este catalogat ca având plaje la fel ca în Maldive.\r\nMaldive de Europa, adic un joc frumos de cuvinte, dar i un loc pentru… [+310 chars]" + } + ] + }', + ]); // Mock POST request with submit $_POST = [ 'submit' => true, - 'aic_entries_nonce' => 'fake_nonce', + 'aic_entries_nonce' => 'fake_nonce', 'question' => 'test question', 'num_calls' => 1, 'api_key' => 'test_api_key', diff --git a/readme.md b/readme.md index efbc799..5a85672 100644 --- a/readme.md +++ b/readme.md @@ -1,17 +1,54 @@ # AIEntries Plugin -This plugin uses Google artificial intelligence (GEMINI) and stability.AI to automate the creation of standard WordPress posts based on configurable parameters from the WordPress admin view. +This plugin uses Google artificial intelligence (GEMINI) and stability.AI to automate the creation of standard WordPress posts based on configurable parameters from the WordPress admin view. It can create posts from any topic you configure from the administrator view. To ensure quality content, this tool is integrated with several free-to-use APIs to fulfill its functionality. -![image](https://github.com/user-attachments/assets/f01bf1a9-a2b9-4bfd-9995-2756219be659) +## This plugin is aware of Google's advice on AI content: +https://developers.google.com/search/blog/2023/02/google-search-and-ai-content?hl=es-419 -![image](https://github.com/user-attachments/assets/81b1e192-83a7-40f1-b856-b4f33f007f1c) +In order to follow they guidelines we are doing these processes: +### News API: + +we use this api to get real articles + +https://newsapi.org/docs + +### Google Gemini API: + +We use this api to generate original content based in real one + +https://ai.google.dev/gemini-api?hl=es-419 + +### Stability AI: + +We use this api to generate post's featured imaged based on ai generated article's title . + +https://stability.ai/ + + +### DISCLAIMER : THIS IS AN IN PROGRESS PROJECT . + + +![politic]() + + +![travel tips]() + + +![bitcoin]() + + +![UFO]() # Getting started! 💥 🚀 ## Requirements ✅ +You need to have a NEWS API's API KEY to use this plugin. + +You can get one for free here : https://newsapi.org/docs + You need to have a GEMINI API KEY to use this plugin. You can get one for free here : https://ai.google.dev/gemini-api/docs/api-key From 7dd3f4619e1a5b86b1401aa82a13cc79303bd12e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julio=20Berm=C3=BAdez?= Date: Sat, 20 Jul 2024 18:19:08 -0300 Subject: [PATCH 5/5] Update readme.md --- readme.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/readme.md b/readme.md index 5a85672..64f08db 100644 --- a/readme.md +++ b/readme.md @@ -29,17 +29,18 @@ https://stability.ai/ ### DISCLAIMER : THIS IS AN IN PROGRESS PROJECT . +![Politics](https://github.com/user-attachments/assets/a2685618-be5f-4cc2-aec6-b96636914aae) -![politic]() +![Travels](https://github.com/user-attachments/assets/00aa2883-488f-4057-a05d-f6e464fe51de) +![Misteries](https://github.com/user-attachments/assets/70c06b1c-1d35-40cb-839f-9aee4e2c249d) -![travel tips]() +![Any theme](https://github.com/user-attachments/assets/2e0e0e7d-03ad-4c82-a26c-5579fcca4fac) +![admin view](https://github.com/user-attachments/assets/7d7b8f00-fe92-41e3-b86b-b1259ffbe519) -![bitcoin]() -![UFO]() # Getting started! 💥 🚀

Next Excecution

Hook Name

Function Name

' . esc_html(gmdate('Y-m-d H:i:s', $timestamp)) . '

' . esc_html($hook) . '

' . esc_html(strval($function_parts['function'][1] ? $function_parts['function'][1] : $function_parts['function'][0])) . '