서민정

Update Client && Update README.md

1 -### 오픈소스sw개발 개인 프로젝트 1 +README referred to [Github](https://github.com/othneildrew/Best-README-Template)
2 -## CHATBOT WITH CRAWLING 2 +
3 +
4 +<!-- PROJECT LOGO -->
5 +<br />
6 +<p align="center">
7 + <h3 align="center">SEARCH AND CHAT</h3>
8 +
9 + <p align="center">
10 + 웹 페이지로 구현된 챗봇과 대화 및 '@'를 이용하여 최신 영상, 정확도 높은 영상, 소식을 카드로 제공합니다.
11 + "http://khuhub.khu.ac.kr/2017103084/oss-chatbot"
12 + <a href="http://khuhub.khu.ac.kr/2017103084/oss-chatbot/">View Demo</a>
13 + ·
14 + <a href="http://khuhub.khu.ac.kr/2017103084/oss-chatbot/issues">Report Bug</a>
15 + ·
16 + <a href="http://khuhub.khu.ac.kr/2017103084/oss-chatbot/merge_requests">Request Feature</a>
17 + </p>
18 +</p>
19 +
20 +
21 +
22 +<!-- TABLE OF CONTENTS -->
23 +## Table of Contents
24 +
25 +* [About the Project](#about-the-project)
26 + * [Built With](#built-with)
27 +* [Getting Started](#getting-started)
28 + * [Prerequisites](#prerequisites)
29 + * [Installation](#installation)
30 +* [Usage](#usage)
31 +* [Roadmap](#roadmap)
32 +* [Contributing](#contributing)
33 +* [License](#license)
34 +* [Contact](#contact)
35 +* [Acknowledgements](#acknowledgements)
36 +
37 +
38 +
39 +<!-- ABOUT THE PROJECT -->
40 +## About The Project
41 +
42 +[![Product Name Screen Shot](./projectScreenShot.PNG)
43 +
44 +카카오톡, 라인 등에서 제공하는 챗봇 어플리케이션과 같이 웹에서도 작동할 수 있는 챗봇을 만들어, 웹 사용자들과 대화할 수 있는 봇을 만들고 싶어 이 프로젝트를 진행하게 되었습니다. 간단한 대화와 더불어 좋아하는 가수, 또는 배우 등의 이름과 함께 검색어를 입력하면 봇이 대신 정보를 가져와주는 편의성을 더하였습니다.
45 +
46 +
47 +### Built With
48 +
49 +* [Nodejs](https://nodejs.org/en/)
50 +* [React](https://ko.reactjs.org/)
51 +* [Google Cloud API](https://cloud.google.com/apis)
52 +* [Dialogflow API](https://dialogflow.cloud.google.com/)
53 +
54 +
55 +<!-- GETTING STARTED -->
56 +## Getting Started
57 +
58 +로컬 컴퓨터에서 실행시킬 수 있는 방법입니다.
59 +
60 +### Prerequisites
61 +
62 +먼저, 이 프로젝트를 실행시키기 위해 필요한 요구사항입니다.
63 +
64 +* Node
65 +[Official Node.js Website](https://nodejs.org/)에서 Node.js를 설치합니다.
66 +또한 `npm` 의 설치도 필요합니다.
67 +
68 +### Installation
69 +
70 +1. 이 리포지토리를 Clone 합니다.
71 +```sh
72 +git clone http://khuhub.khu.ac.kr/2017103084/oss-chatbot/
73 +```
74 +2. root 폴더와 client 폴더에서 아래 명령을 실행합니다.
75 +```sh
76 +npm install
77 +```
78 +3. [Google Developers](https://console.developers.google.com/project)에서 프로젝트를 생성한 뒤, API 키를 발급 받습니다. 이 때, 프로젝트 명(ID)과 API 키의 json 파일이 필요합니다.
79 +
80 +4. [Dialogflow](https://dialogflow.cloud.google.com/)에서 에이전트를 생성합니다. 이 때, GOOGLE PROJECT 탭의 Project ID는 앞서 (3)에서 생성한 프로젝트의 ID를 선택합니다.
81 +
82 +5. root 폴더에 .env 파일을 생성한 뒤, 아래 내용을 채워 넣습니다.
83 +```
84 +googleProjectID = (3)에서 생성한 구글 프로젝트 ID
85 +dialogFlowSessionID = bot-session #원하는 것으로 입력.
86 +dialogFlowSessionLanguageCode = Dialogflow 에이전트 생성 시 설정한 언어 코드 (ex. 한글일 경우에는 "ko" 입니다.)
87 +googleClientEmail = 구글 프로젝트 생성 시 제공되는 이메일 (ex. [프로젝트 명]@[프로젝트명 2].iam.gserviceaccount.com)
88 +```
89 +
90 +6. **중요** 로컬에서 실행하는 경우에는 root의 package.json 중 "@google-cloud/storage": "^5.0.1" 를 지웁니다. 이 패키지는 herokuapp에서 GOOGLE_APPLICATION_CREDENTIALS를 활용하기 위해 설치되어있는 패키지입니다.
91 +
92 +7. 모두 완료 되었다면, 아래 명령어를 입력하여 클라이언트와 서버를 모두 실행시킬 수 있습니다.
93 +```
94 +npm run dev
95 +```
96 +
97 +
98 +<!-- USAGE EXAMPLES -->
99 +## Usage
100 +
101 +해당 프로젝트의 실제 동작 화면은 [SEARCH-AND-CHAT](https://search-and-chat.herokuapp.com/)에서 확인하실 수 있습니다.
102 +React 의 특성 상 뒤로가기 및 Reload 시 오류가 발생할 수 있습니다. 이 때는 아래 URL로 재접속하시면 원활히 사용하실 수 있습니다. 또한 heroku 로 빌드되어 사용이 없는 경우에는 첫 접속 시 로딩 시간이 걸릴 수 있습니다. 조금만 기다려주시면 프로젝트가 실행될 것입니다 😊
103 +
104 +* URL : <https://search-and-chat.herokuapp.com/>
105 +
106 +
107 +<!-- CONTRIBUTING -->
108 +## Contributing
109 +
110 +이 프로젝트를 더욱 발전시키고 싶으신 분들은 아래와 같은 절차를 따라주세요!
111 +
112 +1. Fork the Project
113 +2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`)
114 +3. Commit your Changes (`git commit -m 'Add some AmazingFeature'`)
115 +4. Push to the Branch (`git push origin feature/AmazingFeature`)
116 +5. Open a Pull Request
117 +
118 +<!-- CONTACT -->
119 +## Contact
120 +
121 +프로젝트에 문제가 있거나 궁금하신 사항은 아래 메일로 연락주세요.
122 +* Email : <mathmjseo@khu.ac.kr>
3 123
4 --readme 수정하기
5 --로그인 시 페이지렌더링 안됨 ..... 수정하기
......
...@@ -8,18 +8,13 @@ import Card from "./Sections/Card"; ...@@ -8,18 +8,13 @@ import Card from "./Sections/Card";
8 import CheckString from './Check'; 8 import CheckString from './Check';
9 import { text } from 'body-parser'; 9 import { text } from 'body-parser';
10 10
11 -let userKeyword = ""; 11 +function Chatbot(props) {
12 -let userName = "유저"; 12 +
13 -let autoSearch = 0; 13 + console.log("실행")
14 -if(sessionStorage.length){ 14 + var userName = props.userName;
15 - userKeyword = sessionStorage.getItem("Now_userKeyword"); 15 + var userKeyword = props.userKeyword;
16 - userName = sessionStorage.getItem("Now_userName"); 16 + var autoSearch = props.autoSearch;
17 - autoSearch = 1; 17 +
18 - sessionStorage.clear();
19 -}
20 -
21 -
22 -function Chatbot() {
23 console.log("이름",userName); 18 console.log("이름",userName);
24 console.log("키워드",userKeyword); 19 console.log("키워드",userKeyword);
25 20
...@@ -32,6 +27,22 @@ function Chatbot() { ...@@ -32,6 +27,22 @@ function Chatbot() {
32 27
33 }, []) 28 }, [])
34 29
30 + if(autoSearch){
31 + useEffect(() => {
32 + console.log("I am in autoSearch!!");
33 + setTimeout(function(){
34 + eventQuery('008_AutoSearch');
35 + }, 500);
36 +
37 + setTimeout(function(){
38 + textQuery(`@${userKeyword}_최신`);
39 + textQuery(`@${userKeyword}_정확도`);
40 + textQuery(`@${userKeyword}_소식`);
41 + }, 1000);
42 +
43 + }, [])
44 + }
45 +
35 const textQuery = async (text) => { 46 const textQuery = async (text) => {
36 // First Need to take care of the message I sent 47 // First Need to take care of the message I sent
37 let conversation = { 48 let conversation = {
...@@ -147,20 +158,14 @@ function Chatbot() { ...@@ -147,20 +158,14 @@ function Chatbot() {
147 158
148 } 159 }
149 160
150 - if(autoSearch === 1){ 161 + // if(autoSearch === 1){
151 - setTimeout(function(){
152 - eventQuery('008_AutoSearch');
153 - }, 500);
154 162
155 - setTimeout(function(){ 163 +
156 - textQuery(`@${userKeyword}_최신`); 164 +
157 - textQuery(`@${userKeyword}_정확도`); 165 +
158 - textQuery(`@${userKeyword}_소식`); 166 + // autoSearch = 0;
159 - }, 1000); 167 + // console.log("I am in autoSearch!!");
160 - 168 + // }
161 - autoSearch = 0;
162 - console.log("I am in autoSearch!!");
163 - }
164 169
165 170
166 const keyPressHanlder = (e) => { 171 const keyPressHanlder = (e) => {
......
...@@ -3,16 +3,29 @@ import { Typography, Icon } from 'antd'; ...@@ -3,16 +3,29 @@ import { Typography, Icon } from 'antd';
3 import Chatbot from '../Chatbot/Chatbot'; 3 import Chatbot from '../Chatbot/Chatbot';
4 import { withRouter } from "react-router-dom"; 4 import { withRouter } from "react-router-dom";
5 const { Title } = Typography; 5 const { Title } = Typography;
6 - 6 +let userKeyword = "";
7 +let userName = "유저";
8 +let autoSearch = 0;
9 +console.log("챗페이지 밖");
7 10
8 function chatpage() { 11 function chatpage() {
12 + console.log("챗페이지 안")
13 + if(sessionStorage.length === 2){
14 + console.log("세션스토리지 안")
15 + userKeyword = sessionStorage.getItem("Now_userKeyword");
16 + userName = sessionStorage.getItem("Now_userName");
17 + sessionStorage.clear();
18 +
19 + autoSearch = 1;
20 + }
21 +
9 return ( 22 return (
10 <div> 23 <div>
11 <div style={{ display: 'flex', justifyContent: 'center', marginTop: '1rem' }}> 24 <div style={{ display: 'flex', justifyContent: 'center', marginTop: '1rem' }}>
12 <Title level={2} >CHATBOT&nbsp;<Icon type="robot" /></Title> 25 <Title level={2} >CHATBOT&nbsp;<Icon type="robot" /></Title>
13 </div> 26 </div>
14 <div style={{ display: 'flex', justifyContent: 'center' }}> 27 <div style={{ display: 'flex', justifyContent: 'center' }}>
15 - <Chatbot /> 28 + <Chatbot userName = {userName} userKeyword = {userKeyword} autoSearch = {autoSearch}/>
16 </div> 29 </div>
17 </div> 30 </div>
18 ) 31 )
......
...@@ -6,10 +6,13 @@ import Axios from 'axios'; ...@@ -6,10 +6,13 @@ import Axios from 'axios';
6 const { Title } = Typography; 6 const { Title } = Typography;
7 7
8 console.log("start"); 8 console.log("start");
9 +let url = "/";
9 10
10 -const userInfo = async (info) => { 11 +async function userInfo(){
11 const email = document.getElementById('email').value; 12 const email = document.getElementById('email').value;
12 const pw = document.getElementById('password').value; 13 const pw = document.getElementById('password').value;
14 +
15 +
13 if(email && pw){ 16 if(email && pw){
14 const userVariables = { 17 const userVariables = {
15 email, 18 email,
...@@ -18,6 +21,7 @@ const userInfo = async (info) => { ...@@ -18,6 +21,7 @@ const userInfo = async (info) => {
18 21
19 const response = await Axios.post('/api/login/userInfo', userVariables); 22 const response = await Axios.post('/api/login/userInfo', userVariables);
20 if(response.data !== 'FAIL'){ 23 if(response.data !== 'FAIL'){
24 + url = "/chat";
21 // loginForm.action = `/chat?${response.data}`; 25 // loginForm.action = `/chat?${response.data}`;
22 // loginForm.submit(); 26 // loginForm.submit();
23 var keyword = response.data.keyword; 27 var keyword = response.data.keyword;
...@@ -25,14 +29,16 @@ const userInfo = async (info) => { ...@@ -25,14 +29,16 @@ const userInfo = async (info) => {
25 29
26 sessionStorage.setItem("Now_userKeyword", keyword); 30 sessionStorage.setItem("Now_userKeyword", keyword);
27 sessionStorage.setItem("Now_userName", name); 31 sessionStorage.setItem("Now_userName", name);
28 - window.history.replaceState('login','','/chat'); 32 + // window.history.replaceState('login','','/chat');
29 - window.history.go(); 33 + // window.history.go();
30 // window.location.href = "/chat"; 34 // window.location.href = "/chat";
31 } else{ 35 } else{
36 + url = "/";
32 alert("입력하신 정보와 일치하는 회원이 존재하지 않습니다 😥"); 37 alert("입력하신 정보와 일치하는 회원이 존재하지 않습니다 😥");
33 } 38 }
34 } 39 }
35 else{ 40 else{
41 + url = "/";
36 alert("이메일과 패스워드를 입력해주세요!"); 42 alert("이메일과 패스워드를 입력해주세요!");
37 } 43 }
38 } 44 }
...@@ -67,9 +73,11 @@ function loginpage() { ...@@ -67,9 +73,11 @@ function loginpage() {
67 73
68 <Form.Item> 74 <Form.Item>
69 <div> 75 <div>
70 - <Button type="primary" className="login-form-button" style={{ minWidth: '100%' }} onClick={userInfo}> 76 + <Link to= {`${url}`} onClick= {userInfo} name = "loginLink">
71 - Log in 77 + <Button type="primary" className="login-form-button" style={{ minWidth: '100%' }}>
72 - </Button> 78 + Log in
79 + </Button>
80 + </Link>
73 </div> 81 </div>
74 <Link to ="/register">가입하기</Link> Or <Link to = "/chat">비회원으로 사용하기</Link> 82 <Link to ="/register">가입하기</Link> Or <Link to = "/chat">비회원으로 사용하기</Link>
75 </Form.Item> 83 </Form.Item>
......
1 -1. dialogflow로 기본 기능 구현
2 -2. React로 프론트엔드 구현
3 -3. routing으로 @가수명 입력하면 해당 라우팅(크롤링) 함수로 들어가게 구현
4 -4. 크롤링 구현 (네이버TV 최신 영상 3개 json으로 가져오기)
5 -5. json파일 카드로 넘겨주기
6 -
7 -
8 ----
9 -검색결과가 없을 때 -> 다시 dialogflow 라우터로 넘겨줘서 무슨 말인지 이해하지 못했어요
10 -관련 영상이 3가지 미만일 때 -> 없다고 판단함.
11 ----
12 -
13 -
14 -node 서버: localhost: 5000
15 -프론트엔드/ localhost: 3000
16 -
17 ----- 정리
18 -
19 -리덕스 참고: https://velopert.com/3528
20 -
21 -dialogflow
22 -화자의 의도 intent ,사용자가 말하는 것과 dialogflow가 수행해야할 작업간의 매핑을 나타내는 것.
23 -fallback intent : 사용자의 대화가 어떤 intent 와도 매칭되지 않을 때 선택되어지는 intent
24 -
25 -화자의 속성 entity
26 -ex. 내일 오후 2시 되나요? 에서 '내일', '오후 2시'를 파라미터로 뽑아내는 것.
27 -
28 -문맥 context
29 -내일 오후 2시 되나요? 에서 무엇을 위한 내일 오후 2시인가를 파악하기 위해서 그 전에 대화가 되었던 '수리'라는 것을 기억하는 것을 의미함
30 -
31 -uuid 제대로 이해하고 다시 작성하기
32 -
33 -
34 -
35 -
36 ------
37 -001 - welcome
38 -002 - 인사
39 -003 - @'가수명'
40 --> 해당 가수명으로 크롤링을 했을 때 null이 3개이상 나오면 가수명이 없다고 판단함.
41 --> 만약 가수가 아니더라도 크롤링 시 해당되는 내용이 3개 이상 나오면 해당 내용을 리턴함.
42 ------
43 -
44 -