Bluesky API と Google Apps Script (GAS) でポストを投稿・取得・削除する
1. はじめに
2024年02月06日、Bluesky の招待制度を解除されたので、筆者もアカウントを作成しました。新しいサービスを使い始めたら、まずは API 周りを調査しないといけません。本記事では、 Bluesky API について調査した結果と、Bluesky API を GAS で叩いて遊んだ結果をまとめたものになります。Bluesky API に関しては公式ドキュメント 1 が公開されているので、詳しい仕様については、そちらを参照ください。
2. ポストを投稿する
Bluesky API 経由でポストを投稿する方法は簡単で、com.atproto.server.createSession
を叩いて認証セッションを作成して、com.atproto.repo.createRecord
を叩いてポストを投稿します。
以下のサンプルコードを実行する際は、[USER_IDENTIFIER]
と [APP_PASSWORD]
を変更した後、main
関数を実行します。[USER_IDENTIFIER]
は、登録済みのメールアドレスまたは Handle (xxx.bsky.social) を設定してください。また、[APP_PASSWORD]
にアカウント登録時のパスワードを設定するのは非推奨です。
1function main() {2 createRecord('テストポスト')3}4
5// https://www.docs.bsky.app/docs/api/com-atproto-server-create-session6function createSession() {7 const url = 'https://bsky.social/xrpc/com.atproto.server.createSession'8
9 const payload = {10 identifier: '[USER_IDENTIFIER]',11 password: '[APP_PASSWORD]',12 }13
14 const options = {15 method: 'post',16 headers: {17 'Content-Type': 'application/json; charset=UTF-8',18 },19 payload: JSON.stringify(payload),20 }21
22 const response = UrlFetchApp.fetch(url, options)23 return JSON.parse(response.getContentText())24}25
26// https://www.docs.bsky.app/docs/api/com-atproto-repo-create-record27function createRecord(msg) {28 const url = 'https://bsky.social/xrpc/com.atproto.repo.createRecord'29
30 const payload = {31 repo: createSession().handle,32 collection: 'app.bsky.feed.post',33 record: {34 text: msg,35 createdAt: new Date().toISOString(),36 },37 }38
39 const options = {40 method: 'post',41 headers: {42 'Content-Type': 'application/json',43 Authorization: 'Bearer ' + createSession().accessJwt,44 },45 payload: JSON.stringify(payload),46 }47
48 UrlFetchApp.fetch(url, options)49}
3. 自分のポストを取得する
Bluesky API 経由で自分のポストを取得する方法は簡単で、com.atproto.server.createSession
を叩いて認証セッションを作成して、app.bsky.feed.getAuthorFeed
を叩いて自分のポストを取得します。デフォルトでは最新のポスト、50 件が取得される仕様です。取得件数を変動させたり古いポストを取得するには、limit
や cursor
を変更します。詳しくは公式のドキュメントを参照ください。
以下のサンプルコードを実行する際は、[USER_IDENTIFIER]
と [APP_PASSWORD]
を変更した後、main
関数を実行します。[USER_IDENTIFIER]
は、登録済みのメールアドレスまたは Handle (xxx.bsky.social) を設定してください。また、[APP_PASSWORD]
にアカウント登録時のパスワードを設定するのは非推奨です。
1function main() {2 getAuthorFeed().feed.map((x) => console.log(x))3}4
5// https://www.docs.bsky.app/docs/api/com-atproto-server-create-session6function createSession() {7 const url = 'https://bsky.social/xrpc/com.atproto.server.createSession'8
9 const payload = {10 identifier: '[USER_IDENTIFIER]',11 password: '[APP_PASSWORD]',12 }13
14 const options = {15 method: 'post',16 headers: {17 'Content-Type': 'application/json; charset=UTF-8',18 },19 payload: JSON.stringify(payload),20 }21
22 const response = UrlFetchApp.fetch(url, options)23 return JSON.parse(response.getContentText())24}25
26// https://www.docs.bsky.app/docs/api/app-bsky-feed-get-author-feed27function getAuthorFeed() {28 const url = `https://bsky.social/xrpc/app.bsky.feed.getAuthorFeed?actor=${createSession().handle}`29
30 const options = {31 method: 'GET',32 headers: {33 Authorization: 'Bearer ' + createSession().accessJwt,34 },35 }36
37 const response = UrlFetchApp.fetch(url, options)38 return JSON.parse(response.getContentText())39}
4. 自分のポストを削除する
Bluesky API 経由で自分のポストを削除する場合、ポストの Record Key
を取得する必要があります。Record Key は、Bluesky の Web クライアントで確認することが出来ます。任意のポストを Bluesky の Web クライアントで表示させると、URL として https://bsky.app/profile/xxx.bsky.social/post/3kksx5ddx6d24 などと表示されます。この 3kksx5ddx6d24
が Record Key にあたります。
以下のサンプルコードは、上記で示した getAuthorFeed 関数を利用して、最新ポストの Record Key を取得し、削除するものです。正常に実行されると、自分の最新ポストが削除されるので注意してください。
以下のサンプルコードを実行する際は、[USER_IDENTIFIER]
と [APP_PASSWORD]
を変更した後、main
関数を実行します。[USER_IDENTIFIER]
は、登録済みのメールアドレスまたは Handle (xxx.bsky.social) を設定してください。また、[APP_PASSWORD]
にアカウント登録時のパスワードを設定するのは非推奨です。
1function main() {2 const rkey = getAuthorFeed().feed.shift().post.uri.split('/').pop()3 deleteRecord(rkey)4}5
6// https://www.docs.bsky.app/docs/api/com-atproto-server-create-session7function createSession() {8 const url = 'https://bsky.social/xrpc/com.atproto.server.createSession'9
10 const payload = {11 identifier: '[USER_IDENTIFIER]',12 password: '[APP_PASSWORD]',13 }14
15 const options = {16 method: 'post',17 headers: {18 'Content-Type': 'application/json; charset=UTF-8',19 },20 payload: JSON.stringify(payload),21 }22
23 const response = UrlFetchApp.fetch(url, options)24 return JSON.parse(response.getContentText())25}26
27// https://www.docs.bsky.app/docs/api/app-bsky-feed-get-author-feed28function getAuthorFeed() {29 const url = `https://bsky.social/xrpc/app.bsky.feed.getAuthorFeed?actor=${createSession().handle}`30
31 const options = {32 method: 'GET',33 headers: {34 Authorization: 'Bearer ' + createSession().accessJwt,35 },36 }37
38 const response = UrlFetchApp.fetch(url, options)39 return JSON.parse(response.getContentText())40}41
42// https://www.docs.bsky.app/docs/api/com-atproto-repo-delete-record43function deleteRecord(rkey) {44 const url = 'https://bsky.social/xrpc/com.atproto.repo.deleteRecord'45
46 const payload = {47 repo: createSession().handle,48 collection: 'app.bsky.feed.post',49 rkey: rkey,50 }51
52 const options = {53 method: 'post',54 headers: {55 'Content-Type': 'application/json',56 Authorization: 'Bearer ' + createSession().accessJwt,57 },58 payload: JSON.stringify(payload),59 }60
61 UrlFetchApp.fetch(url, options)62}
5. おわりに
執筆時点では、招待制度を解除されてユーザーが増えた影響か、結構 API の使用制限 (RateLimitExceeded) に引っかかります。一応、GitHub Discussions 2 では 3000 リクエスト / 5 分 に設定されているそうですが、一時的に厳しくなっている可能性もありますね。Bluesky 自体が開発途上なので、API 周りのおいおい整備されていくと思います。いつまで無料で遊べるかもわからないので、今のうちに遊んでおこうと思います。
-
Bluesky, Get Started:https://www.docs.bsky.app/docs/get-started ↩
-
GitHub Discussions, Are there rate limits for the API?:https://github.com/bluesky-social/atproto/discussions/697 ↩