bluesky_cliでコマンドラインから簡単にBluesky SocialのAPIを叩く
概要
こんにちは、真也です。
今日は私が開発保守しているCLIツールの「bluesky_cli」を紹介します。
Dart言語製のツールですが、一度インストールしてしまえばプラットフォームに依存せず実行が可能ですので、Bluesky SocialのAPIをコマンドラインから叩いてみたい方は是非使ってみてください。
そもそも「Bluesky Socialとは何?」という方は、以下の記事を参考にしてください。簡単に説明すると、Twitterと瓜二つの分散型SNSです。
前提
先にも簡単に触れましたが、今回紹介するbluesky_cliをインストールするためには、まずDart言語がPCにインストールされている必要があります。
Dart言語のインストールについては任意の方法でしていただいて構いませんが、以下のようにHomebrewのコマンドを使用すると簡単にインストールできます。
brew install dart-sdk
または、以下のようなWebページを参考にしてください。
bluesky_cliのインストール
Dart言語だけインストールできたら、bluesky_cliをインストールするのはとても簡単です。
次のコマンドを任意のディレクトリで実行してください。
dart pub global activate bluesky_cli
以下のような出力を確認できれば成功です。
katoshinya@Katos-MacBook-Pro ~ % dart pub global activate bluesky_cli
+ ansi_styles 0.3.2+1s... (1.0s)
+ args 2.4.0
+ async 2.11.0
+ at_identifier 0.0.3
+ at_uri 0.0.3
+ bluesky_cli 0.0.5
+ cli_launcher 0.3.1
+ cli_util 0.3.5 (0.4.0 available)
+ collection 1.17.1
+ freezed_annotation 2.2.0
+ http 0.13.5
+ http_parser 4.0.2
+ json_annotation 4.8.0
+ meta 1.9.1
+ nsid 0.0.3
+ path 1.8.3
+ source_span 1.9.1
+ string_scanner 1.2.0
+ term_glyph 1.2.1
+ typed_data 1.3.1
+ xrpc 0.0.6
+ yaml 3.1.1
Building package executables... (1.0s)
Built bluesky_cli:bsky.
Installed executable bsky.
Activated bluesky_cli 0.0.5.
dart pub global activate
でインストールされたDartプログラムはインストールした際にコンパイルされるため、起動がとても速くプラットフォームに依存せず実行が可能です。
bluesky_cliを使ってみる
bluesky_cliがインストールできたら、実際に使ってみましょう。
サポートしているコマンド一覧
まず、bluesky_cliでサポートしているコマンドは以下のとおりです。
以下の表を見ていただければわかるのですが、既にほぼ全てのエンドポイントをサポートしています。
Usage: bsky <command> [arguments]
Global options:
-h, --help Print this usage information.
--identifier Handle or email address for authentication.
(defaults to environment variable "BLUESKY_IDENTIFIER")
--password Bluesky password for authentication.
(defaults to environment variable "BLUESKY_PASSWORD")
--service Name of the service sending the request. Defaults to "bsky.social".
--pretty Enable to output JSON in pretty format.
--status Enable to output status code and reason phrase.
--request Enable to output request method and URI.
--verbose Enable verbose logging.
Available commands:
actors-typeahead Show the typeahead for actors.
delete Delete a specific contents from repository.
feed Show the feed of specific actor.
follow Follow an user.
followers Show the followers.
follows Show the following users.
like Like a specific post.
likes Show the likes of specific post.
mute Mute an user.
mutes Show the muted users.
notification-count Show the count of notification of authenticated user.
notifications Show the notifications of authenticated user.
popular Show the popular contents.
post Post to Bluesky Social.
profile Show the profile of specific user.
profiles Show the profiles of specific users.
repost Repost a specific post.
reposted-by Show the actors reposted specific post.
search-actors Search the actors based on term.
seen-notifications Update all notifications to read.
suggestions Show the actor suggestions.
thread Show the thread of specific post.
timeline Show the timeline of authenticated user.
unmute Unmute an user.
Run "bsky help <command>" for more information about a command.
認証情報の設定
Bluesky SocialのAPIを使用するためには認証情報の設定が必要です。
例えば以下のように実行するコマンドに認証情報を渡すことができます。
bsky timeline --identifier=shinyakato.dev --pasword=xxxxxxxx
Bluesky SocialではまだOAuth認証がサポートされていないため、現在使用できる認証情報はBluesky Socialへログインする際のハンドルまたはメールアドレスとパスワードです。ハンドルまたはメールアドレスをidentifier
オプションに設定し、パスワードはpassword
オプションに設定してください。
ただ、コマンドを叩くたびに認証情報を渡すのは面倒ですよね?
そんな方のためにbluesky_cliでは環境変数から認証情報を渡せる仕組みを提供しています。以下の環境変数に認証情報を設定してください。
環境変数 | 対応するオプション |
---|---|
BLUESKY_IDENTIFIER | identifier |
BLUESKY_PASSWORD | password |
例えば.zprofile
だと次のように環境変数を設定します。
export BLUESKY_IDENTIFIER=shinyakato.dev
export BLUESKY_PASSWORD=xxxxxxxx
上記の環境変数が反映されると、次のようにコマンドを実行することができます。
bsky timeline
簡単ですね。
ポストを投稿してみる
Bluesky Socialへポストを投稿するためには、post
コマンドを使用できます。
bsky post --text="Hello, Bluesky"
通信が成功すると以下のようにレスポンス情報が出力されます。
{"uri":"at://did:plc:iijrtk7ocored6zuziwmqq3c/app.bsky.feed.post/3jsjhoencus2n","cid":"bafyreibithakaywd6irbdx3oonf3xo367rds2gdwyhpqk6tzugyvvdpiru"}
投稿したポストを削除してみる
先に投稿したポストを削除してみましょう。
ポストの削除を行うためにはdelete
コマンドを使用できます。必須オプションのuri
には、先にポストを投稿した際に取得したレスポンスに設定されたuri
フィールドの値を設定してください。例えば、先の例だとat://did:plc:iijrtk7ocored6zuziwmqq3c/app.bsky.feed.post/3jsjhoencus2n
です。
bsky delete --uri=at://did:plc:iijrtk7ocored6zuziwmqq3c/app.bsky.feed.post/3jsjhoencus2n
また、今回は投稿したポストの削除をするためにdelete
コマンドを使用しましたが、ポストの他にもlike
コマンドやrepost
コマンドで作成したLikeやRepostもこのdelete
コマンドで同じように削除できます。なぜこれらのコンテンツをURIだけで判別できるかというと、URI中にコンテンツの発生源があるためです。
例えば、先に使用したURIであるat://did:plc:iijrtk7ocored6zuziwmqq3c/app.bsky.feed.post/3jsjhoencus2n
には、app.bsky.feed.post
というコレクションの中の3jsjhoencus2n
というIDに紐づくデータという情報があります。Likeであればこのコレクション名がapp.bsky.feed.like
になり、Repostであればapp.bsky.feed.repost
といったような感じです。
こうした共通的な規格があるため、特定のコンテンツを削除する際には基本的にdelete
コマンドにURIを渡すだけで可能です。
タイムラインを取得してみる
Bluesky Socialのタイムラインを取得するためには、timeline
コマンドを使用できます。
timeline
コマンドは追加のオプション無しでも使用できるのですが、データ量が多いため今回はlimit
オプションを使用して実行してみます。
bsky timeline --limit=2
{"feed":[{"post":{"uri":"at://did:plc:vnzkv2glj4v4d6afdnw2fhzj/app.bsky.feed.post/3jsjhqjwpvs2n","cid":"bafyreibeypqge5ododmi6re25rsr7hhpicippe5uu2nnacl4ewoh7zoj3m","author":{"did":"did:plc:vnzkv2glj4v4d6afdnw2fhzj","handle":"alexmedick.com","displayName":"Alex Medick","avatar":"https://cdn.bsky.social/imgproxy/8gYBe18Nk9nAjRZ_Hr4D-PaTIHSqQcFRHJX9fZCPXZo/rs:fill:1000:1000:1:0/plain/bafkreih32nsm5znowuax4xxoip4xqotlyurid4zmqic672rb4e3thr5yvu@jpeg","viewer":{"muted":false,"following":"at://did:plc:iijrtk7ocored6zuziwmqq3c/app.bsky.graph.follow/3jrkseh7mdk22"}},"record":{"text":"peace, love, and punk rock 🤙","$type":"app.bsky.feed.post","createdAt":"2023-04-04T04:51:16.609Z"},"replyCount":0,"repostCount":0,"likeCount":0,"indexedAt":"2023-04-04T04:51:16.827Z","viewer":{}}},{"post":{"uri":"at://did:plc:j5jithq57v6uw5hctknexohb/app.bsky.feed.post/3jsjhppdwd22y","cid":"bafyreie6jrc5fj3ajbjkrmk3ykwuis64vizyvle6c7jewxgorl43gm5msa","author":{"did":"did:plc:j5jithq57v6uw5hctknexohb","handle":"jojo.bsky.social","displayName":"ジョジョ","avatar":"https://cdn.bsky.social/imgproxy/wjqT1Wi1utlX8hwKu2UqHaun90cS_ObMImzZm7Ei38s/rs:fill:1000:1000:1:0/plain/bafkreieomnqie5uwzkasmosrnfeypjlhrxsca66tzi4rqeiilq3vw3d5lu@jpeg","viewer":{"muted":false,"following":"at://did:plc:iijrtk7ocored6zuziwmqq3c/app.bsky.graph.follow/3jrkwk2xsec2o","followedBy":"at://did:plc:j5jithq57v6uw5hctknexohb/app.bsky.graph.follow/3jrkw3eaf2s2d"}},"record":{"text":"今日の午後に期末評価のミーティングがあるけどまだ何の準備もしてない。ドイツ人並みにアピールすんの苦手だから嫌なんだよなー。","$type":"app.bsky.feed.post","createdAt":"2023-04-04T04:50:48.845Z"},"replyCount":0,"repostCount":0,"likeCount":0,"indexedAt":"2023-04-04T04:50:48.948Z","viewer":{}}}],"cursor":"1680583848948::bafyreie6jrc5fj3ajbjkrmk3ykwuis64vizyvle6c7jewxgorl43gm5msa"}
また、timeline
コマンドのようにlimit
オプションを指定できるエンドポイントでは、cursor
オプションを使用することでページングが可能です。上記のtimeline
コマンドのレスポンスを見ていただくと"cursor"
フィールドがあると思いますが、このフィールドの値を次のように使用します。
bsky timeline --limit=2 --cursor=1680583848948::bafyreie6jrc5fj3ajbjkrmk3ykwuis64vizyvle6c7jewxgorl43gm5msa
そうすると、先のページに続くタイムラインを取得できます。
{"feed":[{"post":{"uri":"at://did:plc:srdu2w3qc3aqh2ovez4rvql4/app.bsky.feed.post/3jsjhxbttpc2x","cid":"bafyreianxuwohpvmyap5tlak5w5e6kiqn6mlrbllib6idrxzxbhepawdri","author":{"did":"did:plc:srdu2w3qc3aqh2ovez4rvql4","handle":"blackrabbit.bsky.social","displayName":"inle","avatar":"https://cdn.bsky.social/imgproxy/NC5qYA2ka8AktHS2TwtXwZvNRPsdJ0H0_V9_S9XzcmQ/rs:fill:1000:1000:1:0/plain/bafkreia2dv3zqlbbkiudzl6hdd3lxvbmmg3pmsejng4hp3ncx2xsjm24ca@jpeg","viewer":{"muted":false,"following":"at://did:plc:iijrtk7ocored6zuziwmqq3c/app.bsky.graph.follow/3jrmr7manvk2r"}},"record":{"text":"이제 인용도 됩니다!","$type":"app.bsky.feed.post","embed":{"$type":"app.bsky.embed.record","record":{"cid":"bafyreiem2wuafijlgzue3s7mqqz6mwlxtxszopuoinzuv32wdjgjom5awu","uri":"at://did:plc:m3ypzsr5qa7z3adodk4hp7f2/app.bsky.feed.post/3jsjgsaj2kc27"}},"createdAt":"2023-04-04T04:55:02.805Z"},"embed":{"$type":"app.bsky.embed.record#view","record":{"$type":"app.bsky.embed.record#viewRecord","uri":"at://did:plc:m3ypzsr5qa7z3adodk4hp7f2/app.bsky.feed.post/3jsjgsaj2kc27","cid":"bafyreiem2wuafijlgzue3s7mqqz6mwlxtxszopuoinzuv32wdjgjom5awu","author":{"did":"did:plc:m3ypzsr5qa7z3adodk4hp7f2","handle":"iksalkkun.bsky.social","displayName":"익살꾼","avatar":"https://cdn.bsky.social/imgproxy/736xpp9qcqpPA_Di2sTc14x-WqXRyKelSvrKGDkAwGg/rs:fill:1000:1000:1:0/plain/bafkreibrofta34acszjvscsnscdyb5j5z4ndiauifgiom7dkm7sof4wcxm@jpeg","viewer":{"muted":false,"following":"at://did:plc:iijrtk7ocored6zuziwmqq3c/app.bsky.graph.follow/3jrmr7lb35s22","followedBy":"at://did:plc:m3ypzsr5qa7z3adodk4hp7f2/app.bsky.graph.follow/3jsjgkpd3ws27"}},"value":{"text":"검색이 완전 잘 되진 않네 근데 검색 있으니까 완전 트위터다","$type":"app.bsky.feed.post","createdAt":"2023-04-04T04:34:20.161Z"},"embeds":[],"indexedAt":"2023-04-04T04:34:20.309Z"}},"replyCount":0,"repostCount":0,"likeCount":0,"indexedAt":"2023-04-04T04:55:03.225Z","viewer":{}}},{"post":{"uri":"at://did:plc:vok247eewjmbmo3kxaizct2i/app.bsky.feed.post/3jsjhwizhrs2x","cid":"bafyreicvlbwjjxedc4j7iffnad5macs3vlqmxcvwworpoik2ctepquwsru","author":{"did":"did:plc:vok247eewjmbmo3kxaizct2i","handle":"baiser.bsky.social","displayName":"baiser","avatar":"https://cdn.bsky.social/imgproxy/FUFsResb2OivchlouMCXu-41-kRZlN2MhMLPt1n4NI4/rs:fill:1000:1000:1:0/plain/bafkreicrwuidebqva6wpm6sfc6ie4ajywbbjxr6ti27im7wrbiybck4xtm@jpeg","viewer":{"muted":false,"following":"at://did:plc:iijrtk7ocored6zuziwmqq3c/app.bsky.graph.follow/3jqk6a7hyik2s","followedBy":"at://did:plc:vok247eewjmbmo3kxaizct2i/app.bsky.graph.follow/3jqk72ccmns2y"}},"record":{"text":"The Blueからいろいろしてみています。ログアウトはどこでするのかな?⭐︎","$type":"app.bsky.feed.post","createdAt":"2023-04-04T04:54:36.257Z"},"replyCount":0,"repostCount":0,"likeCount":0,"indexedAt":"2023-04-04T04:54:37.195Z","viewer":{}}}],"cursor":"1680584077195::bafyreicvlbwjjxedc4j7iffnad5macs3vlqmxcvwworpoik2ctepquwsru"}
レスポンスを整形する
コマンドを実行した際に出力されるJSONを整形した状態で出力することもできます。
以下のようにpretty
オプションを指定してください。
bsky profile --actor=shinyakato.dev --pretty
{
"did": "did:plc:iijrtk7ocored6zuziwmqq3c",
"handle": "shinyakato.dev",
"displayName": "Shinya Kato 🤯",
"description": "Dart/Flutter & atproto enthusiast\nContrib. bluesky-social/atproto\n\nThe author of many OSS packages for Dart/Flutter\n\nDeveloping Bluesky related packages 👇\nhttps://github.com/myConsciousness/atproto.dart\n\nGitHub: https://github.com/myConsciousness",
"avatar": "https://cdn.bsky.social/imgproxy/JF97YphLyIEWfq4KJNO_ZCYm9v_zNcRj7sSB8UZrRBw/rs:fill:1000:1000:1:0/plain/bafkreidqn4z6ocv5snxuqguarboozqdusam2tehccnu23yab7g2sgv64dq@jpeg",
"banner": "https://cdn.bsky.social/imgproxy/0ijMnNxGs3aYg9Xsb5YkfehBkZo2WRJReLgMtljXPM0/rs:fill:3000:1000:1:0/plain/bafkreiaz67sqpaacxjtbj7texvnz5tlnfpthman4kvciymxg2jc2vayd4m@jpeg",
"followsCount": 3252,
"followersCount": 410,
"postsCount": 805,
"indexedAt": "2023-03-25T14:57:25.791Z",
"viewer": {
"muted": false
}
}
ステータスコードとリクエストURLを表示する
初期状態では非表示になっていますが、オプションを指定することでレスポンスを取得した際のステータスコードや、送信したリクエストのURL情報などを表示することができます。
ステータスコードを表示するためにはstatus
オプションを、リクエストURLを表示するためにはrequest
オプションを指定してください。
bsky profile --actor=shinyakato.dev --status --request
200 OK
GET https://bsky.social/xrpc/app.bsky.actor.getProfile?actor=shinyakato.dev
{"did":"did:plc:iijrtk7ocored6zuziwmqq3c","handle":"shinyakato.dev","displayName":"Shinya Kato 🤯","description":"Dart/Flutter & atproto enthusiast\nContrib. bluesky-social/atproto\n\nThe author of many OSS packages for Dart/Flutter\n\nDeveloping Bluesky related packages 👇\nhttps://github.com/myConsciousness/atproto.dart\n\nGitHub: https://github.com/myConsciousness","avatar":"https://cdn.bsky.social/imgproxy/JF97YphLyIEWfq4KJNO_ZCYm9v_zNcRj7sSB8UZrRBw/rs:fill:1000:1000:1:0/plain/bafkreidqn4z6ocv5snxuqguarboozqdusam2tehccnu23yab7g2sgv64dq@jpeg","banner":"https://cdn.bsky.social/imgproxy/0ijMnNxGs3aYg9Xsb5YkfehBkZo2WRJReLgMtljXPM0/rs:fill:3000:1000:1:0/plain/bafkreiaz67sqpaacxjtbj7texvnz5tlnfpthman4kvciymxg2jc2vayd4m@jpeg","followsCount":3252,"followersCount":410,"postsCount":805,"indexedAt":"2023-03-25T14:57:25.791Z","viewer":{"muted":false}}
取得したレスポンスをファイルに出力する
これはbluesky_cliの機能ではないですが、以下のようにして取得したレスポンスをファイルに出力することができます。
bsky timeline > timeline.json
最後に
ここまで簡単に紹介してきましたが、bluesky_cliのインストール方法と使い方がわかったかと思います。Bluesky SocialのAPIをコマンドラインから叩いてみたい方は、是非使ってみてください!
また、Dart/Flutterで使用できるAT ProtocolやBluesky Social関連のパッケージを以下のリポジトリで開発していますので、興味のある方は覗いてみてください。もし役に立ったと感じた方はGitHubスターもお願いします、開発の励みになります!🙏
Discussion