@s-hirano-ist/s-scripts 0.2.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.
Files changed (62) hide show
  1. package/LICENSE +661 -0
  2. package/dist/fetch-articles.d.ts +3 -0
  3. package/dist/fetch-articles.d.ts.map +1 -0
  4. package/dist/fetch-articles.js +101 -0
  5. package/dist/fetch-articles.js.map +1 -0
  6. package/dist/fetch-books.d.ts +3 -0
  7. package/dist/fetch-books.d.ts.map +1 -0
  8. package/dist/fetch-books.js +67 -0
  9. package/dist/fetch-books.js.map +1 -0
  10. package/dist/fetch-images.d.ts +3 -0
  11. package/dist/fetch-images.d.ts.map +1 -0
  12. package/dist/fetch-images.js +83 -0
  13. package/dist/fetch-images.js.map +1 -0
  14. package/dist/fetch-notes.d.ts +3 -0
  15. package/dist/fetch-notes.d.ts.map +1 -0
  16. package/dist/fetch-notes.js +68 -0
  17. package/dist/fetch-notes.js.map +1 -0
  18. package/dist/find-duplicate-json-articles.d.ts +3 -0
  19. package/dist/find-duplicate-json-articles.d.ts.map +1 -0
  20. package/dist/find-duplicate-json-articles.js +137 -0
  21. package/dist/find-duplicate-json-articles.js.map +1 -0
  22. package/dist/reset-articles.d.ts +3 -0
  23. package/dist/reset-articles.d.ts.map +1 -0
  24. package/dist/reset-articles.js +67 -0
  25. package/dist/reset-articles.js.map +1 -0
  26. package/dist/reset-books.d.ts +3 -0
  27. package/dist/reset-books.d.ts.map +1 -0
  28. package/dist/reset-books.js +67 -0
  29. package/dist/reset-books.js.map +1 -0
  30. package/dist/reset-images.d.ts +3 -0
  31. package/dist/reset-images.d.ts.map +1 -0
  32. package/dist/reset-images.js +67 -0
  33. package/dist/reset-images.js.map +1 -0
  34. package/dist/reset-notes.d.ts +3 -0
  35. package/dist/reset-notes.d.ts.map +1 -0
  36. package/dist/reset-notes.js +67 -0
  37. package/dist/reset-notes.js.map +1 -0
  38. package/dist/revert-articles.d.ts +3 -0
  39. package/dist/revert-articles.d.ts.map +1 -0
  40. package/dist/revert-articles.js +54 -0
  41. package/dist/revert-articles.js.map +1 -0
  42. package/dist/revert-books.d.ts +3 -0
  43. package/dist/revert-books.d.ts.map +1 -0
  44. package/dist/revert-books.js +54 -0
  45. package/dist/revert-books.js.map +1 -0
  46. package/dist/revert-images.d.ts +3 -0
  47. package/dist/revert-images.d.ts.map +1 -0
  48. package/dist/revert-images.js +54 -0
  49. package/dist/revert-images.js.map +1 -0
  50. package/dist/revert-notes.d.ts +3 -0
  51. package/dist/revert-notes.d.ts.map +1 -0
  52. package/dist/revert-notes.js +54 -0
  53. package/dist/revert-notes.js.map +1 -0
  54. package/dist/update-json-articles.d.ts +3 -0
  55. package/dist/update-json-articles.d.ts.map +1 -0
  56. package/dist/update-json-articles.js +116 -0
  57. package/dist/update-json-articles.js.map +1 -0
  58. package/dist/update-raw-articles.d.ts +3 -0
  59. package/dist/update-raw-articles.d.ts.map +1 -0
  60. package/dist/update-raw-articles.js +175 -0
  61. package/dist/update-raw-articles.js.map +1 -0
  62. package/package.json +73 -0
@@ -0,0 +1,101 @@
1
+ #!/usr/bin/env node
2
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
3
+ import { dirname } from "node:path";
4
+ import { makeUnexportedStatus, makeUserId, } from "@s-hirano-ist/s-core/common";
5
+ import { createPushoverService } from "@s-hirano-ist/s-notification";
6
+ const OUTPUT_PATH = "json/article";
7
+ async function main() {
8
+ const env = {
9
+ DATABASE_URL: process.env.DATABASE_URL,
10
+ PUSHOVER_URL: process.env.PUSHOVER_URL,
11
+ PUSHOVER_USER_KEY: process.env.PUSHOVER_USER_KEY,
12
+ PUSHOVER_APP_TOKEN: process.env.PUSHOVER_APP_TOKEN,
13
+ USERNAME_TO_EXPORT: process.env.USERNAME_TO_EXPORT,
14
+ };
15
+ if (Object.values(env).some((v) => !v)) {
16
+ throw new Error("Required environment variables are not set.");
17
+ }
18
+ // Dynamic import for Prisma ESM compatibility
19
+ // @ts-expect-error - Prisma ESM export compatibility
20
+ const { PrismaClient } = await import("@prisma/client");
21
+ const prisma = new PrismaClient({
22
+ accelerateUrl: env.DATABASE_URL ?? "",
23
+ });
24
+ const notificationService = createPushoverService({
25
+ url: env.PUSHOVER_URL ?? "",
26
+ userKey: env.PUSHOVER_USER_KEY ?? "",
27
+ appToken: env.PUSHOVER_APP_TOKEN ?? "",
28
+ });
29
+ const userId = makeUserId(env.USERNAME_TO_EXPORT ?? "");
30
+ const UNEXPORTED = makeUnexportedStatus();
31
+ function categorizeArticles(articles) {
32
+ return articles.reduce((acc, d) => {
33
+ if (!acc[d.categoryName])
34
+ acc[d.categoryName] = [];
35
+ const { title, quote, url } = d;
36
+ acc[d.categoryName].push({ title, quote: quote ?? "", url });
37
+ return acc;
38
+ }, {});
39
+ }
40
+ async function readFileOrCreate(key) {
41
+ const filePath = `${OUTPUT_PATH}/${key}.json`;
42
+ try {
43
+ const data = await readFile(filePath, "utf8");
44
+ return JSON.parse(data);
45
+ }
46
+ catch {
47
+ // File does not exist, create it
48
+ await mkdir(dirname(filePath), { recursive: true });
49
+ const data = { heading: key, description: "FIXME", body: [] };
50
+ const jsonData = JSON.stringify(data, null, 2);
51
+ await writeFile(filePath, jsonData);
52
+ return data;
53
+ }
54
+ }
55
+ async function exportData(data) {
56
+ for (const [key, value] of Object.entries(data)) {
57
+ console.log(`Key: ${key}`);
58
+ const originalData = await readFileOrCreate(key);
59
+ originalData.body.push(...value);
60
+ await writeFile(`${OUTPUT_PATH}/${key}.json`, `${JSON.stringify(originalData, null, 2)}\n`);
61
+ }
62
+ }
63
+ async function fetchArticles() {
64
+ const articles = (await prisma.article.findMany({
65
+ where: { userId, status: UNEXPORTED },
66
+ select: {
67
+ id: true,
68
+ title: true,
69
+ quote: true,
70
+ url: true,
71
+ Category: true,
72
+ },
73
+ })).map((d) => {
74
+ return { ...d, categoryName: d.Category.name };
75
+ });
76
+ console.log(`📊 ${articles.length} 件のデータを取得しました。`);
77
+ await exportData(categorizeArticles(articles));
78
+ console.log("💾 データがJSONファイルに書き出されました。");
79
+ }
80
+ try {
81
+ await fetchArticles();
82
+ await notificationService.notifyInfo("fetch-articles completed", {
83
+ caller: "fetch-articles",
84
+ });
85
+ }
86
+ catch (error) {
87
+ console.error("❌ エラーが発生しました:", error);
88
+ await notificationService.notifyError(`fetch-articles failed: ${error}`, {
89
+ caller: "fetch-articles",
90
+ });
91
+ process.exit(1);
92
+ }
93
+ finally {
94
+ await prisma.$disconnect();
95
+ }
96
+ }
97
+ main().catch((error) => {
98
+ console.error(error);
99
+ process.exit(1);
100
+ });
101
+ //# sourceMappingURL=fetch-articles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch-articles.js","sourceRoot":"","sources":["../src/fetch-articles.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=fetch-books.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch-books.d.ts","sourceRoot":"","sources":["../src/fetch-books.ts"],"names":[],"mappings":""}
@@ -0,0 +1,67 @@
1
+ #!/usr/bin/env node
2
+ import { mkdir, writeFile } from "node:fs/promises";
3
+ import { dirname } from "node:path";
4
+ import { makeUnexportedStatus, makeUserId, } from "@s-hirano-ist/s-core/common";
5
+ import { createPushoverService } from "@s-hirano-ist/s-notification";
6
+ const OUTPUT_DIR = "markdown/books/";
7
+ async function main() {
8
+ const env = {
9
+ DATABASE_URL: process.env.DATABASE_URL,
10
+ PUSHOVER_URL: process.env.PUSHOVER_URL,
11
+ PUSHOVER_USER_KEY: process.env.PUSHOVER_USER_KEY,
12
+ PUSHOVER_APP_TOKEN: process.env.PUSHOVER_APP_TOKEN,
13
+ USERNAME_TO_EXPORT: process.env.USERNAME_TO_EXPORT,
14
+ };
15
+ if (Object.values(env).some((v) => !v)) {
16
+ throw new Error("Required environment variables are not set.");
17
+ }
18
+ // Dynamic import for Prisma ESM compatibility
19
+ // @ts-expect-error - Prisma ESM export compatibility
20
+ const { PrismaClient } = await import("@prisma/client");
21
+ const prisma = new PrismaClient({
22
+ accelerateUrl: env.DATABASE_URL ?? "",
23
+ });
24
+ const notificationService = createPushoverService({
25
+ url: env.PUSHOVER_URL ?? "",
26
+ userKey: env.PUSHOVER_USER_KEY ?? "",
27
+ appToken: env.PUSHOVER_APP_TOKEN ?? "",
28
+ });
29
+ const userId = makeUserId(env.USERNAME_TO_EXPORT ?? "");
30
+ const UNEXPORTED = makeUnexportedStatus();
31
+ async function exportData(data) {
32
+ for (const item of data) {
33
+ const filePath = `${OUTPUT_DIR}${item.ISBN}.md`;
34
+ await mkdir(dirname(filePath), { recursive: true });
35
+ await writeFile(filePath, `# ${item.title}\n`);
36
+ }
37
+ }
38
+ async function fetchBooks() {
39
+ const books = await prisma.book.findMany({
40
+ where: { userId, status: UNEXPORTED },
41
+ });
42
+ console.log(`📊 ${books.length} 件のデータを取得しました。`);
43
+ await exportData(books);
44
+ console.log("💾 データがMarkdownファイルに書き出されました。");
45
+ }
46
+ try {
47
+ await fetchBooks();
48
+ await notificationService.notifyInfo("fetch-books completed", {
49
+ caller: "fetch-books",
50
+ });
51
+ }
52
+ catch (error) {
53
+ console.error("❌ エラーが発生しました:", error);
54
+ await notificationService.notifyError(`fetch-books failed: ${error}`, {
55
+ caller: "fetch-books",
56
+ });
57
+ process.exit(1);
58
+ }
59
+ finally {
60
+ await prisma.$disconnect();
61
+ }
62
+ }
63
+ main().catch((error) => {
64
+ console.error(error);
65
+ process.exit(1);
66
+ });
67
+ //# sourceMappingURL=fetch-books.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch-books.js","sourceRoot":"","sources":["../src/fetch-books.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EACN,oBAAoB,EACpB,UAAU,GAGV,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAQrE,MAAM,UAAU,GAAG,iBAAiB,CAAC;AAErC,KAAK,UAAU,IAAI;IAClB,MAAM,GAAG,GAAG;QACX,YAAY,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY;QACtC,YAAY,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY;QACtC,iBAAiB,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB;QAChD,kBAAkB,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB;QAClD,kBAAkB,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB;KACzC,CAAC;IAEX,IAAI,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACxC,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;IAChE,CAAC;IAED,8CAA8C;IAC9C,qDAAqD;IACrD,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC;IACxD,MAAM,MAAM,GAAG,IAAK,YAAoB,CAAC;QACxC,aAAa,EAAE,GAAG,CAAC,YAAY,IAAI,EAAE;KACrC,CAAC,CAAC;IAEH,MAAM,mBAAmB,GAAG,qBAAqB,CAAC;QACjD,GAAG,EAAE,GAAG,CAAC,YAAY,IAAI,EAAE;QAC3B,OAAO,EAAE,GAAG,CAAC,iBAAiB,IAAI,EAAE;QACpC,QAAQ,EAAE,GAAG,CAAC,kBAAkB,IAAI,EAAE;KACtC,CAAC,CAAC;IAEH,MAAM,MAAM,GAAW,UAAU,CAAC,GAAG,CAAC,kBAAkB,IAAI,EAAE,CAAC,CAAC;IAChE,MAAM,UAAU,GAAW,oBAAoB,EAAE,CAAC;IAElD,KAAK,UAAU,UAAU,CAAC,IAAY;QACrC,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE,CAAC;YACzB,MAAM,QAAQ,GAAG,GAAG,UAAU,GAAG,IAAI,CAAC,IAAI,KAAK,CAAC;YAChD,MAAM,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YACpD,MAAM,SAAS,CAAC,QAAQ,EAAE,KAAK,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC;QAChD,CAAC;IACF,CAAC;IAED,KAAK,UAAU,UAAU;QACxB,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC;YACxC,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE;SACrC,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,MAAM,KAAK,CAAC,MAAM,gBAAgB,CAAC,CAAC;QAEhD,MAAM,UAAU,CAAC,KAAK,CAAC,CAAC;QACxB,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC;IAC9C,CAAC;IAED,IAAI,CAAC;QACJ,MAAM,UAAU,EAAE,CAAC;QACnB,MAAM,mBAAmB,CAAC,UAAU,CAAC,uBAAuB,EAAE;YAC7D,MAAM,EAAE,aAAa;SACrB,CAAC,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,OAAO,CAAC,KAAK,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC;QACtC,MAAM,mBAAmB,CAAC,WAAW,CAAC,uBAAuB,KAAK,EAAE,EAAE;YACrE,MAAM,EAAE,aAAa;SACrB,CAAC,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACjB,CAAC;YAAS,CAAC;QACV,MAAM,MAAM,CAAC,WAAW,EAAE,CAAC;IAC5B,CAAC;AACF,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACtB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACrB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACjB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=fetch-images.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch-images.d.ts","sourceRoot":"","sources":["../src/fetch-images.ts"],"names":[],"mappings":""}
@@ -0,0 +1,83 @@
1
+ #!/usr/bin/env node
2
+ import { mkdir } from "node:fs/promises";
3
+ import path from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ import { makeUnexportedStatus, makeUserId, } from "@s-hirano-ist/s-core/common";
6
+ import { createPushoverService } from "@s-hirano-ist/s-notification";
7
+ import * as Minio from "minio";
8
+ const __filename = fileURLToPath(import.meta.url);
9
+ const __dirname = path.dirname(__filename);
10
+ async function main() {
11
+ const env = {
12
+ DATABASE_URL: process.env.DATABASE_URL,
13
+ PUSHOVER_URL: process.env.PUSHOVER_URL,
14
+ PUSHOVER_USER_KEY: process.env.PUSHOVER_USER_KEY,
15
+ PUSHOVER_APP_TOKEN: process.env.PUSHOVER_APP_TOKEN,
16
+ USERNAME_TO_EXPORT: process.env.USERNAME_TO_EXPORT,
17
+ MINIO_HOST: process.env.MINIO_HOST,
18
+ MINIO_PORT: process.env.MINIO_PORT,
19
+ MINIO_BUCKET_NAME: process.env.MINIO_BUCKET_NAME,
20
+ MINIO_ACCESS_KEY: process.env.MINIO_ACCESS_KEY,
21
+ MINIO_SECRET_KEY: process.env.MINIO_SECRET_KEY,
22
+ };
23
+ if (Object.values(env).some((v) => !v)) {
24
+ throw new Error("Required environment variables are not set.");
25
+ }
26
+ // Dynamic import for Prisma ESM compatibility
27
+ // @ts-expect-error - Prisma ESM export compatibility
28
+ const { PrismaClient } = await import("@prisma/client");
29
+ const prisma = new PrismaClient({
30
+ accelerateUrl: env.DATABASE_URL ?? "",
31
+ });
32
+ const notificationService = createPushoverService({
33
+ url: env.PUSHOVER_URL ?? "",
34
+ userKey: env.PUSHOVER_USER_KEY ?? "",
35
+ appToken: env.PUSHOVER_APP_TOKEN ?? "",
36
+ });
37
+ const minioClient = new Minio.Client({
38
+ endPoint: env.MINIO_HOST ?? "",
39
+ port: Number(env.MINIO_PORT),
40
+ useSSL: true,
41
+ accessKey: env.MINIO_ACCESS_KEY ?? "",
42
+ secretKey: env.MINIO_SECRET_KEY ?? "",
43
+ });
44
+ const userId = makeUserId(env.USERNAME_TO_EXPORT ?? "");
45
+ const UNEXPORTED = makeUnexportedStatus();
46
+ async function fetchImages() {
47
+ const images = await prisma.image.findMany({
48
+ where: { userId, status: UNEXPORTED },
49
+ });
50
+ console.log(`📊 取得した画像データ数: ${images.length}。`);
51
+ const outputDir = path.join(__dirname, "../image/dump");
52
+ await mkdir(outputDir, { recursive: true });
53
+ const downloadPromises = images.map(async (image) => {
54
+ const { path: imagePath } = image;
55
+ const filePath = path.join(outputDir, imagePath);
56
+ await mkdir(path.dirname(filePath), { recursive: true });
57
+ await minioClient.fGetObject(env.MINIO_BUCKET_NAME ?? "", `images/original/${imagePath}`, filePath);
58
+ });
59
+ await Promise.all(downloadPromises);
60
+ console.log("💾 すべての画像の保存が完了しました。");
61
+ }
62
+ try {
63
+ await fetchImages();
64
+ await notificationService.notifyInfo("fetch-images completed", {
65
+ caller: "fetch-images",
66
+ });
67
+ }
68
+ catch (error) {
69
+ console.error("❌ エラーが発生しました:", error);
70
+ await notificationService.notifyError(`fetch-images failed: ${error}`, {
71
+ caller: "fetch-images",
72
+ });
73
+ process.exit(1);
74
+ }
75
+ finally {
76
+ await prisma.$disconnect();
77
+ }
78
+ }
79
+ main().catch((error) => {
80
+ console.error(error);
81
+ process.exit(1);
82
+ });
83
+ //# sourceMappingURL=fetch-images.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch-images.js","sourceRoot":"","sources":["../src/fetch-images.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EACN,oBAAoB,EACpB,UAAU,GAGV,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;AAE3C,KAAK,UAAU,IAAI;IAClB,MAAM,GAAG,GAAG;QACX,YAAY,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY;QACtC,YAAY,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY;QACtC,iBAAiB,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB;QAChD,kBAAkB,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB;QAClD,kBAAkB,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB;QAClD,UAAU,EAAE,OAAO,CAAC,GAAG,CAAC,UAAU;QAClC,UAAU,EAAE,OAAO,CAAC,GAAG,CAAC,UAAU;QAClC,iBAAiB,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB;QAChD,gBAAgB,EAAE,OAAO,CAAC,GAAG,CAAC,gBAAgB;QAC9C,gBAAgB,EAAE,OAAO,CAAC,GAAG,CAAC,gBAAgB;KACrC,CAAC;IAEX,IAAI,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACxC,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;IAChE,CAAC;IAED,8CAA8C;IAC9C,qDAAqD;IACrD,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC;IACxD,MAAM,MAAM,GAAG,IAAK,YAAoB,CAAC;QACxC,aAAa,EAAE,GAAG,CAAC,YAAY,IAAI,EAAE;KACrC,CAAC,CAAC;IAEH,MAAM,mBAAmB,GAAG,qBAAqB,CAAC;QACjD,GAAG,EAAE,GAAG,CAAC,YAAY,IAAI,EAAE;QAC3B,OAAO,EAAE,GAAG,CAAC,iBAAiB,IAAI,EAAE;QACpC,QAAQ,EAAE,GAAG,CAAC,kBAAkB,IAAI,EAAE;KACtC,CAAC,CAAC;IAEH,MAAM,WAAW,GAAG,IAAI,KAAK,CAAC,MAAM,CAAC;QACpC,QAAQ,EAAE,GAAG,CAAC,UAAU,IAAI,EAAE;QAC9B,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC;QAC5B,MAAM,EAAE,IAAI;QACZ,SAAS,EAAE,GAAG,CAAC,gBAAgB,IAAI,EAAE;QACrC,SAAS,EAAE,GAAG,CAAC,gBAAgB,IAAI,EAAE;KACrC,CAAC,CAAC;IAEH,MAAM,MAAM,GAAW,UAAU,CAAC,GAAG,CAAC,kBAAkB,IAAI,EAAE,CAAC,CAAC;IAChE,MAAM,UAAU,GAAW,oBAAoB,EAAE,CAAC;IAElD,KAAK,UAAU,WAAW;QACzB,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC;YAC1C,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE;SACrC,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,kBAAkB,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;QAEhD,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;QACxD,MAAM,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAE5C,MAAM,gBAAgB,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,KAAuB,EAAE,EAAE;YACrE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,KAAK,CAAC;YAClC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;YAEjD,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YACzD,MAAM,WAAW,CAAC,UAAU,CAC3B,GAAG,CAAC,iBAAiB,IAAI,EAAE,EAC3B,mBAAmB,SAAS,EAAE,EAC9B,QAAQ,CACR,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,MAAM,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;QACpC,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;IACrC,CAAC;IAED,IAAI,CAAC;QACJ,MAAM,WAAW,EAAE,CAAC;QACpB,MAAM,mBAAmB,CAAC,UAAU,CAAC,wBAAwB,EAAE;YAC9D,MAAM,EAAE,cAAc;SACtB,CAAC,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,OAAO,CAAC,KAAK,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC;QACtC,MAAM,mBAAmB,CAAC,WAAW,CAAC,wBAAwB,KAAK,EAAE,EAAE;YACtE,MAAM,EAAE,cAAc;SACtB,CAAC,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACjB,CAAC;YAAS,CAAC;QACV,MAAM,MAAM,CAAC,WAAW,EAAE,CAAC;IAC5B,CAAC;AACF,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACtB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACrB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACjB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=fetch-notes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch-notes.d.ts","sourceRoot":"","sources":["../src/fetch-notes.ts"],"names":[],"mappings":""}
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/env node
2
+ import { mkdir, writeFile } from "node:fs/promises";
3
+ import { dirname } from "node:path";
4
+ import { makeUnexportedStatus, makeUserId, } from "@s-hirano-ist/s-core/common";
5
+ import { createPushoverService } from "@s-hirano-ist/s-notification";
6
+ const OUTPUT_DIR = "markdown/note/";
7
+ async function main() {
8
+ const env = {
9
+ DATABASE_URL: process.env.DATABASE_URL,
10
+ PUSHOVER_URL: process.env.PUSHOVER_URL,
11
+ PUSHOVER_USER_KEY: process.env.PUSHOVER_USER_KEY,
12
+ PUSHOVER_APP_TOKEN: process.env.PUSHOVER_APP_TOKEN,
13
+ USERNAME_TO_EXPORT: process.env.USERNAME_TO_EXPORT,
14
+ };
15
+ if (Object.values(env).some((v) => !v)) {
16
+ throw new Error("Required environment variables are not set.");
17
+ }
18
+ // Dynamic import for Prisma ESM compatibility
19
+ // @ts-expect-error - Prisma ESM export compatibility
20
+ const { PrismaClient } = await import("@prisma/client");
21
+ const prisma = new PrismaClient({
22
+ accelerateUrl: env.DATABASE_URL ?? "",
23
+ });
24
+ const notificationService = createPushoverService({
25
+ url: env.PUSHOVER_URL ?? "",
26
+ userKey: env.PUSHOVER_USER_KEY ?? "",
27
+ appToken: env.PUSHOVER_APP_TOKEN ?? "",
28
+ });
29
+ const userId = makeUserId(env.USERNAME_TO_EXPORT ?? "");
30
+ const UNEXPORTED = makeUnexportedStatus();
31
+ async function exportData(data) {
32
+ for (const item of data) {
33
+ const filePath = `${OUTPUT_DIR}${item.title}.md`;
34
+ await mkdir(dirname(filePath), { recursive: true });
35
+ await writeFile(filePath, `# ${item.title}\n\n${item.markdown}\n`);
36
+ }
37
+ }
38
+ async function fetchNotes() {
39
+ const notes = await prisma.note.findMany({
40
+ where: { userId, status: UNEXPORTED },
41
+ select: { id: true, title: true, markdown: true },
42
+ });
43
+ console.log(`📊 ${notes.length} 件のデータを取得しました。`);
44
+ await exportData(notes);
45
+ console.log("💾 データがMarkdownファイルに書き出されました。");
46
+ }
47
+ try {
48
+ await fetchNotes();
49
+ await notificationService.notifyInfo("fetch-notes completed", {
50
+ caller: "fetch-notes",
51
+ });
52
+ }
53
+ catch (error) {
54
+ console.error("❌ エラーが発生しました:", error);
55
+ await notificationService.notifyError(`fetch-notes failed: ${error}`, {
56
+ caller: "fetch-notes",
57
+ });
58
+ process.exit(1);
59
+ }
60
+ finally {
61
+ await prisma.$disconnect();
62
+ }
63
+ }
64
+ main().catch((error) => {
65
+ console.error(error);
66
+ process.exit(1);
67
+ });
68
+ //# sourceMappingURL=fetch-notes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch-notes.js","sourceRoot":"","sources":["../src/fetch-notes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=find-duplicate-json-articles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"find-duplicate-json-articles.d.ts","sourceRoot":"","sources":["../src/find-duplicate-json-articles.ts"],"names":[],"mappings":""}
@@ -0,0 +1,137 @@
1
+ #!/usr/bin/env node
2
+ import fs from "node:fs";
3
+ import { join } from "node:path";
4
+ import { createPushoverService } from "@s-hirano-ist/s-notification";
5
+ function getAllJsonFiles(directory) {
6
+ return fs
7
+ .readdirSync(directory)
8
+ .filter((file) => file.endsWith(".json") && file !== ".DS_Store");
9
+ }
10
+ function readArticleFile(filePath) {
11
+ const fileContents = fs.readFileSync(filePath, "utf8");
12
+ return JSON.parse(fileContents);
13
+ }
14
+ function findDuplicateUrls() {
15
+ const articleDirectory = join(process.cwd(), "json", "article");
16
+ const jsonFiles = getAllJsonFiles(articleDirectory);
17
+ console.log(`検索対象のJSONファイル数: ${jsonFiles.length}`);
18
+ console.log(`ファイル一覧: ${jsonFiles.join(", ")}\n`);
19
+ // URLの出現回数を追跡するマップ
20
+ const urlMap = new Map();
21
+ let totalUrls = 0;
22
+ // 各JSONファイルを処理
23
+ for (const fileName of jsonFiles) {
24
+ const filePath = join(articleDirectory, fileName);
25
+ try {
26
+ const articleFile = readArticleFile(filePath);
27
+ const category = articleFile.heading;
28
+ console.log(`処理中: ${fileName} (カテゴリ: ${category}, 記事数: ${articleFile.body.length})`);
29
+ // 各記事のURLを処理
30
+ for (const item of articleFile.body) {
31
+ totalUrls++;
32
+ const occurrence = {
33
+ url: item.url,
34
+ title: item.title,
35
+ fileName,
36
+ category,
37
+ };
38
+ if (urlMap.has(item.url)) {
39
+ urlMap.get(item.url)?.push(occurrence);
40
+ }
41
+ else {
42
+ urlMap.set(item.url, [occurrence]);
43
+ }
44
+ }
45
+ }
46
+ catch (error) {
47
+ console.error(`エラー: ${fileName} の読み込みに失敗しました:`, error);
48
+ }
49
+ }
50
+ console.log(`\n合計URL数: ${totalUrls}`);
51
+ console.log(`ユニークURL数: ${urlMap.size}`);
52
+ // 重複URLを特定
53
+ const duplicates = [];
54
+ for (const [url, occurrences] of urlMap.entries()) {
55
+ if (occurrences.length > 1) {
56
+ duplicates.push({
57
+ url,
58
+ occurrences,
59
+ });
60
+ }
61
+ }
62
+ return duplicates;
63
+ }
64
+ function displayResults(duplicates) {
65
+ console.log("\n=== 重複URL検出結果 ===");
66
+ console.log(`重複URL数: ${duplicates.length}\n`);
67
+ if (duplicates.length === 0) {
68
+ console.log("重複URLは見つかりませんでした!");
69
+ return;
70
+ }
71
+ // 重複数でソート(多い順)
72
+ duplicates.sort((a, b) => b.occurrences.length - a.occurrences.length);
73
+ duplicates.forEach((duplicate, index) => {
74
+ console.log(`${index + 1}. URL: ${duplicate.url}`);
75
+ console.log(` 重複数: ${duplicate.occurrences.length}回`);
76
+ duplicate.occurrences.forEach((occurrence, occIndex) => {
77
+ console.log(` ${occIndex + 1}) [${occurrence.category}] ${occurrence.fileName}`);
78
+ console.log(` タイトル: ${occurrence.title}`);
79
+ });
80
+ console.log(""); // 空行
81
+ });
82
+ // サマリー統計
83
+ const totalDuplicateOccurrences = duplicates.reduce((sum, dup) => sum + dup.occurrences.length, 0);
84
+ const wastedEntries = totalDuplicateOccurrences - duplicates.length;
85
+ console.log("=== サマリー ===");
86
+ console.log(`重複により無駄になっているエントリ数: ${wastedEntries}`);
87
+ console.log(`最も多く重複しているURL: ${duplicates[0]?.occurrences.length || 0}回重複`);
88
+ // カテゴリ別の重複統計
89
+ const categoryStats = new Map();
90
+ duplicates.forEach((dup) => {
91
+ dup.occurrences.forEach((occ) => {
92
+ categoryStats.set(occ.category, (categoryStats.get(occ.category) || 0) + 1);
93
+ });
94
+ });
95
+ console.log("\nカテゴリ別重複統計:");
96
+ Array.from(categoryStats.entries())
97
+ .sort((a, b) => b[1] - a[1])
98
+ .forEach(([category, count]) => {
99
+ console.log(` ${category}: ${count}個の重複エントリ`);
100
+ });
101
+ }
102
+ async function main() {
103
+ const env = {
104
+ PUSHOVER_URL: process.env.PUSHOVER_URL,
105
+ PUSHOVER_USER_KEY: process.env.PUSHOVER_USER_KEY,
106
+ PUSHOVER_APP_TOKEN: process.env.PUSHOVER_APP_TOKEN,
107
+ };
108
+ if (Object.values(env).some((v) => !v)) {
109
+ throw new Error("Required environment variables are not set.");
110
+ }
111
+ const notificationService = createPushoverService({
112
+ url: env.PUSHOVER_URL ?? "",
113
+ userKey: env.PUSHOVER_USER_KEY ?? "",
114
+ appToken: env.PUSHOVER_APP_TOKEN ?? "",
115
+ });
116
+ try {
117
+ console.log("json/articleディレクトリ内のURL重複を検索中...\n");
118
+ const duplicates = findDuplicateUrls();
119
+ displayResults(duplicates);
120
+ console.log("\n検索完了");
121
+ await notificationService.notifyInfo("find-duplicate-json-articles completed", {
122
+ caller: "find-duplicate-json-articles",
123
+ });
124
+ }
125
+ catch (error) {
126
+ console.error("❌ エラーが発生しました:", error);
127
+ await notificationService.notifyError(`find-duplicate-json-articles failed: ${error}`, {
128
+ caller: "find-duplicate-json-articles",
129
+ });
130
+ process.exit(1);
131
+ }
132
+ }
133
+ main().catch((error) => {
134
+ console.error(error);
135
+ process.exit(1);
136
+ });
137
+ //# sourceMappingURL=find-duplicate-json-articles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"find-duplicate-json-articles.js","sourceRoot":"","sources":["../src/find-duplicate-json-articles.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=reset-articles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reset-articles.d.ts","sourceRoot":"","sources":["../src/reset-articles.ts"],"names":[],"mappings":""}
@@ -0,0 +1,67 @@
1
+ #!/usr/bin/env node
2
+ import { makeExportedAt, makeLastUpdatedStatus, makeUnexportedStatus, makeUserId, } from "@s-hirano-ist/s-core/common";
3
+ import { createPushoverService } from "@s-hirano-ist/s-notification";
4
+ async function main() {
5
+ const env = {
6
+ DATABASE_URL: process.env.DATABASE_URL,
7
+ PUSHOVER_URL: process.env.PUSHOVER_URL,
8
+ PUSHOVER_USER_KEY: process.env.PUSHOVER_USER_KEY,
9
+ PUSHOVER_APP_TOKEN: process.env.PUSHOVER_APP_TOKEN,
10
+ USERNAME_TO_EXPORT: process.env.USERNAME_TO_EXPORT,
11
+ };
12
+ if (Object.values(env).some((v) => !v)) {
13
+ throw new Error("Required environment variables are not set.");
14
+ }
15
+ // Dynamic import for Prisma ESM compatibility
16
+ // @ts-expect-error - Prisma ESM export compatibility
17
+ const { PrismaClient } = await import("@prisma/client");
18
+ const prisma = new PrismaClient({
19
+ accelerateUrl: env.DATABASE_URL ?? "",
20
+ });
21
+ const notificationService = createPushoverService({
22
+ url: env.PUSHOVER_URL ?? "",
23
+ userKey: env.PUSHOVER_USER_KEY ?? "",
24
+ appToken: env.PUSHOVER_APP_TOKEN ?? "",
25
+ });
26
+ const userId = makeUserId(env.USERNAME_TO_EXPORT ?? "");
27
+ const UNEXPORTED = makeUnexportedStatus();
28
+ const LAST_UPDATED = makeLastUpdatedStatus();
29
+ const EXPORTED = "EXPORTED";
30
+ async function resetArticles() {
31
+ await prisma.$transaction(async (tx) => {
32
+ // LAST_UPDATED → EXPORTED (前回バッチを確定)
33
+ await tx.article.updateMany({
34
+ where: { userId, status: LAST_UPDATED },
35
+ data: { status: EXPORTED, exportedAt: makeExportedAt() },
36
+ });
37
+ console.log("💾 LAST_UPDATEDの記事をEXPORTEDに変更しました");
38
+ // UNEXPORTED → LAST_UPDATED (今回バッチをマーク)
39
+ const result = await tx.article.updateMany({
40
+ where: { userId, status: UNEXPORTED },
41
+ data: { status: LAST_UPDATED },
42
+ });
43
+ console.log(`💾 ${result.count}件の記事をリセットしました`);
44
+ });
45
+ }
46
+ try {
47
+ await resetArticles();
48
+ await notificationService.notifyInfo("reset-articles completed", {
49
+ caller: "reset-articles",
50
+ });
51
+ }
52
+ catch (error) {
53
+ console.error("❌ エラーが発生しました:", error);
54
+ await notificationService.notifyError(`reset-articles failed: ${error}`, {
55
+ caller: "reset-articles",
56
+ });
57
+ process.exit(1);
58
+ }
59
+ finally {
60
+ await prisma.$disconnect();
61
+ }
62
+ }
63
+ main().catch((error) => {
64
+ console.error(error);
65
+ process.exit(1);
66
+ });
67
+ //# sourceMappingURL=reset-articles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reset-articles.js","sourceRoot":"","sources":["../src/reset-articles.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=reset-books.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reset-books.d.ts","sourceRoot":"","sources":["../src/reset-books.ts"],"names":[],"mappings":""}