"""Extrae IPv4 + IPv6 validas de un texto, con offsets.""" import ipaddress import re _IPV4_CANDIDATE = re.compile(r"\b\d{1,3}(?:\.\d{1,3}){3}\b") _IPV6_CANDIDATE = re.compile( r"(? list[dict]: """Extrae IPv4 e IPv6 validas con offsets. Filtra candidatos que no parsean como IP valida con `ipaddress`. No distingue IP privadas (10.x, 192.168.x) de publicas — el filtrado de relevancia es responsabilidad del caller. """ results: list[dict] = [] for m in _IPV4_CANDIDATE.finditer(text): candidate = m.group(0) try: ipaddress.IPv4Address(candidate) except ValueError: continue results.append({ "value": candidate, "start": m.start(), "end": m.end(), "type": "ip_address", }) for m in _IPV6_CANDIDATE.finditer(text): candidate = m.group(0).split("%", 1)[0] if candidate.count(":") < 2: continue try: ipaddress.IPv6Address(candidate) except ValueError: continue results.append({ "value": m.group(0), "start": m.start(), "end": m.end(), "type": "ip_address", }) results.sort(key=lambda r: r["start"]) return results