FeedFeedbackAPIってなんなんだー?

By えるたん (@l-tan.dolciss.net)
Published:

Blueskyのウワサ(クシュン)[^donald] [^donald]:ちょうど懐かしい動画を見たところでして……

はじめに

本記事はBluesky Advent Calendar 2025の4日目の記事です。

2024年5月ごろに実装されたFeedFeedbackAPIについて、当時書きかけたままサードパーティーへの開放を待っているうちに忘れていた記事を、出すなら今かということで空き枠に滑り込ませてもらいます。(1年以上間が空いているのでつじつま合わない所あったらすみません)

⏪3日目はすいばり(@suibari.com)さんの「Bluesky AI Bot「全肯定botたん」の2025年の軌跡」です

⏩5日目は桃色豆腐(@momoiro.me)さんの「公式pdsから引っ越して、公式pdsに戻ってみるまで試す」です

拙作の記事投稿についてのPostをまとめたカスタムフィード(by Bluefeed)もあります

これなに

Blueskyの公式アプリのバージョン1.81.0[^1.81.0]にて、カスタムフィードに対してのフィードバック"Show more like this(このような投稿の表示を増やす)🙂","Show less like this(このような投稿の表示を減らす)☹"が送信できるようになりました。[^feedback] [^1.81.0]: https://bsky.app/profile/bsky.app/post/3ks36igfly32h [^feedback]:後述しますが他にもフィードバックが送られています。

これは先日のProduct Roadmapにあった "New feedback mechanisms which the algorithmic feeds can request, such as “show more” and “show less” buttons, and a way to track which posts have been seen to stop duplicates from showing so often."によるもので、フィードバックによって表示される内容を変化させることができるようになるみたいです。

リリース内容にもありますが、この機能は1.81.0時点では公式のDiscoverフィードに対してのみ動作しますていました。ですが今後は他のカスタムフィードにも開放されるようなので、 その後1年の時を経て1.107.0[^1.107.0]、1.109.0[^1.109.0]にてサードパーティーのカスタムフィードに対しても開放されるようになりました。拙作のRepostNextPostにも対応しましたが、その際にGitHubのコードに潜って探索した記録を残しておこうと思います。 [^1.107.0]: https://bsky.app/profile/bsky.app/post/3lxxo3i5pck2c [^1.109.0]: https://bsky.app/profile/bsky.app/post/3m47grlweoc2a

スキーマ実装:atproto#2383

こちらはapp.bsky.feed.getFeedで取得されるPostに付加されるもののようです。(PDS→クライアント)

`` json "feedContext": { "type": "string", "description": "Context provided by feed generator that may be passed back alongside interactions.", "maxLength": 2000 } CODEBLOCK0 json "reqId": { "type": "string", "description": "Unique identifier per request that may be passed back alongside interactions.", "maxLength": 100 } CODEBLOCK1json "acceptsInteractions": { "type": "boolean" } CODEBLOCK2 json "feedContext": { "type": "string", "description": "Context that will be passed through to client and may be passed to feed generator back alongside interactions.", "maxLength": 2000 } CODEBLOCK3 json "interaction": { "type": "object", "properties": { "item": { "type": "string", "format": "at-uri" }, "event": { "type": "string", "knownValues": [ "app.bsky.feed.defs#requestLess", "app.bsky.feed.defs#requestMore", "app.bsky.feed.defs#clickthroughItem", "app.bsky.feed.defs#clickthroughAuthor", "app.bsky.feed.defs#clickthroughReposter", "app.bsky.feed.defs#clickthroughEmbed", "app.bsky.feed.defs#interactionSeen", "app.bsky.feed.defs#interactionLike", "app.bsky.feed.defs#interactionRepost", "app.bsky.feed.defs#interactionReply", "app.bsky.feed.defs#interactionQuote", "app.bsky.feed.defs#interactionShare" ] }, "feedContext": { "type": "string", "description": "Context on a feed item that was orginally supplied by the feed generator on getFeedSkeleton.", "maxLength": 2000 } "reqId": { "type": "string", "description": "Unique identifier per request that may be passed back alongside interactions.", "maxLength": 100 } } }, CODEBLOCK4 json "requestLess": { "type": "token", "description": "Request that less content like the given feed item be shown in the feed" }, CODEBLOCK5 json "requestMore": { "type": "token", "description": "Request that more content like the given feed item be shown in the feed" }, CODEBLOCK6 json "clickthroughItem": { "type": "token", "description": "User clicked through to the feed item" }, CODEBLOCK7 json "clickthroughAuthor": { "type": "token", "description": "User clicked through to the author of the feed item" }, CODEBLOCK8 json "clickthroughReposter": { "type": "token", "description": "User clicked through to the reposter of the feed item" }, CODEBLOCK9 json "clickthroughEmbed": { "type": "token", "description": "User clicked through to the embedded content of the feed item" }, CODEBLOCK10 json "interactionSeen": { "type": "token", "description": "Feed item was seen by user" }, CODEBLOCK11 json "interactionLike": { "type": "token", "description": "User liked the feed item" }, CODEBLOCK12 json "interactionRepost": { "type": "token", "description": "User reposted the feed item" }, CODEBLOCK13 json "interactionReply": { "type": "token", "description": "User replied to the feed item" }, CODEBLOCK14 json "interactionQuote": { "type": "token", "description": "User quoted the feed item" }, CODEBLOCK15 json "interactionShare": { "type": "token", "description": "User shared the feed item" } CODEBLOCK16json { ... "$type": "app.bsky.feed.generator", ... "acceptsInteractions": true } CODEBLOCK17json { "interactions": [ { "$type": "app.bsky.feed.defs#interaction", "item": "at://did:plc:xxxxxxxxxxxxxxxxxxxxxxxx/app.bsky.feed.post/xxxxxxxxxxxxx", "event": "app.bsky.feed.defs#xxxxxxxxxxx", "feedContext": "context", "reqId": "" }, ... ] CODEBLOCK18 json { "feed": [ "post": "at://did:plc:xxxxxxxxxxxxxxxxxxxxxxxx/app.bsky.feed.post/xxxxxxxxxxxxx", "feedContext": "context" ], "cursor": "xxxxxxxxxxx" } ``

さいごに

RepostNextPostではrequestLessで投稿を非表示、requestMoreで最後に非表示にした投稿を再表示という処理を入れましたが、 初のDiscoverフィードのように表示内容をいろいろカスタムに活用できるかと思いますので参考になれば幸いです。 それではみなさまよいBlueskyライフを!

(再掲) ⏩5日目は桃色豆腐(@momoiro.me)さんの「公式pdsから引っ越して、公式pdsに戻ってみるまで試す」です