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
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());
}
}
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
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