Skip to content

Instantly share code, notes, and snippets.

@JBGruber
Created January 15, 2024 08:49

Revisions

  1. JBGruber created this gist Jan 15, 2024.
    73 changes: 73 additions & 0 deletions rbsky
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,73 @@
    #!/usr/bin/Rscript

    # 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(atrrr)
    library(cli)
    library(lubridate, include.only = c("as.period", "interval"),
    quietly = TRUE, warn.conflicts = FALSE)
    if (!require("docopt", quietly = TRUE)) install.packages("docopt")
    library(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, ]
    cli({
    # headline from author • time since post
    cli_h1(c(col_blue(item$author_name), "",
    col_silver(ago(item$indexed_at))))
    # text of post in italic (not all terminals support it)
    cli_text(style_italic("{item$text}"))
    # 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
    cli_text("\n")
    })
    # wait a little before showing the next post
    Sys.sleep(args$timeout)
    }