連合の無いサーバーからの「いいね」は表示されない様ですが、増殖を修正する前から同様なため、これは一旦そのままです。
上記コミットの内容や issue もご参照ください。
- GNU socialの投稿のuriは「ローカル向け」「AP向け」の2つの體系を持ち、兩者を適切に區別できてゐない。※この呼び方は正式な物では無い。
- 投稿時、自サーバーのDBには、「ローカル向け」のuriで保存される。
- 他サーバーのDBには、「AP向け」のuriで保存される。
- 返信時、「する側」は、「AP向け」のuriに向けて返信をする。
- その時點では返信を「される側」のDBには、「ローカル向け」のuriしか無い。
- ここで返信を「される側」は、「AP向け」のuriを持つ投稿を「新しく作成」してしまふ。
増殖したDBのイメージ
(2023-08-22)この修正はうまく機能してゐない可能性があります。
「uriを元にローカルのDBから投稿を探す」箇所に『「AP向け」のuriを元に「ローカル向け」uriの投稿を探す。』処理を追加する事で、 「ローカル向け」投稿がみつかれば、それが返信と結びつく様にしました。
具体的には「ActivityPubPlugin.php」のメソッド「grab_notice_from_url」で投稿IDを元に「Notice::getByID($id)」を呼び出します。この戻り値は「ローカル向け」のURLになります。メソッド「grab_notice_from_url」は、リモートから返信などのアクティビティを受けた際に、アクティビティとローカル投稿とを結びつけるために呼び出されます。
ActivityPubPlugin.php:
- $candidate = Notice::getByID((int)substr($url, (strlen(Activitypub_notice::note_uri(0))-1))); + $id = (int)substr($url, (strlen(Activitypub_notice::note_uri(0))-1)); + if ($id <= 0) { + $id = (int)basename($url); + } + $candidate = Notice::getByID($id); if (Activitypub_notice::note_uri($candidate->getID()) === $url) { // Sanity check return $candidate; + } elseif ($candidate->getLocalUrl() === $url) { // Sanity check (url starts with 'tag:') + return $candidate; } else { common_debug('ActivityPubPlugin Notice Grabber: '.$candidate->getUrl(). ' is different of '.$url); }
「返信された」側のログ「ActivityPub Inbox: Request contents:」を観察。(異なる投稿への返信のためid 256,209 の差はどうでもいい)
- mastodonからのinReplyToはactivitystream(?)になつてゐる。
- GNU socialからのinReplyToはただの投稿のURLになつてゐる。
- GNU socialから返信する時もmastodonの仕様に合せれば、返信する側の不具合も無くなる?
- [gs->gs]
- $ grep 'res-58' public/gnusocial.log
"inReplyTo":"https://gs.bibi.moe/notice/254"
(前後略)- [mastodon->gs]
- $ grep 'mstdn.jpから'
public/gnusocial.log
"inReplyTo":"httpps://gs.bibi.moe/object/note/209"
(前後略)
GNU social から外部サーバーに返信する際に、inReplyTo の値に「url(/notice/xxx)」ではなく「uri(/object/note/xxx)」を指定します。これで mastodon と同じ挙動になります。
具体的には「Activitypub_notice.php」のメソッド「getUri」を編集して返却値を変更します。メソッド「getUri」の戻り値は inReplyTo に代入されます。
Activitypub_notice.php:
+ $uri = $notice->getUri(); + if (common_valid_http_url($uri)) { + return $uri; + } return $notice->getUrl();
GNU socialの同じサーバー同士会話を、別サーバーから取得すると、ツリーが正しく繋がらず、返信が孤立する事がありました。
リモートの会話を取得する時は、返信元の投稿がすでにデータベースにあるのに、もう1度保存を試みて失敗し、返信が繋がりませんでした。
これを修正するには「ActivityPubPlugin.php」のメソッド「grab_notice_from_url」で、投稿がすでにデータベースにある場合、データベースから投稿の URL を取得します。
ActivityPubPlugin.php:
+ try { + return Notice::getByUri($object['id']); + } catch (Exception $e) { + // NOOP + } return Activitypub_notice::create_notice($object, $acclaimed_actor_profile);
ローカルの会話をリモートに通知する時は、返信先の投稿 URL が「ドメイン/activity/xxx」の形式で指定され、リモートのサーバーはこれをうまく紐付けられませんでした。
これを修正するには、「Activitypub_notice.php」のメソッド「getUri」を修正して「'ドメイン/object/note/xxx'」の形式が返却される様にします。
Activitypub_notice.php:
if ($notice->isLocal()) { - return common_local_url('apNotice', ['id' => $notice->getID()]); + return self::note_uri($notice->getID()); } else { + $uri = $notice->getUri(); + if (common_valid_http_url($uri)) { + return $uri; + } return $notice->getUrl(); }