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

# Bot-Tutorial - Laravel Bluesky

> Laravel-Version des offiziellen AT-Protocol-Bot-Tutorials. Implementiert einen Post-Bot, einen Reply-Bot und einen Label-Bot mit dem Paket laravel-bluesky.

## Überblick

Diese Seite ist die Laravel-Fassung des [offiziellen AT-Protocol-Bot-Tutorials](https://atproto.com/guides/bot-tutorial). Sie zeigt, wie Sie die für TypeScript ausgelegten Inhalte mit dem Paket `laravel-bluesky` in PHP/Laravel umsetzen.

Im offiziellen Tutorial werden die Lexicon-Dateien jeweils mit dem `lex`-Kommando heruntergeladen. Bei `laravel-bluesky` sind über [atproto-lexicon-contracts](https://github.com/invokable/atproto-lexicon-contracts) bereits alle Lexicons vorab eingebunden, dieser Schritt entfällt daher. Mit Artisan-Kommandos und den Methoden des Traits `HasShortHand` lassen sich nahezu alle Operationen umsetzen.

```mermaid theme={null}
graph LR
    A["Offizielles Tutorial<br>(TypeScript)"] -->|"Laravel-Version"| B["laravel-bluesky"]
    B --> C["Artisan-Kommandos"]
    B --> D["HasShortHand-Trait"]
    B --> E["Task-Scheduler<br>/ GitHub Actions"]
```

## Voraussetzungen

* Das Paket `laravel-bluesky` ist installiert.
* Ein Bluesky-Account und ein App Password sind vorbereitet.

Installationshinweise finden Sie unter [Laravel Bluesky](/de/packages/laravel-bluesky/index).

```dotenv theme={null}
BLUESKY_IDENTIFIER=yourbot.bsky.social
BLUESKY_APP_PASSWORD=xxxx-xxxx-xxxx-xxxx
```

***

## Teil 1: Basis-Bot (Posten)

### Artisan-Kommando erstellen

Erstellen Sie mit `php artisan make:command` ein Kommando für den Bot.

```bash theme={null}
php artisan make:command BotPostCommand
```

Bearbeiten Sie die generierte Datei `app/Console/Commands/BotPostCommand.php`.

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

### Manuelle Ausführung

```bash theme={null}
php artisan bot:post
```

### Automatische Ausführung per Task-Scheduling

Fügen Sie in `routes/console.php` eine periodische Ausführung hinzu.

```php theme={null}
use Illuminate\Support\Facades\Schedule;

// Alle 3 Stunden posten
Schedule::command('bot:post')->everyThreeHours();
```

Aktivieren Sie den Scheduler, indem Sie folgenden Eintrag in der Crontab setzen.

```bash theme={null}
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
```

### Automatische Ausführung mit GitHub Actions

Ohne eigenen Server können Sie GitHub Actions für die automatische Ausführung verwenden.

```yaml theme={null}
# .github/workflows/bot.yml
name: Bot Post

on:
  schedule:
    - cron: '0 */3 * * *'  # alle 3 Stunden
  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 }}
```

<Tip>
  Registrieren Sie `BLUESKY_IDENTIFIER` und `BLUESKY_APP_PASSWORD` als Secrets in GitHub Actions.
</Tip>

***

## Teil 2: Reply-Bot (Mentions überwachen)

Wir erstellen einen Bot, der automatisch auf Mentions antwortet. Als Erweiterung zeigen wir auch, wie sich Antworten per KI generieren lassen.

### Benachrichtigungen abrufen und auf Mentions antworten

```bash theme={null}
php artisan make:command BotReplyCommand
```

```php theme={null}
<?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) {
            // Nur Mention-Benachrichtigungen verarbeiten
            if (data_get($notification, 'reason') !== 'mention') {
                continue;
            }

            // Bereits gelesene Benachrichtigungen überspringen (isRead == true bedeutet: schon verarbeitet)
            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('Hallo! Vielen Dank für die Erwähnung. 🙂')
                ->reply($reply);

            Bluesky::post($post);

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

        // Benachrichtigungen als gelesen markieren
        Bluesky::updateSeenNotifications(now()->toISOString());
    }
}
```

<Info>
  Wenn die Root des Threads eine andere ist, rufen Sie über `app.bsky.feed.getPostThread` die Thread-Informationen ab und setzen Sie diese als `root`. Diese vereinfachte Implementierung verwendet den Elternpost als Root.
</Info>

### Polling einplanen

```php theme={null}
// routes/console.php
use Illuminate\Support\Facades\Schedule;

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

### Antworten mit KI erzeugen

In Kombination mit dem Paket `laravel/ai` und dem Treiber `laravel-amazon-bedrock` können Sie KI-generierte Antworten passend zum Mention-Inhalt erzeugen.

```bash theme={null}
composer require laravel/ai revolution/laravel-amazon-bedrock
```

Erstellen Sie einen KI-Agent.

```php theme={null}
<?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 'Sie sind ein freundlicher Bot, der auf Bluesky aktiv ist. '
            . 'Erzeugen Sie zu der Nachricht des Nutzers eine kurze und freundliche Antwort auf Deutsch. '
            . 'Halten Sie die Antwort unter 200 Zeichen.';
    }
}
```

Verwenden Sie die KI-Antwort im Kommando.

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

            // Antwort per KI erzeugen
            $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());
    }
}
```

<Tip>
  Die Konfiguration von `laravel-amazon-bedrock` finden Sie unter [Amazon-Bedrock-Treiber](/de/packages/laravel-amazon-bedrock).
</Tip>

***

## Teil 3: Label-Bot

Dies entspricht der Funktion `labelAsBot` aus dem offiziellen Tutorial. Es setzt am Profil des Bot-Accounts ein Self-Label, um explizit als automatisierter Account gekennzeichnet zu sein.

<Info>
  Das Setzen des Labels erfolgt nur einmal beim initialen Setup. Implementieren Sie es als separates Kommando unabhängig von den Kommandos aus Teil 1 und 2.
</Info>

### Label-Bot-Kommando erstellen

```bash theme={null}
php artisan make:command BotLabelCommand
```

```php theme={null}
<?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) {
            // Label !bot setzen
            $profile->labels(SelfLabels::make(['!bot']));
        });

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

### Ausführen

```bash theme={null}
php artisan bot:label
```

Führen Sie dieses Kommando nur einmal beim initialen Setup des Bots aus. Das Label bleibt dauerhaft am Profil gespeichert.

<Warning>
  `!bot` ist ein Standard-Self-Label von Bluesky. Es wird empfohlen, es für Bot-Accounts unbedingt zu setzen.
</Warning>

***

## Zu weiteren offiziellen Tutorials

Das offizielle AT-Protocol-Tutorial deckt weitere Themen ab. Der Stand der Unterstützung in `laravel-bluesky` ist:

### Custom-Feed

Unter [Feed Generator](/de/packages/laravel-bluesky/feed-generator) finden Sie eine ausführliche Anleitung zur Implementierung eines Custom-Feed-Generators mit Laravel.

### OAuth-Authentifizierung

Unter [Socialite](/de/packages/laravel-bluesky/socialite) wird die OAuth-Authentifizierung mit Laravel Socialite beschrieben. Die Umsetzung ist einfacher als im offiziellen Tutorial.

### Soziale App (statusphere)

Eine Laravel-Fassung von statusphere ist unter [invokable/statusphere](https://github.com/invokable/statusphere) veröffentlicht. Sie basiert auf einer älteren statusphere-Version, die die Kommandos `lex` und `tap` nicht verwendet, und weicht dadurch in einigen Punkten vom aktuellen offiziellen Tutorial ab.

## Weiterführende Links

* [Offizielles AT-Protocol-Bot-Tutorial (Englisch)](https://atproto.com/guides/bot-tutorial)
* [Offizielles AT-Protocol-Bot-Tutorial (Japanisch)](https://atproto.com/ja/guides/bot-tutorial)
* [laravel-bluesky](https://github.com/invokable/laravel-bluesky)
* [BlueskyManager und HasShortHand](/de/packages/laravel-bluesky/bluesky-manager)
* [Notification-Kanal](/de/packages/laravel-bluesky/notification)
* [Amazon-Bedrock-Treiber](/de/packages/laravel-amazon-bedrock)


## Related topics

- [Laravel Socialite (Social Authentication)](/de/socialite.md)
- [Webhook / Bot - LINE SDK für Laravel](/de/packages/laravel-line-sdk/bot.md)
- [Laravel Bluesky](/de/packages/laravel-bluesky/index.md)
- [Feed Generator](/de/packages/laravel-bluesky/feed-generator.md)
- [LINE SDK für Laravel](/de/packages/laravel-line-sdk/index.md)
