The Waving Flag: Crossposting To Bluesky

Friday, 22 November 2024

Crossposting To Bluesky

Introduction

Last weekend saw a sudden surge in wargamers leaving Twitter for the Bluesky social network. I wonder why?

Thanks to Henry Hyde creating a starter pack for Historical Miniatures Wargaming I have acquired nearly 150 new followers in 48 hours. Bluesky starter packs allow new members to follow up to 150 people with one click. It's a nice feature.

So I thought it was time to automate posting from my blogs to Bluesky via their RSS feeds. I have already done this for the Fediverse so I had some idea what was required.

What follows applies to Linux. Windows and Mac users look away now.

[1] Autopost setup

Ideally, I wanted something from pypi.org similar to feediverse and better_feediverse. Not least because it's easy to keep things updated. A quick search yielded autopost which looked promising. Installation from pypi.org was straightforward:

pipx install autopost

I created a configuration file:

[[backend]]
type = "Bluesky"  
name = "@vexillia.me.uk@bluesky"
username = "vexillia.me.uk"
password = { type = "Embedded", value = "app password" }

Creating a Bluesky app password was a matter of minutes using this tutorial. The file was saved as:

/home/username/.autopost.toml

There were a few things that required the help of autopost's author, William Woodruff. He was very helpful and replied almost immediately via Github.

[2] Testing

I tested autopost in a terminal with the --dry-run switch:

autopost --dry-run --config-file /home/vexillia/.autopost.toml atom https://blog.vexillia.me.uk/feeds/posts/default

Then I checked it for real:

autopost --config-file /home/vexillia/.autopost.toml atom https://blog.vexillia.me.uk/feeds/posts/default

During testing, I deleted the resulting posts from Bluesky.

[3] Scripting

Autopost is "stateless" by design: it doesn't remember what it's posted. If the feed hasn't been updated it will post the same item again and again. This meant automation was not going to be as simple as adding a command to my list of cron jobs.

I've dealt with this "problem" before when I automated podget. My solution is:

  • store the title of the latest feed item in a tmp file,
  • before each run, read its contents,
  • check whether the title has changed
  • only run autopost if it has
  • store the new title in the tmp file

I reused quite a bit of the code from my podget script.

[4] Rsstail

Before I could write the automation script I had to find a way to read the title of the latest item in the RSS script. Thankfully, rsstail does just that. I installed it from the Ubuntu repositories:

sudo apt install rsstail

Rsstail can do lots with rss feeds. After reading the documentation I set it to return just the title of the latest item and checked the output in a terminal window:

rsstail -1 -u https://blog.vexillia.me.uk/feeds/posts/default -n 1

[5] Automation

Here's my final script it works when run locally and as part of cron job. The main part of the script is wrapped up as a function so it's easy to call it repeatedly for multiple feeds:

#!/bin/sh

checkFeed () {
# Set Autopost Feed Arguments
# -------------------
feed="--config-file /home/vexillia/.autopost.toml atom $2"

# Get title of the latest post
# -------------------
latest=$(rsstail -1 -u $2 -n 1)

# Read previous post title from file (if exists)
# -------------------
valuefile="/var/tmp/var_$1.dat"
if [ ! -f "$valuefile" ]; then
previous_file=""
else
previous_file=$(cat "$valuefile")
fi

# Test for new post, if found post to Bluesky & update feed data file
# -------------------
if [ "$latest" = "$previous_file" ]; then
   echo "$(date +%H:%M:%S) - Old post found, $1" >> /home/vexillia/System/scripts/log/autopost.log
else
   echo "$(date +%H:%M:%S) - New post found, $1" >> /home/vexillia/System/scripts/log/autopost.log
   /home/vexillia/.local/share/pipx/venvs/autopost/bin/autopost $feed
   echo "${latest}" > "$valuefile"
fi
}

# Add log header
# -------------------
echo "\n# -------------------\nDate: $(date '+%a %d %B, %Y%n%H:%M:%S') - Script started" >> /home/vexillia/System/scripts/log/autopost.log


# Check feeds using checkFeed function
# -------------------
checkFeed feed_1 https://blog.vexillia.me.uk/feeds/posts/default
checkFeed feed_2 https://blog.vexillia.me.uk/feeds/comments/default
checkFeed feed_3 https://vexillia.bearblog.dev/feed/

exit

[6] Script notes

If you are going to use this script then, apart from changing the feeds and my username to yours, I recommend starting with just one feed and if you have problems removing the function wrapper.

Once you are sure everything is working, I suggest you comment out the logging.

Much to my surprise, running rsstail under cron did not cause any problems and I didn't have to use a the full path (/user/bin/rsstail).

I did use the full path for autopost (just in case) but I didn't have to "activate" it. When I automated feediverse I had to "activate" the script before running it. This is why the autopost script can be run either locally or as a cron job. With feediverse I had to write separate scripts.

[7] Other options

Autopost will also post the same item to Mastodon and Reddit with one command. All that's required is a [[backend]] section for each target in the config file.

This means I could use this instead of feediverse to post to tabletop.social, but I'll leave things as they are for the time being.

[8] Closing remarks

Setting this up didn't take very long once I got autopost working with the right config file. Once again, I'd like to thank autopost's author, William Woodruff, for his work with autopost and in helping me get started: much appreciated.

2 comments :

Vexillia said...

At present the backend for autopost has an issue: it doesn't pick up the blog item tags at all. It should but it doesn't for some reason. This issue has been raised with the developer and should be resolved reasonably soon now the cause has ben identified.

Vexillia said...

This issue has been resolved with autopost v0.9.

Salute The Flag

If you'd like to support this blog why not leave a comment, or buy me a beer.