Zum Hauptinhalt springen

Überblick

Die Facade Bluesky ist ein dünner Wrapper um BlueskyManager. BlueskyManager verwaltet mehrere Agents, und der Trait HasShortHand bündelt Shortcuts für die am häufigsten verwendeten Methoden.

Architektur

Der BlueskyServiceProvider registriert Factory::class als BlueskyManager als Scoped Singleton (eine Instanz pro Request).
// BlueskyServiceProvider::register()
$this->app->scoped(Factory::class, BlueskyManager::class);
Der getFacadeAccessor() der Facade löst dieses Binding auf.
// Facades/Bluesky.php
protected static function getFacadeAccessor(): string
{
    return Factory::class;
}

Kernmethoden des BlueskyManager

Die vom BlueskyManager selbst definierten Kernmethoden sind die folgenden. Es hilft beim Verständnis der internen Struktur, sie klar von den Methoden des Traits HasShortHand abzugrenzen.

Authentifizierung

MethodeBeschreibung
login(string $identifier, string $password, ?string $service = null)Authentifiziert per App Password und setzt einen LegacyAgent
withToken(?AbstractSession $token)Übergibt eine OAuthSession oder LegacySession und setzt den Agent
check(): boolPrüft, ob authentifiziert wurde (inklusive Token-Gültigkeit)
refreshSession()Aktualisiert das Token
logout()Setzt den Agent zurück

Agent-Operationen

MethodeBeschreibung
agent(): ?AgentGibt den aktuellen Agent zurück
withAgent(?Agent $agent)Setzt den Agent direkt
assertDid(): stringGibt die authentifizierte DID zurück; wirft eine Exception, wenn nicht authentifiziert

HTTP-Client

MethodeBeschreibung
client(bool $auth = true): AtpClientGibt einen authentifizierten (oder anonymen) XRPC-Client zurück
public(): BskyClientGibt einen Client für authentifizierungsfreie öffentliche Endpunkte zurück
send(BackedEnum|string $api, string $method, bool $auth, ?array $params, ?callable $callback)Ruft eine beliebige AT-Protocol-API direkt auf

Utilities

MethodeBeschreibung
identity(): IdentityGibt den Identity-Service (z. B. für DID-Auflösung) zurück
pds(): PDSGibt den PDS-Informationsdienst zurück
entryway(?string $path): stringGibt die Service-URL (z. B. bsky.social) zurück
publicEndpoint(): stringGibt die URL des öffentlichen Endpunkts zurück

Trait HasShortHand

Der Trait HasShortHand verpackt Low-Level-APIs des AT Protocols in verständliche, PHP-freundliche Methoden. Es genügt, im BlueskyManager use HasShortHand; einzufügen, dann sind diese Methoden direkt über Bluesky:: aufrufbar.
// BlueskyManager.php
class BlueskyManager implements Factory
{
    use Conditionable;
    use HasShortHand;
    use Macroable;
    // ...
}
Der Grund, HasShortHand als eigenständigen Trait zu führen, liegt in der einfachen Testbarkeit und Anpassbarkeit. So bleibt der Code des BlueskyManager schlank, während zahlreiche API-Shortcuts angeboten werden.

Posts und Feed

MethodeBeschreibung
post(Post|string|array $text)Erstellt einen neuen Post
getPost(string $uri)Ruft einen Post anhand der AT-URI ab
getPosts(array $uris)Ruft mehrere Posts auf einmal ab
deletePost(string $uri)Löscht einen Post
getTimeline(?string $algorithm, ?int $limit, ?string $cursor)Ruft die Home-Timeline ab
getAuthorFeed(?string $actor, ...)Ruft den Feed eines Accounts ab
searchPosts(string $q, ...)Durchsucht Posts

Engagement

MethodeBeschreibung
like(Like|StrongRef $subject)Erstellt einen Like
deleteLike(string $uri)Entfernt einen Like
repost(Repost|StrongRef $subject)Erstellt einen Repost
deleteRepost(string $uri)Entfernt einen Repost
getActorLikes(?string $actor, ...)Ruft die Likes eines Accounts ab

Folgen

MethodeBeschreibung
follow(Follow|string $did)Folgen
deleteFollow(string $uri)Entfolgen
getFollowers(?string $actor, ...)Ruft die Follower-Liste ab
getFollows(?string $actor, ...)Ruft die Follows-Liste ab

Profil und Account

MethodeBeschreibung
getProfile(?string $actor)Ruft ein Profil ab
upsertProfile(callable $callback)Aktualisiert das Profil
resolveHandle(string $handle)Löst ein Handle in eine DID auf

Medien

MethodeBeschreibung
uploadBlob(StreamInterface|string $data, string $type)Lädt einen Blob (z. B. ein Bild) hoch
uploadVideo(StreamInterface|string $data, string $type)Lädt ein Video hoch
getJobStatus(string $jobId)Prüft den Job-Status eines Video-Uploads
getUploadLimits()Ruft Upload-Limits ab

Benachrichtigungen

MethodeBeschreibung
listNotifications(...)Ruft die Liste der Benachrichtigungen ab
countUnreadNotifications(...)Ruft die Anzahl ungelesener Benachrichtigungen ab
updateSeenNotifications(string $seenAt)Aktualisiert den Gelesen-Status

AT-Protocol-Record-Operationen

MethodeBeschreibung
createRecord(string $repo, string $collection, ...)Erstellt einen Record
getRecord(string $repo, string $collection, string $rkey, ...)Ruft einen Record ab
listRecords(string $repo, string $collection, ...)Listet Records auf
putRecord(string $repo, string $collection, string $rkey, ...)Aktualisiert oder erstellt einen Record
deleteRecord(string $repo, string $collection, string $rkey, ...)Löscht einen Record

Feed-Generator und Labeler

MethodeBeschreibung
publishFeedGenerator(BackedEnum|string $name, Generator $generator)Veröffentlicht einen Feed-Generator
createThreadGate(string $post, ?array $allow)Erstellt ein Thread-Gate
upsertLabelDefinitions(callable $callback)Aktualisiert Label-Definitionen
deleteLabelDefinitions()Löscht Label-Definitionen
createLabels(RepoRef|StrongRef|array $subject, array $labels)Vergibt Labels
deleteLabels(RepoRef|StrongRef|array $subject, array $labels)Entfernt Labels

Beispiele für häufig verwendete Shortcuts

Post erstellen

use Revolution\Bluesky\Facades\Bluesky;

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

Antworten

Für eine Antwort setzen Sie in Post::build() den StrongRef des übergeordneten Posts. HasShortHand besitzt keine spezielle reply()-Methode – übergeben Sie post() stattdessen ein Post-Objekt.
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('Text der Antwort')
    ->reply(root: $parent, parent: $parent);

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

Likes und Reposts

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

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

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

// Repost
Bluesky::withToken($session)->repost($ref);

Profil aktualisieren

upsertProfile() lädt das aktuelle Profil und speichert die in der Closure vorgenommenen Änderungen. Über die Methoden des Profile-Objekts lassen sich unter anderem displayName und description setzen.
use Revolution\Bluesky\Facades\Bluesky;
use Revolution\Bluesky\Record\Profile;

Bluesky::login(config('bluesky.identifier'), config('bluesky.password'))
    ->upsertProfile(function (Profile $profile) {
        $profile->displayName('Neuer Anzeigename')
                ->description('Profilbeschreibung');
    });

Self-Labels setzen

Mit SelfLabels können Sie Self-Labels für den gesamten Account setzen.
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']));
    });

Beliebige API direkt aufrufen

Für Methoden, die nicht in HasShortHand enthalten sind, verwenden Sie send() oder client().
use Revolution\Bluesky\Facades\Bluesky;

// Eine beliebige XRPC-Methode über send() aufrufen
$response = Bluesky::withToken($session)
    ->send(
        api: 'app.bsky.actor.getProfiles',
        method: 'get',
        params: ['actors' => ['did:plc:...', 'did:plc:...']],
    );

// Feinere Steuerung über client()
$response = Bluesky::withToken($session)
    ->client()
    ->bsky()
    ->getProfiles(actors: ['did:plc:...']);

Unterschied zwischen Nutzung über die Facade und direkter Nutzung

Bluesky::post() und app(Factory::class)->post() sind Operationen auf derselben BlueskyManager-Instanz.
use Revolution\Bluesky\Facades\Bluesky;
use Revolution\Bluesky\Contracts\Factory;

// Über die Facade (übliche Verwendung)
Bluesky::login(config('bluesky.identifier'), config('bluesky.password'))
    ->post('Hello');

// Direkt aus dem Container abrufen
$manager = app(Factory::class);
$manager->login(config('bluesky.identifier'), config('bluesky.password'))
        ->post('Hello');

// Per DI über Type-Hint
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');
    }
}
Durch die scoped-Registrierung bleibt der nach login() bestehende Session-Zustand innerhalb eines Requests erhalten.

Conditionable und Macroable

BlueskyManager verwendet zusätzlich die Traits Conditionable und Macroable.

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('Post aus der Produktionsumgebung');
    });

Macroable: Eigene Methoden hinzufügen

Mit macro() können Sie aus der Anwendung Methoden zum BlueskyManager hinzufügen. Üblicherweise definiert man sie in der boot()-Methode des AppServiceProvider.
use Revolution\Bluesky\Facades\Bluesky;

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

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

Eigenen Agent einsetzen

Über withAgent() können Sie eine beliebige Agent-Implementierung direkt einsetzen.
use Revolution\Bluesky\Facades\Bluesky;
use Revolution\Bluesky\Contracts\Agent;

// Ein eigener Agent muss das Agent-Interface implementieren
class MyCustomAgent implements Agent
{
    // ...
}

Bluesky::withAgent(new MyCustomAgent());
Da bei der üblichen Authentifizierung (login() / withToken()) der Agent automatisch gesetzt wird, ist withAgent() vor allem beim Testen relevant.
Zuletzt geändert am 13. Juli 2026