Kim Visscher: 1 added onepassword.py 2 files changed, 161 insertions(+), 0 deletions(-)
Copy & paste the following snippet into your terminal to import this patchset into git:
curl -s https://lists.sr.ht/~anjan/public-inbox/patches/24737/mbox | git am -3Learn more about email & git
--- README.md | 5 ++ onepassword.py | 156 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 161 insertions(+) create mode 100755 onepassword.py diff --git a/README.md b/README.md index d6bf01b..d8b3427 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,11 @@ Please use [git send-email](https://git-send-email.io/) and send a patch to my [ # Summary of scripts +## onepassword.py +- Author: Kim Visscher <kim@visscher.codes> +- License: MIT +- Description: A mobile friendly interface for [1Password](https://1password.com/) + ## Workout - Author: Anjandev Momi <anjan@momi.ca> - License: MIT diff --git a/onepassword.py b/onepassword.py new file mode 100755 index 0000000..9ab99cd --- /dev/null +++ b/onepassword.py @@ -0,0 +1,156 @@ +#!/usr/bin/env python3 + +# This script makes some pretty naive assumptions. +# It assumes that you have setup your 1Password account atleast once, by issuing: op signin <sign_in_address> <email_address> <secret_key> +# Furthermore it assumes a very happy flow of things, and deliberately doesn't do a lot of try-except error handling to improve performance. +# +# To find 1Password's latest CLI release, consult: https://app-updates.agilebits.com/product_history/CLI +# To install 1Password execute the following command: +# wget https://cache.agilebits.com/dist/1P/op/pkg/LATEST/op_linux_arm64_LATEST.zip && \ +# unzip op_linux_arm64_LATEST.zip && \ +# sudo mv op /usr/local/bin/op && \ +# rm op.sig && \ +# rm op_linux_arm64_LATEST.zip +# +# To install pexpect execute the following command: +# sudo pip install pexpect + +import subprocess +import json +import operator +import os +import sys +import pexpect +import re + +SUCCESS = 0 +FAILURE = 1 + +# TODO: change this into a color that suites your dmenu. +COLOR = "#bcecff" + +UUID_REGEX_PATTERN = re.compile("^.*\((.*)\)$") + + +def notify(message): + if not os.environ.get("SSH_CLIENT") and not os.environ.get("SSH_TTY"): + subprocess.run(["notify-send", message]) + + +def notify_and_die(message): + notify(message) + + print(message, file=sys.stderr) + sys.exit(FAILURE) + + +dmenu_result = subprocess.run( + [ + "ash", + "-c", + f"sxmo_dmenu_with_kb.sh -c -p \"pwd:\" -nf '{COLOR}' -nb '{COLOR}' <&-", + ], + capture_output=True, +) +password = bytes.decode(dmenu_result.stdout, "utf-8").strip() + +signin_process = None +try: + signin_process = pexpect.spawn("op signin") + signin_process.expect("Enter the password for .* at .*\.1password\.com: ") + signin_process.sendline(password) + signin_process.expect(pexpect.EOF, timeout=5) + signin_process.close() +except: + notify_and_die("unable to sign in...") + +if signin_process.exitstatus != SUCCESS: + notify_and_die("wrong password...") + +signin_token = ( + bytes.decode(signin_process.before, "utf-8").split("\r\n")[1].split(" ")[1].strip() +) + +list_vaults_process = subprocess.run( + ["ash", "-c", f"{signin_token} op list vaults"], capture_output=True +) +vaults = json.loads(list_vaults_process.stdout) + +vaults = sorted(vaults, key=operator.itemgetter("name")) +dmenu_input = "\n".join([f"{vault['name']} ({vault['uuid']})" for vault in vaults]) + +dmenu_result = subprocess.run( + [ + "sxmo_dmenu_with_kb.sh", + "-c", + "-l", + "10", + ], + capture_output=True, + input=bytes(dmenu_input, "utf-8"), +) +selected_vault_id = UUID_REGEX_PATTERN.match( + bytes.decode(dmenu_result.stdout, "utf-8").strip() +).group(1) + +list_items_process = subprocess.run( + ["ash", "-c", f"{signin_token} op list items"], capture_output=True +) +items = json.loads(list_items_process.stdout) + +items = [ + { + "uuid": item["uuid"], + "title": item["overview"]["title"], + "username": item["overview"]["ainfo"], + } + for item in items + if item["trashed"] == "N" and item["vaultUuid"] == selected_vault_id +] +items = sorted(items, key=operator.itemgetter("title")) + +dmenu_input = "\n".join( + [ + f"{item['title']} ({item['username'] if item['username'] else '-'}) ({item['uuid']})" + for item in items + ] +) + +dmenu_result = subprocess.run( + [ + "sxmo_dmenu_with_kb.sh", + "-c", + "-l", + "10", + ], + capture_output=True, + input=bytes(dmenu_input, "utf-8"), +) + +selected_item_id = UUID_REGEX_PATTERN.match( + bytes.decode(dmenu_result.stdout, "utf-8").strip() +).group(1) + +get_item_process = subprocess.run( + ["ash", "-c", f"{signin_token} op get item {selected_item_id}"], + capture_output=True, +) +item = json.loads(get_item_process.stdout) + +password = list( + filter(lambda field: field["designation"] == "password", item["details"]["fields"]) +)[0]["value"] + +if os.environ.get("SSH_CLIENT") or os.environ.get("SSH_TTY"): + print(password) +else: + subprocess.run( + ["xclip", "-i", "/dev/null"], + ) + subprocess.run( + ["xclip", "-i"], + input=bytes(password, "utf-8"), + ) + notify("copied to clipboard!") + +sys.exit(SUCCESS) -- 2.20.1
Thanks! Applied. To git.sr.ht:~anjan/sxmo-userscripts 7deb5a2..d067649 master -> master -- w:] www.momi.ca pgp:] https://momi.ca/publickey.txt