updated plugin ActivityPub
version 1.3.0
This commit is contained in:
@ -0,0 +1,61 @@
|
||||
<?php
|
||||
namespace Activitypub\Handler;
|
||||
|
||||
use WP_Error;
|
||||
use Activitypub\Collection\Interactions;
|
||||
|
||||
use function Activitypub\is_activity_public;
|
||||
use function Activitypub\object_id_to_comment;
|
||||
|
||||
/**
|
||||
* Handle Create requests
|
||||
*/
|
||||
class Create {
|
||||
/**
|
||||
* Initialize the class, registering WordPress hooks
|
||||
*/
|
||||
public static function init() {
|
||||
\add_action( 'activitypub_inbox_create', array( self::class, 'handle_create' ), 10, 3 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles "Create" requests
|
||||
*
|
||||
* @param array $array The activity-object
|
||||
* @param int $user_id The id of the local blog-user
|
||||
* @param Activitypub\Activity $object The activity object
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function handle_create( $array, $user_id, $object = null ) {
|
||||
if (
|
||||
! isset( $array['object'] ) ||
|
||||
! isset( $array['object']['id'] )
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
// check if Activity is public or not
|
||||
if ( ! is_activity_public( $array ) ) {
|
||||
// @todo maybe send email
|
||||
return;
|
||||
}
|
||||
|
||||
$check_dupe = object_id_to_comment( $array['object']['id'] );
|
||||
|
||||
// if comment exists, call update action
|
||||
if ( $check_dupe ) {
|
||||
\do_action( 'activitypub_inbox_update', $array, $user_id, $object );
|
||||
return;
|
||||
}
|
||||
|
||||
$state = Interactions::add_comment( $array );
|
||||
$reaction = null;
|
||||
|
||||
if ( $state && ! \is_wp_error( $reaction ) ) {
|
||||
$reaction = \get_comment( $state );
|
||||
}
|
||||
|
||||
\do_action( 'activitypub_handled_create', $array, $user_id, $state, $reaction );
|
||||
}
|
||||
}
|
165
wp-content/plugins/activitypub/includes/handler/class-delete.php
Normal file
165
wp-content/plugins/activitypub/includes/handler/class-delete.php
Normal file
@ -0,0 +1,165 @@
|
||||
<?php
|
||||
namespace Activitypub\Handler;
|
||||
|
||||
use WP_Error;
|
||||
use WP_REST_Request;
|
||||
use Activitypub\Http;
|
||||
use Activitypub\Collection\Followers;
|
||||
use Activitypub\Collection\Interactions;
|
||||
|
||||
/**
|
||||
* Handles Delete requests.
|
||||
*/
|
||||
class Delete {
|
||||
/**
|
||||
* Initialize the class, registering WordPress hooks
|
||||
*/
|
||||
public static function init() {
|
||||
\add_action( 'activitypub_inbox_delete', array( self::class, 'handle_delete' ), 10, 2 );
|
||||
// defer signature verification for `Delete` requests.
|
||||
\add_filter( 'activitypub_defer_signature_verification', array( self::class, 'defer_signature_verification' ), 10, 2 );
|
||||
// side effect
|
||||
\add_action( 'activitypub_delete_actor_interactions', array( self::class, 'delete_interactions' ), 10, 1 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles "Delete" requests.
|
||||
*
|
||||
* @param array $activity The delete activity.
|
||||
* @param int $user_id The ID of the user performing the delete activity.
|
||||
*/
|
||||
public static function handle_delete( $activity, $user_id ) {
|
||||
$object_type = isset( $activity['object']['type'] ) ? $activity['object']['type'] : '';
|
||||
|
||||
switch ( $object_type ) {
|
||||
// Actor Types
|
||||
// @see https://www.w3.org/TR/activitystreams-vocabulary/#actor-types
|
||||
case 'Person':
|
||||
case 'Group':
|
||||
case 'Organization':
|
||||
case 'Service':
|
||||
case 'Application':
|
||||
self::maybe_delete_follower( $user_id, $activity );
|
||||
break;
|
||||
// Object and Link Types
|
||||
// @see https://www.w3.org/TR/activitystreams-vocabulary/#object-types
|
||||
case 'Note':
|
||||
case 'Article':
|
||||
case 'Image':
|
||||
case 'Audio':
|
||||
case 'Video':
|
||||
case 'Event':
|
||||
case 'Document':
|
||||
self::maybe_delete_interaction( $activity );
|
||||
break;
|
||||
// Tombstone Type
|
||||
// @see: https://www.w3.org/TR/activitystreams-vocabulary/#dfn-tombstone
|
||||
case 'Tombstone':
|
||||
self::maybe_delete_interaction( $activity );
|
||||
break;
|
||||
// Minimal Activity
|
||||
// @see https://www.w3.org/TR/activitystreams-core/#example-1
|
||||
default:
|
||||
// ignore non Minimal Activities.
|
||||
if ( ! is_string( $activity['object'] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// check if Object is an Actor.
|
||||
if ( $activity['actor'] === $activity['object'] ) {
|
||||
self::maybe_delete_follower( $activity );
|
||||
self::maybe_delete_interactions( $activity );
|
||||
} else { // assume a interaction otherwise.
|
||||
self::maybe_delete_interaction( $activity );
|
||||
}
|
||||
// maybe handle Delete Activity for other Object Types.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a Follower if Actor-URL is a Tombstone.
|
||||
*
|
||||
* @param array $activity The delete activity.
|
||||
*/
|
||||
public static function maybe_delete_follower( $activity ) {
|
||||
$follower = Followers::get_follower_by_actor( $activity['actor'] );
|
||||
|
||||
// verify if Actor is deleted.
|
||||
if ( $follower && Http::is_tombstone( $activity['actor'] ) ) {
|
||||
$follower->delete();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete Reactions if Actor-URL is a Tombstone.
|
||||
*
|
||||
* @param array $activity The delete activity.
|
||||
*/
|
||||
public static function maybe_delete_interactions( $activity ) {
|
||||
// verify if Actor is deleted.
|
||||
if ( Http::is_tombstone( $activity['actor'] ) ) {
|
||||
\wp_schedule_single_event(
|
||||
\time(),
|
||||
'activitypub_delete_actor_interactions',
|
||||
array( $activity['actor'] )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete comments from an Actor.
|
||||
*
|
||||
* @param array $comments The comments to delete.
|
||||
*/
|
||||
public static function delete_interactions( $actor ) {
|
||||
$comments = Interactions::get_interactions_by_actor( $actor );
|
||||
|
||||
if ( is_array( $comments ) ) {
|
||||
foreach ( $comments as $comment ) {
|
||||
wp_delete_comment( $comment->comment_ID );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a Reaction if URL is a Tombstone.
|
||||
*
|
||||
* @param array $activity The delete activity.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function maybe_delete_interaction( $activity ) {
|
||||
if ( is_array( $activity['object'] ) ) {
|
||||
$id = $activity['object']['id'];
|
||||
} else {
|
||||
$id = $activity['object'];
|
||||
}
|
||||
|
||||
$comments = Interactions::get_interaction_by_id( $id );
|
||||
|
||||
if ( $comments && Http::is_tombstone( $id ) ) {
|
||||
foreach ( $comments as $comment ) {
|
||||
wp_delete_comment( $comment->comment_ID, true );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Defer signature verification for `Delete` requests.
|
||||
*
|
||||
* @param bool $defer Whether to defer signature verification.
|
||||
* @param WP_REST_Request $request The request object.
|
||||
*
|
||||
* @return bool Whether to defer signature verification.
|
||||
*/
|
||||
public static function defer_signature_verification( $defer, $request ) {
|
||||
$json = $request->get_json_params();
|
||||
|
||||
if ( isset( $json['type'] ) && 'Delete' === $json['type'] ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
<?php
|
||||
namespace Activitypub\Handler;
|
||||
|
||||
use Activitypub\Http;
|
||||
use Activitypub\Activity\Activity;
|
||||
use Activitypub\Collection\Users;
|
||||
use Activitypub\Collection\Followers;
|
||||
|
||||
/**
|
||||
* Handle Follow requests
|
||||
*/
|
||||
class Follow {
|
||||
/**
|
||||
* Initialize the class, registering WordPress hooks
|
||||
*/
|
||||
public static function init() {
|
||||
\add_action( 'activitypub_inbox_follow', array( self::class, 'handle_follow' ), 10, 2 );
|
||||
\add_action( 'activitypub_followers_post_follow', array( self::class, 'send_follow_response' ), 10, 4 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle "Follow" requests
|
||||
*
|
||||
* @param array $activity The activity object
|
||||
* @param int $user_id The user ID
|
||||
*/
|
||||
public static function handle_follow( $activity, $user_id ) {
|
||||
// save follower
|
||||
$follower = Followers::add_follower( $user_id, $activity['actor'] );
|
||||
|
||||
do_action( 'activitypub_followers_post_follow', $activity['actor'], $activity, $user_id, $follower );
|
||||
}
|
||||
|
||||
/**
|
||||
* Send Accept response
|
||||
*
|
||||
* @param string $actor The Actor URL
|
||||
* @param array $object The Activity object
|
||||
* @param int $user_id The ID of the WordPress User
|
||||
* @param Activitypub\Model\Follower $follower The Follower object
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function send_follow_response( $actor, $object, $user_id, $follower ) {
|
||||
if ( \is_wp_error( $follower ) ) {
|
||||
// it is not even possible to send a "Reject" because
|
||||
// we can not get the Remote-Inbox
|
||||
return;
|
||||
}
|
||||
|
||||
// only send minimal data
|
||||
$object = array_intersect_key(
|
||||
$object,
|
||||
array_flip(
|
||||
array(
|
||||
'id',
|
||||
'type',
|
||||
'actor',
|
||||
'object',
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
$user = Users::get_by_id( $user_id );
|
||||
|
||||
// get inbox
|
||||
$inbox = $follower->get_shared_inbox();
|
||||
|
||||
// send "Accept" activity
|
||||
$activity = new Activity();
|
||||
$activity->set_type( 'Accept' );
|
||||
$activity->set_object( $object );
|
||||
$activity->set_actor( $user->get_id() );
|
||||
$activity->set_to( $actor );
|
||||
$activity->set_id( $user->get_id() . '#follow-' . \preg_replace( '~^https?://~', '', $actor ) . '-' . \time() );
|
||||
|
||||
$activity = $activity->to_json();
|
||||
|
||||
Http::post( $inbox, $activity, $user_id );
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
namespace Activitypub\Handler;
|
||||
|
||||
use Activitypub\Collection\Followers;
|
||||
|
||||
/**
|
||||
* Handle Undo requests
|
||||
*/
|
||||
class Undo {
|
||||
/**
|
||||
* Initialize the class, registering WordPress hooks
|
||||
*/
|
||||
public static function init() {
|
||||
\add_action( 'activitypub_inbox_undo', array( self::class, 'handle_undo' ), 10, 2 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle "Unfollow" requests
|
||||
*
|
||||
* @param array $activity The JSON "Undo" Activity
|
||||
* @param int $user_id The ID of the ID of the WordPress User
|
||||
*/
|
||||
public static function handle_undo( $activity, $user_id ) {
|
||||
if (
|
||||
isset( $activity['object']['type'] ) &&
|
||||
'Follow' === $activity['object']['type']
|
||||
) {
|
||||
Followers::remove_follower( $user_id, $activity['actor'] );
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,89 @@
|
||||
<?php
|
||||
namespace Activitypub\Handler;
|
||||
|
||||
use WP_Error;
|
||||
use Activitypub\Collection\Interactions;
|
||||
|
||||
use function Activitypub\get_remote_metadata_by_actor;
|
||||
|
||||
/**
|
||||
* Handle Update requests.
|
||||
*/
|
||||
class Update {
|
||||
/**
|
||||
* Initialize the class, registering WordPress hooks
|
||||
*/
|
||||
public static function init() {
|
||||
\add_action( 'activitypub_inbox_update', array( self::class, 'handle_update' ), 10, 2 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle "Update" requests
|
||||
*
|
||||
* @param array $array The activity-object
|
||||
* @param int $user_id The id of the local blog-user
|
||||
*/
|
||||
public static function handle_update( $array, $user_id ) {
|
||||
$object_type = isset( $array['object']['type'] ) ? $array['object']['type'] : '';
|
||||
|
||||
switch ( $object_type ) {
|
||||
// Actor Types
|
||||
// @see https://www.w3.org/TR/activitystreams-vocabulary/#actor-types
|
||||
case 'Person':
|
||||
case 'Group':
|
||||
case 'Organization':
|
||||
case 'Service':
|
||||
case 'Application':
|
||||
self::update_actor( $array );
|
||||
break;
|
||||
// Object and Link Types
|
||||
// @see https://www.w3.org/TR/activitystreams-vocabulary/#object-types
|
||||
case 'Note':
|
||||
case 'Article':
|
||||
case 'Image':
|
||||
case 'Audio':
|
||||
case 'Video':
|
||||
case 'Event':
|
||||
case 'Document':
|
||||
self::update_interaction( $array, $user_id );
|
||||
break;
|
||||
// Minimal Activity
|
||||
// @see https://www.w3.org/TR/activitystreams-core/#example-1
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update an Interaction
|
||||
*
|
||||
* @param array $activity The activity-object
|
||||
* @param int $user_id The id of the local blog-user
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function update_interaction( $activity, $user_id ) {
|
||||
$state = Interactions::update_comment( $activity );
|
||||
$reaction = null;
|
||||
|
||||
if ( $state && ! \is_wp_error( $reaction ) ) {
|
||||
$reaction = \get_comment( $state );
|
||||
}
|
||||
|
||||
\do_action( 'activitypub_handled_update', $activity, $user_id, $state, $reaction );
|
||||
}
|
||||
|
||||
/**
|
||||
* Update an Actor
|
||||
*
|
||||
* @param array $activity The activity-object
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function update_actor( $activity ) {
|
||||
// update cache
|
||||
get_remote_metadata_by_actor( $activity['actor'], false );
|
||||
|
||||
// @todo maybe also update all interactions
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user