Showing
23 changed files
with
299 additions
and
25 deletions
No preview for this file type
No preview for this file type
... | @@ -15,11 +15,11 @@ http://khuhub.khu.ac.kr/MotherProject/Jaksimsamil | ... | @@ -15,11 +15,11 @@ http://khuhub.khu.ac.kr/MotherProject/Jaksimsamil |
15 | > 작심삼일 알고리즘 문제풀이 도우미 서비스<br/> | 15 | > 작심삼일 알고리즘 문제풀이 도우미 서비스<br/> |
16 | > | 16 | > |
17 | > > 알고리즘 문제 풀이 스터디를 꾸준히 할 수 있게 돕는 웹 서비스입니다. | 17 | > > 알고리즘 문제 풀이 스터디를 꾸준히 할 수 있게 돕는 웹 서비스입니다. |
18 | -> > <br> [링크](http://ossfinal.com)에서 직접 사용해 보세요! | 18 | +> > <br> [링크](http://www.ossjaksimsamil.ml:3000)에서 직접 사용해 보세요! |
19 | 19 | ||
20 | - | 20 | + |
21 | 21 | ||
22 | - | 22 | + |
23 | 23 | ||
24 | # 기존 프로젝트의 기능 | 24 | # 기존 프로젝트의 기능 |
25 | 25 | ||
... | @@ -40,7 +40,7 @@ http://khuhub.khu.ac.kr/MotherProject/Jaksimsamil | ... | @@ -40,7 +40,7 @@ http://khuhub.khu.ac.kr/MotherProject/Jaksimsamil |
40 | - 개선된 문제 추천 (사용자 실력 맞춤형) | 40 | - 개선된 문제 추천 (사용자 실력 맞춤형) |
41 | 41 | ||
42 | # 기존의 마더 프로젝트에 새롭게 추가한 기능 | 42 | # 기존의 마더 프로젝트에 새롭게 추가한 기능 |
43 | - -카카오 api를 이용한 문제추천 알림 | 43 | + -line 챗봇을 이용한 문제추천 알림 |
44 | 44 | ||
45 | 45 | ||
46 | ## Usages | 46 | ## Usages |
... | @@ -62,7 +62,7 @@ http://khuhub.khu.ac.kr/MotherProject/Jaksimsamil | ... | @@ -62,7 +62,7 @@ http://khuhub.khu.ac.kr/MotherProject/Jaksimsamil |
62 | 1. Clone | 62 | 1. Clone |
63 | 63 | ||
64 | ``` | 64 | ``` |
65 | -git clone http://khuhub.khu.ac.kr/2020-2_open_source_sw_development_Han/JaksimSamil_Develop.git | 65 | +git clone http://khuhub.khu.ac.kr/2020-2_open_source_sw_development_Han/Jaksimsamil.git |
66 | ``` | 66 | ``` |
67 | 67 | ||
68 | 2. Install MongoDB(Ubuntu) | 68 | 2. Install MongoDB(Ubuntu) |
... | @@ -89,7 +89,6 @@ touch .env | ... | @@ -89,7 +89,6 @@ touch .env |
89 | SERVER_PORT= ### | 89 | SERVER_PORT= ### |
90 | MONGO_URL= ### | 90 | MONGO_URL= ### |
91 | JWT_SECRET= ### | 91 | JWT_SECRET= ### |
92 | -KAKAO_JS_KEY = ### | ||
93 | ``` | 92 | ``` |
94 | 93 | ||
95 | 4. Start Node Server | 94 | 4. Start Node Server | ... | ... |
jaksimsamil-page/.eslintcache
0 → 100644
This diff is collapsed. Click to expand it.
This diff could not be displayed because it is too large.
... | @@ -3,25 +3,33 @@ | ... | @@ -3,25 +3,33 @@ |
3 | "version": "0.1.0", | 3 | "version": "0.1.0", |
4 | "private": true, | 4 | "private": true, |
5 | "dependencies": { | 5 | "dependencies": { |
6 | + | ||
7 | + "@material-ui/core": "^4.11.2", | ||
8 | + "@testing-library/jest-dom": "^5.11.6", | ||
9 | + "@testing-library/react": "^11.2.2", | ||
10 | + "@testing-library/user-event": "^12.5.0", | ||
11 | + "axios": "^0.21.0", | ||
12 | + "immer": "^8.0.0", | ||
6 | "@material-ui/core": "^4.10.2", | 13 | "@material-ui/core": "^4.10.2", |
7 | "@testing-library/jest-dom": "^4.2.4", | 14 | "@testing-library/jest-dom": "^4.2.4", |
8 | "@testing-library/react": "^9.3.2", | 15 | "@testing-library/react": "^9.3.2", |
9 | "@testing-library/user-event": "^7.1.2", | 16 | "@testing-library/user-event": "^7.1.2", |
10 | "axios": "^0.19.2", | 17 | "axios": "^0.19.2", |
18 | + "eslint": "^7.14.0", | ||
11 | "immer": "^7.0.5", | 19 | "immer": "^7.0.5", |
12 | "include-media": "^1.4.9", | 20 | "include-media": "^1.4.9", |
13 | - "moment": "^2.27.0", | 21 | + "moment": "^2.29.1", |
14 | "open-color": "^1.7.0", | 22 | "open-color": "^1.7.0", |
15 | - "react": "^16.13.1", | 23 | + "react": "^17.0.1", |
16 | - "react-dom": "^16.13.1", | 24 | + "react-dom": "^17.0.1", |
17 | - "react-redux": "^7.2.0", | 25 | + "react-redux": "^7.2.2", |
18 | "react-router-dom": "^5.2.0", | 26 | "react-router-dom": "^5.2.0", |
19 | - "react-scripts": "3.4.1", | 27 | + "react-scripts": "4.0.1", |
20 | "redux": "^4.0.5", | 28 | "redux": "^4.0.5", |
21 | "redux-actions": "^2.6.5", | 29 | "redux-actions": "^2.6.5", |
22 | "redux-devtools-extension": "^2.13.8", | 30 | "redux-devtools-extension": "^2.13.8", |
23 | "redux-saga": "^1.1.3", | 31 | "redux-saga": "^1.1.3", |
24 | - "styled-components": "^5.1.1" | 32 | + "styled-components": "^5.2.1" |
25 | }, | 33 | }, |
26 | "scripts": { | 34 | "scripts": { |
27 | "start": "react-scripts start", | 35 | "start": "react-scripts start", |
... | @@ -30,7 +38,10 @@ | ... | @@ -30,7 +38,10 @@ |
30 | "eject": "react-scripts eject" | 38 | "eject": "react-scripts eject" |
31 | }, | 39 | }, |
32 | "eslintConfig": { | 40 | "eslintConfig": { |
33 | - "extends": "react-app" | 41 | + "extends": "react-app", |
42 | + "rules": { | ||
43 | + "jsx-a11y/anchor-is-valid": "off" | ||
44 | + } | ||
34 | }, | 45 | }, |
35 | "browserslist": { | 46 | "browserslist": { |
36 | "production": [ | 47 | "production": [ |
... | @@ -44,6 +55,5 @@ | ... | @@ -44,6 +55,5 @@ |
44 | "last 1 safari version" | 55 | "last 1 safari version" |
45 | ] | 56 | ] |
46 | }, | 57 | }, |
47 | - "proxy": "http://localhost:4000", | 58 | + "proxy": "http://localhost:4000" |
48 | - "secure" : false | ||
49 | } | 59 | } | ... | ... |
... | @@ -25,6 +25,10 @@ | ... | @@ -25,6 +25,10 @@ |
25 | Learn how to configure a non-root public URL by running `npm run build`. | 25 | Learn how to configure a non-root public URL by running `npm run build`. |
26 | --> | 26 | --> |
27 | <title>React App</title> | 27 | <title>React App</title> |
28 | + <script src ="https://developers.kakao.com/sdk/js/kakao.min.js"></script> | ||
29 | + <script type = "text/javascript"> | ||
30 | + Kakao.init("9454fd9d91effc97b064c201f04586d2"); | ||
31 | + </script> | ||
28 | </head> | 32 | </head> |
29 | <body> | 33 | <body> |
30 | <noscript>You need to enable JavaScript to run this app.</noscript> | 34 | <noscript>You need to enable JavaScript to run this app.</noscript> | ... | ... |
... | @@ -3,7 +3,7 @@ import { makeStyles } from '@material-ui/core/styles'; | ... | @@ -3,7 +3,7 @@ import { makeStyles } from '@material-ui/core/styles'; |
3 | import Paper from '@material-ui/core/Paper'; | 3 | import Paper from '@material-ui/core/Paper'; |
4 | import Grid from '@material-ui/core/Grid'; | 4 | import Grid from '@material-ui/core/Grid'; |
5 | import palette from '../../lib/styles/palette'; | 5 | import palette from '../../lib/styles/palette'; |
6 | -import AuthForm from '../auth/AuthForm'; | 6 | + |
7 | const useStyles = makeStyles((theme) => ({ | 7 | const useStyles = makeStyles((theme) => ({ |
8 | root: { | 8 | root: { |
9 | flexGrow: 1, | 9 | flexGrow: 1, | ... | ... |
... | @@ -8,6 +8,7 @@ import Paper from '@material-ui/core/Paper'; | ... | @@ -8,6 +8,7 @@ import Paper from '@material-ui/core/Paper'; |
8 | import Grid from '@material-ui/core/Grid'; | 8 | import Grid from '@material-ui/core/Grid'; |
9 | import CircularProgress from '@material-ui/core/CircularProgress'; | 9 | import CircularProgress from '@material-ui/core/CircularProgress'; |
10 | import styled from 'styled-components'; | 10 | import styled from 'styled-components'; |
11 | +import LineQR from './LineQR' | ||
11 | 12 | ||
12 | const useStyles = makeStyles((theme) => ({ | 13 | const useStyles = makeStyles((theme) => ({ |
13 | root: { | 14 | root: { |
... | @@ -80,6 +81,14 @@ const SettingForm = ({ | ... | @@ -80,6 +81,14 @@ const SettingForm = ({ |
80 | /> | 81 | /> |
81 | </Paper> | 82 | </Paper> |
82 | </Grid> | 83 | </Grid> |
84 | + | ||
85 | + <Grid container item xs={6}> | ||
86 | + <Paper className={classes.paper} elevation={3}> | ||
87 | + <h1>QR코드를 찍어주세요</h1> | ||
88 | + <LineQR></LineQR> | ||
89 | + </Paper> | ||
90 | + </Grid> | ||
91 | + | ||
83 | </Grid> | 92 | </Grid> |
84 | </div> | 93 | </div> |
85 | ); | 94 | ); | ... | ... |
... | @@ -75,7 +75,7 @@ const SettingContainer = ({ history }) => { | ... | @@ -75,7 +75,7 @@ const SettingContainer = ({ history }) => { |
75 | } | 75 | } |
76 | }, [dispatch, user, history]); | 76 | }, [dispatch, user, history]); |
77 | useEffect(() => { | 77 | useEffect(() => { |
78 | - if (loading['profile/SYNC_BJID'] == true) { | 78 | + if (loading['profile/SYNC_BJID']) { |
79 | setLoading(true); | 79 | setLoading(true); |
80 | } else { | 80 | } else { |
81 | setLoading(false); | 81 | setLoading(false); | ... | ... |
... | @@ -12,15 +12,15 @@ | ... | @@ -12,15 +12,15 @@ |
12 | ``` | 12 | ``` |
13 | npm install | 13 | npm install |
14 | npm update | 14 | npm update |
15 | -node index.js | 15 | +npm start |
16 | ``` | 16 | ``` |
17 | 17 | ||
18 | ## Example | 18 | ## Example |
19 | 19 | ||
20 | ``` | 20 | ``` |
21 | -POST http://facerain.dcom.club/profile/getprofile | 21 | +POST http://www.ossjaksimsamil.ml:3000/profile/getprofile |
22 | { | 22 | { |
23 | - username: 'syw5141', | 23 | + username : 'redbean096' |
24 | } | 24 | } |
25 | ``` | 25 | ``` |
26 | 26 | ||
... | @@ -40,3 +40,6 @@ POST http://facerain.dcom.club/profile/getprofile | ... | @@ -40,3 +40,6 @@ POST http://facerain.dcom.club/profile/getprofile |
40 | | auth | 로그아웃 | POST | api/auth/logout | [바로가기](/src/api/auth/README.md) | JWT Token | | 40 | | auth | 로그아웃 | POST | api/auth/logout | [바로가기](/src/api/auth/README.md) | JWT Token | |
41 | | auth | 회원가입 | POST | api/auth/register | [바로가기](/src/api/auth/README.md) | None | | 41 | | auth | 회원가입 | POST | api/auth/register | [바로가기](/src/api/auth/README.md) | None | |
42 | | auth | 로그인 확인 | GET | api/auth/check | [바로가기](/src/api/auth/README.md) | None | | 42 | | auth | 로그인 확인 | GET | api/auth/check | [바로가기](/src/api/auth/README.md) | None | |
43 | +| line | 라인 ID 등록 | POST | api/line/linestart | |Line channel access token| | ||
44 | +| line | 라인 문제 메시지 발송 | POST | api/line/linestart | |Line channel access token| | ||
45 | + | ... | ... |
1 | const Koa = require("koa"); | 1 | const Koa = require("koa"); |
2 | const Router = require("koa-router"); | 2 | const Router = require("koa-router"); |
3 | const bodyParser = require("koa-bodyparser"); | 3 | const bodyParser = require("koa-bodyparser"); |
4 | + | ||
4 | const mongoose = require("mongoose"); | 5 | const mongoose = require("mongoose"); |
5 | const fs = require("fs"); | 6 | const fs = require("fs"); |
7 | +const path = require('path'); | ||
8 | +const HTTPS = require('https'); | ||
9 | + | ||
6 | const morgan = require("koa-morgan"); | 10 | const morgan = require("koa-morgan"); |
7 | const jwtMiddleware = require("./src/lib/jwtMiddleware"); | 11 | const jwtMiddleware = require("./src/lib/jwtMiddleware"); |
12 | + | ||
8 | const api = require("./src/api"); | 13 | const api = require("./src/api"); |
9 | 14 | ||
15 | +const cors = require('@koa/cors'); // for fix CORS Error | ||
16 | + | ||
10 | require("dotenv").config(); | 17 | require("dotenv").config(); |
11 | 18 | ||
12 | const app = new Koa(); | 19 | const app = new Koa(); |
... | @@ -15,10 +22,12 @@ const accessLogStream = fs.createWriteStream(__dirname + "/access.log", { | ... | @@ -15,10 +22,12 @@ const accessLogStream = fs.createWriteStream(__dirname + "/access.log", { |
15 | flags: "a", | 22 | flags: "a", |
16 | }); | 23 | }); |
17 | require("dotenv").config(); | 24 | require("dotenv").config(); |
25 | +app.use(cors()); | ||
18 | app.use(bodyParser()); | 26 | app.use(bodyParser()); |
19 | app.use(jwtMiddleware); | 27 | app.use(jwtMiddleware); |
20 | app.use(morgan("combined", { stream: accessLogStream })); | 28 | app.use(morgan("combined", { stream: accessLogStream })); |
21 | -const { SERVER_PORT, MONGO_URL } = process.env; | 29 | + |
30 | +const { SERVER_PORT, MONGO_URL, SSLPORT, DOMAIN } = process.env; | ||
22 | 31 | ||
23 | router.use("/api", api.routes()); | 32 | router.use("/api", api.routes()); |
24 | app.use(router.routes()).use(router.allowedMethods()); | 33 | app.use(router.routes()).use(router.allowedMethods()); |
... | @@ -28,6 +37,7 @@ mongoose | ... | @@ -28,6 +37,7 @@ mongoose |
28 | useNewUrlParser: true, | 37 | useNewUrlParser: true, |
29 | useFindAndModify: false, | 38 | useFindAndModify: false, |
30 | useUnifiedTopology: true, | 39 | useUnifiedTopology: true, |
40 | + useCreateIndex : true | ||
31 | }) | 41 | }) |
32 | .then(() => { | 42 | .then(() => { |
33 | console.log("Connected to MongoDB"); | 43 | console.log("Connected to MongoDB"); |
... | @@ -39,3 +49,19 @@ mongoose | ... | @@ -39,3 +49,19 @@ mongoose |
39 | app.listen(SERVER_PORT, () => { | 49 | app.listen(SERVER_PORT, () => { |
40 | console.log("Server is running on port", process.env.SERVER_PORT); | 50 | console.log("Server is running on port", process.env.SERVER_PORT); |
41 | }); | 51 | }); |
52 | + | ||
53 | +//for Line Channel | ||
54 | +try { | ||
55 | + const option = { | ||
56 | + ca: fs.readFileSync('/etc/letsencrypt/live/' + DOMAIN +'/fullchain.pem'), | ||
57 | + key: fs.readFileSync(path.resolve(process.cwd(), '/etc/letsencrypt/live/' + DOMAIN +'/privkey.pem'), 'utf8').toString(), | ||
58 | + cert: fs.readFileSync(path.resolve(process.cwd(), '/etc/letsencrypt/live/' + DOMAIN +'/cert.pem'), 'utf8').toString(), | ||
59 | + }; | ||
60 | + | ||
61 | + HTTPS.createServer(option, app.callback()).listen(SSLPORT, () => { | ||
62 | + console.log(`[HTTPS] Server is started on port ${SSLPORT}`); | ||
63 | + }); | ||
64 | +} catch (error) { | ||
65 | + console.log('[HTTPS] HTTPS 오류가 발생하였습니다. HTTPS 서버는 실행되지 않습니다.'); | ||
66 | + console.log(error); | ||
67 | +} | ... | ... |
... | @@ -146,6 +146,14 @@ | ... | @@ -146,6 +146,14 @@ |
146 | "to-fast-properties": "^2.0.0" | 146 | "to-fast-properties": "^2.0.0" |
147 | } | 147 | } |
148 | }, | 148 | }, |
149 | + "@koa/cors": { | ||
150 | + "version": "3.1.0", | ||
151 | + "resolved": "https://registry.npmjs.org/@koa/cors/-/cors-3.1.0.tgz", | ||
152 | + "integrity": "sha512-7ulRC1da/rBa6kj6P4g2aJfnET3z8Uf3SWu60cjbtxTA5g8lxRdX/Bd2P92EagGwwAhANeNw8T8if99rJliR6Q==", | ||
153 | + "requires": { | ||
154 | + "vary": "^1.1.2" | ||
155 | + } | ||
156 | + }, | ||
149 | "@sindresorhus/is": { | 157 | "@sindresorhus/is": { |
150 | "version": "0.14.0", | 158 | "version": "0.14.0", |
151 | "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", | 159 | "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", |
... | @@ -826,6 +834,15 @@ | ... | @@ -826,6 +834,15 @@ |
826 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", | 834 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", |
827 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" | 835 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" |
828 | }, | 836 | }, |
837 | + "cors": { | ||
838 | + "version": "2.8.5", | ||
839 | + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", | ||
840 | + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", | ||
841 | + "requires": { | ||
842 | + "object-assign": "^4", | ||
843 | + "vary": "^1" | ||
844 | + } | ||
845 | + }, | ||
829 | "cron-parser": { | 846 | "cron-parser": { |
830 | "version": "2.15.0", | 847 | "version": "2.15.0", |
831 | "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-2.15.0.tgz", | 848 | "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-2.15.0.tgz", | ... | ... |
... | @@ -4,11 +4,13 @@ | ... | @@ -4,11 +4,13 @@ |
4 | "main": "index.js", | 4 | "main": "index.js", |
5 | "license": "MIT", | 5 | "license": "MIT", |
6 | "dependencies": { | 6 | "dependencies": { |
7 | + "@koa/cors": "^3.1.0", | ||
7 | "axios": "^0.19.2", | 8 | "axios": "^0.19.2", |
8 | "bcrypt": "^4.0.1", | 9 | "bcrypt": "^4.0.1", |
9 | "body-parser": "^1.19.0", | 10 | "body-parser": "^1.19.0", |
10 | "cheerio": "^1.0.0-rc.3", | 11 | "cheerio": "^1.0.0-rc.3", |
11 | "cookie-parser": "^1.4.5", | 12 | "cookie-parser": "^1.4.5", |
13 | + "cors": "^2.8.5", | ||
12 | "dotenv": "^8.2.0", | 14 | "dotenv": "^8.2.0", |
13 | "eslint-config-prettier": "^6.11.0", | 15 | "eslint-config-prettier": "^6.11.0", |
14 | "fs": "^0.0.1-security", | 16 | "fs": "^0.0.1-security", | ... | ... |
... | @@ -14,7 +14,7 @@ exports.register = async (ctx) => { | ... | @@ -14,7 +14,7 @@ exports.register = async (ctx) => { |
14 | password: Joi.string().required(), | 14 | password: Joi.string().required(), |
15 | }); | 15 | }); |
16 | 16 | ||
17 | - const result = Joi.validate(ctx.request.body, schema); | 17 | + const result = schema.validate(ctx.request.body); |
18 | if (result.error) { | 18 | if (result.error) { |
19 | ctx.status = 400; | 19 | ctx.status = 400; |
20 | ctx.body = result.error; | 20 | ctx.body = result.error; | ... | ... |
1 | const Router = require("koa-router"); | 1 | const Router = require("koa-router"); |
2 | const auth = new Router(); | 2 | const auth = new Router(); |
3 | const authCtrl = require("./auth.ctrl"); | 3 | const authCtrl = require("./auth.ctrl"); |
4 | + | ||
4 | auth.post("/login", authCtrl.login); | 5 | auth.post("/login", authCtrl.login); |
5 | auth.post("/logout", authCtrl.logout); | 6 | auth.post("/logout", authCtrl.logout); |
6 | auth.post("/register", authCtrl.register); | 7 | auth.post("/register", authCtrl.register); | ... | ... |
... | @@ -6,11 +6,13 @@ const friend = require("./friend"); | ... | @@ -6,11 +6,13 @@ const friend = require("./friend"); |
6 | const notify = require("./notify"); | 6 | const notify = require("./notify"); |
7 | const user = require("./user"); | 7 | const user = require("./user"); |
8 | const profile = require("./profile"); | 8 | const profile = require("./profile"); |
9 | +const line = require("./line") | ||
9 | 10 | ||
10 | api.use("/auth", auth.routes()); | 11 | api.use("/auth", auth.routes()); |
11 | api.use("/friend", friend.routes()); | 12 | api.use("/friend", friend.routes()); |
12 | api.use("/notify", notify.routes()); | 13 | api.use("/notify", notify.routes()); |
13 | api.use("/user", user.routes()); | 14 | api.use("/user", user.routes()); |
14 | api.use("/profile", profile.routes()); | 15 | api.use("/profile", profile.routes()); |
16 | +api.use("/line", line.routes()); | ||
15 | 17 | ||
16 | -module.exports = api; | 18 | +module.exports = api; |
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
jaksimsamil-server/src/api/line/README.md
0 → 100644
File mode changed
jaksimsamil-server/src/api/line/index.js
0 → 100644
jaksimsamil-server/src/api/line/line.ctrl.js
0 → 100644
1 | +const request = require('request'); | ||
2 | +const TARGET_URL = 'https://api.line.me/v2/bot/message/reply' | ||
3 | + | ||
4 | +require("dotenv").config(); | ||
5 | +const TOKEN = process.env.LINE_CHANNEL_KEY; | ||
6 | + | ||
7 | +const Profile = require("../../models/profile"); | ||
8 | +const problem_set = require("../../data/problem_set"); | ||
9 | +const compareBJ = require("../../util/compareBJ"); | ||
10 | + | ||
11 | +/* | ||
12 | + username : default = "" | ||
13 | +*/ | ||
14 | +let username = ""; | ||
15 | + | ||
16 | +/* | ||
17 | +POST api/line/hook | ||
18 | +{ | ||
19 | + for line reply : recommend and set | ||
20 | +} | ||
21 | + */ | ||
22 | +exports.linestart = async(ctx) => { | ||
23 | + var eventObj = ctx.request.body.events[0]; | ||
24 | + | ||
25 | + // request log | ||
26 | + console.log('======================', new Date() ,'======================'); | ||
27 | + console.log('[request]', ctx.request.body); | ||
28 | + console.log('[request source] ', eventObj.source); | ||
29 | + console.log('[request message]', eventObj.message); | ||
30 | + console.log('[username]', username); | ||
31 | + | ||
32 | + //first . set User | ||
33 | + if(username == "") { | ||
34 | + username = eventObj.message.text; | ||
35 | + | ||
36 | + const result = await isExist(username); | ||
37 | + if (!result) { | ||
38 | + username = ""; | ||
39 | + | ||
40 | + request.post( | ||
41 | + { | ||
42 | + url: TARGET_URL, | ||
43 | + headers: { | ||
44 | + 'Authorization': `Bearer ${TOKEN}` | ||
45 | + }, | ||
46 | + json: { | ||
47 | + "replyToken":eventObj.replyToken, | ||
48 | + "messages":[ | ||
49 | + { | ||
50 | + "type":"text", | ||
51 | + "text": "작심삼일 사이트의 ID값이 올바르지 않습니다. 다시 입력해주세요." | ||
52 | + } | ||
53 | + ] | ||
54 | + } | ||
55 | + },(body) => { | ||
56 | + console.log(body) | ||
57 | + }); | ||
58 | + } else { | ||
59 | + request.post({ | ||
60 | + url: TARGET_URL, | ||
61 | + headers: { | ||
62 | + 'Authorization': `Bearer ${TOKEN}` | ||
63 | + }, | ||
64 | + json: { | ||
65 | + "replyToken":eventObj.replyToken, | ||
66 | + "messages":[ | ||
67 | + { | ||
68 | + "type":"text", | ||
69 | + "text": eventObj.message.text + " : 정상 등록 되었습니다." | ||
70 | + } | ||
71 | + ] | ||
72 | + } | ||
73 | + },(body) => { | ||
74 | + console.log(body) | ||
75 | + }); | ||
76 | + | ||
77 | + } | ||
78 | + }; | ||
79 | + | ||
80 | + //second. can reset username | ||
81 | + if(eventObj.message.text == "reset ID") { | ||
82 | + username = ""; | ||
83 | + request.post( | ||
84 | + { | ||
85 | + url: TARGET_URL, | ||
86 | + headers: { | ||
87 | + 'Authorization': `Bearer ${TOKEN}` | ||
88 | + }, | ||
89 | + json: { | ||
90 | + "replyToken": eventObj.replyToken, | ||
91 | + "messages":[ | ||
92 | + { | ||
93 | + "type":"text", | ||
94 | + "text": "작심삼일 사이트의 ID가 초기화 되었습니다." | ||
95 | + } | ||
96 | + ] | ||
97 | + } | ||
98 | + },(body) => { | ||
99 | + console.log(body) | ||
100 | + }); | ||
101 | + } | ||
102 | + | ||
103 | + //main : recommend Problem | ||
104 | + if(eventObj.message.text == "문제") { | ||
105 | + console.log("문제를 추천합니다."); | ||
106 | + let recommendData = await lineRecommend(username); | ||
107 | + recommendBJ(eventObj.replyToken, recommendData); | ||
108 | + | ||
109 | + console.log(recommendData); | ||
110 | + } | ||
111 | + | ||
112 | +} | ||
113 | + | ||
114 | +//for recommend message | ||
115 | +function recommendBJ(replyToken, recommendData) { | ||
116 | + var recommendProblem = "오늘의 추천문제는 " + recommendData.problem_title + "입니다."; | ||
117 | + var problemURL = "https://www.boj.kr/" + recommendData.problem_number; | ||
118 | + request.post( | ||
119 | + { | ||
120 | + url: TARGET_URL, | ||
121 | + headers: { | ||
122 | + 'Authorization': `Bearer ${TOKEN}` | ||
123 | + }, | ||
124 | + json: { | ||
125 | + "replyToken":replyToken, | ||
126 | + "messages":[ | ||
127 | + { | ||
128 | + "type":"text", | ||
129 | + "text": recommendProblem | ||
130 | + }, | ||
131 | + { | ||
132 | + "type":"text", | ||
133 | + "text": problemURL | ||
134 | + } | ||
135 | + ] | ||
136 | + } | ||
137 | + },(body) => { | ||
138 | + console.log(body) | ||
139 | + }); | ||
140 | +} | ||
141 | + | ||
142 | +async function lineRecommend (username) { | ||
143 | + | ||
144 | + const profile = await Profile.findByUsername(username); | ||
145 | + if (!profile) { | ||
146 | + console.log("401"); | ||
147 | + return; | ||
148 | + } | ||
149 | + | ||
150 | + const unsolved_data = await compareBJ.compareBJ( | ||
151 | + profile.getBJdata(), | ||
152 | + problem_set.problem_set | ||
153 | + ); | ||
154 | + | ||
155 | + const recommendData = await compareBJ.randomItem(unsolved_data); | ||
156 | + | ||
157 | + if (!recommendData) { | ||
158 | + console.log("402"); | ||
159 | + return; | ||
160 | + } | ||
161 | + | ||
162 | + return recommendData; | ||
163 | + | ||
164 | +}; | ||
165 | + | ||
166 | +async function isExist(username) { | ||
167 | + const profile = await Profile.findByUsername(username); | ||
168 | + | ||
169 | + if (!profile) { | ||
170 | + return false; | ||
171 | + } | ||
172 | + | ||
173 | + return true; | ||
174 | +} |
1 | const Router = require("koa-router"); | 1 | const Router = require("koa-router"); |
2 | const profile = new Router(); | 2 | const profile = new Router(); |
3 | const profileCtrl = require("./profile.ctrl"); | 3 | const profileCtrl = require("./profile.ctrl"); |
4 | + | ||
4 | profile.post("/solved:id"); | 5 | profile.post("/solved:id"); |
5 | profile.get("/solvednum:id"); | 6 | profile.get("/solvednum:id"); |
6 | profile.post("/recommend", profileCtrl.recommend); | 7 | profile.post("/recommend", profileCtrl.recommend); |
7 | profile.patch("/syncBJ", profileCtrl.syncBJ); | 8 | profile.patch("/syncBJ", profileCtrl.syncBJ); |
8 | profile.post("/setprofile", profileCtrl.setProfile); | 9 | profile.post("/setprofile", profileCtrl.setProfile); |
9 | profile.post("/getprofile", profileCtrl.getProfile); | 10 | profile.post("/getprofile", profileCtrl.getProfile); |
11 | + | ||
10 | module.exports = profile; | 12 | module.exports = profile; | ... | ... |
... | @@ -51,7 +51,7 @@ exports.setProfile = async (ctx) => { | ... | @@ -51,7 +51,7 @@ exports.setProfile = async (ctx) => { |
51 | }) | 51 | }) |
52 | .unknown(); | 52 | .unknown(); |
53 | console.log(ctx.request.body); | 53 | console.log(ctx.request.body); |
54 | - const result = Joi.validate(ctx.request.body, schema); | 54 | + const result = schema.validate(ctx.request.body); |
55 | if (result.error) { | 55 | if (result.error) { |
56 | ctx.status = 400; | 56 | ctx.status = 400; |
57 | ctx.body = result.error; | 57 | ctx.body = result.error; |
... | @@ -118,14 +118,16 @@ POST /api/proflie/recommend | ... | @@ -118,14 +118,16 @@ POST /api/proflie/recommend |
118 | */ | 118 | */ |
119 | exports.recommend = async (ctx) => { | 119 | exports.recommend = async (ctx) => { |
120 | const { username } = ctx.request.body; | 120 | const { username } = ctx.request.body; |
121 | - | ||
122 | if (!username) { | 121 | if (!username) { |
122 | + console.log('no given username'); | ||
123 | ctx.status = 401; | 123 | ctx.status = 401; |
124 | return; | 124 | return; |
125 | } | 125 | } |
126 | try { | 126 | try { |
127 | + console.log('finding username:', username); | ||
127 | const profile = await Profile.findByUsername(username); | 128 | const profile = await Profile.findByUsername(username); |
128 | if (!profile) { | 129 | if (!profile) { |
130 | + console.log('no profile'); | ||
129 | ctx.status = 401; | 131 | ctx.status = 401; |
130 | return; | 132 | return; |
131 | } | 133 | } |
... | @@ -137,5 +139,7 @@ exports.recommend = async (ctx) => { | ... | @@ -137,5 +139,7 @@ exports.recommend = async (ctx) => { |
137 | //데이터가 비었을 떄 예외처리 필요 | 139 | //데이터가 비었을 떄 예외처리 필요 |
138 | } catch (e) { | 140 | } catch (e) { |
139 | ctx.throw(500, e); | 141 | ctx.throw(500, e); |
142 | + } finally { | ||
143 | + console.log('successfully sent user recommendation') | ||
140 | } | 144 | } |
141 | }; | 145 | }; | ... | ... |
-
Please register or login to post a comment