Skip to content

Instantly share code, notes, and snippets.

@janboddez
Last active April 19, 2024 12:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save janboddez/5b27fd7dbf80f8dc9a94282fe089ac38 to your computer and use it in GitHub Desktop.
Save janboddez/5b27fd7dbf80f8dc9a94282fe089ac38 to your computer and use it in GitHub Desktop.
<?php
add_action( 'transition_post_status', function ( $new_status, $old_status, $post ) { // phpcs:ignore PEAR.Functions.FunctionCallSignature.ContentAfterOpenBracket,PEAR.Functions.FunctionCallSignature.MultipleArguments
if ( 'publish' !== $new_status || 'publish' !== $old_status ) {
// Run only on when the post is public, or was public.
return;
}
// $hash = get_transient( "activitypub:sent:post:{$post->ID}" );
$hash = get_post_meta( $post->ID, '_activitypub_sent_hash', true );
if ( '' === $hash ) {
// Looks like this post's new. Do not interrupt the normal flow of things.
error_log( "[AP/Limit Updates] The post with ID {$post->ID} hasn't yet been sent out." );
return;
}
// "Clone" `$post`, keeping only the following properties.
$obj = array_filter(
(array) $post,
function ( $key ) {
return in_array( $key, array( 'post_name', 'post_title', 'post_content', 'post_type', 'post_author' ), true );
},
ARRAY_FILTER_USE_KEY
);
$cats = wp_get_post_categories( $post->ID, array( 'fields' => 'names' ) );
$tags = wp_get_post_tags( $post->ID, array( 'fields' => 'names' ) );
// Because I use Gutenberg in combination with "old style" meta boxes (added
// by different plugins), there'll be two requests to WP's back end, and two
// calls to `transition_post_status`. The first will still show the old tags,
// the second one will show the newer tags.
// error_log( serialize( $cats ) . serialize( $tags ) );
// Either way, this works. Mostly.
if ( md5( serialize( $obj ) . serialize( $cats ) . serialize( $tags ) ) === $hash && class_exists( '\\Activitypub\\Scheduler' ) && method_exists( \Activitypub\Scheduler::class, 'schedule_post_activity' ) ) {
// We're updating a post, but it hasn't actually changed. Unhook scheduler.
error_log( "[AP/Limit Updates] Post hasn't actually changed. Unscheduling federation for the post with ID {$post->ID}." );
remove_action( 'transition_post_status', array( \Activitypub\Scheduler::class, 'schedule_post_activity' ), 33 );
}
}, 30, 3 ); // phpcs:ignore PEAR.Functions.FunctionCallSignature.CloseBracketLine,PEAR.Functions.FunctionCallSignature.MultipleArguments
add_action( 'activitypub_safe_remote_post_response', function ( $response, $url, $body ) { // phpcs:ignore PEAR.Functions.FunctionCallSignature.ContentAfterOpenBracket,PEAR.Functions.FunctionCallSignature.MultipleArguments
if ( is_wp_error( $response ) ) {
// Reschedule?
return;
}
// It'd be better to do this once per scheduled event rather than after every POST! But I'm not sure there's a hook for that.
$array = json_decode( $body, true );
if ( empty( $array['object']['id'] ) || ! filter_var( $array['object']['id'], FILTER_VALIDATE_URL ) ) {
return;
}
$fragment = wp_parse_url( $array['object']['id'], PHP_URL_FRAGMENT );
if ( ! empty( $fragment ) && preg_match( '~^comment-\d+$~', $fragment ) ) {
// Comment. We don't support these, yet.
return;
}
$post = get_post( url_to_postid( $array['object']['id'] ) );
if ( empty( $post->ID ) ) {
return;
}
// "Clone" `$post`, keeping only the following properties.
$obj = array_filter(
(array) $post,
function ( $key ) {
return in_array( $key, array( 'post_name', 'post_title', 'post_content', 'post_type', 'post_author' ), true );
},
ARRAY_FILTER_USE_KEY
);
$cats = wp_get_post_categories( $post->ID, array( 'fields' => 'names' ) );
$tags = wp_get_post_tags( $post->ID, array( 'fields' => 'names' ) );
// Generate a hash of the "post array," categories, and tags.
$hash = md5( serialize( $obj ) . serialize( $cats ) . serialize( $tags ) );
// set_transient( "activitypub:sent:post:{$post->ID}", $hash, MONTH_IN_SECONDS );
error_log( "[AP/Limit Updates] Saving the hash for the post with ID {$post->ID}." );
update_post_meta( $post->ID, '_activitypub_sent_hash', $hash );
}, 10, 3 ); // phpcs:ignore PEAR.Functions.FunctionCallSignature.CloseBracketLine,PEAR.Functions.FunctionCallSignature.MultipleArguments
@janboddez
Copy link
Author

janboddez commented Apr 19, 2024

To do: check out activitypub_send_activity_to_followers and the "state" instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment