123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167 |
- #!/bin/sh
- #―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
- # Name: sfeed_mastodon
- # Desc: Post feed data from sfeed to the fediverse.
- # Reqs: curl, xargs
- # Date: 2023-11-16
- # Lisc: GPLv3
- # Auth: @jadedctrl@jam.xwx.moe
- #―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
- # Print a friendly usage message.
- usage() {
- echo "usage: $(basename $0) [-h] [-a FEDI_AUTH] SERVER_URL"
- echo "Posts sfeed(1) feed data from stdin to Mastodon-compatible servers."
- echo ""
- echo " -h print this message and exit"
- echo " -a the authorization token for your account"
- echo " -s the scope for posts, one of: public/unlisted/private/direct"
- echo " -t template for post contents"
- echo ""
- echo "To find your authorization token, you can snoop through request headers in"
- echo "your web-browser. In Firefox, this can be done through:"
- echo ' Developer Tools (F12) → Network → Headers'
- echo 'Look for your $FEDI_AUTH value in the Authorization header like so:'
- echo ' Authorization: Bearer $FEDI_AUTH'
- echo 'Either place this value in your $FEDI_AUTH environment variable, or pass it'
- echo "with -a."
- echo ""
- echo "The template (-t) is an HTML value for this script’s post format."
- echo "Post-related variables go within {{double-braces}}, and the following"
- echo "variables are recognized: title, url, desc, desc_short, unix_date."
- echo "By default, the template used is:"
- echo " <b>{{title}}</b><br>{{url}}<br><br><blockquote>{{desc_short}}</blockquote>"
- }
- # Deescape a URL-escaped string (percent-encoded), passed over stdin.
- url_deescape() {
- sed 's@+@ @g;s@%@\\x@g' \
- | xargs -0 printf "%b"
- }
- # Takes a post’s contents and create the corresponding client-API JSON.
- post_json() {
- local message_text="$1"
- printf '{ "content_type": "text/html", "visibility": "%s",' "$FEDI_SCOPE"
- printf '"status": "%s" }\n' "$message_text"
- }
- # Post a status with HTML content to the given Mastodon-compatible server.
- post_status() {
- local server="$1"
- local auth_token="$2"
- local message_text="$3"
- curl --request POST \
- --header "Authorization: Bearer $auth_token" \
- --header "Content-Type: application/json" \
- --data "$(post_json "$message_text" | tr -d '\n')" \
- "${server}/api/v1/statuses"
- }
- # Print an sfeed post line as per $TEMPLATE, with the following variables:
- # {{title}}, {{unix_date}}, {{url}}, {{desc}}, {{desc_short}}
- sfeed_post_text() {
- local sfeed_line="$1"
- local unix_date="$(echo "$line" | awk --field-separator '\t' '{print $1}')"
- local title="$(echo "$line" | awk --field-separator '\t' '{print $2}')"
- local url="$(echo "$line" | awk --field-separator '\t' '{print $3}' | url_deescape)"
- local desc="$(echo "$line" | awk --field-separator '\t' '{print $4}')"
- local desc_short="$(echo "$desc" | head -c250)"
- # Show that the description was truncated.
- if test "$(echo "$desc_short" | wc -c)" -gt 250; then
- desc_short="$desc_short […]"
- fi
- if test -z "$title"; then
- title="$url"
- fi
- # If there is nothing to post, then don’t stdout anything.
- if test -z "$url"; then
- return
- fi
- printf "$TEMPLATE" \
- | tr -d '|' \
- | sed "s|{{title}}|$title|g" \
- | sed "s|{{unix_date}}|$unix_date|g" \
- | sed "s|{{url}}|$url|g" \
- | sed "s|{{desc}}|$desc|g" \
- | sed "s|{{desc_short}}|$desc_short|g" \
- | sed 's|\\n||g' \
- | sed 's|"|\\"|g' \
- | tr -d ' \n'
- }
- # Post an sfeed feed entry, by line, to a Mastodon-compatible fedi server.
- post_sfeed_line() {
- local server="$1"
- local auth="$2"
- local line="$3"
- local message_text="$(sfeed_post_text "$line")"
- if test -n "$line" -a -n "$message_text"; then
- post_status "$server" "$auth" "$message_text"
- fi
- }
- TEMPLATE='<b>{{title}}</b><br>{{url}}<br><br><blockquote>{{desc_short}}</blockquote>'
- while getopts 'ha:t:' arg; do
- case $arg in
- h)
- usage
- exit 0
- ;;
- s)
- FEDI_SCOPE="$OPTARG"
- ;;
- a)
- FEDI_AUTH="$OPTARG"
- ;;
- t)
- TEMPLATE="$OPTARG"
- ;;
- esac
- done
- shift $((OPTIND-1))
- SERVER_URL="$1"
- if test -z "$FEDI_AUTH"; then
- 1>&2 echo 'You need to set the environment variable $FEDI_AUTH!'
- 1>&2 echo 'You can find your auth key by examining the "Authentication: Bearer" header'
- 1>&2 echo "used in requests by your server's web-client."
- 1>&2 echo 'In Firefox, F12→Network.'
- 1>&2 echo ""
- exit 2
- fi
- if test -z "$SERVER_URL"; then
- 1>&2 echo "No server specified!"
- 1>&2 echo "Make sure to provide a server base URL (like https://fedi.server) as the last argument."
- 1>&2 echo ""
- 1>&2 usage
- exit 3
- fi
- if test -z "$FEDI_SCOPE"; then
- FEDI_SCOPE="public"
- fi
- IFS="
- "
- while read -r line; do
- post_sfeed_line "$SERVER_URL" "$FEDI_AUTH" "$line"
- done
|