Bluesky.bot

TypeScript でボットを作る

このガイドでは、公式の TypeScript SDK である @atproto/api を使って、Bluesky に投稿するボットを書きます。Node.js 20 以降で動作します。

1. アプリパスワードを作成する

ボットとして Bluesky にサインインし、「設定」→「プライバシーとセキュリティ」→「アプリパスワード」 を開いて作成します。ボットはアカウントのメインパスワードではなく、必ずアプリパスワードでサインインします。アプリパスワードなら、アカウントに手を付けずにいつでも取り消せます。

2. プロジェクトを準備する

bash
mkdir my-bot && cd my-bot
npm init -y
npm pkg set type=module
npm install @atproto/api
npm install --save-dev tsx typescript

認証情報はコードに書かず、環境変数に置きます。

bash
export BLUESKY_HANDLE="weather.bluesky.bot"
export BLUESKY_APP_PASSWORD="xxxx-xxxx-xxxx-xxxx"

3. ボットを書く

bot.ts
// bot.ts: ボットとして 1 回投稿します。`npx tsx bot.ts` で実行します。
import { AtpAgent, RichText } from "@atproto/api";

// ボット自身のアカウントに、アプリパスワードでサインインします
// (「設定」>「プライバシーとセキュリティ」>「アプリパスワード」)。
// メインパスワードは決して使いません。
const identifier = process.env.BLUESKY_HANDLE ?? "";
const password = process.env.BLUESKY_APP_PASSWORD ?? "";
if (!identifier || !password) {
  throw new Error("Set BLUESKY_HANDLE and BLUESKY_APP_PASSWORD.");
}

const agent = new AtpAgent({ service: "https://bsky.social" });
await agent.login({ identifier, password });

// RichText がリンク、メンション、ハッシュタグを見つけてクリックできるようにします。
const text = new RichText({
  text: "Today: sunny, 21°C. Forecast at https://example.com #weather",
});
await text.detectFacets(agent);

const { uri } = await agent.post({
  text: text.text,
  facets: text.facets,
  createdAt: new Date().toISOString(),
});
console.log(`Posted ${uri}`);

このコードがしていること:

  • AtpAgent は、Bluesky がホストするアカウントのサーバー https://bsky.social と通信します。ボットが別のサーバー(セルフホストの PDS)にある場合は、そのサーバーの URL を指定します。
  • login は、ハンドルとアプリパスワードでセッションを開きます。
  • RichText と detectFacets は、リンクと #weather をクリックできる facet に変換します。ただの text では、普通の文字として表示されてしまいます。
  • post は投稿を作成し、その at:// URI を返します。

4. 実行する

bash
npx tsx bot.ts

対処しておきたいエラー

  • レート制限: アカウントやサーバーの操作が多すぎると、Bluesky は 429 を返します。間隔を空けて、あとで再試行してください。ベストプラクティス も参照してください。
  • 認証情報の期限切れ: アプリパスワードを取り消すと login が失敗します。新しいアプリパスワードを作成してください。
  • 長すぎる投稿: 投稿は 300 文字(書記素)までです。長い文章は短くするか、スレッドにして投稿します。

次のステップ