Shared Inbox (#617)
* init shared inbox * try to get user id from activity * some code formatting * disable ACTIVITYPUB_SHARED_INBOX_FEATURE * done! * do not use the inbox-user at all * fix user check! * fix user check!
This commit is contained in:
parent
a9c65f55d6
commit
a8078ce72b
8 changed files with 101 additions and 53 deletions
|
@ -33,6 +33,7 @@ require_once __DIR__ . '/includes/functions.php';
|
||||||
\defined( 'ACTIVITYPUB_CUSTOM_POST_CONTENT' ) || \define( 'ACTIVITYPUB_CUSTOM_POST_CONTENT', "<strong>[ap_title]</strong>\n\n[ap_content]\n\n[ap_hashtags]\n\n[ap_shortlink]" );
|
\defined( 'ACTIVITYPUB_CUSTOM_POST_CONTENT' ) || \define( 'ACTIVITYPUB_CUSTOM_POST_CONTENT', "<strong>[ap_title]</strong>\n\n[ap_content]\n\n[ap_hashtags]\n\n[ap_shortlink]" );
|
||||||
\defined( 'ACTIVITYPUB_AUTHORIZED_FETCH' ) || \define( 'ACTIVITYPUB_AUTHORIZED_FETCH', false );
|
\defined( 'ACTIVITYPUB_AUTHORIZED_FETCH' ) || \define( 'ACTIVITYPUB_AUTHORIZED_FETCH', false );
|
||||||
\defined( 'ACTIVITYPUB_DISABLE_REWRITES' ) || \define( 'ACTIVITYPUB_DISABLE_REWRITES', false );
|
\defined( 'ACTIVITYPUB_DISABLE_REWRITES' ) || \define( 'ACTIVITYPUB_DISABLE_REWRITES', false );
|
||||||
|
\defined( 'ACTIVITYPUB_SHARED_INBOX_FEATURE' ) || \define( 'ACTIVITYPUB_SHARED_INBOX_FEATURE', false );
|
||||||
|
|
||||||
\define( 'ACTIVITYPUB_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
|
\define( 'ACTIVITYPUB_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
|
||||||
\define( 'ACTIVITYPUB_PLUGIN_BASENAME', plugin_basename( __FILE__ ) );
|
\define( 'ACTIVITYPUB_PLUGIN_BASENAME', plugin_basename( __FILE__ ) );
|
||||||
|
|
|
@ -15,7 +15,12 @@ class Create {
|
||||||
* Initialize the class, registering WordPress hooks
|
* Initialize the class, registering WordPress hooks
|
||||||
*/
|
*/
|
||||||
public static function init() {
|
public static function init() {
|
||||||
\add_action( 'activitypub_inbox_create', array( self::class, 'handle_create' ), 10, 3 );
|
\add_action(
|
||||||
|
'activitypub_inbox_create',
|
||||||
|
array( self::class, 'handle_create' ),
|
||||||
|
10,
|
||||||
|
3
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -15,11 +15,24 @@ class Delete {
|
||||||
* Initialize the class, registering WordPress hooks
|
* Initialize the class, registering WordPress hooks
|
||||||
*/
|
*/
|
||||||
public static function init() {
|
public static function init() {
|
||||||
\add_action( 'activitypub_inbox_delete', array( self::class, 'handle_delete' ), 10, 2 );
|
\add_action(
|
||||||
|
'activitypub_inbox_delete',
|
||||||
|
array( self::class, 'handle_delete' )
|
||||||
|
);
|
||||||
|
|
||||||
// defer signature verification for `Delete` requests.
|
// defer signature verification for `Delete` requests.
|
||||||
\add_filter( 'activitypub_defer_signature_verification', array( self::class, 'defer_signature_verification' ), 10, 2 );
|
\add_filter(
|
||||||
|
'activitypub_defer_signature_verification',
|
||||||
|
array( self::class, 'defer_signature_verification' ),
|
||||||
|
10,
|
||||||
|
2
|
||||||
|
);
|
||||||
|
|
||||||
// side effect
|
// side effect
|
||||||
\add_action( 'activitypub_delete_actor_interactions', array( self::class, 'delete_interactions' ), 10, 1 );
|
\add_action(
|
||||||
|
'activitypub_delete_actor_interactions',
|
||||||
|
array( self::class, 'delete_interactions' )
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -28,7 +41,7 @@ class Delete {
|
||||||
* @param array $activity The delete activity.
|
* @param array $activity The delete activity.
|
||||||
* @param int $user_id The ID of the user performing the delete activity.
|
* @param int $user_id The ID of the user performing the delete activity.
|
||||||
*/
|
*/
|
||||||
public static function handle_delete( $activity, $user_id ) {
|
public static function handle_delete( $activity ) {
|
||||||
$object_type = isset( $activity['object']['type'] ) ? $activity['object']['type'] : '';
|
$object_type = isset( $activity['object']['type'] ) ? $activity['object']['type'] : '';
|
||||||
|
|
||||||
switch ( $object_type ) {
|
switch ( $object_type ) {
|
||||||
|
@ -39,7 +52,7 @@ class Delete {
|
||||||
case 'Organization':
|
case 'Organization':
|
||||||
case 'Service':
|
case 'Service':
|
||||||
case 'Application':
|
case 'Application':
|
||||||
self::maybe_delete_follower( $user_id, $activity );
|
self::maybe_delete_follower( $activity );
|
||||||
break;
|
break;
|
||||||
// Object and Link Types
|
// Object and Link Types
|
||||||
// @see https://www.w3.org/TR/activitystreams-vocabulary/#object-types
|
// @see https://www.w3.org/TR/activitystreams-vocabulary/#object-types
|
||||||
|
|
|
@ -14,8 +14,17 @@ class Follow {
|
||||||
* Initialize the class, registering WordPress hooks
|
* Initialize the class, registering WordPress hooks
|
||||||
*/
|
*/
|
||||||
public static function init() {
|
public static function init() {
|
||||||
\add_action( 'activitypub_inbox_follow', array( self::class, 'handle_follow' ), 10, 2 );
|
\add_action(
|
||||||
\add_action( 'activitypub_followers_post_follow', array( self::class, 'send_follow_response' ), 10, 4 );
|
'activitypub_inbox_follow',
|
||||||
|
array( self::class, 'handle_follow' )
|
||||||
|
);
|
||||||
|
|
||||||
|
\add_action(
|
||||||
|
'activitypub_followers_post_follow',
|
||||||
|
array( self::class, 'send_follow_response' ),
|
||||||
|
10,
|
||||||
|
4
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -24,11 +33,30 @@ class Follow {
|
||||||
* @param array $activity The activity object
|
* @param array $activity The activity object
|
||||||
* @param int $user_id The user ID
|
* @param int $user_id The user ID
|
||||||
*/
|
*/
|
||||||
public static function handle_follow( $activity, $user_id ) {
|
public static function handle_follow( $activity ) {
|
||||||
// save follower
|
$user = Users::get_by_resource( $activity['object'] );
|
||||||
$follower = Followers::add_follower( $user_id, $activity['actor'] );
|
|
||||||
|
|
||||||
do_action( 'activitypub_followers_post_follow', $activity['actor'], $activity, $user_id, $follower );
|
if ( ! $user || is_wp_error( $user ) ) {
|
||||||
|
// If we can not find a user,
|
||||||
|
// we can not initiate a follow process
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$user_id = $user->get__id();
|
||||||
|
|
||||||
|
// save follower
|
||||||
|
$follower = Followers::add_follower(
|
||||||
|
$user_id,
|
||||||
|
$activity['actor']
|
||||||
|
);
|
||||||
|
|
||||||
|
do_action(
|
||||||
|
'activitypub_followers_post_follow',
|
||||||
|
$activity['actor'],
|
||||||
|
$activity,
|
||||||
|
$user_id,
|
||||||
|
$follower
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Activitypub\Handler;
|
namespace Activitypub\Handler;
|
||||||
|
|
||||||
|
use Activitypub\Collection\Users;
|
||||||
use Activitypub\Collection\Followers;
|
use Activitypub\Collection\Followers;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -11,7 +12,10 @@ class Undo {
|
||||||
* Initialize the class, registering WordPress hooks
|
* Initialize the class, registering WordPress hooks
|
||||||
*/
|
*/
|
||||||
public static function init() {
|
public static function init() {
|
||||||
\add_action( 'activitypub_inbox_undo', array( self::class, 'handle_undo' ), 10, 2 );
|
\add_action(
|
||||||
|
'activitypub_inbox_undo',
|
||||||
|
array( self::class, 'handle_undo' )
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -20,11 +24,23 @@ class Undo {
|
||||||
* @param array $activity The JSON "Undo" Activity
|
* @param array $activity The JSON "Undo" Activity
|
||||||
* @param int $user_id The ID of the ID of the WordPress User
|
* @param int $user_id The ID of the ID of the WordPress User
|
||||||
*/
|
*/
|
||||||
public static function handle_undo( $activity, $user_id ) {
|
public static function handle_undo( $activity ) {
|
||||||
if (
|
if (
|
||||||
isset( $activity['object']['type'] ) &&
|
isset( $activity['object']['type'] ) &&
|
||||||
'Follow' === $activity['object']['type']
|
'Follow' === $activity['object']['type'] &&
|
||||||
|
isset( $activity['object']['object'] ) &&
|
||||||
|
filter_var( $activity['object']['object'], FILTER_VALIDATE_URL )
|
||||||
) {
|
) {
|
||||||
|
$user = Users::get_by_resource( $activity['object']['object'] );
|
||||||
|
|
||||||
|
if ( ! $user || is_wp_error( $user ) ) {
|
||||||
|
// If we can not find a user,
|
||||||
|
// we can not initiate a follow process
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$user_id = $user->get__id();
|
||||||
|
|
||||||
Followers::remove_follower( $user_id, $activity['actor'] );
|
Followers::remove_follower( $user_id, $activity['actor'] );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,10 @@ class Update {
|
||||||
* Initialize the class, registering WordPress hooks
|
* Initialize the class, registering WordPress hooks
|
||||||
*/
|
*/
|
||||||
public static function init() {
|
public static function init() {
|
||||||
\add_action( 'activitypub_inbox_update', array( self::class, 'handle_update' ), 10, 2 );
|
\add_action(
|
||||||
|
'activitypub_inbox_update',
|
||||||
|
array( self::class, 'handle_update' )
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -23,7 +26,7 @@ class Update {
|
||||||
* @param array $array The activity-object
|
* @param array $array The activity-object
|
||||||
* @param int $user_id The id of the local blog-user
|
* @param int $user_id The id of the local blog-user
|
||||||
*/
|
*/
|
||||||
public static function handle_update( $array, $user_id ) {
|
public static function handle_update( $array ) {
|
||||||
$object_type = isset( $array['object']['type'] ) ? $array['object']['type'] : '';
|
$object_type = isset( $array['object']['type'] ) ? $array['object']['type'] : '';
|
||||||
|
|
||||||
switch ( $object_type ) {
|
switch ( $object_type ) {
|
||||||
|
@ -45,7 +48,7 @@ class Update {
|
||||||
case 'Video':
|
case 'Video':
|
||||||
case 'Event':
|
case 'Event':
|
||||||
case 'Document':
|
case 'Document':
|
||||||
self::update_interaction( $array, $user_id );
|
self::update_interaction( $array );
|
||||||
break;
|
break;
|
||||||
// Minimal Activity
|
// Minimal Activity
|
||||||
// @see https://www.w3.org/TR/activitystreams-core/#example-1
|
// @see https://www.w3.org/TR/activitystreams-core/#example-1
|
||||||
|
@ -62,7 +65,7 @@ class Update {
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public static function update_interaction( $activity, $user_id ) {
|
public static function update_interaction( $activity ) {
|
||||||
$state = Interactions::update_comment( $activity );
|
$state = Interactions::update_comment( $activity );
|
||||||
$reaction = null;
|
$reaction = null;
|
||||||
|
|
||||||
|
@ -70,7 +73,7 @@ class Update {
|
||||||
$reaction = \get_comment( $state );
|
$reaction = \get_comment( $state );
|
||||||
}
|
}
|
||||||
|
|
||||||
\do_action( 'activitypub_handled_update', $activity, $user_id, $state, $reaction );
|
\do_action( 'activitypub_handled_update', $activity, null, $state, $reaction );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -226,6 +226,18 @@ class User extends Actor {
|
||||||
return get_rest_url_by_path( sprintf( 'users/%d/collections/featured', $this->get__id() ) );
|
return get_rest_url_by_path( sprintf( 'users/%d/collections/featured', $this->get__id() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function get_endpoints() {
|
||||||
|
$endpoints = null;
|
||||||
|
|
||||||
|
if ( ACTIVITYPUB_SHARED_INBOX_FEATURE ) {
|
||||||
|
$endpoints = array(
|
||||||
|
'sharedInbox' => get_rest_url_by_path( 'inbox' ),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $endpoints;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extend the User-Output with Attachments.
|
* Extend the User-Output with Attachments.
|
||||||
*
|
*
|
||||||
|
|
|
@ -94,11 +94,8 @@ class Inbox {
|
||||||
$json->generator = 'http://wordpress.org/?v=' . \get_bloginfo_rss( 'version' );
|
$json->generator = 'http://wordpress.org/?v=' . \get_bloginfo_rss( 'version' );
|
||||||
$json->type = 'OrderedCollectionPage';
|
$json->type = 'OrderedCollectionPage';
|
||||||
$json->partOf = get_rest_url_by_path( sprintf( 'users/%d/inbox', $user->get__id() ) ); // phpcs:ignore
|
$json->partOf = get_rest_url_by_path( sprintf( 'users/%d/inbox', $user->get__id() ) ); // phpcs:ignore
|
||||||
|
|
||||||
$json->totalItems = 0; // phpcs:ignore
|
$json->totalItems = 0; // phpcs:ignore
|
||||||
|
|
||||||
$json->orderedItems = array(); // phpcs:ignore
|
$json->orderedItems = array(); // phpcs:ignore
|
||||||
|
|
||||||
$json->first = $json->partOf; // phpcs:ignore
|
$json->first = $json->partOf; // phpcs:ignore
|
||||||
|
|
||||||
// filter output
|
// filter output
|
||||||
|
@ -155,37 +152,10 @@ class Inbox {
|
||||||
$data = $request->get_json_params();
|
$data = $request->get_json_params();
|
||||||
$activity = Activity::init_from_array( $data );
|
$activity = Activity::init_from_array( $data );
|
||||||
$type = $request->get_param( 'type' );
|
$type = $request->get_param( 'type' );
|
||||||
$users = self::get_recipients( $data );
|
$type = \strtolower( $type );
|
||||||
|
|
||||||
if ( ! $users ) {
|
\do_action( 'activitypub_inbox', $data, null, $type, $activity );
|
||||||
return new WP_Error(
|
\do_action( "activitypub_inbox_{$type}", $data, null, $activity );
|
||||||
'rest_invalid_param',
|
|
||||||
\__( 'No recipients found', 'activitypub' ),
|
|
||||||
array(
|
|
||||||
'status' => 400,
|
|
||||||
'params' => array(
|
|
||||||
'to' => \__( 'Please check/validate "to" field', 'activitypub' ),
|
|
||||||
'bto' => \__( 'Please check/validate "bto" field', 'activitypub' ),
|
|
||||||
'cc' => \__( 'Please check/validate "cc" field', 'activitypub' ),
|
|
||||||
'bcc' => \__( 'Please check/validate "bcc" field', 'activitypub' ),
|
|
||||||
'audience' => \__( 'Please check/validate "audience" field', 'activitypub' ),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ( $users as $user ) {
|
|
||||||
$user = User_Collection::get_by_various( $user );
|
|
||||||
|
|
||||||
if ( is_wp_error( $user ) ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$type = \strtolower( $type );
|
|
||||||
|
|
||||||
\do_action( 'activitypub_inbox', $data, $user->ID, $type, $activity );
|
|
||||||
\do_action( "activitypub_inbox_{$type}", $data, $user->ID, $activity );
|
|
||||||
}
|
|
||||||
|
|
||||||
$rest_response = new WP_REST_Response( array(), 202 );
|
$rest_response = new WP_REST_Response( array(), 202 );
|
||||||
$rest_response->header( 'Content-Type', 'application/activity+json; charset=' . get_option( 'blog_charset' ) );
|
$rest_response->header( 'Content-Type', 'application/activity+json; charset=' . get_option( 'blog_charset' ) );
|
||||||
|
|
Loading…
Reference in a new issue