メインコンテンツへスキップ

概要

Bluesky Facade は BlueskyManager の薄いラッパーです。BlueskyManager は複数の Agent を管理し、HasShortHand トレイトが頻繁に使うメソッドのショートカットをまとめて提供します。

アーキテクチャ

BlueskyServiceProviderFactory::classBlueskyManager としてスコープ付きシングルトン(1リクエストにつき1インスタンス)で登録します。
// BlueskyServiceProvider::register()
$this->app->scoped(Factory::class, BlueskyManager::class);
Facade の getFacadeAccessor() がこのバインディングを解決します。
// Facades/Bluesky.php
protected static function getFacadeAccessor(): string
{
    return Factory::class;
}

BlueskyManager のコアメソッド

BlueskyManager 自身が定義するコアメソッドは以下のとおりです。HasShortHand トレイトのメソッドとは区別して把握しておくと、内部構造の理解に役立ちます。

認証

メソッド説明
login(string $identifier, string $password, ?string $service = null)App Password で認証し LegacyAgent をセット
withToken(?AbstractSession $token)OAuthSession または LegacySession を渡して Agent をセット
check(): bool認証済みかどうかを確認(トークン有効期限も検証)
refreshSession()トークンをリフレッシュ
logout()Agent をクリア

Agent 操作

メソッド説明
agent(): ?Agent現在の Agent を取得
withAgent(?Agent $agent)Agent を直接セット
assertDid(): string認証済み DID を返す。未認証なら例外をスロー

HTTP クライアント

メソッド説明
client(bool $auth = true): AtpClient認証済み(または匿名の)XRPC クライアントを返す
public(): BskyClient認証不要のパブリックエンドポイントクライアントを返す
send(BackedEnum|string $api, string $method, bool $auth, ?array $params, ?callable $callback)任意の AT Protocol API を直接呼び出す

ユーティリティ

メソッド説明
identity(): IdentityDID 解決などのアイデンティティサービスを取得
pds(): PDSPDS 情報サービスを取得
entryway(?string $path): stringサービス URL(bsky.social など)を返す
publicEndpoint(): stringパブリックエンドポイント URL を返す

HasShortHand トレイト

HasShortHand トレイトは、AT Protocol の低レベル API を PHP 向けのわかりやすいメソッドにラップしています。BlueskyManageruse HasShortHand; と記述するだけで、これらのメソッドが Bluesky:: から直接呼べるようになります。
// BlueskyManager.php
class BlueskyManager implements Factory
{
    use Conditionable;
    use HasShortHand;
    use Macroable;
    // ...
}
HasShortHand を独立したトレイトにしている理由は、テスト・カスタマイズの容易さです。このトレイトを使えば BlueskyManager のコードをシンプルに保ちながら、豊富な API ショートカットを提供できます。

投稿・フィード

メソッド説明
post(Post|string|array $text)新規投稿を作成
getPost(string $uri)AT-URI で投稿を取得
getPosts(array $uris)複数の投稿を一括取得
deletePost(string $uri)投稿を削除
getTimeline(?string $algorithm, ?int $limit, ?string $cursor)ホームタイムラインを取得
getAuthorFeed(?string $actor, ...)指定アカウントのフィードを取得
searchPosts(string $q, ...)投稿を検索

エンゲージメント

メソッド説明
like(Like|StrongRef $subject)いいねを作成
deleteLike(string $uri)いいねを取り消し
repost(Repost|StrongRef $subject)リポストを作成
deleteRepost(string $uri)リポストを取り消し
getActorLikes(?string $actor, ...)アカウントのいいね一覧を取得

フォロー

メソッド説明
follow(Follow|string $did)フォロー
deleteFollow(string $uri)フォロー解除
getFollowers(?string $actor, ...)フォロワー一覧を取得
getFollows(?string $actor, ...)フォロー中一覧を取得

プロフィール・アカウント

メソッド説明
getProfile(?string $actor)プロフィールを取得
upsertProfile(callable $callback)プロフィールを更新
resolveHandle(string $handle)ハンドルを DID に解決

メディア

メソッド説明
uploadBlob(StreamInterface|string $data, string $type)画像などのブロブをアップロード
uploadVideo(StreamInterface|string $data, string $type)動画をアップロード
getJobStatus(string $jobId)動画アップロードのジョブ状態を確認
getUploadLimits()アップロード制限を取得

通知

メソッド説明
listNotifications(...)通知一覧を取得
countUnreadNotifications(...)未読通知件数を取得
updateSeenNotifications(string $seenAt)既読を更新

AT Protocol レコード操作

メソッド説明
createRecord(string $repo, string $collection, ...)レコードを作成
getRecord(string $repo, string $collection, string $rkey, ...)レコードを取得
listRecords(string $repo, string $collection, ...)レコード一覧を取得
putRecord(string $repo, string $collection, string $rkey, ...)レコードを更新・作成
deleteRecord(string $repo, string $collection, string $rkey, ...)レコードを削除

フィードジェネレーター・ラベラー

メソッド説明
publishFeedGenerator(BackedEnum|string $name, Generator $generator)フィードジェネレーターを公開
createThreadGate(string $post, ?array $allow)スレッドゲートを作成
upsertLabelDefinitions(callable $callback)ラベル定義を更新
deleteLabelDefinitions()ラベル定義を削除
createLabels(RepoRef|StrongRef|array $subject, array $labels)ラベルを付与
deleteLabels(RepoRef|StrongRef|array $subject, array $labels)ラベルを削除

よく使うショートカットの例

投稿する

use Revolution\Bluesky\Facades\Bluesky;

$response = Bluesky::login(
    identifier: config('bluesky.identifier'),
    password: config('bluesky.password'),
)->post('Hello Bluesky');

リプライする

リプライは Post::build() で親投稿の StrongRef を設定します。HasShortHand に専用の reply() メソッドはなく、post()Post オブジェクトを渡します。
use Revolution\Bluesky\Facades\Bluesky;
use Revolution\Bluesky\Record\Post;
use Revolution\Bluesky\Types\StrongRef;

$parent = StrongRef::to(uri: 'at://did:plc:.../app.bsky.feed.post/...', cid: 'bafyrei...');

$reply = Post::create('リプライのテキスト')
    ->reply(root: $parent, parent: $parent);

Bluesky::login(config('bluesky.identifier'), config('bluesky.password'))
    ->post($reply);

いいね・リポスト

use Revolution\Bluesky\Facades\Bluesky;
use Revolution\Bluesky\Types\StrongRef;

$ref = StrongRef::to(uri: 'at://did:plc:.../app.bsky.feed.post/...', cid: 'bafyrei...');

// いいね
Bluesky::withToken($session)->like($ref);

// リポスト
Bluesky::withToken($session)->repost($ref);

プロフィールを更新する

upsertProfile() は現在のプロフィールを取得し、クロージャ内で変更した内容を保存します。Profile オブジェクトのメソッドを使って displayName・description などを設定できます。
use Revolution\Bluesky\Facades\Bluesky;
use Revolution\Bluesky\Record\Profile;

Bluesky::login(config('bluesky.identifier'), config('bluesky.password'))
    ->upsertProfile(function (Profile $profile) {
        $profile->displayName('新しい表示名')
                ->description('プロフィール説明文');
    });

セルフラベルを設定する

SelfLabels を使って、アカウント全体に対してセルフラベルを設定できます。
use Revolution\Bluesky\Facades\Bluesky;
use Revolution\Bluesky\Record\Profile;
use Revolution\Bluesky\Types\SelfLabels;

Bluesky::login(config('bluesky.identifier'), config('bluesky.password'))
    ->upsertProfile(function (Profile $profile) {
        $profile->labels(SelfLabels::make(['!no-unauthenticated']));
    });

任意の API を直接呼び出す

HasShortHand にないメソッドは send() または client() を使います。
use Revolution\Bluesky\Facades\Bluesky;

// send() で任意の XRPC メソッドを呼び出す
$response = Bluesky::withToken($session)
    ->send(
        api: 'app.bsky.actor.getProfiles',
        method: 'get',
        params: ['actors' => ['did:plc:...', 'did:plc:...']],
    );

// client() でより細かい操作
$response = Bluesky::withToken($session)
    ->client()
    ->bsky()
    ->getProfiles(actors: ['did:plc:...']);

Facade 経由と直接利用の違い

Bluesky::post()app(Factory::class)->post() は同じ BlueskyManager インスタンスに対する操作です。
use Revolution\Bluesky\Facades\Bluesky;
use Revolution\Bluesky\Contracts\Factory;

// Facade 経由(通常の使い方)
Bluesky::login(config('bluesky.identifier'), config('bluesky.password'))
    ->post('Hello');

// コンテナから直接取得
$manager = app(Factory::class);
$manager->login(config('bluesky.identifier'), config('bluesky.password'))
        ->post('Hello');

// 型ヒントで DI
class MyService
{
    public function __construct(private Factory $bluesky) {}

    public function doPost(): void
    {
        $this->bluesky->login(
            config('bluesky.identifier'),
            config('bluesky.password'),
        )->post('Hello from DI');
    }
}
scoped 登録のため、1リクエスト内では login() 後のセッション状態が保持されます。

Conditionable と Macroable

BlueskyManagerConditionableMacroable トレイトも使用しています。

Conditionable: when() / unless()

use Revolution\Bluesky\Facades\Bluesky;

Bluesky::login(config('bluesky.identifier'), config('bluesky.password'))
    ->when(config('app.env') === 'production', function ($bluesky) {
        $bluesky->post('本番環境からの投稿');
    });

Macroable: カスタムメソッドの追加

macro() を使うとアプリケーション側から BlueskyManager にメソッドを追加できます。AppServiceProviderboot() 内で定義するのが一般的です。
use Revolution\Bluesky\Facades\Bluesky;

Bluesky::macro('postWithHashtag', function (string $text, string $tag) {
    /** @var \Revolution\Bluesky\BlueskyManager $this */
    return $this->post("{$text} #{$tag}");
});

// 使用例
Bluesky::login(config('bluesky.identifier'), config('bluesky.password'))
    ->postWithHashtag('Hello', 'laravel');

カスタム Agent の差し込み

withAgent() を使うと、任意の Agent 実装を直接セットできます。
use Revolution\Bluesky\Facades\Bluesky;
use Revolution\Bluesky\Contracts\Agent;

// カスタム Agent を実装する場合は Agent インターフェースを実装する
class MyCustomAgent implements Agent
{
    // ...
}

Bluesky::withAgent(new MyCustomAgent());
通常の認証(login() / withToken())を使えば自動でエージェントがセットされるため、withAgent() を直接使う機会はテスト時が主となります。

参考リンク

Last modified on April 26, 2026