Files
ef_front/datareq/datareq.js

135 lines
4.4 KiB
JavaScript
Raw Normal View History

2025-10-15 10:31:03 +00:00
#!/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);
});