Showing
8 changed files
with
172 additions
and
99 deletions
1 | const puppeteer = require("puppeteer"); | 1 | const puppeteer = require("puppeteer"); |
2 | //use puppeteer | 2 | //use puppeteer |
3 | -Info = { | ||
4 | - id : "null", | ||
5 | - pw : "null", | ||
6 | - peed : "null", | ||
7 | - subjects : [] | ||
8 | -} | ||
9 | - | ||
10 | -function setTimeoutPromise(ms) { | ||
11 | - return new Promise((resolve, reject) => { | ||
12 | - setTimeout(() => resolve(), ms); | ||
13 | - }); | ||
14 | -} | ||
15 | 3 | ||
16 | async function login(id, pw) { | 4 | async function login(id, pw) { |
17 | try { | 5 | try { |
18 | //for visibility, headless: false | 6 | //for visibility, headless: false |
19 | - browser = await puppeteer.launch({ | 7 | + const browser = await puppeteer.launch({ |
20 | headless: false, | 8 | headless: false, |
21 | args: [ | 9 | args: [ |
22 | "--window-size=1920x1080", | 10 | "--window-size=1920x1080", |
... | @@ -27,7 +15,7 @@ async function login(id, pw) { | ... | @@ -27,7 +15,7 @@ async function login(id, pw) { |
27 | ], | 15 | ], |
28 | }); | 16 | }); |
29 | 17 | ||
30 | - const page = await browser.newPage(); | 18 | + const [page] = await browser.pages(); |
31 | await page.setViewport({ | 19 | await page.setViewport({ |
32 | width: 1920, | 20 | width: 1920, |
33 | height: 1080, | 21 | height: 1080, |
... | @@ -44,7 +32,7 @@ async function login(id, pw) { | ... | @@ -44,7 +32,7 @@ async function login(id, pw) { |
44 | page.waitForNavigation(), | 32 | page.waitForNavigation(), |
45 | ]); | 33 | ]); |
46 | 34 | ||
47 | - //When login is failed, return {err: "Incorrect~"} | 35 | + //When login is failed, return false |
48 | if ( | 36 | if ( |
49 | page.url() === | 37 | page.url() === |
50 | "https://e-campus.khu.ac.kr/xn-sso/gw-cb.php?from=&login_type=standalone&return_url=https%3A%2F%2Fe-campus.khu.ac.kr%2Flogin%2Fcallback" | 38 | "https://e-campus.khu.ac.kr/xn-sso/gw-cb.php?from=&login_type=standalone&return_url=https%3A%2F%2Fe-campus.khu.ac.kr%2Flogin%2Fcallback" |
... | @@ -57,22 +45,28 @@ async function login(id, pw) { | ... | @@ -57,22 +45,28 @@ async function login(id, pw) { |
57 | // "#visual > div > div.xn-main-login-container > div:nth-child(2) > div.xn-main-link-wrap.xn-main-lms-link-wrap > a"; | 45 | // "#visual > div > div.xn-main-login-container > div:nth-child(2) > div.xn-main-link-wrap.xn-main-lms-link-wrap > a"; |
58 | // await page.waitForSelector(selector); | 46 | // await page.waitForSelector(selector); |
59 | // await Promise.all([page.click(selector), page.waitForNavigation()]); | 47 | // await Promise.all([page.click(selector), page.waitForNavigation()]); |
60 | - const promise1 = Promise.resolve(); | 48 | + |
61 | - promise1.then(value => { | ||
62 | - Info.id = id; | ||
63 | - Info.pw = pw; | ||
64 | - }) | ||
65 | await page.goto("https://khcanvas.khu.ac.kr/"); | 49 | await page.goto("https://khcanvas.khu.ac.kr/"); |
66 | - return page; | 50 | + |
51 | + let selector = "#global_nav_profile_link"; | ||
52 | + await page.waitForSelector(selector); | ||
53 | + await page.click(selector); | ||
54 | + | ||
55 | + const peed = await getPeed(page); | ||
56 | + const subjects = await getSubjects(page); | ||
57 | + browser.close(); | ||
58 | + return { peed, subjects }; | ||
67 | } | 59 | } |
68 | } catch (err) { | 60 | } catch (err) { |
69 | console.log(err); | 61 | console.log(err); |
62 | + return "error"; | ||
70 | } | 63 | } |
71 | } | 64 | } |
72 | 65 | ||
73 | //function that get your peed for your Ecampus calendar | 66 | //function that get your peed for your Ecampus calendar |
74 | async function getPeed(page) { | 67 | async function getPeed(page) { |
75 | - selector = "#global_nav_calendar_link > div.menu-item-icon-container > svg"; | 68 | + let selector = |
69 | + "#global_nav_calendar_link > div.menu-item-icon-container > svg"; | ||
76 | await page.waitForSelector(selector, { timeout: 1000 }); | 70 | await page.waitForSelector(selector, { timeout: 1000 }); |
77 | await Promise.all([page.click(selector), page.waitForNavigation()]); | 71 | await Promise.all([page.click(selector), page.waitForNavigation()]); |
78 | 72 | ||
... | @@ -88,12 +82,14 @@ async function getPeed(page) { | ... | @@ -88,12 +82,14 @@ async function getPeed(page) { |
88 | data.link = await page.evaluate((data) => { | 82 | data.link = await page.evaluate((data) => { |
89 | return data.href; | 83 | return data.href; |
90 | }, temp); | 84 | }, temp); |
91 | - // console.log(Promise.resolve(data)); | 85 | + |
92 | - const promise2 = Promise.resolve(data.link); | 86 | + //close the peed window to get subjects |
93 | - promise2.then(value => { | 87 | + selector = |
94 | - Info.peed = value; | 88 | + "body > div:nth-child(9) > div.ui-dialog-titlebar.ui-widget-header.ui-corner-all.ui-helper-clearfix > button"; |
95 | - }) | 89 | + await page.waitForSelector(selector, { timeout: 1000 }); |
96 | - return Promise.resolve(data); | 90 | + await page.keyboard.press("Escape"); |
91 | + | ||
92 | + return data.link; | ||
97 | 93 | ||
98 | // let temp = await page.$("#calendar-feed-box-lower > a"); | 94 | // let temp = await page.$("#calendar-feed-box-lower > a"); |
99 | // const feed = await page.evaluate((data) => data.href, temp); | 95 | // const feed = await page.evaluate((data) => data.href, temp); |
... | @@ -107,28 +103,19 @@ async function getPeed(page) { | ... | @@ -107,28 +103,19 @@ async function getPeed(page) { |
107 | } | 103 | } |
108 | 104 | ||
109 | async function getSubjects(page) { | 105 | async function getSubjects(page) { |
110 | - //close the peed window to get subjects | 106 | + let selector = |
111 | - await page.click('body > div:nth-child(9) > div.ui-dialog-titlebar.ui-widget-header.ui-corner-all.ui-helper-clearfix > button > span'); | 107 | + "#global_nav_courses_link > div.menu-item-icon-container > svg"; |
112 | - await page.waitForTimeout(500); | 108 | + await page.waitForSelector(selector); |
113 | - await page.click( | 109 | + await page.click(selector); |
114 | - "#global_nav_courses_link > div.menu-item-icon-container > svg" | ||
115 | - ); | ||
116 | 110 | ||
117 | let data = []; | 111 | let data = []; |
118 | - let selector = | 112 | + selector = |
119 | "#nav-tray-portal > span > span > div > div > div > div > div > ul:nth-child(3) > li"; | 113 | "#nav-tray-portal > span > span > div > div > div > div > div > ul:nth-child(3) > li"; |
120 | await page.waitForSelector(selector); | 114 | await page.waitForSelector(selector); |
121 | const number = await page.$$eval(selector, (data) => data.length); | 115 | const number = await page.$$eval(selector, (data) => data.length); |
122 | for (let index = 0; index < number; index++) { | 116 | for (let index = 0; index < number; index++) { |
123 | data.push(await getOne(page, index + 1)); | 117 | data.push(await getOne(page, index + 1)); |
124 | } | 118 | } |
125 | - const promise3 = Promise.resolve(data); | ||
126 | - promise3.then(value => { | ||
127 | - // Info.subjects = value; | ||
128 | - for (let index = 0; index < value.length; index++) { | ||
129 | - Info.subjects.push(value[index].name) | ||
130 | - } | ||
131 | - }) | ||
132 | return data; | 119 | return data; |
133 | } | 120 | } |
134 | 121 | ||
... | @@ -147,19 +134,7 @@ async function getOne(page, index) { | ... | @@ -147,19 +134,7 @@ async function getOne(page, index) { |
147 | }, temp); | 134 | }, temp); |
148 | // data.subjectName = await page.$eval("#nav-tray-portal > span > span > div > div > div > div > div > ul:nth-child(3) > li:nth-child(" + index + ") > a", (data) => data.textContent); | 135 | // data.subjectName = await page.$eval("#nav-tray-portal > span > span > div > div > div > div > div > ul:nth-child(3) > li:nth-child(" + index + ") > a", (data) => data.textContent); |
149 | // data.subjectLink = await page.$eval("#nav-tray-portal > span > span > div > div > div > div > div > ul:nth-child(3) > li:nth-child(" + index + ") > a", (data) => data.href); | 136 | // data.subjectLink = await page.$eval("#nav-tray-portal > span > span > div > div > div > div > div > ul:nth-child(3) > li:nth-child(" + index + ") > a", (data) => data.href); |
150 | - return Promise.resolve(data); | 137 | + return data; |
151 | -} | ||
152 | - | ||
153 | -async function close() { | ||
154 | - browser.close(); | ||
155 | } | 138 | } |
156 | 139 | ||
157 | - | ||
158 | exports.login = login; | 140 | exports.login = login; |
159 | -exports.getPeed = getPeed; | ||
160 | -exports.getSubjects = getSubjects; | ||
161 | -exports.close = close; | ||
162 | - | ||
163 | - | ||
164 | - | ||
165 | - | ... | ... |
... | @@ -3,17 +3,22 @@ const mysql2 = require("mysql2/promise"); | ... | @@ -3,17 +3,22 @@ const mysql2 = require("mysql2/promise"); |
3 | const fs = require("fs"); | 3 | const fs = require("fs"); |
4 | const parseICal = require("./ICal"); | 4 | const parseICal = require("./ICal"); |
5 | 5 | ||
6 | -function jcalToSQL(jcal, userID) { | 6 | +const [id, pw] = fs |
7 | - const fsql = fs.readFileSync("server/libs/sql.pvdata", "utf8"); | 7 | + .readFileSync("server/libs/sql.pvdata", "utf8") |
8 | - const [id, pw] = fsql.split("\r\n"); | 8 | + .split("\r\n"); |
9 | - const connection = mysql.createConnection({ | 9 | +const connectOption = { |
10 | host: "localhost", | 10 | host: "localhost", |
11 | user: id, | 11 | user: id, |
12 | password: pw, | 12 | password: pw, |
13 | database: "db", | 13 | database: "db", |
14 | - }); | 14 | +}; |
15 | 15 | ||
16 | - connection.connect(); | 16 | +async function jcalToSQL(jcal, userID) { |
17 | + // const fsql = fs.readFileSync("server/libs/sql.pvdata", "utf8"); | ||
18 | + // const [id, pw] = fsql.split("\r\n"); | ||
19 | + const connection = await mysql2.createConnection(connectOption); | ||
20 | + | ||
21 | + await connection.connect(); | ||
17 | 22 | ||
18 | const commonCols = [ | 23 | const commonCols = [ |
19 | "userID", | 24 | "userID", |
... | @@ -48,14 +53,11 @@ function jcalToSQL(jcal, userID) { | ... | @@ -48,14 +53,11 @@ function jcalToSQL(jcal, userID) { |
48 | else console.log("unexpected scheType", sche); | 53 | else console.log("unexpected scheType", sche); |
49 | } | 54 | } |
50 | 55 | ||
51 | - connection.query(dateQueryString, [dateSchedules], (error, result) => { | 56 | + let result = await connection.query(dateQueryString, [dateSchedules]); |
52 | - if (error) console.log(error); | 57 | + console.log(`schedules_date | ${result}`); |
53 | - else console.log(`schedules_date | ${result.affectedRows} rows added`); | 58 | + |
54 | - }); | 59 | + result = await connection.query(timeQueryString, [timeSchedules]); |
55 | - connection.query(timeQueryString, [timeSchedules], (error, result) => { | 60 | + console.log(`schedules_time | ${result}`); |
56 | - if (error) console.log(error); | ||
57 | - else console.log(`schedules_time | ${result.affectedRows} rows added`); | ||
58 | - }); | ||
59 | 61 | ||
60 | connection.end(); | 62 | connection.end(); |
61 | } | 63 | } |
... | @@ -67,14 +69,4 @@ function jcalToSQL(jcal, userID) { | ... | @@ -67,14 +69,4 @@ function jcalToSQL(jcal, userID) { |
67 | // const jcal = parseICal(fdata); | 69 | // const jcal = parseICal(fdata); |
68 | // jcalToSQL(jcal, 1); | 70 | // jcalToSQL(jcal, 1); |
69 | 71 | ||
70 | -const [id, pw] = fs | ||
71 | - .readFileSync("server/libs/sql.pvdata", "utf8") | ||
72 | - .split("\r\n"); | ||
73 | -const connectOption = { | ||
74 | - host: "localhost", | ||
75 | - user: id, | ||
76 | - password: pw, | ||
77 | - database: "db", | ||
78 | -}; | ||
79 | - | ||
80 | module.exports = { jcalToSQL, connectOption }; | 72 | module.exports = { jcalToSQL, connectOption }; | ... | ... |
1 | +const { default: axios } = require("axios"); | ||
1 | const express = require("express"); | 2 | const express = require("express"); |
2 | const router = express.Router(); | 3 | const router = express.Router(); |
3 | 4 | ||
4 | -const { getPeed, getSubjects, login, close } = require("./E_Campus.js"); | 5 | +const { login } = require("./E_Campus.js"); |
6 | +const parseICal = require("./ICal.js"); | ||
5 | 7 | ||
6 | async function runrun() { | 8 | async function runrun() { |
7 | - page = await login("lorem", "lorem"); | ||
8 | - await getPeed(page); | ||
9 | - await getSubjects(page); | ||
10 | - await close(); | ||
11 | - console.log(Info); | ||
12 | - console.log(Info.subjects) | ||
13 | - | ||
14 | - } | ||
15 | - runrun(); | ||
16 | - | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
9 | + const { data: ical } = await axios({ | ||
10 | + url: "https://khcanvas.khu.ac.kr/feeds/calendars/user_YzxoryVh1hAQTeUJRljeaYavgmw1OXEGKIzNVpnI.ics", | ||
11 | + method: "GET", | ||
12 | + responseType: "blob", | ||
13 | + }); | ||
14 | + const Jcal = parseICal(ical); | ||
15 | + console.log(Jcal); | ||
16 | +} | ||
17 | +runrun(); | ... | ... |
... | @@ -20,6 +20,27 @@ async function route() { | ... | @@ -20,6 +20,27 @@ async function route() { |
20 | res.end(); | 20 | res.end(); |
21 | } | 21 | } |
22 | }); | 22 | }); |
23 | + | ||
24 | + // [{name, link}, ...] | ||
25 | + subjectsRouter.post("/s", async (req, res) => { | ||
26 | + console.log("post /db/subjects/s"); | ||
27 | + try { | ||
28 | + const subList = []; | ||
29 | + for (const s of req.body.list) { | ||
30 | + const subjectID = s.link.split("courses/")[1]; | ||
31 | + const queryString = ` | ||
32 | + INSERT IGNORE INTO subjects | ||
33 | + (ID, name) | ||
34 | + VALUES (${subjectID},' ${s.name}')`; | ||
35 | + await connection.query(queryString); | ||
36 | + subList.push({ name: s.name, subjectID }); | ||
37 | + } | ||
38 | + res.send(subList); | ||
39 | + } catch (e) { | ||
40 | + console.log(e); | ||
41 | + res.end(); | ||
42 | + } | ||
43 | + }); | ||
23 | } | 44 | } |
24 | route(); | 45 | route(); |
25 | 46 | ... | ... |
... | @@ -58,6 +58,36 @@ async function route() { | ... | @@ -58,6 +58,36 @@ async function route() { |
58 | res.end(); | 58 | res.end(); |
59 | } | 59 | } |
60 | }); | 60 | }); |
61 | + | ||
62 | + // (userID, [subjectID, ...]) | ||
63 | + userSubjectRouter.post("/s", async (req, res) => { | ||
64 | + console.log("post /db/user-subject/s"); | ||
65 | + const colors = [ | ||
66 | + "3ADF00", | ||
67 | + "0040FF", | ||
68 | + "FF0000", | ||
69 | + "FFFF00", | ||
70 | + "FF00FF", | ||
71 | + "FF8000", | ||
72 | + "6E6E6E", | ||
73 | + "8000FF", | ||
74 | + "B40431", | ||
75 | + "2EFEF7", | ||
76 | + ]; | ||
77 | + try { | ||
78 | + for (const i in req.body.subList) { | ||
79 | + const queryString = ` | ||
80 | + INSERT INTO \`user-subject\` | ||
81 | + (userID, subjectID, status, color) | ||
82 | + VALUES (${req.body.userID}, ${req.body.subList[i].subjectID}, 1, '${colors[i]}')`; | ||
83 | + await connection.query(queryString); | ||
84 | + } | ||
85 | + res.end(); | ||
86 | + } catch (e) { | ||
87 | + console.log(e); | ||
88 | + res.end(); | ||
89 | + } | ||
90 | + }); | ||
61 | } | 91 | } |
62 | route(); | 92 | route(); |
63 | 93 | ... | ... |
1 | +const cryptoJs = require("crypto-js"); | ||
1 | const express = require("express"); | 2 | const express = require("express"); |
2 | const mysql2 = require("mysql2/promise"); | 3 | const mysql2 = require("mysql2/promise"); |
3 | const { connectOption } = require("../libs/MySQL"); | 4 | const { connectOption } = require("../libs/MySQL"); |
... | @@ -35,6 +36,26 @@ async function route() { | ... | @@ -35,6 +36,26 @@ async function route() { |
35 | res.end(); | 36 | res.end(); |
36 | } | 37 | } |
37 | }); | 38 | }); |
39 | + | ||
40 | + // (loginID, loginPW, name, ical) => ID | ||
41 | + usersRouter.post("/", async (req, res) => { | ||
42 | + console.log("post /db/users/"); | ||
43 | + try { | ||
44 | + const hashpw = cryptoJs.SHA256(req.body.loginPW).toString(); | ||
45 | + let queryString = ` | ||
46 | + INSERT INTO users | ||
47 | + (loginID, loginPW, name, ical) | ||
48 | + VALUES ('${req.body.loginID}', '${hashpw}', '${req.body.name}', '${req.body.ical}')`; | ||
49 | + await connection.query(queryString); | ||
50 | + | ||
51 | + queryString = `SELECT LAST_INSERT_ID() ID`; | ||
52 | + const [results] = await connection.query(queryString); | ||
53 | + res.send(results[0]); | ||
54 | + } catch (e) { | ||
55 | + console.log(e); | ||
56 | + res.end(); | ||
57 | + } | ||
58 | + }); | ||
38 | } | 59 | } |
39 | route(); | 60 | route(); |
40 | 61 | ... | ... |
1 | +const axios = require("axios"); | ||
1 | const express = require("express"); | 2 | const express = require("express"); |
2 | const router = express.Router(); | 3 | const router = express.Router(); |
3 | 4 | ||
4 | -const { getPeed, getSubjects, login, close } = require("../libs/E_Campus.js"); | 5 | +const { login } = require("../libs/E_Campus.js"); |
6 | +const parseICal = require("../libs/ICal.js"); | ||
7 | +const { jcalToSQL } = require("../libs/MySQL.js"); | ||
5 | 8 | ||
9 | +// (id, pw) => failed | error | {peed, subjects, name, ID} | ||
6 | router.post("/", async (req, res) => { | 10 | router.post("/", async (req, res) => { |
7 | console.log(`listened /login ${req.body.id} ${req.body.pw}`); | 11 | console.log(`listened /login ${req.body.id} ${req.body.pw}`); |
8 | - const page = await login(req.body.id, req.body.pw); | 12 | + const result = await login(req.body.id, req.body.pw); |
9 | - if (page) { | 13 | + if (result && result !== "error") { |
10 | try { | 14 | try { |
11 | - res.send("success"); | 15 | + const { peed, subjects } = result; |
16 | + | ||
17 | + const resUser = await axios.post("http://localhost:3001/db/users", { | ||
18 | + loginID: req.body.id, | ||
19 | + loginPW: req.body.pw, | ||
20 | + ical: peed, | ||
21 | + }); | ||
22 | + const userID = resUser.data.ID; | ||
23 | + const { data: subList } = await axios.post( | ||
24 | + "http://localhost:3001/db/subjects/s", | ||
25 | + { | ||
26 | + list: subjects, | ||
27 | + } | ||
28 | + ); | ||
29 | + await axios.post("http://localhost:3001/db/user-subject/s", { | ||
30 | + userID, | ||
31 | + subList, | ||
32 | + }); | ||
33 | + const { data: ical } = await axios({ | ||
34 | + url: peed, | ||
35 | + method: "GET", | ||
36 | + responseType: "blob", | ||
37 | + }); | ||
38 | + await jcalToSQL(parseICal(ical), userID); | ||
39 | + res.send({ userID }); | ||
12 | } catch (e) { | 40 | } catch (e) { |
13 | console.log(e); | 41 | console.log(e); |
14 | res.send("error"); | 42 | res.send("error"); |
15 | } | 43 | } |
16 | - } else res.send("failed"); | 44 | + } else res.send(result ? "failed" : "error"); |
17 | }); | 45 | }); |
18 | 46 | ||
19 | module.exports = router; | 47 | module.exports = router; | ... | ... |
... | @@ -45,7 +45,9 @@ const Login = () => { | ... | @@ -45,7 +45,9 @@ const Login = () => { |
45 | if (isCorrectPW) await localforage.setItem("userID", Number(userDBID)); | 45 | if (isCorrectPW) await localforage.setItem("userID", Number(userDBID)); |
46 | else { | 46 | else { |
47 | setState({ ...state, btn: "Login" }); | 47 | setState({ ...state, btn: "Login" }); |
48 | - alert("ID/PW를 확인해주세요"); | 48 | + alert( |
49 | + "등록된 ID/PW와 다릅니다\n(비밀번호가 변경되었다면 관리자에게 문의하세요)" | ||
50 | + ); | ||
49 | return; | 51 | return; |
50 | } | 52 | } |
51 | } else { | 53 | } else { |
... | @@ -57,14 +59,17 @@ const Login = () => { | ... | @@ -57,14 +59,17 @@ const Login = () => { |
57 | pw: state.pw, | 59 | pw: state.pw, |
58 | } | 60 | } |
59 | ); | 61 | ); |
60 | - if (loginResult === "login failed") { | 62 | + if (loginResult === "failed") { |
61 | setState({ ...state, btn: "Login" }); | 63 | setState({ ...state, btn: "Login" }); |
62 | alert("ID/PW를 확인해주세요"); | 64 | alert("ID/PW를 확인해주세요"); |
63 | return; | 65 | return; |
66 | + } else if (loginResult === "error") { | ||
67 | + setState({ ...state, btn: "Login" }); | ||
68 | + alert("다시 시도해 주세요"); | ||
69 | + return; | ||
64 | } | 70 | } |
65 | - // + else (성공시) localforage에 userID추가 | 71 | + await localforage.setItem("userID", loginResult.userID); |
66 | } | 72 | } |
67 | - // + localforage에 id pw 추가 | ||
68 | await localforage.setItem("id", state.id); | 73 | await localforage.setItem("id", state.id); |
69 | await localforage.setItem("pw", state.pw); | 74 | await localforage.setItem("pw", state.pw); |
70 | await localforage.setItem("session", true); | 75 | await localforage.setItem("session", true); | ... | ... |
-
Please register or login to post a comment