Panoramica
La Facade Bluesky è un wrapper sottile su BlueskyManager. BlueskyManager gestisce più agenti e il trait HasShortHand raccoglie in un unico posto le scorciatoie ai metodi più frequenti.
Architettura
BlueskyServiceProvider registra Factory::class come BlueskyManager in un singleton scoped (una istanza per richiesta).
// BlueskyServiceProvider::register()
$this->app->scoped(Factory::class, BlueskyManager::class);
Il getFacadeAccessor() della Facade risolve questo binding.
// Facades/Bluesky.php
protected static function getFacadeAccessor(): string
{
return Factory::class;
}
Metodi core di BlueskyManager
I metodi core definiti da BlueskyManager stesso sono i seguenti. Distinguerli dai metodi del trait HasShortHand aiuta a comprendere la struttura interna.
Autenticazione
| Metodo | Descrizione |
|---|
login(string $identifier, string $password, ?string $service = null) | Autentica con App Password e imposta un LegacyAgent |
withToken(?AbstractSession $token) | Passa una OAuthSession o LegacySession e imposta l’Agent |
check(): bool | Verifica se sei autenticato (controlla anche la scadenza del token) |
refreshSession() | Rinnova il token |
logout() | Rimuove l’Agent |
Operazioni sull’Agent
| Metodo | Descrizione |
|---|
agent(): ?Agent | Ottieni l’Agent corrente |
withAgent(?Agent $agent) | Imposta direttamente un Agent |
assertDid(): string | Restituisce il DID autenticato. Lancia un’eccezione se non sei autenticato |
Client HTTP
| Metodo | Descrizione |
|---|
client(bool $auth = true): AtpClient | Restituisce un client XRPC autenticato (o anonimo) |
public(): BskyClient | Restituisce un client per gli endpoint pubblici senza autenticazione |
send(BackedEnum|string $api, string $method, bool $auth, ?array $params, ?callable $callback) | Invoca direttamente qualsiasi API AT Protocol |
Utility
| Metodo | Descrizione |
|---|
identity(): Identity | Ottiene il servizio identity (risoluzione DID, ecc.) |
pds(): PDS | Ottiene il servizio di informazioni PDS |
entryway(?string $path): string | Restituisce l’URL del servizio (es. bsky.social) |
publicEndpoint(): string | Restituisce l’URL dell’endpoint pubblico |
Trait HasShortHand
Il trait HasShortHand incapsula API di basso livello di AT Protocol in metodi PHP più chiari. Basta scrivere use HasShortHand; in BlueskyManager per rendere questi metodi invocabili direttamente da Bluesky::.
// BlueskyManager.php
class BlueskyManager implements Factory
{
use Conditionable;
use HasShortHand;
use Macroable;
// ...
}
Il motivo per cui HasShortHand è un trait indipendente è la facilità di test e personalizzazione. Grazie a questo trait, il codice di BlueskyManager resta semplice pur fornendo un ampio ventaglio di shortcut API.
Post e feed
| Metodo | Descrizione |
|---|
post(Post|string|array $text) | Crea un nuovo post |
getPost(string $uri) | Recupera un post tramite AT-URI |
getPosts(array $uris) | Recupera più post in una sola volta |
deletePost(string $uri) | Elimina un post |
getTimeline(?string $algorithm, ?int $limit, ?string $cursor) | Ottiene la home timeline |
getAuthorFeed(?string $actor, ...) | Ottiene il feed dell’account specificato |
searchPosts(string $q, ...) | Cerca post |
Engagement
| Metodo | Descrizione |
|---|
like(Like|StrongRef $subject) | Crea un like |
deleteLike(string $uri) | Rimuove il like |
repost(Repost|StrongRef $subject) | Crea un repost |
deleteRepost(string $uri) | Rimuove il repost |
getActorLikes(?string $actor, ...) | Ottiene l’elenco dei like di un account |
Follow
| Metodo | Descrizione |
|---|
follow(Follow|string $did) | Segui |
deleteFollow(string $uri) | Smetti di seguire |
getFollowers(?string $actor, ...) | Ottiene l’elenco dei follower |
getFollows(?string $actor, ...) | Ottiene l’elenco degli account seguiti |
Profilo e account
| Metodo | Descrizione |
|---|
getProfile(?string $actor) | Ottiene il profilo |
upsertProfile(callable $callback) | Aggiorna il profilo |
resolveHandle(string $handle) | Risolve un handle in un DID |
| Metodo | Descrizione |
|---|
uploadBlob(StreamInterface|string $data, string $type) | Carica un blob (immagine, ecc.) |
uploadVideo(StreamInterface|string $data, string $type) | Carica un video |
getJobStatus(string $jobId) | Verifica lo stato del job di upload video |
getUploadLimits() | Ottiene i limiti di upload |
Notifiche
| Metodo | Descrizione |
|---|
listNotifications(...) | Ottiene l’elenco delle notifiche |
countUnreadNotifications(...) | Ottiene il conteggio delle notifiche non lette |
updateSeenNotifications(string $seenAt) | Aggiorna lo stato di lettura |
Operazioni sui record AT Protocol
| Metodo | Descrizione |
|---|
createRecord(string $repo, string $collection, ...) | Crea un record |
getRecord(string $repo, string $collection, string $rkey, ...) | Recupera un record |
listRecords(string $repo, string $collection, ...) | Ottiene l’elenco dei record |
putRecord(string $repo, string $collection, string $rkey, ...) | Aggiorna o crea un record |
deleteRecord(string $repo, string $collection, string $rkey, ...) | Elimina un record |
Feed generator e labeler
| Metodo | Descrizione |
|---|
publishFeedGenerator(BackedEnum|string $name, Generator $generator) | Pubblica un feed generator |
createThreadGate(string $post, ?array $allow) | Crea un thread gate |
upsertLabelDefinitions(callable $callback) | Aggiorna le definizioni delle label |
deleteLabelDefinitions() | Elimina le definizioni delle label |
createLabels(RepoRef|StrongRef|array $subject, array $labels) | Assegna label |
deleteLabels(RepoRef|StrongRef|array $subject, array $labels) | Rimuove label |
Esempi di shortcut di uso frequente
Pubblicare un post
use Revolution\Bluesky\Facades\Bluesky;
$response = Bluesky::login(
identifier: config('bluesky.identifier'),
password: config('bluesky.password'),
)->post('Hello Bluesky');
Rispondere
Nelle risposte imposta lo StrongRef del post genitore tramite Post::build(). In HasShortHand non c’è un metodo reply() dedicato: passi un oggetto Post a 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('Testo della risposta')
->reply(root: $parent, parent: $parent);
Bluesky::login(config('bluesky.identifier'), config('bluesky.password'))
->post($reply);
Like e repost
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);
Aggiornare il profilo
upsertProfile() recupera il profilo attuale e salva le modifiche apportate dentro la closure. Puoi usare i metodi dell’oggetto Profile per impostare displayName, description e altro.
use Revolution\Bluesky\Facades\Bluesky;
use Revolution\Bluesky\Record\Profile;
Bluesky::login(config('bluesky.identifier'), config('bluesky.password'))
->upsertProfile(function (Profile $profile) {
$profile->displayName('Nuovo nome visualizzato')
->description('Testo di descrizione del profilo');
});
Impostare self-label
Con SelfLabels puoi impostare self-label per l’intero account.
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']));
});
Invocare direttamente un’API arbitraria
Per i metodi non presenti in HasShortHand, usa send() o client().
use Revolution\Bluesky\Facades\Bluesky;
// Invoca un metodo XRPC arbitrario con send()
$response = Bluesky::withToken($session)
->send(
api: 'app.bsky.actor.getProfiles',
method: 'get',
params: ['actors' => ['did:plc:...', 'did:plc:...']],
);
// Con client() hai un controllo più fine
$response = Bluesky::withToken($session)
->client()
->bsky()
->getProfiles(actors: ['did:plc:...']);
Differenza tra utilizzo via Facade e utilizzo diretto
Bluesky::post() e app(Factory::class)->post() operano sulla stessa istanza di BlueskyManager.
use Revolution\Bluesky\Facades\Bluesky;
use Revolution\Bluesky\Contracts\Factory;
// Via Facade (uso classico)
Bluesky::login(config('bluesky.identifier'), config('bluesky.password'))
->post('Hello');
// Recupero diretto dal container
$manager = app(Factory::class);
$manager->login(config('bluesky.identifier'), config('bluesky.password'))
->post('Hello');
// DI tramite 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');
}
}
Grazie alla registrazione scoped, all’interno di una singola richiesta lo stato della sessione dopo login() viene mantenuto.
Conditionable e Macroable
BlueskyManager utilizza anche i trait Conditionable e 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 dall\'ambiente di produzione');
});
Macroable: aggiungere metodi personalizzati
Con macro() puoi aggiungere metodi a BlueskyManager dal lato applicazione. È tipico definirli nel boot() di AppServiceProvider.
use Revolution\Bluesky\Facades\Bluesky;
Bluesky::macro('postWithHashtag', function (string $text, string $tag) {
/** @var \Revolution\Bluesky\BlueskyManager $this */
return $this->post("{$text} #{$tag}");
});
// Esempio di utilizzo
Bluesky::login(config('bluesky.identifier'), config('bluesky.password'))
->postWithHashtag('Hello', 'laravel');
Iniettare un Agent personalizzato
Con withAgent() puoi impostare direttamente una qualsiasi implementazione di Agent.
use Revolution\Bluesky\Facades\Bluesky;
use Revolution\Bluesky\Contracts\Agent;
// Per implementare un Agent personalizzato, implementa l'interfaccia Agent
class MyCustomAgent implements Agent
{
// ...
}
Bluesky::withAgent(new MyCustomAgent());
Con l’autenticazione normale (login() / withToken()) l’agente viene impostato automaticamente, quindi le occasioni per usare direttamente withAgent() sono principalmente in fase di test.
Link di riferimento