Ü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
| Methode | Beschreibung |
|---|
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(): bool | Prüft, ob authentifiziert wurde (inklusive Token-Gültigkeit) |
refreshSession() | Aktualisiert das Token |
logout() | Setzt den Agent zurück |
Agent-Operationen
| Methode | Beschreibung |
|---|
agent(): ?Agent | Gibt den aktuellen Agent zurück |
withAgent(?Agent $agent) | Setzt den Agent direkt |
assertDid(): string | Gibt die authentifizierte DID zurück; wirft eine Exception, wenn nicht authentifiziert |
HTTP-Client
| Methode | Beschreibung |
|---|
client(bool $auth = true): AtpClient | Gibt einen authentifizierten (oder anonymen) XRPC-Client zurück |
public(): BskyClient | Gibt 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
| Methode | Beschreibung |
|---|
identity(): Identity | Gibt den Identity-Service (z. B. für DID-Auflösung) zurück |
pds(): PDS | Gibt den PDS-Informationsdienst zurück |
entryway(?string $path): string | Gibt die Service-URL (z. B. bsky.social) zurück |
publicEndpoint(): string | Gibt 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
| Methode | Beschreibung |
|---|
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
| Methode | Beschreibung |
|---|
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
| Methode | Beschreibung |
|---|
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
| Methode | Beschreibung |
|---|
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
| Methode | Beschreibung |
|---|
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
| Methode | Beschreibung |
|---|
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
| Methode | Beschreibung |
|---|
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
| Methode | Beschreibung |
|---|
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.
Weiterführende Links
Zuletzt geändert am 13. Juli 2026