Poor Dude’s Janky Bluesky Feed Reader CLI Via atrrr

[This article was first published on Johannes B. Gruber on Johannes B. Gruber, and kindly contributed to R-bloggers]. (You can report issue about the content on this page here)
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

Have you ever wanted to see your favourite social media posts in your command line? No? Me neither, but at least hrbrmstr has a few months ago. Or to be honest, I don’t know which social media site he prefers, but Bluesky is currently my favourite. With the ease of use and algorithmic curation that I loved about Twitter before its demise and the super interesting and easy to work with AT protocol, which should make Bluesky “billionaire-proof”1, I’m hopeful that this social network it here to stay.

Recently, I have published the atrrr package with a few friends, so I thought I could remove the pesky Python part from hrbrmstr’s command line interface. Along the way, I also looked into how one can write a command line tool with R. I really love using command line tools2 and was always a bit disappointed that people don’t seem to write them in R. After spending some time on this, I have to say: it’s not that bad, especially given the packages docopt and cli, but it’s definitly a bit more manual than in Python.

But let’s have a look at the result first:

And here is of course the commented source code (also available as a GitHub Gist):


# Command line application Bluesky feed reader based on atrrr.
# Make executable with `chmod u+x rbsky`.
# If you are on macOS, you should replace the first line with:
# #!/usr/local/bin/Rscript
# Not sure how to make it work in Windows ¯\_(ツ)_/¯
# based on https://rud.is/b/2023/07/07/poor-dudes-janky-bluesky-feed-reader-cli-via-r-python/

library(lubridate, include.only = c("as.period", "interval"), 
        quietly = TRUE, warn.conflicts = FALSE)
if (!require("docopt", quietly = TRUE)) install.packages("docopt")

# function to displace time since a post was made
ago <- function(t) {
  as.period(Sys.time() - t) |>
    as.character() |>
    tolower() |>
    gsub("\\d+\\.\\d+s", "ago", x = _)

# docopt can produce some documentation when you run `rbsky -h`
doc <- "Usage: rbsky [-a ALGO] [-n NUM] [-t S] [-h]

-a --algorithm ALGO   algorithm used to sort the posts [e.g., \"reverse-chronological\"]
-n --n_posts NUM      Maximum number of records to return [default: 25]
-t --timeout S        Time to wait before displaying the next post [default. 0.5 seconds]
-h --help             show this help text"

# this line parses the arguments passed from the command line and makes sure the
# documentation is shown when `rbsky -h` is run
args <- docopt(doc)
if (is.null(args$n_posts)) args$n_posts <- 25L
if (is.null(args$timeout)) args$timeout <- 0.5

# get feed
feed <- get_own_timeline(algorithm = args$algorithm,
                         limit = as.integer(args$n_posts),
                         verbose = FALSE)

# print feed
for (i in seq_along(feed$uri)) {
  item <- feed[i, ]
    # headline from author • time since post
    cli_h1(c(col_blue(item$author_name), " • ",
    # text of post in italic (not all terminals support it)
    # print quoted text if available
    quote <- purrr::pluck(item, "embed_data", 1, "external")
    if (!is.null(quote)) {
      cli_blockquote("{quote$title}\n{quote$text}", citation = quote$uri)
    # display that posts contains image(s)
    imgs <- length(purrr::pluck(item, "embed_data", 1, "images"))
    if (imgs > 0) {
      cli_text(col_green("[{imgs} IMAGE{?S}]"))
    # new line before next post
  # wait a little before showing the next post

I added the location of the file to my PATH3 with export PATH="/home/johannes/bin/:$PATH" to make it run without typing e.g., Rscript rbsky or ./rbsky. And there you go. If you want to explore how to search and analyse posts from Bluesky and then post the results via R, have a look at the atrrrpkgdown site: https://jbgruber.github.io/atrrr/.

  1. Once the protocol fulfils its vision that one can always take their follower network and posts to a different site using the protocol.↩︎

  2. I liked this summary of reasons to use them https://youtu.be/Q1dwzi5DKio.↩︎

  3. The PATH environment variable is the location of one or several directories that your system searches for executables.↩︎

To leave a comment for the author, please follow the link and comment on their blog: Johannes B. Gruber on Johannes B. Gruber.

R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

Never miss an update!
Subscribe to R-bloggers to receive
e-mails with the latest R posts.
(You will not see this message again.)

Click here to close (This popup will not appear again)