diff --git a/setup.py b/setup.py index b9be62a..a2aabc2 100755 --- a/setup.py +++ b/setup.py @@ -42,4 +42,12 @@ "Programming Language :: Python :: 3.11", "Topic :: Software Development :: Libraries :: Python Modules", ], + entry_points={ + 'console_scripts': [ + 'pyotp = pyotp.__main__:generate', + 'pyotph = pyotp.__main__:generate_hex', + 'pytotp = pyotp.__main__:otp', + 'pyhotp = pyotp.__main__:hotp', + ] + }, ) diff --git a/src/pyotp/__init__.py b/src/pyotp/__init__.py index a695790..f093ea8 100644 --- a/src/pyotp/__init__.py +++ b/src/pyotp/__init__.py @@ -9,6 +9,8 @@ from .otp import OTP as OTP from .totp import TOTP as TOTP +__version__ = "2.9.0" + def random_base32(length: int = 32, chars: Sequence[str] = list("ABCDEFGHIJKLMNOPQRSTUVWXYZ234567")) -> str: # Note: the otpauth scheme DOES NOT use base32 padding for secret lengths not divisible by 8. diff --git a/src/pyotp/__main__.py b/src/pyotp/__main__.py new file mode 100644 index 0000000..e4e55a6 --- /dev/null +++ b/src/pyotp/__main__.py @@ -0,0 +1,53 @@ +from pyotp import __version__, TOTP, HOTP, random_base32, random_hex +from sys import argv + + +def argument_parser(): + if len(argv) > 1: + if argv[1] in ('-v', '--version'): + print(f'PyOTP v.{__version__}') + else: + print(f'''PyOTP v.{__version__} usage:\ + \n pyotp - Generate a 32-character base32 secret\ + \n pyotph - Generate a hex-encoded base32 secret\ + \n pytotp - Return TOTP digits from base32 secret\ + \n pyhotp - Return HOTP digits from base32 secret\ + ''') + exit() + + +def generate(hex=False): + argument_parser() + if not hex: + print(random_base32()) + else: + print(random_hex()) + + +def generate_hex(): + generate(hex=True) + + +def otp(is_totp=True): + argument_parser() + try: + if is_totp: + print("Enter base32 secret: ", end='') + secret = input() + print(TOTP(secret).now()) + else: + print("Enter base32 secret: ", end='') + secret = input() + print("Enter number: ", end='') + number = int(input()) + print(HOTP(secret).at(number)) + except: + print(f'Invalid secret: {secret}') + + +def hotp(): + otp(is_totp=False) + + +if __name__ == "__main__": + generate()