#!/usr/bin/env bash # # page-signal — wrap signal-cli send for paging Craig via Signal. # # Sends from a dedicated pager account to Craig's Signal account by # default. Override the recipient with --to <+number-or-uuid>. # # Usage: # page-signal "message" # page Craig (default recipient) # page-signal --file path "message" # with attachment # page-signal --to +15551234567 "msg" # override recipient (number or UUID) # page-signal --quiet "message" # suppress success output # page-signal --json "message" # structured output (timestamp + status) # echo "msg" | page-signal # message from stdin (no positional) # # Sender account and default recipient come from PAGE_SIGNAL_ACCOUNT and # PAGE_SIGNAL_TO; both have built-in defaults below. Requires signal-cli # installed and registered with the sender account. # # Use this when desktop notifications won't reach the user — page-signal # fires cross-device. For routine completions and periodic status pings, # stick with `notify`; Signal is for things that need attention while away # from the desk. set -euo pipefail quiet=0 json=0 file= account="${PAGE_SIGNAL_ACCOUNT:-+15045173983}" recipient_args=("${PAGE_SIGNAL_TO:-b1b5601e-6126-47f8-afaa-0a59f5188fde}") message= usage() { sed -n '3,23p' "$0" | sed 's/^# \{0,1\}//' } while [ "$#" -gt 0 ]; do case "$1" in -h|--help) usage exit 0 ;; --quiet) quiet=1 shift ;; --json) json=1 shift ;; --file) [ "$#" -ge 2 ] || { echo "page-signal: --file needs a path" >&2; exit 2; } file="$2" [ -f "$file" ] || { echo "page-signal: file not found: $file" >&2; exit 2; } shift 2 ;; --to) [ "$#" -ge 2 ] || { echo "page-signal: --to needs a +E.164 number or a Signal account UUID" >&2; exit 2; } case "$2" in +[0-9]*) ;; [0-9a-fA-F]*-[0-9a-fA-F]*-[0-9a-fA-F]*) ;; *) echo "page-signal: --to expects +E.164 (e.g. +15551234567) or a Signal account UUID" >&2; exit 2 ;; esac recipient_args=("$2") shift 2 ;; --) shift break ;; -*) echo "page-signal: unknown flag: $1 (use --help)" >&2 exit 2 ;; *) message="$1" shift ;; esac done if ! command -v signal-cli >/dev/null 2>&1; then echo "page-signal: signal-cli not found in PATH" >&2 exit 3 fi # Message: from positional arg, or from stdin if none given. if [ -z "$message" ]; then if [ -t 0 ]; then echo "page-signal: no message (pass as arg or pipe via stdin)" >&2 exit 2 fi message="$(cat)" fi # Build the send command. cmd=(signal-cli -a "$account" send -m "$message") if [ -n "$file" ]; then cmd+=(-a "$file") fi cmd+=("${recipient_args[@]}") # Send. Capture stderr so we can surface clean failure messages. timestamp="$(date '+%Y-%m-%dT%H:%M:%S%z')" if err="$("${cmd[@]}" 2>&1 >/dev/null)"; then status=ok else status=fail fi if [ "$json" -eq 1 ]; then printf '{"status":"%s","timestamp":"%s","recipient":"%s"' \ "$status" "$timestamp" "${recipient_args[0]}" if [ -n "$file" ]; then printf ',"attachment":"%s"' "$file" fi if [ "$status" = "fail" ]; then printf ',"error":"%s"' "$(echo "$err" | head -1 | sed 's/"/\\"/g')" fi printf '}\n' elif [ "$quiet" -eq 0 ]; then if [ "$status" = "ok" ]; then echo "page-signal: sent to ${recipient_args[*]} at $timestamp" else echo "page-signal: FAIL — $err" >&2 fi fi [ "$status" = "ok" ]