So, you want to publish in Bluesky with a python program?
Tags: python, bluesky, atprotocol, posse
Published: 2023-11-02 19:04:43

Bluesky is a microblogging social platform that has been available for aproximately a year. Currently, access is by invitation only, but invitations are becoming more readily available. If you don't have one yet, you should receive one soon.

In my quest to experiment with the platform, I aimed to publish posts programmatically. I stumbled upon a helpful resource, [Posting via the Bluesky API,](https://atproto.com/blog/create-post)  which guided me in getting started.

Bluesky utilizes [the AT protocol](https://atproto.com/) so I conducted a quick search to find a Python implementation of it, available at [atproto](https://github.com/MarshalX/atproto). You can install it on your system using the usual method:

    pip install -U atproto

Once installed, you can start posting using the appropriate code. For instance, you can post a text message with a line like this:


You can post a text message with some line such as:

    client.send_post(text='Hello World!')

provided, of course, that you are authenticated, and so on.

However, I wanted to publish text with links, and simply writing a URL in your text won't automatically create a link:

![Example of publication in Bluesky, with link not interpreted and then, as a reply, with the link interpreted](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o0xi80f6d19ja9cjdnj7.png)

To achieve this, I needed to do some research. You can see the difference in the reply between having a link and not having one. You can include additional information when you write by using what they call 'facets.' For adding a link, you can use the  `AppBskyRichtextFacet`, which allows you to:

* Add a uri
* Specify the start and end indices of the URI in your text

For example, if you want to insert some text before your URI, you can do something like this:

    models.AppBskyRichtextFacet.Main(
                features=[models.AppBskyRichtextFacet.Link(uri=uri)],
                index=models.AppBskyRichtextFacet.ByteSlice(byte_start=len(text)+1,
                                                            byte_end=len(text)+len(uri)+1),
                )

Note that you are specifying the position where your URI begins and ends. You can append it to your list of facets and send it as text to your Bluesky account.

You can see the complete program at:

<script src="https://gist.github.com/fernand0/6e099c1049f74cbb3151f6f7cc3163e5.js"></script>

```
from atproto import Client, models


def main():
    client = Client()
    password = input("Password? ")
    profile = client.login('fernand0.bsky.social', password)
    print('Welcome,', profile.display_name)

    facets =  []

    text = 'Mi GitHub:'
    uri = 'http://github.com/fernand0'
    facets.append(
            models.AppBskyRichtextFacet.Main(
                features=[models.AppBskyRichtextFacet.Link(uri=uri)],
                index=models.AppBskyRichtextFacet.ByteSlice(byte_start=len(text)+1,
                                                            byte_end=len(text)+len(uri)+1),
                )
            )

    text = f"{text} {uri}"
    response = client.com.atproto.repo.create_record(
        models.ComAtprotoRepoCreateRecord.Data(
            repo=client.me.did,
            collection=models.ids.AppBskyFeedPost,
            record=models.AppBskyFeedPost.Main(created_at=client.get_current_time_iso(), text=text, facets=facets),
        )
    )
    print(f"Response: {response}")


if __name__ == '__main__':
    main()
```

You can download the code in this [publish in bluesky gist](https://gist.github.com/fernand0/6e099c1049f74cbb3151f6f7cc3163e5).