Changeset 3467027
- Timestamp:
- 02/22/2026 05:48:35 PM (2 weeks ago)
- Location:
- fediboost
- Files:
-
- 8 edited
- 1 copied
-
tags/1.0.1 (copied) (copied from fediboost/trunk)
-
tags/1.0.1/fediboost.php (modified) (4 diffs)
-
tags/1.0.1/includes/class-boost.php (modified) (7 diffs)
-
tags/1.0.1/readme.txt (modified) (4 diffs)
-
tags/1.0.1/uninstall.php (modified) (1 diff)
-
trunk/fediboost.php (modified) (4 diffs)
-
trunk/includes/class-boost.php (modified) (7 diffs)
-
trunk/readme.txt (modified) (4 diffs)
-
trunk/uninstall.php (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
fediboost/tags/1.0.1/fediboost.php
r3460488 r3467027 4 4 * Plugin URI: https://github.com/kraftbj/fediboost 5 5 * Description: Automatically boost WordPress posts on connected Mastodon accounts when published via ActivityPub. 6 * Version: 1.0. 06 * Version: 1.0.1 7 7 * Requires at least: 6.9 8 8 * Requires PHP: 7.4 … … 51 51 52 52 // Define plugin constants. 53 define( 'FEDIBOOST_VERSION', '1.0. 0' );53 define( 'FEDIBOOST_VERSION', '1.0.1' ); 54 54 define( 'FEDIBOOST_PLUGIN_FILE', __FILE__ ); 55 55 define( 'FEDIBOOST_PLUGIN_DIR', plugin_dir_path( __FILE__ ) ); … … 73 73 * 74 74 * FediBoost\Boost::init_hooks(): 75 * wp_after_insert_post (priority 50) → on_post_publish() 76 * fediboost_boost_post (cron) → execute_boost() 75 * wp_after_insert_post (priority 50) → on_post_publish() 76 * activitypub_outbox_processing_complete → on_federation_complete() 77 * fediboost_boost_post (cron) → execute_boost() 77 78 * 78 79 * FediBoost\Admin::init_hooks(): … … 134 135 function fediboost_deactivate() { 135 136 // Clear all scheduled boost events. 136 wp_ clear_scheduled_hook( 'fediboost_boost_post' );137 wp_unschedule_hook( 'fediboost_boost_post' ); 137 138 138 139 // Remove the ActivityPub notice flag. -
fediboost/tags/1.0.1/includes/class-boost.php
r3460482 r3467027 35 35 36 36 /** 37 * Boost delay in seconds (30 seconds to allow ActivityPub federation).37 * Boost delay in seconds after ActivityPub federation completes. 38 38 * 39 39 * @since 1.0.0 … … 42 42 */ 43 43 const BOOST_DELAY = 30; 44 45 /** 46 * Fallback delay in seconds when the ActivityPub federation hook does not fire. 47 * 48 * @since 1.0.1 49 * 50 * @var int 51 */ 52 const FALLBACK_DELAY = 300; 44 53 45 54 /** … … 84 93 add_action( 'wp_after_insert_post', array( $this, 'on_post_publish' ), 50, 4 ); 85 94 95 /* 96 * Hook into ActivityPub federation completion to schedule boost after federation. 97 * Relies on the activitypub_outbox_processing_complete action, added in ActivityPub 5.4.0. 98 * If this hook is unavailable (older plugin version or plugin inactive), the fallback 99 * scheduled in on_post_publish() will handle the boost instead. 100 */ 101 add_action( 'activitypub_outbox_processing_complete', array( $this, 'on_federation_complete' ), 10, 4 ); 102 86 103 // Register cron hook handler. 87 104 add_action( self::CRON_HOOK, array( $this, 'execute_boost' ) ); … … 90 107 /** 91 108 * Handle post publish event. 109 * 110 * Marks the post as pending boost and schedules a fallback. The primary boost 111 * scheduling happens in on_federation_complete() after ActivityPub has finished 112 * federating the post. 92 113 * 93 114 * @since 1.0.0 … … 137 158 } 138 159 139 // Schedule the boost. 160 // Store a transient mapping the ActivityPub URL to this post ID so we can 161 // identify it when the activitypub_outbox_processing_complete hook fires. 162 $activitypub_url = $activitypub->get_activitypub_url( $post ); 163 164 if ( ! $activitypub_url ) { 165 $this->log_info( 'No ActivityPub URL available, skipping boost', array( 'post_id' => $post_id ) ); 166 return; 167 } 168 169 set_transient( 'fediboost_pending_' . md5( $activitypub_url ), $post_id, HOUR_IN_SECONDS ); 170 171 // Schedule a fallback boost in case the ActivityPub federation hook doesn't fire. 172 $this->schedule_fallback_boost( $post_id ); 173 } 174 175 /** 176 * Handle ActivityPub federation completion. 177 * 178 * Fires after the ActivityPub plugin has finished sending a post to all follower 179 * inboxes. Cancels the fallback boost and reschedules the boost relative to 180 * federation completion rather than post publish time. 181 * 182 * @since 1.0.1 183 * 184 * @param array $inboxes Target inbox URLs. 185 * @param string $json The ActivityPub Activity JSON. 186 * @param int $actor_id The actor user ID. 187 * @param int $outbox_item_id The outbox item post ID. 188 */ 189 public function on_federation_complete( $inboxes, $json, $actor_id, $outbox_item_id ) { 190 // Only process Create activities (new posts, not updates or deletes). 191 $type = get_post_meta( $outbox_item_id, '_activitypub_activity_type', true ); 192 193 if ( ! $type ) { 194 // Fall back to parsing the activity JSON if meta is unavailable. 195 $activity = json_decode( $json, true ); 196 197 if ( ! is_array( $activity ) ) { 198 return; 199 } 200 201 $type = isset( $activity['type'] ) ? $activity['type'] : ''; 202 } 203 204 if ( 'Create' !== $type ) { 205 return; 206 } 207 208 // Get the ActivityPub object URL from outbox item meta. 209 $object_id = get_post_meta( $outbox_item_id, '_activitypub_object_id', true ); 210 211 if ( empty( $object_id ) ) { 212 // Fall back to parsing the activity JSON. 213 if ( ! isset( $activity ) ) { 214 $activity = json_decode( $json, true ); 215 } 216 217 if ( ! is_array( $activity ) ) { 218 return; 219 } 220 221 $object = isset( $activity['object'] ) ? $activity['object'] : array(); 222 $object_id = isset( $object['id'] ) ? $object['id'] : ''; 223 } 224 225 if ( empty( $object_id ) ) { 226 return; 227 } 228 229 // Look up the pending boost transient to find the WordPress post ID. 230 $transient_key = 'fediboost_pending_' . md5( $object_id ); 231 $post_id = get_transient( $transient_key ); 232 233 if ( ! $post_id ) { 234 return; 235 } 236 237 $this->log_info( 238 'Federation complete, rescheduling boost', 239 array( 240 'post_id' => $post_id, 241 'outbox_item_id' => $outbox_item_id, 242 ) 243 ); 244 245 // Clean up the pending transient. 246 delete_transient( $transient_key ); 247 248 // Cancel the fallback boost. 249 $this->unschedule_boost( $post_id ); 250 251 // Schedule the boost for the configured delay after federation completes. 140 252 $this->schedule_boost( $post_id ); 141 253 } … … 185 297 186 298 /** 299 * Schedule a fallback boost with a longer delay. 300 * 301 * Used as a safety net in case the activitypub_outbox_processing_complete hook 302 * does not fire (e.g., older ActivityPub plugin version). If the federation hook 303 * fires first, it will cancel this fallback and reschedule with the normal delay. 304 * 305 * @since 1.0.1 306 * 307 * @param int $post_id The post ID to boost. 308 * @return bool True if scheduled, false on failure. 309 */ 310 public function schedule_fallback_boost( $post_id ) { 311 // Check if already scheduled (prevent duplicates). 312 if ( wp_next_scheduled( self::CRON_HOOK, array( $post_id ) ) ) { 313 $this->log_info( 'Fallback boost already scheduled', array( 'post_id' => $post_id ) ); 314 return false; 315 } 316 317 /** 318 * Filters the fallback delay in seconds before a boost is executed when the 319 * ActivityPub federation completion hook does not fire. 320 * 321 * @since 1.0.1 322 * 323 * @param int $delay Fallback delay in seconds. Default 300 (5 minutes). 324 */ 325 $delay = apply_filters( 'fediboost_fallback_delay', self::FALLBACK_DELAY ); 326 $scheduled_time = time() + $delay; 327 328 $result = wp_schedule_single_event( $scheduled_time, self::CRON_HOOK, array( $post_id ) ); 329 330 if ( false === $result ) { 331 $this->log_error( 'Failed to schedule fallback boost', array( 'post_id' => $post_id ) ); 332 return false; 333 } 334 335 $this->log_info( 336 'Fallback boost scheduled', 337 array( 338 'post_id' => $post_id, 339 'scheduled_time' => $scheduled_time, 340 'delay' => $delay, 341 ) 342 ); 343 344 return true; 345 } 346 347 /** 348 * Unschedule a pending boost for a post. 349 * 350 * @since 1.0.1 351 * 352 * @param int $post_id The post ID. 353 */ 354 private function unschedule_boost( $post_id ) { 355 $timestamp = wp_next_scheduled( self::CRON_HOOK, array( $post_id ) ); 356 357 if ( $timestamp ) { 358 wp_unschedule_event( $timestamp, self::CRON_HOOK, array( $post_id ) ); 359 $this->log_info( 'Cancelled previous boost schedule', array( 'post_id' => $post_id ) ); 360 } 361 } 362 363 /** 187 364 * Execute boost for a post on all connected accounts. 188 365 * … … 209 386 $activitypub = ActivityPub::get_instance(); 210 387 $activitypub_url = $activitypub->get_activitypub_url( $post ); 388 389 // Clean up any stale pending boost transient (fallback path). 390 if ( $activitypub_url ) { 391 delete_transient( 'fediboost_pending_' . md5( $activitypub_url ) ); 392 } 211 393 212 394 if ( false === $activitypub_url ) { -
fediboost/tags/1.0.1/readme.txt
r3460488 r3467027 5 5 Tested up to: 6.9 6 6 Requires PHP: 7.4 7 Stable tag: 1.0. 07 Stable tag: 1.0.1 8 8 License: GPLv2 or later 9 9 License URI: https://www.gnu.org/licenses/gpl-2.0.html … … 78 78 = fediboost_boost_delay = 79 79 80 Delay in seconds between post publication and the boost action. Default: 30.80 Delay in seconds after ActivityPub federation completes before the boost is executed. This delay is only used when the federation completion hook fires successfully. Default: 30. 81 81 82 82 **Parameters:** … … 87 87 88 88 `add_filter( 'fediboost_boost_delay', function( $delay ) { 89 // Wait 2 minutes before boosting.89 // Wait 2 minutes after federation before boosting. 90 90 return 120; 91 } );` 92 93 = fediboost_fallback_delay = 94 95 Delay in seconds before a boost is executed when the ActivityPub federation completion hook does not fire. This acts as a safety net for older versions of the ActivityPub plugin that do not support the `activitypub_outbox_processing_complete` hook. If the federation hook fires first, the fallback is cancelled and `fediboost_boost_delay` is used instead. Default: 300 (5 minutes). 96 97 **Parameters:** 98 99 * `$delay` (int) — The fallback delay in seconds. 100 101 **Example:** 102 103 `add_filter( 'fediboost_fallback_delay', function( $delay ) { 104 // Wait 10 minutes in the fallback path. 105 return 600; 91 106 } );` 92 107 … … 152 167 == Changelog == 153 168 169 = 1.0.1 = 170 * Delay boost scheduling until after ActivityPub federation completes 171 * Add fallback boost scheduling for older ActivityPub versions 172 154 173 = 1.0.0 = 155 174 * Initial release -
fediboost/tags/1.0.1/uninstall.php
r3460482 r3467027 85 85 ) 86 86 ); 87 88 // Delete transients with fediboost_pending_ prefix (pending boost markers). 89 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Required for transient cleanup by prefix 90 $wpdb->query( 91 $wpdb->prepare( 92 "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s OR option_name LIKE %s", 93 $wpdb->esc_like( '_transient_fediboost_pending_' ) . '%', 94 $wpdb->esc_like( '_transient_timeout_fediboost_pending_' ) . '%' 95 ) 96 ); -
fediboost/trunk/fediboost.php
r3460488 r3467027 4 4 * Plugin URI: https://github.com/kraftbj/fediboost 5 5 * Description: Automatically boost WordPress posts on connected Mastodon accounts when published via ActivityPub. 6 * Version: 1.0. 06 * Version: 1.0.1 7 7 * Requires at least: 6.9 8 8 * Requires PHP: 7.4 … … 51 51 52 52 // Define plugin constants. 53 define( 'FEDIBOOST_VERSION', '1.0. 0' );53 define( 'FEDIBOOST_VERSION', '1.0.1' ); 54 54 define( 'FEDIBOOST_PLUGIN_FILE', __FILE__ ); 55 55 define( 'FEDIBOOST_PLUGIN_DIR', plugin_dir_path( __FILE__ ) ); … … 73 73 * 74 74 * FediBoost\Boost::init_hooks(): 75 * wp_after_insert_post (priority 50) → on_post_publish() 76 * fediboost_boost_post (cron) → execute_boost() 75 * wp_after_insert_post (priority 50) → on_post_publish() 76 * activitypub_outbox_processing_complete → on_federation_complete() 77 * fediboost_boost_post (cron) → execute_boost() 77 78 * 78 79 * FediBoost\Admin::init_hooks(): … … 134 135 function fediboost_deactivate() { 135 136 // Clear all scheduled boost events. 136 wp_ clear_scheduled_hook( 'fediboost_boost_post' );137 wp_unschedule_hook( 'fediboost_boost_post' ); 137 138 138 139 // Remove the ActivityPub notice flag. -
fediboost/trunk/includes/class-boost.php
r3460482 r3467027 35 35 36 36 /** 37 * Boost delay in seconds (30 seconds to allow ActivityPub federation).37 * Boost delay in seconds after ActivityPub federation completes. 38 38 * 39 39 * @since 1.0.0 … … 42 42 */ 43 43 const BOOST_DELAY = 30; 44 45 /** 46 * Fallback delay in seconds when the ActivityPub federation hook does not fire. 47 * 48 * @since 1.0.1 49 * 50 * @var int 51 */ 52 const FALLBACK_DELAY = 300; 44 53 45 54 /** … … 84 93 add_action( 'wp_after_insert_post', array( $this, 'on_post_publish' ), 50, 4 ); 85 94 95 /* 96 * Hook into ActivityPub federation completion to schedule boost after federation. 97 * Relies on the activitypub_outbox_processing_complete action, added in ActivityPub 5.4.0. 98 * If this hook is unavailable (older plugin version or plugin inactive), the fallback 99 * scheduled in on_post_publish() will handle the boost instead. 100 */ 101 add_action( 'activitypub_outbox_processing_complete', array( $this, 'on_federation_complete' ), 10, 4 ); 102 86 103 // Register cron hook handler. 87 104 add_action( self::CRON_HOOK, array( $this, 'execute_boost' ) ); … … 90 107 /** 91 108 * Handle post publish event. 109 * 110 * Marks the post as pending boost and schedules a fallback. The primary boost 111 * scheduling happens in on_federation_complete() after ActivityPub has finished 112 * federating the post. 92 113 * 93 114 * @since 1.0.0 … … 137 158 } 138 159 139 // Schedule the boost. 160 // Store a transient mapping the ActivityPub URL to this post ID so we can 161 // identify it when the activitypub_outbox_processing_complete hook fires. 162 $activitypub_url = $activitypub->get_activitypub_url( $post ); 163 164 if ( ! $activitypub_url ) { 165 $this->log_info( 'No ActivityPub URL available, skipping boost', array( 'post_id' => $post_id ) ); 166 return; 167 } 168 169 set_transient( 'fediboost_pending_' . md5( $activitypub_url ), $post_id, HOUR_IN_SECONDS ); 170 171 // Schedule a fallback boost in case the ActivityPub federation hook doesn't fire. 172 $this->schedule_fallback_boost( $post_id ); 173 } 174 175 /** 176 * Handle ActivityPub federation completion. 177 * 178 * Fires after the ActivityPub plugin has finished sending a post to all follower 179 * inboxes. Cancels the fallback boost and reschedules the boost relative to 180 * federation completion rather than post publish time. 181 * 182 * @since 1.0.1 183 * 184 * @param array $inboxes Target inbox URLs. 185 * @param string $json The ActivityPub Activity JSON. 186 * @param int $actor_id The actor user ID. 187 * @param int $outbox_item_id The outbox item post ID. 188 */ 189 public function on_federation_complete( $inboxes, $json, $actor_id, $outbox_item_id ) { 190 // Only process Create activities (new posts, not updates or deletes). 191 $type = get_post_meta( $outbox_item_id, '_activitypub_activity_type', true ); 192 193 if ( ! $type ) { 194 // Fall back to parsing the activity JSON if meta is unavailable. 195 $activity = json_decode( $json, true ); 196 197 if ( ! is_array( $activity ) ) { 198 return; 199 } 200 201 $type = isset( $activity['type'] ) ? $activity['type'] : ''; 202 } 203 204 if ( 'Create' !== $type ) { 205 return; 206 } 207 208 // Get the ActivityPub object URL from outbox item meta. 209 $object_id = get_post_meta( $outbox_item_id, '_activitypub_object_id', true ); 210 211 if ( empty( $object_id ) ) { 212 // Fall back to parsing the activity JSON. 213 if ( ! isset( $activity ) ) { 214 $activity = json_decode( $json, true ); 215 } 216 217 if ( ! is_array( $activity ) ) { 218 return; 219 } 220 221 $object = isset( $activity['object'] ) ? $activity['object'] : array(); 222 $object_id = isset( $object['id'] ) ? $object['id'] : ''; 223 } 224 225 if ( empty( $object_id ) ) { 226 return; 227 } 228 229 // Look up the pending boost transient to find the WordPress post ID. 230 $transient_key = 'fediboost_pending_' . md5( $object_id ); 231 $post_id = get_transient( $transient_key ); 232 233 if ( ! $post_id ) { 234 return; 235 } 236 237 $this->log_info( 238 'Federation complete, rescheduling boost', 239 array( 240 'post_id' => $post_id, 241 'outbox_item_id' => $outbox_item_id, 242 ) 243 ); 244 245 // Clean up the pending transient. 246 delete_transient( $transient_key ); 247 248 // Cancel the fallback boost. 249 $this->unschedule_boost( $post_id ); 250 251 // Schedule the boost for the configured delay after federation completes. 140 252 $this->schedule_boost( $post_id ); 141 253 } … … 185 297 186 298 /** 299 * Schedule a fallback boost with a longer delay. 300 * 301 * Used as a safety net in case the activitypub_outbox_processing_complete hook 302 * does not fire (e.g., older ActivityPub plugin version). If the federation hook 303 * fires first, it will cancel this fallback and reschedule with the normal delay. 304 * 305 * @since 1.0.1 306 * 307 * @param int $post_id The post ID to boost. 308 * @return bool True if scheduled, false on failure. 309 */ 310 public function schedule_fallback_boost( $post_id ) { 311 // Check if already scheduled (prevent duplicates). 312 if ( wp_next_scheduled( self::CRON_HOOK, array( $post_id ) ) ) { 313 $this->log_info( 'Fallback boost already scheduled', array( 'post_id' => $post_id ) ); 314 return false; 315 } 316 317 /** 318 * Filters the fallback delay in seconds before a boost is executed when the 319 * ActivityPub federation completion hook does not fire. 320 * 321 * @since 1.0.1 322 * 323 * @param int $delay Fallback delay in seconds. Default 300 (5 minutes). 324 */ 325 $delay = apply_filters( 'fediboost_fallback_delay', self::FALLBACK_DELAY ); 326 $scheduled_time = time() + $delay; 327 328 $result = wp_schedule_single_event( $scheduled_time, self::CRON_HOOK, array( $post_id ) ); 329 330 if ( false === $result ) { 331 $this->log_error( 'Failed to schedule fallback boost', array( 'post_id' => $post_id ) ); 332 return false; 333 } 334 335 $this->log_info( 336 'Fallback boost scheduled', 337 array( 338 'post_id' => $post_id, 339 'scheduled_time' => $scheduled_time, 340 'delay' => $delay, 341 ) 342 ); 343 344 return true; 345 } 346 347 /** 348 * Unschedule a pending boost for a post. 349 * 350 * @since 1.0.1 351 * 352 * @param int $post_id The post ID. 353 */ 354 private function unschedule_boost( $post_id ) { 355 $timestamp = wp_next_scheduled( self::CRON_HOOK, array( $post_id ) ); 356 357 if ( $timestamp ) { 358 wp_unschedule_event( $timestamp, self::CRON_HOOK, array( $post_id ) ); 359 $this->log_info( 'Cancelled previous boost schedule', array( 'post_id' => $post_id ) ); 360 } 361 } 362 363 /** 187 364 * Execute boost for a post on all connected accounts. 188 365 * … … 209 386 $activitypub = ActivityPub::get_instance(); 210 387 $activitypub_url = $activitypub->get_activitypub_url( $post ); 388 389 // Clean up any stale pending boost transient (fallback path). 390 if ( $activitypub_url ) { 391 delete_transient( 'fediboost_pending_' . md5( $activitypub_url ) ); 392 } 211 393 212 394 if ( false === $activitypub_url ) { -
fediboost/trunk/readme.txt
r3460488 r3467027 5 5 Tested up to: 6.9 6 6 Requires PHP: 7.4 7 Stable tag: 1.0. 07 Stable tag: 1.0.1 8 8 License: GPLv2 or later 9 9 License URI: https://www.gnu.org/licenses/gpl-2.0.html … … 78 78 = fediboost_boost_delay = 79 79 80 Delay in seconds between post publication and the boost action. Default: 30.80 Delay in seconds after ActivityPub federation completes before the boost is executed. This delay is only used when the federation completion hook fires successfully. Default: 30. 81 81 82 82 **Parameters:** … … 87 87 88 88 `add_filter( 'fediboost_boost_delay', function( $delay ) { 89 // Wait 2 minutes before boosting.89 // Wait 2 minutes after federation before boosting. 90 90 return 120; 91 } );` 92 93 = fediboost_fallback_delay = 94 95 Delay in seconds before a boost is executed when the ActivityPub federation completion hook does not fire. This acts as a safety net for older versions of the ActivityPub plugin that do not support the `activitypub_outbox_processing_complete` hook. If the federation hook fires first, the fallback is cancelled and `fediboost_boost_delay` is used instead. Default: 300 (5 minutes). 96 97 **Parameters:** 98 99 * `$delay` (int) — The fallback delay in seconds. 100 101 **Example:** 102 103 `add_filter( 'fediboost_fallback_delay', function( $delay ) { 104 // Wait 10 minutes in the fallback path. 105 return 600; 91 106 } );` 92 107 … … 152 167 == Changelog == 153 168 169 = 1.0.1 = 170 * Delay boost scheduling until after ActivityPub federation completes 171 * Add fallback boost scheduling for older ActivityPub versions 172 154 173 = 1.0.0 = 155 174 * Initial release -
fediboost/trunk/uninstall.php
r3460482 r3467027 85 85 ) 86 86 ); 87 88 // Delete transients with fediboost_pending_ prefix (pending boost markers). 89 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Required for transient cleanup by prefix 90 $wpdb->query( 91 $wpdb->prepare( 92 "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s OR option_name LIKE %s", 93 $wpdb->esc_like( '_transient_fediboost_pending_' ) . '%', 94 $wpdb->esc_like( '_transient_timeout_fediboost_pending_' ) . '%' 95 ) 96 );
Note: See TracChangeset
for help on using the changeset viewer.