Easily Publish a Post on Bluesky with PHP

20 January 2025 - 484 mots - php

Bluesky is a decentralized social network based on an open protocol called the AT Protocol, allowing users to control their data and interactions. Unlike centralized platforms, Bluesky enables different instances (servers) to connect, offering greater freedom and customization. The goal is to create a more transparent environment where users can share information and interact without the constraints of traditional networks. Each instance has its own rules, allowing for a diversity of opinions and communities.

Logo Bluesky

After this introduction to the Bluesky service, let’s learn how to publish a post on the Bluesky network using PHP.

Prerequisites

You need to obtain an application password.

To do this:

  • Log in to your Bluesky instance.
  • Go to the “Settings” menu.
  • Navigate to “Privacy and Security.”
  • Select “App Passwords.”
  • Click on the “Add App Password” button.
  • Define the name of the application: in our case, we’ll call it “BlueskyBot.”
  • Click the “Next” button.
  • Retrieve your app password.

Theory

We will use the Bluesky API, whose documentation is available online.

Implementation

The implementation will be done in PHP 8.4 with the Curl extension installed and enabled.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
<?php

const BLUESKY_USERNAME = 'xxxxx.bsky.social';
const BLUESKY_APP_PASSWORD = 'xxxx-xxxx-xxxx-xxxx';

function fnPostBluesky(
  string $status,
  string $language = 'en'
  
) {
  $hCurl = curl_init();

  // com.atproto.server.createSession : Fetch the Bearer token
  curl_setopt_array($hCurl, array(
    CURLOPT_URL => 'https://bsky.social/xrpc/com.atproto.server.createSession',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => '',
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 0,
    CURLOPT_FOLLOWLOCATION => true,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_POSTFIELDS =>'{
      "identifier":"'.BLUESKY_USERNAME.'",
      "password":"'.BLUESKY_APP_PASSWORD.'"
    }',
    CURLOPT_HTTPHEADER => array(
      'Content-Type: application/json'
    ),
  ));
  $resSession = curl_exec($hCurl);
  $arrSession = json_decode($resSession,TRUE);

  // com.atproto.repo.createRecord : Create the post
  curl_setopt_array($hCurl, array(
    CURLOPT_URL => 'https://bsky.social/xrpc/com.atproto.repo.createRecord',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => '',
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 0,
    CURLOPT_FOLLOWLOCATION => true,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_POSTFIELDS =>'{
      "repo":"'.$arrSession['did'].'",
      "collection":"app.bsky.feed.post",
      "record":{
          "$type":"app.bsky.feed.post",
          "createdAt":"'.date("c").'",
          "text":"'.$status.'",
          "langs":["'.$language.'"]
      }
    }',
    CURLOPT_HTTPHEADER => array(
      'Content-Type: application/json',
      'Authorization: Bearer '.$arrSession['accessJwt']
    ),
  ));
  
  $response = curl_exec($hCurl);
  curl_close($hCurl);
  return json_decode($response, true);
}

$response = fnPostBluesky(
  '🚧 Ceci est un test 🚧',
  'fr'
);

var_dump($response);

echo 'URL : https://bsky.app/profile/' . BLUESKY_USERNAME. '/post/' . substr($response['uri'], strrpos($response['uri'], '/') + 1) . PHP_EOL;

This code is the simplest implementation possible, as you can see, without using any library and with minimal extensions.

Conclusion

After a simple execution of the code, here is the result:

Result

With the documentation, there are several possible improvements to make:

  • Detect mentions/URLs in the text and implement them in the code.
  • Add the ability to quote a post.
  • Include images in a post.
  • Add a social card to a post.

Laisser un commentaire

Merci. Votre message a bien été enregistré.