#!/usr/bin/env python3 from __future__ import annotations import argparse import os import sys import time import pyotp def build_totp(secret_or_uri: str) -> pyotp.TOTP: value = secret_or_uri.strip() if value.startswith("otpauth://"): parsed = pyotp.parse_uri(value) if not isinstance(parsed, pyotp.TOTP): raise ValueError("otpauth URI is not a TOTP URI") return parsed return pyotp.TOTP(value) def read_secret(args: argparse.Namespace) -> str: value = os.getenv("WETECH_P81_TOTP_SECRET") or os.getenv("TEST_TOTP_SECRET") if not value: raise ValueError("WETECH_P81_TOTP_SECRET is not configured") return value def main(argv: list[str] | None = None) -> int: parser = argparse.ArgumentParser( description="Fetch or verify the current P81 6-digit TOTP code for browser automation." ) parser.add_argument("--at", type=int, default=None, help="epoch seconds; defaults to now") parser.add_argument("--verify", help="verify a provided code instead of printing the current code") parser.add_argument("--valid-window", type=int, default=1, help="adjacent time windows accepted for --verify") args = parser.parse_args(argv) try: totp = build_totp(read_secret(args)) timestamp = args.at or int(time.time()) if args.verify is not None: ok = totp.verify(args.verify, for_time=timestamp, valid_window=args.valid_window) print("ok" if ok else "invalid") return 0 if ok else 1 print(totp.at(timestamp)) return 0 except Exception as exc: print(f"error: {exc}", file=sys.stderr) return 2 if __name__ == "__main__": raise SystemExit(main())