32 lines
913 B
Python
32 lines
913 B
Python
"""Коды пополнения баланса."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import re
|
|
import secrets
|
|
import string
|
|
|
|
# Без похожих символов O/0, I/1, L
|
|
_CODE_ALPHABET = "".join(
|
|
c for c in (string.ascii_uppercase + string.digits) if c not in "O0IL1"
|
|
)
|
|
_CODE_RE = re.compile(r"^[A-Z0-9]{4}(?:-[A-Z0-9]{4}){3}$")
|
|
|
|
|
|
def normalize_code(raw: str) -> str:
|
|
"""XXXX-XXXX-XXXX-XXXX из произвольного ввода."""
|
|
cleaned = "".join(ch for ch in (raw or "").upper() if ch.isalnum())
|
|
if len(cleaned) != 16:
|
|
return cleaned
|
|
return "-".join(cleaned[i : i + 4] for i in range(0, 16, 4))
|
|
|
|
|
|
def is_valid_code_format(code: str) -> bool:
|
|
norm = normalize_code(code)
|
|
return bool(_CODE_RE.fullmatch(norm))
|
|
|
|
|
|
def generate_code() -> str:
|
|
parts = ["".join(secrets.choice(_CODE_ALPHABET) for _ in range(4)) for _ in range(4)]
|
|
return "-".join(parts)
|