返回 Social Auto Upload
login_qrcode.py
根目录 / utils / login_qrcode.py
1 # -*- coding: utf-8 -*-
2 from datetime import datetime
3 import base64
4 from pathlib import Path
5 import sys
6
7 import cv2
8 import segno
9
10
11 def build_login_qrcode_path(account_file: str, suffix: str = "login_qrcode") -> Path:
12 account_path = Path(account_file)
13 timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
14 return account_path.with_name(f"{account_path.stem}_{suffix}_{timestamp}.png")
15
16
17 def save_data_url_image(data_url: str, output_path: Path) -> Path:
18 if not data_url.startswith("data:image/"):
19 raise ValueError("二维码地址不是 data:image 格式")
20
21 header, encoded = data_url.split(",", 1)
22 if ";base64" not in header:
23 raise ValueError("二维码图片不是 base64 编码")
24
25 output_path.parent.mkdir(parents=True, exist_ok=True)
26 output_path.write_bytes(base64.b64decode(encoded))
27 return output_path
28
29
30 def remove_qrcode_file(qrcode_path: Path | None) -> bool:
31 if qrcode_path and qrcode_path.exists():
32 qrcode_path.unlink()
33 return True
34 return False
35
36
37 def decode_qrcode_from_path(qrcode_path: Path) -> str | None:
38 # Windows 下 cv2.imread 不支持中文路径, 改用 np.fromfile + imdecode
39 import numpy as np
40
41 try:
42 image = cv2.imdecode(np.fromfile(str(qrcode_path), dtype=np.uint8), cv2.IMREAD_COLOR)
43 except Exception:
44 return None
45 if image is None:
46 return None
47
48 detector = cv2.QRCodeDetector()
49 qrcode_content, _, _ = detector.detectAndDecode(image)
50 return qrcode_content or None
51
52
53 def _print_ascii_qrcode(qrcode) -> None:
54 border = 1
55 rows = list(qrcode.matrix)
56 empty_line = " " * (len(rows[0]) + border * 2)
57 print(empty_line)
58 for row in rows:
59 line = [" "] * border
60 line.extend("##" if cell else " " for cell in row)
61 line.extend([" "] * border)
62 print("".join(line))
63 print(empty_line)
64
65
66 def print_terminal_qrcode(
67 qrcode_content: str,
68 qrcode_path: Path,
69 app_name: str,
70 compact: bool = True,
71 border: int = 0,
72 ) -> None:
73 print()
74 print(f"请使用{app_name}扫描下方二维码登录:")
75 qrcode = segno.make(qrcode_content, error="L", boost_error=False)
76 try:
77 if hasattr(sys.stdout, "reconfigure"):
78 sys.stdout.reconfigure(encoding="utf-8")
79 qrcode.terminal(compact=compact, border=border)
80 except (UnicodeEncodeError, OSError):
81 print("当前终端不支持 Unicode 二维码字符,已切换为 ASCII 打印:")
82 _print_ascii_qrcode(qrcode)
83 print("在 Windows 下建议使用 Windows Terminal(支持 UTF-8,可完整显示二维码)")
84 print(f"否则请打开 {qrcode_path} 扫码")
85 print()
86
86 lines PYTHON