I’m working on some server scripting and I wanted to find a way to make sure I get proper alerts. I tried hard getting Twilio working cheaply, but that failed. So I remembered that I use Prowl for other things on my phone–so why not just send more alerts that way?
So, again with the help of ChatGPT I have made a terrible monstrosity:
#!/bin/bash
# Exit if any command fails, if an unset variable is used, or if a command in a pipeline fails
set -euo pipefail
# Default values
application="Shell Notification"
priority=0
event="Event"
message=""
logfile="/var/log/send-prowl-alert.log"
url=""
# Usage information
usage() {
echo "Usage: $0 --message=<message> [--application=<application>] [--event=<event>] [--description=<description>] [--priority=<priority>] [--url=<url>]"
echo "Required:"
echo " --message=<message> A description of the event, generally terse"
echo " Maximum of 10000 bytes"
echo "Optional:"
echo " --application=<application> The name of the application (default: 'Shell Notification')"
echo " Maximum of 256 bytes"
echo " --event=<event> The name of the event or subject of the notification (default: 'Event')"
echo " Maximum of 1024 bytes"
echo " --priority=<priority> The priority of the alert (default: 0)"
echo " An integer value ranging [-2, 2] representing:"
echo " -2 Very Low"
echo " -1 Moderate"
echo " 0 Normal"
echo " 1 High"
echo " 2 Emergency"
echo " Emergency priority messages may bypass quiet hours according to the user's settings."
echo " --url=<url> The URL which should be attached to the notification"
echo " Maximum of 512 bytes"
echo " --help Displays this help message"
}
# URL Encodes a string
urlencode() {
local string="$1"
local length="${#string}"
local i
for ((i = 0; i < length; i++)); do
local c="${string:i:1}"
case $c in
[a-zA-Z0-9.~_-])
printf '%s' "$c"
;;
*)
printf '%%%02X' "'$c"
;;
esac
done
}
# Check if the script is being run manually or via cron
if [[ -t 1 ]]; then
# Output to console if being run manually
log_message() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"; }
else
# Output to log file if being run via cron
log_message() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" >> "${logfile}"
# Truncate the log file to 1 megabyte
if [[ $(wc -c <"${logfile}") -gt 1000000 ]]; then
tail -c 1000000 "${logfile}" > "${logfile}.tmp" && mv "${logfile}.tmp" "${logfile}"
fi
}
fi
# Parse arguments
for arg in "$@"; do
case "${arg}" in
--message=*)
message=${arg#*=}
;;
--application=*)
application=${arg#*=}
;;
--event=*)
event=${arg#*=}
;;
--priority=*)
priority=${arg#*=}
;;
--url=*)
url=${arg#*=}
;;
--help)
usage
exit 0
;;
*)
echo "Error: Unsupported argument ${arg}"
usage
exit 1
;;
esac
done
# Create a variable to store error messages
errors=""
# Check if curl is installed
if ! command -v curl &> /dev/null; then
errors+="Error: curl is not installed. Please install curl and try again.\n"
fi
# Check that a message was provided
if [[ -z "${message}" ]]; then
errors+="Error: No message provided."
fi
# Check if the URL is valid
if [[ -n $url && ! $url =~ ^(https?://)[^\s/$.?#].[^\s]*$ ]]; then
errors+="Error: Invalid URL.\n"
fi
# Check byte size of the parameters and append error if they exceed the max limit
if [[ "${#url}" -gt 512 ]]; then
errors+="Error: URL exceeds maximum byte limit (512 bytes).\n"
fi
if [[ "${#application}" -gt 256 ]]; then
errors+="Error: Application name exceeds maximum byte limit (256 bytes).\n"
fi
if [[ "${#event}" -gt 1024 ]]; then
errors+="Error: Event name exceeds maximum byte limit (1024 bytes).\n"
fi
if [[ "${#message}" -gt 10000 ]]; then
errors+="Error: Message exceeds maximum length (10000 bytes).\n"
fi
if [[ ! "${priority}" =~ ^-?[0-2]$ ]]; then
errors+="Error: Invalid priority. Must be an integer between -2 and 2.\n"
fi
# Check if the API key file exists and is not empty
if [[ ! -s ~/.prowl_api_key ]]; then
errors+="Error: The Prowl API key file does not exist or is empty. Please create a file at ~/.prowl_api_key and add your API key to it.\nExample:\n echo 'your_api_key' > ~/.prowl_api_key\n chmod 600 ~/.prowl_api_key\n"
fi
# Check the permissions on the API key file, if it exists
# We have to do it in a convoluted cross platform way because macos does not support `stat -c`
if [[ -f ~/.prowl_api_key ]]; then
# Retrieve the file permissions and remove any trailing '@' symbol (indicating extended attributes)
permissions=$(ls -l -d ~/.prowl_api_key | awk '{print $1}' | tr -d '@')
# Check if the permissions are not set to '-rw-------'
if [[ "$permissions" != "-rw-------" ]]; then
# Add an error message to the 'errors' variable
errors+="Error: The permissions on the API key file are not set correctly. Please run 'chmod 600 ~/.prowl_api_key' and try again.\n"
fi
fi
# If any errors were detected, print the error messages and exit
if [[ -n $errors ]]; then
echo -e "${errors}" # -e enables interpretation of backslash escapes like \n
exit 1
fi
# Get the Prowl API key
prowl_api_key=$(cat ~/.prowl_api_key)
# Save the alert data for logging before we encode it
alert_log_string="$application : $event : $priority : $url : $message"
# URL-encode the variables
prowl_api_key=$(urlencode "$prowl_api_key")
application=$(urlencode "$application")
event=$(urlencode "$event")
message=$(urlencode "$message")
priority=$(urlencode "$priority")
url=$(urlencode "$url")
# Send the alert
response=$(curl -s "https://api.prowlapp.com/publicapi/add?apikey=${prowl_api_key}&application=${application}&event=${event}&description=${message}&priority=${priority}&url=${url}")
# Check if the alert was sent successfully
if [[ "${response}" != *"success code=\"200\""* ]]; then
log_message "Error sending alert: ${alert_log_string}"
log_message "Response: ${response}"
exit 1
fi
log_message "Alert sent successfully: $alert_log_string"
exit 0
Code language: PHP (php)
Good luck!
Leave a Reply