From 22a2d0cd5613c5398dfb8c6656467389f1acbfbb Mon Sep 17 00:00:00 2001 From: alstn2468 Date: Mon, 14 May 2018 18:47:40 +0900 Subject: [PATCH] 2018-05-14 --- README.md | 13 +++- app/menu/restaurant.json | 26 +++++++ app/my_module/button.py | 18 +++++ app/my_module/repdic.py | 31 ++++++++ app/my_module/scheduleparser.py | 53 +++++++++++++ app/my_module/stringformat.py | 23 ++++++ app/views.py | 134 +++++++++----------------------- 7 files changed, 198 insertions(+), 100 deletions(-) create mode 100644 app/menu/restaurant.json create mode 100644 app/my_module/button.py create mode 100644 app/my_module/repdic.py create mode 100644 app/my_module/scheduleparser.py create mode 100644 app/my_module/stringformat.py diff --git a/README.md b/README.md index 59e672aa..a3320ed4 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ SCH Food Chatbot [![made-with-python](https://img.shields.io/badge/Made%20with-Python-1f425f.svg)](https://www.python.org/) [![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT) -[![Generic badge](https://img.shields.io/badge/Version-1.0.0-green.svg)](https://shields.io/) +[![Generic badge](https://img.shields.io/badge/Version-2.2.0-green.svg)](https://shields.io/) ## 제작자 : [김민수](https://github.com/alstn2468)
Soonchunhyang University
Department of Computer Software Engineering @@ -113,16 +113,21 @@ Python과 Django 웹 프레임워크를 사용하여 제작한 자동 응답형 ## 버전 2018/05/12
-- Version [(1.0.0)](https://github.com/alstn2468/SCH_Food_ChatBot/commit/a90e974c8cbcb5274cc9d3174393c5dadf446160) released
+- Version [(1.0.0)](https://github.com/alstn2468/SCH_Food_ChatBot/commit/a90e974c8cbcb5274cc9d3174393c5dadf446160) Released
2018/05/14
-- Version [(2.0.0)](https://github.com/alstn2468/SCH_Food_ChatBot/commit/0345f08a672d499816ca8cf03f60ab140992656c) Update
+- Version [(2.0.0)](https://github.com/alstn2468/SCH_Food_ChatBot/commit/0345f08a672d499816ca8cf03f60ab140992656c) New Function Updated
- 학사 일정 확인 기능 추가 완료 2018/05/14
-- Version [(2.1.0)](https://github.com/alstn2468/SCH_Food_ChatBot/commit/ce419d7c03e235c8cc61a78d2b26d75e1f364079) Update
+- Version [(2.1.0)](https://github.com/alstn2468/SCH_Food_ChatBot/commit/ce419d7c03e235c8cc61a78d2b26d75e1f364079) Food Menu Button Optimized
- 버튼 메뉴 세분화 완료 +2018/05/14
+- Version [(2.2.1)](https://github.com/alstn2468/SCH_Food_ChatBot/commit/ce419d7c03e235c8cc61a78d2b26d75e1f364079) New Function Updated / Source Code Modularization
+- 학교 Wi-Fi 기능 추가 완료 +- 소스 코드 모듈화 완료 + ## 친구 추가 diff --git a/app/menu/restaurant.json b/app/menu/restaurant.json new file mode 100644 index 00000000..c1ef8f6f --- /dev/null +++ b/app/menu/restaurant.json @@ -0,0 +1,26 @@ +{ + "식당" : [ + {"0" : "이층집 뼈다귀"}, + {"1" : "궁중 화로"}, + {"2" : "미스터 짱닭 치킨"}, + {"3" : "중국성"}, + {"4" : "모던 팩토리"}, + {"5" : "장충동할머니 족발보쌈"}, + {"6" : "도스마스"}, + {"7" : "행복한 돈가스"}, + {"8" : "토마토 도시락"}, + {"9" : "불스 떡볶이"}, + {"10" : "천원국수"}, + {"11" : "온양왕족발보쌈"}, + {"12" : "은성식당"}, + {"13" : "신창족발"}, + {"14" : "북경탕수육"}, + {"15" : "푸짐한밥상"}, + {"16" : "영식당"}, + {"17" : "돼지고기김치찌개"}, + {"18" : "신창상회"}, + {"19" : "한솥도시락"}, + {"20" : "김밥나라"}, + {"20" : } + ] +} diff --git a/app/my_module/button.py b/app/my_module/button.py new file mode 100644 index 00000000..ba9ed2dc --- /dev/null +++ b/app/my_module/button.py @@ -0,0 +1,18 @@ +# views.py의 keyboard에서 사용할 버튼 모듈 + +basic_button = [ +'학식', +'종강', +'학사 일정', +'교내 Wi-Fi', +'개발자 정보' +] + +food_sel_process_button = [ +'향설1 생활관', +'향설2 생활관', +'향설3 생활관', +'학생회관', +'교직원 식당', +'처음으로' +] diff --git a/app/my_module/repdic.py b/app/my_module/repdic.py new file mode 100644 index 00000000..ca285964 --- /dev/null +++ b/app/my_module/repdic.py @@ -0,0 +1,31 @@ +# 문자열에서 문자를 교환할 때 사용 할 딕셔너리 모듈 + +trans_dic = { +'[': '' , +']': '', +'{' : '', +'}': '' , +"'": '', +',' : '\n', +':' : '\n', +' ' : '', +'\n' : '\n·', +'-중식/석식-' : '\n[중식/석식]', +'-조식-' : '\n[조식]', +'-컵밥-' : '\n[컵밥]', +'-중식-' : '\n[중식]', +'-석식-' : '\n[석식]', +'-한식-' : '\n[한식]', +'-덮밥-' : '\n[덮밥]', +'-양식-' : '\n[양식]', +'-도시락-' : '\n[도시락]', +'-스페셜메뉴-' : '\n[스페셜메뉴]', +'-돈까스-' : '\n[돈까스]', +'-라면-' : '\n[라면]', +'-메뉴-' : '\n[메뉴]', +'-부대라면-' : '\n[부대라면]', +'-한정메뉴-' : '\n[한정메뉴]', +'-샐러드바-' : '\n[샐러드바]', +'\n·\n' : '\n\n', +'·' : '· ' +} diff --git a/app/my_module/scheduleparser.py b/app/my_module/scheduleparser.py new file mode 100644 index 00000000..cbeba773 --- /dev/null +++ b/app/my_module/scheduleparser.py @@ -0,0 +1,53 @@ +# 학사 일정 파싱 모듈 + +from pytz import timezone +from bs4 import BeautifulSoup +import requests, os, re +import json + +def parser() : + + # Location of parser.py + BASE_DIR = os.path.dirname(os.path.abspath(__file__)) + + # HTTP GET Request + request = requests.get('https://homepage.sch.ac.kr/sch/05/05010000.jsp') + + # GET HTML Source + html = request.text + + # Use BeautifulSoup, From HTML Source to Python Object + # First Parameter is HTML Source, Second Parameter is the parser to be used + soup = BeautifulSoup(html, 'html.parser') + + # HTML element using CSS Selector + schedules = soup.find_all('a', {'class' : 'schedule'}) + + schedule_day = [] + schedule_list = [] + + for schedule in schedules: + # 날짜 가져오기 + schedule_day.append(schedule.text) + # 세부 내용 가져오기 + schedule_list.append(schedule.get('title')) + + idx = 0 + + result_message = '의 학사일정\n' + + for schedule in schedule_day : + schedule_message = '\n[' + str(schedule) + '일 일정]\n' + '· ' + schedule_list[idx] + result_message = str(result_message) + schedule_message + idx += 1 + + # GET HTTP Header + header = request.headers + + # GET HTTP Status ( 200 : normal ) + status = request.status_code + + # Check HTTP ( TRUE / FALSE ) + is_HTTP_OK = request.ok + + return result_message diff --git a/app/my_module/stringformat.py b/app/my_module/stringformat.py new file mode 100644 index 00000000..6f61690e --- /dev/null +++ b/app/my_module/stringformat.py @@ -0,0 +1,23 @@ +# 선택한 버튼이 학식 메뉴일 경우 메세지 포매팅 +select_button = '[*] 선택한 버튼 : {0}\n[*] {1}의\n[*] {0} 메뉴입니다.\n' + +# 선택한 버튼이 학식이 아닐 경우 +select_else_button = '[*] 선택한 버튼 : {0}\n' + +# 종강 버튼 선택 시 +end_day = '[*] 오늘 : {0}\n[*] 종강 : {1}\n[*] 종강까지 {2}일 남았습니다.' + +# json 파일 오픈 예외 문자 +json_open_error = '\n에러메세지가 보이면 관리자에게 알려주세요.' + +# 일요일 예외 +sun_except = '\n일요일에 {0} 식당은\n운영하지 않습니다.' + +# 주말 예외 +weekend_except = '\n주말에 {0} 식당은\n운영하지 않습니다.' + +# Wi-Fi 정보 +wifi_info = '[*] ID : H(대문자)+학번(8자리)\n[*] 비밀번호 : 생년월일\n[*] 예시 : H20171234\n[*] 예시 : 980101' + +# 심각한 오류 +fatal_error = '[*] 심각한 오류입니다.\n[*] 개발자에게 알려주세요' diff --git a/app/views.py b/app/views.py index 6ac525bf..a187b9a9 100644 --- a/app/views.py +++ b/app/views.py @@ -1,11 +1,12 @@ from django.shortcuts import render from django.http import JsonResponse from django.views.decorators.csrf import csrf_exempt +from app.my_module.button import * +from app.my_module.repdic import * +from app.my_module.scheduleparser import * +from app.my_module.stringformat import * from pytz import timezone -from bs4 import BeautifulSoup -import requests, os, re -import datetime -import json +import requests, datetime, json # 데이터 목록 # menu/SnowFlowerOne.json 향설1 생활관 @@ -22,32 +23,12 @@ [*] 새로운 기능 문의 환영 [*] 에러 발견 문의 환영''' -# 선택한 버튼이 학식 메뉴일 경우 메세지 포매팅 -select_button = '[*] 선택한 버튼 : {0}\n[*] {1}의\n[*] {0} 메뉴입니다.\n' - # 데이터를 보기 좋게 출력하기 위한 문자열 처리 함수 def char_replace(meal) : - meal = meal.translate({ ord('['): '', ord(']'): '', ord('{'): '', ord('}'): '', ord("'"): '', ord(','): '\n', ord(':'): '\n',ord(' '): ''}) - meal = meal.replace('\n', '\n·') - meal = meal.replace('-중식/석식-', '\n[중식/석식]') - meal = meal.replace('-조식-', '\n[조식]') - meal = meal.replace('-컵밥-', '\n[컵밥]') - meal = meal.replace('-중식-', '\n[중식]') - meal = meal.replace('-석식-', '\n[석식]') - meal = meal.replace('-한식-', '\n[한식]') - meal = meal.replace('-덮밥-', '\n[덮밥]') - meal = meal.replace('-양식-', '\n[양식]') - meal = meal.replace('-도시락-', '\n[도시락]') - meal = meal.replace('-스페셜메뉴-', '\n[스페셜메뉴]') - meal = meal.replace('-돈까스-', '\n[돈까스]') - meal = meal.replace('-라면-', '\n[라면]') - meal = meal.replace('-메뉴-', '\n[메뉴]') - meal = meal.replace('-부대라면-', '\n[부대라면]') - meal = meal.replace('-한정메뉴-', '\n[한정메뉴]') - meal = meal.replace('-샐러드바-', '\n[샐러드바]') - meal = meal.replace('\n·\n', '\n\n') - meal = meal.replace('·', '· ') + for key, value in trans_dic.items() : + + meal = meal.replace(key, value) return meal @@ -63,7 +44,7 @@ def re_process(output) : 'keyboard': { 'type': 'buttons', - 'buttons' : ['학식', '종강', '학사 일정', '개발자 정보'] + 'buttons' : basic_button } } ) @@ -80,7 +61,7 @@ def food_sel_process() : 'keyboard' : { 'type' : 'buttons', - 'buttons' : ['향설1 생활관', '향설2 생활관', '향설3 생활관', '학생회관', '교직원 식당', '처음으로'] + 'buttons' : food_sel_process_button } } ) @@ -90,7 +71,7 @@ def keyboard(request) : return JsonResponse ( { 'type' : 'buttons', - 'buttons' : ['학식', '종강', '학사 일정', '처음으로', '개발자 정보'] + 'buttons' : basic_button } ) @@ -142,10 +123,10 @@ def answer(request) : meal = char_replace(meal) else : - meal = '\n일요일에 ' + content_name + ' 식당은\n운영하지 않습니다.' + meal = sun_except.format(content_name) except Exception as e: - meal = str(e) + '\n에러메세지가 보이면 관리자에게 알려주세요.' + meal = str(e) + json_open_error send_message = select_button.format(content_name, today_info) + meal @@ -162,10 +143,10 @@ def answer(request) : meal = char_replace(meal) else : - meal = '\n주말에 ' + content_name + ' 식당은\n운영하지 않습니다.' + meal = weekend_except.format(content_name) except Exception as e: - meal = str(e) + '\n에러메세지가 보이면 관리자에게 알려주세요.' + meal = str(e) + json_open_error send_message = select_button.format(content_name, today_info) + meal @@ -202,7 +183,7 @@ def answer(request) : meal = char_replace(meal) except Exception as e: - meal = str(e) + '\n에러메세지가 보이면 관리자에게 알려주세요.' + meal = str(e) + json_open_error send_message = select_button.format(content_name, today_info) + meal @@ -235,10 +216,10 @@ def answer(request) : meal = char_replace(meal) else : - meal = '\n주말에 ' + content_name + ' 식당은\n운영하지 않습니다.' + meal = weekend_except.format(content_name) except Exception as e: - meal = str(e) + '\n에러메세지가 보이면 관리자에게 알려주세요.' + meal = str(e) + json_open_error send_message = select_button.format(content_name, today_info) + meal @@ -271,98 +252,59 @@ def answer(request) : meal = char_replace(meal) else : - meal = '\n주말에 '+ content_name + '은\n운영하지 않습니다.' + meal = weekend_except.format(content_name) except Exception as e: - meal = str(e) + '\n에러메세지가 보이면 관리자에게 알려주세요.' + meal = str(e) + json_open_error send_message = select_button.format(content_name, today_info) + meal return re_process(send_message) elif content_name == '처음으로' : - return re_process(content_name) + return re_process(content_name) - elif content_name == '종강' : + elif content_name == '교내 Wi-Fi' : - # 종강 일 - finish = datetime.datetime(2018, 6, 22) - finish_info = finish.strftime('%Y년 %m월 %d일') - date_dif = finish - today - - send_message = '[*] 선택한 버튼 : ' + content_name + '\n[*] 오늘 : ' + today_info + '\n[*] 종강 : ' + finish_info + '\n[*] 종강까지 %d일 남았습니다.' % date_dif.days + send_message = select_else_button.format(content_name) + wifi_info return re_process(send_message) - elif content_name == '학사 일정' : - - # Location of parser.py - BASE_DIR = os.path.dirname(os.path.abspath(__file__)) + elif content_name == '종강' : - # HTTP GET Request - request = requests.get('https://homepage.sch.ac.kr/sch/05/05010000.jsp') + # 종강 일 + try : + finish = datetime.datetime(2018, 6, 22) + finish_info = finish.strftime('%Y년 %m월 %d일') + date_dif = finish - today - # GET HTML Source - html = request.text - # Use BeautifulSoup, From HTML Source to Python Object - # First Parameter is HTML Source, Second Parameter is the parser to be used - soup = BeautifulSoup(html, 'html.parser') + send_message = select_else_button.format(content_name) + end_day.format(today_info, finish_info, date_dif.days) - # HTML element using CSS Selector - schedules = soup.find_all('a', {'class' : 'schedule'}) + except Exception as e : + send_message = str(e) - schedule_day = [] - schedule_list = [] + return re_process(send_message) - for schedule in schedules: - # 날짜 가져오기 - schedule_day.append(schedule.text) - # 세부 내용 가져오기 - schedule_list.append(schedule.get('title')) + elif content_name == '학사 일정' : - idx = 0 + result_message = parser() today_info = today.strftime('%Y년 %m월') - result_message = '의 학사일정' - - for schedule in schedule_day : - schedule_message = '\n[' + str(schedule) + '일 일정]\n' + '· ' + schedule_list[idx] - result_message = str(result_message) + schedule_message - idx += 1 - - # GET HTTP Header - header = request.headers - - # GET HTTP Status ( 200 : normal ) - status = request.status_code - - # Check HTTP ( TRUE / FALSE ) - is_HTTP_OK = request.ok - - send_message = '[*] 선택한 버튼 : ' + content_name + '\n[*] ' + today_info + result_message + send_message = select_else_button.format(content_name) + '[*] ' + today_info + result_message return re_process(send_message) elif content_name == '개발자 정보' : - send_message = '[*] 선택한 버튼 : ' + content_name + '\n' + dev_info + send_message = select_else_button.format(content_name) + dev_info return re_process(send_message) else : - error_message = '[*] 심각한 오류입니다.\n[*] 개발자에게 알려주세요' - - if type_name == 'photo' : - error_message = '[*] 사진을 보내도 기능이 없네요.\n[*] 버튼을 눌러주세요!' - - elif type_name == 'video' : - error_message = '[*] 영상을 보내도 기능이 없네요.\n[*] 버튼을 눌러주세요!' - - elif type_name == 'audio' : - error_message = '[*] 녹음 파일을 보내도 기능이 없네요.\n[*] 버튼을 눌러주세요!' + error_message = fatal_error return re_process(error_message)