/** * Collecteur Adresses * Géocodage via BAN (api-adresse.data.gouv.fr) et scaffold pour risques */ const fetch = require('node-fetch') const USER_AGENT = '4NK-IA-Front/1.0 (Document Analysis Tool)' const REQUEST_TIMEOUT_MS = 12000 // URLs des services publics const GEORISQUE_BASE_URL = 'https://www.georisques.gouv.fr' const CADASTRE_BASE_URL = 'https://cadastre.data.gouv.fr' async function geocodeBAN(address) { const q = [address.street, address.postalCode, address.city, address.country] .filter(Boolean) .join(' ') const url = `https://api-adresse.data.gouv.fr/search/?q=${encodeURIComponent(q)}&limit=1` const start = Date.now() try { const res = await fetch(url, { headers: { 'User-Agent': USER_AGENT, 'Accept': 'application/json' }, timeout: REQUEST_TIMEOUT_MS, }) if (!res.ok) throw new Error(`HTTP ${res.status}`) const json = await res.json() const f = json.features && json.features[0] if (!f) { return { success: true, duration: Date.now() - start, score: 0, lat: null, lon: null, label: null } } return { success: true, duration: Date.now() - start, score: f.properties && typeof f.properties.score === 'number' ? f.properties.score : null, lat: f.geometry?.coordinates ? f.geometry.coordinates[1] : null, lon: f.geometry?.coordinates ? f.geometry.coordinates[0] : null, label: f.properties?.label || null, } } catch (e) { return { success: false, duration: Date.now() - start, error: e.message } } } async function collectGéoRisque(lat, lon) { if (!lat || !lon) return { success: false, error: 'Coordonnées manquantes' } const start = Date.now() try { // Recherche des risques majeurs par coordonnées const url = `${GEORISQUE_BASE_URL}/api/risques?lat=${lat}&lon=${lon}&rayon=1000` const res = await fetch(url, { headers: { 'User-Agent': USER_AGENT, 'Accept': 'application/json' }, timeout: REQUEST_TIMEOUT_MS, }) if (!res.ok) throw new Error(`HTTP ${res.status}`) const data = await res.json() const risks = (data.risques || []).map(risk => ({ type: risk.type || 'Risque majeur', level: risk.niveau || 'Non spécifié', description: risk.description || '', sourceUrl: `${GEORISQUE_BASE_URL}/risques/${risk.id || ''}`, distance: risk.distance || null })) return { success: true, duration: Date.now() - start, risks, count: risks.length } } catch (e) { return { success: false, duration: Date.now() - start, error: e.message, risks: [] } } } async function collectCadastre(lat, lon) { if (!lat || !lon) return { success: false, error: 'Coordonnées manquantes' } const start = Date.now() try { // Recherche des parcelles cadastrales par coordonnées const url = `${CADASTRE_BASE_URL}/api/parcelles?lat=${lat}&lon=${lon}&distance=100` const res = await fetch(url, { headers: { 'User-Agent': USER_AGENT, 'Accept': 'application/json' }, timeout: REQUEST_TIMEOUT_MS, }) if (!res.ok) throw new Error(`HTTP ${res.status}`) const data = await res.json() const parcelles = (data.parcelles || []).map(parcelle => ({ section: parcelle.section || '', numero: parcelle.numero || '', commune: parcelle.commune || '', surface: parcelle.surface || null, sourceUrl: `${CADASTRE_BASE_URL}/parcelles/${parcelle.id || ''}` })) return { success: true, duration: Date.now() - start, parcelles, count: parcelles.length } } catch (e) { return { success: false, duration: Date.now() - start, error: e.message, parcelles: [] } } } async function collectAddressData(address) { // Étape 1: Géocodage BAN const geocode = await geocodeBAN(address) let risks = [] let cadastre = [] // Étape 2: Si géocodage réussi, collecter risques et cadastre if (geocode.success && geocode.lat && geocode.lon) { console.log(`[Address] Géocodage réussi: ${geocode.lat}, ${geocode.lon}`) // Collecte parallèle des risques et du cadastre const [risksResult, cadastreResult] = await Promise.all([ collectGéoRisque(geocode.lat, geocode.lon), collectCadastre(geocode.lat, geocode.lon) ]) risks = risksResult.risks || [] cadastre = cadastreResult.parcelles || [] console.log(`[Address] Risques: ${risks.length}, Parcelles: ${cadastre.length}`) } return { success: geocode.success, geocode, risks, cadastre, timestamp: new Date().toISOString(), sources: ['ban', 'georisque', 'cadastre'] } } module.exports = { collectAddressData, }