HyeonJun Jeon

[Implement] Save iCal in DB

...@@ -22,4 +22,4 @@ npm-debug.log* ...@@ -22,4 +22,4 @@ npm-debug.log*
22 yarn-debug.log* 22 yarn-debug.log*
23 yarn-error.log* 23 yarn-error.log*
24 .prettierignore 24 .prettierignore
25 -server/libs/login.pvdata 25 +*.pvdata
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
6 6
7 - Front-End : React 7 - Front-End : React
8 - Back-End : Express 8 - Back-End : Express
9 -- Storage : LocalForage 9 +- DataBase : MySQL
10 - Crawl : Puppeteer 10 - Crawl : Puppeteer
11 11
12 <br> 12 <br>
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
17 "express": "^4.18.1", 17 "express": "^4.18.1",
18 "fs": "^0.0.1-security", 18 "fs": "^0.0.1-security",
19 "localforage": "^1.10.0", 19 "localforage": "^1.10.0",
20 + "mysql": "^2.18.1",
20 "puppeteer": "^14.1.1", 21 "puppeteer": "^14.1.1",
21 "react": "^18.1.0", 22 "react": "^18.1.0",
22 "react-dom": "^18.1.0", 23 "react-dom": "^18.1.0",
...@@ -4904,6 +4905,14 @@ ...@@ -4904,6 +4905,14 @@
4904 "node": "*" 4905 "node": "*"
4905 } 4906 }
4906 }, 4907 },
4908 + "node_modules/bignumber.js": {
4909 + "version": "9.0.0",
4910 + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz",
4911 + "integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A==",
4912 + "engines": {
4913 + "node": "*"
4914 + }
4915 + },
4907 "node_modules/binary-extensions": { 4916 "node_modules/binary-extensions": {
4908 "version": "2.2.0", 4917 "version": "2.2.0",
4909 "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", 4918 "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
...@@ -11601,6 +11610,42 @@ ...@@ -11601,6 +11610,42 @@
11601 "multicast-dns": "cli.js" 11610 "multicast-dns": "cli.js"
11602 } 11611 }
11603 }, 11612 },
11613 + "node_modules/mysql": {
11614 + "version": "2.18.1",
11615 + "resolved": "https://registry.npmjs.org/mysql/-/mysql-2.18.1.tgz",
11616 + "integrity": "sha512-Bca+gk2YWmqp2Uf6k5NFEurwY/0td0cpebAucFpY/3jhrwrVGuxU2uQFCHjU19SJfje0yQvi+rVWdq78hR5lig==",
11617 + "dependencies": {
11618 + "bignumber.js": "9.0.0",
11619 + "readable-stream": "2.3.7",
11620 + "safe-buffer": "5.1.2",
11621 + "sqlstring": "2.3.1"
11622 + },
11623 + "engines": {
11624 + "node": ">= 0.6"
11625 + }
11626 + },
11627 + "node_modules/mysql/node_modules/readable-stream": {
11628 + "version": "2.3.7",
11629 + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
11630 + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
11631 + "dependencies": {
11632 + "core-util-is": "~1.0.0",
11633 + "inherits": "~2.0.3",
11634 + "isarray": "~1.0.0",
11635 + "process-nextick-args": "~2.0.0",
11636 + "safe-buffer": "~5.1.1",
11637 + "string_decoder": "~1.1.1",
11638 + "util-deprecate": "~1.0.1"
11639 + }
11640 + },
11641 + "node_modules/mysql/node_modules/string_decoder": {
11642 + "version": "1.1.1",
11643 + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
11644 + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
11645 + "dependencies": {
11646 + "safe-buffer": "~5.1.0"
11647 + }
11648 + },
11604 "node_modules/nanoid": { 11649 "node_modules/nanoid": {
11605 "version": "3.3.4", 11650 "version": "3.3.4",
11606 "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", 11651 "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz",
...@@ -14759,6 +14804,14 @@ ...@@ -14759,6 +14804,14 @@
14759 "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", 14804 "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
14760 "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" 14805 "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
14761 }, 14806 },
14807 + "node_modules/sqlstring": {
14808 + "version": "2.3.1",
14809 + "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz",
14810 + "integrity": "sha1-R1OT/56RR5rqYtyvDKPRSYOn+0A=",
14811 + "engines": {
14812 + "node": ">= 0.6"
14813 + }
14814 + },
14762 "node_modules/stable": { 14815 "node_modules/stable": {
14763 "version": "0.1.8", 14816 "version": "0.1.8",
14764 "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", 14817 "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz",
...@@ -20121,6 +20174,11 @@ ...@@ -20121,6 +20174,11 @@
20121 "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", 20174 "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz",
20122 "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==" 20175 "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ=="
20123 }, 20176 },
20177 + "bignumber.js": {
20178 + "version": "9.0.0",
20179 + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz",
20180 + "integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A=="
20181 + },
20124 "binary-extensions": { 20182 "binary-extensions": {
20125 "version": "2.2.0", 20183 "version": "2.2.0",
20126 "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", 20184 "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
...@@ -24974,6 +25032,41 @@ ...@@ -24974,6 +25032,41 @@
24974 "thunky": "^1.0.2" 25032 "thunky": "^1.0.2"
24975 } 25033 }
24976 }, 25034 },
25035 + "mysql": {
25036 + "version": "2.18.1",
25037 + "resolved": "https://registry.npmjs.org/mysql/-/mysql-2.18.1.tgz",
25038 + "integrity": "sha512-Bca+gk2YWmqp2Uf6k5NFEurwY/0td0cpebAucFpY/3jhrwrVGuxU2uQFCHjU19SJfje0yQvi+rVWdq78hR5lig==",
25039 + "requires": {
25040 + "bignumber.js": "9.0.0",
25041 + "readable-stream": "2.3.7",
25042 + "safe-buffer": "5.1.2",
25043 + "sqlstring": "2.3.1"
25044 + },
25045 + "dependencies": {
25046 + "readable-stream": {
25047 + "version": "2.3.7",
25048 + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
25049 + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
25050 + "requires": {
25051 + "core-util-is": "~1.0.0",
25052 + "inherits": "~2.0.3",
25053 + "isarray": "~1.0.0",
25054 + "process-nextick-args": "~2.0.0",
25055 + "safe-buffer": "~5.1.1",
25056 + "string_decoder": "~1.1.1",
25057 + "util-deprecate": "~1.0.1"
25058 + }
25059 + },
25060 + "string_decoder": {
25061 + "version": "1.1.1",
25062 + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
25063 + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
25064 + "requires": {
25065 + "safe-buffer": "~5.1.0"
25066 + }
25067 + }
25068 + }
25069 + },
24977 "nanoid": { 25070 "nanoid": {
24978 "version": "3.3.4", 25071 "version": "3.3.4",
24979 "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", 25072 "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz",
...@@ -27132,6 +27225,11 @@ ...@@ -27132,6 +27225,11 @@
27132 "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", 27225 "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
27133 "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" 27226 "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
27134 }, 27227 },
27228 + "sqlstring": {
27229 + "version": "2.3.1",
27230 + "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz",
27231 + "integrity": "sha1-R1OT/56RR5rqYtyvDKPRSYOn+0A="
27232 + },
27135 "stable": { 27233 "stable": {
27136 "version": "0.1.8", 27234 "version": "0.1.8",
27137 "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", 27235 "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz",
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
12 "express": "^4.18.1", 12 "express": "^4.18.1",
13 "fs": "^0.0.1-security", 13 "fs": "^0.0.1-security",
14 "localforage": "^1.10.0", 14 "localforage": "^1.10.0",
15 + "mysql": "^2.18.1",
15 "puppeteer": "^14.1.1", 16 "puppeteer": "^14.1.1",
16 "react": "^18.1.0", 17 "react": "^18.1.0",
17 "react-dom": "^18.1.0", 18 "react-dom": "^18.1.0",
......
...@@ -22,40 +22,43 @@ function parseICal(text) { ...@@ -22,40 +22,43 @@ function parseICal(text) {
22 const errArr = []; 22 const errArr = [];
23 function process(sche, k, v) { 23 function process(sche, k, v) {
24 switch (k) { 24 switch (k) {
25 - case "DTSTAMP":
26 - k = "CREATED";
27 - v = dateTimeToDate(v);
28 - break;
29 - case "UID":
30 - v = v.split("-")[2];
31 - break;
32 case "DTSTART": 25 case "DTSTART":
33 - k = "START"; 26 + sche.scheType = "time";
34 - v = dateTimeToDate(v); 27 + sche.date = getDatestr(v);
28 + k = "startTime";
29 + v = getTimestr(v);
35 break; 30 break;
36 case "DTEND": 31 case "DTEND":
37 - k = "END"; 32 + k = "endTime";
38 - v = dateTimeToDate(v); 33 + v = sche.startTime;
39 break; 34 break;
40 case "DTSTART;VALUE=DATE": 35 case "DTSTART;VALUE=DATE":
41 - case "DTEND;VALUE=DATE": 36 + sche.scheType = "date";
42 - k = "DATE"; 37 + k = "date";
43 - v = dateToDate(v); 38 + v = getDatestr(v);
44 break; 39 break;
40 + case "DTEND;VALUE=DATE":
41 + return;
45 case "X-ALT-DESC;FMTTYPE=text/html": 42 case "X-ALT-DESC;FMTTYPE=text/html":
46 - k = "DETAIL"; 43 + k = "detail";
47 break; 44 break;
48 case "SUMMARY": 45 case "SUMMARY":
49 - k = "LABEL"; 46 + k = "label";
50 - let b; 47 + v = v.substring(0, v.indexOf(" ["));
51 - [v, b] = v.split(" ["); 48 + break;
52 - sche["SUBJECT"] = b.substring(0, b.length - 1); 49 + case "UID":
50 + k = "uid";
51 + v = v.split("-")[2];
53 break; 52 break;
53 + case "DTSTAMP":
54 case "CLASS": 54 case "CLASS":
55 case "SEQUENCE": 55 case "SEQUENCE":
56 return; 56 return;
57 case "DESCRIPTION": 57 case "DESCRIPTION":
58 + k = "description";
58 case "URL": 59 case "URL":
60 + k = "url";
61 + sche.subjectID = v.substring(v.indexOf("se_") + 3, v.indexOf("&m"));
59 break; 62 break;
60 default: 63 default:
61 errArr.push(k); 64 errArr.push(k);
...@@ -70,19 +73,18 @@ function insert(str, idxs, char) { ...@@ -70,19 +73,18 @@ function insert(str, idxs, char) {
70 return nstr; 73 return nstr;
71 } 74 }
72 75
73 -function dateTimeToDate(str) { 76 +function getDatestr(str) {
74 - const [a, b] = str.split("T"); 77 + const a = str.substring(0, str.indexOf("T"));
75 - return new Date(insert(a, [4, 6, 8], "-") + "T" + insert(b, [2, 4, 6], ":")); 78 + return insert(a, [4, 6, 8], "-");
76 } 79 }
77 80
78 -function dateToDate(str) { 81 +function getTimestr(str) {
79 - return new Date(insert(str, [4, 6, 8], "-")); 82 + const b = str.substring(str.indexOf("T") + 1);
83 + return insert(b, [2, 4, 6], ":");
80 } 84 }
81 85
82 -// let result; 86 +// const fdata = fs.readFileSync("C:/Users/teddy/Downloads/data.ics", "utf8");
83 -// fs.readFile("C:/Users/teddy/Downloads/data.ics", "utf8", (err, data) => { 87 +// const jcal = parseICal(fdata);
84 -// if (err) console.log(err); 88 +// console("done");
85 -// else result = parseICal(data);
86 -// });
87 89
88 -export { parseICal }; 90 +module.exports = parseICal;
......
1 +const mysql = require("mysql");
2 +const fs = require("fs");
3 +const parseICal = require("./ICal");
4 +
5 +function jcalToSQL(jcal, userID) {
6 + const fsql = fs.readFileSync("server/libs/sql.pvdata", "utf8");
7 + const [id, pw] = fsql.split("\r\n");
8 + const connection = mysql.createConnection({
9 + host: "localhost",
10 + user: id,
11 + password: pw,
12 + database: "db",
13 + });
14 +
15 + connection.connect();
16 +
17 + const commonCols = [
18 + "uid",
19 + "label",
20 + "subjectID",
21 + "type",
22 + "description",
23 + "url",
24 + "detail",
25 + "status",
26 + ];
27 + const dateScheCols = [...commonCols, "date"];
28 + const timeScheCols = [...commonCols, "date", "startTime", "endTime"];
29 + const dateQueryString =
30 + "INSERT IGNORE INTO schedules_date (userID," +
31 + dateScheCols.join(",") +
32 + ") VALUES ?";
33 + const timeQueryString =
34 + "INSERT IGNORE INTO schedules_time (userID," +
35 + timeScheCols.join(",") +
36 + ") VALUES ?";
37 +
38 + const dateSchedules = [];
39 + const timeSchedules = [];
40 + for (const sche of jcal) {
41 + if (sche.scheType === "date") {
42 + dateSchedules.push([userID, ...dateScheCols.map((col) => sche[col])]);
43 + } else if (sche.scheType === "time") {
44 + timeSchedules.push([userID, ...timeScheCols.map((col) => sche[col])]);
45 + } else console.log("unexpected scheType", sche);
46 + }
47 +
48 + connection.query(dateQueryString, [dateSchedules], (error, result) => {
49 + if (error) console.log(error);
50 + else console.log(`schedules_date | ${result.affectedRows} rows added`);
51 + });
52 + connection.query(timeQueryString, [timeSchedules], (error, result) => {
53 + if (error) console.log(error);
54 + else console.log(`schedules_time | ${result.affectedRows} rows added`);
55 + });
56 +
57 + connection.end();
58 +}
59 +
60 +// iCal의 소유주를 DB에 등록 후 userID get
61 +// subjectID가 subjects, userID가 users에 있어야함
62 +const fdata = fs.readFileSync("C:/Users/teddy/Downloads/data.ics", "utf8");
63 +const jcal = parseICal(fdata);
64 +jcalToSQL(jcal, 1);
65 +
66 +module.exports = jcalToSQL;