本页是 AT Protocol 官方 bot 教程 的 Laravel 版。介绍如何用 laravel-bluesky 包,通过 PHP/Laravel 实现原本面向 TypeScript 的内容。
官方教程会通过 lex 命令每次下载 Lexicon 文件,但 laravel-bluesky 已经从 atproto-lexicon-contracts 事先导入了全部 Lexicon,所以不需要这一步。通过 Artisan 命令和 HasShortHand trait 的方法,几乎可以完成所有操作。
前置条件
- 已经安装
laravel-bluesky 包
- 已经准备好 Bluesky 账号和 App Password
安装方法请参考 Laravel Bluesky。
BLUESKY_IDENTIFIER=yourbot.bsky.social
BLUESKY_APP_PASSWORD=xxxx-xxxx-xxxx-xxxx
第 1 部分:基础 bot(发帖)
创建 Artisan 命令
使用 php artisan make:command 创建 bot 用的命令。
php artisan make:command BotPostCommand
编辑生成的 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.');
}
}
手动执行
使用定时任务自动执行
在 routes/console.php 中添加定时执行的设置。
use Illuminate\Support\Facades\Schedule;
// 每 3 小时发一次
Schedule::command('bot:post')->everyThreeHours();
要启用调度器,请在 cron 中配置以下条目。
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
用 GitHub Actions 自动执行
如果没有服务器,也可以用 GitHub Actions 自动执行。
# .github/workflows/bot.yml
name: Bot Post
on:
schedule:
- cron: '0 */3 * * *' # 每 3 小时
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 }}
请把 BLUESKY_IDENTIFIER 和 BLUESKY_APP_PASSWORD 注册到 GitHub Actions 的 secrets 中。
第 2 部分:回复 bot(监听 mention)
创建一个对 mention 自动回复的 bot。同时也介绍使用 AI 生成回复的示例。
获取通知并对 mention 回复
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) {
// 只处理 mention 类型的通知
if (data_get($notification, 'reason') !== 'mention') {
continue;
}
// 跳过已读通知(isRead 为 true 的表示已处理)
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('你好!感谢你的 mention。🙂')
->reply($reply);
Bluesky::post($post);
$this->info("Replied to: {$uri}");
}
// 将通知标记为已读
Bluesky::updateSeenNotifications(now()->toISOString());
}
}
如果 thread 的 root 与父帖不同,请通过 app.bsky.feed.getPostThread 获取 thread 信息并设置到 root。这里的简易实现直接把父帖当作 root。
定时轮询
// routes/console.php
use Illuminate\Support\Facades\Schedule;
Schedule::command('bot:reply')->everyFiveMinutes();
用 AI 生成回复
结合 laravel/ai 包和 laravel-amazon-bedrock 驱动,可以根据 mention 内容生成 AI 回复。
composer require laravel/ai revolution/laravel-amazon-bedrock
创建 AI agent。
<?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 '你是一个在 Bluesky 上活动的友好 bot。'
. '请对用户的消息用中文生成简短且亲切的回复。'
. '回复请控制在 200 字以内。';
}
}
在命令中使用 AI 回复。
<?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;
}
// 用 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());
}
}
第 3 部分:label bot
对应官方教程中的 labelAsBot。给 bot 账号的个人资料添加 self label,明确表明这是一个自动化账号。
label 只需要在初次设置时执行一次。它作为独立于第 1、2 部分的命令来实现。
创建 label bot 命令
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) {
// 设置 !bot label
$profile->labels(SelfLabels::make(['!bot']));
});
$this->info('Bot label applied successfully.');
}
}
请在 bot 初次设置时执行一次即可。label 会持久保存在个人资料中。
!bot 是 Bluesky 的标准 self label。官方推荐所有 bot 账号都应设置。
其他官方教程
AT Protocol 的官方教程还有其他几个主题。以下是 laravel-bluesky 的对应情况。
自定义 feed
Feed Generator 中详细介绍了用 Laravel 实现自定义 feed generator 的方法。
OAuth 认证
Socialite 中介绍了如何用 Laravel Socialite 实现 OAuth 认证。比官方教程更易于实现。
社交应用(statusphere)
Laravel 版的 statusphere 以 invokable/statusphere 公开发布。它基于尚未使用 lex 或 tap 命令的旧版 statusphere,因此与最新官方教程略有差异。
参考链接