Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add/User Delete activities #552

Open
wants to merge 52 commits into
base: trunk
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
bcf29e1
Profiles: update followers when profile fields change
mattwiebe Oct 31, 2023
e3a78fb
use static
mattwiebe Oct 31, 2023
af3e61c
only try to merge mention inboxes when valid
mattwiebe Nov 1, 2023
3785cee
Add Server Class, known_inboxes method
mediaformat Nov 8, 2023
d64ed73
Add a server dispatch activity
mediaformat Nov 8, 2023
565a6ca
Add a delete wp user action
mediaformat Nov 8, 2023
9e8065a
lint:fix
mediaformat Nov 8, 2023
4d83e1a
Merge branch 'master' into add/ServerActivities
pfefferle Nov 10, 2023
7543884
Add blog user followers to known inboxes
mediaformat Nov 10, 2023
05b4ebf
public function
mediaformat Nov 11, 2023
2bfb930
update send_server_activity
mediaformat Nov 11, 2023
6c548bc
update delete schedulers
mediaformat Nov 11, 2023
41f05ef
get temporary key for deleted user
mediaformat Nov 11, 2023
f101daf
Merge branch 'master' into add/ServerActivities
mediaformat Nov 11, 2023
87d32cb
Merge branch 'master' into add/ServerActivities
mediaformat Nov 13, 2023
06a023e
Rename to Application class
mediaformat Nov 13, 2023
5090e84
Merge branch 'master' into add/ServerActivities
mediaformat Nov 27, 2023
8499aa4
Merge branch 'master' into add/ServerActivities
pfefferle Nov 30, 2023
96b29a3
Merge branch 'master' into add/ServerActivities
pfefferle Dec 18, 2023
76771aa
Merge branch 'master' into add/ServerActivities
pfefferle May 6, 2024
fcbfa74
Fix PHP errors and lint issues
mattwiebe May 7, 2024
ca3d1bc
Update includes/class-scheduler.php
mediaformat May 8, 2024
e894bc6
Rename action and function
mediaformat May 8, 2024
1aa30ed
Use get_all_followers for inboxes
mediaformat May 8, 2024
fb0f679
schedule_actor_delete
mediaformat May 8, 2024
61951f7
has_cap activitypub
mediaformat May 8, 2024
4cef50d
activitypub_send_actor_delete_activity
mediaformat May 8, 2024
6c1fa00
remove Application class
mediaformat May 8, 2024
01b4d09
private key already stored
mediaformat May 8, 2024
22a664e
clean up user, delete signature options key
mediaformat May 8, 2024
aa448d3
get signing keys from options for actor delete activity
mediaformat May 9, 2024
f9fee8c
Send Delete activity to shared_inboxes
mediaformat May 9, 2024
2df226e
set temp signature option
mediaformat May 9, 2024
d1e0074
cleanup
mediaformat May 9, 2024
bf50942
phpcs
mediaformat May 9, 2024
c781662
phpcbf
mediaformat May 9, 2024
39fffc7
Merge branch 'master' into add/ServerActivities
pfefferle May 16, 2024
7af4eb1
Merge branch 'master' into add/ServerActivities
pfefferle May 16, 2024
c9477d7
Merge branch 'master' into add/ServerActivities
pfefferle Jun 4, 2024
dc88d91
Merge branch 'master' into add/ServerActivities
pfefferle Jun 25, 2024
b84286e
init cli
pfefferle Jun 25, 2024
0de423a
add http gone class
pfefferle Jun 26, 2024
2f33377
add http gone
pfefferle Jun 26, 2024
39e6e71
rewrite dispatcher a bit
pfefferle Jun 26, 2024
520c3fb
mark as federated
pfefferle Jun 26, 2024
962e6dd
cleanups
pfefferle Jun 26, 2024
2730907
remove lagacy code
pfefferle Jun 26, 2024
295d5bc
fix instance of check
pfefferle Jun 26, 2024
4fcf151
better $user handling
pfefferle Jun 27, 2024
f319cac
better support of system users
pfefferle Jun 27, 2024
62714a5
better description
pfefferle Jul 9, 2024
84dbdc4
Merge branch 'master' into add/ServerActivities
pfefferle Jul 11, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 68 additions & 14 deletions includes/class-activity-dispatcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ class Activity_Dispatcher {
public static function init() {
\add_action( 'activitypub_send_activity', array( self::class, 'send_activity' ), 10, 2 );
\add_action( 'activitypub_send_activity', array( self::class, 'send_activity_or_announce' ), 10, 2 );
\add_action( 'activitypub_send_update_profile_activity', array( self::class, 'send_profile_update' ), 10, 1 );
\add_action( 'activitypub_send_server_activity', array( self::class, 'send_server_activity' ), 10, 1 );
}

/**
Expand Down Expand Up @@ -71,17 +73,7 @@ public static function send_activity( WP_Post $wp_post, $type ) {
$activity->set_type( $type );
$activity->set_object( $object );

$follower_inboxes = Followers::get_inboxes( $wp_post->post_author );
$mentioned_inboxes = Mention::get_inboxes( $activity->get_cc() );

$inboxes = array_merge( $follower_inboxes, $mentioned_inboxes );
$inboxes = array_unique( $inboxes );

$json = $activity->to_json();

foreach ( $inboxes as $inbox ) {
safe_remote_post( $inbox, $json, $wp_post->post_author );
}
self::send_activity_to_inboxes( $activity, $wp_post->post_author );
}

/**
Expand Down Expand Up @@ -110,16 +102,78 @@ public static function send_announce( WP_Post $wp_post, $type ) {
// send only the id
$activity->set_object( $object->get_id() );

$follower_inboxes = Followers::get_inboxes( $wp_post->post_author );
$mentioned_inboxes = Mention::get_inboxes( $activity->get_cc() );
self::send_activity_to_inboxes( $activity, $wp_post->post_author );
}

/**
* Send a "Update" Activity when a user updates their profile.
*
* @param int $user_id The user ID to send an update for.
*
*/
public static function send_profile_update( $user_id ) {
$user = Users::get_by_various( $user_id );

// bail if that's not a good user
if ( is_wp_error( $user ) ) {
return;
}

// build the update
$activity = new Activity();
$activity->set_id( $user->get_url() . '#update' );
$activity->set_type( 'Update' );
$activity->set_actor( $user->get_url() );
$activity->set_object( $user->get_url() );
$activity->set_to( 'https://www.w3.org/ns/activitystreams#Public' );

// send the update
self::send_activity_to_inboxes( $activity, $user_id );
}

/**
* Send an Activity to all followers and mentioned users.
*
* @param Activity $activity The ActivityPub Activity.
* @param int $user_id The user ID.
*
* @return void
*/
private static function send_activity_to_inboxes( $activity, $user_id ) {
$follower_inboxes = Followers::get_inboxes( $user_id );

$mentioned_inboxes = array();
$cc = $activity->get_cc();
if ( $cc ) {
$mentioned_inboxes = Mention::get_inboxes( $cc );
}

$inboxes = array_merge( $follower_inboxes, $mentioned_inboxes );
$inboxes = array_unique( $inboxes );

if ( empty( $inboxes ) ) {
return;
}

$json = $activity->to_json();

foreach ( $inboxes as $inbox ) {
safe_remote_post( $inbox, $json, $wp_post->post_author );
safe_remote_post( $inbox, $json, $user_id );
}
}

/**
* Send an Activity to all known (shared_)inboxes.
*
* @param Activity $activity The ActivityPub Activity.
*
* @return void
*/
private static function send_server_activity( $activity ) {
$json = $activity->to_json();
$inboxes = Server::known_inboxes();
foreach ( $inboxes as $inbox ) {
safe_remote_post( $inbox, $json, -1 );
}
}
}
88 changes: 88 additions & 0 deletions includes/class-scheduler.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,17 @@
use Activitypub\Collection\Users;
use Activitypub\Collection\Followers;
use Activitypub\Transformer\Post;
use Activitypub\Activity\Activity;

use function Activitypub\is_user_type_disabled;

/**
* ActivityPub Scheduler Class
*
* @author Matthias Pfefferle
*/
class Scheduler {

/**
* Initialize the class, registering WordPress hooks
*/
Expand All @@ -22,6 +26,23 @@ public static function init() {
\add_action( 'activitypub_cleanup_followers', array( self::class, 'cleanup_followers' ) );

\add_action( 'admin_init', array( self::class, 'schedule_migration' ) );

// profile updates for blog options
if ( ! is_user_type_disabled( 'blog' ) ) {
\add_action( 'update_option_site_icon', array( self::class, 'blog_user_update' ) );
\add_action( 'update_option_blogdescription', array( self::class, 'blog_user_update' ) );
\add_action( 'update_option_blogname', array( self::class, 'blog_user_update' ) );
\add_filter( 'pre_set_theme_mod_custom_logo', array( self::class, 'blog_user_update' ) );
\add_filter( 'pre_set_theme_mod_header_image', array( self::class, 'blog_user_update' ) );
}

// profile updates for user options
if ( ! is_user_type_disabled( 'user' ) ) {
mediaformat marked this conversation as resolved.
Show resolved Hide resolved
\add_action( 'updated_user_meta', array( self::class, 'user_update' ), 10, 3 );
// @todo figure out a feasible way of updating the header image since it's not unique to any user.

\add_action( 'delete_user', array( self::class, 'schedule_profile_delete' ), 10, 3 );
}
}

/**
Expand Down Expand Up @@ -166,4 +187,71 @@ public static function schedule_migration() {
\wp_schedule_single_event( \time(), 'activitypub_schedule_migration' );
}
}

/**
* Send a profile update when relevant user meta is updated.
*
* @param int $meta_id Meta ID being updated.
* @param int $user_id User ID being updated.
* @param string $meta_key Meta key being updated.
* @return void
*/
public static function user_update( $meta_id, $user_id, $meta_key ) {
// don't bother if the user can't publish
if ( ! \user_can( $user_id, 'publish_posts' ) ) {
return;
}
// the user meta fields that affect a profile.
$fields = array(
'activitypub_user_description',
'description',
'user_url',
'display_name',
);
if ( in_array( $meta_key, $fields, true ) ) {
self::schedule_profile_update( $user_id );
}
}

/**
* Theme mods only have a dynamic filter so we fudge it like this.
* @param mixed $value
* @return mixed
*/
public static function blog_user_update( $value = null ) {
self::schedule_profile_update( 0 );
return $value;
}

/**
* Send a profile update to all followers. Gets hooked into all relevant options/meta etc.
* @param int $user_id The user ID to update (Could be 0 for Blog-User).
*/
public static function schedule_profile_update( $user_id ) {
\wp_schedule_single_event(
\time(),
'activitypub_send_update_profile_activity',
array( $user_id )
);
}

/**
* Send an Actor Delete activity.
* @param int $user_id The user ID to Delete.
*/
public static function schedule_profile_delete( $user_id ) {
$user = get_userdata( $user_id );
if ( $user->has_cap( 'publish_posts' ) ) {
$author_url = \get_author_posts_url( $user->ID );

$activity = new Activity();
$activity->set_id( $author_url . '#delete' );
$activity->set_type( 'Delete' );
$activity->set_actor( $author_url );
$activity->set_object( $author_url );
$activity->set_to( [ 'https://www.w3.org/ns/activitystreams#Public' ] );
mediaformat marked this conversation as resolved.
Show resolved Hide resolved

\wp_schedule_single_event( \time(), 'activitypub_send_server_activity', array( $activity ) );
}
}
}
25 changes: 25 additions & 0 deletions includes/class-server.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

namespace Activitypub;

/**
* ActivityPub Server Class
*
* @author Django Doucet
*/
class Server {

private static function known_inboxes() {
$authors = get_users(
array(
'capability' => 'publish_posts',
)
);
$follower_inboxes_all = [];
foreach ( $authors as $user ) {
$follower_inboxes = Followers::get_inboxes( $user->ID );
$follower_inboxes_all = array_merge( $follower_inboxes, $follower_inboxes_all );
}
return array_unique( array_filter( $follower_inboxes_all ) );
}
}
Loading