Note
このドキュメントは2026-02-27 02:42にPLaMo Translation Modelを使用して自動翻訳されました。
FEP-9967: 投票機能
概要
ActivityPubネットワークにおける投票の実装方法について記述します。
履歴
Mastodonは2019年に投票機能を実装しました [参照][MastodonPollsドキュメント]。
ActivityStreams仕様では質問を表現するための推奨事項が定められていますが [https://www.w3.org/TR/activitystreams-vocabulary/#questions]、これらの推奨事項は実用的でないことが判明しており、実際の標準規格はこれとは異なるアプローチを採用しています。
要件
本文書中で使用される「MUST」「MUST NOT」「REQUIRED」「SHALL」「SHALL NOT」「SHOULD」「SHOULD NOT」「RECOMMENDED」「MAY」「OPTIONAL」の各用語は、RFC-2119で規定されている解釈に従うものとします。
概要図
sequenceDiagram
actor Alice
actor Bob
actor Charlie
Note right of Alice: Aliceが投票を公開します
Alice ->> Bob: Create(Question)
Alice ->> Charlie: Create(Question)
Note left of Bob: Bobが投票を行います
Bob ->> Alice: Create(Note)
Note right of Alice: Aliceは投票結果を受け取り、集計情報を更新します
Alice ->> Bob: Update(Question)
Alice ->> Charlie: Update(Question)
質問オブジェクトの定義
投票は「Question」オブジェクトとして表現されます。このオブジェクトは必ず「Create」アクティビティと共に公開されなければなりません ActivityStreams語彙とは異なり、Question自体が非遷移型アクティビティとして定義されている点に注意が必要です]。
通常、「Question」オブジェクトの構造は「Note」オブジェクトと類似しています。基本的なプロパティであるattributedToやcontentに加え、以下のいずれかを必ず含む必要があります:
oneOf: 単一選択式の投票が必要な場合anyOf: 複数選択式の投票が可能な場合
このプロパティの値は、投票オプションを表すオブジェクト配列でなければなりません:
type:Note型を示す文字列name: 投票選択肢のテキスト表現replies: 総投票数をコレクション形式で保持type:Collection型を示す文字列totalItems: 当該投票オプションに対する総投票数
投票選択肢のname値は同一投票内で一意である必要があります。もしテキストにカスタム絵文字が使用されている場合、対応するEmojiオブジェクトが「Question」オブジェクトのtag配列に追加されます。
投票選択肢の数は多くの場合制限が設けられますが、その上限値は実装によって異なります。
「Question」オブジェクトには「endTime」プロパティを任意で設定でき、これは投票終了時刻を示します。一部の実装では「closed」プロパティを「endTime」の代わりに、あるいはそれに加えて使用する場合があります(たとえ投票が継続中であっても)。消費者側では、「closed」プロパティは「endTime」と同様に処理する必要があります。
「Question」オブジェクトには「updated」プロパティを設定することが推奨されます。
具体例:
{
"@context": "https://www.w3.org/ns/activitystreams",
"id": "https://social.example/polls/1",
"type": "Question",
"attributedTo": "https://social.example/actors/1",
"to": "https://www.w3.org/ns/activitystreams#Public",
"content": "<p>質問内容</p>",
"endTime": "2024-07-17T18:18:17Z",
"updated": "2024-07-16T20:53:05Z",
"oneOf": [
{
"type": "Note",
"name": "回答1",
"replies": {
"type": "Collection",
"totalItems": 596
}
},
{
"type": "Note",
"name": "回答2",
"replies": {
"type": "Collection",
"totalItems": 379
}
}
]
}
投票処理
投票オブジェクトの構造
個々の投票は「Note」オブジェクトとして表現され、以下の構造を持ちます:
id: 当該投票の識別子type:Note型を示す文字列attributedTo: この投票を行ったアクターinReplyTo: 対応するQuestionオブジェクトのIDname: 選択された投票選択肢のnameプロパティ値to: 当該投票を作成した投稿者
このオブジェクトには「content」プロパティを含めてはなりません。
このオブジェクトは「Create」アクティビティでラップされ、投票作成者に送信されます。もし投票が匿名式の場合、このアクティビティは他のいかなるアクターにも配信されてはなりません。
複数選択が可能な場合、各投票はそれぞれ独立したアクティビティとして送信されなければなりません。
投票の具体例:
{
"@context": "https://www.w3.org/ns/activitystreams",
"id": "https://social.example/votes/1",
"type": "Note",
"attributedTo": "https://social.example/actors/2",
"inReplyTo": "https://social.example/polls/1",
"name": "回答1",
"to": "https://social.example/actors/1"
}
投票の受信処理
投票オブジェクトの構造は直接返信と極めて類似しています。nameプロパティとinReplyToプロパティを持つ「Note」として識別可能ですが、contentプロパティを含まない点が特徴です。
投票を受信した際、投票作成者は以下の検証を行います:
- 投票者が投票権限を有すること(公開投票でない場合)
- 当該投票がまだ有効であること(
endTimeが指定されている場合) - 指定された
idの投票が既に登録されていないこと - 指定された
nameの選択肢に対する投票が既に記録されていないこと(複数選択不可の場合)
これらのいずれかの検証に失敗した場合、その投票は無視されなければなりません。
それ以外の場合、投票作成者は該当する投票オプションの投票数を更新します(対応するrepliesコレクションのtotalItemsプロパティ値を変更)。また、この時点の日時に合わせて「updated」プロパティの値も更新されます。
結果公開処理
投票作成者が投票を受け取った際、「Question」オブジェクトを含む更新済み情報を記載した「Update」アクティビティを発行します。このアクティビティは当該投票の視聴者全員および全ての投票参加者アクターに配信されなければなりません。
選択肢の編集機能
投票の種類(単一選択/複数選択)やその選択肢は、いつでも変更可能です。その場合、投票作成者は必ず現在の投票数をリセットする必要があります。
今後の課題
本文書で説明している投票識別方法は信頼性に欠けます。なぜなら、返信メッセージが一見して投票と区別がつかない可能性があるためです。代替表現方式として「Respond」アクティビティなどの検討が進められています FEP-9098。
実装状況
本仕様は、MastodonおよびPleromaにおける投票機能の実装に基づいています。
参考文献
- Christine Lemmer-Webber, Jessica Tallon, Erin Shepherd, Amy Guy, Evan Prodromou, ActivityPub, 2018
- James M Snell, Evan Prodromou, Activity Vocabulary, 2017
- S. Bradner, RFCで要件レベルを示すためのキーワードの使用法, 1997
- Mastodon開発チーム, 投票機能
- silverpill, FEP-9098: カスタム絵文字, 2025
著作権
CC0 1.0 Universal(パブリックドメイン献呈)
法律で認められる範囲内において、本Fediverse Enhancement Proposalの著者らは、当該著作物に関するすべての著作権および関連権利を放棄しています。