/** * SiPongi+ Scraper & Realtime Karhutla Monitor * Base: https://sipongi.gakkum.kehutanan.go.id / https://opsroom.sipongidata.my.id * Data: Titik Panas (Hotspot), Sebaran Karhutla, Indikasi Luas Kebakaran, Daops Pemadaman, Berita Terkini */ import fetch from 'node-fetch' const OPS_API = 'https://opsroom.sipongidata.my.id/api' const USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36' const defaultHeaders = { 'User-Agent': USER_AGENT, 'Accept': 'application/json, text/plain, */*', 'Referer': 'https://sipongi.gakkum.kehutanan.go.id/' } /** * Mengambil ringkasan statistik kebakaran nasional */ export async function getSummaryKebakaran() { try { const res = await fetch(`${OPS_API}/getSummaryKebakaran`, { headers: defaultHeaders }) if (!res.ok) throw new Error(`HTTP Error ${res.status}`) return await res.json() } catch (e) { console.error('[SiPongi getSummaryKebakaran Error]:', e.message) return null } } /** * Mengambil data titik panas (Hotspot) realtime dari satelit NASA-MODIS, SNPP, & NOAA20 * @param {Object} options * @param {number} options.late Jam terakhir (default: 24 jam) * @param {Array} options.satelit Satelit pemantau * @param {Array} options.confidence Tingkat kepercayaan ('low', 'medium', 'high') */ export async function getRealtimeHotspots({ late = 24, satelit = ['NASA-MODIS', 'NASA-SNPP', 'NASA-NOAA20'], confidence = ['low', 'medium', 'high'] } = {}) { try { const params = new URLSearchParams({ wilayah: 'IN', filterperiode: 'false', late: String(late) }) satelit.forEach(s => params.append('satelit[]', s)) confidence.forEach(c => params.append('confidence[]', c)) const res = await fetch(`${OPS_API}/opsroom/indoHotspot?${params.toString()}`, { headers: defaultHeaders }) if (!res.ok) throw new Error(`HTTP Error ${res.status}`) const geojson = await res.json() const features = geojson.features || [] const provinceCounts = {} const confidenceCounts = { low: 0, medium: 0, high: 0 } const satelliteCounts = {} features.forEach(f => { const p = f.properties || {} const prov = p.nama_provinsi || p.provinsi || 'Lainnya' const conf = (p.confidence_level || 'low').toLowerCase() const sat = p.sumber || 'Unknown' provinceCounts[prov] = (provinceCounts[prov] || 0) + 1 confidenceCounts[conf] = (confidenceCounts[conf] || 0) + 1 satelliteCounts[sat] = (satelliteCounts[sat] || 0) + 1 }) // Sort provinsi berdasarkan titik panas terbanyak const topProvinces = Object.entries(provinceCounts) .sort((a, b) => b[1] - a[1]) .map(([provinsi, count]) => ({ provinsi, count })) return { total_hotspots: features.length, periode_jam: late, satellite_counts: satelliteCounts, confidence_counts: confidenceCounts, top_provinces: topProvinces, features } } catch (e) { console.error('[SiPongi getRealtimeHotspots Error]:', e.message) return null } } /** * Mengambil operasi pemadaman terkini oleh Manggala Agni / Daops */ export async function getDaopsPemadaman() { try { const res = await fetch(`${OPS_API}/daops/pemadaman`, { headers: defaultHeaders }) if (!res.ok) throw new Error(`HTTP Error ${res.status}`) const json = await res.json() const features = json?.data?.features || [] return { total_operasi: features.length, operations: features.map(f => ({ id: f.properties?.id, daops: f.properties?.nama_daops || f.properties?.daops, provinsi: f.properties?.nama_provinsi || f.properties?.provinsi, status: f.properties?.status, tanggal: f.properties?.tanggal, luas_terbakar: f.properties?.luas_terbakar, lokasi: f.properties?.lokasi, koordinat: f.geometry?.coordinates })) } } catch (e) { console.error('[SiPongi getDaopsPemadaman Error]:', e.message) return null } } /** * Mengambil daftar berita terkini Karhutla KLHK / Kemenhut */ export async function getBeritaKarhutla(page = 1, perPage = 6) { try { const res = await fetch(`${OPS_API}/listBerita?direction=desc&sortBy=created_at&page=${page}&per_page=${perPage}`, { headers: defaultHeaders }) if (!res.ok) throw new Error(`HTTP Error ${res.status}`) const json = await res.json() const items = json.data || [] return items.map(item => ({ id: item.id, title: item.title, slug: item.slug, date: item.created_at ? item.created_at.split('T')[0] : '', image: item.image ? (item.image.startsWith('http') ? item.image : `https://opsroom.sipongidata.my.id/storage/${item.image}`) : null, content: item.content ? item.content.replace(/<[^>]+>/g, '').trim() : '' })) } catch (e) { console.error('[SiPongi getBeritaKarhutla Error]:', e.message) return [] } } export default { getSummaryKebakaran, getRealtimeHotspots, getDaopsPemadaman, getBeritaKarhutla }