updated plugin ActivityPub version 8.3.0
This commit is contained in:
@ -8,12 +8,12 @@
|
||||
namespace Activitypub;
|
||||
|
||||
/**
|
||||
* Class to handle embedding ActivityPub content
|
||||
* Class to handle embedding ActivityPub content.
|
||||
*/
|
||||
class Embed {
|
||||
|
||||
/**
|
||||
* Initialize the embed handler
|
||||
* Initialize the embed handler.
|
||||
*/
|
||||
public static function init() {
|
||||
\add_filter( 'pre_oembed_result', array( self::class, 'maybe_use_activitypub_embed' ), 10, 3 );
|
||||
@ -32,7 +32,8 @@ class Embed {
|
||||
public static function get_html( $url, $inline_css = true ) {
|
||||
// Try to get ActivityPub representation.
|
||||
$object = Http::get_remote_object( $url );
|
||||
if ( is_wp_error( $object ) ) {
|
||||
|
||||
if ( \is_wp_error( $object ) || ! is_activity_object( $object ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -55,9 +56,11 @@ class Embed {
|
||||
// If we don't have an avatar URL, but we have an author URL, try to fetch it.
|
||||
if ( ! $avatar_url && $author_url ) {
|
||||
$author = Http::get_remote_object( $author_url );
|
||||
if ( ! is_wp_error( $author ) ) {
|
||||
if ( is_wp_error( $author ) ) {
|
||||
$author = array();
|
||||
} else {
|
||||
$avatar_url = $author['icon']['url'] ?? '';
|
||||
$author_name = $author['name'] ?? $author_name;
|
||||
$author_name = empty( $author['name'] ) ? $author_name : $author['name'];
|
||||
}
|
||||
}
|
||||
|
||||
@ -65,7 +68,7 @@ class Embed {
|
||||
if ( empty( $author['webfinger'] ) ) {
|
||||
if ( ! empty( $author['preferredUsername'] ) && ! empty( $author['url'] ) ) {
|
||||
// Construct webfinger-style identifier from username and domain.
|
||||
$domain = wp_parse_url( $author['url'], PHP_URL_HOST );
|
||||
$domain = \wp_parse_url( object_to_uri( $author['url'] ), PHP_URL_HOST );
|
||||
$author['webfinger'] = '@' . $author['preferredUsername'] . '@' . $domain;
|
||||
} else {
|
||||
// Fallback to URL.
|
||||
@ -79,33 +82,53 @@ class Embed {
|
||||
$boosts = isset( $activity_object['shares']['totalItems'] ) ? (int) $activity_object['shares']['totalItems'] : null;
|
||||
$favorites = isset( $activity_object['likes']['totalItems'] ) ? (int) $activity_object['likes']['totalItems'] : null;
|
||||
|
||||
$image = '';
|
||||
$audio = null;
|
||||
$images = array();
|
||||
$video = null;
|
||||
if ( isset( $activity_object['image']['url'] ) ) {
|
||||
$image = $activity_object['image']['url'];
|
||||
$images = array(
|
||||
array(
|
||||
'type' => 'Image',
|
||||
'url' => $activity_object['image']['url'],
|
||||
'name' => $activity_object['image']['name'] ?? '',
|
||||
),
|
||||
);
|
||||
} elseif ( isset( $activity_object['attachment'] ) ) {
|
||||
foreach ( $activity_object['attachment'] as $attachment ) {
|
||||
if ( isset( $attachment['type'] ) && in_array( $attachment['type'], array( 'Image', 'Document' ), true ) ) {
|
||||
$image = $attachment['url'];
|
||||
break;
|
||||
$type = isset( $attachment['mediaType'] ) ? strtok( $attachment['mediaType'], '/' ) : strtolower( $attachment['type'] );
|
||||
|
||||
switch ( $type ) {
|
||||
case 'image':
|
||||
$images[] = $attachment;
|
||||
break;
|
||||
case 'video':
|
||||
$video = $attachment;
|
||||
break 2;
|
||||
case 'audio':
|
||||
$audio = $attachment;
|
||||
break 2;
|
||||
}
|
||||
}
|
||||
$images = \array_slice( $images, 0, 4 );
|
||||
}
|
||||
|
||||
ob_start();
|
||||
load_template(
|
||||
ACTIVITYPUB_PLUGIN_DIR . 'templates/reply-embed.php',
|
||||
ACTIVITYPUB_PLUGIN_DIR . 'templates/embed.php',
|
||||
false,
|
||||
array(
|
||||
'audio' => $audio,
|
||||
'author_name' => $author_name,
|
||||
'author_url' => $author_url,
|
||||
'avatar_url' => $avatar_url,
|
||||
'boosts' => $boosts,
|
||||
'content' => $content,
|
||||
'favorites' => $favorites,
|
||||
'images' => $images,
|
||||
'published' => $published,
|
||||
'title' => $title,
|
||||
'content' => $content,
|
||||
'image' => $image,
|
||||
'boosts' => $boosts,
|
||||
'favorites' => $favorites,
|
||||
'url' => $activity_object['id'],
|
||||
'video' => $video,
|
||||
'webfinger' => $author['webfinger'],
|
||||
)
|
||||
);
|
||||
@ -130,7 +153,7 @@ class Embed {
|
||||
*/
|
||||
public static function has_real_oembed( $url, $args = array() ) {
|
||||
// Temporarily remove our filter to avoid infinite loops.
|
||||
\remove_filter( 'pre_oembed_result', array( self::class, 'maybe_use_activitypub_embed' ), 10, 3 );
|
||||
\remove_filter( 'pre_oembed_result', array( self::class, 'maybe_use_activitypub_embed' ) );
|
||||
|
||||
// Try to get a "real" oEmbed result. If found, it'll be cached to avoid unnecessary HTTP requests in `wp_oembed_get`.
|
||||
$oembed_result = \wp_oembed_get( $url, $args );
|
||||
@ -201,7 +224,7 @@ class Embed {
|
||||
}
|
||||
|
||||
// Try to get ActivityPub representation.
|
||||
$activitypub_html = get_embed_html( $url );
|
||||
$activitypub_html = self::get_html( $url );
|
||||
if ( ! $activitypub_html ) {
|
||||
return $html;
|
||||
}
|
||||
@ -234,14 +257,18 @@ class Embed {
|
||||
* @return \WP_REST_Response|\WP_Error The response to send to the client.
|
||||
*/
|
||||
public static function oembed_fediverse_fallback( $response, $handler, $request ) {
|
||||
if ( is_wp_error( $response ) && 'oembed_invalid_url' === $response->get_error_code() ) {
|
||||
if ( '/oembed/1.0/proxy' !== $request->get_route() ) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
if ( ( is_wp_error( $response ) && 'oembed_invalid_url' === $response->get_error_code() ) || empty( $response->html ) ) {
|
||||
$url = $request->get_param( 'url' );
|
||||
$html = get_embed_html( $url );
|
||||
$html = self::get_html( $url );
|
||||
|
||||
if ( $html ) {
|
||||
$args = $request->get_params();
|
||||
$data = (object) array(
|
||||
'provider_name' => 'Embed Handler',
|
||||
'provider_name' => 'ActivityPub oEmbed',
|
||||
'html' => $html,
|
||||
'scripts' => array(),
|
||||
);
|
||||
@ -256,6 +283,21 @@ class Embed {
|
||||
|
||||
$response = new \WP_REST_Response( $data );
|
||||
}
|
||||
} elseif ( ! empty( $request->get_param( 'activitypub' ) ) ) {
|
||||
/*
|
||||
* If the 'activitypub' parameter is present, perform an additional validation step:
|
||||
* Ensure the provided URL resolves to a valid ActivityPub object.
|
||||
*
|
||||
* This differs from the standard oEmbed flow, which does not explicitly validate
|
||||
* the URL as an ActivityPub object unless the initial oEmbed lookup fails.
|
||||
* This block is triggered for requests from the Federated Reply block, where we
|
||||
* want to inform users whether post authors will be notified of the reply.
|
||||
*/
|
||||
$object = Http::get_remote_object( $request->get_param( 'url' ) );
|
||||
|
||||
if ( \is_wp_error( $object ) || ! is_activity_object( $object ) ) {
|
||||
$response = new \WP_Error( 'oembed_invalid_url', \get_status_header_desc( 404 ), array( 'status' => 404 ) );
|
||||
}
|
||||
}
|
||||
|
||||
return $response;
|
||||
|
||||
Reference in New Issue
Block a user