# -----------------------------------------------------------------------------
# Home-Ka — US real-estate aggregator (Groupe KA)
# Author: Simon-Pierre Boucher — contact@spboucher.ai
# connectors/json/jsonld_site.py : schema.org JSON-LD site connector.
#
# Many brokerage sites (Real Estate Webmasters and other server-rendered
# platforms) publish each listing as JSON-LD (`Product` + `RealEstateListing`
# / `SingleFamilyResidence` nodes) — clean, stable data with full address,
# geo, price and photos, no proxy needed. This is the SECONDARY crawler path
# (authority 3): use it to bootstrap coverage while converting the brokerage
# to a direct feed. Ported from immo-ka connectors/jsonld.py.
#
# {"id": "michael_saunders", "connector_type": "jsonld", "config": {
# "base_url": "https://www.michaelsaunders.com",
# "url_include": "/listing/",
# "external_id_regex": "/listing/([A-Z0-9-]+)/", # from the URL
# "max_pages": 400, "static": {"state": "FL"}}}
# -----------------------------------------------------------------------------
from __future__ import annotations
import hashlib
import json
import re
import time
from ..base import BaseConnector
from ...normalize import parse_price
from ...schema import Listing
_LD_RE = re.compile(r'',
re.S | re.I)
_LOC_RE = re.compile(r"\s*(?:)?\s*",
re.S | re.I)
_LISTING_TYPES = {
"realestatelisting", "singlefamilyresidence", "house", "residence",
"apartment", "product", "accommodation", "condominium", "townhouse",
# some SSR platforms (Repliers/Next.js) mark the listing as a plain Place;
# safe here because pages are pre-filtered by url_include
"place",
}
# URL slug fallback: ".../7039-s-straight-avenue-homosassa-fl-34446/"
_SLUG_ADDR_RE = re.compile(r"/([\w-]+)-([a-z]{2})-(\d{5})/?$", re.I)
# `name` fallback: several platforms (Real Geeks, @properties/Christie's)
# put the full address in Product.name — "123 Main St #4, Austin, TX 78701"
_NAME_ADDR_RE = re.compile(
r"^(.+?),\s*([^,]+?),\s*([A-Za-z]{2})[,\s]+(\d{5})(?:-\d{4})?\s*$")
# Next.js "flight" streaming: some SSR sites (Douglas Elliman) embed the
# JSON-LD as self.__next_s.push([0,{"type":"application/ld+json",
# "children":""}]) instead of a