updated plugin ActivityPub version 5.8.0

This commit is contained in:
2025-04-29 21:19:06 +00:00
committed by Gitium
parent 19dfd317cc
commit fdfbf76539
166 changed files with 14119 additions and 7163 deletions

View File

@ -10,10 +10,11 @@ namespace Activitypub\Integration;
use DateTime;
use Activitypub\Webfinger as Webfinger_Util;
use Activitypub\Http;
use Activitypub\Collection\Users;
use Activitypub\Mention;
use Activitypub\Collection\Actors;
use Activitypub\Collection\Followers;
use Activitypub\Collection\Extra_Fields;
use Enable_Mastodon_Apps\Mastodon_API;
use Activitypub\Transformer\Factory;
use Enable_Mastodon_Apps\Entity\Account;
use Enable_Mastodon_Apps\Entity\Status;
use Enable_Mastodon_Apps\Entity\Media_Attachment;
@ -36,12 +37,14 @@ class Enable_Mastodon_Apps {
\add_filter( 'mastodon_api_account_followers', array( self::class, 'api_account_followers' ), 10, 2 );
\add_filter( 'mastodon_api_account', array( self::class, 'api_account_external' ), 15, 2 );
\add_filter( 'mastodon_api_account', array( self::class, 'api_account_internal' ), 9, 2 );
\add_filter( 'mastodon_api_status', array( self::class, 'api_status' ), 9, 2 );
\add_filter( 'mastodon_api_search', array( self::class, 'api_search' ), 40, 2 );
\add_filter( 'mastodon_api_search', array( self::class, 'api_search_by_url' ), 40, 2 );
\add_filter( 'mastodon_api_get_posts_query_args', array( self::class, 'api_get_posts_query_args' ) );
\add_filter( 'mastodon_api_statuses', array( self::class, 'api_statuses_external' ), 10, 2 );
\add_filter( 'mastodon_api_status_context', array( self::class, 'api_get_replies' ), 10, 23 );
\add_action( 'mastodon_api_update_credentials', array( self::class, 'api_update_credentials' ), 10, 2 );
\add_filter( 'mastodon_api_status_context', array( self::class, 'api_get_replies' ), 10, 3 );
\add_filter( 'mastodon_api_update_credentials', array( self::class, 'api_update_credentials' ), 10, 2 );
\add_filter( 'mastodon_api_submit_status_text', array( Mention::class, 'the_content' ) );
}
/**
@ -58,7 +61,7 @@ class Enable_Mastodon_Apps {
// Check if the blog user is permissible for this user.
user_can( $user_id, 'activitypub' )
) {
return Users::BLOG_USER_ID;
return Actors::BLOG_USER_ID;
}
return $user_id;
@ -77,7 +80,7 @@ class Enable_Mastodon_Apps {
}
$user_id = self::maybe_map_user_to_blog( $user_id );
$user = Users::get_by_id( $user_id );
$user = Actors::get_by_id( $user_id );
if ( ! $user || is_wp_error( $user ) ) {
return $data;
}
@ -139,7 +142,7 @@ class Enable_Mastodon_Apps {
// The Mastodon API submits a simple hash for every field.
// We can reasonably assume a similar order for our operations below.
$ids = wp_list_pluck( Extra_Fields::get_actor_fields( $user_id ), 'ID' );
$is_blog = Users::BLOG_USER_ID === $user_id;
$is_blog = Actors::BLOG_USER_ID === $user_id;
$post_type = $is_blog ? Extra_Fields::BLOG_POST_TYPE : Extra_Fields::USER_POST_TYPE;
foreach ( $fields as $i => $field ) {
@ -190,7 +193,7 @@ class Enable_Mastodon_Apps {
if ( $acct && ! is_wp_error( $acct ) ) {
$acct = \str_replace( 'acct:', '', $acct );
} else {
$acct = $item->get_url();
$acct = $item->get_id();
}
$account = new Account();
@ -239,7 +242,7 @@ class Enable_Mastodon_Apps {
return $user_data;
}
$user = Users::get_by_various( $user_id );
$user = Actors::get_by_various( $user_id );
if ( $user && ! is_wp_error( $user ) ) {
return $user_data;
@ -269,7 +272,7 @@ class Enable_Mastodon_Apps {
*/
public static function api_account_internal( $user_data, $user_id ) {
$user_id_to_use = self::maybe_map_user_to_blog( $user_id );
$user = Users::get_by_id( $user_id_to_use );
$user = Actors::get_by_id( $user_id_to_use );
if ( ! $user || is_wp_error( $user ) ) {
return $user_data;
@ -324,6 +327,44 @@ class Enable_Mastodon_Apps {
return $account;
}
/**
* Use our representation of posts to power each status item.
* Includes proper referncing of 3rd party comments that arrived via federation.
*
* @param null|Status $status The status, typically null to allow later filters their shot.
* @param int $post_id The post ID.
* @return Status|null The status.
*/
public static function api_status( $status, $post_id ) {
$post = \get_post( $post_id );
if ( ! $post ) {
return $status;
}
return self::api_post_status( $post_id );
}
/**
* Transforms a WordPress post into a Mastodon-compatible status object.
*
* Takes a post ID, transforms it into an ActivityPub object, and converts
* it to a Mastodon API status format including the author's account info.
*
* @param int $post_id The WordPress post ID to transform.
* @return Status|null The Mastodon API status object, or null if the post is not found
*/
private static function api_post_status( $post_id ) {
$post = Factory::get_transformer( get_post( $post_id ) );
if ( is_wp_error( $post ) ) {
return null;
}
$data = $post->to_object()->to_array();
$account = self::api_account_internal( null, get_post_field( 'post_author', $post_id ) );
return self::activity_to_status( $data, $account, $post_id );
}
/**
* Get account for actor.
*
@ -332,7 +373,7 @@ class Enable_Mastodon_Apps {
* @return Account|null The account.
*/
private static function get_account_for_actor( $uri ) {
if ( ! is_string( $uri ) ) {
if ( ! is_string( $uri ) || empty( $uri ) ) {
return null;
}
$data = get_remote_metadata_by_actor( $uri );
@ -343,6 +384,10 @@ class Enable_Mastodon_Apps {
$account = new Account();
$acct = Webfinger_Util::uri_to_acct( $uri );
if ( ! $acct || is_wp_error( $acct ) ) {
return null;
}
if ( str_starts_with( $acct, 'acct:' ) ) {
$acct = substr( $acct, 5 );
}
@ -489,22 +534,23 @@ class Enable_Mastodon_Apps {
*
* @param array $item The activity.
* @param Account $account The account.
* @param int $post_id The post ID. Optional, but will be preferred in the Status.
*
* @return Status|null The status.
*/
private static function activity_to_status( $item, $account ) {
private static function activity_to_status( $item, $account, $post_id = null ) {
if ( isset( $item['object'] ) ) {
$object = $item['object'];
} else {
$object = $item;
}
if ( ! isset( $object['type'] ) || 'Note' !== $object['type'] ) {
if ( ! isset( $object['type'] ) || 'Note' !== $object['type'] || ! $account ) {
return null;
}
$status = new Status();
$status->id = $object['id'];
$status->id = $post_id ?? $object['id'];
$status->created_at = new DateTime( $object['published'] );
$status->content = $object['content'];
$status->account = $account;
@ -624,7 +670,7 @@ class Enable_Mastodon_Apps {
$posts['orderedItems']
);
$activitypub_statuses = array_merge( $activitypub_statuses, array_filter( $new_statuses ) );
$url = $posts['next'];
$url = $posts['next'] ?? null;
if ( count( $activitypub_statuses ) >= $limit ) {
break;
@ -649,20 +695,37 @@ class Enable_Mastodon_Apps {
return $context;
}
$replies_url = $meta['replies']['first']['next'];
$replies = Http::get_remote_object( $replies_url, true );
if ( is_wp_error( $replies ) || ! isset( $replies['items'] ) ) {
if ( ! empty( $meta['replies']['first']['items'] ) ) {
$replies = $meta['replies']['first'];
} elseif ( isset( $meta['replies']['first']['next'] ) ) {
$replies_url = $meta['replies']['first']['next'];
$replies = Http::get_remote_object( $replies_url, true );
if ( is_wp_error( $replies ) || ! isset( $replies['items'] ) ) {
return $context;
}
} else {
return $context;
}
foreach ( $replies['items'] as $url ) {
$response = Http::get( $url, true );
if ( is_wp_error( $response ) || wp_remote_retrieve_response_code( $response ) !== 200 ) {
continue;
}
$status = json_decode( wp_remote_retrieve_body( $response ), true );
if ( ! $status || is_wp_error( $status ) ) {
continue;
foreach ( $replies['items'] as $reply ) {
if ( isset( $reply['id'] ) && is_string( $reply['id'] ) && isset( $reply['content'] ) && is_string( $reply['content'] ) ) {
$status = $reply;
} else {
if ( is_string( $reply ) ) {
$url = $reply;
} elseif ( isset( $reply['url'] ) && is_string( $reply['url'] ) ) {
$url = $reply['url'];
} else {
continue;
}
$response = Http::get( $url, true );
if ( is_wp_error( $response ) || wp_remote_retrieve_response_code( $response ) !== 200 ) {
continue;
}
$status = json_decode( wp_remote_retrieve_body( $response ), true );
if ( ! $status || is_wp_error( $status ) ) {
continue;
}
}
$account = self::get_account_for_actor( $status['attributedTo'] );