Vai al contenuto principale

Panoramica

Questa pagina è la versione Laravel del tutorial ufficiale per bot di AT Protocol. Spiega come implementare in PHP/Laravel, tramite il pacchetto laravel-bluesky, i contenuti pensati per TypeScript. Nel tutorial ufficiale il file Lexicon viene scaricato di volta in volta con il comando lex, ma in laravel-bluesky tutti i Lexicon sono già inclusi in anticipo tramite atproto-lexicon-contracts, quindi questo passaggio non è necessario. Con i comandi Artisan e i metodi del trait HasShortHand puoi realizzare praticamente tutte le operazioni.

Prerequisiti

  • Il pacchetto laravel-bluesky è già installato
  • Devi avere un account Bluesky e una app password
Per le istruzioni di installazione consulta Laravel Bluesky.
BLUESKY_IDENTIFIER=yourbot.bsky.social
BLUESKY_APP_PASSWORD=xxxx-xxxx-xxxx-xxxx

Parte 1: bot base (post)

Creare un comando Artisan

Crea un comando per il bot con php artisan make:command.
php artisan make:command BotPostCommand
Modifica il file generato app/Console/Commands/BotPostCommand.php.
<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Revolution\Bluesky\Facades\Bluesky;

class BotPostCommand extends Command
{
    protected $signature = 'bot:post';

    protected $description = 'Post to Bluesky';

    public function handle(): void
    {
        Bluesky::login(
            identifier: config('bluesky.identifier'),
            password: config('bluesky.password'),
        )->post('🙂');

        $this->info('Posted successfully.');
    }
}

Esecuzione manuale

php artisan bot:post

Esecuzione automatica con il task scheduler

Aggiungi le impostazioni per l’esecuzione periodica in routes/console.php.
use Illuminate\Support\Facades\Schedule;

// Post ogni 3 ore
Schedule::command('bot:post')->everyThreeHours();
Per abilitare lo scheduler, imposta il seguente cron.
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1

Esecuzione automatica con GitHub Actions

Se non hai un server, puoi comunque eseguirlo automaticamente con GitHub Actions.
# .github/workflows/bot.yml
name: Bot Post

on:
  schedule:
    - cron: '0 */3 * * *'  # ogni 3 ore
  workflow_dispatch:

jobs:
  post:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: shivammathur/setup-php@v2
        with:
          php-version: '8.4'
      - run: composer install --no-dev --optimize-autoloader
      - run: php artisan bot:post
        env:
          BLUESKY_IDENTIFIER: ${{ secrets.BLUESKY_IDENTIFIER }}
          BLUESKY_APP_PASSWORD: ${{ secrets.BLUESKY_APP_PASSWORD }}
Registra BLUESKY_IDENTIFIER e BLUESKY_APP_PASSWORD nei secret di GitHub Actions.

Parte 2: bot di risposta (monitoraggio delle menzioni)

Creiamo un bot che risponde automaticamente alle menzioni. Vediamo anche un esempio in cui la risposta viene generata da un’AI.

Recuperare le notifiche e rispondere alle menzioni

php artisan make:command BotReplyCommand
<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Revolution\Bluesky\Facades\Bluesky;
use Revolution\Bluesky\Record\Post;
use Revolution\Bluesky\Types\ReplyRef;
use Revolution\Bluesky\Types\StrongRef;

class BotReplyCommand extends Command
{
    protected $signature = 'bot:reply';

    protected $description = 'Reply to mentions on Bluesky';

    public function handle(): void
    {
        Bluesky::login(
            identifier: config('bluesky.identifier'),
            password: config('bluesky.password'),
        );

        $notifications = Bluesky::listNotifications(limit: 20)->json('notifications', []);

        foreach ($notifications as $notification) {
            // Elabora solo le notifiche di menzione
            if (data_get($notification, 'reason') !== 'mention') {
                continue;
            }

            // Salta le notifiche già lette (isRead a true sono già elaborate)
            if (data_get($notification, 'isRead')) {
                continue;
            }

            $uri = data_get($notification, 'uri');
            $cid = data_get($notification, 'cid');

            if (! $uri || ! $cid) {
                continue;
            }

            $ref = StrongRef::to(uri: $uri, cid: $cid);
            $reply = ReplyRef::to(root: $ref, parent: $ref);

            $post = Post::create('Ciao! Grazie per la menzione. 🙂')
                ->reply($reply);

            Bluesky::post($post);

            $this->info("Replied to: {$uri}");
        }

        // Segna le notifiche come lette
        Bluesky::updateSeenNotifications(now()->toISOString());
    }
}
Se il root del thread è diverso, recupera le informazioni del thread con app.bsky.feed.getPostThread e impostalo come root. In questa implementazione semplificata, il post padre viene usato come root.

Schedulare il polling

// routes/console.php
use Illuminate\Support\Facades\Schedule;

Schedule::command('bot:reply')->everyFiveMinutes();

Generare la risposta con l’AI

Combinando il pacchetto laravel/ai con il driver laravel-amazon-bedrock, puoi generare risposte AI adattate al contenuto della menzione.
composer require laravel/ai revolution/laravel-amazon-bedrock
Crea un agente AI.
<?php

namespace App\Ai\Agents;

use Laravel\Ai\Contracts\Agent;
use Laravel\Ai\Promptable;

class BotReplyAgent implements Agent
{
    use Promptable;

    public function instructions(): string
    {
        return 'Sei un bot amichevole attivo su Bluesky.'
            . ' Genera risposte brevi e cordiali in italiano ai messaggi degli utenti.'
            . ' Le risposte devono essere entro 200 caratteri.';
    }
}
Usa le risposte AI nel comando.
<?php

namespace App\Console\Commands;

use App\Ai\Agents\BotReplyAgent;
use Illuminate\Console\Command;
use Revolution\Bluesky\Facades\Bluesky;
use Revolution\Bluesky\Record\Post;
use Revolution\Bluesky\Types\ReplyRef;
use Revolution\Bluesky\Types\StrongRef;

class BotReplyCommand extends Command
{
    protected $signature = 'bot:reply';

    protected $description = 'Reply to mentions on Bluesky using AI';

    public function handle(): void
    {
        Bluesky::login(
            identifier: config('bluesky.identifier'),
            password: config('bluesky.password'),
        );

        $notifications = Bluesky::listNotifications(limit: 20)->json('notifications', []);

        foreach ($notifications as $notification) {
            if (data_get($notification, 'reason') !== 'mention') {
                continue;
            }

            if (data_get($notification, 'isRead')) {
                continue;
            }

            $uri = data_get($notification, 'uri');
            $cid = data_get($notification, 'cid');
            $mentionText = data_get($notification, 'record.text', '');

            if (! $uri || ! $cid) {
                continue;
            }

            // Genera la risposta con l'AI
            $replyText = (new BotReplyAgent)->prompt($mentionText)->text;

            $ref = StrongRef::to(uri: $uri, cid: $cid);
            $reply = ReplyRef::to(root: $ref, parent: $ref);

            $post = Post::create($replyText)->reply($reply);

            Bluesky::post($post);

            $this->info("AI replied to: {$uri}");
        }

        Bluesky::updateSeenNotifications(now()->toISOString());
    }
}
Per la configurazione di laravel-amazon-bedrock consulta il driver Amazon Bedrock.

Parte 3: bot per label

È la funzionalità equivalente a labelAsBot del tutorial ufficiale. Applica una self-label al profilo dell’account bot per dichiarare esplicitamente che si tratta di un account automatizzato.
L’applicazione della label va eseguita una sola volta, in fase di configurazione iniziale. Va implementata come comando separato dai comandi della Parte 1 e 2.

Creare il comando del bot per label

php artisan make:command BotLabelCommand
<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Revolution\Bluesky\Facades\Bluesky;
use Revolution\Bluesky\Record\Profile;
use Revolution\Bluesky\Types\SelfLabels;

class BotLabelCommand extends Command
{
    protected $signature = 'bot:label';

    protected $description = 'Add bot self-label to the Bluesky profile';

    public function handle(): void
    {
        Bluesky::login(
            identifier: config('bluesky.identifier'),
            password: config('bluesky.password'),
        )->upsertProfile(function (Profile $profile) {
            // Imposta la label !bot
            $profile->labels(SelfLabels::make(['!bot']));
        });

        $this->info('Bot label applied successfully.');
    }
}

Esecuzione

php artisan bot:label
Esegui questo comando una sola volta, durante la configurazione iniziale del bot. La label viene salvata in modo persistente nel profilo.
!bot è una self-label standard di Bluesky. Se ne consiglia sempre l’impostazione per gli account bot.

Sugli altri tutorial ufficiali

Il tutorial ufficiale di AT Protocol tratta anche altri argomenti. Ecco lo stato del supporto in laravel-bluesky.

Feed personalizzati

In Feed Generator trovi la spiegazione dettagliata su come implementare un feed generator personalizzato con Laravel.

Autenticazione OAuth

In Socialite trovi la spiegazione su come implementare l’autenticazione OAuth con Laravel Socialite. È più semplice da implementare rispetto al tutorial ufficiale.

App sociale (statusphere)

La versione Laravel di statusphere è pubblicata come invokable/statusphere. È basata su una versione più vecchia di statusphere che non usava i comandi lex o tap, quindi presenta lievi differenze rispetto al tutorial ufficiale più recente.
Ultima modifica il 13 luglio 2026