如何让WordPress插件在草稿文章创建后自动执行标题改写?
实现WordPress草稿自动改写标题并发布
问题概述
我开发了一款WordPress插件,可将草稿文章的标题改写为36-38字符长度,手动点击「Autofill」按钮能正常触发流程:调用ChatGPT改写标题、检查字符长度(不符合则重复调用)、更新标题并发布文章。但现在需要实现新草稿保存时自动启动该流程,尝试过钩子和cron任务但未成功,求可行方案。
解决方案
要实现自动触发,核心是利用WordPress的save_post钩子监听草稿创建事件,并将原前端的ChatGPT调用逻辑重构为PHP后端函数,避免前端依赖。以下是具体实现步骤和修改后的完整代码:
1. 核心修改点
- 新增PHP版ChatGPT调用函数,替代前端AJAX逻辑
- 注册
save_post钩子,监听新草稿创建事件 - 添加触发条件判断,仅在新草稿首次保存时执行
- 保留循环调用逻辑,确保标题长度符合要求
- 添加错误处理,避免流程中断
2. 修改后的完整代码
<?php /* Plugin Name: ChatGPT Dashboard */ // Add a custom menu item to the WordPress dashboard function chatgpt_dashboard_menu() { add_menu_page( 'ChatGPT Dashboard', 'ChatGPT', 'manage_options', 'chatgpt-dashboard', 'chatgpt_dashboard_page', 'dashicons-format-chat', 20 ); } add_action('admin_menu', 'chatgpt_dashboard_menu'); // Enqueue jQuery UI library function chatgpt_enqueue_scripts() { wp_enqueue_script('jquery-ui-core'); wp_enqueue_script('jquery-ui-draggable'); } add_action('admin_enqueue_scripts', 'chatgpt_enqueue_scripts'); // Register plugin settings function chatgpt_register_settings() { register_setting('chatgpt_options', 'chatgpt_api_key'); } add_action('admin_init', 'chatgpt_register_settings'); // Callback function to display the ChatGPT dashboard page function chatgpt_dashboard_page() { ?> <div class="wrap"> <h1>ChatGPT Dashboard</h1> <!-- API Key settings form --> <form method="post" action="options.php"> <?php settings_fields('chatgpt_options'); ?> <?php do_settings_sections('chatgpt_options'); ?> <table class="form-table"> <tr valign="top"> <th scope="row">API Key</th> <td><input type="text" name="chatgpt_api_key" value="<?php echo esc_attr(get_option('chatgpt_api_key')); ?>" /></td> </tr> </table> <?php submit_button(); ?> </form> <!-- Chat interface --> <div id="chat-container"> <div id="chat-log"></div> <input type="text" id="user-input" placeholder="Type your message..." /> <button id="submit-button">Send</button> <button id="autofill-button">Autofill</button> </div> </div> <script> (function ($) { $(document).ready(function () { // Function to handle user input and generate ChatGPT responses function handleUserInput() { var userInput = $('#user-input').val(); // Get the API key from the WordPress options database var apiKey = '<?php echo get_option("chatgpt_api_key"); ?>'; // Make sure the API key is provided if (!apiKey) { alert('Please enter an API key in the ChatGPT dashboard settings.'); return; } // Make an API call to ChatGPT to get a response function callChatGPT() { $.ajax({ url: 'https://api.openai.com/v1/chat/completions', type: 'POST', beforeSend: function (xhr) { xhr.setRequestHeader('Authorization', 'Bearer ' + apiKey); xhr.setRequestHeader('Content-Type', 'application/json'); }, data: JSON.stringify({ model: 'gpt-3.5-turbo', messages: [ { role: 'system', content: 'You are a user' }, { role: 'user', content: userInput }, ], }), success: function (response) { var chatLog = $('#chat-log'); if (!response.choices || !response.choices.length) { chatLog.append('<p><strong>Error:</strong> No response received</p>'); return; } var botResponse = response.choices[0].message.content; // Check if botResponse is an array if (Array.isArray(botResponse)) { botResponse = botResponse.map(msg => msg.content).join(''); } // Count the number of characters in the bot response var characterCount = botResponse.length; // Display the user input, bot response, and character count in the chat log chatLog.append('<p><strong>You:</strong> ' + userInput + '</p>'); chatLog.append('<p><strong>Bot:</strong> ' + botResponse + '</p>'); chatLog.append('<p><strong>Character count:</strong> ' + characterCount + '</p>'); // Clear the user input field $('#user-input').val(''); // Scroll to the bottom of the chat log chatLog.scrollTop(chatLog.prop('scrollHeight')); // Check if the character count is within the desired range (36, 37, or 38) if (characterCount >= 36 && characterCount <= 38) { // Print the new title 5 times in a row for (let i = 0; i < 5; i++) { chatLog.append('<p><strong>New Title:</strong> ' + botResponse + '</p>'); } // Update draft post and publish $.ajax({ url: '<?php echo admin_url("admin-ajax.php"); ?>', type: 'POST', data: { action: 'create_draft_post', title: botResponse, }, success: function (response) { console.log('Draft post updated:', response); chatLog.append('<p><strong>New Title:</strong> ' + botResponse + '</p>'); }, error: function (xhr, status, error) { console.error(error); }, }); return; } // Repeat the question until the character count is within the desired range callChatGPT(); }, error: function (xhr, status, error) { var chatLog = $('#chat-log'); chatLog.append('<p><strong>Error:</strong> ' + error + '</p>'); console.error(error); }, }); } callChatGPT(); } // Handle user input when the submit button is clicked $('#submit-button').on('click', function (e) { e.preventDefault(); handleUserInput(); }); // Handle user input when the enter key is pressed $('#user-input').on('keydown', function (e) { if (e.keyCode === 13) { e.preventDefault(); handleUserInput(); } }); // Handle autofill button click $('#autofill-button').on('click', function (e) { e.preventDefault(); // Get the draft posts $.ajax({ url: '<?php echo admin_url("admin-ajax.php"); ?>', type: 'POST', data: { action: 'get_draft_posts', }, success: function (response) { if (response && response.length) { var draftTitle = response[0].post_title; var autofillText = 'Summarize "' + draftTitle + '" to 38 characters'; $('#user-input').val(autofillText); // Automatically start the process of generating the response handleUserInput(); } }, error: function (xhr, status, error) { console.error(error); }, }); }); }); })(jQuery); </script> <?php } // AJAX handler to retrieve draft posts function chatgpt_get_draft_posts() { $draftPosts = get_posts(array( 'post_status' => 'draft', 'numberposts' => 1, )); wp_send_json($draftPosts); } add_action('wp_ajax_get_draft_posts', 'chatgpt_get_draft_posts'); add_action('wp_ajax_nopriv_get_draft_posts', 'chatgpt_get_draft_posts'); // AJAX handler to update the existing draft post with the new title and publish it function chatgpt_create_draft_post() { $title = sanitize_text_field($_POST['title']); $draftPosts = get_posts(array( 'post_status' => 'draft', 'numberposts' => 1, )); if (empty($draftPosts)) { wp_send_json_error('No draft post found.'); return; } $draftPost = $draftPosts[0]; $draftPostID = $draftPost->ID; // Update the title of the draft post wp_update_post(array( 'ID' => $draftPostID, 'post_title' => $title, 'post_status' => 'publish', )); wp_send_json_success($draftPostID); } add_action('wp_ajax_create_draft_post', 'chatgpt_create_draft_post'); add_action('wp_ajax_nopriv_create_draft_post', 'chatgpt_create_draft_post'); // -------------------------- 新增自动处理逻辑 -------------------------- // PHP版ChatGPT调用函数 function chatgpt_call_api($prompt) { $api_key = get_option('chatgpt_api_key'); if (!$api_key) return false; $url = 'https://api.openai.com/v1/chat/completions'; $headers = array( 'Authorization' => 'Bearer ' . $api_key, 'Content-Type' => 'application/json' ); $body = json_encode(array( 'model' => 'gpt-3.5-turbo', 'messages' => array( array('role' => 'system', 'content' => 'You are a professional title editor.'), array('role' => 'user', 'content' => $prompt) ) )); $response = wp_remote_post($url, array( 'headers' => $headers, 'body' => $body, 'timeout' => 30 )); if (is_wp_error($response)) return false; $data = json_decode(wp_remote_retrieve_body($response), true); if (empty($data['choices'][0]['message']['content'])) return false; return trim($data['choices'][0]['message']['content']); } // 自动处理新草稿标题 function chatgpt_auto_process_draft($post_id, $post, $update) { // 跳过自动保存、修订版,仅处理新创建的草稿 if (wp_is_post_autosave($post_id) || wp_is_post_revision($post_id)) return; if ($update || $post->post_status !== 'draft') return; $original_title = $post->post_title; $prompt = "Summarize \"{$original_title}\" to a title with exactly 36-38 characters."; $new_title = ''; $max_attempts = 5; // 限制最大尝试次数,避免无限循环 $attempts = 0; // 循环调用直到符合长度要求或达到最大尝试次数 while ($attempts < $max_attempts) { $new_title = chatgpt_call_api($prompt); if (!$new_title) break; $char_count = mb_strlen($new_title); if ($char_count >= 36 && $char_count <= 38) { // 更新标题并发布 wp_update_post(array( 'ID' => $post_id, 'post_title' => $new_title, 'post_status' => 'publish' )); break; } $attempts++; // 调整提示词,告知当前长度不符合要求 $prompt = "Summarize \"{$original_title}\" to a title with exactly 36-38 characters. Current title is {$char_count} characters: {$new_title}"; } } add_action('save_post', 'chatgpt_auto_process_draft', 10, 3);
3. 关键说明
save_post钩子触发条件:仅在新草稿首次创建时执行(排除自动保存、修订版和已发布文章更新)- ChatGPT调用限制:添加了
max_attempts限制,避免因API返回始终不符合要求导致无限循环 - 安全处理:对用户输入的标题进行
sanitize_text_field过滤,确保数据安全 - 错误处理:检测API调用失败情况,避免流程中断
内容的提问来源于stack exchange,提问作者Luke
相关产品推荐
相关产品推荐

