🐧

ActivityPubに入門してみた

createdAt
2024-12-22
updatedAt
2024-12-24
reading time
5 min read

はじめに

これはFediverse Advent Calendar 2024の22日目の記事です

以前Activity Pubの初歩の初歩として簡単なチュートリアルをやっていました。 今回はその発展として、きちんとユーザのフォローなどをDBに記録するだけの簡単なサーバを書いたので、記録を残します。

リポジトリは以下にあります

https://github.com/tunamaguro/apub-lite

作ったモノの機能

現状実装できているのは、以下の3つだけです

  • 他サーバからアクターが見える
  • 他のサーバからのFollowAcceptできる
  • フォロワーにノートを送信できる

ObjectActionを一切記録していないので、作成されたNoteは相手方のサーバにしか保存されません

初歩から追加したところ

Follow周りの処理の実装

よそのActorからFollowされたとき、AcceptFollowしてきたActorのインボックスに投げる、 相手にフォローが承認されたことを伝えることができます。このあたりの流れはActivityPubまとめWikiと、 Matchboxを参考にしました。 言葉でもシンプルなので、実装も以下のようにとてもシンプルです

match kind {
InboxKinds::Follow(follow) => {
let follow_person = activity_service
.get_actor_by_url(follow.actor.as_ref())
.await?;
let follower_repo = registry.follower_repository();
follower_repo
.create(&user.id, &follow_person.actor_url)
.await?;
let accept = Accept::builder()
.actor(user.user_uri(&config))
.id(generate_activity_uri(&config).into())
.object(follow)
.context(Default::default())
.build();
activity_service
.post_activity(&accept, &follow_person.inbox, &signing_key, &user_key_id)
.await?;
tracing::info!(kind = "Accept", actor = %follow_person.actor_url, object = user.name);
}

Ref: https://github.com/tunamaguro/apub-lite/blob/410c94d95748b023a59a3b337ccf2e71bbff810f/crates/apub-api/src/handler/inbox.rs#L63-L82

この実装では、Followに対して何かしらレスポンスを返す前にAcceptを投げていますが、これでも一応問題ないみたいです

フォロワーへのノート配信

今回はシンプルな実装なのでDBからフォロワーの一覧を取得し、それぞれのインボックスに1つずつCreateを送信しています。 この際、自身が作成したことを証明するためHTTP Message Signatures(draft 15)による署名をして送る必要があります。 これは初歩の初歩でやったことと基本的に同じです。

(私が簡単に調べた限り)Mastodonは最新の仕様であるRFC9421に準拠していないため、少し古めの仕様を見て実装する必要がありました。 ただ、将来的にすべてのサーバが対応していけば、この古めの規格に従う必要はなくなるのではないかと思っています

実装してみた感想

RustによるWebアプリケーション開発を読んだので、何か動くものを実装してみたくなりこれに至りました。 パフォーマンスなどもろもろのことを見なかったことにすれば、実装自体は簡単なので練習にはちょうどよかったと思います。 また、ちょうどMastodonやMisskeyの裏で動いている仕組みが気になっていたので、それを何となく知れて良かったです。

一応NoteおよびCreateを保存するようにしたところで、これはおしまいにするつもりです。ただ、時間があればCloudflare Workerで動くようにするところまでやるかもしれません