HyeonJun Jeon

[Implement] Save iCal in DB

......@@ -22,4 +22,4 @@ npm-debug.log*
yarn-debug.log*
yarn-error.log*
.prettierignore
server/libs/login.pvdata
*.pvdata
......
......@@ -6,7 +6,7 @@
- Front-End : React
- Back-End : Express
- Storage : LocalForage
- DataBase : MySQL
- Crawl : Puppeteer
<br>
......
......@@ -17,6 +17,7 @@
"express": "^4.18.1",
"fs": "^0.0.1-security",
"localforage": "^1.10.0",
"mysql": "^2.18.1",
"puppeteer": "^14.1.1",
"react": "^18.1.0",
"react-dom": "^18.1.0",
......@@ -4904,6 +4905,14 @@
"node": "*"
}
},
"node_modules/bignumber.js": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz",
"integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A==",
"engines": {
"node": "*"
}
},
"node_modules/binary-extensions": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
......@@ -11601,6 +11610,42 @@
"multicast-dns": "cli.js"
}
},
"node_modules/mysql": {
"version": "2.18.1",
"resolved": "https://registry.npmjs.org/mysql/-/mysql-2.18.1.tgz",
"integrity": "sha512-Bca+gk2YWmqp2Uf6k5NFEurwY/0td0cpebAucFpY/3jhrwrVGuxU2uQFCHjU19SJfje0yQvi+rVWdq78hR5lig==",
"dependencies": {
"bignumber.js": "9.0.0",
"readable-stream": "2.3.7",
"safe-buffer": "5.1.2",
"sqlstring": "2.3.1"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/mysql/node_modules/readable-stream": {
"version": "2.3.7",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
"integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
"dependencies": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
"isarray": "~1.0.0",
"process-nextick-args": "~2.0.0",
"safe-buffer": "~5.1.1",
"string_decoder": "~1.1.1",
"util-deprecate": "~1.0.1"
}
},
"node_modules/mysql/node_modules/string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"dependencies": {
"safe-buffer": "~5.1.0"
}
},
"node_modules/nanoid": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz",
......@@ -14759,6 +14804,14 @@
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
},
"node_modules/sqlstring": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz",
"integrity": "sha1-R1OT/56RR5rqYtyvDKPRSYOn+0A=",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/stable": {
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz",
......@@ -20121,6 +20174,11 @@
"resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz",
"integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ=="
},
"bignumber.js": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz",
"integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A=="
},
"binary-extensions": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
......@@ -24974,6 +25032,41 @@
"thunky": "^1.0.2"
}
},
"mysql": {
"version": "2.18.1",
"resolved": "https://registry.npmjs.org/mysql/-/mysql-2.18.1.tgz",
"integrity": "sha512-Bca+gk2YWmqp2Uf6k5NFEurwY/0td0cpebAucFpY/3jhrwrVGuxU2uQFCHjU19SJfje0yQvi+rVWdq78hR5lig==",
"requires": {
"bignumber.js": "9.0.0",
"readable-stream": "2.3.7",
"safe-buffer": "5.1.2",
"sqlstring": "2.3.1"
},
"dependencies": {
"readable-stream": {
"version": "2.3.7",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
"integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
"requires": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
"isarray": "~1.0.0",
"process-nextick-args": "~2.0.0",
"safe-buffer": "~5.1.1",
"string_decoder": "~1.1.1",
"util-deprecate": "~1.0.1"
}
},
"string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"requires": {
"safe-buffer": "~5.1.0"
}
}
}
},
"nanoid": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz",
......@@ -27132,6 +27225,11 @@
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
},
"sqlstring": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz",
"integrity": "sha1-R1OT/56RR5rqYtyvDKPRSYOn+0A="
},
"stable": {
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz",
......
......@@ -12,6 +12,7 @@
"express": "^4.18.1",
"fs": "^0.0.1-security",
"localforage": "^1.10.0",
"mysql": "^2.18.1",
"puppeteer": "^14.1.1",
"react": "^18.1.0",
"react-dom": "^18.1.0",
......
......@@ -22,40 +22,43 @@ function parseICal(text) {
const errArr = [];
function process(sche, k, v) {
switch (k) {
case "DTSTAMP":
k = "CREATED";
v = dateTimeToDate(v);
break;
case "UID":
v = v.split("-")[2];
break;
case "DTSTART":
k = "START";
v = dateTimeToDate(v);
sche.scheType = "time";
sche.date = getDatestr(v);
k = "startTime";
v = getTimestr(v);
break;
case "DTEND":
k = "END";
v = dateTimeToDate(v);
k = "endTime";
v = sche.startTime;
break;
case "DTSTART;VALUE=DATE":
case "DTEND;VALUE=DATE":
k = "DATE";
v = dateToDate(v);
sche.scheType = "date";
k = "date";
v = getDatestr(v);
break;
case "DTEND;VALUE=DATE":
return;
case "X-ALT-DESC;FMTTYPE=text/html":
k = "DETAIL";
k = "detail";
break;
case "SUMMARY":
k = "LABEL";
let b;
[v, b] = v.split(" [");
sche["SUBJECT"] = b.substring(0, b.length - 1);
k = "label";
v = v.substring(0, v.indexOf(" ["));
break;
case "UID":
k = "uid";
v = v.split("-")[2];
break;
case "DTSTAMP":
case "CLASS":
case "SEQUENCE":
return;
case "DESCRIPTION":
k = "description";
case "URL":
k = "url";
sche.subjectID = v.substring(v.indexOf("se_") + 3, v.indexOf("&m"));
break;
default:
errArr.push(k);
......@@ -70,19 +73,18 @@ function insert(str, idxs, char) {
return nstr;
}
function dateTimeToDate(str) {
const [a, b] = str.split("T");
return new Date(insert(a, [4, 6, 8], "-") + "T" + insert(b, [2, 4, 6], ":"));
function getDatestr(str) {
const a = str.substring(0, str.indexOf("T"));
return insert(a, [4, 6, 8], "-");
}
function dateToDate(str) {
return new Date(insert(str, [4, 6, 8], "-"));
function getTimestr(str) {
const b = str.substring(str.indexOf("T") + 1);
return insert(b, [2, 4, 6], ":");
}
// let result;
// fs.readFile("C:/Users/teddy/Downloads/data.ics", "utf8", (err, data) => {
// if (err) console.log(err);
// else result = parseICal(data);
// });
// const fdata = fs.readFileSync("C:/Users/teddy/Downloads/data.ics", "utf8");
// const jcal = parseICal(fdata);
// console("done");
export { parseICal };
module.exports = parseICal;
......
const mysql = require("mysql");
const fs = require("fs");
const parseICal = require("./ICal");
function jcalToSQL(jcal, userID) {
const fsql = fs.readFileSync("server/libs/sql.pvdata", "utf8");
const [id, pw] = fsql.split("\r\n");
const connection = mysql.createConnection({
host: "localhost",
user: id,
password: pw,
database: "db",
});
connection.connect();
const commonCols = [
"uid",
"label",
"subjectID",
"type",
"description",
"url",
"detail",
"status",
];
const dateScheCols = [...commonCols, "date"];
const timeScheCols = [...commonCols, "date", "startTime", "endTime"];
const dateQueryString =
"INSERT IGNORE INTO schedules_date (userID," +
dateScheCols.join(",") +
") VALUES ?";
const timeQueryString =
"INSERT IGNORE INTO schedules_time (userID," +
timeScheCols.join(",") +
") VALUES ?";
const dateSchedules = [];
const timeSchedules = [];
for (const sche of jcal) {
if (sche.scheType === "date") {
dateSchedules.push([userID, ...dateScheCols.map((col) => sche[col])]);
} else if (sche.scheType === "time") {
timeSchedules.push([userID, ...timeScheCols.map((col) => sche[col])]);
} else console.log("unexpected scheType", sche);
}
connection.query(dateQueryString, [dateSchedules], (error, result) => {
if (error) console.log(error);
else console.log(`schedules_date | ${result.affectedRows} rows added`);
});
connection.query(timeQueryString, [timeSchedules], (error, result) => {
if (error) console.log(error);
else console.log(`schedules_time | ${result.affectedRows} rows added`);
});
connection.end();
}
// iCal의 소유주를 DB에 등록 후 userID get
// subjectID가 subjects, userID가 users에 있어야함
const fdata = fs.readFileSync("C:/Users/teddy/Downloads/data.ics", "utf8");
const jcal = parseICal(fdata);
jcalToSQL(jcal, 1);
module.exports = jcalToSQL;