Pythonライブラリを使って試す。
成果物
前回まで
- BlueSky @ytyaru
- SNSサービスBlueSkyに登録してみた
- BlueSkyの投稿をダウンロードしたらCARという謎のファイル形式だった
- ラズパイ4B bookworm Go言語 インストール v1.24.5
- BlueSkyのCARファイルをgoskyコマンドで展開した
- BlueSkyのCARに含まれた画像ファイルを取得する方法が示された資料を探す
- BlueSkyのCARに含まれた画像ファイルを取得する(cookbook/go-repo-exportをインストールする)
必要なもの
- BlueSkyアカウント
- ハンドル:
ytyaru.bsky.social
- アプリ用パスワード:
(以下手順で作成する)
- DID:
ytyaru.bsky.social
- ハンドル:
- Python
- 仮想環境
atproto
ライブラリ
- 仮想環境
アプリ用パスワードを生成する
- BlueSkyにアクセスする
設定
→プライバシーとセキュリティ
→アプリパスワード
→アプリパスワードを追加
- 固有名を入力せず
次へ
- アプリパスワードをコピーしてどこかにメモる
このアプリパスワードに固有の名前を入力するか、ランダムに生成された名前を使用してください。 ☑ダイレクトメッセージへのアクセスを許可
ダイレクトメッセージへのアクセスを許可は必要ないと思うけど一応。
アプリパスワードをお知らせします! ハンドルと一緒にこのパスワードを使用して、他のアプリにサインインします。 セキュリティ上の理由から、これを再度表示することはできません。このアプリパスワードを紛失した場合は、新しいものを生成する必要があります。
パスワードはメモること!
情報源
CURL, Python, TypeScript, Dart, Goで実行可能らしい。JavaScriptは?
Pythonライブラリ
インストール
pip(エラー)
Docs get-startedの最初にある以下コマンドを入力したがエラー。
$ pip install atproto error: externally-managed-environment
ラズパイ4B bookworm 2025-05-13版では pip
で何かをインストールしようとすると上記エラーが出る。
なので次のような対処をする必要がある。(めんどくさい)
- インストール対象がコマンドアプリのときは
pipx
でインストールする - インストール対象がPythonライブラリのときは仮想環境を作ってインストールする
今回はPythonライブラリをインストールするので後者を選択する。
仮想環境
作成
python -m venv blueskyposttest
アクティベート
cd blueskyposttest/bin chmod +x activate ./activate
仮想環境ディレクトリのbin/
配下にあるactivate
コマンドを実行することで、仮想環境を有効化する。
なぜか実行権限がついていなかったので、chmod
コマンドで付与してから実行した。
仮想環境がアクティベートされると、端末の行頭にアクティベートされた仮想環境の名前が出てくる。
(blueskyposttest) pi@raspberrypi:/tmp/work/blueskyposttest/bin $
ディアクティベート
無効化するのは以下コマンド。
deactivate
pip
仮想環境をアクティベートした状態でpip
を実行する。
(blueskyposttest) pi@raspberrypi:/tmp/work/blueskyposttest/bin $ pip install atproto
インストールできた!
依存関係
パッケージの依存関係をファイルに出力しておく。すると後から一括でインストールできて便利。
書き出し
pip freeze > requirements.txt
現在インストールされているパッケージの一覧をファイル出力する。
インストール
pip install -r requirements.txt
所定のファイルに記録されたパッケージ一覧を全てインストールする。
テストコードを書く
最小
from atproto import Client client = Client() client.login('ハンドル', 'パスワード')
リッチ・テキスト
atproto_client.utils.TextBuilderを見るとメンションなどの機能を使える。
関数 | 用途 | 引数 |
---|---|---|
text |
通常テキスト | 投稿テキスト |
tag |
ハッシュタグ | 表記テキスト, ハッシュタグ値 |
mention |
メンション(特定ユーザ) | 表記テキスト, DID(分散ID) |
link |
URL(任意テキスト表記) | 表記テキスト, URL |
特にURLを任意テキストにできるのは嬉しい。
でもこれ、文字数制限ってどうなるの?
- 表記テキストの長さでカウント
- URLの長さでカウント
- 両方の長さでカウント
わからんけど、多分両方だろう。
main.py
#!/usr/bin/env python3 import sys from atproto import Client, client_utils def main(handle, password) -> None: client = Client(base_url='https://bsky.social') client.login(handle, password) text_builder = client_utils.TextBuilder() text_builder.text('APIで投稿してみる。\n改行確認。\n\nPythonライブラリatprotoで実行した。\n\n') text_builder.text('タグの挿入。実際の値はblueskyだが以下別の表記にしてみた。\n') text_builder.tag('#ブルスカ', 'bluesky') text_builder.text(' ') text_builder.text('\nハッシュ記号のないタグも挿入できるか試す。\n') text_builder.text(' ') text_builder.tag('BlueSky', 'bluesky') text_builder.text(' \n\n') text_builder.mention('私自身へのメンション', 'did:plc:ffttrlkbljhdeoypveptm4sj') text_builder.text(' ') text_builder.link('私のはてなブログ', 'https://ytyaru.hatenablog.com/') text_builder.text('へのリンク。通常はURL文字列だが任意テキストで表示されたはず。') client.send_post(text_builder) if __name__ == '__main__': if len(sys.argv) < 3: print("Error: BlueSkyユーザのハンドルとパスワードを引数に渡してください。", file=sys.stderr) sys.exit(1) main(sys.argv[1], sys.argv[2])
実行
BS_HANDLE=ytyaru.bsky.social BS_PASSWORD=アプリ用パスワード $ ./main.py "$BS_HANDLE" "$BS_PASSWORD"
結果
APIで投稿してみる。 改行確認。 Pythonライブラリatprotoで実行した。 タグの挿入。実際の値はblueskyだが以下別の表記にしてみた。 #ブルスカ ハッシュ記号のないタグも挿入できるか試す。 BlueSky 私自身へのメンション 私のはてなブログへのリンク。通常はURL文字列だが任意テキストで表示されたはず。
— ytyaru (@ytyaru.bsky.social) 2025年8月4日 16:36
おまけ
自分のDIDが必要ならclient.get_profile
(client.me.handle)
関数で取得できる。
... # DID取得するため profile = client.get_profile(client.me.handle) print(f'DID:{profile.did}') ... text_builder.mention('私自身へのメンション', profile.did) # 'did:plc:ffttrlkbljhdeoypveptm4sj'
所感
あとは連携を考えたい所。
- クライアントの自作
- 予約投稿(指定日時になったら所定の内容を投稿する)
- webhook連携(GitHubにプッシュが来たらその情報をBlueSkyで投稿する等)
以下が参考になりそう。
残念なことに「はてなブログ」はBlueSkyと連携できない。BlueSkyと連携できるようにして欲しいなー。はてなブログで投稿したらBlueSkyにも自動投稿されるようにして欲しいなぁ。
はてなwebhookはあるけど、有料なんだよなぁ。無料ユーザにも開放して欲しいなぁ。|д゚)チラッ