56 lines
2.1 KiB
Python
56 lines
2.1 KiB
Python
from __future__ import annotations
|
|
|
|
import re
|
|
import unicodedata
|
|
from typing import Any
|
|
|
|
_DIGIT_WORDS = {
|
|
"zero": "0", "um": "1", "uma": "1", "dois": "2", "duas": "2",
|
|
"tres": "3", "quatro": "4", "cinco": "5", "seis": "6", "sete": "7",
|
|
"oito": "8", "nove": "9",
|
|
}
|
|
|
|
|
|
def _norm(text: Any) -> str:
|
|
value = unicodedata.normalize("NFKD", str(text or "").casefold())
|
|
value = "".join(ch for ch in value if not unicodedata.combining(ch))
|
|
return re.sub(r"\s+", " ", value).strip()
|
|
|
|
|
|
def extract_requested_line_reference(text: Any) -> dict[str, str] | None:
|
|
"""Extrai somente uma referência explícita de linha citada pelo usuário.
|
|
|
|
Não transforma a referência em identidade autorizada. Essa decisão pertence à
|
|
política de linha ativa no domínio Contas.
|
|
"""
|
|
raw = str(text or "").strip()
|
|
if not raw:
|
|
return None
|
|
norm = _norm(raw)
|
|
|
|
# Número completo explicitamente presente no texto (10 a 13 dígitos, com
|
|
# separadores opcionais). Evita capturar valores monetários ou protocolos curtos.
|
|
for match in re.finditer(r"(?<!\d)(?:\+?\d[\s().-]*){10,13}(?!\d)", raw):
|
|
digits = "".join(ch for ch in match.group(0) if ch.isdigit())
|
|
if 10 <= len(digits) <= 13:
|
|
return {"kind": "full", "value": digits, "raw": match.group(0).strip()}
|
|
|
|
# Referência por final da linha: "final 4321", "final quatro três dois um",
|
|
# "termina em 4321". Só a referência é extraída; nunca é assumida como MSISDN.
|
|
marker = re.search(r"\b(?:final|termina(?:ndo)?\s+em|terminado\s+em)\b(.{0,45})", norm)
|
|
if marker:
|
|
tail = marker.group(1)
|
|
numeric = re.search(r"\b(\d{4})\b", tail)
|
|
if numeric:
|
|
return {"kind": "suffix", "value": numeric.group(1), "raw": numeric.group(1)}
|
|
tokens = re.findall(r"[a-z]+", tail)
|
|
digits: list[str] = []
|
|
for token in tokens:
|
|
if token in _DIGIT_WORDS:
|
|
digits.append(_DIGIT_WORDS[token])
|
|
if len(digits) == 4:
|
|
return {"kind": "suffix", "value": "".join(digits), "raw": " ".join(tokens[:4])}
|
|
elif digits:
|
|
break
|
|
return None
|