#!/bin/bash
# This file is in the public domain.
# Send an SMS using Telesign API
set -eu

# Check shared secrets
if [ -x "$TELESIGN_AUTH_TOKEN" ]
then
    echo "TELESIGN_AUTH_TOKEN not set in environment"
    exit 1
fi

if [ $# -ne 1 ]; then
    echo "Usage: $0 <phone_number>" 1>&2
    exit 1
fi

PHONE_NUMBER="$1"
MESSAGE=$(cat -)

TMPFILE=$(mktemp /tmp/telesign-sms-logging-XXXXXX)

RESPONSE=$(curl --silent --show-error --fail \
  --url https://rest-api.telesign.com/v1/messaging \
  --request POST \
  --header "Authorization: Basic $TELESIGN_AUTH_TOKEN" \
  --header "Content-Type: application/x-www-form-urlencoded" \
  --data account_livecycle_event=transact \
  --data "phone_number=$PHONE_NUMBER" \
  --data-urlencode "message=$MESSAGE" \
  --data "message_type=OTP")

echo "$RESPONSE" > "$TMPFILE"
REFERENCE_ID=$(jq -r '.reference_id' "$TMPFILE")

if [ "$REFERENCE_ID" == "null" ];
then
    echo "Telesign: failed to retrieve reference ID for message to $PHONE_NUMBER." 1>&2
    echo "$RESPONSE" 1>&2
    exit 1
fi

STATUS_CODE=$(echo "$RESPONSE" | jq -r '.status.code')

case "$STATUS_CODE" in
    "200")
	# Delivered to headset. Should basically never happen here.
        echo "Telesign: message delivered successfully to $PHONE_NUMBER." 1>&2
	exit 0
        ;;
    "203"|"292"|"295")
	# Delivered to gateway
	sleep 2
        ;;
    "207"|"211"|"220"|"221"|"222"|"231"|"237"|"238")
	# Failure to deliver (hard)
	echo "Telesign: could not deliver message to $PHONE_NUMBER: $STATUS_CODE" 1>&2
	exit 1
        ;;
    "210")
	# Temporary phone error
	;;
    "250")
	# Final status unknown
	echo "Telesign: final status unknown for message to $PHONE_NUMBER, assuming success" 1>&2
	exit 0
	;;
    "290")
	# Message in progress, go into loop below
	sleep 2
        ;;
    "502"|"503"|"504"|"505"|"506"|"507"|"508"|"509"|"510"|"511"|"512"|"513"|"514"|"515"|"517"|"520"|"521")
	echo "Telesign: carrier problem ($STATUS_CODE) delivering to $PHONE_NUMBER" 1>&2
	exit 1
	;;
    "10000")
	# Internal error at telesign...
	echo "Telesign: internal error delivering to $PHONE_NUMBER" 1>&2
        echo "$RESPONSE" 1>&2
	exit 1
	;;
    "10019"|"10020")
	# Rate limit exceeded. Treating as hard failure for now.
	echo "Telesign: Rate limit exceeded ($STATUS_CODE) delivering to $PHONE_NUMBER" 1>&2
        echo "$RESPONSE" 1>&2
	exit 1
	;;
    *)
	# Many possible status codes for failure...
	echo "Telesign: Message delivery to $PHONE_NUMBER failed: $STATUS_CODE" 1>&2
        echo "$RESPONSE" 1&>2
	exit 1
	;;
esac

MAX_ITERATIONS=12

# Poll for message status
echo "Polling message status (reference_id: $REFERENCE_ID)..." 1>&2
for N in $(seq 1 "$MAX_ITERATIONS")
do
    STATUS_RESPONSE=$(curl --silent --show-error --fail \
      --url "https://rest-api.telesign.com/v1/messaging/$REFERENCE_ID" \
      --header "Authorization: Basic $TELESIGN_AUTH_TOKEN")

    echo "$STATUS_RESPONSE" >> "$TMPFILE"

    STATUS_CODE=$(echo "$STATUS_RESPONSE" | jq -r '.status.code')
    DESCRIPTION=$(echo "$STATUS_RESPONSE" | jq -r '.status.description')

    case "$STATUS_CODE" in
	"200")
	    # Delivered to headset. Great!
            echo "Telesign: message delivered successfully to $PHONE_NUMBER." 1>&2
            exit 0
            ;;
	"203"|"290"|"292"|"295")
	    # Delivered to gateway, wait a bit for an update
	    sleep 2
            ;;
	"210")
	    # Temporary phone error
	    sleep 15
	    ;;
	"207"|"211"|"220"|"221"|"222"|"231"|"237"|"238")
	    # Failure to deliver (hard)
	    echo "Telesign: could not deliver message to $PHONE_NUMBER ($STATUS_CODE)" 1>&2
	    exit 8
            ;;
	"250")
	    # Final status unknown
	    echo "Telesign: final status for delivery to $PHONE_NUMBER unknown, assuming success" 1>&2
	    exit 0
	    ;;
	"502"|"503"|"504"|"505"|"506"|"507"|"508"|"509"|"510"|"511"|"512"|"513"|"514"|"515"|"517"|"520"|"521")
	    echo "Telesign: carrier problem ($STATUS_CODE) for message to $PHONE_NUMBER" 1>&2
	    exit 7
	    ;;
	"10000")
	    # Internal error at telesign...
	    echo "Telesign: internal error for message to $PHONE_NUMBER" 1>&2
	    exit 9
	    ;;
	"10019"|"10020")
	    # Rate limit exceeded. Treating as hard failure for now.
	    echo "Telesign: rate limit exceeded for message to $PHONE_NUMBER" 1>&2
	    exit 10
	    ;;
	*)
	    # Many possible status codes for failure...
	    echo "Telesign: message delivery to $PHONE_NUMBER failed: $STATUS_CODE" 1>&2
            echo "$RESPONSE" 1&>2
	    exit 11
	    ;;
    esac
done

echo "Telesign: unclear delivery status ${STATUS_CODE:-} (${DESCRIPTION:-}) for message to $PHONE_NUMBER after ${MAX_ITERATIONS:-} iterations. Assuming failure." 1>&2
exit 12
