Files
sxmo-utils/scripts/modem/sxmo_modemsendsms.sh
2023-05-14 00:19:17 -07:00

192 lines
6.2 KiB
Bash
Executable File

#!/bin/sh
# SPDX-License-Identifier: AGPL-3.0-only
# Copyright 2022 Sxmo Contributors
# shellcheck disable=SC3045
# include common definitions
# shellcheck source=scripts/core/sxmo_common.sh
. sxmo_common.sh
info() {
sxmo_log "$*"
printf "%s\n" "$*"
}
err() {
info "$*"
exit 1
}
usage() {
printf "Usage: %s number|contact [-|message]\n" "$(basename "$0")"
exit 1
}
[ 0 -eq $# ] && usage
NUMBER="$1"
make_attachments_arg() {
LOGDIRNUM="$1"
MAX_SIZE="$(grep "^TotalMaxAttachmentSize" "$MMS_BASE_DIR/mms" | cut -d'=' -f2)"
MAX_NUMBER="$(grep "^MaxAttachments" "$MMS_BASE_DIR/mms" | cut -d'=' -f2)"
[ -z "$MAX_NUMBER" ] && MAX_NUMBER="25"
[ -z "$MAX_SIZE" ] && MAX_SIZE="1100000"
ATT_NUM=0
TOTAL_SIZE=0
while read -r ATTACHMENT; do
[ -f "$ATTACHMENT" ] || err "Attachment ($ATTACHMENT) not found!"
CTYPE=$(file -b --mime-type "$ATTACHMENT")
# The 'file' command returns longer mime-types than mmsctl
# likes, so convert those (if any) here. I have only tested mp3
# (which needs to be converted) and jpeg (which does not).
case "$CTYPE" in
"audio/mpegapplication/octet-stream")
CTYPE="audio/mpeg"
;;
esac
# basic mms error checking (since mmsctl does not do it)
ATT_NUM="$((ATT_NUM+1))"
TOTAL_SIZE="$((TOTAL_SIZE+$(wc -c < "$ATTACHMENT")))"
if [ "$ATT_NUM" -gt "$MAX_NUMBER" ]; then
err "Number of attachments ($ATT_NUM) greater than MaxAttachments ($MAX_NUMBER)."
fi
if [ "$ATT_NUM" -ge 1 ] && [ "$TOTAL_SIZE" -gt "$MAX_SIZE" ]; then
err "Total size of attachments ($TOTAL_SIZE) greater than TotalMaxAttachmentSize ($MAX_SIZE)."
fi
printf " %s '%s' -c '%s'" "-a" "$ATTACHMENT" "$CTYPE"
done < "$SXMO_LOGDIR/$LOGDIRNUM/draft.attachments.txt"
}
# if number does not start with + assume it is a contact name, and if it isn't
# in our contacts book, then alert the user but continue anyway, e.g., one
# might send a message to "2600" or something.
if ! echo "$NUMBER" | grep -q '^+'; then
ACTUAL_NUMBER="$(sxmo_contacts.sh --all | grep "^$NUMBER:" | cut -d':' -f2 | sed 's/^ //')"
if [ -z "$ACTUAL_NUMBER" ]; then
info "WARNING: $NUMBER does not look like a phone number or a contact."
else
NUMBER="$ACTUAL_NUMBER"
fi
fi
if [ "-" = "$2" ]; then
TEXT="$(cat)"
else
shift
[ 0 -eq $# ] && usage
TEXT="$*"
fi
# if multiple recipients or attachment, then send via mmsctl
if [ "$(printf %s "$NUMBER" | xargs pnc find | wc -l)" -gt 1 ] || [ -f "$SXMO_LOGDIR/$NUMBER/draft.attachments.txt" ]; then
MMS_BASE_DIR="${SXMO_MMS_BASE_DIR:-"$HOME"/.mms/modemmanager}"
[ -d "$MMS_BASE_DIR" ] || err "MMS not configured."
# ensure we use the correct LOGDIRNUM (e.g., if multiple recipients, sort numerically)
NUMBER="$(printf %s "$NUMBER" | xargs pnc find | sort -u | grep . | xargs printf %s)"
# generate mmsctl arguments
TMPFILE="$(mktemp)" # we remove this after we attempt run mmsctl
printf %s "$TEXT" > "$TMPFILE"
# -a 'filename' -c 'content/type' -a 'filename2' -c 'content/type'
[ -f "$SXMO_LOGDIR/$NUMBER/draft.attachments.txt" ] && ATTACHMENTS_ARG="$(make_attachments_arg "$NUMBER" | sed 's/^ //')"
# -a 'tmpfile' for message content
ATTACHMENTS_ARG="-a '$TMPFILE' $ATTACHMENTS_ARG"
# -r +123 -r +345
RECIPIENTS_ARG="$(printf %s "$NUMBER" | sed 's/+/ -r +/g' | sed 's/^ //')"
# Send it to mmsd-tng via mmsctl. We can't use dbus-send since
# dbus-send doesn't recognize a(sss) types.
info "mmsctl -S $RECIPIENTS_ARG $ATTACHMENTS_ARG"
MMSCTL_RES="$(eval mmsctl -S "$RECIPIENTS_ARG" "$ATTACHMENTS_ARG")"
MMSCTL_OK="$?"
rm "$TMPFILE"
[ "$MMSCTL_OK" -ne 0 ] && err "mmsctl failed with \"$MMSCTL_RES\""
# mmsd-tng should immediately add a message of status 'draft' and then
# after a few beats it will send it and transform that message to
# 'sent'.
info "Waiting for mmsd-tng to send..."
MMS_PIPE="$(mktemp -u)"
mkfifo "$MMS_PIPE"
timeout 60 dbus-monitor "interface='org.ofono.mms.Message',type='signal',member='PropertyChanged'" > "$MMS_PIPE" &
MMS_PIPE_PID="$!"
while read -r line; do
if printf %s "$line" | grep -q 'member=PropertyChanged'; then
MESSAGE_PATH="$(echo "$line" | cut -d'=' -f6 | cut -d';' -f1)"
fi
if printf %s "$line" | grep -q "string \"sent\""; then
SENT_SUCCESS=1
break
fi
done < "$MMS_PIPE"
rm -f "$NAMED_PIPE"
kill "$MMS_PIPE_PID"
[ -z "$SENT_SUCCESS" ] && err "mmsd-tng did not send the draft."
[ -f "$SXMO_LOGDIR/$NUMBER/draft.attachments.txt" ] && rm -f "$SXMO_LOGDIR/$NUMBER/draft.attachments.txt"
# process it just like any other mms (this will handle logging it)
sxmo_mms.sh processmms "$MESSAGE_PATH"
MMS_FILE="$(basename "$MESSAGE_PATH")"
CONTACTNAME="$(sxmo_contacts.sh --name-or-number "$NUMBER")"
sxmo_hook_sendsms.sh "$CONTACTNAME" "$TEXT" "$MMS_FILE" "$CONTACTNAME"
info "Sent mms text to $CONTACTNAME."
# we are dealing with a normal sms, so use mmcli
else
TEXTSIZE="${#TEXT}"
#mmcli doesn't appear to be able to interpret a proper escape
#mechanism, so we'll substitute double quotes for two single quotes
SAFE_TEXT=$(echo "$TEXT" | sed "s/\"/''/g")
SMSNO="$(
mmcli -m any --messaging-create-sms="text=\"$SAFE_TEXT\",number=$NUMBER" |
grep -o "[0-9]*$"
)"
SMS_RES="$(mmcli -s "${SMSNO}" --send --timeout="${SXMO_MM_TIMEOUT:-"30"}" 2>&1)"
SMS_OK="$?"
if [ "$SMS_OK" = 1 ]; then
# if we fail to send due to a bad number,
# clear it from the modem
if echo "$SMS_RES" | grep -q "Invalid number"; then
for i in $(mmcli -m any --messaging-list-sms | grep " (unknown)" | cut -f5 -d' '); do
mmcli -m any -s "$i" -K | grep -q "not requested" && mmcli -m any --messaging-delete-sms="$i" >/dev/null
done
err "Couldn't send text message: Invalid number."
else
err "Couldn't send text message ($SMS_RES)"
fi
fi
# we sent it successfully, but also clear it from the modem
for i in $(mmcli -m any --messaging-list-sms | grep " (sent)" | cut -f5 -d' ') ; do
mmcli -m any --messaging-delete-sms="$i" > /dev/null
done
TIME="$(date +%FT%H:%M:%S%z)"
mkdir -p "$SXMO_LOGDIR/$NUMBER"
sxmo_hook_smslog.sh "sent" "$NUMBER" "$NUMBER" "$TIME" "$TEXT" >> "$SXMO_LOGDIR/$NUMBER/sms.txt"
printf "%s\tsent_txt\t%s\t%s chars\n" "$TIME" "$NUMBER" "$TEXTSIZE" >> "$SXMO_LOGDIR/modemlog.tsv"
CONTACTNAME="$(sxmo_contacts.sh --name-or-number "$NUMBER")"
sxmo_hook_sendsms.sh "$CONTACTNAME" "$TEXT"
info "Sent sms text to $CONTACTNAME."
fi