8fecc090bf
* s+ow: many - fix #52: handle SPOW_CRON=n - start sm phase at 59, not after - print failed to get location message - fix usage text indentation * s+ow: lint and format
387 lines
10 KiB
Bash
Executable file
387 lines
10 KiB
Bash
Executable file
#!/bin/sh
|
|
|
|
# surplus on wheels (s+ow): a pure shell script to run surplus with mdtest using the termux-api
|
|
|
|
# shellcheck disable=SC2059
|
|
LOCATION_FALLBACK="%d%d%d\nSingapore?"
|
|
# shellcheck disable=SC2269
|
|
LOCATION_PRIORITISE_NETWORK="$LOCATION_PRIORITISE_NETWORK"
|
|
LOCATION_TIMEOUT=${LOCATION_TIMEOUT:-50}
|
|
|
|
# shellcheck disable=SC2269
|
|
JID_NOMINAL_TARGET="$JID_NOMINAL_TARGET"
|
|
# shellcheck disable=SC2269
|
|
JID_ERRORED_TARGET="$JID_ERRORED_TARGET"
|
|
|
|
MDTEST_BIN="$HOME/.local/bin/mdtest"
|
|
MDTEST_DIR="$HOME/.local/share/mdtest"
|
|
|
|
SPOW_CACHE_DIR="$HOME/.cache/s+ow"
|
|
|
|
# per-tool session logs
|
|
SPOW_NETLC_OUT="$SPOW_CACHE_DIR/location.net.json"
|
|
SPOW_GPSLC_OUT="$SPOW_CACHE_DIR/location.gps.json"
|
|
SPOW_LOCTN_OUT="$SPOW_CACHE_DIR/location.json"
|
|
SPOW_SPLUS_OUT="$SPOW_CACHE_DIR/surplus.out.log"
|
|
SPOW_SPLUS_ERR="$SPOW_CACHE_DIR/surplus.err.log"
|
|
|
|
# per-session collated logs
|
|
SPOW_SESH_OUT="$SPOW_CACHE_DIR/out.log"
|
|
SPOW_SESH_ERR="$SPOW_CACHE_DIR/err.log"
|
|
|
|
# per-week collated logs
|
|
SPOW_WEEK_PRE="$SPOW_CACHE_DIR/$(date +%Y)W$(date +"%V")"
|
|
SPOW_WEEK_OUT="$SPOW_WEEK_PRE.out.log"
|
|
SPOW_WEEK_ERR="$SPOW_WEEK_PRE.err.log"
|
|
|
|
# last successful surplus output
|
|
SPOW_LAST_OUT="$SPOW_CACHE_DIR/last"
|
|
|
|
# list of fakes
|
|
# shellcheck disable=SC2034
|
|
SPOW_FAKE_OUT="$SPOW_CACHE_DIR/fake"
|
|
|
|
# check for network location priority
|
|
if [ "$LOCATION_PRIORITISE_NETWORK" = "n" ]; then
|
|
LOCATION_PRIORITISE_NETWORK=""
|
|
fi
|
|
|
|
# check for cron status
|
|
if [ "$SPOW_CRON" = "n" ]; then
|
|
SPOW_CRON=""
|
|
fi
|
|
|
|
# ensure commands exist
|
|
if ! command -v termux-location >/dev/null 2>&1; then
|
|
printf "s+ow: error: termux-location is not installed.\ninstall it with 'pkg install termux-api' and with installing the termux:api app from the play store or f-droid.\n"
|
|
exit 1
|
|
fi
|
|
|
|
if ! command -v surplus >/dev/null 2>&1; then
|
|
printf "s+ow: error: surplus is not installed.\ninstall it with 'pip install https://github.com/markjoshwel/surplus/releases/latest/download/surplus-latest-py3-none-any.whl'\n"
|
|
exit 1
|
|
fi
|
|
|
|
if ! command -v ~/.local/bin/mdtest >/dev/null 2>&1; then
|
|
printf "s+ow: error: mdtest is not installed.\ninstall it by getting a release or building it from source from https://github.com/markjoshwel/whatsmeow-termux\n"
|
|
exit 1
|
|
fi
|
|
|
|
# ensure directories
|
|
mkdir -p "$SPOW_CACHE_DIR" "$MDTEST_DIR"
|
|
|
|
# create new session logs
|
|
rm -f "$SPOW_LOCTN_OUT" "$SPOW_SPLUS_OUT" "$SPOW_SPLUS_ERR" \
|
|
"$SPOW_SESH_OUT" "$SPOW_SESH_ERR"
|
|
touch "$SPOW_NETLC_OUT" "$SPOW_GPSLC_OUT" "$SPOW_LOCTN_OUT" \
|
|
"$SPOW_SPLUS_OUT" "$SPOW_SPLUS_ERR" \
|
|
"$SPOW_SESH_OUT" "$SPOW_SESH_ERR" \
|
|
"$SPOW_WEEK_OUT" "$SPOW_WEEK_ERR"
|
|
|
|
status=0 # 0 is nominal
|
|
# 1 is an termux-location error
|
|
# 2 is a surplus error
|
|
|
|
# helper functions
|
|
|
|
locate() {
|
|
# spawn termux-location processes
|
|
(
|
|
termux-location -p "network" >"$SPOW_NETLC_OUT"
|
|
if [ -s "$SPOW_NETLC_OUT" ]; then
|
|
printf "net" | tee -a "$SPOW_SESH_ERR"
|
|
else
|
|
printf "net?" | tee -a "$SPOW_SESH_ERR"
|
|
fi
|
|
cat "$SPOW_NETLC_OUT" >>"$SPOW_SESH_OUT"
|
|
) &
|
|
tl_net_pid="$!"
|
|
sleep 1
|
|
(
|
|
termux-location -p "gps" >"$SPOW_GPSLC_OUT"
|
|
if [ -s "$SPOW_GPSLC_OUT" ]; then
|
|
printf "gps" | tee -a "$SPOW_SESH_ERR"
|
|
else
|
|
printf "gps?" | tee -a "$SPOW_SESH_ERR"
|
|
fi
|
|
cat "$SPOW_GPSLC_OUT" >>"$SPOW_SESH_OUT"
|
|
) &
|
|
tl_gps_pid="$!"
|
|
|
|
# wait until timeout or both finished
|
|
printf "running termux-location" | tee -a "$SPOW_SESH_ERR"
|
|
while [ "$LOCATION_TIMEOUT" -gt 0 ]; do
|
|
# get process statuses
|
|
kill -0 "$tl_net_pid" >/dev/null 2>&1
|
|
tl_net_status="$?"
|
|
kill -0 "$tl_gps_pid" >/dev/null 2>&1
|
|
tl_gps_status="$?"
|
|
|
|
# break if both finished
|
|
if [ "$tl_net_status" -eq 1 ] && [ "$tl_gps_status" -eq 1 ]; then
|
|
break
|
|
fi
|
|
|
|
# exception: if network is proritised: just use that
|
|
if [ "$tl_net_status" -eq 1 ] && [ -n "$LOCATION_PRIORITISE_NETWORK" ]; then
|
|
# break only if theres an actual response
|
|
if [ -s "$SPOW_NETLC_OUT" ]; then
|
|
break
|
|
fi
|
|
# else just keep on waiting for gps to finish
|
|
fi
|
|
|
|
sleep 1
|
|
printf "." | tee -a "$SPOW_SESH_ERR"
|
|
LOCATION_TIMEOUT=$((LOCATION_TIMEOUT - 1))
|
|
done
|
|
if [ "$LOCATION_TIMEOUT" -eq 0 ]; then
|
|
printf " errored (timeout)\n" | tee -a "$SPOW_SESH_ERR"
|
|
else
|
|
printf " nominal\n" | tee -a "$SPOW_SESH_ERR"
|
|
fi
|
|
|
|
# check outputs
|
|
printf "determining output: " | tee -a "$SPOW_SESH_ERR"
|
|
if [ -s "$SPOW_NETLC_OUT" ] && [ -s "$SPOW_GPSLC_OUT" ]; then
|
|
printf "both succeeded, "
|
|
acc_net="$(grep "\"accuracy\"" <"$SPOW_NETLC_OUT" | awk -F ': ' '{print $2}' | tr -d ',')"
|
|
acc_gps="$(grep "\"accuracy\"" <"$SPOW_GPSLC_OUT" | awk -F ': ' '{print $2}' | tr -d ',')"
|
|
|
|
# compare accuracy
|
|
if awk -v n1="$acc_net" -v n2="$acc_gps" 'BEGIN { if (n1 < n2) exit 0; else exit 1; }'; then
|
|
printf "choosing network (%s < %s)" "$acc_net" "$acc_gps" | tee -a "$SPOW_SESH_ERR"
|
|
cat "$SPOW_NETLC_OUT" >"$SPOW_LOCTN_OUT"
|
|
else
|
|
printf "choosing gps (%s < %s)" "$acc_gps" "$acc_net" | tee -a "$SPOW_SESH_ERR"
|
|
cat "$SPOW_GPSLC_OUT" >"$SPOW_LOCTN_OUT"
|
|
fi
|
|
|
|
cat "$SPOW_GPSLC_OUT" >"$SPOW_LOCTN_OUT"
|
|
else
|
|
# one or none succeeded
|
|
if [ -s "$SPOW_NETLC_OUT" ]; then
|
|
if [ -n "$LOCATION_PRIORITISE_NETWORK" ]; then
|
|
printf "using network (prioritised)" | tee -a "$SPOW_SESH_ERR"
|
|
else
|
|
printf "using network" | tee -a "$SPOW_SESH_ERR"
|
|
fi
|
|
cat "$SPOW_NETLC_OUT" >"$SPOW_LOCTN_OUT"
|
|
fi
|
|
if [ -s "$SPOW_GPSLC_OUT" ]; then
|
|
printf "using gps" | tee -a "$SPOW_SESH_ERR"
|
|
cat "$SPOW_GPSLC_OUT" >"$SPOW_LOCTN_OUT"
|
|
fi
|
|
fi
|
|
if [ ! -s "$SPOW_LOCTN_OUT" ]; then
|
|
printf "none (error)" | tee -a "$SPOW_SESH_ERR"
|
|
fi
|
|
printf "\n" | tee -a "$SPOW_SESH_ERR"
|
|
}
|
|
|
|
gensharetext() {
|
|
surplus -td "$1" >"$SPOW_SPLUS_OUT" 2>"$SPOW_SPLUS_ERR"
|
|
ret="$?"
|
|
cat "$SPOW_SPLUS_OUT" >>"$SPOW_SESH_OUT"
|
|
cat "$SPOW_SPLUS_ERR" >>"$SPOW_SESH_ERR"
|
|
return "$ret"
|
|
}
|
|
|
|
send() {
|
|
(cd "$MDTEST_DIR" && "$MDTEST_BIN" send "$1" "$2")
|
|
}
|
|
|
|
notify_start() {
|
|
termux-notification \
|
|
--priority "min" \
|
|
--ongoing \
|
|
--id "s+ow" \
|
|
--title "surplus on wheels" \
|
|
--content "s+ow has started running."
|
|
}
|
|
|
|
notify() {
|
|
# $1 is text
|
|
# $2 is attempt number (if any)
|
|
attempt_text="$1"
|
|
if [ $# -eq 2 ]; then
|
|
attempt_text="$1 (attempt $2)"
|
|
fi
|
|
termux-notification \
|
|
--priority "min" \
|
|
--ongoing \
|
|
--id "s+ow" \
|
|
--title "surplus on wheels" \
|
|
--content "$attempt_text"
|
|
}
|
|
|
|
notify_end() {
|
|
# $1 is done tuple
|
|
# $2 is sharetext
|
|
termux-notification \
|
|
--priority "min" \
|
|
--id "s+ow" \
|
|
--title "surplus on wheels" \
|
|
--content "$(printf 'Run has finished. %s\n\n%s' "$1" "$2")"
|
|
}
|
|
|
|
# program functions
|
|
|
|
mdtest() {
|
|
(cd "$MDTEST_DIR" && "$MDTEST_BIN")
|
|
}
|
|
|
|
run() {
|
|
notify_start
|
|
printf "[run! stdout (%s)]\n" "$(date)" >>"$SPOW_SESH_OUT"
|
|
printf "[run! stderr (%s)]\n" "$(date)" >>"$SPOW_SESH_ERR"
|
|
|
|
time_run_start="$(date +%s)"
|
|
|
|
# if cron: wait until its the new hour
|
|
if [ -n "$SPOW_CRON" ]; then
|
|
notify "Waiting for the 30th second to pass..."
|
|
printf "waiting for the 30th second to pass...\n"
|
|
while [ "$(date +'%S')" -lt 30 ]; do
|
|
printf " $(date)\n"
|
|
sleep 1
|
|
done
|
|
printf "proceeding\n"
|
|
fi
|
|
|
|
time_locate_start="$(date +%s)"
|
|
|
|
# termux-location
|
|
location=""
|
|
for locate_run in 1 2 3; do # run three times in case :p
|
|
notify "Running termux-location" "$locate_run"
|
|
|
|
if [ "$locate_run" -gt "1" ]; then
|
|
LOCATION_TIMEOUT=75 locate
|
|
fi
|
|
|
|
if [ ! -s "$SPOW_LOCTN_OUT" ]; then
|
|
# erroneous: is empty
|
|
echo "s+ow: error: failed to get location" | tee -a "$SPOW_SESH_ERR"
|
|
status=1
|
|
else
|
|
# nominal: is not empty
|
|
location="$(cat "$SPOW_LOCTN_OUT")"
|
|
status=0
|
|
break
|
|
fi
|
|
done
|
|
|
|
time_locate_end="$(date +%s)"
|
|
time_locate=$((time_locate_end - time_locate_start))
|
|
|
|
time_surplus_start="$(date +%s)"
|
|
|
|
# surplus
|
|
printf "running surplus... "
|
|
notify "Running surplus -td $location"
|
|
if [ "$status" -eq 0 ]; then
|
|
if gensharetext "$location"; then
|
|
# surplus ran nominally
|
|
cp "$SPOW_SPLUS_OUT" "$SPOW_LAST_OUT"
|
|
status=0
|
|
printf "nominal\n"
|
|
else
|
|
# something happened :^)
|
|
status=2
|
|
printf "errored\n"
|
|
fi
|
|
else
|
|
printf "skipped\n"
|
|
fi
|
|
|
|
time_surplus_end="$(date +%s)"
|
|
time_surplus=$((time_surplus_end - time_surplus_start))
|
|
|
|
# if cron: wait until its the new hour
|
|
if [ -n "$SPOW_CRON" ]; then
|
|
notify "Waiting for the new hour..."
|
|
printf "waiting until the new hour...\n"
|
|
while [ "$(date +'%M')" -lt 59 ]; do
|
|
printf " $(date)\n"
|
|
sleep 1
|
|
done
|
|
printf "proceeding\n"
|
|
fi
|
|
|
|
time_sendmsg_start="$(date +%s)"
|
|
|
|
# mdtest/send message
|
|
printf "sending message(s)... "
|
|
notify "Sending message(s)"
|
|
sent_type=0 # 0 for freshly made sharetext
|
|
# 1 for recycling a last location
|
|
# 2 for using fallback template
|
|
sharetext=""
|
|
if [ "$status" -eq 0 ]; then
|
|
# s+ow has behaved nominally until now, send as per normal
|
|
sharetext="$(cat "$SPOW_SPLUS_OUT")"
|
|
printf "\n"
|
|
send "$JID_NOMINAL_TARGET" "$sharetext"
|
|
else
|
|
# something has gone wrong, send an appropriate fallback
|
|
sharetext=""
|
|
if [ -s "$SPOW_LAST_OUT" ]; then
|
|
# use last successful location
|
|
sharetext="$(cat "$SPOW_LAST_OUT")"
|
|
sent_type=1
|
|
printf "using last...\n"
|
|
else
|
|
# no last location, use fallback
|
|
# shellcheck disable=SC2059
|
|
sharetext="$(printf "$LOCATION_FALLBACK" "$status" "$locate_run" "$sent_type")"
|
|
sent_type=2
|
|
printf "using fallback... \n"
|
|
fi
|
|
|
|
# send done info except
|
|
printf "(%d, %d, %d) [lc:%ds sp:%ds]\n" "$status" "$locate_run" "$sent_type" "$time_locate" "$time_surplus" >>"$SPOW_SESH_ERR"
|
|
|
|
send "$JID_NOMINAL_TARGET" "$sharetext"
|
|
send "$JID_ERRORED_TARGET" "$(cat "$SPOW_SESH_ERR")"
|
|
fi
|
|
|
|
time_sendmsg_end="$(date +%s)"
|
|
time_sendmsg=$((time_sendmsg_end - time_sendmsg_start))
|
|
|
|
time_run_end="$(date +%s)"
|
|
time_run=$((time_run_end - time_run_start))
|
|
|
|
done_info="$(printf "(%d, %d, %d) [lc:%ds sp:%ds sm:%ds - %ds]\n" "$status" "$locate_run" "$sent_type" "$time_locate" "$time_surplus" "$time_sendmsg" "$time_run")"
|
|
echo "done $done_info" | tee -a "$SPOW_SESH_ERR"
|
|
|
|
# cleanup
|
|
notify_end "$done_info" "$sharetext"
|
|
}
|
|
|
|
# script entry
|
|
|
|
if [ "$1" = "mdtest" ]; then
|
|
mdtest
|
|
elif [ -z "$1" ]; then
|
|
# ensure JID targets are set
|
|
if [ -z "$JID_NOMINAL_TARGET" ] || [ -z "$JID_ERRORED_TARGET" ]; then
|
|
echo "s+ow: error: JID_NOMINAL_TARGET and JID_ERRORED_TARGET are not set"
|
|
exit 1
|
|
fi
|
|
run
|
|
else
|
|
echo "usage: $0 [mdtest]
|
|
|
|
surplus on wheels: a pure shell script to run surplus with mdtest using the termux-api
|
|
|
|
choices
|
|
$0 mdtest
|
|
run mdtest for testing or authentication
|
|
$0
|
|
run surplus on wheels normally"
|
|
fi
|
|
|
|
printf "%s\n\n" "$(cat "$SPOW_SESH_OUT")" >>"$SPOW_WEEK_OUT"
|
|
printf "%s\n\n" "$(cat "$SPOW_SESH_ERR")" >>"$SPOW_WEEK_ERR"
|