Files
EveryPublish/utils/login_qrcode.py
T
2026-03-24 23:02:22 +08:00

74 lines
2.3 KiB
Python

# -*- coding: utf-8 -*-
from datetime import datetime
import base64
from pathlib import Path
import sys
import cv2
import segno
def build_login_qrcode_path(account_file: str, suffix: str = "login_qrcode") -> Path:
account_path = Path(account_file)
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
return account_path.with_name(f"{account_path.stem}_{suffix}_{timestamp}.png")
def save_data_url_image(data_url: str, output_path: Path) -> Path:
if not data_url.startswith("data:image/"):
raise ValueError("二维码地址不是 data:image 格式")
header, encoded = data_url.split(",", 1)
if ";base64" not in header:
raise ValueError("二维码图片不是 base64 编码")
output_path.parent.mkdir(parents=True, exist_ok=True)
output_path.write_bytes(base64.b64decode(encoded))
return output_path
def remove_qrcode_file(qrcode_path: Path | None) -> bool:
if qrcode_path and qrcode_path.exists():
qrcode_path.unlink()
return True
return False
def decode_qrcode_from_path(qrcode_path: Path) -> str | None:
image = cv2.imread(str(qrcode_path))
if image is None:
return None
detector = cv2.QRCodeDetector()
qrcode_content, _, _ = detector.detectAndDecode(image)
return qrcode_content or None
def _print_ascii_qrcode(qrcode) -> None:
border = 1
rows = list(qrcode.matrix)
empty_line = " " * (len(rows[0]) + border * 2)
print(empty_line)
for row in rows:
line = [" "] * border
line.extend("##" if cell else " " for cell in row)
line.extend([" "] * border)
print("".join(line))
print(empty_line)
def print_terminal_qrcode(qrcode_content: str, qrcode_path: Path, app_name: str) -> None:
print()
print(f"请使用{app_name}扫描下方二维码登录:")
qrcode = segno.make(qrcode_content, error="L", boost_error=False)
try:
if hasattr(sys.stdout, "reconfigure"):
sys.stdout.reconfigure(encoding="utf-8")
qrcode.terminal(compact=True, border=0)
except (UnicodeEncodeError, OSError):
print("当前终端不支持 Unicode 二维码字符,已切换为 ASCII 打印:")
_print_ascii_qrcode(qrcode)
print("在 Windows 下建议使用 Windows Terminal(支持 UTF-8,可完整显示二维码)")
print(f"否则请打开 {qrcode_path} 扫码")
print()