「コメント欄ではメンション先を選べない」問題のコード

とりあえず、関連記事。

"WordPressのプラグイン「ActivityPub」のアカウントa@Aの投稿にマストドンのアカウントb@Bから返信があり、その返信にa@Aがコメント欄から返信して、その返信にさらにa@Aがコメント欄から返信する際に、b@Bへのメンションを外したいのですが、できません。

さらに、同じスレッドで、別のマストドンのアカウントc@Cからa@Aに返信(メンションはa@A宛だけ)があった後、そのc@Cの返信にa@Aが返信しようとすると、b@Bへのメンションも追加されてしまいます。
"
コメント欄ではメンション先を選べない | いしい@試行錯誤
https://ishii00141.stars.ne.jp/20250216-1635-895/

"今も同じかどうか確認するためのテスト。
"
コメントと通知の関係を確認するテスト | いしい@試行錯誤
https://ishii00141.stars.ne.jp/20250311-0803-1646/

この問題に関するコードは、これではないかと思うものを見つけたのでメモ。

/wp-content/plugins/activitypub/includes/transformer/class-comment.php

/**
 * Gets the ancestors of the comment, but only the ones that are ActivityPub comments.
 *
 * @return array The list of ancestors.
 */
protected function get_comment_ancestors() {
	$ancestors = get_comment_ancestors( $this->item );

	// Now that we have the full tree of ancestors, only return the ones received from the fediverse.
	return array_filter(
		$ancestors,
		function ( $comment_id ) {
			return \get_comment_meta( $comment_id, 'protocol', true ) === 'activitypub';
		}
	);
}

/**
* Collect all other Users that participated in this comment-thread
* to send them a notification about the new reply.
*
* @param array $mentions Optional. The already mentioned ActivityPub users. Default empty array.
*
* @return array The list of all Repliers.
*/
public function extract_reply_context( $mentions = array() ) {
	// Check if `$this->item` is a WP_Comment.
	if ( 'WP_Comment' !== get_class( $this->item ) ) {
		return $mentions;
	}

	$ancestors = $this->get_comment_ancestors();
	if ( ! $ancestors ) {
		return $mentions;
	}

	foreach ( $ancestors as $comment_id ) {
		$comment = \get_comment( $comment_id );
		if ( $comment && ! empty( $comment->comment_author_url ) ) {
			$acct = Webfinger::uri_to_acct( $comment->comment_author_url );
			if ( $acct && ! is_wp_error( $acct ) ) {
				$acct              = str_replace( 'acct:', '@', $acct );
				$mentions[ $acct ] = $comment->comment_author_url;
			}
		}
	}

	return $mentions;
}

このコードを に分析してもらったら、「このコードの目的」は次の通りだった。

このコードは、WordPressサイトにActivityPub連携機能が実装されている場合に、コメントへの返信があった際に、その返信がどのコメントスレッドに対するものかを把握し、そのスレッドに参加している他のActivityPubユーザーに通知を送るために、必要な情報を収集する役割を果たしていると考えられます。これにより、分散型のソーシャルネットワーク上でのコミュニケーションを円滑に行うことができます。

要するに、スレッドに参加している全員に通知する仕組みらしい。バグではなく仕様。

未分類
管理人のマストドンアカウントへのリンクなど

コメント

  1. ishii ishii より:

    foreach のコードの前に return $mentions; を追加して foreach のコードを無視させることで、不要な通知を避けることができた。
    https://ishii00141.stars.ne.jp/?c=687

    すなわち、通知が必要ならばコメント欄にメンションを記載しなければいけないようにできた。
    https://ishii00141.stars.ne.jp/?c=688

    その方向で、対処方法を #Gemini に相談してみることにする。

  2. ishii ishii より:

    このコードを使って、通知(cc)のためのメンションリストを作っていると思われるコード。

    /**
     * Helper function to get the @-Mentions from the comment content.
     *
     * @return array The list of @-Mentions.
     */
    protected function get_mentions() {
      \add_filter( 'activitypub_extract_mentions', array( $this, 'extract_reply_context' ) );
    
      /**
       * Filter the mentions in the comment.
       *
       * @param array     $mentions The list of mentions.
       * @param string    $content  The content of the comment.
       * @param \WP_Comment $comment  The comment object.
       *
       * @return array The filtered list of mentions.
       */
    
    return apply_filters( 'activitypub_extract_mentions', array(), $this->item->comment_content, $this->item );
    }
    
    • ishii ishii より:

      これに関してはいろいろと試したが、通知を防ぐことはできなかった。

    • ishii ishii より:

      \add_filter( 'activitypub_extract_mentions', array( $this, 'extract_reply_context' ) );
      をコメントアウトするだけで、ccに通知URLが追加されずに済む。

      https://ishii00141.stars.ne.jp/?c=722

      • ishii ishii より:

        スレッド内のアカウントに自動的に通知(ccにアカウントのURLを追加)されるのを防ぐには、次のコードをfunctions.phpに追加することで実現できた。

        // 自動付加メンションによる通知を避ける
        function force_empty_activitypub_mentions( $mentions, $content, $comment ) {
          return array();
        }
        add_filter( 'activitypub_extract_mentions', 'force_empty_activitypub_mentions', 999, 3 );
  3. ishii ishii より:

    このコードを使って、送信するコンテンツにメンションを追加していると思われるコード。

    /**
     * Returns the content for the ActivityPub Item.
     *
     * The content will be generated based on the user settings.
     *
     * @return string The content.
     */
    protected function get_content() {
      $comment  = $this->item;
      $content  = $comment->comment_content;
      $mentions = '';
        foreach ( $this->extract_reply_context() as $acct => $url ) {
        $mentions .= sprintf(
          '<a rel="mention" class="u-url mention" href="%1$s" title="%2$s">%3$s</a> ',
          esc_url( $url ),
          esc_attr( $acct ),
          esc_html( '@' . strtok( $acct, '@' ) )
        );
      }
      $content = $mentions . $content;
    
      /**
       * Filter the content of the comment.
       *
       * @param string    $content The content of the comment.
       * @param \WP_Comment $comment The comment object.
       * @param array     $args  The arguments.
       *
       * @return string The filtered content of the comment.
       */
      $content = \apply_filters( 'comment_text', $content, $comment, array() );
      $content = \preg_replace( '/[\n\r\t]/', '', $content );
      $content = \trim( $content );
    
      /**
       * Filter the content of the comment.
       *
       * @param string    $content The content of the comment.
       * @param \WP_Comment $comment The comment object.
       *
       * @return string The filtered content of the comment.
       */
      return \apply_filters( 'activitypub_the_content', $content, $comment );
    }
    
    • ishii ishii より:

      Fediverseで表示された場合に自動追加されたメンションが表示されないようにするには、次のコードをfunctions.phpに追加することで実現できた。ただし、通知はされる。

      // Fediverseでメンションが表示されないようにする(ただし、通知は防げない)
      function my_filter_comment_text( $content, $comment, $args ) {
        // 常に元のコメントコンテンツで $content を上書きする
        $content = $comment->comment_content;
      
        // その後の処理は元のフィルターチェーンに沿って行われます
        return $content;
      }
      add_filter( 'comment_text', 'my_filter_comment_text', 5, 3 );
タイトルとURLをコピーしました