Blueskyの個別ポストURLから埋め込みコードを生成する
Blueskyのポスト埋め込みコード(<blockquote ~)を個別ポストのURLから生成するPHPコード。
事前準備
- Blueskyのアプリパスワードを取得しておく
- phpdotenvをインストールして
.envファイルに以下を入力
ID='Blueskyのアカウント'API='アプリパスワード'コード
コード例の埋め込みポストはBluesky公式のポストから。
//phpdotenvrequire __DIR__. '/vendor/autoload.php';use Dotenv\Dotenv;$dotenv = Dotenv::createImmutable(__DIR__);$dotenv->load();
/** * BlueskyアカウントのDIDを取得 */function BlueskyDid($bsky_handle) { $query_url = "https://bsky.social/xrpc/com.atproto.identity.resolveHandle?handle={$bsky_handle}"; $ch = curl_init($query_url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']); curl_setopt($ch, CURLOPT_TIMEOUT, 5); curl_setopt($ch, CURLOPT_FAILONERROR, true);
$result = curl_exec($ch); curl_close($ch);
return $result;}
/** * アクセストークンの取得 */function getBlueskyAccessToken($identifier, $password) { $login_url = 'https://bsky.social/xrpc/com.atproto.server.createSession'; $data = [ 'identifier' => $identifier, 'password' => $password ];
$ch = curl_init($login_url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']); curl_setopt($ch, CURLOPT_TIMEOUT, 5); curl_setopt($ch, CURLOPT_FAILONERROR, true); $response = curl_exec($ch); curl_close($ch);
$session = json_decode($response, true); return $session['accessJwt'] ?? null;}
/** * postを取得 */function getBlueskyPost($token, $post_url) { $ch = curl_init($post_url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Bearer {$token}"]); curl_setopt($ch, CURLOPT_TIMEOUT, 5); curl_setopt($ch, CURLOPT_FAILONERROR, true);
$result = curl_exec($ch); curl_close($ch);
return $result;}
/** * 埋め込み生成 */$url = 'https://bsky.app/profile/bsky.app/post/3l6oveex3ii2l';preg_match('/https:\/\/bsky\.app\/profile\/(.+)\/post\/(.+)/', $url, $match);
$account = BlueskyDid($match[1]);$account_data = json_decode($account, true) ?: [];
$api_url = "https://bsky.social/xrpc/app.bsky.feed.getPosts?uris=at://{$account_data['did']}/app.bsky.feed.post/{$match[2]}";$token = getBlueskyAccessToken($_ENV['ID'], $_ENV['API']);$post = getBlueskyPost($token, $api_url);$post_data = json_decode($post, true) ?: [];
//日付変換 UTC->JST$post_date = new DateTime($post_data['posts'][0]['record']['createdAt']);$post_date->setTimeZone(new DateTimeZone('Asia/Tokyo'));
$bluesky_embed = <<<EOT<blockquote class="bluesky-embed" data-bluesky-uri="{$post_data['posts'][0]['uri']}" data-bluesky-cid="{$post_data['posts'][0]['cid']}" data-bluesky-embed-color-mode="system"><p lang="{$post_data['posts'][0]['record']['langs'][0]}">{$post_data['posts'][0]['record']['text']}<br><br><a href="https://bsky.app/profile/{$post_data['posts'][0]['author']['did']}/post/{$match[2]}?ref_src=embed">[image or embed]</a></p>— {$post_data['posts'][0]['author']['displayName']} (<a href="https://bsky.app/profile/{$post_data['posts'][0]['author']['did']}?ref_src=embed">@{$post_data['posts'][0]['author']['handle']}</a>) <a href="https://bsky.app/profile/{$post_data['posts'][0]['author']['did']}/post/{$match[2]}?ref_src=embed">{$post_date->format('Y年n月j日 G:i')}</a></blockquote><script async src="https://embed.bsky.app/static/embed.js" charset="utf-8"></script>EOT;
echo $bluesky_embed;getBlueskyPost()で取得できるデータにポストのslug単体がないので、URLから切り出している($post_data['posts'][0]['uri']から切り出してもいいかもだけど)
テキストのみのポストもURLつきのポストも画像付きのポストも同じコードで埋め込める。
ただしログインしないと見れないポストは、埋め込みウィジェット内に「「The author of this post has requested their posts not be displayed on external sites.」という文言と該当ポストへのリンクが表示される。
現時点ではこれを識別する方法はなさそう?