GoToSocial Push notifications using Pushover

       773 words, 4 minutes

GoToSocial does not seem to support push notifications for iOS applications. As far as I understand, this is because it doesn’t implement the Mastodon Web Push API . But GtS exposes a notification API. So let’s poll this API and use Pushover to get push notifications on the iOS devices.

How it works

A shell script is scheduled to run every minutes. It will query GoToSocial’s notification API and discover if new notifications are available. In such case, it will parse the notification list and call Pushover’s API for each one of them. In the end, the user gets a Pushover notification for every available GoToSocial notifications.

Disclaimer: I’m targeting iOS devices because those are what I use. But the whole process should work with any Pushover client.

Pushover

I’m using Pushover whenever I want to be notified of events on my iPhone. That includes Home Assistant, collectd, Uptime Kuma and various servers scripts. All that is needed is an application token.

Log in to your Pushover account and write down Your User Key.

Scroll down to the Your Applications section and click Create an Application/API Token. Fill-in the Name and the optional Description for this token. Select an Icon if you wish. Check the box to agree to ToS and click Create Application.

Write down your API Token/Key.

GoToSocial

Getting an application token for GtS is detailed here .

Create an application and write down the value of client_id and client_secret:

#  curl -s -X POST 'https://gotosocial.example/api/v1/apps' \
  -H 'Content-Type:application/json' \
  -d '{
    "client_name": "gts-notif",
    "redirect_uris": "urn:ietf:wg:oauth:2.0:oob",
    "scopes": "read"
  }'

Authorize your application using a Web navigator and browsing to:
https://gotosocial.example/oauth/authorize?client_id=INSERT_CLIENT_ID&redirect_uri=urn:ietf:wg:oauth:2.0:oob&response_type=code

If you’re not already logged in to GtS, enter your credentials and click the Sign in button. Review the authorization request and click the Allow button.

Write down your out-of-band token with scope "read".

Using the values you wrote down earlier, get an application token by issuing an extra curl command and write down the value of the access_token field.

# curl -s -X POST 'https://gotosocial.example/oauth/token' \
  -H 'Content-Type:application/json' \
  -d '{
    "redirect_uri": "urn:ietf:wg:oauth:2.0:oob",
    "client_id": "INSERT_CLIENT_ID",
    "client_secret": "INSERT_CLIENT_SECRET",
    "grant_type": "authorization_code",
    "code": "INSERT_OOB_TOKEN"
  }'

You can check that your access token works with an API call such as:

curl -s \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer INSERT_ACCESS_TOKEN' \
  'https://gotosocial.example/api/v1/accounts/verify_credentials'

Notification script

My script runs on a NetBSD server. It uses bash(1), curl(1) and jq(1). Installing those tools here goes like this:

# pkgin in bash curl jq

The script itself goes like this:

#!/usr/pkg/bin/bash
#
# Check for GtS notifications and use Pushover to notify.

PATH="/bin:/sbin:/usr/bin:/usr/sbin:/usr/pkg/bin:/usr/pkg/sbin"

# Pushover configuration
PUSH_USER="INSERT_PUSHOVER_USER_KEY"
PUSH_TOKEN="INSERT_PUSHOVER_API_KEY"

# GoToSocial configuration
GTS_HOST="gotosocial.example"
GTS_TOKEN="INSERT_GOTOSOCIAL_ACCESS_TOKEN"

# Last notification is stored and read as $LAST_NOTIF.
TMPFILE="/tmp/$(basename """$0""")_tmp"
if [ -f "$TMPFILE" ]; then . "$TMPFILE"; fi

# Send Pushover notification
call_pushover() {
# parameters: $1 is PUSH_TITLE, $2 is PUSH_TEXT
    curl --silent --output /dev/null --show-error \
      -F "token=${PUSH_TOKEN}" \
      -F "user=${PUSH_USER}" \
      -F "title=${1}" \
      -F "message=${2}" \
      https://api.pushover.net/1/messages.json
}

# If we don't know what the last notification was, just grab the latest one
# Else, let's grab no more than 20.
if [ -z "$LAST_NOTIF" ]; then
    URL_PARAMS="?limit=1"
else
    URL_PARAMS="?limit=20&since_id=$LAST_NOTIF"
fi

# Get the GtS notification(s) and send Pushover one(s).
NEW_NOTIF=""
curl -s \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer ${GTS_TOKEN}" \
  "https://${GTS_HOST}/api/v1/notifications${URL_PARAMS}" \
  | jq -r '.[] | { id, type, created_at, "acct": .account.display_name,
    "content": (if .status.content == null then "" else .status.content end)
    | gsub("<.+?>"; "") | .[0:100] }
    | [ .id, .type, .created_at, .acct, .content ]
    | @csv' | while read -r NOTIF; do
    FIELDS=(); OFS=$IFS; IFS='","'

    # Convert the CVS line into a shell array.
    for i in $NOTIF; do FIELDS+=($i); done
    IFS=$OFS

    # Save the last notification ID for further calls.
    if [ -z "$NEW_NOTIF" ]; then
        NEW_NOTIF="${FIELDS[0]}"
        echo "LAST_NOTIF=$NEW_NOTIF" > "$TMPFILE"
    fi

    # Set an emoji depending on the type of notification.
    if   [ "${FIELDS[1]}" = "favourite" ]; then FIELDS[1]="❤️";
    elif [ "${FIELDS[1]}" = "follow" ];    then FIELDS[1]="👥";
    elif [ "${FIELDS[1]}" = "mention" ];   then FIELDS[1]="💬";
    elif [ "${FIELDS[1]}" = "reblog" ];    then FIELDS[1]="🚀";
    elif [ "${FIELDS[1]}" = "update" ];    then FIELDS[1]="📝";
    fi

    # Have Pushover notify the device.
    call_pushover "${FIELDS[3]}" "${FIELDS[1]} ${FIELDS[4]}"
done

exit 0
#EOF

I set the executable bit on the script and schedule it from the crontab:

# chmod 0700 /home/scripts/gts-notif

# crontab -l
(...)
# Check for GoToSocial notification
*  *  *  *  *  /home/scripts/gts-notif 2>&1

This is what it looks like on my iPhone after a few testings:

I can now get push-notified when someone communicates with @chirp@nogoo.me , the communication account on the Fediverse for the NoGoo.me service .

That’s All Folks! Happy notifications!