Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env python3
- # Version 10
- # POSTED ONLINE: https://pastebin.com/g10jVftx
- # Windows: $ pip install pyperclip asciimatics
- #
- # Linux: $ sudo pacman -S python-pyperclip
- # $ sudo pacman -S wl-clipboard <-- Pyperclip has issues with KDE + Wayland. Installing this seems to get it to work.
- # $ yay -S python-asciimatics
- #
- # NOTE: For Linux you also need to install a copy/paste mechanism if you don't have one.
- # KDE has /bin/klipper installed by default. For other window managers try [$ sudo pacman -S xclip] or [$ sudo pacman -S xsel].
- #
- # NOTE: If you get error "Cannot find '.setClipboardContents' in object /klipper at org.kde.klipper",
- # its because klipper isn't running on startup. Try Start > klipper to see if the problem goes away.
- #
- # NOTE: To display klipper in the taskbar, right click the ^ > Configure System Tray... > Entries > Clipboard: [Show when relevant].
- import pyperclip
- from asciimatics.screen import Screen
- from asciimatics.event import KeyboardEvent
- # -----
- def draw_menu(screen, menuItems, selectedIndex, title, highlight):
- # Clear screen.
- clear(screen)
- # Draw title.
- if title:
- writeline(screen, title)
- # Draw menu items.
- for i in range(len(menuItems)):
- menuItem = menuItems[i]
- if highlight in menuItem:
- left,right = menuItem.split(highlight)
- write(screen, f' {"●" if i == selectedIndex else "○"} {left}', Screen.COLOUR_GREEN if i == selectedIndex else Screen.COLOUR_CYAN)
- write(screen, f'{highlight}', Screen.COLOUR_RED)
- writeline(screen, f'{right}', Screen.COLOUR_GREEN if i == selectedIndex else Screen.COLOUR_CYAN)
- else:
- writeline(screen, f' {"●" if i == selectedIndex else "○"} {menuItem}', Screen.COLOUR_RED)
- # Draw usage information.
- writeline(screen)
- writeline(screen, ' Make → Space', Screen.COLOUR_YELLOW)
- writeline(screen, ' Copy → Enter', Screen.COLOUR_YELLOW)
- writeline(screen, ' Rise → Up', Screen.COLOUR_YELLOW)
- writeline(screen, ' Fall → Down', Screen.COLOUR_YELLOW)
- writeline(screen, ' Smol → Left', Screen.COLOUR_YELLOW)
- writeline(screen, ' Swol → Right', Screen.COLOUR_YELLOW)
- writeline(screen, ' Quit → Escape', Screen.COLOUR_YELLOW)
- # Draw screen.
- screen.refresh()
- # -----
- row = 0
- col = 0
- def writeline(screen, text='', color=Screen.COLOUR_WHITE):
- global row
- global col
- lines = text.split('\n')
- for i, line in enumerate(lines):
- screen.print_at(line, col, row, color)
- row += 1
- col = 0
- def write(screen, text='', color=Screen.COLOUR_WHITE):
- global row
- global col
- lines = text.split('\n')
- for i, line in enumerate(lines):
- screen.print_at(line, col, row, color)
- if i < len(lines) - 1:
- row += 1
- col = 0
- else:
- col += len(line)
- def clear(screen):
- global row
- global col
- row = 0
- col = 0
- screen.clear()
- # -----
- import string
- # Character groups to be used in the password.
- CHARACTER_GROUPS = [
- string.ascii_lowercase,
- string.ascii_uppercase,
- string.digits,
- string.punctuation,
- ]
- TIMESTAMP_DIVIDER = '_'
- from datetime import datetime
- import secrets
- def generate_timestamped_passwords(password_length, count=5):
- dt = datetime.now()
- short_time_stamp = dt.strftime('%y%m%d')
- password_characters = ''.join(CHARACTER_GROUPS)
- password_characters = password_characters.replace(TIMESTAMP_DIVIDER, '')
- passwords = []
- retries = 100
- for _ in range(count):
- for attempt in range(retries):
- # SOURCE: https://docs.python.org/3/library/secrets.html
- password = ''.join(secrets.choice(password_characters) for _ in range(password_length))
- password = shuffle(short_time_stamp, password, TIMESTAMP_DIVIDER)
- if validate_password(password):
- passwords.append(password)
- break
- else:
- passwords.append(f'ERROR: Failed to generate a valid password after {retries} attempts.')
- large_time_stamp = f' Created: {dt.strftime("%Y-%m-%d %H:%M:%S")}\n'
- large_time_stamp += f' Length: {password_length}\n'
- return passwords, large_time_stamp, short_time_stamp
- # -----
- MIN_CHARACTERS_PER_GROUP = 2
- def validate_password(password):
- for group in CHARACTER_GROUPS:
- if sum(char in group for char in password) < MIN_CHARACTERS_PER_GROUP:
- return False
- return True
- # -----
- # Insert a word into a sentence randomly.
- def shuffle(word, sentence, divider = ' '):
- max_word_index = len(sentence) - len(word)
- # Generate a random integer in the range [0, n).
- random_index = secrets.randbelow(max_word_index + 1)
- # Prevent sentences from starting/ending with a word divider.
- if random_index == 1:
- random_index = 0 # Push word left one position.
- elif random_index == max_word_index - 1:
- random_index = max_word_index # Push word right one position.
- # Insert the word into the sentence.
- sentence = sentence[:random_index] + word + sentence[random_index + len(word):]
- # Insert word dividers.
- sentence = list(sentence)
- left_index = random_index - 1
- right_index = random_index + len(word)
- if left_index >= 0:
- sentence[left_index] = divider
- if right_index < len(sentence):
- sentence[right_index] = divider
- return ''.join(sentence)
- # -----
- def wait_for_any_keypress(screen):
- writeline(screen, ' Press any key to continue . . . ')
- screen.refresh()
- # Wait for user keyboard input indefinitely.
- while True:
- screen.wait_for_input(5) # Sleep for this many seconds while waiting for input. This prevents 100% CPU usage from the loop.
- ev = screen.get_event()
- if isinstance(ev, KeyboardEvent):
- break
- # -----
- MIN_PASSWORD_LENGTH = 13
- def main(screen):
- password_length = 32
- menuItems, large_time_stamp, short_time_stamp = generate_timestamped_passwords(password_length)
- selectedIndex = 0
- draw_menu(screen, menuItems, selectedIndex, large_time_stamp, short_time_stamp) # Initial drawing.
- while True:
- # Get keyboard input.
- screen.wait_for_input(5) # Sleep for this many seconds while waiting for input. This prevents 100% CPU usage from the loop.
- ev = screen.get_event()
- if not isinstance(ev, KeyboardEvent):
- continue
- # If Escape key is pressed.
- elif ev.key_code == -1:
- break
- # If Space key is pressed.
- elif ev.key_code == ord(' '):
- menuItems, large_time_stamp, short_time_stamp = generate_timestamped_passwords(password_length)
- # If Up key is pressed.
- elif ev.key_code == Screen.KEY_UP:
- # Loop around backwards.
- selectedIndex = (selectedIndex - 1 + len(menuItems)) % len(menuItems)
- # If Down key is pressed.
- elif ev.key_code == Screen.KEY_DOWN:
- # Loop around forwards.
- selectedIndex = (selectedIndex + 1) % len(menuItems)
- # If Left key is pressed.
- elif ev.key_code == Screen.KEY_LEFT:
- # Reduce length of passwords.
- password_length = max(MIN_PASSWORD_LENGTH, password_length - 1)
- menuItems, large_time_stamp, short_time_stamp = generate_timestamped_passwords(password_length)
- # If Right key is pressed.
- elif ev.key_code == Screen.KEY_RIGHT:
- # Increase length of passwords.
- password_length = password_length + 1
- menuItems, large_time_stamp, short_time_stamp = generate_timestamped_passwords(password_length)
- # If Enter key is pressed.
- # NOTE: On Windows the enter key appears to be \r, and on Linux its \n.
- elif ev.key_code == ord('\r') or ev.key_code == ord('\n'):
- pyperclip.copy(menuItems[selectedIndex])
- writeline(screen, f"\n Copied {menuItems[selectedIndex]} to clipboard.\n")
- wait_for_any_keypress(screen)
- # Else an unexpected key is pressed.
- # else:
- # try:
- # writeline(screen, "\n The pressed key '{}' {} is not associated with a menu function.\n".format(chr(ev.key_code), ev.key_code))
- # except ValueError:
- # writeline(screen, "\n The pressed key {} is not associated with a menu function.\n".format(ev.key_code))
- # wait_for_any_keypress(screen)
- draw_menu(screen, menuItems, selectedIndex, large_time_stamp, short_time_stamp)
- if __name__ == '__main__':
- Screen.wrapper(main)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement