How to 'Like' a Post in Bluesky using Javascript

 


The Problem

If you look at the API reference for Bluesky to 'like' a post, you'll find it isn't there.

If you use the NPM repository for the AT protocol you can 'like' a post with this simple command:

    await agent.like(uri,cid)

This works - but you have to have installed and loaded the entire module to make it work, and then you're in module hell with versions and upgrades and the rest.

If you're ChatGPT you expect there's a simple API function, like this:

    await fetch('https://bsky.social/xrpc/app.bsky.feed.favoritePost',{...})

but there isn't one.

What's key about Bluesky is that it separates the application layer and the data layer. This matters a lot because it changes how we need to think about doing things like giving a post a 'like'. It's not simply a matter of performing a function. It's a matter of creating a record in a repository. Which repository? My repository.

My repository is currently hosted on Bluesky, but I can imagine that changing. The application I'm using is also hosted by Bluesky, but that could change as well. So we need to be smart about how we describe the content we're liking and where we're storing the record.

The Record

I first create the record I want to store. Like this:


        const record = {
            "$type": "app.bsky.feed.like",
            createdAt: new Date().toISOString(),
            subject: {
                uri: uri,
                py_type: 'com.atproto.repo.strongRef',
                cid: cid
            }
        }

In this record, I define the 'type' and a Bluesky 'like' record (and yeah, we could have any number of types). The 'subject' of this record is a specific post, which I identify as a 'stongRef' using both the 'uri' and the 'cid'.

The uri is the post's location as defined by the atmosphere (AT) protocol. It looks like this:   

  at://did:plc:v33us6ae36e4zl2qqijueffi/app.bsky.feed.post/3l576cazyjq2x  

The atmosphere address points to the repository where the post is located. The repository belongs to an individual who is identified by a DID - a distributed identifier. The repository is a 'post' repository, and the specific item has an identifier '3l576cazyjq2x'.

We can convert the AT address into a traditional web URL. The DID is associated with a 'handle', for example, 'guillecoru.bsky.social'. We can use the bsky.app to get that post:

    https://bsky.app/profile/guillecoru.bsky.social/post/3l576cazyjq2x

The cid is the post's content-based address. It looks like this:   

    bafyreiccpgycnovrqguhbqgthtqbpfiyvhk52svq33uox65ojqz6qqewi4  

The content ID (cid) was created by taking the content of the post and running it through a hash algorithm. You can read about the process here. I've written about it before.

The Save

Now I want to save my record to Bluesky. For this I will use a fetch() command. Here's what it looks like:

        const response = await fetch('https://bsky.social/xrpc/com.atproto.repo.createRecord', {
            method: 'POST',
            headers: {
                'Authorization': `Bearer ${accessToken}`,
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({
                collection: 'app.bsky.feed.like',
                repo: did,
                record: record
            }),
        });

Fetch is making an API request to post a new record. 

The headers contain my previously obtained access Token. I obtain this when I create a session by logging in to Bluesky. It's a long string of characters.

The body of my request specifies the repository I want to add the record to. This will be my repository, identified by my DID, which I've stored in a variable called 'did'. I obtained this from Bluesky when I logged in. The body also specifies the collection I want the record to belong to, and of course contains the record itself.

That's it! In the full function I do some error checking just to make sure everything went OK.

P.S.

This isn't the complete script. I just want to focus in this post on how to 'like' a post. You would still of course have to write the login script and get the post information. Those are exercises for another day.


Comments

Popular Posts