> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# BlueskyManager e HasShortHand

> Illustra l'architettura di BlueskyManager, l'implementazione dietro la Facade Bluesky, e i metodi di scorciatoia forniti dal trait HasShortHand.

## 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

```mermaid theme={null}
graph TD
    A["Facade Bluesky<br>(Revolution\\Bluesky\\Facades\\Bluesky)"] --> B["BlueskyManager<br>(interfaccia Factory)"]
    B --> C["Trait HasShortHand<br>Insieme dei metodi shortcut"]
    B --> D["Trait Conditionable<br>when() / unless()"]
    B --> E["Trait Macroable<br>macro() / mixin()"]
    B --> F{"Agent"}
    F --> G["LegacyAgent<br>(App Password)"]
    F --> H["OAuthAgent<br>(OAuth)"]
    G --> I["LegacySession"]
    H --> J["OAuthSession"]
```

`BlueskyServiceProvider` registra `Factory::class` come `BlueskyManager` in un singleton scoped (una istanza per richiesta).

```php theme={null}
// BlueskyServiceProvider::register()
$this->app->scoped(Factory::class, BlueskyManager::class);
```

Il `getFacadeAccessor()` della Facade risolve questo binding.

```php theme={null}
// 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::`.

```php theme={null}
// BlueskyManager.php
class BlueskyManager implements Factory
{
    use Conditionable;
    use HasShortHand;
    use Macroable;
    // ...
}
```

<Info>
  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.
</Info>

### 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 |

### Media

| 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

```php theme={null}
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()`.

```php theme={null}
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

```php theme={null}
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.

```php theme={null}
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.

```php theme={null}
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()`.

```php theme={null}
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`.

```php theme={null}
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()

```php theme={null}
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`.

```php theme={null}
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`.

```php theme={null}
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());
```

<Info>
  Con l'autenticazione normale (`login()` / `withToken()`) l'agente viene impostato automaticamente, quindi le occasioni per usare direttamente `withAgent()` sono principalmente in fase di test.
</Info>

## Link di riferimento

* [Confronto tra metodi di autenticazione](/it/packages/laravel-bluesky/authentication) — dettagli su App Password e OAuth
* [Basic client](/it/packages/laravel-bluesky/basic-client) — esempi di operazioni API dopo l'autenticazione
* [Testing](/it/packages/laravel-bluesky/testing) — metodi di test con i Fake
* Source: [src/BlueskyManager.php](https://github.com/invokable/laravel-bluesky/blob/main/src/BlueskyManager.php)
* Source: [src/HasShortHand.php](https://github.com/invokable/laravel-bluesky/blob/main/src/HasShortHand.php)


## Related topics

- [Tutorial per bot - Laravel Bluesky](/it/packages/laravel-bluesky/bot-tutorial.md)
- [Confronto tra metodi di autenticazione - Laravel Bluesky](/it/packages/laravel-bluesky/authentication.md)
- [Identity](/it/packages/laravel-bluesky/identity.md)
- [TextBuilder](/it/packages/laravel-bluesky/text-builder.md)
- [Illuminate\Support\Manager — anatomia del sistema di driver](/it/advanced/manager.md)
