#!/usr/bin/env node // 요청 예시: https://www.everfactory.kr/api/contents/update?date=YYYYMMDD // 사용법 // 1) 오늘(가장 최신)부터 특정 일자까지 요청: // node datareq/datareq.js 20251014 // 2) 특정 최신일자부터 특정 과거일자까지 요청: // node datareq/datareq.js 20251015 20251001 // 환경변수로 호출 간 지연(ms) 조절: RATE_MS=500 node datareq/datareq.js 20251014 const BASE_URL = "http://localhost:9551/api/contents/update"; const DEFAULT_RATE_MS = Number(process.env.RATE_MS || 400); function isValidYyyyMmDd(value) { return typeof value === "string" && /^\d{8}$/.test(value); } function truncateText(text, maxLen = 256) { if (typeof text !== "string") return ""; return text.length > maxLen ? text.slice(0, maxLen) : text; } function parseYyyyMmDdToDate(yyyyMmDd) { const year = Number(yyyyMmDd.slice(0, 4)); const month = Number(yyyyMmDd.slice(4, 6)) - 1; // 0-based const day = Number(yyyyMmDd.slice(6, 8)); // Date(YYYY, M, D)는 로컬 타임존 기준. 간단성을 위해 로컬 기준 사용. return new Date(year, month, day); } function formatDateToYyyyMmDd(date) { const y = String(date.getFullYear()); const m = String(date.getMonth() + 1).padStart(2, "0"); const d = String(date.getDate()).padStart(2, "0"); return `${y}${m}${d}`; } function addDays(date, delta) { const next = new Date(date); next.setDate(next.getDate() + delta); return next; } async function sleep(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); } async function requestForDate(dateStr) { const url = `${BASE_URL}?date=${dateStr}`; try { const res = await fetch(url, { method: "GET" }); const text = await res.text().catch(() => ""); if (!res.ok) { const preview = truncateText(text, 256); console.error(`[FAIL] ${dateStr} | ${url} -> ${res.status} ${res.statusText} ${preview ? `| ${preview}` : ""}`); return { ok: false, status: res.status, body: text }; } const preview = truncateText(text, 256); console.log(`[OK] ${dateStr} | ${url} -> ${preview || res.status}`); return { ok: true, status: res.status, body: text }; } catch (err) { const errMsg = err instanceof Error ? err.message : String(err); console.error(`[ERROR] ${dateStr} | ${url} -> ${truncateText(errMsg, 256)}`); return { ok: false, error: err }; } } async function main() { const args = process.argv.slice(2); if (args.length === 0) { console.log("사용법: node datareq/datareq.js <끝일자YYYYMMDD> [시작(최신)일자YYYYMMDD]"); console.log("예시1: node datareq/datareq.js 20251014"); console.log("예시2: node datareq/datareq.js 20251015 20251001"); process.exit(1); } let newestStr; // 최신일자 (내림차순 시작점) let oldestStr; // 종료일자 (내림차순 끝점) if (args.length === 1) { const today = new Date(); newestStr = formatDateToYyyyMmDd(today); oldestStr = args[0]; } else { // args.length >= 2 인 경우: [최신일자, 종료일자] newestStr = args[0]; oldestStr = args[1]; } if (!isValidYyyyMmDd(newestStr) || !isValidYyyyMmDd(oldestStr)) { console.error("날짜 형식은 YYYYMMDD 여야 합니다."); process.exit(1); } let newestDate = parseYyyyMmDdToDate(newestStr); let oldestDate = parseYyyyMmDdToDate(oldestStr); // 최신 >= 종료 가 아니면 자동 교환 if (newestDate < oldestDate) { const tmp = newestDate; newestDate = oldestDate; oldestDate = tmp; newestStr = formatDateToYyyyMmDd(newestDate); oldestStr = formatDateToYyyyMmDd(oldestDate); } console.log(`요청 범위: 최신 ${newestStr} → 종료 ${oldestStr} (내림차순)`); console.log(`요청 간 지연: ${DEFAULT_RATE_MS}ms`); let current = newestDate; while (current >= oldestDate) { const dateStr = formatDateToYyyyMmDd(current); await requestForDate(dateStr); // 너무 빠른 연속 호출 방지 await sleep(DEFAULT_RATE_MS); current = addDays(current, -1); } console.log("모든 요청이 완료되었습니다."); } // Node 18+ 환경 가정: fetch 전역 제공. 없으면 종료 안내. if (typeof fetch !== "function") { console.error("현재 Node 런타임에 fetch가 없습니다. Node 18+를 사용하거나 폴리필을 추가하세요."); process.exit(1); } main().catch((err) => { console.error("예상치 못한 오류:", err); process.exit(1); });