自分用の投稿専用クライアントであるpostemとpost-tweetをそれぞれBlueskyに対応しました。

postem

それぞれ紹介記事を書いてありますが、多分自分しか使ってないとは思います。 ただ、投稿の8割ぐらいはこれ経由な気がするので、かなり使っているツールです。

JSer.infoの更新のためのデータを入れるのは、postemが99%ぐらいなので、ほぼ毎日使ってる感じです。

Blueskyの対応

Blueskyは、裏側の仕組みが違う見た目がTwitterみたいなサービスです。 またPrivate Betaですが、@s7tyaさんに招待コードをもらったので、アカウントを作っていじっています。

Twitterみたいなものなので、Twitterに投稿するときのリンク投稿用クライアントであるそれぞれもBlueskyに対応してみました。

両方ともクロスポストに対応してるので、TwitterとBlueskyどちらにも投稿できるようになっています。 両方とも自分しか使ってないと思うので、バイナリ配布をしてないですが、READMEを見て各自でビルドしてみてください。

BlueskyはAPIトークンがまだなく、App Passwordというアカウント削除とかができないようなパスワードを使ってAPIを叩くようになっています。将来的には、もっとちゃんとしたものを実装するそうです。

Today we’re shipping app passwords, a short-term solution for authentication that will let users experiment with new clients without having to fully trust them with their passwords. In the long term, we plan to implement SSO (Single Sign-On) with scoped permissions. https://blueskyweb.xyz/blog/4-21-2023-atproto-developer-ecosystem

そのため、それぞれのアプリようにApp Passwordを作成して設定する必要があります。

  1. Visit https://bsky.app/settings/app-passwords
  2. Create new App Password
  3. 次の設定を埋める

両方とも似たような設定になってるので、設定するjsファイルにuser idとappPasswordを入れてビルドすれば利用できます。

{
  enabled: true,
  name: "bluesky",
  indexPath: path.join(__dirname, "services/bluesky/index.js"),
  options: {
    // 1. Visit https://bsky.app/settings/app-passwords
    // 2. Create new App Password
    // 3. Fill the following fields
    username: "username.bsky.social",
    appPassword: "password"
  }
}

設定がちゃんとできて、ビルドできれば、あとは普通に投稿できます。

BlueskyのAPI

Bluesky APIで検索すると違うものがかかるので、AT Protocol APIで検索します。

JavaScriptの場合は、公式のAPIクライアントがあるので、これを利用するのが簡単です。

少しクセがあるポイントとして、単純にテキストを投稿しても自動的にURLがリンクになったり、OGPのカードが出てくれる分けじゃありません。 Rich textという仕組みがあり、リンクやmentionなどはこのRich textを使って表現されます。

テキストと位置情報をマッピングするJSONみたいな仕様になっていますが、@atproto/apiを使えば勝手にやってくれるので、これを使うことが推奨されています。

import { BskyAgent, RichText } from "@atproto/api";
const text = `投稿内容 https://example.com`;
const agent = new BskyAgent({
    service: "https://bsky.social"
});
await agent.login({
    identifier: this.serviceOptions.identifier,
    password: this.serviceOptions.appPassword
});
const rt = new RichText({ text });
await rt.detectFacets(agent); // automatically detects mentions and links
const postRecord = {
    $type: "app.bsky.feed.post",
    text: rt.text,
    facets: rt.facets,
    createdAt: new Date().toISOString()
};
return agent.post(postRecord);

Twitter Cardsみたいなことを投稿する側でやる必要があるそうです。

この辺はフィッシング的な問題が色々あってなんか変わりそうな気がするので、あんまり深くはみていません。

おわりに

Blueskyのアカウントを作ってみたので、とりあえず使ってるアプリを対応してみました。

BlueskyのAPIは公式のクライアントがあって、JSの場合はTypeScriptでちゃんと型がついてるので、facets周りの癖を除けば素直です。 App Passwordsは単なるパスワード認証なので、使うときもシンプルで個人用に作る時は楽です。

Twitterを使うとき結構APIに依存してて、APIの挙動がおかしかったり、Usageが限界を突破してたりでよくわからない感じになっています。

Twitter API Usage

Essentialが廃止になってプロジェクトに所属してないAPI Keyは動かなくなったり(これは仕様)、プロジェクトに所属してても動かないことがあったり色々よくわかない動きをしています。試すにも今はFreeだと一つのAppsしか登録できないので、試しにくかったりします。

バックアッププランとしてAPIが使いやすいBlueskyを試してみたという感じでした。