From 8ae5c1d67ec71494a2713f0603131d56979013fa Mon Sep 17 00:00:00 2001 From: Jaidyn Ann <10477760+JadedCtrl@users.noreply.github.com> Date: Sun, 3 Sep 2023 12:27:03 -0500 Subject: [PATCH] Init Support for Mastodon, JSON output --- bookmarks-dl.sh | 101 ++++++++++++++++++++++++++++++++++++++++++++ sources/mastodon.sh | 91 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 192 insertions(+) create mode 100755 bookmarks-dl.sh create mode 100755 sources/mastodon.sh diff --git a/bookmarks-dl.sh b/bookmarks-dl.sh new file mode 100755 index 0000000..19608c6 --- /dev/null +++ b/bookmarks-dl.sh @@ -0,0 +1,101 @@ +#!/bin/sh +#――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― +# Name: bookmarks-dl +# Desc: A script used to download remote bookmarks into the XBEL format. +# Auth: Jaidyn Ann +# Date: 2023-09-02 +# Reqs: lynx, jq +# Lisc: GPLv3 +#――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― + +SOURCE_DIRS="./sources/ $HOME/.local/libexec/bookmarks-dl/ /usr/local/libexec/bookmarks-dl/ /usr/libexec/bookmarks-dl/" + +usage() { + 1>&2 echo "usage: $(basename "$0") SOURCE ..." + 1>&2 echo " $(basename "$0") --list" + 1>&2 echo " $(basename "$0") --help" + 1>&2 echo "" + 1>&2 echo " SOURCE is a source of bookmarks." + 1>&2 echo " You can see a list of sources with '--list'." +} + + +# Return the paths to all available bookmarks-dl “source” scripts. +all_sources() { + find $SOURCE_DIRS -type f -name '*.sh' \ + 2> /dev/null +} + + +# Return the path to a specific bookmarks-dl source. +get_source() { + local source_name="$1" + all_sources \ + | grep "/$source_name.sh" \ + | head -1 +} + + +# List all available bookmarks-dl sources user-friendly-like. +list_sources() { + for source in $(all_sources); do + printf '%s\t%s\n' \ + "$(basename "$source" | sed 's/\.sh//')" \ + "$source" + done +} + + +# Given some HTML, return it’s plain-text and deescaped form. +html_text_deescape() { + lynx -dump -stdin +} + + +# Print a piped string in HTML-escaped form. +html_escape() { + json_escape \ + | jq -r '. | @html' +} + + +# Print a piped string in JSON-escaped format. +json_escape() { + sed 's!"!\\"!g' \ + | perl -pe 's!\n!\\n!' \ + | sed 's/^/"/' \ + | sed 's/$/"/' +} + + +SOURCE_NAME="$1" +case "$SOURCE_NAME" in + --list|list) + list_sources + exit 0 + ;; + --help|-h|help|'') + usage + exit 1 + ;; + *) + source "$(get_source "$SOURCE_NAME")" \ + 2> /dev/null > /dev/null + if test "$?" -ne 0; then + 1>&2 echo "The source '$SOURCE_NAME' couldn’t be found." + 1>&2 echo "Try '$(basename "$0") --list' to see a list of possible sources." + fi + ;; +esac + + +if test -z "$1"; then + usage + exit 1 +else + shift +fi + + +# Overloaded by the `source`-d bookmarks-dl “source.” +source_start $@ diff --git a/sources/mastodon.sh b/sources/mastodon.sh new file mode 100755 index 0000000..b941dc7 --- /dev/null +++ b/sources/mastodon.sh @@ -0,0 +1,91 @@ +#!/bin/sh +#――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― +# Name: bookmarks-dl: Mastodon +# Desc: A source for bookmarks-dl that fetches bookmarks from Mastodon/Pleroma. +# Auth: Jaidyn Ann +# Date: 2023-09-02 +# Reqs: curl, jq +# Lisc: GPLv3 +#――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― + +usage() { + 1>&2 echo "usage: bookmarks-dl mastodon [-h] [-a USER_TOKEN] -u USERNAME -d DOMAIN" + 1>&2 echo "" + 1>&2 echo " -h print this message and exit" + 1>&2 echo " -a the authorization token for your account; see below" + 1>&2 echo " -u account username" + 1>&2 echo " -d the server’s domain name" +} + + +# Fetch all of a user’s Mastodon/Pleroma bookmarks. +fetch_bookmarks() { + local auth="$1" + local domain="$2" + local url="$3" + if test -z "$url"; then + url="https://$domain/api/v1/bookmarks?limit=40" + printf "[" # Start the JSON array + fi + + local header_file="$(mktemp)" + curl -H "Authorization: Bearer $auth" \ + -D "$header_file" \ + "$url" \ + | bookmarks_parse + + local next_url="$(header_next_link "$header_file")" + rm "$header_file" + if test -n "$next_url"; then + fetch_bookmarks "$auth" "$domain" "$next_url" \ + | sed 's/^},},/}]/' # Two },}, means end of JSON array + fi +} + + +source_start() { + local auth="" + local domain="" + while getopts 'ha:u:d:' arg; do + case $arg in + h) + usage + exit 1 + ;; + a) + auth="$OPTARG" + ;; + d) + domain="$OPTARG" + ;; + esac + done + + if test -z "$auth" -o -z "$domain"; then + usage + exit 5 + else + fetch_bookmarks "$auth" "$domain" + fi +} + + +# Given a page of /api/v1/bookmarks, parse into the simple bookmarks-dl format +bookmarks_parse() { + jq -r '.[] | { "desc": .content, "href": .url, "added": .created_at }' \ + | sed 's/^}/},/' \ + | head -n-1 + printf '},' +} + + +# If curl’s HTTP response contains a “link” header for pagination, return the +# “next” page’s URL. +header_next_link() { + local header_file="$1" + grep '^link:' "$header_file" \ + | tr -d ' ' \ + | tr '[A-Z]' '[a-z]' \ + | sed 's/>;rel="next",.*//' \ + | sed 's/link: