-
Notifications
You must be signed in to change notification settings - Fork 0
/
app.mjs
157 lines (131 loc) · 5.12 KB
/
app.mjs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
import * as fs from "fs";
import dotenv from "dotenv";
import fetch from "node-fetch";
import cron from "node-cron";
import cronstrue from "cronstrue";
dotenv.config();
let locale = process.env.LOCALE || "en";
let timeZone = process.env.TIMEZONE || "Etc/UTC";
async function getSpaces(token) {
const res = await fetch("https://www.notion.so/api/v3/getSpaces", {
method: "POST", body: JSON.stringify({}), headers: {
"Cookie": `token_v2=${token};`, "Content-Type": "application/json",
}
});
const json = await res.json();
let spacesIds = [];
for (const user in json) {
/** @property {Object} space - notion space */
for (const space in json[user].space) {
spacesIds.push(space)
}
}
return spacesIds;
}
async function exportSpace(token, spaceId, exportType) {
console.log(`[Notion] ${exportType} export starting...`);
const exportTask = {
task: {
eventName: "exportSpace", request: { spaceId, exportOptions: { locale, timeZone, exportType } },
},
};
const enqueueTaskResponse = await fetch("https://www.notion.so/api/v3/enqueueTask", {
method: "POST",
body: JSON.stringify(exportTask),
headers: { "Cookie": `token_v2=${token};`, "Content-Type": "application/json" }
});
const { taskId } = await enqueueTaskResponse.json();
return await new Promise((resolve, reject) => {
const interval = setInterval(async () => {
const response = await fetch("https://www.notion.so/api/v3/getTasks", {
method: "POST", body: JSON.stringify({ taskIds: [taskId] }), headers: {
"Cookie": `token_v2=${token};`, "Content-Type": "application/json",
}
});
/**
* @property {Object[]} results[] - array of tasks results
* @property {Object} results[].status - status of one task result
* @property {int} taskStatus.pagesExported - number of exported pages
* @property {int} taskStatus.exportURL - URL of the export
*/
const json = await response.json();
const taskStatus = json.results[0].status;
if (!taskStatus) {
clearInterval(interval);
reject(new Error());
} else if (taskStatus.type === "complete") {
clearInterval(interval);
console.log(`[Notion] ${exportType} export successful ! (Pages exported: ${taskStatus.pagesExported})`);
resolve(taskStatus.exportURL);
}
}, 1000);
});
}
async function downloadExport(exportType, url) {
console.log(`[Notion] ${exportType} export downloading...`);
const path = `./data/${exportType}/`;
const td = new Date().toISOString()
.replace(/-/g, '')
.replace(/T/, '_')
.replace(/:/g, '')
.replace(/\..+/, '');
const fileName = `Export_${td}${url.match(/[\da-f-]+.zip/)[0]}`;
if (!fs.existsSync(path)) {
fs.mkdirSync(path, { recursive: true });
}
const writeStream = fs.createWriteStream(path.concat(fileName));
const response = await fetch(url);
response.body.pipe(writeStream);
await new Promise((executor) => {
response.body.on("end", executor);
});
console.log(`[Notion] ${exportType} export download successful !`);
}
async function startExportTask() {
let token = process.env.TOKEN;
if (!token) {
console.error(`[Notion] token not defined`);
process.exit(1)
}
let exportType = process.env.EXPORT_TYPE || "html+markdown";
const spaces = await getSpaces(token);
await Promise.all(spaces.map(async (spaceId) => {
switch (exportType) {
case "html": {
let htmlUrl = await exportSpace(token, spaceId, "html");
await downloadExport(htmlUrl, "html");
break;
}
case "markdown": {
let mdUrl = await exportSpace(token, spaceId, "markdown");
await downloadExport(mdUrl, "markdown");
break;
}
case "html+markdown": {
let htmlUrl = await exportSpace(token, spaceId, "html");
await downloadExport(htmlUrl, "html");
let mdUrl = await exportSpace(token, spaceId, "markdown");
await downloadExport(mdUrl, "markdown");
break;
}
default: {
console.error(`[Notion] Export of type ${exportType} not supported !`);
process.exit(1)
}
}
}));
}
(async () => {
let cronExpression = process.env.CRON;
if (!cronExpression) {
console.log(`[Notion] No cron expression defined executing export once.`);
await startExportTask();
} else {
console.log(`[Notion] Execution export with scheduling: ${cronstrue.toString(cronExpression).toLowerCase()} (cron expression: ${cronExpression})`);
cron.schedule(cronExpression, () => {
(async () => {
await startExportTask();
})();
}, timeZone);
}
})();