ws4agpt_get_settings('ws4agpt-cron-job-type') == 'easy-cron' && strpos($userAgent, 'easycron.com') !== false) { wp_clear_scheduled_hook('ws4agpt_auto_add_article_event'); $this->ws4agpt_auto_add_article(); } elseif ($this->ws4agpt_get_settings('ws4agpt-cron-job-type') == 'cron-job-org' && strpos($userAgent, 'cron-job.org') !== false) { wp_clear_scheduled_hook('ws4agpt_auto_add_article_event'); $this->ws4agpt_auto_add_article(); } elseif ($this->ws4agpt_get_settings('ws4agpt-cron-job-type') == 'wp-cron') { if (!wp_next_scheduled('ws4agpt_auto_add_article_event')) { wp_schedule_event(time(), $this->ws4agpt_get_settings('ws4agpt_frequency'), 'ws4agpt_auto_add_article_event'); } add_action('ws4agpt_auto_add_article_event', array($this, 'ws4agpt_auto_add_article'), 10, 2); }else { add_action('ws4agpt_auto_add_article_event', array($this, 'ws4agpt_auto_add_article'), 10, 2); } } self::ws4agpt_register_post_type(); } public function ws4agpt_add_caps(){ // gets the author role $role = get_role( 'aioseo_manager' ); // This only works, because it accesses the class instance. // would allow the author to edit others' posts for current theme only if($role) $role->add_cap( 'upload_files' ); } /** * Registers the post type for contact forms. */ public static function ws4agpt_register_post_type() { // ✅ Register the custom post type (public, clean URLs) register_post_type('ws4agpt_gpt_post', array( 'labels' => array( 'name' => __('AI Auto SEO', 'ai-auto-seo'), 'singular_name' => __('AI Auto SEO', 'ai-auto-seo'), ), 'description' => __('AI Auto SEO', 'ai-auto-seo'), 'public' => true, 'publicly_queryable' => true, 'show_ui' => true, 'show_in_menu' => true, 'menu_position' => 20, 'menu_icon' => 'dashicons-book', 'capability_type' => 'post', 'supports' => array( 'title', 'editor', 'comments', 'revisions', 'trackbacks', 'author', 'excerpt', 'page-attributes', 'thumbnail', 'custom-fields', 'post-formats' ), 'has_archive' => true, 'rewrite' => true, // Clean permalink like /postname )); // ✅ Private admin-only taxonomies (no URLs, no public access) $taxonomy_args = array( 'show_ui' => true, 'show_admin_column' => true, 'query_var' => false, 'public' => false, 'publicly_queryable' => false, 'rewrite' => false, ); // Titles taxonomy register_taxonomy('ws4agpt_titles', 'ws4agpt_gpt_post', array_merge( $taxonomy_args, ['hierarchical' => false, 'labels' => self::ws4agpt_get_taxonomy_lables('Title')] )); // Keyword taxonomy register_taxonomy('ws4agpt_keyword', 'ws4agpt_gpt_post', array_merge( $taxonomy_args, ['hierarchical' => false, 'labels' => self::ws4agpt_get_taxonomy_lables('Keyword')] )); // Category taxonomy register_taxonomy('ws4agpt_gpt_cat', 'ws4agpt_gpt_post', array_merge( $taxonomy_args, ['hierarchical' => true, 'labels' => self::ws4agpt_get_taxonomy_lables('Category')] )); } public static function ws4agpt_get_taxonomy_lables($label, $pLabel = '') { // Set the plural label if not provided $pLabel = $pLabel ? $pLabel : $label . 's'; // Adding translator comments explaining the placeholders $labels = array( // Translators: %s represents the plural label of the taxonomy 'name' => sprintf( _x( 'All %s items', 'taxonomy general name', 'ai-auto-seo' ), $pLabel ), // Translators: %s represents the singular label of the taxonomy 'singular_name' => sprintf( _x( 'One %s', 'taxonomy singular name', 'ai-auto-seo' ), $label ), // Translators: %s represents the plural label of the taxonomy 'search_items' => sprintf( __( 'Search %s', 'ai-auto-seo' ), $pLabel ), // Translators: %s represents the plural label of the taxonomy 'all_items' => sprintf( __( 'All %s', 'ai-auto-seo' ), $pLabel ), // Translators: %s represents the singular label of the taxonomy 'parent_item' => sprintf( __( 'Parent %s', 'ai-auto-seo' ), $label ), // Translators: %s represents the singular label of the taxonomy 'parent_item_colon' => sprintf( __( 'Parent %s:', 'ai-auto-seo' ), $label ), // Translators: %s represents the singular label of the taxonomy 'edit_item' => sprintf( __( 'Edit %s', 'ai-auto-seo' ), $label ), // Translators: %s represents the singular label of the taxonomy 'update_item' => sprintf( __( 'Update %s', 'ai-auto-seo' ), $label ), // Translators: %s represents the singular label of the taxonomy 'add_new_item' => sprintf( __( 'Add New %s', 'ai-auto-seo' ), $label ), // Translators: %s represents the singular label of the taxonomy 'new_item_name' => sprintf( __( 'New %s Name', 'ai-auto-seo' ), $label ), // Translators: %s represents the plural label of the taxonomy 'menu_name' => sprintf( __( 'Add/View %s', 'ai-auto-seo' ), $pLabel ), ); return $labels; } function ws4agpt_admin_menu(){ $manager = get_option('ws4agpt_manager', 'manage_options'); $bulk = add_submenu_page( 'edit.php?post_type=ws4agpt_gpt_post', __( 'AI Auto SEO', 'ai-auto-seo' ), __( 'Generate Article', 'ai-auto-seo' ), $manager, 'ws4agpt_gpt_single_options', array($this, 'ws4agpt_single_options'), 5 ); $bulk = add_submenu_page( 'edit.php?post_type=ws4agpt_gpt_post', __( 'AI Auto SEO', 'ai-auto-seo' ), __( 'Generate Image(s)', 'ai-auto-seo' ), $manager, 'ws4agpt_gpt_image_options', array($this, 'ws4agpt_image_options'), 5 ); $bulk = add_submenu_page( 'edit.php?post_type=ws4agpt_gpt_post', __( 'AI Auto SEO', 'ai-auto-seo' ), __( 'Bulk Options', 'ai-auto-seo' ), $manager, 'ws4agpt_gpt_bulk_options', array($this, 'ws4agpt_bulk_options'), 20 ); $bulk = add_submenu_page( 'edit.php?post_type=ws4agpt_gpt_post', __( 'AI Auto SEO', 'ai-auto-seo' ), __( 'Settings', 'ai-auto-seo' ), $manager, 'ws4agpt_gpt_settings', array($this, 'ws4agpt_settings'), 20 ); //add_action( 'load-' . $bulk, array($this, 'load_gpt_bulk_options'), 10, 0 ); } /** * Add extra fields to custom taxonomy edit and add form callback functions */ // Add/Edit taxonomy page function ws4agpt_keyword_custom_tax_fields($tag) { $term_meta = array(); // Check for existing taxonomy meta for term ID. if (is_object($tag) && isset($tag->term_id)) { $t_id = $tag->term_id; $term_meta = get_option("ws4agpt_taxonomy_$t_id"); } // Add nonce field wp_nonce_field('ws4agpt_save_keyword_custom_fields', 'ws4agpt_keyword_custom_nonce'); ?>

$value) { // Only allow specific keys we expect if (in_array($key, ['keyword_link1', 'keyword_link2'])) { // Value is already sanitized by array_map above $term_meta[$key] = $value; } } // Save the sanitized option array. update_option("ws4agpt_taxonomy_$t_id", $term_meta); } } function ws4agpt_get_settings($key=""){ $defaults = array( 'ws4agpt_admin_menu_manager'=> 'administrator', 'is_wp_post' => 'yes', 'ws4agpt_api_key' => '', 'ws4agpt_run_cron' => 'no', 'ws4agpt_post_type' => 'post', 'ws4agpt_publish' => 'no', 'ws4agpt_submission_type' => 'no', 'ws4agpt-cron-job-type' => 'wp-cron', 'ws4agpt_frequency' => 'daily', 'ws4agpt_gpt-model' => 'gpt-3.5-turbo', 'ws4agpt_temprature' => 0.9, 'ws4agpt_top_p' => 1, 'ws4agpt_presence_penalty' => 1, 'ws4agpt_frequency_penalty' => 0.1, 'ws4agpt_api_n' => 1, 'ws4agpt_best_of' => 1, 'ws4agpt_max_tokens' => 3800, 'ws4agpt_h2_key' => 'yes', ); if(empty($this->ws4agpt_settings)) $settings = get_option('ws4agpt_settings'); else $settings = $this->ws4agpt_settings; if($key){ if(isset($settings[$key])){ return $settings[$key]; }else{ return $defaults[$key]; } } $settings = empty($settings)?array():$settings; return array_merge($defaults, $settings);; } function ws4agpt_settings(){ require_once(WS4AGPT_ARTICLES_PLUGIN_DIR.'/views/settings.php'); } function ws4agpt_display_pro_message() { echo '
'; echo '

This feature is only available in the Pro version. Please get the Pro version to access this feature.

'; echo '
'; } function ws4agpt_general_settings() { $result = array(); $prompt = ''; if ( isset( $_POST['ws4agpt_g_settings_submit'] ) ) { // Sanitize and unslash nonce $nonce = isset( $_REQUEST['_wpnonce'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['_wpnonce'] ) ) : ''; // Verify nonce if ( ! wp_verify_nonce( $nonce, 'ws4agpt-settings' ) ) { $result['data'] = $this->ws4agpt_get_settings(); $result['error'] = __( 'Security check failed.', 'ai-auto-seo' ); } else { // Sanitize POST data $result['data'] = $this->ws4agpt_get_settings(); // Ensure we always load the current settings $result['data']['is_wp_post'] = isset( $_POST['is_wp_post'] ) ? 'yes' : 'no'; $result['data']['ws4agpt_admin_menu_manager'] = empty( $_POST['ws4agpt_admin_menu_manager'] ) ? 'administrator' : sanitize_text_field(wp_unslash($_POST['ws4agpt_admin_menu_manager'] )); $result['data']['ws4agpt-cron-job-type'] = isset( $_POST['ws4agpt-cron-job-type'] ) ? sanitize_text_field( wp_unslash( $_POST['ws4agpt-cron-job-type'] ) ) : ''; $result['data']['ws4agpt_run_cron'] = isset( $_POST['ws4agpt_run_cron'] ) ? 'yes' : 'no'; // Handle cron job type settings if ( $result['data']['ws4agpt-cron-job-type'] != 'wp-cron' ) { wp_clear_scheduled_hook( 'ws4agpt_auto_add_article_event' ); } // Reschedule cron if needed if ( $result['data']['ws4agpt-cron-job-type'] == 'wp-cron' && isset( $result['data']['ws4agpt_frequency'] ) && ( $this->ws4agpt_get_settings('ws4agpt_frequency') != $result['data']['ws4agpt_frequency'] ) ) { wp_clear_scheduled_hook( 'ws4agpt_auto_add_article_event' ); wp_reschedule_event( time(), $result['data']['ws4agpt_frequency'], 'ws4agpt_auto_add_article_event' ); } // Update user role and capabilities global $wp_roles; $role = $result['data']['ws4agpt_admin_menu_manager']; $caps = isset( $wp_roles->roles[$role] ) ? $wp_roles->roles[$role]['capabilities'] : array(); $_caps = array(); $_caps1 = array(); foreach ( $caps as $cap => $is ) { if ( str_starts_with( $cap, 'level' ) ) { $_caps[] = $cap; } else { $_caps1[] = $cap; } } // Set the correct manager role if ( ! empty( $_caps ) ) { $manager = $_caps[0]; } else { $manager = $_caps1[0]; } // Save the settings if no errors if ( ! isset( $result['error'] ) ) { update_option( 'ws4agpt_manager', $manager ); update_option( 'ws4agpt_settings', $result['data'] ); $this->ws4agpt_settings = $result['data']; $result['success'] = __( 'Settings saved successfully.', 'ai-auto-seo' ); } } } else { $result['data'] = $this->ws4agpt_get_settings(); } // Include the settings view require_once( WS4AGPT_ARTICLES_PLUGIN_DIR . '/views/settings-general.php' ); } function ws4agpt_is_openai_key_valid( $api_key ) { $response = wp_remote_get( 'https://api.openai.com/v1/models', array( 'headers' => array( 'Authorization' => 'Bearer ' . $api_key, ), 'timeout' => 15, ) ); if ( is_wp_error( $response ) ) { // Request failed — could be network issue. return array( 'valid' => false, 'error' => $response->get_error_message(), ); } $code = wp_remote_retrieve_response_code( $response ); if ( 200 === $code ) { return array( 'valid' => true, ); } elseif ( 401 === $code ) { return array( 'valid' => false, 'error' => 'Unauthorized – API key is invalid or expired.', ); } else { return array( 'valid' => false, 'error' => 'Unexpected error. HTTP code: ' . $code, ); } } function ws4agpt_gpt_settings(){ $result = array(); $prompt = ''; if ( isset( $_POST['ws4agpt_settings_submit'] ) ) { // Unsanitize the nonce before verifying it $nonce = isset( $_REQUEST['_wpnonce'] ) ? sanitize_text_field(wp_unslash( $_REQUEST['_wpnonce'] )) : ''; if ( ! wp_verify_nonce( $nonce, 'ws4agpt-gpt-settings' ) ) { $result['data'] = $this->ws4agpt_get_settings(); $result['error'] = __( 'Security check', 'ai-auto-seo' ); } else { $result['data'] = $this->ws4agpt_get_settings(); $key = get_option('ws4agpt_aeS25_wsfa_wsfa'); if (!$key) { $key = bin2hex(random_bytes(16)); // auto-generate a 32-character key add_option('ws4agpt_aeS25_wsfa_wsfa', $key); } $iv = substr($key, 0, 16); // Check if 'ws4agpt_api_key' is set before using it $result['data']['ws4agpt_api_key'] = isset( $_POST['ws4agpt_api_key'] ) ? sanitize_text_field( wp_unslash( $_POST['ws4agpt_api_key'] ) ) : ''; if (!empty($result['data']['ws4agpt_api_key'])) { $result['data']['ws4agpt_api_key'] = openssl_encrypt($result['data']['ws4agpt_api_key'], 'AES-256-CBC', $key, 0, $iv); } $result['data']['ws4agpt_post_type'] = isset( $_POST['ws4agpt_post_type'] ) ? sanitize_text_field( wp_unslash($_POST['ws4agpt_post_type'])) : 'post'; $result['data']['ws4agpt_publish'] = isset( $_POST['ws4agpt_publish'] ) ? 'yes' : 'no'; $result['data']['ws4agpt_submission_type'] = isset( $_POST['ws4agpt_submission_type'] ) ? 'yes' : 'no'; $result['data']['ws4agpt_frequency'] = isset( $_POST['ws4agpt_frequency'] ) ? sanitize_text_field( wp_unslash( $_POST['ws4agpt_frequency'] ) ) : ''; $result['data']['ws4agpt_gpt-model'] = isset( $_POST['ws4agpt_gpt-model'] ) ? sanitize_text_field( wp_unslash( $_POST['ws4agpt_gpt-model'] ) ) : ''; $result['data']['ws4agpt_temprature'] = isset( $_POST['ws4agpt_temprature'] ) ? sanitize_text_field( wp_unslash( $_POST['ws4agpt_temprature'] ) ) : ''; $result['data']['ws4agpt_top_p'] = isset( $_POST['ws4agpt_top_p'] ) ? sanitize_text_field( wp_unslash( $_POST['ws4agpt_top_p'] ) ) : ''; $result['data']['ws4agpt_presence_penalty'] = isset( $_POST['ws4agpt_presence_penalty'] ) ? sanitize_text_field( wp_unslash( $_POST['ws4agpt_presence_penalty'] ) ) : ''; $result['data']['ws4agpt_frequency_penalty'] = isset( $_POST['ws4agpt_frequency_penalty'] ) ? sanitize_text_field( wp_unslash( $_POST['ws4agpt_frequency_penalty'] ) ) : ''; $result['data']['ws4agpt_api_n'] = isset( $_POST['ws4agpt_api_n'] ) ? sanitize_text_field( wp_unslash( $_POST['ws4agpt_api_n'] ) ) : ''; $result['data']['ws4agpt_best_of'] = isset( $_POST['ws4agpt_best_of'] ) ? sanitize_text_field( wp_unslash( $_POST['ws4agpt_best_of'] ) ) : ''; $result['data']['ws4agpt_max_tokens'] = isset( $_POST['ws4agpt_max_tokens'] ) ? sanitize_text_field( wp_unslash( $_POST['ws4agpt_max_tokens'] ) ) : ''; // Validate token limits based on model $gpt_4_models = array('gpt-4', 'gpt-4-turbo', 'gpt-4-turbo-32k'); $gpt_3_5_models = array('gpt-3.5-turbo', 'gpt-3.5-turbo-16k'); if (in_array($result['data']['ws4agpt_gpt-model'], $gpt_3_5_models) && $result['data']['ws4agpt_max_tokens'] > 3900) { $result['error'] = __('Max tokens value should not be more than 3900 for GPT-3.5 models.', 'ai-auto-seo'); } elseif ($result['data']['ws4agpt_gpt-model'] == 'gpt-4o-mini' && $result['data']['ws4agpt_max_tokens'] > 16000) { $result['error'] = __('Max tokens value should not be more than 16000 for GPT-4o-mini.', 'ai-auto-seo'); } elseif ($result['data']['ws4agpt_gpt-model'] == 'gpt-4o' && $result['data']['ws4agpt_max_tokens'] > 16000) { $result['error'] = __('Max tokens value should not be more than 16000 for GPT-4o.', 'ai-auto-seo'); } elseif (in_array($result['data']['ws4agpt_gpt-model'], $gpt_4_models) && $result['data']['ws4agpt_max_tokens'] > 8000) { $result['error'] = __('Max tokens value should not be more than 8000 for GPT-4 models.', 'ai-auto-seo'); } elseif ($result['data']['ws4agpt_gpt-model'] == 'gpt-4-turbo-32k' && $result['data']['ws4agpt_max_tokens'] > 32000) { $result['error'] = __('Max tokens value should not be more than 32000 for GPT-4 Turbo 32k.', 'ai-auto-seo'); } if ( ! isset( $result['error'] ) ) { update_option( 'ws4agpt_settings', $result['data'] ); $this->ws4agpt_settings = $result['data']; $result['success'] = __( 'Settings saved successfully.', 'ai-auto-seo' ); } } } else { $result['data'] = $this->ws4agpt_get_settings(); } require_once( WS4AGPT_ARTICLES_PLUGIN_DIR . '/views/settings-gpt.php' ); } function ws4agpt_handle_run_now() { // Check nonce safely (return false instead of dying). if ( ! check_ajax_referer( 'ws4agpt_handle_submit_run_now_data', 'nonce', false ) ) { wp_send_json_error('Security check failed. Invalid nonce.'); } // Security check if needed if (!current_user_can('manage_options')) { wp_send_json_error('Unauthorized'); } $key = get_option('ws4agpt_aeS25_wsfa_wsfa'); $iv = substr($key, 0, 16); $apiKey = openssl_decrypt($this->ws4agpt_get_settings('ws4agpt_api_key'), 'AES-256-CBC', $key, 0, $iv); $ws4a_api_result = $this->ws4agpt_is_openai_key_valid($apiKey); if ( !$ws4a_api_result['valid'] ) { wp_send_json_error('API key is invalid or expired.'); } // Generate unique task ID $task_id = uniqid('ws4agpt_', true); update_option("ws4agpt_task_on_manual_runcron_$task_id", 'in-progress'); set_transient($task_id, [ 'status' => 'running', 'message' => 'Task is running...' ], 600); // Schedule single event for now wp_schedule_single_event(time(), 'ws4agpt_do_background_task', [$task_id]); wp_send_json_success(['task_id' => $task_id]); } function ws4agpt_run_task_scheduled($task_id){ // Call your function here $result = $this->ws4agpt_auto_add_article(); // pass params if needed // Save result if (!empty($result['success'])) { set_transient($task_id, [ 'status' => 'success', 'message' => $result['success'] ], 600); } else { set_transient($task_id, [ 'status' => 'error', 'message' => $result['error'] ?? 'Unknown error' ], 600); } delete_option("ws4agpt_task_on_manual_runcron_$task_id"); } // Polling: check task status function ws4agpt_check_task_status() { // Check nonce safely (return false instead of dying). if ( ! check_ajax_referer( 'ws4agpt_handle_check_post_taskss_status', 'nonce', false ) ) { wp_send_json_error('Security check failed. Invalid nonce.'); } $task_id = sanitize_text_field($_POST['task_id'] ?? ''); // phpcs:ignore if (!$task_id) { wp_send_json_error('Missing task ID'); } $status = get_transient($task_id); if (!$status) { wp_send_json_error('Task not found or expired'); } // delete_option("ws4agpt_task_on_manual_runcron_$task_id"); wp_send_json_success($status); } function ws4agpt_layout_settings(){ $result = array(); $prompt = ''; if(isset($_POST['ws4agpt_gpt_layout_submit'])){ $nonce = isset( $_REQUEST['_wpnonce'] ) ? sanitize_text_field(wp_unslash( $_REQUEST['_wpnonce'] )) : ''; // phpcs:ignore if( ! wp_verify_nonce( $nonce, 'ws4agpt-layout-settings' ) ){ $result['data'] = $this->ws4agpt_get_settings(); $result['error'] = __( 'Security check', 'ai-auto-seo' ); }else{ $result['data'] = $this->ws4agpt_get_settings(); $result['data']['ws4agpt_h2_key'] = isset($_POST['ws4agpt_h2_key'])?'yes':'no'; update_option('ws4agpt_settings', $result['data']); $this->ws4agpt_settings = $result['data']; $result['success'] = __( 'Settings saved successfully.', 'ai-auto-seo' ); } }else{ $result['data'] = $this->ws4agpt_get_settings(); } require_once(WS4AGPT_ARTICLES_PLUGIN_DIR.'/views/settings-layout.php'); } function ws4agpt_get_regex($tagname) { return '\\[' // Opening bracket. . '(\\[?)' // 1: Optional second opening bracket for escaping shortcodes: [[tag]]. . "($tagname)" // 2: Shortcode name. . '(?![\\w-])' // Not followed by word character or hyphen. . '(' // 3: Unroll the loop: Inside the opening shortcode tag. . '[^\\]\\/]*' // Not a closing bracket or forward slash. . '(?:' . '\\/(?!\\])' // A forward slash not followed by a closing bracket. . '[^\\]\\/]*' // Not a closing bracket or forward slash. . ')*?' . ')' . '(?:' . '(\\/)' // 4: Self-closing tag... . '\\]' // ...and closing bracket. . '|' . '\\]' // Closing bracket. . '(?:' . '(' // 5: Unroll the loop: Optionally, anything between the opening and closing shortcode tags. . '[^\\[]*+' // Not an opening bracket. . '(?:' . '\\[(?!\\/\\2\\])' // An opening bracket not followed by the closing shortcode tag. . '[^\\[]*+' // Not an opening bracket. . ')*+' . ')' . '\\[\\/\\2\\]' // Closing shortcode tag. . ')?' . ')' . '(\\]?)'; // 6: Optional second closing bracket for escaping shortcodes: [[tag]]. } function ws4agpt_single_options(){ // Load the view for single options require_once(WS4AGPT_ARTICLES_PLUGIN_DIR.'/views/single-options.php'); } function ws4agpt_bulk_options() { // Remove the main site check since we want it available everywhere require_once(WS4AGPT_ARTICLES_PLUGIN_DIR . '/views/bulk-options.php'); } function ws4agpt_bulk_import($titles, $keywords, $links1, $links2, $categories, $company, $imgUrl, $imgAlt, $length=1000, $density=1, $is_wp_post = false, $parent=0){ $result = array(); foreach($titles as $title){ $term = $this->ws4agpt_insert_term('ws4agpt_titles', $title); if(isset($term['error'])){ $result['error'][$title] = $term['error']; }else{ $_titles[] = $term['term_id']; } } foreach($keywords as $i=>$keyword){ $_links1 = isset($links1[$i])?$links1[$i]:''; $_links2 = isset($links2[$i])?$links2[$i]:''; $term = $this->ws4agpt_insert_term('ws4agpt_keyword', $keyword, $_links1, $_links2); if(isset($term['error'])){ $result['error'][$keyword] = $term['error']; }else{ $_keywords[] = $term['term_id']; } } //var_dump($parent); $cats = array(); foreach($categories as $category){ $term = $this->ws4agpt_insert_term('ws4agpt_gpt_cat', $category, '', '', $parent); if(isset($term['error'])){ $result['error'][$category] = $term['error']; }else{ $_categories[] = $term['term_id']; } } if(isset($result['error']) && !empty($result['error'])){ return $result; } $contents = array(); foreach($titles as $key => $title){ $_company = (is_array($company) && isset($company[$key]))?$company[$key]:''; $_imgUrl = (is_array($imgUrl) && isset($imgUrl[$key]))?$imgUrl[$key]:''; $_imgAlt = (is_array($imgAlt) && isset($imgAlt[$key]))?$imgAlt[$key]:''; $_length = (is_array($length))?$length[$key]:$length; $_density = (is_array($density))?$density[$key]:$density; $_is_wp_post = (is_array($is_wp_post))?$is_wp_post[$key]:$is_wp_post; $keyword = isset($keywords[$key]) ? $keywords[$key] : ''; $category = isset($categories[$key]) ? $categories[$key] : ''; $companyVal = isset($company[$key]) ? $company[$key] : ''; $contents[] = '[ws4agpt_gpt_post title="'.esc_attr($title).'" keywords="'.esc_attr($keyword).'" categories="'.esc_attr($category).'" company="'.esc_attr($companyVal).'" img_url="'.$_imgUrl.'" img_alt="'.$_imgAlt.'" length="'.$_length.'" density="'.$_density.'" is_wp_post="'.$_is_wp_post.'"]'; } $data = array(); $data['post_title'] = $titles[0]; $data['post_content'] = implode('|| ', $contents); $data['post_type'] = 'ws4agpt_gpt_post'; $data['post_status'] = 'publish'; $data['tax_input'] = array( 'ws4agpt_titles' => $_titles, 'ws4agpt_keyword' => $_keywords, 'ws4agpt_gpt_cat' => $_categories ); $id = wp_insert_post($data); if(!is_wp_error($id)){ update_post_meta($id, 'article_length', $length); update_post_meta($id, 'density', $density); update_post_meta($id, 'is_wp_post', $is_wp_post); $settings = get_option('ws4agpt_settings'); $url = get_edit_post_link($id); $result['success'] = sprintf("Success: Group post generated successfully, review the post here", $url); }else{ $result['error']['Group Post Insert Error'] = $id->get_error_message(); } return $result; } function ws4agpt_process_bulk_csv_import($rows){ $titles = $keywords = $categories = $company = $length = $density = $is_wp_post = array(); foreach($rows as $row) { $titles[] = isset($row['title']) ? $row['title'] : ''; $keywords[] = isset($row['keyword']) ? $row['keyword'] : ''; $links1[] = isset($row['keyword_link1']) ? $row['keyword_link1'] : ''; $links2[] = isset($row['keyword_link2']) ? $row['keyword_link2'] : ''; $categories[] = isset($row['category']) ? $row['category'] : ''; $company[] = isset($row['company']) ? $row['company'] : ''; $imgUrl[] = isset($row['image_url']) ? $row['image_url'] : ''; $imgAlt[] = isset($row['image_alt']) ? $row['image_alt'] : ''; // Fix for undefined array keys $length[] = isset($row['numberofwords']) ? absint($row['numberofwords']) : 1000; // Default to 1000 if not set $density[] = isset($row['keyworddensity']) ? absint($row['keyworddensity']) : 1; // Default to 1 if not set $is_wp_post[] = isset($row['is_wp_post']) ? $row['is_wp_post'] : 'no'; } return $this->ws4agpt_bulk_import( $titles, $keywords, $links1, $links2, $categories, $company, $imgUrl, $imgAlt, $length, $density, $is_wp_post ); } function ws4agpt_image_options() { $result = $images = array(); $prompt = ''; if (isset($_POST['save-to-library'])) { $nonce = isset($_REQUEST['_wpnonce']) ? sanitize_text_field(wp_unslash($_REQUEST['_wpnonce'])) : ''; // phpcs:ignore if (!wp_verify_nonce($nonce, 'ws4agpt-save-images')) { $result['error'] = __('Security check', 'ai-auto-seo'); } else { // $images = isset($_POST['images']) ? $_POST['images'] : array(); // phpcs:ignore // Sanitize and validate image URLs $raw_images = isset( $_POST['images'] ) && is_array( $_POST['images'] ) ? array_map( 'esc_url_raw', wp_unslash( $_POST['images'] ) ) : []; foreach ( $raw_images as $image ) { $image_url = esc_url_raw( wp_unslash( $image ) ); // Validate it's actually a URL if ( filter_var( $image_url, FILTER_VALIDATE_URL ) ) { // Handle sideloading image media_sideload_image( $image_url, 0 ); } } $result['success'] = 'Images saved successfully.'; } } $default_image_options = array( 'keyword' => '', 'styles' => 'none', 'photography' => 'none', 'lighting' => 'none', 'subject' => 'none', 'camera' => '', 'composition' => '', 'resolution' => '', 'color' => 'none', 'effects' => 'none', 'size' => '256x256', 'number' => '4' ); $result['data'] = $default_image_options; $template_path = trailingslashit( WS4AGPT_ARTICLES_PLUGIN_DIR ) . 'views/image-options.php'; if ( file_exists( $template_path ) ) { require_once $template_path; } else { $result['error'] = __( 'Template not found.', 'ai-auto-seo' ); } } /********************************** Ajax function for Generates image prompts and displays a form for saving images to the library. **********************************/ function ws4agpt_submit_post_image_data(){ // Check nonce safely (return false instead of dying). if ( ! check_ajax_referer( 'ws4agpt_handle_submit_post_imgdata', 'nonce', false ) ) { wp_send_json_error(['error' => 'Security check failed. Invalid nonce.']); } $result = $images = array(); $prompt = ''; if (isset($_POST['keyword'])) { $result['data']['keyword'] = $keyword = sanitize_text_field(wp_unslash($_POST['keyword']));// phpcs:ignore $result['data']['styles'] = $styles = sanitize_text_field(wp_unslash($_POST['styles']));// phpcs:ignore $result['data']['photography'] = $photography = sanitize_text_field(wp_unslash($_POST['photography']));// phpcs:ignore $result['data']['lighting'] = $lighting = sanitize_text_field(wp_unslash($_POST['lighting']));// phpcs:ignore $result['data']['subject'] = $subject = sanitize_text_field(wp_unslash($_POST['subject']));// phpcs:ignore $result['data']['camera'] = $camera = sanitize_text_field(wp_unslash($_POST['camera']));// phpcs:ignore $result['data']['composition'] = $composition = sanitize_text_field(wp_unslash($_POST['composition']));// phpcs:ignore $result['data']['resolution'] = $resolution = sanitize_text_field(wp_unslash($_POST['resolution']));// phpcs:ignore $result['data']['color'] = $color = sanitize_text_field(wp_unslash($_POST['lighting']));// phpcs:ignore $result['data']['effects'] = $effects = sanitize_text_field(wp_unslash($_POST['effects']));// phpcs:ignore $result['data']['size'] = $size = sanitize_text_field(wp_unslash($_POST['size']));// phpcs:ignore $result['data']['number'] = $number = sanitize_text_field(wp_unslash($_POST['number']));// phpcs:ignore // Create the prompt string $prompt = 'create a realistic '; $prompt .= $styles !== 'none' ? $styles . ', ' : ''; $prompt .= $photography !== 'none' ? $photography . ', ' : ''; $prompt .= $lighting !== 'none' ? $lighting . ', ' : ''; $prompt .= $subject !== 'none' ? $subject . ', ' : ''; $prompt .= 'image for "' . esc_attr($keyword) . '" '; $prompt .= $camera ? $camera . ', ' : ''; $prompt .= $composition ? $composition . ', ' : ''; $prompt .= $resolution ? $resolution . ', ' : ''; $prompt .= $color !== 'none' ? 'color: ' . esc_attr($color) . ', ' : ''; $prompt .= $effects !== 'none' ? 'Special Effects: ' . esc_attr($effects) . ', ' : ''; $prompt .= $resolution ? $resolution . ', ' : ''; $_res = $this->ws4agpt_generate_image($prompt, $size, $number); $res = json_decode($_res); if ($res->created) { ob_start(); echo '
'; wp_nonce_field('ws4agpt-save-images'); foreach ($res->data as $image) { $images[] = $image->url; // phpcs:ignore PluginCheck.CodeAnalysis.ImageFunctions.NonEnqueuedImage echo '
'.esc_attr($keyword).'
'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped echo ' Store to library
'; } echo '

'; echo '
'; $html_output = ob_get_clean(); wp_send_json_success($html_output); } else { $eror_message = $res->error->message; wp_send_json_error(['error' => $eror_message, 'response' => $res]); } } // Return default values if no keyword is provided $default_image_options = array( 'keyword' => '', 'styles' => 'none', 'photography' => 'none', 'lighting' => 'none', 'subject' => 'none', 'camera' => '', 'composition' => '', 'resolution' => '', 'color' => 'none', 'effects' => 'none', 'size' => '256x256', 'number' => '4', ); wp_send_json_success($default_image_options); wp_die(); } private function ws4agpt_generate_image($prompt, $size, $number){ $key = get_option('ws4agpt_aeS25_wsfa_wsfa'); $iv = substr($key, 0, 16); $apiKey = openssl_decrypt($this->ws4agpt_get_settings('ws4agpt_api_key'), 'AES-256-CBC', $key, 0, $iv); // Set the API endpoint URL $url = "https://api.openai.com/v1/images/generations"; // Set the request headers $headers = array( "Content-Type" => "application/json", "Authorization" => "Bearer " . $apiKey, ); // Set the request body $body = array( "prompt" => $prompt, "size" => $size, "n" => (int) $number, ); // Make the API request using WordPress HTTP API $response = wp_remote_post($url, array( 'headers' => $headers, 'body' => wp_json_encode($body), 'timeout' => 120, )); // Check for WP_Error if ( is_wp_error($response) ) { $this->ws4agpt_log_error('API Request Error: ', $response->get_error_message()); return false; } // Get the response body $body = wp_remote_retrieve_body($response); // $this->ws4agpt_log_error('API Response: ', $body); return $body; } function ws4agpt_auto_add_article() { $success_count = 0; // initialize it here $posts = get_posts(array( 'post_type' => 'ws4agpt_gpt_post', 'post_status' => 'publish', 'numberposts' => -1, 'orderby' => 'date', 'order' => 'ASC', )); foreach ($posts as $post) { $contents = $titles = $cats = $keywords = $company = $errors = array(); // Initialize other_wp_sites $other_wp_sites = ''; $_other_wp_sites = array(); if (!empty($post->post_content)) { $contents = explode('||', $post->post_content); } if (!empty($contents)) { $content = $contents[0]; // Use the updated regex pattern $pattern = $this->ws4agpt_get_regex('ws4agpt_gpt_post'); preg_match_all("/$pattern/", $content, $matches); $attrsString = isset($matches[3][0]) ? $matches[3][0] : ''; $attrs = []; if ($attrsString) { // This pattern matches attributes with potential nested quotes preg_match_all('/(\w+)=(["\'])(.*?)\2/', $attrsString, $attrMatches); if (!empty($attrMatches[1]) && !empty($attrMatches[3])) { $attrs = array_combine($attrMatches[1], $attrMatches[3]); } } $title = isset($attrs['title']) ? $attrs['title'] : ''; $keywords = isset($attrs['keywords']) ? explode(',', $attrs['keywords']) : array(); $cats = isset($attrs['categories']) ? explode(',', $attrs['categories']) : array(); $company = isset($attrs['company']) ? $attrs['company'] : ''; $imgUrl = isset($attrs['img_url']) ? $attrs['img_url'] : ''; $imgAlt = isset($attrs['img_alt']) ? $attrs['img_alt'] : ''; $length = isset($attrs['length']) ? $attrs['length'] : 1000; $density = isset($attrs['density']) ? $attrs['density'] : 1; $is_wp_post = isset($attrs['is_wp_post']) ? $attrs['is_wp_post'] : false; if ($other_wp_sites) { // Clean and split the `other_wp_sites` value based on your specific format $other_wp_sites = trim($other_wp_sites, '{}'); $sitePairs = explode(',', $other_wp_sites); foreach ($sitePairs as $pair) { $pair = trim($pair); // Ensure there's an '=' in the pair for splitting if (strpos($pair, '=') !== false) { list($site, $post_status) = explode('=', $pair); $_other_wp_sites[trim($site)] = trim($post_status); } } } // Process Keywords $_keywords = array(); foreach ($keywords as $keyword) { $term = get_term_by('name', $keyword, 'ws4agpt_keyword'); if (!$term) { $term = wp_insert_term( $keyword, 'ws4agpt_keyword', ); if (!is_wp_error($term)) { $term_id = $term['term_id']; } else { $errors[] = $term->get_error_message(); } } else { $term_id = $term->term_id; } if (empty($errors)) { $_keywords[$term_id] = $keyword; } } $result = $this->ws4agpt_generate_post($title, $_keywords, $cats, $company, $length, $density, $imgAlt, $imgUrl, $is_wp_post); if (!empty($result['error'])) { $this->ws4agpt_log_error('Cron Schedule generate article error:', $result['error']); $errors[] = $result['error']; } else { // Remove first processed content and update post_content unset($contents[0]); wp_update_post([ 'ID' => $post->ID, 'post_content' => implode('|| ', $contents), ]); $success_count++; } // Process only one post if ws4agpt_submission_type != 'yes' if ($this->ws4agpt_get_settings('ws4agpt_submission_type') != 'yes') { break; } } else { wp_update_post(array('ID' => $post->ID, 'post_status' => 'draft')); } } if ($success_count > 0) { return ['success' => "Processed {$success_count} posts."]; } elseif (!empty($errors)) { return ['error' => implode('; ', $errors)]; } else { return ['error' => 'No posts found or nothing to process.']; } } private function ws4agpt_load_media_dependencies() { require_once(ABSPATH . 'wp-admin/includes/media.php'); require_once(ABSPATH . 'wp-admin/includes/file.php'); require_once(ABSPATH . 'wp-admin/includes/image.php'); } private function ws4agpt_generate_post($title, $keywords, $cats, $company='', $length=1000, $density=1, $image_alt='', $image_url='', $is_wp_post= false){ $key = get_option('ws4agpt_aeS25_wsfa_wsfa'); $iv = substr($key, 0, 16); $apiKey = openssl_decrypt($this->ws4agpt_get_settings('ws4agpt_api_key'), 'AES-256-CBC', $key, 0, $iv); if (empty($apiKey)) { $result['error'] = "No content returned from the API."; return $result; } ob_start(); $result = array( 'success' => '', 'error' => '', 'data' => array() ); // Load media handling functions only once $this->ws4agpt_load_media_dependencies(); $content = ''; if ($length > 2000 && $length <= 10000) { $model = $this->ws4agpt_get_settings('ws4agpt_gpt-model'); if ($model !== 'gpt-4o-mini') { $result['error'] = 'The post that you trying to publish is greater than 2000 words, please select GPT Model 4o mini and set max tokens to 16000.'; return $result; } $prompts = $this->ws4agpt_generate_long_article_in_chunks($title, $keywords, $cats, $company, $length, $density); if ( empty( $prompts ) ) { $result['error'] = 'Server error: Failed to generate long content. Please try later.'; return $result; } $content = $prompts; $content = preg_replace('/^###\s+.*?\n/', '', $content, 1); $content = $this->ws4agpt_parseMarkdown($content); } else { $prompt = $this->ws4agpt_prepare_prompt($title, $keywords, $cats, $company, $length, $density); $_res = $this->ws4agpt_get_api_completions($prompt, $length); if ( !empty($_res) ) { $res = json_decode($_res); if (isset($res->choices) && !empty($res->choices[0]->message->content)) { $model = $this->ws4agpt_get_settings('ws4agpt_gpt-model'); $content = $this->ws4agpt_is_turbo_model($model) ? wp_strip_all_tags($res->choices[0]->message->content ?? '') : wp_strip_all_tags($res->choices[0]->text ?? ''); $content = preg_replace('/^###\s+.*?\n/', '', $content, 1); $content = $this->ws4agpt_parseMarkdown($content); }else{ $this->ws4agpt_log_error('API Response: ', $res); $result['error'] = "No content returned from the API. Please try later."; return $result; } }else{ $this->ws4agpt_log_error('API Response: ', $_res); $result['error'] = "No content returned from the API. Please try later."; return $result; } } if (empty($content)) { $result['error'] = "No content returned from the API."; return $result; } // IMAGE handling $imagetags = ''; $imageSrc = ''; $_keywords = implode(', ', array_values($keywords)); if(empty($image_url)){ if($image_alt){ $_img_res= $this->ws4agpt_generate_image("Find an image for ".$_keywords, '256x256', 1); $img_res = json_decode($_img_res); if($img_res->created){ foreach($img_res->data as $image){ $image_url = $image->url; // Check if the image URL is valid and not expired if (!empty($image_url)) { // Sideload the image $_image = media_sideload_image($image_url, 0, $image_alt, 'id'); // Check if sideloading was successful if (is_wp_error($_image)) { $errr = $_image->get_error_message(); $this->ws4agpt_log_error('Image Error: ', $errr); } else { // Image was sideloaded successfully $imageSrc = wp_get_original_image_path($_image); $_image = wp_get_attachment_image($_image); // Prepare the image tag for insertion in the content $imagetags .= str_replace( 'ws4agpt_log_error('Image Creation Error: ', $img_res); } } }else{ $_image = media_sideload_image($image_url, 0, $image_alt, 'id'); if (is_wp_error($_image)) { $imagetags .= '' . esc_attr($image_alt) . '';// phpcs:ignore } else { $imageSrc = wp_get_original_image_path($_image); $_image = wp_get_attachment_image($_image); $imagetags .= str_replace(' $keyword ) { $ws4agpt_keyword_quoted = preg_quote( $keyword, '/' ); $term_meta = get_option( "ws4agpt_taxonomy_$id" ); $links_count = 0; $ws4agpt_replacements[ $keyword ] = function( $matches ) use ( &$links_count, $term_meta ) { $links_count++; // Count available links in term meta (keyword_link1, keyword_link2, etc.) $available_links = []; if ( is_array( $term_meta ) ) { foreach ( $term_meta as $key => $val ) { if ( strpos( $key, 'keyword_link' ) === 0 && ! empty( $val ) ) { $available_links[] = $val; } } } if ( ! empty( $available_links ) ) { // Cycle through available links if density > number of links $index = ( $links_count - 1 ) % count( $available_links ); $url = esc_url( $available_links[ $index ] ); $text = esc_html( $matches[0] ); $title = esc_attr( $matches[0] ); return ''; } return $matches[0]; }; } // Apply replacements for each keyword (respect density setting) foreach ( $ws4agpt_replacements as $keyword => $callback ) { $ws4agpt_keyword_quoted = preg_quote( $keyword, '/' ); $content = preg_replace_callback( "/$ws4agpt_keyword_quoted/i", $callback, $content, absint( $density ) // density decides number of replacements ); } // Insert image in content if (!empty($imagetags)) { $content = '

' . $imagetags . '' . $content . '

'; } // Add H2 keyword if('yes' == $this->ws4agpt_get_settings('ws4agpt_h2_key')){ $_keywords = array_values($keywords); $content .= !empty($_keywords)?"\r\n".'

'.esc_html($_keywords[0]).'

':''; } // Combine the keywords into a comma-separated list $keywords_list = implode(', ', $keywords); $_cats = array(); foreach($cats as $cat){ $term = get_term_by('name', $cat, 'category'); if(!$term){ $term = wp_insert_term( $cat, 'category', ); if(!is_wp_error($term)){ $_cats[] = $term['term_id']; } }else{ $_cats[] = $term->term_id; } } // Insert post if requested if ($this->ws4agpt_get_settings('is_wp_post') === 'yes' && $is_wp_post === 'yes') { $post_data = [ 'post_title' => $title, 'post_content' => $content, // This content can be generated by using the keywords together 'post_type' => $this->ws4agpt_get_settings('ws4agpt_post_type') ?: 'post', 'post_status' => $this->ws4agpt_get_settings('ws4agpt_publish') === 'yes' ? 'publish' : 'draft', 'post_category'=> $_cats, // Add the keywords as post tags (comma-separated) 'tags_input' => $keywords_list, // Here we use the combined list ]; $post_id = wp_insert_post($post_data); if (is_wp_error($post_id)) { $error_message = is_wp_error($id) ? $id->get_error_message() : 'Unknown error, post ID was 0.'; $this->ws4agpt_log_error('Failed to post article on Wordpress using cron', $error_message); $result['error'] = "Failed to post article on Wordpress"; // Get detailed error message }else{ $result['success'] = "Article generated successfully."; unset($result['error']); } $created_url = get_edit_post_link($post_id); } ob_clean(); return $result; } /**************************** Ajax function for submit data ****************************/ function ws4agpt_submit_post_data(){ // Check nonce safely (return false instead of dying). if ( ! check_ajax_referer( 'ws4agpt_handle_submit_post_data', 'nonce', false ) ) { wp_send_json_error(['message' => 'Security check failed. Invalid nonce.']); } $key = get_option('ws4agpt_aeS25_wsfa_wsfa'); $iv = substr($key, 0, 16); $apiKey = openssl_decrypt($this->ws4agpt_get_settings('ws4agpt_api_key'), 'AES-256-CBC', $key, 0, $iv); $ws4a_api_result = $this->ws4agpt_is_openai_key_valid($apiKey); if ( !$ws4a_api_result['valid'] ) { wp_send_json_error(['message' => 'API key is invalid or expired.']); } if(isset($_POST['title'])) { $title = isset($_POST['title']) ? sanitize_text_field(wp_unslash($_POST['title'])) : ''; // phpcs:ignore $title_term = get_term_by('name', $title, 'ws4agpt_gpt_post'); // phpcs:ignore if(!$title_term){ wp_insert_term($title, 'ws4agpt_titles'); // phpcs:ignore } // Ensure proper sanitization and array check for each field $keywords = isset($_POST['keywords']) && is_array($_POST['keywords'])? array_map('sanitize_text_field', wp_unslash($_POST['keywords'])): []; // phpcs:ignore $categories[] = isset($_POST['categories']) ? sanitize_text_field(wp_unslash($_POST['categories'])): []; // phpcs:ignore $company = isset($_POST['company']) ? sanitize_text_field(wp_unslash($_POST['company'])) : ''; // phpcs:ignore $density = isset($_POST['density']) ? sanitize_text_field(wp_unslash($_POST['density'])) : ''; // phpcs:ignore $length = isset($_POST['length']) ? sanitize_text_field(wp_unslash($_POST['length'])) : ''; // phpcs:ignore $is_image = isset($_POST['is_image']) && $_POST['is_image'] == 'yes' ? 'yes' : 'no'; // phpcs:ignore $is_wp_post = isset($_POST['is_wp_post']) && $_POST['is_wp_post'] == 'yes' ? 'yes' : 'no'; // phpcs:ignore $image_alt = $is_image == 'yes' && isset($_POST['image_alt']) ? sanitize_text_field(wp_unslash($_POST['image_alt'])) : ''; // phpcs:ignore // Prepare categories and keywords $cats = []; $keys = []; // Process categories if (!empty($categories) && is_array($categories)) { foreach ($categories as $cat_id) { // Get term by ID in the 'gpt_cat' taxonomy $term = get_term($cat_id, 'ws4agpt_gpt_cat'); // phpcs:ignore if ($term && !is_wp_error($term)) { $cats[] = $term->name; // Add category name to the $cats array } } } // Process keywords if (!empty($keywords)) { foreach ($keywords as $keyword_id) { $term = get_term($keyword_id, 'ws4agpt_keyword'); // Make sure 'keyword' is correct if ($term && !is_wp_error($term)) { $keys[$term->term_id] = $term->name; } } } $image_url = ''; // Image URL placeholder // Generate a unique task ID to track progress $task_id = uniqid('ws4agpt_', true); // Store the task status as 'in-progress' update_option("ws4agpt_task_status_$task_id", 'in-progress'); // Schedule the background task wp_schedule_single_event(time() + 5, 'ws4agpt_generate_post_data_task', [serialize([ 'task_id' => $task_id, 'title' => $title, 'keywords' => $keys, 'categories' => $cats, 'company' => $company, 'density' => $density, 'length' => $length, 'is_image' => $is_image, 'image_alt' => $image_alt, 'is_wp_post' => $is_wp_post ])]); // Immediate success response to the user wp_send_json_success(['message' => 'Content generation started. You will be notified once completed.', 'task_id' => $task_id]); } } function ws4agpt_generate_post_data_background_task($args) { $args = unserialize($args); // Extract arguments $task_id = $args['task_id']; $title = $args['title']; $keywords = $args['keywords']; $categories = $args['categories']; $company = $args['company']; $density = $args['density']; $length = $args['length']; $is_image = $args['is_image']; $image_alt = $args['image_alt']; $is_wp_post = $args['is_wp_post']; $image_url = ''; // Image URL placeholder // Debugging: Log start of the task // Now we can call the existing function to generate the post data. $result = $this->ws4agpt_generate_post_data($title, $keywords, $categories, $company, $length, $density, $image_alt, $image_url, $is_wp_post); // $this->ws4agpt_log_error('Complete result: ', $result); if (isset($result['success']) && !empty($result['success'])) { // Update task status to 'completed' update_option("ws4agpt_task_status_$task_id", 'completed'); } else { // Update task status to 'failed' update_option("ws4agpt_task_status_$task_id", 'failed'); update_option("ws4agpt_task_status_response_$task_id", $result['error']); } } public function ws4agpt_check_post_task_status() { // Verify nonce to ensure request is legitimate $nonce = isset($_REQUEST['nonce']) ? sanitize_text_field(wp_unslash($_REQUEST['nonce'])) : ''; // phpcs:ignore if (!wp_verify_nonce($nonce, 'ws4agpt_handle_check_post_task_status')) { wp_send_json_error(['status' => 'failed', 'message' => 'Nonce validation failed']); } // Get the task ID passed via AJAX if (!isset($_POST['task_id'])) { wp_send_json_error(['message' => 'Task ID is missing']); } $task_id = sanitize_text_field(wp_unslash($_POST['task_id'])); // Get task status from the database $status = get_option("ws4agpt_task_status_$task_id", 'pending'); // Default is 'pending' // If the task is complete, send success, else send still-in-progress status if ($status === 'completed') { // Delete the task status option after success delete_option("ws4agpt_task_status_$task_id"); wp_send_json_success(['status' => 'completed', 'message' => 'Article generated successfully.']); } elseif ($status === 'failed') { $res_data = get_option("ws4agpt_task_status_response_$task_id"); wp_send_json_error(['status' => 'failed', 'message' => $res_data]); } else { wp_send_json_success(['status' => 'progress', 'message' => 'Article generation is still in progress.']); } } private function ws4agpt_generate_post_data($title, $keywords, $cats, $company = '', $length = 1000, $density = 1, $image_alt = '', $image_url = '', $is_wp_post = false) { ob_start(); $result = array( 'success' => '', 'error' => '', 'data' => array() ); $key = get_option('ws4agpt_aeS25_wsfa_wsfa'); $iv = substr($key, 0, 16); $apiKey = openssl_decrypt($this->ws4agpt_get_settings('ws4agpt_api_key'), 'AES-256-CBC', $key, 0, $iv); if (empty($apiKey)) { $result['error'] = 'GPT API key not found.'; return $result; } // Load media handling functions only once $this->ws4agpt_load_media_dependencies(); $content = ''; if ($length > 2000 && $length <= 10000) { $prompts = $this->ws4agpt_generate_long_article_in_chunks($title, $keywords, $cats, $company, $length, $density); if ( empty( $prompts ) ) { $result['error'] = 'Server error: Failed to generate long content. Please try later.'; return $result; } $content = $prompts; $content = preg_replace('/^###\s+.*?\n/', '', $content, 1); $content = $this->ws4agpt_parseMarkdown($content); } else { $prompt = $this->ws4agpt_prepare_prompt($title, $keywords, $cats, $company, $length, $density); $_res = $this->ws4agpt_get_api_completions($prompt, $length); if ( !empty($_res) ) { // $this->ws4agpt_log_error('API Response new: ', $_res); $res = json_decode($_res); // $this->ws4agpt_log_error('API Response: ', $res); if (isset($res->choices) && !empty($res->choices[0]->message->content)) { $model = $this->ws4agpt_get_settings('ws4agpt_gpt-model'); $content = $this->ws4agpt_is_turbo_model($model) ? wp_strip_all_tags($res->choices[0]->message->content ?? '') : wp_strip_all_tags($res->choices[0]->text ?? ''); $content = preg_replace('/^###\s+.*?\n/', '', $content, 1); $content = $this->ws4agpt_parseMarkdown($content); }else{ $this->ws4agpt_log_error('API Response: ', $res); $result['error'] = "No content returned from the API. Please try later."; return $result; } }else{ $this->ws4agpt_log_error('API Response: ', $_res); $result['error'] = "No content returned from the API. Please try later."; return $result; } } if (empty($content)) { $result['error'] = "No content returned from the API."; return $result; } // IMAGE handling $imagetags = ''; $imageSrc = ''; $_keywords = implode(', ', array_values($keywords)); if(empty($image_url)){ if($image_alt){ $_img_res= $this->ws4agpt_generate_image("Find an image for ".$_keywords, '256x256', 1); $img_res = json_decode($_img_res); if($img_res->created){ foreach($img_res->data as $image){ $image_url = $image->url; // Check if the image URL is valid and not expired if (!empty($image_url)) { // Sideload the image $_image = media_sideload_image($image_url, 0, $image_alt, 'id'); // Check if sideloading was successful if (is_wp_error($_image)) { $error_msg = $_image->get_error_message(); $result['error'] = 'Image could not be inserted. ' . esc_html( $error_msg ); $this->ws4agpt_log_error('Image Error: ', $error_msg); } else { // Image was sideloaded successfully $imageSrc = wp_get_original_image_path($_image); $_image = wp_get_attachment_image($_image); // Prepare the image tag for insertion in the content $imagetags .= str_replace( 'ws4agpt_log_error('Image Creation Error: ', $img_res); } } }else{ $_image = media_sideload_image($image_url, 0, $image_alt, 'id'); if (is_wp_error($_image)) { $result['error'] = $_image->get_error_message(); $imagetags .= '' . esc_attr($image_alt) . '';// phpcs:ignore } else { $imageSrc = wp_get_original_image_path($_image); $_image = wp_get_attachment_image($_image); $imagetags .= str_replace(' $keyword ) { $ws4agpt_keyword_quoted = preg_quote( $keyword, '/' ); $term_meta = get_option( "ws4agpt_taxonomy_$id" ); $links_count = 0; $ws4agpt_replacements[ $keyword ] = function( $matches ) use ( &$links_count, $term_meta ) { $links_count++; // Count available links in term meta (keyword_link1, keyword_link2, etc.) $available_links = []; if ( is_array( $term_meta ) ) { foreach ( $term_meta as $key => $val ) { if ( strpos( $key, 'keyword_link' ) === 0 && ! empty( $val ) ) { $available_links[] = $val; } } } if ( ! empty( $available_links ) ) { // Cycle through available links if density > number of links $index = ( $links_count - 1 ) % count( $available_links ); $url = esc_url( $available_links[ $index ] ); $text = esc_html( $matches[0] ); $title = esc_attr( $matches[0] ); return ''; } return $matches[0]; }; } // Apply replacements for each keyword (respect density setting) foreach ( $ws4agpt_replacements as $keyword => $callback ) { $ws4agpt_keyword_quoted = preg_quote( $keyword, '/' ); $content = preg_replace_callback( "/$ws4agpt_keyword_quoted/i", $callback, $content, absint( $density ) // density decides number of replacements ); } // Insert image in content if (!empty($imagetags)) { $content = '

' . $imagetags . '' . $content . '

'; } // Add H2 keyword if('yes' == $this->ws4agpt_get_settings('ws4agpt_h2_key')){ $_keywords = array_values($keywords); $content .= !empty($_keywords)?"\r\n".'

'.esc_html($_keywords[0]).'

':''; } // Combine the keywords into a comma-separated list $keywords_list = implode(', ', $keywords); $_cats = array(); foreach($cats as $cat){ $term = get_term_by('name', $cat, 'category'); if(!$term){ $term = wp_insert_term( $cat, 'category', ); if(!is_wp_error($term)){ $_cats[] = $term['term_id']; } }else{ $_cats[] = $term->term_id; } } // Insert post if requested $created_url = ''; if ($this->ws4agpt_get_settings('is_wp_post') === 'yes' && $is_wp_post === 'yes') { $post_data = [ 'post_title' => $title, 'post_content' => $content, // This content can be generated by using the keywords together 'post_type' => $this->ws4agpt_get_settings('ws4agpt_post_type') ?: 'post', 'post_status' => $this->ws4agpt_get_settings('ws4agpt_publish') === 'yes' ? 'publish' : 'draft', 'post_category'=> $_cats, // Add the keywords as post tags (comma-separated) 'tags_input' => $keywords_list, // Here we use the combined list ]; $post_id = wp_insert_post($post_data); if (is_wp_error($post_id)) { $error_message = esc_html($post_id->get_error_message()); // $result['error'] = $error_message; $result['error'] = "Failed to post article on Wordpress"; }else{ $result['success'] = "Article generated successfully."; unset($result['error']); } $created_url = get_edit_post_link($post_id); } ob_clean(); return $result; } private function ws4agpt_generate_long_article_in_chunks($title, $keywords, $cats, $company, $length, $density = 1) { $chunk_word_count = 1000; $total_chunks = ceil($length / $chunk_word_count); // Step 1: Generate outline (only top-level subtopics) $outline_prompt = "Generate a detailed outline with {$total_chunks} unique subtopics for an article titled: \"{$title}\". Each topic must be unique, specific, and suitable for expanding into 1000 words. Return as a numbered plain list."; $outline_response = $this->ws4agpt_get_api_completions($outline_prompt, $length); $outline_json = json_decode($outline_response); $outline_text = $outline_json->choices[0]->message->content ?? ''; // Parse only top-level numbered items (ignore nested bullets) preg_match_all('/^\d+\.\s*(.+)$/m', $outline_text, $matches); $outline_topics = $matches[1] ?? []; if (empty($outline_topics)) { $this->ws4agpt_log_error('ws4agpt_generate_long_article_in_chunks', $outline_json); return ''; } $covered_topics = []; $previous_summaries = []; $final_content = []; for ($i = 0; $i < count($outline_topics); $i++) { $part = $i + 1; $sub_topics = trim($outline_topics[$i]); $subtopic = str_replace('*', '', $sub_topics); $is_last = ($part === count($outline_topics)); // Append subtopic to prompt title $custom_title = "{$title} - {$subtopic}"; // Generate prompt using your cleaned function $prompt = $this->ws4agpt_prepare_prompt($custom_title, $keywords, $cats, $company, $chunk_word_count, $density); // Add anti-duplication logic if (!empty($previous_summaries)) { $prompt .= "\n\n== Previous Summaries ==\n"; foreach ($previous_summaries as $idx => $sum) { $prompt .= "Part " . ($idx + 1) . " Summary:\n{$sum}\n"; } } if (!empty($covered_topics)) { $prompt .= "\n== Do NOT Repeat These Subtopics ==\n"; foreach (array_unique($covered_topics) as $topic) { $prompt .= "- {$topic}\n"; } } // Add section logic $prompt .= "\n\nWrite Part {$part} of the article. Focus only on the topic: \"{$subtopic}\".\n Use subheadings. Do not repeat previous ideas.\n"; // Request content $response = $this->ws4agpt_get_api_completions($prompt, $length); $result = json_decode($response); $content = $result->choices[0]->message->content ?? ''; if ( empty( $content ) ) { $this->ws4agpt_log_error( 'ws4agpt_generate_long_article_in_chunks', 'Chunk ' . $part . ' returned empty content.' ); return ''; // Stop execution and return error immediately } // Track topics (subheadings) preg_match_all('/]*>(.*?)<\/h[2-4]>|^(#+\s*)(.*)/m', $content, $matches); $headings = array_filter(array_map('trim', array_merge($matches[1], $matches[3]))); $covered_topics = array_merge($covered_topics, $headings); // Summarize this chunk (light summary logic) $summary_prompt = "Summarize this section in 2-3 sentences:\n\n{$content}"; $summary_response = $this->ws4agpt_get_api_completions($summary_prompt, $length); // Append content $final_content[] = $content; } return implode("\n\n", $final_content); } private function ws4agpt_prepare_prompt($title, $keywords, $cats, $company = '', $length = 1000, $density = 1) { // Convert length and density to integers to prevent string multiplication $length = intval($length); $density = intval($density); // Calculate keyword frequency using integers $keyword_frequency = (int)(($length * $density) / 100); // Sanitize title $title = htmlspecialchars($title, ENT_QUOTES, 'UTF-8'); // Prepare keyword phrase if (is_array($keywords)) { $keywords = implode('", "', array_values($keywords)); } $prompt = "Write an engaging, well-structured article with the following specifications:\n"; $prompt .= "- Length: Up to {$length} words.\n"; $prompt .= "- Title: \"{$title}\" (but do NOT include this title at the top of the article).\n"; $prompt .= "Writing rules:\n"; $prompt .= "- Use a clear introduction, body, and conclusion.\n"; $prompt .= "- Organize with proper paragraphs (

) and logical flow.\n"; $prompt .= "- The content must be unique, informative, and engaging.\n"; $prompt .= "- Avoid keyword stuffing. Use synonyms and natural variations.\n"; $prompt .= "- Write in a conversational but professional tone.\n\n"; // Keyword handling (dynamic) $prompt .= "Keyword usage rules:\n"; $prompt .= "- Exact Keyword Phrase: Use the exact keyword phrase \"{$keywords}\" exactly as provided and it must always appear inside complete sentences or paragraphs. The phrase \"{$keywords}\" must appear exactly {$keyword_frequency} times in the article.\n"; $prompt .= "IMPORTANT: NEVER use the keyword phrase(s) as a heading, subheading, bold line, bullet point, or standalone text.\n"; $prompt .= "- Do not wrap the keyword phrase(s) in

,

,

, or make them separate titles or links.\n"; $prompt .= "- Spread the keyword phrase(s) naturally across the article, without repetition in close proximity.\n\n"; $prompt .= "- Maintain readability, flow, and natural language as the top priority.\n"; // Include categories if provided if (is_array($cats) && !empty($cats)) { $categories = implode('", "', $cats); $prompt .= "- Mention the category terms \"{$categories}\" naturally at least twice in the article body.\n"; // $prompt .= "- In the content, ensure the phrase \"{$categories}\" is mentioned at least twice within the body in the article.\n"; } elseif (!empty($cats)) { $prompt .= "- Mention the category term \"{$cats}\" naturally at least twice in the article body.\n"; // $prompt .= "- In the content, ensure the phrase \"{$cats}\" is mentioned at least twice within the body in the article.\n"; } // Include company name if provided if (!empty($company)) { $prompt .= "- Include the company name \"{$company}\" exactly twice in the article in natural, meaningful sentences. Do not use variations or additional words.\n"; } // Strong instruction to avoid hashes $prompt .= "- DO NOT use the hash (#) symbol anywhere. All headings, subheadings, titles, and paragraphs must be plain text only. Do NOT use Markdown-style headers like '### Heading'.\n"; $prompt .= "- Use only plain text headings and subheadings. Numbered or bulleted lists are allowed as plain text (e.g., '1. Heading', 'A. Subheading').\n"; $prompt .= "Ensure that the exact keyword phrase \"{$keywords}\" is used precisely as provided, without any consideration for grammar or sentence structure. The keyword phrase must be used exactly {$keyword_frequency} times throughout the article.\n"; $prompt .= "Remember, the keyword phrase \"{$keywords}\" must be inserted exactly as provided, regardless of its impact on the readability or grammar of the content. This requirement is non-negotiable, and the keyword phrase should be used exactly {$keyword_frequency} times, even if it does not make grammatical sense."; $prompt .= "- DO NOT use hash (#) symbols anywhere in the article, including in subheadings or titles. This includes Markdown-style headers (e.g., `### Heading`).\n"; // Log the generated prompt for debugging return $prompt; } private function ws4agpt_get_api_completions($prompt, $length) { // Retrieve API key and other settings $key = get_option('ws4agpt_aeS25_wsfa_wsfa'); $iv = substr($key, 0, 16); $apiKey = openssl_decrypt($this->ws4agpt_get_settings('ws4agpt_api_key'), 'AES-256-CBC', $key, 0, $iv); // phpcs:ignore $model = $this->ws4agpt_get_settings('ws4agpt_gpt-model'); $top_p = $this->ws4agpt_get_settings('ws4agpt_top_p'); $temperature = $this->ws4agpt_get_settings('ws4agpt_temprature'); $presence_penalty = $this->ws4agpt_get_settings('ws4agpt_presence_penalty'); $frequency_penalty = $this->ws4agpt_get_settings('ws4agpt_frequency_penalty'); $api_n = $this->ws4agpt_get_settings('ws4agpt_api_n'); $best_of = $this->ws4agpt_get_settings('ws4agpt_best_of'); $max_tokens = $this->ws4agpt_get_settings('ws4agpt_max_tokens'); // Set the request headers $headers = array( "Content-Type: application/json", "Authorization: Bearer " . $apiKey, ); $gpt_3_models = array('gpt-3.5-turbo', 'gpt-3.5-turbo-16k'); $gpt_4_models = array('gpt-4', 'gpt-4-turbo', 'gpt-4-turbo-32k'); $gpt_4_mini_models = array('gpt-4o-mini'); if ( in_array( $model, $gpt_3_models ) ) { $url = "https://api.openai.com/v1/chat/completions"; $message = new stdClass(); $message->role = 'user'; $message->content = $prompt; $gpt3_max_tokens = 3900; $data = array( "model" => $model, "messages" => array($message), "temperature" => (float) $temperature, "top_p" => (float) $top_p, "frequency_penalty" => (float) $frequency_penalty, "presence_penalty" => (float) $presence_penalty, "n" => (int) $api_n, "max_tokens" => (int) $gpt3_max_tokens, ); } elseif (in_array($model, $gpt_4_models)) { $url = "https://api.openai.com/v1/chat/completions"; $message = new stdClass(); $message->role = 'user'; $message->content = $prompt; $gpt4_max_tokens = 3900; $data = array( "model" => $model, "messages" => array($message), "temperature" => (float) $temperature, "top_p" => (float) $top_p, "frequency_penalty" => (float) $frequency_penalty, "presence_penalty" => (float) $presence_penalty, "n" => (int) $api_n, "max_tokens" => (int) $gpt4_max_tokens, ); } elseif (in_array($model, ['gpt-4o'])) { $url = "https://api.openai.com/v1/chat/completions"; $message = new stdClass(); $message->role = 'user'; $message->content = $prompt; $max_tokens = 5000; $data = array( "model" => $model, "messages" => array($message), "temperature" => (float) $temperature, "top_p" => (float) $top_p, "frequency_penalty" => (float) $frequency_penalty, "presence_penalty" => (float) $presence_penalty, "n" => (int) $api_n, "max_tokens" => (int) $max_tokens, ); } elseif (in_array($model, ['gpt-4o-mini'])) { $url = "https://api.openai.com/v1/chat/completions"; $message = new stdClass(); $message->role = 'user'; $message->content = $prompt; $gpt4mini_max_tokens = (int) ceil($length * 1.1); $data = array( "model" => $model, "messages" => array($message), "temperature" => (float) $temperature, "top_p" => (float) $top_p, "frequency_penalty" => (float) $frequency_penalty, "presence_penalty" => (float) $presence_penalty, "n" => (int) $api_n, "max_tokens" => (int) $gpt4mini_max_tokens, ); } else { $url = "https://api.openai.com/v1/completions"; $data = array( "model" => $model, "prompt" => $prompt, "temperature" => (float) $temperature, "top_p" => (float) $top_p, "frequency_penalty" => (float) $frequency_penalty, "presence_penalty" => (float) $presence_penalty, "n" => (int) $api_n, "best_of" => (int) $best_of, "max_tokens" => (int) $max_tokens, ); } // Log the request data for debugging //$this->ws4agpt_log_error('ws4agpt_get_api_completions $data', $data); $response = $this->ws4agpt_process_request($url, $apiKey, $data, true); return $response; } function ws4agpt_process_request($url, $apiKey, $data = array(), $post = false) { $headers = array( 'Authorization' => 'Bearer ' . $apiKey, 'Content-Type' => 'application/json', ); $args = array( 'method' => $post ? 'POST' : 'GET', 'timeout' => 120, 'headers' => $headers, 'body' => !empty($data) ? wp_json_encode($data) : null, ); $response = wp_remote_request($url, $args); if (is_wp_error($response)) { return new WP_Error('request_failed', 'Failed to make the API request', $response->get_error_message()); } return wp_remote_retrieve_body($response); } function ws4agpt_insert_term($term_type, $term_name, $link1='', $link2='', $term_parent=0) { $result = array(); $term_name = sanitize_text_field(trim($term_name)); if (!empty($term_name)) { $term = get_term_by('name', $term_name, $term_type); if (!$term) { $term = wp_insert_term( $term_name, $term_type, array('parent' => $term_parent) ); if (!is_wp_error($term)) { $result['term_id'] = $term['term_id']; } else { $result['error'] = $term->get_error_message(); return $result; // Return early if there's an error } } else { $result['term_id'] = $term->term_id; } } else { $result['error'] = "Term name is empty."; return $result; // Return early if the term name is empty } if (isset($result['term_id'])) { $option_key = 'ws4agpt_taxonomy_' . $result['term_id']; $term_meta = get_option( $option_key, array() ); // default is array, no warning if ( ! is_array( $term_meta ) ) { $term_meta = array(); } // $term_meta = get_option("ws4agpt_taxonomy_" . $result['term_id']); $term_meta['keyword_link1'] = $link1; $term_meta['keyword_link2'] = $link2; update_option( $option_key, $term_meta ); } return $result; } function ws4agpt_is_turbo_model($model){ // List of turbo models $turbo_models = array( 'gpt-3.5-turbo', 'gpt-3.5-turbo-0301', 'gpt-4', 'gpt-4-turbo', 'gpt-4-turbo-32k', 'gpt-4o', 'gpt-4o-mini' ); return in_array($model, $turbo_models); } /* Add custom cron schedules. * The default supported recurrences are hourly, twicedaily, daily and weekly. */ function ws4agpt_add_schedules( $schedules ) { $schedules['minute'] = array( 'interval' => 60, 'display' => __( 'Every Minute', 'ai-auto-seo' ), ); $schedules['everytwominutes'] = array( 'interval' => 120, 'display' => __( 'Every two minutes', 'ai-auto-seo' ), ); $schedules['everyfiveminutes'] = array( 'interval' => 300, 'display' => __('Every five minutes', 'ai-auto-seo') ); $schedules['sixtimesaweek'] = array( 'interval' => 100800, 'display' => __('Six times a Week', 'ai-auto-seo') ); $schedules['fivetimesaweek'] = array( 'interval' => 120960, 'display' => __('Five times a Week', 'ai-auto-seo') ); $schedules['fourtimesaweek'] = array( 'interval' => 151200, 'display' => __('Four times a Week', 'ai-auto-seo') ); $schedules['thriceweekly'] = array( 'interval' => 201600, 'display' => __('Thrice a Week', 'ai-auto-seo') ); $schedules['twiceweekly'] = array( 'interval' => 302400, ); $schedules['thricemonthly'] = array( 'interval' => 864000, 'display' => __('Thrice a Month', 'ai-auto-seo') ); $schedules['twicemonthly'] = array( 'interval' => 1296000, 'display' => __('Twice a Month', 'ai-auto-seo') ); $schedules['monthly'] = array( 'interval' => 2592000, 'display' => __('Once a Month', 'ai-auto-seo') ); return $schedules; } public function ws4agpt_dismiss_notice(){ // Verify the nonce before processing form data $nonce = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : ''; // phpcs:ignore if (!wp_verify_nonce($nonce, 'ws4agpt_dismiss_notices')) { wp_send_json_error(); } // Check if notice_id exists and unslash it $notice_id = isset($_POST['notice_id']) ? sanitize_text_field(wp_unslash($_POST['notice_id'])) : ''; if (empty($notice_id)) { wp_send_json_error(); } $user_id = get_current_user_id(); update_user_meta($user_id, $notice_id, time()); wp_send_json_success(); } public static function ws4agpt_admin_notice(){ global $pagenow; $post_type = isset($_GET['post_type']) ? sanitize_text_field(wp_unslash($_GET['post_type'])) : ''; // phpcs:ignore $page_type = isset($_GET['page']) ? sanitize_text_field(wp_unslash($_GET['page'])) : ''; // phpcs:ignore $ws4agpt_page_types = [ 'ws4agpt_gpt_image_options', 'ws4agpt_gpt_single_options', 'ws4agpt_gpt_bulk_options', 'ws4agpt_gpt_settings', ]; $ws4agpt_user_id = get_current_user_id(); $ws4agpt_notice_id = 'ws4agpt_promo_notice'; // Check dismissal timestamp $last_dismissed = get_user_meta($ws4agpt_user_id, $ws4agpt_notice_id, true); if ($last_dismissed && (time() - intval($last_dismissed)) < 86400) { return; // less than 1 day, don't show } $is_plugin_screen = ( ($pagenow === 'edit.php' && $post_type === 'ws4agpt_gpt_post') || in_array($page_type, $ws4agpt_page_types) ); if (get_option('ws4agpt_auto_seo_pro_active') !== 'yes' && $is_plugin_screen) { // Get current stored text $stored_promo = array( 'heading' => get_option('ws4agpt_promo_heading', __('qqGet the Pro Version and Build Content and Links Across Social Media and Other Sites Now!', 'ai-auto-seo')), 'subtext' => get_option('ws4agpt_promo_subtext', __('Bulk Schedule, Local Posts, and more!', 'ai-auto-seo')), 'image' => get_option('ws4agpt_promo_image', ''), 'link' => get_option('ws4agpt_promo_link', 'https://websiteservice4all.com') ); // Try to get server text with increased timeout $args = array( 'headers' => array( 'Cache-Control' => 'no-cache', // Prevent caching 'Pragma' => 'no-cache', // Prevent caching ), 'timeout' => 10 ); $response = wp_remote_get('https://autoseoguys.com/wp-json/free-plugin-message/v1/data?timestamp=' . time(), $args); // Log error if request fails if (is_wp_error($response)) { // Production code should use proper logging mechanism instead of error_log } elseif (200 === wp_remote_retrieve_response_code($response)) { $promo_data = json_decode(wp_remote_retrieve_body($response), true); if ($promo_data && isset($promo_data['heading']) && isset($promo_data['subtext']) && isset($promo_data['image']) && isset($promo_data['link'])) { $server_promo = array( 'heading' => sanitize_text_field($promo_data['heading']), 'subtext' => sanitize_text_field($promo_data['subtext']), 'image' => esc_url_raw($promo_data['image']), 'link' => esc_url_raw($promo_data['link']) ); // Compare and update if different if ($stored_promo['heading'] !== $server_promo['heading'] || $stored_promo['subtext'] !== $server_promo['subtext'] || $stored_promo['image'] !== $server_promo['image'] || $stored_promo['link'] !== $server_promo['link']) { update_option('ws4agpt_promo_heading', $server_promo['heading']); update_option('ws4agpt_promo_subtext', $server_promo['subtext']); update_option('ws4agpt_promo_image', $server_promo['image']); update_option('ws4agpt_promo_link', $server_promo['link']); $stored_promo = $server_promo; } } } // Build the notice HTML $notice_html = '
'; // Add image if exists if (!empty($stored_promo['image'])) { $notice_html .= 'Promo Image';// phpcs:ignore } $notice_html .= '

' . esc_html($stored_promo['heading']) . '

' . '

' . esc_html($stored_promo['subtext']) . '

' . '' . esc_html__('CLICK HERE', 'ai-auto-seo') . '' . '
' . '
'; echo wp_kses_post($notice_html); } } function ws4agpt_add_plugin_action_link($links){ $option = get_option('ws4agpt_auto_seo_pro_active'); if($option != 'yes'){ // Build the URL $pro_url = 'https://autoseoguys.com/'; $settings_url = admin_url('edit.php?post_type=ws4agpt_gpt_post&page=ws4agpt_gpt_settings'); // Pro link $pro_link = '' . esc_html__('Upgrade to PRO', 'ai-auto-seo') . ''; // Settings link $settings_link = '' . esc_html__('Settings', 'ai-auto-seo') . ''; // Link first: Having the link show up as the first link array_unshift($links, $pro_link); array_unshift($links, $settings_link); } return $links; } public function ws4agpt_admin_enqueue_scripts(){ $ws4agpt_js_path = WS4AGPT_ARTICLES_PLUGIN_DIR . 'assets/js/scripts.js'; $ws4agpt_js_ver = defined( 'WS4AGPT_ARTICLES_VERSION' ) ? WS4AGPT_ARTICLES_VERSION : ( file_exists( $ws4agpt_js_path ) ? filemtime( $ws4agpt_js_path ) : false ); wp_enqueue_script( 'ws4agpt-gpt-script', plugins_url( 'assets/js/scripts.js', __FILE__ ), array( 'jquery' ), $ws4agpt_js_ver, true ); $key = get_option('ws4agpt_aeS25_wsfa_wsfa'); $iv = substr($key, 0, 16); if($key){ $apiKey=openssl_decrypt($this->ws4agpt_get_settings('ws4agpt_api_key'), 'AES-256-CBC', $key, 0, $iv); // phpcs:ignore }else{ $apiKey=$this->ws4agpt_get_settings('ws4agpt_api_key'); } $is_wp_post_enabled = $this->ws4agpt_get_settings('is_wp_post'); $model = $this->ws4agpt_get_settings('ws4agpt_gpt-model'); $gptmodeltoken = $this->ws4agpt_get_settings('ws4agpt_max_tokens'); $localized_data = array( 'apiKey' => esc_js($apiKey), 'submitRunnowNonce' => wp_create_nonce('ws4agpt_handle_submit_run_now_data'), 'submitNonce' => wp_create_nonce('ws4agpt_handle_submit_post_data'), 'statusNonce' => wp_create_nonce('ws4agpt_handle_check_post_task_status'), 'imagoptionNonce' => wp_create_nonce('ws4agpt_handle_submit_post_imgdata'), 'settinggeneralNonce' => wp_create_nonce('ws4agpt_handle_check_post_taskss_status'), 'dismisspromoNonce' => wp_create_nonce('ws4agpt_dismiss_notices'), 'ajaxUrl' => admin_url('admin-ajax.php'), 'isWpPostEnabled' => $is_wp_post_enabled, 'gptModel' => $model, 'gptModeltoken' => $gptmodeltoken, ); wp_localize_script('ws4agpt-gpt-script', 'WS4AGPT_VARS', $localized_data); } public static function ws4agpt_activation(){ self::ws4agpt_register_post_type(); flush_rewrite_rules(); add_option('ws4agpt_auto_seo_pro_active', 'no'); add_option('ws4agpt_manager', 'manage_options'); $args = array( false ); if (! wp_next_scheduled ( 'ws4agpt_auto_add_article_event' )) { wp_schedule_event( time(), 'daily', 'ws4agpt_auto_add_article_event' ); } // Add default promo text options add_option('ws4agpt_promo_heading', __('Get the Pro Version and Build Content and Links Across Social Media and Other Sites Now!', 'ai-auto-seo')); add_option('ws4agpt_promo_subtext', __('Bulk Schedule, Local Posts, and more!', 'ai-auto-seo')); add_option('ws4agpt_promo_image', ''); add_option('ws4agpt_promo_link', 'https://websiteservice4all.com'); } public static function ws4agpt_deactivation() { wp_clear_scheduled_hook( 'ws4agpt_auto_add_article_event' ); } public function ws4agpt_log_error($title, $data) { if ($this->log) { global $wp_filesystem; // Ensure WP_Filesystem is initialized if (empty($wp_filesystem)) { require_once ABSPATH . 'wp-admin/includes/file.php'; WP_Filesystem(); } // Log file path $upload_dir = wp_upload_dir(); $log_dir = trailingslashit($upload_dir['basedir']) . 'aiautoseo-logs'; // Create the directory if it doesn't exist if (!file_exists($log_dir)) { wp_mkdir_p($log_dir); } $log_file = trailingslashit($log_dir) . 'gpt_logs.log'; // Prepare the timestamp in UTC format $timestamp = gmdate('Y-m-d H:i:s'); // Prepare the log message $log_message = $timestamp . ' ' . $title . "\r\n"; // If data is an array or object, print it; else, append the string if (!is_string($data)) { $log_message .= wp_json_encode($data, JSON_PRETTY_PRINT); } else { $log_message .= $data; } $log_message .= "\r\n"; // Append the log message to the file if ($wp_filesystem->exists($log_file) || $wp_filesystem->put_contents($log_file, '', FS_CHMOD_FILE)) { // Retrieve current content, append the new log, and save it back $current_content = $wp_filesystem->get_contents($log_file); $new_content = $current_content . $log_message; $wp_filesystem->put_contents($log_file, $new_content, FS_CHMOD_FILE); } else { $message = "Could not write to log file: $log_file"; } } } public function ws4agpt_maybe_upgrade() { $current_version = get_option('ws4agpt_version', '1.0.0'); if (version_compare($current_version, WS4AGPT_ARTICLES_VERSION, '<')) { // Perform any upgrade tasks here // Update the stored version number update_option('ws4agpt_version', WS4AGPT_ARTICLES_VERSION); } } private function ws4agpt_parseMarkdown($markdown) { // Extract and remove the title if (preg_match('/^# ([^\n]+)\n/', $markdown, $matches)) { $title = $matches[1]; // Store the title if needed $markdown = str_replace($matches[0], '', $markdown); } // Remove any extra newlines at the start $markdown = ltrim($markdown); // Convert headings (e.g., ### Heading 3) $markdown = preg_replace('/^### (.+)$/m', '

$1

', $markdown); $markdown = preg_replace('/^## (.+)$/m', '

$1

', $markdown); $markdown = preg_replace('/^# (.+)$/m', '

$1

', $markdown); // Convert bold text (e.g., **bold**) $markdown = preg_replace('/\*\*(.+?)\*\*/', '$1', $markdown); // Convert italic text (e.g., *italic*) $markdown = preg_replace('/\*(.+?)\*/', '$1', $markdown); // Convert line breaks $markdown = nl2br($markdown); return $markdown; } } global $ws4agpt_admin; $ws4agpt_admin = new WS4AGPT_Admin();