Passer au contenu principal

Vue d’ensemble

Cette page est la version Laravel du tutoriel officiel de bot AT Protocol. Elle explique comment implémenter en PHP/Laravel avec le package laravel-bluesky ce que le tutoriel officiel montre en TypeScript. Le tutoriel officiel télécharge à chaque fois les fichiers Lexicon via la commande lex, mais laravel-bluesky intègre déjà tous les Lexicons via atproto-lexicon-contracts : cette étape est donc superflue. À l’aide des commandes Artisan et des méthodes du trait HasShortHand, la quasi-totalité des opérations est réalisable.

Prérequis

  • Le package laravel-bluesky doit être installé
  • Vous devez disposer d’un compte Bluesky et d’un App Password
Pour la procédure d’installation, voir Laravel Bluesky.
BLUESKY_IDENTIFIER=yourbot.bsky.social
BLUESKY_APP_PASSWORD=xxxx-xxxx-xxxx-xxxx

Partie 1 : bot de base (publication)

Créer une commande Artisan

Créez la commande du bot avec php artisan make:command.
php artisan make:command BotPostCommand
Modifiez le fichier généré 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.');
    }
}

Exécution manuelle

php artisan bot:post

Exécution automatique via le planificateur

Ajoutez une planification dans routes/console.php.
use Illuminate\Support\Facades\Schedule;

// Publier toutes les 3 heures
Schedule::command('bot:post')->everyThreeHours();
Pour activer le planificateur, ajoutez la ligne suivante à cron :
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1

Exécution automatique via GitHub Actions

Si vous n’avez pas de serveur, GitHub Actions permet également d’exécuter automatiquement la commande.
# .github/workflows/bot.yml
name: Bot Post

on:
  schedule:
    - cron: '0 */3 * * *'  # Toutes les 3 heures
  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 }}
Enregistrez BLUESKY_IDENTIFIER et BLUESKY_APP_PASSWORD dans les secrets de GitHub Actions.

Partie 2 : bot de réponse (surveillance des mentions)

Créons un bot qui répond automatiquement aux mentions. Nous présenterons également un exemple générant des réponses par IA.

Récupérer les notifications et répondre aux mentions

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) {
            // Ne traiter que les notifications de type mention
            if (data_get($notification, 'reason') !== 'mention') {
                continue;
            }

            // Ignorer les notifications déjà lues (isRead à true = déjà traitées)
            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('Bonjour ! Merci pour la mention. 🙂')
                ->reply($reply);

            Bluesky::post($post);

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

        // Marquer les notifications comme lues
        Bluesky::updateSeenNotifications(now()->toISOString());
    }
}
Si le root du thread diffère, récupérez les informations du thread avec app.bsky.feed.getPostThread et affectez-les à root. Cette implémentation simplifiée traite le post parent comme root.

Planifier le polling

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

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

Générer les réponses avec l’IA

En combinant le package laravel/ai et le pilote laravel-amazon-bedrock, vous pouvez générer des réponses IA adaptées au contenu de la mention.
composer require laravel/ai revolution/laravel-amazon-bedrock
Créez un agent IA.
<?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 'Vous êtes un bot amical qui interagit sur Bluesky. '
            . 'Générez en français une réponse courte et chaleureuse au message de l\'utilisateur. '
            . 'La réponse doit faire au maximum 200 caractères.';
    }
}
Utilisez la réponse IA dans la commande.
<?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;
            }

            // Générer la réponse via IA
            $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());
    }
}
Pour la configuration de laravel-amazon-bedrock, voir Pilote Amazon Bedrock.

Partie 3 : bot de label

Fonctionnalité équivalente à labelAsBot du tutoriel officiel. Il s’agit d’ajouter un self label au profil du compte bot pour signaler explicitement qu’il s’agit d’un compte automatisé.
La labellisation ne s’exécute qu’une seule fois, lors de la configuration initiale. Elle est implémentée en tant que commande distincte des parties 1 et 2.

Créer la commande du bot de 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) {
            // Appliquer le label !bot
            $profile->labels(SelfLabels::make(['!bot']));
        });

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

Exécution

php artisan bot:label
N’exécutez cette commande qu’une seule fois lors de la configuration initiale du bot. Le label est stocké de manière permanente dans le profil.
!bot est un self label standard de Bluesky. Il est recommandé de toujours l’appliquer aux comptes de type bot.

Autres tutoriels officiels

Le tutoriel officiel AT Protocol traite d’autres sujets. Voici l’état de la prise en charge dans laravel-bluesky.

Flux personnalisés

Feed Generator décrit en détail comment implémenter un feed generator personnalisé avec Laravel.

Authentification OAuth

Socialite explique comment implémenter l’authentification OAuth avec Laravel Socialite. L’implémentation est plus simple que dans le tutoriel officiel.

Application sociale (statusphere)

Une version Laravel de statusphere est publiée sous invokable/statusphere. Elle s’appuie sur une version antérieure de statusphere qui n’utilise pas encore les commandes lex ou tap, elle diffère donc légèrement du tutoriel officiel le plus récent.

Liens utiles

Dernière modification le 13 juillet 2026