@s-hirano-ist/s-scripts 1.26.7 → 4.0.0
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/README.md +2 -0
- package/dist/chunk-5OXUZW2Q.js +590 -0
- package/dist/chunk-7PVU2Z32.js +71 -0
- package/dist/chunk-AJMTRCPJ.js +15 -0
- package/dist/chunk-AZF2R2BF.js +85 -0
- package/dist/chunk-F4J6JBR4.js +115 -0
- package/dist/chunk-HDYQV2Y2.js +58 -0
- package/dist/chunk-HIK7SX34.js +85 -0
- package/dist/chunk-IWNZQXDG.js +7660 -0
- package/dist/chunk-J4VLH4VA.js +267 -0
- package/dist/chunk-JZOR5GA2.js +42 -0
- package/dist/chunk-KKZP7ZF3.js +77 -0
- package/dist/chunk-N6TZF755.js +102 -0
- package/dist/chunk-S5WJ5VXW.js +85 -0
- package/dist/chunk-UXGLXHQ6.js +40 -0
- package/dist/cleanup-minio-images.js +115 -92
- package/dist/enrich-books.js +87 -78
- package/dist/fetch-articles.js +101 -90
- package/dist/fetch-books.js +147 -128
- package/dist/fetch-images.js +88 -72
- package/dist/fetch-notes.js +66 -54
- package/dist/find-duplicate-json-articles.js +100 -97
- package/dist/fix-book-frontmatter.js +111 -99
- package/dist/fix-image-formats.js +81 -65
- package/dist/ingest-articles.js +30 -249
- package/dist/ingest-books.js +61 -318
- package/dist/ingest-images.js +33 -184
- package/dist/ingest-notes.js +41 -171
- package/dist/rag/delete-collection.js +32 -22
- package/dist/rag/ingest.js +371 -92
- package/dist/rag/search.js +80 -76
- package/dist/reset-articles.js +57 -60
- package/dist/reset-books.js +57 -59
- package/dist/reset-images.js +57 -59
- package/dist/reset-notes.js +57 -59
- package/dist/revert-articles.js +53 -55
- package/dist/revert-books.js +53 -53
- package/dist/revert-images.js +53 -53
- package/dist/revert-notes.js +53 -53
- package/dist/s-content-format.js +103 -13
- package/dist/update-json-articles.js +101 -97
- package/dist/update-raw-articles.js +130 -130
- package/dist/validate-json-articles.js +129 -130
- package/package.json +14 -51
- package/dist/cleanup-minio-images.d.ts +0 -3
- package/dist/cleanup-minio-images.d.ts.map +0 -1
- package/dist/cleanup-minio-images.js.map +0 -1
- package/dist/enrich-books.d.ts +0 -3
- package/dist/enrich-books.d.ts.map +0 -1
- package/dist/enrich-books.js.map +0 -1
- package/dist/fetch-articles.d.ts +0 -3
- package/dist/fetch-articles.d.ts.map +0 -1
- package/dist/fetch-articles.js.map +0 -1
- package/dist/fetch-books.d.ts +0 -3
- package/dist/fetch-books.d.ts.map +0 -1
- package/dist/fetch-books.js.map +0 -1
- package/dist/fetch-images.d.ts +0 -3
- package/dist/fetch-images.d.ts.map +0 -1
- package/dist/fetch-images.js.map +0 -1
- package/dist/fetch-notes.d.ts +0 -3
- package/dist/fetch-notes.d.ts.map +0 -1
- package/dist/fetch-notes.js.map +0 -1
- package/dist/find-duplicate-json-articles.d.ts +0 -3
- package/dist/find-duplicate-json-articles.d.ts.map +0 -1
- package/dist/find-duplicate-json-articles.js.map +0 -1
- package/dist/fix-book-frontmatter.d.ts +0 -3
- package/dist/fix-book-frontmatter.d.ts.map +0 -1
- package/dist/fix-book-frontmatter.js.map +0 -1
- package/dist/fix-image-formats.d.ts +0 -3
- package/dist/fix-image-formats.d.ts.map +0 -1
- package/dist/fix-image-formats.js.map +0 -1
- package/dist/infrastructures/articles-command-repository.d.ts +0 -57
- package/dist/infrastructures/articles-command-repository.d.ts.map +0 -1
- package/dist/infrastructures/articles-command-repository.js +0 -68
- package/dist/infrastructures/articles-command-repository.js.map +0 -1
- package/dist/infrastructures/books-command-repository.d.ts +0 -34
- package/dist/infrastructures/books-command-repository.d.ts.map +0 -1
- package/dist/infrastructures/books-command-repository.js +0 -53
- package/dist/infrastructures/books-command-repository.js.map +0 -1
- package/dist/infrastructures/cache-invalidation-client.d.ts +0 -9
- package/dist/infrastructures/cache-invalidation-client.d.ts.map +0 -1
- package/dist/infrastructures/cache-invalidation-client.js +0 -21
- package/dist/infrastructures/cache-invalidation-client.js.map +0 -1
- package/dist/infrastructures/cache-invalidation-client.test.d.ts +0 -2
- package/dist/infrastructures/cache-invalidation-client.test.d.ts.map +0 -1
- package/dist/infrastructures/cache-invalidation-client.test.js +0 -25
- package/dist/infrastructures/cache-invalidation-client.test.js.map +0 -1
- package/dist/infrastructures/images-command-repository.d.ts +0 -34
- package/dist/infrastructures/images-command-repository.d.ts.map +0 -1
- package/dist/infrastructures/images-command-repository.js +0 -53
- package/dist/infrastructures/images-command-repository.js.map +0 -1
- package/dist/infrastructures/notes-command-repository.d.ts +0 -34
- package/dist/infrastructures/notes-command-repository.d.ts.map +0 -1
- package/dist/infrastructures/notes-command-repository.js +0 -53
- package/dist/infrastructures/notes-command-repository.js.map +0 -1
- package/dist/ingest-articles.d.ts +0 -3
- package/dist/ingest-articles.d.ts.map +0 -1
- package/dist/ingest-articles.js.map +0 -1
- package/dist/ingest-books.d.ts +0 -3
- package/dist/ingest-books.d.ts.map +0 -1
- package/dist/ingest-books.js.map +0 -1
- package/dist/ingest-images.d.ts +0 -3
- package/dist/ingest-images.d.ts.map +0 -1
- package/dist/ingest-images.js.map +0 -1
- package/dist/ingest-notes.d.ts +0 -3
- package/dist/ingest-notes.d.ts.map +0 -1
- package/dist/ingest-notes.js.map +0 -1
- package/dist/lib/glob-paths.d.ts +0 -6
- package/dist/lib/glob-paths.d.ts.map +0 -1
- package/dist/lib/glob-paths.js +0 -9
- package/dist/lib/glob-paths.js.map +0 -1
- package/dist/lib/glob-paths.test.d.ts +0 -2
- package/dist/lib/glob-paths.test.d.ts.map +0 -1
- package/dist/lib/glob-paths.test.js +0 -30
- package/dist/lib/glob-paths.test.js.map +0 -1
- package/dist/lib/html-charset.d.ts +0 -4
- package/dist/lib/html-charset.d.ts.map +0 -1
- package/dist/lib/html-charset.js +0 -33
- package/dist/lib/html-charset.js.map +0 -1
- package/dist/lib/html-charset.test.d.ts +0 -2
- package/dist/lib/html-charset.test.d.ts.map +0 -1
- package/dist/lib/html-charset.test.js +0 -27
- package/dist/lib/html-charset.test.js.map +0 -1
- package/dist/rag/delete-collection.d.ts +0 -3
- package/dist/rag/delete-collection.d.ts.map +0 -1
- package/dist/rag/delete-collection.js.map +0 -1
- package/dist/rag/ingest-config.d.ts +0 -8
- package/dist/rag/ingest-config.d.ts.map +0 -1
- package/dist/rag/ingest-config.js +0 -8
- package/dist/rag/ingest-config.js.map +0 -1
- package/dist/rag/ingest.d.ts +0 -3
- package/dist/rag/ingest.d.ts.map +0 -1
- package/dist/rag/ingest.js.map +0 -1
- package/dist/rag/search.d.ts +0 -3
- package/dist/rag/search.d.ts.map +0 -1
- package/dist/rag/search.js.map +0 -1
- package/dist/reset-articles.d.ts +0 -3
- package/dist/reset-articles.d.ts.map +0 -1
- package/dist/reset-articles.js.map +0 -1
- package/dist/reset-books.d.ts +0 -3
- package/dist/reset-books.d.ts.map +0 -1
- package/dist/reset-books.js.map +0 -1
- package/dist/reset-images.d.ts +0 -3
- package/dist/reset-images.d.ts.map +0 -1
- package/dist/reset-images.js.map +0 -1
- package/dist/reset-notes.d.ts +0 -3
- package/dist/reset-notes.d.ts.map +0 -1
- package/dist/reset-notes.js.map +0 -1
- package/dist/revert-articles.d.ts +0 -3
- package/dist/revert-articles.d.ts.map +0 -1
- package/dist/revert-articles.js.map +0 -1
- package/dist/revert-books.d.ts +0 -3
- package/dist/revert-books.d.ts.map +0 -1
- package/dist/revert-books.js.map +0 -1
- package/dist/revert-images.d.ts +0 -3
- package/dist/revert-images.d.ts.map +0 -1
- package/dist/revert-images.js.map +0 -1
- package/dist/revert-notes.d.ts +0 -3
- package/dist/revert-notes.d.ts.map +0 -1
- package/dist/revert-notes.js.map +0 -1
- package/dist/s-content-format-runner.d.ts +0 -10
- package/dist/s-content-format-runner.d.ts.map +0 -1
- package/dist/s-content-format-runner.js +0 -76
- package/dist/s-content-format-runner.js.map +0 -1
- package/dist/s-content-format.d.ts +0 -3
- package/dist/s-content-format.d.ts.map +0 -1
- package/dist/s-content-format.js.map +0 -1
- package/dist/s-content-format.test.d.ts +0 -2
- package/dist/s-content-format.test.d.ts.map +0 -1
- package/dist/s-content-format.test.js +0 -99
- package/dist/s-content-format.test.js.map +0 -1
- package/dist/update-json-articles.d.ts +0 -3
- package/dist/update-json-articles.d.ts.map +0 -1
- package/dist/update-json-articles.js.map +0 -1
- package/dist/update-raw-articles.d.ts +0 -3
- package/dist/update-raw-articles.d.ts.map +0 -1
- package/dist/update-raw-articles.js.map +0 -1
- package/dist/validate-json-articles.d.ts +0 -3
- package/dist/validate-json-articles.d.ts.map +0 -1
- package/dist/validate-json-articles.js.map +0 -1
|
@@ -1,114 +1,118 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
2
|
+
import { createRequire as __cliCreateRequire } from "node:module"; const require = __cliCreateRequire(import.meta.url);
|
|
3
|
+
import {
|
|
4
|
+
decodeHtml
|
|
5
|
+
} from "./chunk-UXGLXHQ6.js";
|
|
6
|
+
import {
|
|
7
|
+
createPushoverService
|
|
8
|
+
} from "./chunk-7PVU2Z32.js";
|
|
9
|
+
import "./chunk-JZOR5GA2.js";
|
|
10
|
+
|
|
11
|
+
// src/update-json-articles.ts
|
|
3
12
|
import * as cheerio from "cheerio";
|
|
4
13
|
import { readdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
5
14
|
import { join } from "node:path";
|
|
6
15
|
import { setTimeout } from "node:timers/promises";
|
|
7
|
-
import { decodeHtml } from "./lib/html-charset.js";
|
|
8
16
|
async function getOgTags(url) {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
19
|
-
const buffer = Buffer.from(await response.arrayBuffer());
|
|
20
|
-
const html = decodeHtml(response.headers, buffer);
|
|
21
|
-
const $ = cheerio.load(html);
|
|
22
|
-
const ogTags = {};
|
|
23
|
-
$("meta[property]").each((_, el) => {
|
|
24
|
-
const property = $(el).attr("property")?.trim();
|
|
25
|
-
const content = $(el).attr("content");
|
|
26
|
-
if (property && content) {
|
|
27
|
-
ogTags[property] = content;
|
|
28
|
-
}
|
|
29
|
-
});
|
|
30
|
-
const ogImageUrl = ogTags["og:image"];
|
|
31
|
-
const ogTitle = ogTags["og:title"];
|
|
32
|
-
const ogDescription = ogTags["og:description"];
|
|
33
|
-
return { ogImageUrl, ogTitle, ogDescription };
|
|
34
|
-
}
|
|
35
|
-
catch (error) {
|
|
36
|
-
console.error(`Error fetching OG tags for ${url}:`, error);
|
|
37
|
-
return {};
|
|
17
|
+
try {
|
|
18
|
+
console.log(`Fetching OG tags for: ${url}`);
|
|
19
|
+
const response = await fetch(url, {
|
|
20
|
+
headers: {
|
|
21
|
+
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
if (!response.ok) {
|
|
25
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
38
26
|
}
|
|
27
|
+
const buffer = Buffer.from(await response.arrayBuffer());
|
|
28
|
+
const html = decodeHtml(response.headers, buffer);
|
|
29
|
+
const $ = cheerio.load(html);
|
|
30
|
+
const ogTags = {};
|
|
31
|
+
$("meta[property]").each((_, el) => {
|
|
32
|
+
const property = $(el).attr("property")?.trim();
|
|
33
|
+
const content = $(el).attr("content");
|
|
34
|
+
if (property && content) {
|
|
35
|
+
ogTags[property] = content;
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
const ogImageUrl = ogTags["og:image"];
|
|
39
|
+
const ogTitle = ogTags["og:title"];
|
|
40
|
+
const ogDescription = ogTags["og:description"];
|
|
41
|
+
return { ogImageUrl, ogTitle, ogDescription };
|
|
42
|
+
} catch (error) {
|
|
43
|
+
console.error(`Error fetching OG tags for ${url}:`, error);
|
|
44
|
+
return {};
|
|
45
|
+
}
|
|
39
46
|
}
|
|
40
47
|
async function processArticleFile(filePath) {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
item.ogTitle = ogTags.ogTitle;
|
|
58
|
-
else
|
|
59
|
-
console.warn(`No OG title found for ${item.url}`);
|
|
60
|
-
if (ogTags.ogDescription)
|
|
61
|
-
item.ogDescription = ogTags.ogDescription;
|
|
62
|
-
else
|
|
63
|
-
console.warn(`No OG description found for ${item.url}`);
|
|
64
|
-
// Add a small delay to avoid overwhelming servers
|
|
65
|
-
await setTimeout(1000);
|
|
66
|
-
}
|
|
67
|
-
// Write back to file
|
|
68
|
-
writeFileSync(filePath, `${JSON.stringify(articleData, null, "\t")}\n`, "utf-8");
|
|
69
|
-
console.log(`Completed processing ${filePath}`);
|
|
70
|
-
}
|
|
71
|
-
catch (error) {
|
|
72
|
-
console.error(`Error processing ${filePath}:`, error);
|
|
48
|
+
try {
|
|
49
|
+
const jsonContent = readFileSync(filePath, "utf-8");
|
|
50
|
+
const articleData = JSON.parse(jsonContent);
|
|
51
|
+
console.log(`Processing ${filePath}...`);
|
|
52
|
+
for (const item of articleData.body) {
|
|
53
|
+
if (item.ogImageUrl || item.ogTitle || item.ogDescription || item.skip) {
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
const ogTags = await getOgTags(item.url);
|
|
57
|
+
if (ogTags.ogImageUrl) item.ogImageUrl = ogTags.ogImageUrl;
|
|
58
|
+
else console.warn(`No OG image found for ${item.url}`);
|
|
59
|
+
if (ogTags.ogTitle) item.ogTitle = ogTags.ogTitle;
|
|
60
|
+
else console.warn(`No OG title found for ${item.url}`);
|
|
61
|
+
if (ogTags.ogDescription) item.ogDescription = ogTags.ogDescription;
|
|
62
|
+
else console.warn(`No OG description found for ${item.url}`);
|
|
63
|
+
await setTimeout(1e3);
|
|
73
64
|
}
|
|
65
|
+
writeFileSync(
|
|
66
|
+
filePath,
|
|
67
|
+
`${JSON.stringify(articleData, null, " ")}
|
|
68
|
+
`,
|
|
69
|
+
"utf-8"
|
|
70
|
+
);
|
|
71
|
+
console.log(`Completed processing ${filePath}`);
|
|
72
|
+
} catch (error) {
|
|
73
|
+
console.error(`Error processing ${filePath}:`, error);
|
|
74
|
+
}
|
|
74
75
|
}
|
|
75
76
|
async function main() {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
77
|
+
const env = {
|
|
78
|
+
PUSHOVER_URL: process.env.PUSHOVER_URL,
|
|
79
|
+
PUSHOVER_USER_KEY: process.env.PUSHOVER_USER_KEY,
|
|
80
|
+
PUSHOVER_APP_TOKEN: process.env.PUSHOVER_APP_TOKEN
|
|
81
|
+
};
|
|
82
|
+
if (Object.values(env).some((v) => !v)) {
|
|
83
|
+
throw new Error("Required environment variables are not set.");
|
|
84
|
+
}
|
|
85
|
+
const notificationService = createPushoverService({
|
|
86
|
+
url: env.PUSHOVER_URL ?? "",
|
|
87
|
+
userKey: env.PUSHOVER_USER_KEY ?? "",
|
|
88
|
+
appToken: env.PUSHOVER_APP_TOKEN ?? ""
|
|
89
|
+
});
|
|
90
|
+
const articleDir = join(process.cwd(), "json", "article");
|
|
91
|
+
try {
|
|
92
|
+
const files = readdirSync(articleDir).filter(
|
|
93
|
+
(file) => file.endsWith(".json")
|
|
94
|
+
);
|
|
95
|
+
console.log(`Found ${files.length} JSON files to process`);
|
|
96
|
+
for (const file of files) {
|
|
97
|
+
const filePath = join(articleDir, file);
|
|
98
|
+
await processArticleFile(filePath);
|
|
83
99
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
appToken: env.PUSHOVER_APP_TOKEN ?? "",
|
|
100
|
+
console.log("All files processed successfully!");
|
|
101
|
+
await notificationService.notifyInfo("update-json-articles completed", {
|
|
102
|
+
caller: "update-json-articles"
|
|
88
103
|
});
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
caller: "update-json-articles",
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
catch (error) {
|
|
103
|
-
console.error("Error in main process:", error);
|
|
104
|
-
await notificationService.notifyError(`update-json-articles failed: ${String(error)}`, {
|
|
105
|
-
caller: "update-json-articles",
|
|
106
|
-
});
|
|
107
|
-
process.exit(1);
|
|
108
|
-
}
|
|
104
|
+
} catch (error) {
|
|
105
|
+
console.error("Error in main process:", error);
|
|
106
|
+
await notificationService.notifyError(
|
|
107
|
+
`update-json-articles failed: ${String(error)}`,
|
|
108
|
+
{
|
|
109
|
+
caller: "update-json-articles"
|
|
110
|
+
}
|
|
111
|
+
);
|
|
112
|
+
process.exit(1);
|
|
113
|
+
}
|
|
109
114
|
}
|
|
110
115
|
main().catch((error) => {
|
|
111
|
-
|
|
112
|
-
|
|
116
|
+
console.error(error);
|
|
117
|
+
process.exit(1);
|
|
113
118
|
});
|
|
114
|
-
//# sourceMappingURL=update-json-articles.js.map
|
|
@@ -1,102 +1,104 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
2
|
+
import { createRequire as __cliCreateRequire } from "node:module"; const require = __cliCreateRequire(import.meta.url);
|
|
3
|
+
import {
|
|
4
|
+
decodeHtml
|
|
5
|
+
} from "./chunk-UXGLXHQ6.js";
|
|
6
|
+
import {
|
|
7
|
+
createPushoverService
|
|
8
|
+
} from "./chunk-7PVU2Z32.js";
|
|
9
|
+
import "./chunk-JZOR5GA2.js";
|
|
10
|
+
|
|
11
|
+
// src/update-raw-articles.ts
|
|
3
12
|
import { existsSync } from "node:fs";
|
|
4
13
|
import { mkdir, readdir, readFile, writeFile } from "node:fs/promises";
|
|
5
14
|
import path from "node:path";
|
|
6
15
|
import TurndownService from "turndown";
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const OUTPUT_DIR = "raw/article";
|
|
16
|
+
var JSON_DIR = "json/article";
|
|
17
|
+
var OUTPUT_DIR = "raw/article";
|
|
10
18
|
async function fetchWebsiteMarkdown(url) {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}
|
|
20
|
-
const buffer = Buffer.from(await response.arrayBuffer());
|
|
21
|
-
const html = decodeHtml(response.headers, buffer);
|
|
22
|
-
const turndownService = new TurndownService({
|
|
23
|
-
headingStyle: "atx",
|
|
24
|
-
codeBlockStyle: "fenced",
|
|
25
|
-
bulletListMarker: "-",
|
|
26
|
-
strongDelimiter: "**",
|
|
27
|
-
emDelimiter: "_",
|
|
28
|
-
});
|
|
29
|
-
turndownService.remove(["script", "style", "nav", "footer", "aside"]);
|
|
30
|
-
turndownService.addRule("preserveLinks", {
|
|
31
|
-
filter: ["a"],
|
|
32
|
-
replacement: (content, node) => {
|
|
33
|
-
const element = node;
|
|
34
|
-
const href = element.getAttribute("href");
|
|
35
|
-
if (!href)
|
|
36
|
-
return content;
|
|
37
|
-
if (href.startsWith("http") || href.startsWith("https")) {
|
|
38
|
-
return `[${content}](${href})`;
|
|
39
|
-
}
|
|
40
|
-
try {
|
|
41
|
-
const absoluteUrl = new URL(href, url).href;
|
|
42
|
-
return `[${content}](${absoluteUrl})`;
|
|
43
|
-
}
|
|
44
|
-
catch {
|
|
45
|
-
return content;
|
|
46
|
-
}
|
|
47
|
-
},
|
|
48
|
-
});
|
|
49
|
-
turndownService.addRule("preserveImages", {
|
|
50
|
-
filter: ["img"],
|
|
51
|
-
replacement: (_content, node) => {
|
|
52
|
-
const element = node;
|
|
53
|
-
const src = element.getAttribute("src");
|
|
54
|
-
const alt = element.getAttribute("alt") || "";
|
|
55
|
-
if (!src)
|
|
56
|
-
return "";
|
|
57
|
-
if (src.startsWith("http") || src.startsWith("https")) {
|
|
58
|
-
return ``;
|
|
59
|
-
}
|
|
60
|
-
try {
|
|
61
|
-
const absoluteUrl = new URL(src, url).href;
|
|
62
|
-
return ``;
|
|
63
|
-
}
|
|
64
|
-
catch {
|
|
65
|
-
return "";
|
|
66
|
-
}
|
|
67
|
-
},
|
|
68
|
-
});
|
|
69
|
-
const markdown = turndownService.turndown(html);
|
|
70
|
-
return markdown.trim();
|
|
71
|
-
}
|
|
72
|
-
catch (error) {
|
|
73
|
-
console.error(`Failed to fetch ${url}:`, error);
|
|
74
|
-
return "";
|
|
19
|
+
try {
|
|
20
|
+
const response = await fetch(url, {
|
|
21
|
+
headers: {
|
|
22
|
+
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
if (!response.ok) {
|
|
26
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
75
27
|
}
|
|
28
|
+
const buffer = Buffer.from(await response.arrayBuffer());
|
|
29
|
+
const html = decodeHtml(response.headers, buffer);
|
|
30
|
+
const turndownService = new TurndownService({
|
|
31
|
+
headingStyle: "atx",
|
|
32
|
+
codeBlockStyle: "fenced",
|
|
33
|
+
bulletListMarker: "-",
|
|
34
|
+
strongDelimiter: "**",
|
|
35
|
+
emDelimiter: "_"
|
|
36
|
+
});
|
|
37
|
+
turndownService.remove(["script", "style", "nav", "footer", "aside"]);
|
|
38
|
+
turndownService.addRule("preserveLinks", {
|
|
39
|
+
filter: ["a"],
|
|
40
|
+
replacement: (content, node) => {
|
|
41
|
+
const element = node;
|
|
42
|
+
const href = element.getAttribute("href");
|
|
43
|
+
if (!href) return content;
|
|
44
|
+
if (href.startsWith("http") || href.startsWith("https")) {
|
|
45
|
+
return `[${content}](${href})`;
|
|
46
|
+
}
|
|
47
|
+
try {
|
|
48
|
+
const absoluteUrl = new URL(href, url).href;
|
|
49
|
+
return `[${content}](${absoluteUrl})`;
|
|
50
|
+
} catch {
|
|
51
|
+
return content;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
turndownService.addRule("preserveImages", {
|
|
56
|
+
filter: ["img"],
|
|
57
|
+
replacement: (_content, node) => {
|
|
58
|
+
const element = node;
|
|
59
|
+
const src = element.getAttribute("src");
|
|
60
|
+
const alt = element.getAttribute("alt") || "";
|
|
61
|
+
if (!src) return "";
|
|
62
|
+
if (src.startsWith("http") || src.startsWith("https")) {
|
|
63
|
+
return ``;
|
|
64
|
+
}
|
|
65
|
+
try {
|
|
66
|
+
const absoluteUrl = new URL(src, url).href;
|
|
67
|
+
return ``;
|
|
68
|
+
} catch {
|
|
69
|
+
return "";
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
const markdown = turndownService.turndown(html);
|
|
74
|
+
return markdown.trim();
|
|
75
|
+
} catch (error) {
|
|
76
|
+
console.error(`Failed to fetch ${url}:`, error);
|
|
77
|
+
return "";
|
|
78
|
+
}
|
|
76
79
|
}
|
|
77
80
|
async function jsonToMarkdown(jsonFile) {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
const markdownContent = `# [${title}](${url})
|
|
81
|
+
const rawData = await readFile(jsonFile, "utf-8");
|
|
82
|
+
const data = JSON.parse(rawData);
|
|
83
|
+
const bodyList = data.body || [];
|
|
84
|
+
if (!existsSync(OUTPUT_DIR)) {
|
|
85
|
+
await mkdir(OUTPUT_DIR, { recursive: true });
|
|
86
|
+
}
|
|
87
|
+
for (const item of bodyList) {
|
|
88
|
+
const { title, quote, url, skip } = item;
|
|
89
|
+
try {
|
|
90
|
+
const strippedUrl = url.replace(/^https?:\/\//u, "");
|
|
91
|
+
const safeUrl = encodeURIComponent(strippedUrl);
|
|
92
|
+
const outputFilename = `${safeUrl}.md`;
|
|
93
|
+
const outputPath = path.join(OUTPUT_DIR, outputFilename);
|
|
94
|
+
if (existsSync(outputPath) || skip) {
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
const websiteText = await fetchWebsiteMarkdown(url);
|
|
98
|
+
if (!websiteText) {
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
const markdownContent = `# [${title}](${url})
|
|
100
102
|
|
|
101
103
|
---
|
|
102
104
|
|
|
@@ -108,51 +110,49 @@ ${quote}
|
|
|
108
110
|
|
|
109
111
|
${websiteText}
|
|
110
112
|
`;
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
console.error("Error on file:", url);
|
|
116
|
-
}
|
|
113
|
+
await writeFile(outputPath, markdownContent, "utf-8");
|
|
114
|
+
console.log(`Exported: ${outputPath}`);
|
|
115
|
+
} catch {
|
|
116
|
+
console.error("Error on file:", url);
|
|
117
117
|
}
|
|
118
|
+
}
|
|
118
119
|
}
|
|
119
120
|
async function main() {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
121
|
+
const env = {
|
|
122
|
+
PUSHOVER_URL: process.env.PUSHOVER_URL,
|
|
123
|
+
PUSHOVER_USER_KEY: process.env.PUSHOVER_USER_KEY,
|
|
124
|
+
PUSHOVER_APP_TOKEN: process.env.PUSHOVER_APP_TOKEN
|
|
125
|
+
};
|
|
126
|
+
if (Object.values(env).some((v) => !v)) {
|
|
127
|
+
throw new Error("Required environment variables are not set.");
|
|
128
|
+
}
|
|
129
|
+
const notificationService = createPushoverService({
|
|
130
|
+
url: env.PUSHOVER_URL ?? "",
|
|
131
|
+
userKey: env.PUSHOVER_USER_KEY ?? "",
|
|
132
|
+
appToken: env.PUSHOVER_APP_TOKEN ?? ""
|
|
133
|
+
});
|
|
134
|
+
try {
|
|
135
|
+
const jsonFiles = await readdir(JSON_DIR);
|
|
136
|
+
const jsonFilePaths = jsonFiles.filter((file) => file.endsWith(".json")).map((file) => path.join(JSON_DIR, file));
|
|
137
|
+
for (const jsonFile of jsonFilePaths) {
|
|
138
|
+
console.log(`Processing: ${jsonFile}`);
|
|
139
|
+
await jsonToMarkdown(jsonFile);
|
|
127
140
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
userKey: env.PUSHOVER_USER_KEY ?? "",
|
|
131
|
-
appToken: env.PUSHOVER_APP_TOKEN ?? "",
|
|
141
|
+
await notificationService.notifyInfo("update-raw-articles completed", {
|
|
142
|
+
caller: "update-raw-articles"
|
|
132
143
|
});
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
caller: "update-raw-articles",
|
|
144
|
-
});
|
|
145
|
-
}
|
|
146
|
-
catch (error) {
|
|
147
|
-
console.error("Error in main process:", error);
|
|
148
|
-
await notificationService.notifyError(`update-raw-articles failed: ${String(error)}`, {
|
|
149
|
-
caller: "update-raw-articles",
|
|
150
|
-
});
|
|
151
|
-
process.exit(1);
|
|
152
|
-
}
|
|
144
|
+
} catch (error) {
|
|
145
|
+
console.error("Error in main process:", error);
|
|
146
|
+
await notificationService.notifyError(
|
|
147
|
+
`update-raw-articles failed: ${String(error)}`,
|
|
148
|
+
{
|
|
149
|
+
caller: "update-raw-articles"
|
|
150
|
+
}
|
|
151
|
+
);
|
|
152
|
+
process.exit(1);
|
|
153
|
+
}
|
|
153
154
|
}
|
|
154
155
|
main().catch((error) => {
|
|
155
|
-
|
|
156
|
-
|
|
156
|
+
console.error(error);
|
|
157
|
+
process.exit(1);
|
|
157
158
|
});
|
|
158
|
-
//# sourceMappingURL=update-raw-articles.js.map
|