[object Object]

← back to Commercialrealestate

enrich-condo-brokers: record ALL license numbers per listing (multi-agent listingAgents capture, not just [0]) + hook every agent DRE# into its full CA DRE record (cached, $0)

fcd24a8dddf8107849b72a6fc946cc9a985e45ab · 2026-08-03 10:53:25 -0700 · Steve Abrams

Files touched

Diff

commit fcd24a8dddf8107849b72a6fc946cc9a985e45ab
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Mon Aug 3 10:53:25 2026 -0700

    enrich-condo-brokers: record ALL license numbers per listing (multi-agent listingAgents capture, not just [0]) + hook every agent DRE# into its full CA DRE record (cached, $0)
---
 scripts/enrich-condo-brokers.js | 44 ++++++++++++++++++++++++++++++++---------
 1 file changed, 35 insertions(+), 9 deletions(-)

diff --git a/scripts/enrich-condo-brokers.js b/scripts/enrich-condo-brokers.js
index 544d465..14d2ddd 100644
--- a/scripts/enrich-condo-brokers.js
+++ b/scripts/enrich-condo-brokers.js
@@ -54,16 +54,32 @@ function extractBroker(raw) {
   // Redfin embeds the listing state as an ESCAPED JSON string (\"listingAgents\":[...]) inside the
   // page, so normalize \" -> " before matching. Harmless for our field extraction.
   const html = String(raw).replace(/\\"/g, '"');
-  // Richest block: "listingAgents":[{"agentInfo":{"agentName":"..."},"brokerName":"...","license":"...","breNumber":"..."}]
-  const la = html.match(/"listingAgents":\s*\[\s*\{(.*?)\}\s*\]/s);
+  // Record EVERY license number on the listing (Steve 2026-08-03): the listingAgents array carries
+  // the primary listing agent AND any co-listing agent, each with its own name/brokerName/license.
+  // Capture the full array, split into agent objects (one level of nesting = agentInfo), and pull a
+  // {name, firm, dre} from each — not just [0]. Primary stays in the flat fields for back-compat.
+  const la = html.match(/"listingAgents":\s*\[(.*?)\]/s);
   if (la) {
-    const blk = la[1];
-    const an = blk.match(/"agentName":"([^"]{1,80})"/);
-    const bn = blk.match(/"brokerName":"([^"]{1,120})"/);
-    const lic = blk.match(/"(?:license|breNumber)":"(\d{6,8})"/);
-    if (an && an[1] && !/^\s*$/.test(an[1])) out.broker_name = an[1].trim();
-    if (bn && bn[1]) out.firm_name = bn[1].trim();
-    if (lic) out.broker_dre = lic[1];
+    const objs = la[1].match(/\{[^{}]*(?:\{[^{}]*\}[^{}]*)*\}/g) || [];
+    const agents = [];
+    const seen = new Set();
+    for (const blk of objs) {
+      const an = blk.match(/"agentName":"([^"]{1,80})"/);
+      const bn = blk.match(/"brokerName":"([^"]{1,120})"/);
+      const lic = blk.match(/"(?:license|breNumber)":"(\d{6,8})"/);
+      const a = {};
+      if (an && an[1].trim()) a.name = an[1].trim();
+      if (bn && bn[1].trim()) a.firm = bn[1].trim();
+      if (lic) a.dre = lic[1];
+      const k = a.dre || a.name;
+      if ((a.name || a.dre) && k && !seen.has(k)) { seen.add(k); agents.push(a); }
+    }
+    if (agents.length) {
+      out.agents = agents;                                    // ALL license-bearing agents
+      if (agents[0].name) out.broker_name = agents[0].name;   // primary (back-compat)
+      if (agents[0].firm) out.firm_name = agents[0].firm;
+      if (agents[0].dre) out.broker_dre = agents[0].dre;
+    }
   }
   // Fallback flat fields near the top of the page state.
   if (!out.broker_name) { const m = html.match(/"listingAgentName":"([^"]{1,80})"/); if (m && m[1].trim()) out.broker_name = m[1].trim(); }
@@ -178,6 +194,16 @@ async function main() {
     else gotBroker++;
     let dre = null;
     if (b.broker_dre) { dre = await hookDre(b.broker_dre, dreCache); if (dre && dre.dre_status) gotDre++; }
+    // Hook EVERY license number on the listing into its full CA DRE record (Steve: record all
+    // license numbers, always hook the full list). DRE lookups are $0/local and cached, so
+    // resolving co-agents adds no cost; the primary reuses the record already fetched above.
+    if (Array.isArray(b.agents)) {
+      for (const a of b.agents) {
+        if (!a.dre) continue;
+        const d = (a.dre === b.broker_dre) ? dre : await hookDre(a.dre, dreCache);
+        if (d) a.dre_record = d;
+      }
+    }
     brokers[c.id] = { id: c.id, address: c.address, city: c.city, ...b, dre: dre || undefined, fetched_at: new Date().toISOString(), http: status };
     fs.writeFileSync(BROKERS, JSON.stringify(brokers, null, 1));
     process.stdout.write(`\r  ${done}/${targets.length}  broker:${gotBroker}  dre:${gotDre}  blocked:${blocked.length}   `);

← a06fde2 detail-modal drill enrichment (index/sales/mls): index broke  ·  back to Commercialrealestate  ·  record all license numbers on every listing (display): email 3a9480d →