From f6344f6f5c99fb088cf85df14a0916aa647b8014 Mon Sep 17 00:00:00 2001 From: Alex Kirk Date: Sun, 6 Oct 2024 09:45:12 +0200 Subject: [PATCH 1/8] Log activitypub actions --- .../class-feed-parser-activitypub.php | 25 ++++++ includes/class-logging.php | 80 +++++++++++++++++++ templates/admin/logs.php | 27 +++++++ 3 files changed, 132 insertions(+) create mode 100644 templates/admin/logs.php diff --git a/feed-parsers/class-feed-parser-activitypub.php b/feed-parsers/class-feed-parser-activitypub.php index f8258aa2..a8369c48 100644 --- a/feed-parsers/class-feed-parser-activitypub.php +++ b/feed-parsers/class-feed-parser-activitypub.php @@ -1823,6 +1823,18 @@ public function activitypub_like_post( $url, $external_post_id, $user_id ) { ) ); } + $type = 'like'; + $message = sprintf( + // translators: %s is the URL of the post. + __( 'Liked %s', 'friends' ), + '' . $external_post_id . '' + ); + $details = array( + 'actor' => $actor, + 'object' => $external_post_id, + ); + + Logging::log( 'like', $message, $details, self::SLUG, $user_id ); } /** @@ -2108,6 +2120,19 @@ public function activitypub_announce( $url, $user_id ) { foreach ( $inboxes as $inbox ) { \Activitypub\safe_remote_post( $inbox, $json, $user_id ); } + + $message = sprintf( + // translators: %s is the URL of the post. + __( 'Announced %s', 'friends' ), + '' . $url . '' + ); + + $details = array( + 'url' => $url, + 'inboxes' => count( $inboxes ), + ); + + Logging::log( 'announce', $message, $details, self::SLUG, $user_id ); } /** diff --git a/includes/class-logging.php b/includes/class-logging.php index 08509f91..4f7533f5 100644 --- a/includes/class-logging.php +++ b/includes/class-logging.php @@ -18,6 +18,13 @@ * @author Alex Kirk */ class Logging { + /** + * The custom post type for logging. + * + * @var string + */ + const CPT = 'friends_log'; + /** * Contains a reference to the Friends class. * @@ -35,12 +42,48 @@ public function __construct( Friends $friends ) { $this->register_hooks(); } + /** + * Register the custom post type for logging. + */ + private function register_post_type() { + $args = array( + 'labels' => array( + 'name' => __( 'Friends Logs', 'friends' ), + 'singular_name' => __( 'Friends Log', 'friends' ), + ), + 'public' => false, + 'show_ui' => false, + 'show_in_menu' => false, + 'supports' => array( 'title', 'editor' ), + ); + register_post_type( self::CPT, $args ); + + register_post_meta( + self::CPT, + 'type', + array( + 'type' => 'string', + 'single' => true, + ) + ); + register_post_meta( + self::CPT, + 'module', + array( + 'type' => 'string', + 'single' => true, + ) + ); + } + /** * Register the WordPress hooks */ private function register_hooks() { + add_action( 'init', array( $this, 'register_post_type' ) ); add_action( 'friends_retrieved_new_posts', array( $this, 'log_feed_successfully_fetched' ), 10, 3 ); add_action( 'friends_retrieve_friends_error', array( $this, 'log_feed_error' ), 10, 2 ); + add_action( 'friends_log', array( $this, 'log_entry' ), 10, 2 ); } /** @@ -72,4 +115,41 @@ public function log_feed_successfully_fetched( User_Feed $user_feed, $new_posts, public function log_feed_error( User_Feed $user_feed, $error ) { $user_feed->update_last_log( $error->get_error_message() ); } + + /** + * Save a log message. + * + * @param string $type The type of log message. + * @param string $message The message. + * @param string $details The details of the log message. + * @param string $module The module that generated the log message. + * @param int $user_id The ID of the user that generated the log message. + * @return int The ID of the log post. + */ + public static function log( $type, $message, $details, $module, $user_id ) { + $post_id = wp_insert_post( + array( + 'post_type' => self::CPT, + 'post_title' => $message, + 'post_content' => $details, + 'post_author' => $user_id, + 'post_status' => 'publish', + ) + ); + + add_post_meta( $post_id, 'type', $type ); + add_post_meta( $post_id, 'module', $module ); + + return $post_id; + } + + public static function get_logs() { + $logs = get_posts( + array( + 'post_type' => self::CPT, + 'posts_per_page' => 100, + ) + ); + return $logs; + } } diff --git a/templates/admin/logs.php b/templates/admin/logs.php new file mode 100644 index 00000000..8f3dfbdb --- /dev/null +++ b/templates/admin/logs.php @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + From 37de737ebd79bc4af351d7defb8881b1154571a6 Mon Sep 17 00:00:00 2001 From: Alex Kirk Date: Tue, 15 Oct 2024 07:21:20 +0100 Subject: [PATCH 2/8] make function public --- includes/class-logging.php | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/includes/class-logging.php b/includes/class-logging.php index 4f7533f5..66752ce8 100644 --- a/includes/class-logging.php +++ b/includes/class-logging.php @@ -42,10 +42,20 @@ public function __construct( Friends $friends ) { $this->register_hooks(); } + /** + * Register the WordPress hooks + */ + private function register_hooks() { + add_action( 'init', array( $this, 'register_post_type' ) ); + add_action( 'friends_retrieved_new_posts', array( $this, 'log_feed_successfully_fetched' ), 10, 3 ); + add_action( 'friends_retrieve_friends_error', array( $this, 'log_feed_error' ), 10, 2 ); + add_action( 'friends_log', array( $this, 'log_entry' ), 10, 2 ); + } + /** * Register the custom post type for logging. */ - private function register_post_type() { + public function register_post_type() { $args = array( 'labels' => array( 'name' => __( 'Friends Logs', 'friends' ), @@ -76,16 +86,6 @@ private function register_post_type() { ); } - /** - * Register the WordPress hooks - */ - private function register_hooks() { - add_action( 'init', array( $this, 'register_post_type' ) ); - add_action( 'friends_retrieved_new_posts', array( $this, 'log_feed_successfully_fetched' ), 10, 3 ); - add_action( 'friends_retrieve_friends_error', array( $this, 'log_feed_error' ), 10, 2 ); - add_action( 'friends_log', array( $this, 'log_entry' ), 10, 2 ); - } - /** * Log that a feed was sucessfully fetched. * From 6a4119d11451078b8009394bd4678c8e691ba788 Mon Sep 17 00:00:00 2001 From: Alex Kirk Date: Tue, 15 Oct 2024 07:30:20 +0100 Subject: [PATCH 3/8] Fix writing a non-string to the post_content --- includes/class-logging.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/includes/class-logging.php b/includes/class-logging.php index 66752ce8..58cd0d1d 100644 --- a/includes/class-logging.php +++ b/includes/class-logging.php @@ -121,7 +121,7 @@ public function log_feed_error( User_Feed $user_feed, $error ) { * * @param string $type The type of log message. * @param string $message The message. - * @param string $details The details of the log message. + * @param array $details The details of the log message. * @param string $module The module that generated the log message. * @param int $user_id The ID of the user that generated the log message. * @return int The ID of the log post. @@ -131,7 +131,7 @@ public static function log( $type, $message, $details, $module, $user_id ) { array( 'post_type' => self::CPT, 'post_title' => $message, - 'post_content' => $details, + 'post_content' => wp_json_encode( $details ), 'post_author' => $user_id, 'post_status' => 'publish', ) From 28dffba23812e7513c0e398af9161f15ff179161 Mon Sep 17 00:00:00 2001 From: Alex Kirk Date: Tue, 15 Oct 2024 07:33:51 +0100 Subject: [PATCH 4/8] Log the inboxes --- feed-parsers/class-feed-parser-activitypub.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/feed-parsers/class-feed-parser-activitypub.php b/feed-parsers/class-feed-parser-activitypub.php index a8369c48..ff26ac34 100644 --- a/feed-parsers/class-feed-parser-activitypub.php +++ b/feed-parsers/class-feed-parser-activitypub.php @@ -2117,8 +2117,11 @@ public function activitypub_announce( $url, $user_id ) { $json = $activity->to_json(); + $report = array(); foreach ( $inboxes as $inbox ) { - \Activitypub\safe_remote_post( $inbox, $json, $user_id ); + $response = \Activitypub\safe_remote_post( $inbox, $json, $user_id ); + $report[ $inbox ] = wp_remote_retrieve_response_message( $response ); + } $message = sprintf( @@ -2129,7 +2132,7 @@ public function activitypub_announce( $url, $user_id ) { $details = array( 'url' => $url, - 'inboxes' => count( $inboxes ), + 'inboxes' => $report, ); Logging::log( 'announce', $message, $details, self::SLUG, $user_id ); From c49cf314bd1f1d6688eee9491c5124151e6c86a7 Mon Sep 17 00:00:00 2001 From: Alex Kirk Date: Tue, 15 Oct 2024 07:38:55 +0100 Subject: [PATCH 5/8] pretty --- includes/class-logging.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/class-logging.php b/includes/class-logging.php index 58cd0d1d..e72e5186 100644 --- a/includes/class-logging.php +++ b/includes/class-logging.php @@ -131,7 +131,7 @@ public static function log( $type, $message, $details, $module, $user_id ) { array( 'post_type' => self::CPT, 'post_title' => $message, - 'post_content' => wp_json_encode( $details ), + 'post_content' => wp_json_encode( $details, JSON_PRETTY_PRINT ), 'post_author' => $user_id, 'post_status' => 'publish', ) From f261b3883360fb31c5746d3be3c59b7917b1bc45 Mon Sep 17 00:00:00 2001 From: Alex Kirk Date: Tue, 15 Oct 2024 07:57:54 +0100 Subject: [PATCH 6/8] Improve boosting --- .../class-feed-parser-activitypub.php | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/feed-parsers/class-feed-parser-activitypub.php b/feed-parsers/class-feed-parser-activitypub.php index ff26ac34..ae566bc6 100644 --- a/feed-parsers/class-feed-parser-activitypub.php +++ b/feed-parsers/class-feed-parser-activitypub.php @@ -2108,13 +2108,29 @@ public function activitypub_announce( $url, $user_id ) { $activity->set_actor( $actor ); $activity->set_object( $url ); $activity->set_id( $actor . '#activitypub_announce-' . \preg_replace( '~^https?://~', '', $url ) ); + $activity->set_to( 'https://www.w3.org/ns/activitystreams#Public' ); + $activity->set_published( \gmdate( 'Y-m-d\TH:i:s\Z', time() ) ); - $follower_inboxes = \Activitypub\Collection\Followers::get_inboxes( $user_id ); - $mentioned_inboxes = \Activitypub\Mention::get_inboxes( $activity->get_cc() ); - - $inboxes = array_merge( $follower_inboxes, $mentioned_inboxes ); + $inboxes = apply_filters( 'activitypub_send_to_inboxes', array(), $user_id, $activity ); $inboxes = array_unique( $inboxes ); + if ( empty( $inboxes ) ) { + + $message = sprintf( + // translators: %s is the URL of the post. + __( 'Announce failed for %s', 'friends' ), + '' . $url . '' + ); + + $details = array( + 'url' => $url, + 'error' => __( 'No inboxes to send to.', 'friends' ), + ); + + Logging::log( 'announce-failed', $message, $details, self::SLUG, $user_id ); + return; + } + $json = $activity->to_json(); $report = array(); From 18059c0b497c4f62a9dd2c3e20e9c24ae67fbc94 Mon Sep 17 00:00:00 2001 From: Alex Kirk Date: Tue, 15 Oct 2024 08:03:15 +0100 Subject: [PATCH 7/8] Output log --- includes/class-admin.php | 35 +++++++++++++++++++++++++++++++++++ templates/admin/logs.php | 8 +++++++- 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/includes/class-admin.php b/includes/class-admin.php index 5a27bc12..fd034d3b 100644 --- a/includes/class-admin.php +++ b/includes/class-admin.php @@ -178,6 +178,15 @@ public function admin_menu() { add_action( 'load-' . $page_type . '_page_edit-friend-rules', array( $this, 'process_admin_edit_friend_rules' ) ); } + if ( isset( $_GET['page'] ) && 'friends-log' === $_GET['page'] ) { + $user = new User( intval( $_GET['user'] ) ); + if ( $user ) { + // translators: as in log file. + $title = __( 'Log', 'friends' ); + add_submenu_page( 'friends', $title, $title, $required_role, 'friends-log', array( $this, 'render_friends_log' ) ); + } + } + if ( isset( $_GET['page'] ) && 'unfriend' === $_GET['page'] ) { $user = new User( intval( $_GET['user'] ) ); if ( $user ) { @@ -2491,6 +2500,32 @@ public function render_admin_import_export() { public function process_admin_import_export() { } + public function render_friends_log() { + Friends::template_loader()->get_template_part( + 'admin/settings-header', + null, + array( + 'active' => 'friends-log', + 'title' => __( 'Friends', 'friends' ), + ) + ); + $this->check_admin_settings(); + + ?> +

+ get_template_part( + 'admin/logs', + null, + array( + 'logs' => Logging::get_logs(), + ) + ); + + Friends::template_loader()->get_template_part( 'admin/settings-footer' ); + } + /** * Gets the friend roles. * diff --git a/templates/admin/logs.php b/templates/admin/logs.php index 8f3dfbdb..07b32344 100644 --- a/templates/admin/logs.php +++ b/templates/admin/logs.php @@ -20,8 +20,14 @@ ?>
- + +
post_date ); ?>post_title ); ?>post_author ) ); ?>
post_date ); ?>post_title ); ?> +
+ post_title ); ?> +
post_content ); ?>
+
+
post_author ) ); ?>
From ab4376103eaba346cbdba62435b3ed992ee54e42 Mon Sep 17 00:00:00 2001 From: Alex Kirk Date: Tue, 15 Oct 2024 08:14:13 +0100 Subject: [PATCH 8/8] Improve more activitypub activities --- .../class-feed-parser-activitypub.php | 126 +++++++++++++++--- includes/class-admin.php | 17 +-- 2 files changed, 112 insertions(+), 31 deletions(-) diff --git a/feed-parsers/class-feed-parser-activitypub.php b/feed-parsers/class-feed-parser-activitypub.php index ae566bc6..b470e4be 100644 --- a/feed-parsers/class-feed-parser-activitypub.php +++ b/feed-parsers/class-feed-parser-activitypub.php @@ -1797,10 +1797,6 @@ public function queue_like_post( \WP_Post $post, $author_url ) { */ public function activitypub_like_post( $url, $external_post_id, $user_id ) { $type = 'Like'; - $inbox = self::get_inbox_by_actor( $url, $type ); - if ( is_wp_error( $inbox ) ) { - return $inbox; - } $actor = \get_author_posts_url( $user_id ); $activity = new \Activitypub\Activity\Activity(); @@ -1810,8 +1806,34 @@ public function activitypub_like_post( $url, $external_post_id, $user_id ) { $activity->set_actor( $actor ); $activity->set_object( $external_post_id ); $activity->set_id( $actor . '#like-' . \preg_replace( '~^https?://~', '', $external_post_id ) ); - $activity = $activity->to_json(); - $response = \Activitypub\safe_remote_post( $inbox, $activity, $user_id ); + $activity->set_published( \gmdate( 'Y-m-d\TH:i:s\Z', time() ) ); + + $inboxes = apply_filters( 'activitypub_send_to_inboxes', array(), $user_id, $activity ); + $inboxes = array_unique( $inboxes ); + + if ( empty( $inboxes ) ) { + $message = sprintf( + // translators: %s is the URL of the post. + __( 'Like failed for %s', 'friends' ), + '' . $url . '' + ); + + $details = array( + 'url' => $url, + 'error' => __( 'No inboxes to send to.', 'friends' ), + ); + + Logging::log( 'like-failed', $message, $details, self::SLUG, $user_id ); + return; + } + + $json = $activity->to_json(); + + $report = array(); + foreach ( $inboxes as $inbox ) { + $response = \Activitypub\safe_remote_post( $inbox, $json, $user_id ); + $report[ $inbox ] = wp_remote_retrieve_response_message( $response ); + } $user_feed = User_Feed::get_by_url( $url ); if ( $user_feed instanceof User_Feed ) { @@ -1830,8 +1852,9 @@ public function activitypub_like_post( $url, $external_post_id, $user_id ) { '' . $external_post_id . '' ); $details = array( - 'actor' => $actor, - 'object' => $external_post_id, + 'actor' => $actor, + 'url' => $external_post_id, + 'inboxes' => $report, ); Logging::log( 'like', $message, $details, self::SLUG, $user_id ); @@ -1894,10 +1917,6 @@ public function queue_unlike_post( \WP_Post $post, $author_url ) { */ public function activitypub_unlike_post( $url, $external_post_id, $user_id ) { $type = 'Like'; - $inbox = self::get_inbox_by_actor( $url, $type ); - if ( is_wp_error( $inbox ) ) { - return $inbox; - } $actor = \get_author_posts_url( $user_id ); $activity = new \Activitypub\Activity\Activity(); @@ -1914,8 +1933,33 @@ public function activitypub_unlike_post( $url, $external_post_id, $user_id ) { ) ); $activity->set_id( $actor . '#unlike-' . \preg_replace( '~^https?://~', '', $external_post_id ) ); - $activity = $activity->to_json(); - $response = \Activitypub\safe_remote_post( $inbox, $activity, $user_id ); + + $inboxes = apply_filters( 'activitypub_send_to_inboxes', array(), $user_id, $activity ); + $inboxes = array_unique( $inboxes ); + + if ( empty( $inboxes ) ) { + $message = sprintf( + // translators: %s is the URL of the post. + __( 'Unlike failed for %s', 'friends' ), + '' . $url . '' + ); + + $details = array( + 'url' => $url, + 'error' => __( 'No inboxes to send to.', 'friends' ), + ); + + Logging::log( 'unlike-failed', $message, $details, self::SLUG, $user_id ); + return; + } + + $json = $activity->to_json(); + + $report = array(); + foreach ( $inboxes as $inbox ) { + $response = \Activitypub\safe_remote_post( $inbox, $json, $user_id ); + $report[ $inbox ] = wp_remote_retrieve_response_message( $response ); + } $user_feed = User_Feed::get_by_url( $url ); if ( $user_feed instanceof User_Feed ) { @@ -1927,6 +1971,19 @@ public function activitypub_unlike_post( $url, $external_post_id, $user_id ) { ) ); } + $type = 'unlike'; + $message = sprintf( + // translators: %s is the URL of the post. + __( 'Unliked %s', 'friends' ), + '' . $external_post_id . '' + ); + $details = array( + 'actor' => $actor, + 'url' => $external_post_id, + 'inboxes' => $report, + ); + + Logging::log( 'unlike', $message, $details, self::SLUG, $user_id ); } public function boost_button() { @@ -2115,7 +2172,6 @@ public function activitypub_announce( $url, $user_id ) { $inboxes = array_unique( $inboxes ); if ( empty( $inboxes ) ) { - $message = sprintf( // translators: %s is the URL of the post. __( 'Announce failed for %s', 'friends' ), @@ -2137,7 +2193,6 @@ public function activitypub_announce( $url, $user_id ) { foreach ( $inboxes as $inbox ) { $response = \Activitypub\safe_remote_post( $inbox, $json, $user_id ); $report[ $inbox ] = wp_remote_retrieve_response_message( $response ); - } $message = sprintf( @@ -2194,18 +2249,47 @@ public function activitypub_unannounce( $url, $user_id ) { 'id' => $actor . '#activitypub_announce-' . \preg_replace( '~^https?://~', '', $url ), ) ); + $activity->set_published( \gmdate( 'Y-m-d\TH:i:s\Z', time() ) ); - $follower_inboxes = \Activitypub\Collection\Followers::get_inboxes( $user_id ); - $mentioned_inboxes = \Activitypub\Mention::get_inboxes( $activity->get_cc() ); - - $inboxes = array_merge( $follower_inboxes, $mentioned_inboxes ); + $inboxes = apply_filters( 'activitypub_send_to_inboxes', array(), $user_id, $activity ); $inboxes = array_unique( $inboxes ); + if ( empty( $inboxes ) ) { + $message = sprintf( + // translators: %s is the URL of the post. + __( 'Unannounce failed for %s', 'friends' ), + '' . $url . '' + ); + + $details = array( + 'url' => $url, + 'error' => __( 'No inboxes to send to.', 'friends' ), + ); + + Logging::log( 'unannounce-failed', $message, $details, self::SLUG, $user_id ); + return; + } + $json = $activity->to_json(); + $report = array(); foreach ( $inboxes as $inbox ) { - \Activitypub\safe_remote_post( $inbox, $json, $user_id ); + $response = \Activitypub\safe_remote_post( $inbox, $json, $user_id ); + $report[ $inbox ] = wp_remote_retrieve_response_message( $response ); } + + $message = sprintf( + // translators: %s is the URL of the post. + __( 'Unannounced %s', 'friends' ), + '' . $url . '' + ); + + $details = array( + 'url' => $url, + 'inboxes' => $report, + ); + + Logging::log( 'unannounce', $message, $details, self::SLUG, $user_id ); } /** diff --git a/includes/class-admin.php b/includes/class-admin.php index fd034d3b..ab466695 100644 --- a/includes/class-admin.php +++ b/includes/class-admin.php @@ -178,13 +178,10 @@ public function admin_menu() { add_action( 'load-' . $page_type . '_page_edit-friend-rules', array( $this, 'process_admin_edit_friend_rules' ) ); } - if ( isset( $_GET['page'] ) && 'friends-log' === $_GET['page'] ) { - $user = new User( intval( $_GET['user'] ) ); - if ( $user ) { - // translators: as in log file. - $title = __( 'Log', 'friends' ); - add_submenu_page( 'friends', $title, $title, $required_role, 'friends-log', array( $this, 'render_friends_log' ) ); - } + if ( isset( $_GET['page'] ) && 'friends-logs' === $_GET['page'] ) { + // translators: as in log file. + $title = __( 'Log', 'friends' ); + add_submenu_page( 'friends', $title, $title, $required_role, 'friends-logs', array( $this, 'render_friends_logs' ) ); } if ( isset( $_GET['page'] ) && 'unfriend' === $_GET['page'] ) { @@ -2500,19 +2497,19 @@ public function render_admin_import_export() { public function process_admin_import_export() { } - public function render_friends_log() { + public function render_friends_logs() { Friends::template_loader()->get_template_part( 'admin/settings-header', null, array( - 'active' => 'friends-log', + 'active' => 'friends-logs', 'title' => __( 'Friends', 'friends' ), ) ); $this->check_admin_settings(); ?> -

+

get_template_part(