Bluesky Bot

I've been playing around with Bluesky lately and building a bot to automatically share Words on Wednesday posts to that platform.

 

I'm not stranger to social media automation, but it's also never been my strong suit. Back in August of 2017, I had automation set up for a few social media platforms with presumably OnlyWire. That worked for a while, but by August of 2018, I had swapped to dlvr.it for my social media sharing needs.

At some point along the line, probably around September of 2024, dlvr.it stopped sharing to my Words on Wednesday Facebook Page. Either that, or I was manually sharing those posts each week and just gave up. In either case, that page has been basically dead for over a year now.

In the past year or so, I've made a point to visit Facebook less. It was my sort of default state when I would unlock my phone to visit Facebook and doom scroll for a bit. I recognized that because the algorithm prioritizes things that make you angry, I was seeing a lot of content from anti-vaxxers, flat earthers, and tons of other pseudoscience groups that I disdain. Beyond that, I was letting it get under my skin and negatively affect my mood. I had made too much of a habit of engaging in social media and allowed it too much control over my life.

In the absence of Facebook, I had an account on X (can we just call it Twitter?). That was fine for short-form posts until Elon Musk turned the site into an AI dumpster fire. Google+ died, as it probably should have from the very beginning. Instagram was never one that I really leaned into, despite having an account there as well.

None of those scratched that sort of itch to passively consume posts from a curated feed. Eventually, I heard about Bluesky as a lot of my friends started migrating to it in the wake of Elon's X overhaul. I held out at first, since I needed another social media platform about as much as I needed another hole in the head. After some time, I decided to try it out. A platform based on the same architecture as Twitter without the Musk ick seemed worth a look.

Not having algorithmic posts thrown at me purely for engagement felt nice. I could pick what topics I was interested in, and Bluesky would show me that, plus related topics. It was refreshing to have some control over what I saw, but also get news and entertainment in small and easily digested chunks.

As I was looking into what all you could do on Bluesky, I discovered that the platform is really bot-friendly. They have tons of resources for how to create bots, what those can post, and generally how to interact with the platform in an automated and programmatic way. Immediately, I considered that a Words on Wednesday bot could be a fun and interesting project.

I made a fork of the GitHub project and started playing around with it. Given we use JavaScript at work for several projects and I could use some extra practice with it, I went with that version. I manually posted a couple of times just to have some content on the page, then got the default smiley face posting from the bot.

 

After I integrated the bot with the Words on Wednesday profile, there was a sequence of problem solving steps to get it working the way I wanted. I had to figure out how to read the RSS feed from Blogger. I could read in some of the posts, but not all, so I had to figure out how to consume a paginated feed. After I could read subsequent pages of posts, I had to aggregate them into a single array.

Each subsequent step gave me a more functional bot, and gave me a new problem to solve. It was engaging and addictive in a way that I haven't felt in a long time with software development. I got really familiar with the support forums for Blogger and learned a lot about a platform I've been using for years.

 

After I got the RSS consumption working for Blogger, I had to figure out how to post those links to Bluesky. I figured out that a lot of the magic that Bluesky does when you manually copy a link into a post isn't present with an automated post. If your bot includes a link in a text post, it just comes through as plain text. I couldn't reasonably expect would-be readers to copy a link from a post into their browser; it had to just work.

I did finally get links working, including a preview of the post. It didn't have an image from the post, but that's a problem we could tackle later. I was able to get a random blog post pulled in from RSS and shared to Bluesky by simply running a Node.js project. That was a huge win.

A random post was neat, but for the bot to function properly as an automation, I would need it to run on its own as a cron job. I got the cron schedule figured out, and it would properly trigger if the project was running when the scheduled time arrived, but it didn't make sense to have an IDE up and a project running constantly. It was automatic, sure, but it was really clunky.

For a while, I considered packaging the project as an .exe and running that on the same machine I use for our Plex and Minecraft servers. It's a ThinkPad T-14 that I won from a work raffle, and it's always on anyway. I figured social media automation seemed related enough and it wouldn't be using up any more electricity than it was already consuming by staying on.

While I was continuing to work on the bot, I discovered GitHub Workflows. These are basically jobs that GitHub will automatically run from your project repo on a schedule. Fortunately, GitHub allows you to run these workflows for free within certain limits. Since I was only looking to post once a week on Wednesdays, this was a non-issue for me.

 

The workflows are pretty easy to get running after you get set up. You simply create yml files in a sub-folder of your repo and export the functions you want called. Those can then be called directly on demand or automatically via the cron scheduling. I crutched pretty heavily on Copilot for help there, but I finally got the automation running.

It occurred to me that I could go beyond just sharing new posts on Wednesdays. I could set up posts to share multiple times through the week. Thirsty Thursday Eve is already a monthly segment on the blog, so having a random post with that label share every Thursday was an easy connection to make. I had to research how to filter the RSS feed to a particular tag, but I got that working pretty quickly.

After Thirsty Thursday, I came up with a few additional weekly ideas. Turn the Page Tuesday could be when I share a random Book Report post. Shuffle Saturday could be just a random post without any label restrictions. I also considered Flashback Friday to share old WordPress posts, but that would be a separate RSS feed to figure out.

I did some additional investigation and found that WordPress uses an API to retrieve a list of posts. With my backend development experience, that wasn't very tough to figure out. After formatting that array of posts to look and behave similar to the Blogger posts, it was quick and easy to share a random post via the same mechanism I was already using.

After I got the code pushed up and the workflow scheduler configured, I found that the automation for Tuesday, Thursday, Friday, and Saturday worked, but Wednesday never posted. I had some logic to check for a post made within the past 24 hours (so that I don't accidentally share the same post on subsequent weeks where a new post didn't get published), but those conditions seemed to be satisfied.

I finally discovered that the workflows use UTC for their scheduled time, and I was operating on Eastern time. The automation worked when I ran the project locally because the cron schedule was using my system time. In a hosted environment, nothing indicated a specific time zone, so they default to using UTC. I looked back at the posts for the other days, and sure enough, they were going out a few hours before when I expected them to.

With that discovery, I updated the cron schedules in the yml files for each day to be 5 hours ahead. This would make EST operate as expected and EDT run an hour later. I could've added some logic to convert for Daylight Saving Time, but I figured it wasn't worth the effort. An hour forward or backward wouldn't matter much as long as it was AFTER the new post got published on Wednesday. You can't exactly automate sharing of a blog post if that post hasn't been published yet.

 

I still haven't gotten images coming through with the link and preview. I got an image, but lost the rest of the content. Then, I got the image with the preview text, but no link. Finally, I got a link text, but it isn't clickable. I think it's something I can figure out by experimenting with formatting, but as a side project, I'm not dedicating a huge amount of time with it.

It's been a super fun process to figure out Bluesky and build a custom automation bot. Potentially when I get the Bluesky bot exactly where I want it, I might go back and see if I can build a Facebook bot to revive that page. Either way, it's interesting to get a look behind the curtain with social media and build a neat project with real world functionality.

Comments