admin管理员组

文章数量:1131573

I'm currently trying to work with webhooks without using any plugins, and I'd like to avoid them if possible.

The webhook should be triggered when a change is made to the Custom Post Type "event." So far, so good.

Now, I want to differentiate between:

  1. a brand-new post
  2. a modified already-existing post

And here's where it gets complicated!

When a new post is published, the function is triggered 3 times with the following statuses:

[10-Oct-2023 19:18:43 UTC] New Status: auto-draft
[10-Oct-2023 19:18:43 UTC] Old Status: new

[10-Oct-2023 19:19:04 UTC] New Status: publish
[10-Oct-2023 19:19:04 UTC] Old Status: auto-draft

[10-Oct-2023 19:19:06 UTC] New Status: publish
[10-Oct-2023 19:19:06 UTC] Old Status: publish

When an existing post is modified, the function is triggered twice:

[10-Oct-2023 19:23:04 UTC] New Status: publish
[10-Oct-2023 19:23:04 UTC] Old Status: publish

[10-Oct-2023 19:23:05 UTC] New Status: publish
[10-Oct-2023 19:23:05 UTC] Old Status: publish

I can certainly ensure in the receiving program that things are not processed twice. However, I simply cannot find a criterion to differentiate between a new post and an existing one.

At the moment I try to get it with the function "transition_post_status".

I also tried the function "save_post", but on save_post the update boolean is always 1. Regardless if I create a new post or modify an existing.

Happy for any hint!

functions.php:

// Add a custom REST API endpoint for the webhook
function custom_webhook_endpoint() {
    register_rest_route('custom-webhooks/v1', '/trigger', array(
        'methods' => 'POST',
        'callback' => 'custom_webhook_callback',
    ));
}

// Callback function to handle incoming webhook requests
function custom_webhook_callback($request) {
    // Process the webhook data and trigger your Python script or other actions
    // Example: $data = $request->get_json_params();
    // Implement your logic here

    // Return a response if needed
    return rest_ensure_response(array('message' => 'Webhook received successfully'));
}

add_action('rest_api_init', 'custom_webhook_endpoint');

function trigger_webhook_on_new_event($new_status, $old_status, $post) {
    // Check if the post type is 'event'
    error_log('New Status: ' . $new_status);
    error_log('Old Status: ' . $old_status);
    if ($post->post_type === 'event') {
        // Check if the post is being published (new or update)
        if ($post->post_type === 'event' && $new_status === 'publish' && $old_status !== 'publish') {
            // This is a new post
            // Set up the URL for your Python web handler for new posts
            $webhook_base = 'http://localhost:5000/webhook/add';
        } elseif ($new_status === 'publish') {
            // This is an update that changes the post_status to publish
            // Set up the URL for your Python web handler for updates that publish
            $webhook_base = 'http://localhost:5000/webhook/modify';
        }

        // Get post meta data
        $all_post_meta = get_post_meta($post->ID);

        $start = isset($all_post_meta['start'][0]) ? $all_post_meta['start'][0] : '';

        // Define the data you want to send in the POST request
        $data = array(
            'id' => $post->ID,
            'description' => $post->post_content,
            'excerpt' => $post->post_excerpt,
            'title' => $post->post_title,
            'url' => get_permalink($post->ID),
            'start' => $start,
        );

        // Send a POST request to your Python web handler
        $response = wp_safe_remote_post($webhook_base, array(
            'body' => json_encode($data),
            'headers' => array('Content-Type' => 'application/json'),
        ));

        // Check for errors in the response, if needed
        if (is_wp_error($response)) {
            // Handle errors here
            error_log('Webhook error: ' . $response->get_error_message());
        }
    }
}

add_action('transition_post_status', 'trigger_webhook_on_new_event', 10, 3);
function trigger_webhook_on_new_event($new_status, $old_status, $post) {
    // Check if the post type is 'event'
    error_log('New Status: ' . $new_status);
    error_log('Old Status: ' . $old_status);
    if ($post->post_type === 'event') {
        // Check if the post is being published (new or update)
        if ($post->post_type === 'event' && $new_status === 'publish' && $old_status !== 'publish') {
            // This is a new post
            // Set up the URL for your Python web handler for new posts
            $webhook_base = 'http://localhost:5000/webhook/add';
        } elseif ($new_status === 'publish') {
            // This is an update that changes the post_status to publish
            // Set up the URL for your Python web handler for updates that publish
            $webhook_base = 'http://localhost:5000/webhook/modify';
        }

        // Get post meta data
        $all_post_meta = get_post_meta($post->ID);

        $start = isset($all_post_meta['start'][0]) ? $all_post_meta['start'][0] : '';

        // Define the data you want to send in the POST request
        $data = array(
            'id' => $post->ID,
            'description' => $post->post_content,
            'excerpt' => $post->post_excerpt,
            'title' => $post->post_title,
            'url' => get_permalink($post->ID),
            'start' => $start,
        );

        // Send a POST request to your Python web handler
        $response = wp_safe_remote_post($webhook_base, array(
            'body' => json_encode($data),
            'headers' => array('Content-Type' => 'application/json'),
        ));

        // Check for errors in the response, if needed
        if (is_wp_error($response)) {
            // Handle errors here
            error_log('Webhook error: ' . $response->get_error_message());
        }
    }
}

add_action('transition_post_status', 'trigger_webhook_on_new_event', 10, 3);

webhandler.py:

from flask import Flask, request

app = Flask(__name__)

# Import the google_maps class here
from google_maps import google_maps

# Create an instance of the google_maps class
google_maps_instance = google_maps()

# Create variables to track the last post ID for modify and add webhooks
# WordPress call save post twice. I don't know why.
last_modify_post_id = None
last_add_post_id = None

@app.route('/webhook/modify', methods=['POST'])
def receive_webhook_modify():
    global last_modify_post_id

    # Get the JSON data from the incoming webhook request
    data = request.json

    # Check if the received post ID is the same as the last one for modify
    if data['id'] == last_modify_post_id:
        print("Webhook already processed for modify with post ID:", last_modify_post_id)
        return "Webhook already processed"

    # If it's a new post ID, process the webhook for modify
    last_modify_post_id = data['id']

    print("Received Webhook on modify:")
    print(data)

    # You can add your custom logic here to process the webhook data for modify

    return "Webhook received successfully"


@app.route('/webhook/add', methods=['POST'])
def receive_webhook_add():
    global last_add_post_id

    # Get the JSON data from the incoming webhook request
    data = request.json

    # Check if the received post ID is the same as the last one for add
    if data['id'] == last_add_post_id:
        print("Webhook already processed for add with post ID:", last_add_post_id)
        return "Webhook already processed"

    # If it's a new post ID, process the webhook for add
    last_add_post_id = data['id']

    print("Received Webhook on add:")
    print(data)

    # You can add your custom logic here to process the webhook data for add
    google_maps_instance.create_event(data)

    return "Webhook received successfully"

if __name__ == '__main__':
    app.run(port=5000)

I'm currently trying to work with webhooks without using any plugins, and I'd like to avoid them if possible.

The webhook should be triggered when a change is made to the Custom Post Type "event." So far, so good.

Now, I want to differentiate between:

  1. a brand-new post
  2. a modified already-existing post

And here's where it gets complicated!

When a new post is published, the function is triggered 3 times with the following statuses:

[10-Oct-2023 19:18:43 UTC] New Status: auto-draft
[10-Oct-2023 19:18:43 UTC] Old Status: new

[10-Oct-2023 19:19:04 UTC] New Status: publish
[10-Oct-2023 19:19:04 UTC] Old Status: auto-draft

[10-Oct-2023 19:19:06 UTC] New Status: publish
[10-Oct-2023 19:19:06 UTC] Old Status: publish

When an existing post is modified, the function is triggered twice:

[10-Oct-2023 19:23:04 UTC] New Status: publish
[10-Oct-2023 19:23:04 UTC] Old Status: publish

[10-Oct-2023 19:23:05 UTC] New Status: publish
[10-Oct-2023 19:23:05 UTC] Old Status: publish

I can certainly ensure in the receiving program that things are not processed twice. However, I simply cannot find a criterion to differentiate between a new post and an existing one.

At the moment I try to get it with the function "transition_post_status".

I also tried the function "save_post", but on save_post the update boolean is always 1. Regardless if I create a new post or modify an existing.

Happy for any hint!

functions.php:

// Add a custom REST API endpoint for the webhook
function custom_webhook_endpoint() {
    register_rest_route('custom-webhooks/v1', '/trigger', array(
        'methods' => 'POST',
        'callback' => 'custom_webhook_callback',
    ));
}

// Callback function to handle incoming webhook requests
function custom_webhook_callback($request) {
    // Process the webhook data and trigger your Python script or other actions
    // Example: $data = $request->get_json_params();
    // Implement your logic here

    // Return a response if needed
    return rest_ensure_response(array('message' => 'Webhook received successfully'));
}

add_action('rest_api_init', 'custom_webhook_endpoint');

function trigger_webhook_on_new_event($new_status, $old_status, $post) {
    // Check if the post type is 'event'
    error_log('New Status: ' . $new_status);
    error_log('Old Status: ' . $old_status);
    if ($post->post_type === 'event') {
        // Check if the post is being published (new or update)
        if ($post->post_type === 'event' && $new_status === 'publish' && $old_status !== 'publish') {
            // This is a new post
            // Set up the URL for your Python web handler for new posts
            $webhook_base = 'http://localhost:5000/webhook/add';
        } elseif ($new_status === 'publish') {
            // This is an update that changes the post_status to publish
            // Set up the URL for your Python web handler for updates that publish
            $webhook_base = 'http://localhost:5000/webhook/modify';
        }

        // Get post meta data
        $all_post_meta = get_post_meta($post->ID);

        $start = isset($all_post_meta['start'][0]) ? $all_post_meta['start'][0] : '';

        // Define the data you want to send in the POST request
        $data = array(
            'id' => $post->ID,
            'description' => $post->post_content,
            'excerpt' => $post->post_excerpt,
            'title' => $post->post_title,
            'url' => get_permalink($post->ID),
            'start' => $start,
        );

        // Send a POST request to your Python web handler
        $response = wp_safe_remote_post($webhook_base, array(
            'body' => json_encode($data),
            'headers' => array('Content-Type' => 'application/json'),
        ));

        // Check for errors in the response, if needed
        if (is_wp_error($response)) {
            // Handle errors here
            error_log('Webhook error: ' . $response->get_error_message());
        }
    }
}

add_action('transition_post_status', 'trigger_webhook_on_new_event', 10, 3);
function trigger_webhook_on_new_event($new_status, $old_status, $post) {
    // Check if the post type is 'event'
    error_log('New Status: ' . $new_status);
    error_log('Old Status: ' . $old_status);
    if ($post->post_type === 'event') {
        // Check if the post is being published (new or update)
        if ($post->post_type === 'event' && $new_status === 'publish' && $old_status !== 'publish') {
            // This is a new post
            // Set up the URL for your Python web handler for new posts
            $webhook_base = 'http://localhost:5000/webhook/add';
        } elseif ($new_status === 'publish') {
            // This is an update that changes the post_status to publish
            // Set up the URL for your Python web handler for updates that publish
            $webhook_base = 'http://localhost:5000/webhook/modify';
        }

        // Get post meta data
        $all_post_meta = get_post_meta($post->ID);

        $start = isset($all_post_meta['start'][0]) ? $all_post_meta['start'][0] : '';

        // Define the data you want to send in the POST request
        $data = array(
            'id' => $post->ID,
            'description' => $post->post_content,
            'excerpt' => $post->post_excerpt,
            'title' => $post->post_title,
            'url' => get_permalink($post->ID),
            'start' => $start,
        );

        // Send a POST request to your Python web handler
        $response = wp_safe_remote_post($webhook_base, array(
            'body' => json_encode($data),
            'headers' => array('Content-Type' => 'application/json'),
        ));

        // Check for errors in the response, if needed
        if (is_wp_error($response)) {
            // Handle errors here
            error_log('Webhook error: ' . $response->get_error_message());
        }
    }
}

add_action('transition_post_status', 'trigger_webhook_on_new_event', 10, 3);

webhandler.py:

from flask import Flask, request

app = Flask(__name__)

# Import the google_maps class here
from google_maps import google_maps

# Create an instance of the google_maps class
google_maps_instance = google_maps()

# Create variables to track the last post ID for modify and add webhooks
# WordPress call save post twice. I don't know why.
last_modify_post_id = None
last_add_post_id = None

@app.route('/webhook/modify', methods=['POST'])
def receive_webhook_modify():
    global last_modify_post_id

    # Get the JSON data from the incoming webhook request
    data = request.json

    # Check if the received post ID is the same as the last one for modify
    if data['id'] == last_modify_post_id:
        print("Webhook already processed for modify with post ID:", last_modify_post_id)
        return "Webhook already processed"

    # If it's a new post ID, process the webhook for modify
    last_modify_post_id = data['id']

    print("Received Webhook on modify:")
    print(data)

    # You can add your custom logic here to process the webhook data for modify

    return "Webhook received successfully"


@app.route('/webhook/add', methods=['POST'])
def receive_webhook_add():
    global last_add_post_id

    # Get the JSON data from the incoming webhook request
    data = request.json

    # Check if the received post ID is the same as the last one for add
    if data['id'] == last_add_post_id:
        print("Webhook already processed for add with post ID:", last_add_post_id)
        return "Webhook already processed"

    # If it's a new post ID, process the webhook for add
    last_add_post_id = data['id']

    print("Received Webhook on add:")
    print(data)

    # You can add your custom logic here to process the webhook data for add
    google_maps_instance.create_event(data)

    return "Webhook received successfully"

if __name__ == '__main__':
    app.run(port=5000)
Share Improve this question asked Oct 10, 2023 at 20:26 BjörnBjörn 11 bronze badge
Add a comment  | 

1 Answer 1

Reset to default 0

I found a workaround, in this forum - This did the trick:

[https://wordpress.stackexchange.com/questions/225760/update-is-always-true-in-save-post][1]

It's still hit multiple times, but it's working.

本文标签: hooksWebhooksDiffer between newexisting updates