@heripo/research-radar 5.2.1 → 5.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +46 -10
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2250,6 +2250,23 @@ const extractNttId = (html) => {
|
|
|
2250
2250
|
}
|
|
2251
2251
|
return '';
|
|
2252
2252
|
};
|
|
2253
|
+
/**
|
|
2254
|
+
* Reads a JSON body without trusting that it is JSON.
|
|
2255
|
+
*
|
|
2256
|
+
* These parsers fetch their own API through the crawling fetch, which does not
|
|
2257
|
+
* always carry the API's answer: a request the origin's robots.txt disallows is
|
|
2258
|
+
* answered locally with an empty document, and `response.json()` throws on it.
|
|
2259
|
+
* A refusal should leave the target with nothing to report, not raise a parse
|
|
2260
|
+
* error that reads like a broken parser.
|
|
2261
|
+
*/
|
|
2262
|
+
async function readJson(response) {
|
|
2263
|
+
try {
|
|
2264
|
+
return (await response.json());
|
|
2265
|
+
}
|
|
2266
|
+
catch {
|
|
2267
|
+
return null;
|
|
2268
|
+
}
|
|
2269
|
+
}
|
|
2253
2270
|
/**
|
|
2254
2271
|
* Parses the list page from seamuse.go.kr (국립해양유산연구소).
|
|
2255
2272
|
* The site uses client-side rendering — list data is fetched from a JSON API.
|
|
@@ -2267,9 +2284,9 @@ const parseSeamuseList = async (_html, listDataPath, infoPathPrefix, customFetch
|
|
|
2267
2284
|
},
|
|
2268
2285
|
body,
|
|
2269
2286
|
});
|
|
2270
|
-
const data = await response
|
|
2287
|
+
const data = await readJson(response);
|
|
2271
2288
|
const posts = [];
|
|
2272
|
-
for (const item of data
|
|
2289
|
+
for (const item of data?.resultList ?? []) {
|
|
2273
2290
|
posts.push({
|
|
2274
2291
|
uniqId: String(item.nttId),
|
|
2275
2292
|
title: item.nttSj?.trim() ?? '',
|
|
@@ -2302,11 +2319,11 @@ const parseSeamuseDetail = async (html, infoDataPath, customFetch) => {
|
|
|
2302
2319
|
'Content-Type': 'application/json',
|
|
2303
2320
|
},
|
|
2304
2321
|
});
|
|
2305
|
-
const data = await response
|
|
2306
|
-
const content = data
|
|
2322
|
+
const data = await readJson(response);
|
|
2323
|
+
const content = data?.result?.nttCn ?? '';
|
|
2307
2324
|
return {
|
|
2308
2325
|
detailContent: new TurndownService().turndown(content),
|
|
2309
|
-
hasAttachedFile: (data
|
|
2326
|
+
hasAttachedFile: (data?.files?.length ?? 0) > 0,
|
|
2310
2327
|
hasAttachedImage: content.includes('<img'),
|
|
2311
2328
|
};
|
|
2312
2329
|
};
|
|
@@ -4440,9 +4457,10 @@ class ContentGenerateProvider {
|
|
|
4440
4457
|
*
|
|
4441
4458
|
* Applied at the fetch layer, the same seam the KRAS and excavation-report
|
|
4442
4459
|
* adapters use, so core's crawling pipeline is untouched: a disallowed request
|
|
4443
|
-
* is answered with
|
|
4444
|
-
*
|
|
4445
|
-
*
|
|
4460
|
+
* is answered locally with an empty document instead of being sent, and the
|
|
4461
|
+
* target simply yields no articles. The refusal is reported through
|
|
4462
|
+
* `onBlocked`, not as a fetch failure — see {@link createRobotsGate} for why
|
|
4463
|
+
* that distinction matters.
|
|
4446
4464
|
*/
|
|
4447
4465
|
/**
|
|
4448
4466
|
* Parses robots.txt into user-agent groups.
|
|
@@ -4648,13 +4666,31 @@ function createRobotsGate(baseFetch = fetch, options = {}) {
|
|
|
4648
4666
|
return baseFetch(input, init);
|
|
4649
4667
|
}
|
|
4650
4668
|
onBlocked?.({ url: requestUrl, userAgent, rule: verdict.rule });
|
|
4651
|
-
|
|
4669
|
+
// An empty document rather than a 4xx. A site's crawling policy is not a
|
|
4670
|
+
// fault on our side, but core cannot tell the difference: it turns any
|
|
4671
|
+
// non-2xx list response into a thrown error and logs
|
|
4672
|
+
// `crawl.list.fetch.failed` at error level, which applications forward to
|
|
4673
|
+
// their alerting. Fourteen targets are disallowed at all times, so every
|
|
4674
|
+
// run raised fourteen alerts that no one could act on, and real fetch
|
|
4675
|
+
// failures were buried among them.
|
|
4676
|
+
//
|
|
4677
|
+
// Answering 200 with no content makes the target yield nothing, which is
|
|
4678
|
+
// what being disallowed means. The refusal is not hidden: it is still
|
|
4679
|
+
// reported through `onBlocked`, which the provider logs as
|
|
4680
|
+
// `crawl.robots.blocked`, and the health-check decides what to skip from
|
|
4681
|
+
// `isAllowed` rather than from this status. Every parser in this package
|
|
4682
|
+
// returns an empty list for this body.
|
|
4683
|
+
return new Response(`<!-- Blocked by robots.txt (${verdict.rule}) - ${new URL(requestUrl).origin}/robots.txt -->`, {
|
|
4684
|
+
status: 200,
|
|
4685
|
+
statusText: 'Blocked by robots.txt',
|
|
4686
|
+
headers: { 'content-type': 'text/html; charset=utf-8' },
|
|
4687
|
+
});
|
|
4652
4688
|
};
|
|
4653
4689
|
return { isAllowed, fetch: gatedFetch };
|
|
4654
4690
|
}
|
|
4655
4691
|
/**
|
|
4656
4692
|
* Wraps a fetch so that requests disallowed by the origin's robots.txt are
|
|
4657
|
-
*
|
|
4693
|
+
* answered with an empty document instead of sent. See {@link createRobotsGate}.
|
|
4658
4694
|
*/
|
|
4659
4695
|
function createRobotsAwareFetch(baseFetch = fetch, options = {}) {
|
|
4660
4696
|
return createRobotsGate(baseFetch, options).fetch;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@heripo/research-radar",
|
|
3
3
|
"private": false,
|
|
4
4
|
"type": "module",
|
|
5
|
-
"version": "5.2.
|
|
5
|
+
"version": "5.2.2",
|
|
6
6
|
"description": "AI-driven intelligence for Korean cultural heritage. This package serves as both a ready-to-use newsletter service and a practical implementation example for the LLM-Newsletter-Kit.",
|
|
7
7
|
"main": "dist/index.js",
|
|
8
8
|
"types": "dist/index.d.ts",
|