#!/bin/bash
set -eo pipefail
[ -n "$DEBUG" ] && set -x
printpass=${_SECM_PRINT:-}
printraw=${_SECM_PRINTRAW:-}
listandexit=
while getopts Plrh opt; do
case ${opt} in
P) printpass=1 ;;
r) printraw=1 ;;
l) listandexit=1 ;;
h | ?)
echo "usage: secretmenu [-bp] [-Pr] [-l] [query]"
echo
exit 2
;;
esac
done
shift $((OPTIND - 1))
# check requirements
for tool in bemenu fd flock fzf jq rbw; do
if ! command -v "$tool" >/dev/null; then
printf "%s: %s not installed but required\n" "$(basename "$0")" "$tool" >&2
exit 1
fi
done
__menu() {
if [ -t 1 ]; then
echo "terminal mode not implemented"
exit 1
fi
MENU_PROMPT=" secret" menu -l10 --accept-single ${@:+--filter "$@"}
}
__list_secrets() {
rbw list --fields name,user,folder,id | column -t -s $'\t'
}
__query_secret() {
# query by the last space-separated item (id)
local id=${1##* }
echo "$id" >&2
rbw get --raw -- "$id" 2>&1
# jq '.data + (.fields|map({(.name|@text|ascii_downcase): .value})|add)' -r | column -s: -t
}
if [ -n "$printraw" ]; then
__handle() {
jq
}
elif [ -n "$printpass" ]; then
__handle() {
jq -r '.data.password'
}
else # copy to clipboard
__handle() {
jq -r '.data.username, .data.password' |
awk 'NR==2 {system("wl-copy -n \"" $0 "\"");hit+=1} NR==1 {system("wl-copy -n -p \"" $0 "\"");hit+=1} END{if(hit==0){print("no secret found") >/dev/stderr; exit(1);}}'
}
fi
# main
if [ -n "$listandexit" ]; then
__list_secrets
exit 0
fi
# ensure only one menu runs at a time
lockfile="$XDG_RUNTIME_DIR"/secretmenu.lock
[ "$FLOCKER" != "$lockfile" ] && exec env FLOCKER="$lockfile" _SECM_PRINT="$printpass" _SECM_PRINTRAW="$printraw" flock -ew 30 "$lockfile" "$0" "$@"
trap '{ env UNSAFE=1 rm $lockfile 2>/dev/null || true; }' EXIT TERM INT
ico=$(iconez -fs -n dialog-password-symbolic)
trap '{ notify-send -a secretmenu -i "${ico}" -c error "secretmenu: failed :(" "pipefail"; exit 1; }' ERR
pw=$(__list_secrets | __menu "$@")
__query_secret "$pw" | __handle
__ok=$?
[ -n "$printpass" ] && exit "$__ok"
if [ "$__ok" -eq 0 ]; then
notify-send \
-a secretmenu \
-i "${ico}" \
'secretmenu: secret copied' \
'will be removed after next paste'
fi
exit "$__ok"