feat(script): Add script

This commit is contained in:
hygienic-books 2025-03-08 18:07:31 +01:00
parent 013648addc
commit 108be98ec3
3 changed files with 138 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
.idea
*.conf

View File

@ -0,0 +1,97 @@
#!/bin/bash
# shellcheck disable=SC2059
declare message_geofence_enter message_geofence_exit message_device_online message_device_unknown message_device_offline message_event_other signal_sender_phone_number signal_recipients_array signal_api_endpoint_full_path allow_unique_device_ids_posix_ere device_name event_type battery_level message
payload="${1}"
function load_config() {
local this_script_call_cmd this_script_resolved_abs_path conf_file_resolved_abs_path conf_file_resolved_file_name
this_script_call_cmd="${BASH_SOURCE[0]}"
this_script_resolved_abs_path="$(readlink -f "${this_script_call_cmd}")"
conf_file_resolved_abs_path="${this_script_resolved_abs_path}"'.conf'
conf_file_resolved_file_name="$(basename "${conf_file_resolved_abs_path}")"
if [[ -r "${conf_file_resolved_abs_path}" ]]; then
# shellcheck source="${conf_file_resolved_abs_path}"
source "${conf_file_resolved_abs_path}"
fi
# Optional, will use default values if not given by user
: "${message_geofence_enter:='%s entered geofence %s.'}"
: "${message_geofence_exit:='%s left geofence %s.'}"
: "${message_device_online:='On %s Traccar Client app is now active.'}"
: "${message_device_unknown:='On %s Traccar Client app has not checked in for 10 minutes, the app is likely off now.'}"
: "${message_device_offline:='On %s Traccar Client app is now off.'}"
: "${message_device_unhandled:='For %s we do not want to send a message to Signal. Nothing to do.\n'}"
: "${message_event_other:='%s triggered event "%s" in Traccar server.'}"
: "${allow_unique_device_ids_posix_ere:=''}"
# Mandatory, user must specify
: "${signal_sender_phone_number:?'Please specify the signal-cli-rest-api phone number of your sender Signal account. Place a file named '"'${conf_file_resolved_file_name}'"' next to this script (same dir) and define a variable signal_sender_phone_number='"'"'value'"'"' in it.'}"
: "${signal_recipients_array:?'Please specify recipients like so: ["group.ImxvbmdpdH=","recipient.21","+18005550111","i-am-a-uuid"]. Place a file named '"'${conf_file_resolved_file_name}'"' next to this script (same dir) and define a variable signal_recipients_array='"'"'value'"'"' in it.'}"
: "${signal_api_endpoint_full_path:?'Please specify the signal-cli-rest-api full URL for sending a message like so: https://fully.qualified.domain.name/v2/send. Place a file named '"'${conf_file_resolved_file_name}'"' next to this script (same dir) and define a variable signal_api_endpoint_full_path='"'"'value'"'"' in it.'}"
}
function get_event_data() {
local device_unique_id
device_unique_id="$(<<<"${payload}" jq --raw-output '.device.uniqueId')"
device_name="$(<<<"${payload}" jq --raw-output '.device.name')"
event_type="$(<<<"${payload}" jq --raw-output '.event.type')"
if [[ "${event_type}" = 'geofenceEnter' || "${event_type}" = 'geofenceExit' ]]; then
battery_level="$(<<<"${payload}" jq --raw-output '.position.attributes.batteryLevel')"
battery_level="$(echo "${battery_level}"' / 1' | bc)"
fi
if ! [[ "${device_unique_id}" =~ ${allow_unique_device_ids_posix_ere} ]]; then
printf -- "${message_device_unhandled}" "${device_name}"
exit 0
fi
}
function craft_message() {
local geofence_name
case "${event_type}" in
'geofenceEnter')
geofence_name="$(<<<"${payload}" jq --raw-output '.geofence.name')"
message="${message_geofence_enter}"
message="$(printf -- "${message}" "${device_name}" "${geofence_name}" "${battery_level}")"
;;
'geofenceExit')
geofence_name="$(<<<"${payload}" jq --raw-output '.geofence.name')"
message="${message_geofence_exit}"
message="$(printf -- "${message}" "${device_name}" "${geofence_name}" "${battery_level}")"
;;
'deviceOnline')
message="${message_device_online}"
message="$(printf -- "${message}" "${device_name}")"
;;
'deviceUnknown')
message="${message_device_unknown}"
message="$(printf -- "${message}" "${device_name}")"
;;
'deviceOffline')
message="${message_device_offline}"
message="$(printf -- "${message}" "${device_name}")"
;;
*)
message="${message_event_other}"
message="$(printf -- "${message}" "${device_name}" "${event_type}")"
;;
esac
}
function send_to_signal() {
local signal_message
signal_message="${1}"
echo "${signal_message}"
curl \
--request 'POST' \
--header 'Content-Type: application/json' \
--data '{"message":"'"${signal_message}"'","number":"'"${signal_sender_phone_number}"'","recipients":'"${signal_recipients_array}"'}' \
"${signal_api_endpoint_full_path}"
}
load_config
get_event_data
craft_message
send_to_signal "${message}"

View File

@ -0,0 +1,39 @@
# First positional argument '%s' is Traccar device name, second
# positional argument '%s' is geofence name, third one is battery level.
# This cannot be switched around, please word your message accordingly.
# Notice how a line break takes the form '\\n', that's two backslashes.
message_geofence_enter='%s entered geofence %s.\\n\\nBattery level %s%%.'
message_geofence_exit='%s left geofence %s.\\n\\nBattery level %s%%.'
# Argument '%s' is Traccar device name
message_device_online='On %s Traccar Client app is now active.'
message_device_unknown='On %s Traccar Client app has not checked in for 10 minutes, the app is likely off now.'
message_device_offline='On %s Traccar Client app is now off.'
# Argument '%s' is Traccar device name but this one unlike the three
# message strings before is used as stdout log output when the device ID
# that triggered an event doesn't match our allow list in
# allow_unique_device_ids_posix_ere, see below. Note a trailing '\n'
# (backslash-n) at the end of this string. This is a Bash printf
# replacement string.
message_device_unhandled='For %s we do not want to send Signal messages. Nothing to do.\n'
# First positional argument '%s' is Traccar device name, second
# positional argument '%s' is event name. This cannot be switched
# around, please word your message accordingly.
message_event_other='%s triggered event "%s" in Traccar server.'
# If this is a non-empty value we'll use it to only handle Traccar
# events for these unique device IDs. Events triggered by other device
# IDs will be discarded. If this is an empty string or if it's not
# declared at all we'll handle events for all device IDs. In Traccar
# server every device has a unique ID that's distinct from its
# pretty-printed device name. This is a Posix Extended Regular
# Expression (ERE). Most Perl-Compatible Regular Expression (PCRE)
# syntax works. Most notably lookarounds are unsupported in ERE.
allow_unique_device_ids_posix_ere='^(901874|81919333|9991212)$'
# signal-cli-rest-api config
signal_sender_phone_number='+18005550199'
signal_recipients_array='["group.ImxvbmdpdH=","recipient.21","+18005550111","i-am-a-uuid"]'
signal_api_endpoint_full_path='https://fully.qualified.domain.name/v2/send'