Ответ на комментарий от btimofeev
btimofeev> Я использую скрипт https://github.com/carnager/rofi-pass , который позволяет искать и копировать логины\пароли через rofi (https://github.com/davatorium/rofi )С помощью rofi работает у меня сторонний скрипт bemoji для выбора эмодзи из UTF-8: https://github.com/marty-oehme/bemoji .
Кстати, вот сам скрипт "pypassmenu" на текущий момент. Пусть под лицензией UNLICENSE. Далёк от идеала, но может кто вдохновится или будет интересно.
#!/usr/bin/env python import os import re import sys import logging from time import sleep from pathlib import Path from subprocess import Popen, PIPE from argparse import ArgumentParser class PassFile: def __init__(self, name: str, content: str): self.name = name self._lines: list[str] = content.split('\n') self._fields: dict[str, str] = {} for line in self._lines: m = re.match(r'(.+): (.+)', line) if m: self._fields[m.group(1)] = m.group(2) logging.info(f'Created PassFile instance of {name}') logging.debug(f'PassFile fields: {self._fields}') @property def password(self) -> str: return self._lines[0] def _get_field(self, field: str) -> str: return self._fields[field] @property def email(self) -> str: try: logging.debug('Trying to find "email" field') return self._get_field('email') except KeyError: logging.debug('Falling back to "e-mail" field') return self._get_field('e-mail') @property def login(self) -> str: try: logging.debug('Trying to find "login" field') return self._get_field('login') except KeyError: logging.debug('Falling back to e(-)mail field') return self.email def fetch_passfiles() -> dict[str,Path]: store_path = Path(os.getenv('PASSWORD_STORE_DIR') or os.getenv('HOME') + '/.password-store') gpg_files = list(store_path.glob('**/*.gpg')) gpg_files_dict = {} for filepath in gpg_files: relative_filepath = str(filepath.relative_to(store_path)) gpg_files_dict[re.sub(r'\.gpg$', '', relative_filepath)] = filepath return gpg_files_dict def choose_passfile_with_dmenu(gpg_files_dict: dict[str,Path]) -> tuple[str, Path]: p = Popen(['dmenu'], stdout=PIPE, stdin=PIPE, text=True) index = '\n'.join([key for key in gpg_files_dict]) stdout = p.communicate(input=index)[0] choosen_filename = stdout.strip() return choosen_filename, gpg_files_dict[choosen_filename] def fetch_passfile_by_path(filename: str, filepath: Path) -> PassFile: p = Popen(['gpg', '-d', '--quiet', str(filepath)], stdout=PIPE, text=True) return PassFile(filename, p.stdout.read().strip()) def copy_to_clipboard(text: str): p = Popen(['xclip', '-selection', 'clipboard'], stdin=PIPE, text=True) p.communicate(input=text) logging.info('Clipboard was written') logging.debug(f'Clipboard content: {text}') def clear_clipboard(): logging.debug('Clipboard cleared!') copy_to_clipboard('') def notify(header: str, body: str): Popen(['notify-send', header, body]) logging.info('Notification sent') logging.debug(f'Notification content:\n{header=}\n{body=}') def main(): parser = ArgumentParser(prog='pypassmenu', description='Improved passmenu written in python') supported_fields = ( 'password', 'login', 'email', ) parser.add_argument('field', type=str, choices=supported_fields, default=supported_fields[0], help='Obtained field') args = parser.parse_args() # logging.basicConfig(level=logging.DEBUG) filename, filepath = choose_passfile_with_dmenu(fetch_passfiles()) pass_ = fetch_passfile_by_path(filename, filepath) important_value = 'something' try: match args.field: case 'password': important_value = pass_.password case 'login': important_value = pass_.login case 'email': important_value = pass_.email except KeyError: notify('Не удалось найти поле', f'pypassmenu: выбранное поле не найдено в {pass_.name}') sys.exit(1) copy_to_clipboard(important_value) sleep(20) clear_clipboard() if __name__ == '__main__': main()
tuple (2024-10-19 08:42:54)
[Ответить]