#!/bin/sh set -e # Validate environment if ! command -v msgbus > /dev/null; then printf "missing msgbus command. Use: go install git.mills.io/prologic/msgbus/cmd/msgbus@master" exit 1 fi if ! command -v salty > /dev/null; then printf "missing salty command. Use: go install go.mills.io/salty/cmd/salty@master" exit 1 fi if ! command -v salty-keygen > /dev/null; then printf "missing salty-keygen command. Use: go install go.mills.io/salty/cmd/salty-keygen@master" exit 1 fi if [ -z "$SALTY_IDENTITY" ]; then export SALTY_IDENTITY="$HOME/.config/salty/$USER.key" fi get_user () { user=$(grep user: "$SALTY_IDENTITY" | awk '{print $3}') if [ -z "$user" ]; then user="$USER" fi echo "$user" } stream () { if [ -z "$SALTY_IDENTITY" ]; then echo "SALTY_IDENTITY not set" return 2 fi echo '\007' jq -r '.payload' | base64 -d | salty -i "$SALTY_IDENTITY" -d } lookup () { if [ $# -lt 1 ]; then printf "lookup takes 1 arugment %d given\n" "$#" printf "Try %s lookup nick@domain\n" "$(basename "$0")" return 1 fi user="$1" nick="$(echo "$user" | awk -F@ '{ print $1 }')" domain="$(echo "$user" | awk -F@ '{ print $2 }')" if ! curl -qfsSL "https://$domain/.well-known/salty/${nick}.json"; then echo "error: lookup failed" return 1 fi } readmsgs () { topic="$1" if [ -z "$topic" ]; then topic=$(get_user) fi export SALTY_IDENTITY="$HOME/.config/salty/$topic.key" if [ ! -f "$SALTY_IDENTITY" ]; then echo "identity file missing for user $topic" >&2 return 1 fi msgbus sub "$topic" "$0" } sendmsg () { if [ $# -lt 2 ]; then printf "sendmsg requires 2 arguments %d provided" "$#" printf "Try %s send nick@domain message\n" "$(basename "$0")" return 1 fi if [ -z "$SALTY_IDENTITY" ]; then echo "SALTY_IDENTITY not set" return 2 fi user="$1" message="$2" if [ -z "$message" ]; then echo "error: empty message" exit 2 fi salty_json="$(mktemp /tmp/salty.XXXXXX)" lookup "$user" > "$salty_json" endpoint="$(jq -r '.endpoint' < "$salty_json")" topic="$(jq -r '.topic' < "$salty_json")" key="$(jq -r '.key' < "$salty_json")" rm "$salty_json" message="[$(date +%FT%TZ)] <$(get_user)> $message" echo "$message" \ | salty -i "$SALTY_IDENTITY" -r "$key" \ | msgbus -u "$endpoint" pub "$topic" } chatwith() { if [ $# -lt 1 ]; then printf "chatwith requires 1 arguments %d provided" "$#" printf "Try %s chat nick@domain\n" "$(basename "$0")" return 1 fi if [ -z "$SALTY_IDENTITY" ]; then echo "SALTY_IDENTITY not set" return 2 fi user="$1" salty_json="$(mktemp /tmp/salty.XXXXXX)" lookup "$user" > "$salty_json" endpoint="$(jq -r '.endpoint' < "$salty_json")" topic="$(jq -r '.topic' < "$salty_json")" key="$(jq -r '.key' < "$salty_json")" rm "$salty_json" while true; do printf "> " read -r message if [ -z "$message" ]; then continue fi message="[$(date +%FT%TZ)] <$(get_user)> $message" echo "$message" \ | salty -i "$SALTY_IDENTITY" -r "$key" \ | msgbus -u "$endpoint" pub "$topic" done } make_user () { mkdir -p "$HOME/.config/salty" if [ $# -lt 1 ]; then user=$USER else user=$1 fi identity_file="$HOME/.config/salty/$user.key" if [ -f "$identity_file" ]; then printf "user key already exists!" return 1 fi # Check for msgbus env.. probably can make it fallback to looking for a config file? if [ -z "$MSGBUS_URI" ]; then printf "missing MSGBUS_URI in environment" return 1 fi salty-keygen -o "$identity_file" echo "# user: $user" >> "$identity_file" pubkey=$(grep key: "$identity_file" | awk '{print $4}') cat <<- EOF Create this file in your webserver well-known folder. https://hostname.tld/.well-known/salty/$user.json { "endpoint": "$MSGBUS_URI", "topic": "$user", "key": "$pubkey" } EOF } show_help() { printf "Usage: %s [options] [arguments]\n" "$(basename "$0")" printf "\n" printf "Options:\n" printf " -h/--help Show this help" printf "\n" printf "\n" printf "Commands:\n" printf " chat -- Chat with a user by nick@domain\n" printf " lookup -- Lookup a user by nick@domain\n" printf " make-user -- Generate a new user key pair\n" printf " read -- Reads your messages\n" printf " send -- Sends a message to nick@domain\n" } # check if streaming if [ ! -t 1 ]; then stream exit 0 fi # Show Help if [ $# -lt 1 ]; then show_help exit 1 fi CMD=$1 shift case $CMD in -h|--help) show_help ;; chat) chatwith "$@" ;; send) sendmsg "$@" ;; read) readmsgs "$@" ;; lookup) lookup "$@" ;; make-user) make_user "$@" ;; esac