@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.
- package/LICENSE +661 -0
- package/dist/fetch-articles.d.ts +3 -0
- package/dist/fetch-articles.d.ts.map +1 -0
- package/dist/fetch-articles.js +101 -0
- package/dist/fetch-articles.js.map +1 -0
- package/dist/fetch-books.d.ts +3 -0
- package/dist/fetch-books.d.ts.map +1 -0
- package/dist/fetch-books.js +67 -0
- package/dist/fetch-books.js.map +1 -0
- package/dist/fetch-images.d.ts +3 -0
- package/dist/fetch-images.d.ts.map +1 -0
- package/dist/fetch-images.js +83 -0
- package/dist/fetch-images.js.map +1 -0
- package/dist/fetch-notes.d.ts +3 -0
- package/dist/fetch-notes.d.ts.map +1 -0
- package/dist/fetch-notes.js +68 -0
- package/dist/fetch-notes.js.map +1 -0
- package/dist/find-duplicate-json-articles.d.ts +3 -0
- package/dist/find-duplicate-json-articles.d.ts.map +1 -0
- package/dist/find-duplicate-json-articles.js +137 -0
- package/dist/find-duplicate-json-articles.js.map +1 -0
- package/dist/reset-articles.d.ts +3 -0
- package/dist/reset-articles.d.ts.map +1 -0
- package/dist/reset-articles.js +67 -0
- package/dist/reset-articles.js.map +1 -0
- package/dist/reset-books.d.ts +3 -0
- package/dist/reset-books.d.ts.map +1 -0
- package/dist/reset-books.js +67 -0
- package/dist/reset-books.js.map +1 -0
- package/dist/reset-images.d.ts +3 -0
- package/dist/reset-images.d.ts.map +1 -0
- package/dist/reset-images.js +67 -0
- package/dist/reset-images.js.map +1 -0
- package/dist/reset-notes.d.ts +3 -0
- package/dist/reset-notes.d.ts.map +1 -0
- package/dist/reset-notes.js +67 -0
- package/dist/reset-notes.js.map +1 -0
- package/dist/revert-articles.d.ts +3 -0
- package/dist/revert-articles.d.ts.map +1 -0
- package/dist/revert-articles.js +54 -0
- package/dist/revert-articles.js.map +1 -0
- package/dist/revert-books.d.ts +3 -0
- package/dist/revert-books.d.ts.map +1 -0
- package/dist/revert-books.js +54 -0
- package/dist/revert-books.js.map +1 -0
- package/dist/revert-images.d.ts +3 -0
- package/dist/revert-images.d.ts.map +1 -0
- package/dist/revert-images.js +54 -0
- package/dist/revert-images.js.map +1 -0
- package/dist/revert-notes.d.ts +3 -0
- package/dist/revert-notes.d.ts.map +1 -0
- package/dist/revert-notes.js +54 -0
- package/dist/revert-notes.js.map +1 -0
- package/dist/update-json-articles.d.ts +3 -0
- package/dist/update-json-articles.d.ts.map +1 -0
- package/dist/update-json-articles.js +116 -0
- package/dist/update-json-articles.js.map +1 -0
- package/dist/update-raw-articles.d.ts +3 -0
- package/dist/update-raw-articles.d.ts.map +1 -0
- package/dist/update-raw-articles.js +175 -0
- package/dist/update-raw-articles.js.map +1 -0
- package/package.json +73 -0
|
@@ -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 resetBooks() {
|
|
31
|
+
await prisma.$transaction(async (tx) => {
|
|
32
|
+
// LAST_UPDATED → EXPORTED (前回バッチを確定)
|
|
33
|
+
await tx.book.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.book.updateMany({
|
|
40
|
+
where: { userId, status: UNEXPORTED },
|
|
41
|
+
data: { status: LAST_UPDATED },
|
|
42
|
+
});
|
|
43
|
+
console.log(`💾 ${result.count}件の本をリセットしました`);
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
await resetBooks();
|
|
48
|
+
await notificationService.notifyInfo("reset-books completed", {
|
|
49
|
+
caller: "reset-books",
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
console.error("❌ エラーが発生しました:", error);
|
|
54
|
+
await notificationService.notifyError(`reset-books failed: ${error}`, {
|
|
55
|
+
caller: "reset-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=reset-books.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reset-books.js","sourceRoot":"","sources":["../src/reset-books.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reset-images.d.ts","sourceRoot":"","sources":["../src/reset-images.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 resetImages() {
|
|
31
|
+
await prisma.$transaction(async (tx) => {
|
|
32
|
+
// LAST_UPDATED → EXPORTED (前回バッチを確定)
|
|
33
|
+
await tx.image.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.image.updateMany({
|
|
40
|
+
where: { userId, status: UNEXPORTED },
|
|
41
|
+
data: { status: LAST_UPDATED },
|
|
42
|
+
});
|
|
43
|
+
console.log(`💾 ${result.count}件の画像をリセットしました`);
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
await resetImages();
|
|
48
|
+
await notificationService.notifyInfo("reset-images completed", {
|
|
49
|
+
caller: "reset-images",
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
console.error("❌ エラーが発生しました:", error);
|
|
54
|
+
await notificationService.notifyError(`reset-images failed: ${error}`, {
|
|
55
|
+
caller: "reset-images",
|
|
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-images.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reset-images.js","sourceRoot":"","sources":["../src/reset-images.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reset-notes.d.ts","sourceRoot":"","sources":["../src/reset-notes.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 resetNotes() {
|
|
31
|
+
await prisma.$transaction(async (tx) => {
|
|
32
|
+
// LAST_UPDATED → EXPORTED (前回バッチを確定)
|
|
33
|
+
await tx.note.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.note.updateMany({
|
|
40
|
+
where: { userId, status: UNEXPORTED },
|
|
41
|
+
data: { status: LAST_UPDATED },
|
|
42
|
+
});
|
|
43
|
+
console.log(`💾 ${result.count}件のノートをリセットしました`);
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
await resetNotes();
|
|
48
|
+
await notificationService.notifyInfo("reset-notes completed", {
|
|
49
|
+
caller: "reset-notes",
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
console.error("❌ エラーが発生しました:", error);
|
|
54
|
+
await notificationService.notifyError(`reset-notes failed: ${error}`, {
|
|
55
|
+
caller: "reset-notes",
|
|
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-notes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reset-notes.js","sourceRoot":"","sources":["../src/reset-notes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"revert-articles.d.ts","sourceRoot":"","sources":["../src/revert-articles.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { 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
|
+
try {
|
|
30
|
+
await prisma.article.updateMany({
|
|
31
|
+
where: { userId, status: LAST_UPDATED },
|
|
32
|
+
data: { status: UNEXPORTED },
|
|
33
|
+
});
|
|
34
|
+
console.log("💾 LAST_UPDATEDの記事をUNEXPORTEDに変更しました");
|
|
35
|
+
await notificationService.notifyInfo("revert-articles completed", {
|
|
36
|
+
caller: "revert-articles",
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
console.error("❌ エラーが発生しました:", error);
|
|
41
|
+
await notificationService.notifyError(`revert-articles failed: ${error}`, {
|
|
42
|
+
caller: "revert-articles",
|
|
43
|
+
});
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
finally {
|
|
47
|
+
await prisma.$disconnect();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
main().catch((error) => {
|
|
51
|
+
console.error(error);
|
|
52
|
+
process.exit(1);
|
|
53
|
+
});
|
|
54
|
+
//# sourceMappingURL=revert-articles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"revert-articles.js","sourceRoot":"","sources":["../src/revert-articles.ts"],"names":[],"mappings":";AACA,OAAO,EACN,qBAAqB,EACrB,oBAAoB,EACpB,UAAU,GAGV,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAErE,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;IAClD,MAAM,YAAY,GAAW,qBAAqB,EAAE,CAAC;IAErD,IAAI,CAAC;QACJ,MAAM,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC;YAC/B,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE;YACvC,IAAI,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE;SAC5B,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,sCAAsC,CAAC,CAAC;QACpD,MAAM,mBAAmB,CAAC,UAAU,CAAC,2BAA2B,EAAE;YACjE,MAAM,EAAE,iBAAiB;SACzB,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,2BAA2B,KAAK,EAAE,EAAE;YACzE,MAAM,EAAE,iBAAiB;SACzB,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 @@
|
|
|
1
|
+
{"version":3,"file":"revert-books.d.ts","sourceRoot":"","sources":["../src/revert-books.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { 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
|
+
try {
|
|
30
|
+
await prisma.book.updateMany({
|
|
31
|
+
where: { userId, status: LAST_UPDATED },
|
|
32
|
+
data: { status: UNEXPORTED },
|
|
33
|
+
});
|
|
34
|
+
console.log("💾 LAST_UPDATEDの本をUNEXPORTEDに変更しました");
|
|
35
|
+
await notificationService.notifyInfo("revert-books completed", {
|
|
36
|
+
caller: "revert-books",
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
console.error("❌ エラーが発生しました:", error);
|
|
41
|
+
await notificationService.notifyError(`revert-books failed: ${error}`, {
|
|
42
|
+
caller: "revert-books",
|
|
43
|
+
});
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
finally {
|
|
47
|
+
await prisma.$disconnect();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
main().catch((error) => {
|
|
51
|
+
console.error(error);
|
|
52
|
+
process.exit(1);
|
|
53
|
+
});
|
|
54
|
+
//# sourceMappingURL=revert-books.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"revert-books.js","sourceRoot":"","sources":["../src/revert-books.ts"],"names":[],"mappings":";AACA,OAAO,EACN,qBAAqB,EACrB,oBAAoB,EACpB,UAAU,GAGV,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAErE,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;IAClD,MAAM,YAAY,GAAW,qBAAqB,EAAE,CAAC;IAErD,IAAI,CAAC;QACJ,MAAM,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC;YAC5B,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE;YACvC,IAAI,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE;SAC5B,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAC;QACnD,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 @@
|
|
|
1
|
+
{"version":3,"file":"revert-images.d.ts","sourceRoot":"","sources":["../src/revert-images.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { 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
|
+
try {
|
|
30
|
+
await prisma.image.updateMany({
|
|
31
|
+
where: { userId, status: LAST_UPDATED },
|
|
32
|
+
data: { status: UNEXPORTED },
|
|
33
|
+
});
|
|
34
|
+
console.log("💾 LAST_UPDATEDの画像をUNEXPORTEDに変更しました");
|
|
35
|
+
await notificationService.notifyInfo("revert-images completed", {
|
|
36
|
+
caller: "revert-images",
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
console.error("❌ エラーが発生しました:", error);
|
|
41
|
+
await notificationService.notifyError(`revert-images failed: ${error}`, {
|
|
42
|
+
caller: "revert-images",
|
|
43
|
+
});
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
finally {
|
|
47
|
+
await prisma.$disconnect();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
main().catch((error) => {
|
|
51
|
+
console.error(error);
|
|
52
|
+
process.exit(1);
|
|
53
|
+
});
|
|
54
|
+
//# sourceMappingURL=revert-images.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"revert-images.js","sourceRoot":"","sources":["../src/revert-images.ts"],"names":[],"mappings":";AACA,OAAO,EACN,qBAAqB,EACrB,oBAAoB,EACpB,UAAU,GAGV,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAErE,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;IAClD,MAAM,YAAY,GAAW,qBAAqB,EAAE,CAAC;IAErD,IAAI,CAAC;QACJ,MAAM,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC;YAC7B,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE;YACvC,IAAI,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE;SAC5B,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,sCAAsC,CAAC,CAAC;QACpD,MAAM,mBAAmB,CAAC,UAAU,CAAC,yBAAyB,EAAE;YAC/D,MAAM,EAAE,eAAe;SACvB,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,yBAAyB,KAAK,EAAE,EAAE;YACvE,MAAM,EAAE,eAAe;SACvB,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 @@
|
|
|
1
|
+
{"version":3,"file":"revert-notes.d.ts","sourceRoot":"","sources":["../src/revert-notes.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { 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
|
+
try {
|
|
30
|
+
await prisma.note.updateMany({
|
|
31
|
+
where: { userId, status: LAST_UPDATED },
|
|
32
|
+
data: { status: UNEXPORTED },
|
|
33
|
+
});
|
|
34
|
+
console.log("💾 LAST_UPDATEDのノートをUNEXPORTEDに変更しました");
|
|
35
|
+
await notificationService.notifyInfo("revert-notes completed", {
|
|
36
|
+
caller: "revert-notes",
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
console.error("❌ エラーが発生しました:", error);
|
|
41
|
+
await notificationService.notifyError(`revert-notes failed: ${error}`, {
|
|
42
|
+
caller: "revert-notes",
|
|
43
|
+
});
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
finally {
|
|
47
|
+
await prisma.$disconnect();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
main().catch((error) => {
|
|
51
|
+
console.error(error);
|
|
52
|
+
process.exit(1);
|
|
53
|
+
});
|
|
54
|
+
//# sourceMappingURL=revert-notes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"revert-notes.js","sourceRoot":"","sources":["../src/revert-notes.ts"],"names":[],"mappings":";AACA,OAAO,EACN,qBAAqB,EACrB,oBAAoB,EACpB,UAAU,GAGV,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAErE,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;IAClD,MAAM,YAAY,GAAW,qBAAqB,EAAE,CAAC;IAErD,IAAI,CAAC;QACJ,MAAM,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC;YAC5B,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE;YACvC,IAAI,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE;SAC5B,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,uCAAuC,CAAC,CAAC;QACrD,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 @@
|
|
|
1
|
+
{"version":3,"file":"update-json-articles.d.ts","sourceRoot":"","sources":["../src/update-json-articles.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { readdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { createPushoverService } from "@s-hirano-ist/s-notification";
|
|
5
|
+
import { JSDOM, VirtualConsole } from "jsdom";
|
|
6
|
+
// REF: https://zenn.dev/littleforest/articles/scrape-og-tags
|
|
7
|
+
function extractOgpData(metaElements) {
|
|
8
|
+
return metaElements
|
|
9
|
+
.filter((element) => element.hasAttribute("property"))
|
|
10
|
+
.reduce((previous, current) => {
|
|
11
|
+
const property = current.getAttribute("property")?.trim();
|
|
12
|
+
const content = current.getAttribute("content");
|
|
13
|
+
if (!property || !content)
|
|
14
|
+
return previous;
|
|
15
|
+
previous[property] = content;
|
|
16
|
+
return previous;
|
|
17
|
+
}, {});
|
|
18
|
+
}
|
|
19
|
+
async function getOgTags(url) {
|
|
20
|
+
try {
|
|
21
|
+
console.log(`Fetching OG tags for: ${url}`);
|
|
22
|
+
// REF: https://github.com/jsdom/jsdom#virtual-consoles
|
|
23
|
+
const virtualConsole = new VirtualConsole();
|
|
24
|
+
const dom = await JSDOM.fromURL(url, { virtualConsole });
|
|
25
|
+
virtualConsole.on("error", () => { });
|
|
26
|
+
virtualConsole.on("warn", () => { });
|
|
27
|
+
virtualConsole.on("info", () => { });
|
|
28
|
+
virtualConsole.on("dir", () => { });
|
|
29
|
+
const meta = dom.window.document.head.querySelectorAll("meta");
|
|
30
|
+
const ogTags = extractOgpData([...meta]);
|
|
31
|
+
const ogImageUrl = ogTags?.["og:image"];
|
|
32
|
+
const ogTitle = ogTags?.["og:title"];
|
|
33
|
+
const ogDescription = ogTags?.["og:description"];
|
|
34
|
+
return { ogImageUrl, ogTitle, ogDescription };
|
|
35
|
+
}
|
|
36
|
+
catch (_error) {
|
|
37
|
+
console.error(`Error fetching OG tags for ${url}:`);
|
|
38
|
+
return {};
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
async function processArticleFile(filePath) {
|
|
42
|
+
try {
|
|
43
|
+
const jsonContent = readFileSync(filePath, "utf-8");
|
|
44
|
+
const articleData = JSON.parse(jsonContent);
|
|
45
|
+
console.log(`Processing ${filePath}...`);
|
|
46
|
+
for (let i = 0; i < articleData.body.length; i++) {
|
|
47
|
+
const item = articleData.body[i];
|
|
48
|
+
// Skip if OG tags already exist
|
|
49
|
+
if (item.ogImageUrl || item.ogTitle || item.ogDescription || item.skip) {
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
const ogTags = await getOgTags(item.url);
|
|
53
|
+
// Only add properties if they have values
|
|
54
|
+
if (ogTags.ogImageUrl)
|
|
55
|
+
item.ogImageUrl = ogTags.ogImageUrl;
|
|
56
|
+
else
|
|
57
|
+
console.warn(`No OG image found for ${item.url}`);
|
|
58
|
+
if (ogTags.ogTitle)
|
|
59
|
+
item.ogTitle = ogTags.ogTitle;
|
|
60
|
+
else
|
|
61
|
+
console.warn(`No OG title found for ${item.url}`);
|
|
62
|
+
if (ogTags.ogDescription)
|
|
63
|
+
item.ogDescription = ogTags.ogDescription;
|
|
64
|
+
else
|
|
65
|
+
console.warn(`No OG description found for ${item.url}`);
|
|
66
|
+
// Add a small delay to avoid overwhelming servers
|
|
67
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
68
|
+
}
|
|
69
|
+
// Write back to file
|
|
70
|
+
writeFileSync(filePath, `${JSON.stringify(articleData, null, "\t")}\n`, "utf-8");
|
|
71
|
+
console.log(`Completed processing ${filePath}`);
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
console.error(`Error processing ${filePath}:`, error);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
async function main() {
|
|
78
|
+
const env = {
|
|
79
|
+
PUSHOVER_URL: process.env.PUSHOVER_URL,
|
|
80
|
+
PUSHOVER_USER_KEY: process.env.PUSHOVER_USER_KEY,
|
|
81
|
+
PUSHOVER_APP_TOKEN: process.env.PUSHOVER_APP_TOKEN,
|
|
82
|
+
};
|
|
83
|
+
if (Object.values(env).some((v) => !v)) {
|
|
84
|
+
throw new Error("Required environment variables are not set.");
|
|
85
|
+
}
|
|
86
|
+
const notificationService = createPushoverService({
|
|
87
|
+
url: env.PUSHOVER_URL ?? "",
|
|
88
|
+
userKey: env.PUSHOVER_USER_KEY ?? "",
|
|
89
|
+
appToken: env.PUSHOVER_APP_TOKEN ?? "",
|
|
90
|
+
});
|
|
91
|
+
const articleDir = join(process.cwd(), "json", "article");
|
|
92
|
+
try {
|
|
93
|
+
const files = readdirSync(articleDir).filter((file) => file.endsWith(".json"));
|
|
94
|
+
console.log(`Found ${files.length} JSON files to process`);
|
|
95
|
+
for (const file of files) {
|
|
96
|
+
const filePath = join(articleDir, file);
|
|
97
|
+
await processArticleFile(filePath);
|
|
98
|
+
}
|
|
99
|
+
console.log("All files processed successfully!");
|
|
100
|
+
await notificationService.notifyInfo("update-json-articles completed", {
|
|
101
|
+
caller: "update-json-articles",
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
console.error("Error in main process:", error);
|
|
106
|
+
await notificationService.notifyError(`update-json-articles failed: ${error}`, {
|
|
107
|
+
caller: "update-json-articles",
|
|
108
|
+
});
|
|
109
|
+
process.exit(1);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
main().catch((error) => {
|
|
113
|
+
console.error(error);
|
|
114
|
+
process.exit(1);
|
|
115
|
+
});
|
|
116
|
+
//# sourceMappingURL=update-json-articles.js.map
|