#!/usr/bin/env sh # # by Siddharth Dushantha # VERSION="1.0.0" # Everything related to 'tmpsms' will be stored in this directory. Once the # computer get restarted, this directory gets deleted. TMPSMS_DIR="/tmp/tmpsms" # The phone number that the user has selected gets stored in this file so that # the do not have reselect at ever run. TMPSMS_PHONE_NUMBER="$TMPSMS_DIR/phonenumber.txt" # 'fzf' is used to allow the user to select a phone number. This variable # stores extra arguments which the user might to provide, so that 'fzf' # behaves to their liking. FZF_ARGUMENTS="" # The temporary SMS service is provided by Upmasked API="https://upmasked.com" usage(){ # Using 'cat << EOF' we can easily output a multiline text. This is much # better than using 'echo' for each line or using '\n' to create a new line. cat <] tmpsms init [--fzf ] tmpsms -h | --version When called with no options or commands, tmpsms lists the 3 newest messages. Options -h, --help Show this help message -c, --count Only show the newest messages --version Show version Commands init Initialize a new phone number by selecting one from the available ones using 'fzf' --fzf Extra arguments to use for 'fzf' EOF } print_error(){ # Print error message # # The first argument provided to this function will be the error message. # Script will exit after printing the error message. printf "%s\n" "Error: $1" >&2 exit 1 } select_phone_number(){ # There are 2 ways which this function is called in this script. # [1] The user wants to initilize a new phone number by running 'tmpsms init' # [2] The user runs 'tmpsms' to check for new messages, but $TMPSMS_PHONE_NUMBER # does't exist. Therefore they have to select phone number before we can # show them the messages. # # When the function 'select_phone_number()' is called with the argument 'true' # that means this function was called becaues the user ran 'tmpsms init' # # We need this variable so we can know whether or not we need to show the user # the phone number they have selected. If they ran 'tmpsms init', then we will # show them the phone number they selected. This is so that they can easily # copy and paste it to whatever site that needs the phone number. EXTERNALLY=${1:-false} # Fetch the available phone numbers DATA=$(curl -s "$API/api/sms/numbers") # Using 'jq' we are able to get the length of the JSON data retreived from # API. The length indicates the the total number of phone numbers available. DATA_LENGTH=$(printf %s "$DATA" | jq length) # This is where we store the phone numbers which then gets shown to the user # through 'fzf' so that they can select one. PHONE_NUMBERS="" index=1 while [ $index -le "$DATA_LENGTH" ]; do # Since arrays in JSON data start at 0, we must subtract # the value of $index by 1 so that we dont miss one of the # phone numbers in the array PHONE_NUMBER_INFO=$(printf %s "$DATA" | jq -r ".[$index-1]") PHONE_NUMBER=$(printf %s "$PHONE_NUMBER_INFO" | jq -r ".number") COUNTRY_CODE=$(printf %s "$PHONE_NUMBER_INFO" | jq -r ".country") PHONE_NUMBERS="$PHONE_NUMBERS$COUNTRY_CODE +$PHONE_NUMBER\n" index=$((index+1)) done # By default we use 'fzf' without any arguments in order to display the # phone numbers they can use. If the '--fzf' argument is passed along with # 'fzf' arguments, 'tmpsms' will make sure to use them. FZF_COMMAND="fzf" [ -n "$FZF_ARGUMENTS" ] && FZF_COMMAND="fzf $FZF_ARGUMENTS" # If the user did not select a phone number then quit 'tmpsms' as the # user might have just wanted to check if there were any new number # that they could use. SELECTION=$(printf %b "$PHONE_NUMBERS" | $FZF_COMMAND) [ -z "$SELECTION" ] && print_error "Phone number was not selected" # Store the selected phone number in $TMPSMS_PHONE_NUMBER for later use printf %s "$SELECTION" > "$TMPSMS_PHONE_NUMBER" # If the user ran 'tmpsms init', then show them their selection [ "$EXTERNALLY" = true ] && printf "%s\n" "$SELECTION" } list_messages(){ # By default, the 3 newest messages are shown. But if the user would like # to see more of the messages, they can provide how many they want to see # by using the '--count' option. COUNT="${1:-3}" # The provided value to '--count' must be an interger. We can verify that it is # an integer by checking if $COUNT matches the regex. REGEX='^[0-9]+$' if ! printf %s "$COUNT" | grep -Eq "$REGEX";then print_error "'$COUNT' is not an integer" fi # If /tmp/tmpsms/phonenumber.txt does not exist or is empty that means that # the user has not initialized a phone number yet. [ ! -s "$TMPSMS_PHONE_NUMBER" ] && print_error "A phone number must be initilzied in order to view the messages" # The country code is needed because it gets displayed to the user. It may # be useful for the user to know which country the phone number is from # so that they dont have to guess by looking at the area code. COUNTRY_CODE=$(awk -F" " '{print $1}' < $TMPSMS_PHONE_NUMBER) PHONE_NUMBER=$(awk -F"+" '{print $2}' < $TMPSMS_PHONE_NUMBER) DATA=$(curl -s "$API/api/sms/messages/$PHONE_NUMBER") # Even though we are using the phone numbers that are available on # upmasked.com, there is a chance that they might remove one of the numbers. # The checking needs to be done in case the phone number that is stored in # $TMPSMS_PHONE_NUMBER has been removed. if printf %s "$DATA" | grep -Eq "Not Found"; then print_error "Looks like the phone number '+$PHONE_NUMBER' no longer exists. Initialize a new one and try again." fi DATA_LENGTH=$(printf %s "$DATA" | jq length) # If the number of messages the user wants to view is greater than the # number of messages that are available, then make sure to show # all the messages that are available. [ "$COUNT" -gt "$DATA_LENGTH" ] && COUNT="$DATA_LENGTH" # Show a nice little header before showing the messages printf "%s\n\n" "[ Messages for +$PHONE_NUMBER ($COUNTRY_CODE) ]" # All the messages get stored in here MESSAGES="" index=1 while [ $index -le "$COUNT" ]; do # Since arrays in JSON data start at 0, we must subtract # the value of $index by 1 so that we dont miss one of the # messages in the array MESSAGE_DATA=$(printf %s "$DATA" | jq -r ".[$index-1]") BODY=$(printf %s "$MESSAGE_DATA" | jq -r ".body" | tr "\n" " ") SENDER=$(printf %s "$MESSAGE_DATA" | jq -r ".originator") # The '||' is used as a divider for 'column'. 'column' will use this # divider as a point of reference to create the division. By default # 'column' uses a blank space but that would not work in our case as the # message could have multiple white spaces and 'column' would # split the words that are seperated by white space, in different columns. MESSAGES="$MESSAGES$SENDER ||$BODY\n" index=$((index+1)) done # Show the messages cleanly printf "%b" "$MESSAGES" | column -t -s "||" } main(){ # Iterate the array of dependencies and check if the user has them installed. for dependency in jq curl fzf; do if ! command -v "$dependency" >/dev/null 2>&1; then print_error "Could not find '$dependency', is it installed?" fi done # Create the $TMPSMS_DIR directory and dont throw any errors # if it already exists mkdir -p "$TMPSMS_DIR" # If no arguments are provided just show the messages [ $# -eq 0 ] && list_messages && exit 0 while [ "$1" ]; do case "$1" in init) case "$2" in --fzf) FZF_ARGUMENTS="$3" && select_phone_number true ;; "") select_phone_number true ;; esac ;; --help | -h) usage && exit ;; --count | -c) list_messages "$2" && shift 2;; --version) printf %s "$VERSION" && exit ;; -*) print_error "option '$1' does not exist" ;; *) print_error "command '$1' does not exist" ;; esac shift done } main "$@"