i3/.config/i3/pass_typer.py

76 lines
2.3 KiB
Python
Executable File

#!/usr/bin/env python3
import os
import re
import subprocess
from functools import partial
from itertools import chain
from pathlib import Path
PASSWORD_STORE = Path(
os.environ.get("PASSWORD_STORE_DIR", Path("~/.password-store").expanduser())
)
cmd = partial(subprocess.run, capture_output=True, encoding="ascii")
def alias(server_name):
match server_name.rpartition("@"):
case [user, at, ("salt" | "salt.sawtooth.claremontmakerspace.org")]:
return f"cms/{user}{at}cms-net-svcs"
case [user, at, host] if host.lower().startswith("cms-wall-display") or host.startswith("iPad"):
return f"cms/{user}{at}ipads"
case [user, at, ("octopi-taz-6" | "octopi-lulzbot-mini")]:
return f"cms/{user}{at}octopi"
case [user, at, server] if re.match(".*-pidgey(.vpn)?", server):
return "tsrc/pidgey"
case _:
return f"**/{server_name}"
def notify(summary: str, body: str) -> None:
subprocess.run(["notify-send", summary, body])
def rofi_select(options: list[str]) -> str:
options_str = "\n".join(options)
rofi = cmd(["rofi", "-dmenu"], input=options_str)
return rofi.stdout.strip()
def get_password(password_name: str) -> str:
pass_result = cmd(["pass", password_name])
password, _, _ = pass_result.stdout.partition("\n")
return password
def select_and_type(server_name: Path) -> None:
path = ("servers" / server_name).with_name(server_name.name + ".gpg")
files = chain(
PASSWORD_STORE.glob(str(path)),
PASSWORD_STORE.glob(str(path.with_name("*@" + path.name))),
)
file_list = list(
dict.fromkeys(str(f.relative_to(PASSWORD_STORE).with_suffix("")) for f in files)
)
selected = rofi_select(file_list)
if selected:
password = get_password(selected)
subprocess.run(["xdotool", "type", password + "\n"])
window_name = cmd(["xdotool", "getactivewindow", "getwindowname"]).stdout.strip()
ssh_match = re.search(":([^ ]+=[^ ]* )*(mosh|ssh) (?P<server>.*)", window_name)
if ssh_match:
server_name = alias(ssh_match.group("server"))
notify(f"Matched server '{server_name}'", f"Window name: {window_name}")
select_and_type(Path(server_name))
else:
notify("Window name did not match any rules", f"Window name: {window_name}")