shihxuancheng 5 years ago
parent
commit
ead96f919c
10 changed files with 147 additions and 95 deletions
  1. 11
      back_end/bot_app/__init__.py
  2. 2
      back_end/bot_app/fulfillment/buying_drink.py
  3. 7
      back_end/bot_app/fulfillment/controllers.py
  4. 16
      back_end/bot_app/fulfillment/system_pic.py
  5. 37
      back_end/bot_app/fulfillment/utility.py
  6. 151
      back_end/bot_app/fulfillment/whl_family.py
  7. 5
      back_end/config.py
  8. 12
      credential/qa_bot_auth.json
  9. 0
      front_end/detect_intent_texts.py
  10. 1
      resources/assets/qa_bot dialog flow.drawio

11
back_end/bot_app/__init__.py

@ -1,19 +1,14 @@
from flask import Flask
import bot_app.fulfillment.utility as util
from bot_app.fulfillment.controllers import fulfillment
import bot_app.fulfillment.controllers as controller
app = Flask(__name__)
app.config.from_object('config')
app.register_blueprint(fulfillment)
controller.init_app(app)
util.init_app(app)
@app.route('/')
def index():
return 'Service Working!!!'
@app.route('/test')
def test():
return util.simple_response('Hello World Test!!')
return 'Service Working!!!'

2
back_end/bot_app/fulfillment/buying_drink.py

@ -74,4 +74,6 @@ def ordering_delivery_info(fulfillment):
}
})
def init_app(app):
pass

7
back_end/bot_app/fulfillment/controllers.py

@ -54,3 +54,10 @@ def fetch_url():
print(res.json())
result = res
return res
def init_app(app):
app.register_blueprint(fulfillment)
util.init_app(app)
buying_drink.init_app(app)
system_pic.init_app(app)
whl_family.init_app(app)

16
back_end/bot_app/fulfillment/system_pic.py

@ -30,9 +30,17 @@ def looking_for_pic(fulfillment):
return util.simple_response(text_content=strRes)
# 取消問題轉達給pic
def cancel_forward(fulfillment):
util.reset_all_contexts(fulfillmentObj=fulfillment)
return util.simple_response(fulfillmentObj={
'outputContexts': fulfillment.get('queryResult').get('outputContexts')
})
# 確認轉達問題給pic
def confirm_forward(fulfillment):
print(fulfillment)
return util.simple_response(fulfillmentObj={
'followupEventInput': {
'name': 'events_forward_issue',
@ -41,6 +49,7 @@ def confirm_forward(fulfillment):
}
})
# 轉達問題給pic
def forward_issue(fulfillment):
params = fulfillment.get('queryResult').get('parameters')
@ -53,4 +62,7 @@ def forward_issue(fulfillment):
user_name = 'Richard Shih'
strRes = '好的' + user_name + '已將您的問題 "' + issue + '" 轉達給 ' + sys_code + ' 負責人'
return util.simple_response(text_content=strRes)
return util.simple_response(text_content=strRes)
def init_app(app):
pass

37
back_end/bot_app/fulfillment/utility.py

@ -1,10 +1,11 @@
from flask import jsonify
from sqlalchemy import create_engine
db_engine = None
def simple_response(text_content='', fulfillmentObj=None):
if not fulfillmentObj==None:
if not fulfillmentObj == None:
jsonResp = fulfillmentObj
else:
jsonResp = {
@ -36,10 +37,30 @@ def simple_response(text_content='', fulfillmentObj=None):
return jsonify(jsonResp)
def lookup_context(fulfillment,lookup_pattern):
def lookup_context(fulfillment, lookup_pattern):
contexts = fulfillment.get('queryResult').get('outputContexts')
search_key = fulfillment.get('session') + '/contexts/' + lookup_pattern
return next((x for x in contexts if x['name']== search_key),None)
return next((x for x in contexts if x['name'] == search_key), None)
# 清除所有的Output Contexts
def reset_all_contexts(fulfillmentObj=None,context_list=[]):
if 'queryResult' in fulfillmentObj.keys():
contexts = fulfillmentObj.get('queryResult').get('outputContexts')
else:
contexts = fulfillmentObj.get('outputContexts')
for context in contexts:
if len(context_list) > 0:
if context['name'] in context_list:
context['lifespanCount'] = 0
else:
context['lifespanCount'] = 0
return fulfillmentObj
def get_db_conn():
try:
@ -48,13 +69,13 @@ def get_db_conn():
except Exception as e:
print(str(e))
def init_app(app, pre_connect = True):
def init_app(app, pre_connect=True):
global db_engine
db_engine = create_engine(app.config['SQLALCHEMY_DATABASE_URI'], encoding='utf8')
db_engine = create_engine(app.config['SQLALCHEMY_DATABASE_URI'], encoding='utf8')
pre_connect = app.config['DATABASE_CONNECT_OPTIONS']['PRE_CONNECT']
if pre_connect:
try:
conn = db_engine.connect()
except Exception as e:
except Exception as e:
print(str(e))

151
back_end/bot_app/fulfillment/whl_family.py

@ -1,35 +1,41 @@
# %%
import requests
from bs4 import BeautifulSoup as bs
import bot_app.fulfillment.utility as util
from datetime import datetime
base_url = 'http://family.wanhai.com'
loginURL = base_url + '/Login.jsp'
account = 'M1933'
password = 'Whlm1933'
account = None
password = None
payload = {'Account': account, 'Password': password}
meeting_rooms = None
massage_rooms = None
session_req = None
# session_req.post(loginURL,data=payload)
def getSession(check_login=True):
global session_req
if session_req is None:
session_req = requests.Session()
if check_login and not isLogin():
login(account, password)
return session_req
# %%
def login(id, pw):
global session_req
if session_req is None:
session_req = requests.Session()
res = session_req.post(
loginURL, data={'Account': account, 'Password': password})
base_url + '/Login.jsp', data={'Account': id, 'Password': pw})
print(res.request.headers['Cookie'])
# %%
def isLogin():
global session_req
if session_req is None:
session_req = requests.Session()
route_url = base_url + '/MainPage.jsp'
route_url = base_url + '/LeaseEquip/equipListOnePage.jsp'
res = session_req.get(route_url, allow_redirects=False)
if res.status_code == 200:
print(res.request.headers['Cookie'])
@ -38,10 +44,10 @@ def isLogin():
return False
# %%
def getEquipList(type='MEETING'):
# 取得可用設備列表
def get_equip_list(type='MEETING'):
equipList_url = base_url + '/LeaseEquip/equipListOnePage.jsp'
result = session_req.get(
result = getSession().get(
equipList_url + '?file_num=61621&account_id=' + account + '&equip_type=' + type)
print(result.request.headers['Cookie'])
@ -54,8 +60,8 @@ def getEquipList(type='MEETING'):
return equipDict
# %%
def getEquipName(equipId):
# 取得設備名稱
def get_equip_name(equipId):
if equipId in meeting_rooms.keys():
return meeting_rooms[equipId]['name']
elif equipId in massage_rooms.keys():
@ -64,31 +70,30 @@ def getEquipName(equipId):
return None
# %%
# 查詢設備是否已被占用(by 特定日期/時段)
def isEquipInUsed(b_date, b_time, e_time, equip_type, equip_id):
def is_equip_in_use(equip_id, b_date=datetime.today(), b_time=datetime.now(), e_time=datetime.now(),
equip_type='MEETING'):
if equip_type == 'MASSAGE':
print('Not Support Now!!!')
return False
equipUsageURL = base_url + '/LeaseEquip/equipUsage.jsp'
payload = [('q_from_date', b_date),
('q_from_time', b_time),
('q_to_date', b_date),
('q_to_time', e_time),
payload = [('q_from_date', datetime.strftime(b_date, '%Y%m%d')),
('q_from_time', datetime.strftime(b_time, '%H:%M:%S')),
('q_to_date', datetime.strftime(b_date, '%Y%m%d')),
('q_to_time', datetime.strftime(e_time, '%H:%M:%S')),
('q_equip_type', equip_type),
('ID_keyD', equip_id)]
result = session_req.post(equipUsageURL, data=payload)
result = getSession().post(equipUsageURL, data=payload)
soup = bs(result.text, 'html.parser')
elements = soup.select('td > b')
if (len(elements) > 1) and (not '目前無人預約' in elements[1].text):
if (len(elements) > 1) and ('目前無人預約' not in elements[1].text):
return True
else:
return False
return False
# %%
# 查詢設備可用時段(by 特定日期
# 查詢設備可用時段(by 特定日期)
def search_available_time(equip_type, equip_id, strDate):
if equip_type == 'MASSAGE':
print('Not Support Now!!!')
@ -107,7 +112,6 @@ def search_available_time(equip_type, equip_id, strDate):
print('{}:\n{}'.format(equip_id, soup.select('td[nowrap]')[0].text))
# %%
# 查詢可用設備(by 特定日期/時段)
def search_available_equips(equip_type, strDate, b_time, e_time):
if equip_type == 'MASSAGE':
@ -122,7 +126,7 @@ def search_available_equips(equip_type, strDate, b_time, e_time):
('q_equip_type', equip_type)]
payload.extend([('ID_keyD', e) for e in meeting_rooms.keys()])
result = session_req.post(equipUsageURL, data=payload)
result = getSession().post(equipUsageURL, data=payload)
soup = bs(result.text, 'html.parser')
equips = [equip.text.strip() for equip in soup.select(
'div[id="equips"] td[align="center"]')]
@ -138,7 +142,7 @@ def search_available_equips(equip_type, strDate, b_time, e_time):
map(lambda bb: [int(x) for x in bb], periods))]
# print(equips[index])
# for pp in periodIntvs:
# for pp in periodIntvs:ontext['lifespanCount'] = 0
# print(pp,'\n')
for periodIntv in periodIntvs:
@ -152,9 +156,8 @@ def search_available_equips(equip_type, strDate, b_time, e_time):
print('{}\n'.format(equips[index]))
# %%
# 預約設備
def bookingEquip(equip_id, equip_type, strDate, b_time, e_time):
def booking_equip(equip_id, equip_type, strDate, b_time, e_time):
if equip_type == 'MASSAGE':
print('Not Support Now!!!')
bookingURL = base_url + '/LeaseEquip/equipBooking_db.jsp'
@ -184,14 +187,13 @@ def bookingEquip(equip_id, equip_type, strDate, b_time, e_time):
# 'to_date': '20190606',
# 'select_equips': equip_id
}
soup = bs(session_req.post(bookingURL, data=payload).text, 'html.parser')
soup = bs(getSession().post(bookingURL, data=payload).text, 'html.parser')
print(soup.select('table tr:nth-child(2) td:nth-child(5)')[0].text)
# print(soup.prettify())
# %%
# 取消預約設備
def cancalBookingEquip(equip_type, rent_no):
def cancel_booking(equip_type, rent_no):
if equip_type == 'MASSAGE':
print('Not Support Now!!!')
bookingURL = base_url + '/LeaseEquip/userBooking_db.jsp'
@ -209,15 +211,14 @@ def cancalBookingEquip(equip_type, rent_no):
# 'q_rent_no':'',
# 'q_su_id':''
}
soup = bs(session_req.post(bookingURL, data=payload).text, 'html.parser')
soup = bs(getSession().post(bookingURL, data=payload).text, 'html.parser')
print(soup.prettify())
# %%
# 列出個人設備預約紀錄
def listRentedEquips():
def get_rented_equips():
equipList_url = base_url + '/LeaseEquip/equipListOnePage.jsp'
result = session_req.get(
result = getSession().get(
equipList_url + '?file_num=61621&account_id=' + account + '&equip_type=MEETING')
soup = bs(result.text, 'html.parser')
elements = soup.select('form[name="dataForm1"] input[name^="i_rent_no"]')
@ -227,31 +228,53 @@ def listRentedEquips():
return rentedList
# %%
# listRentedEquips()
# %%
# equipId = 'CF15-10F-DN-01'
# print(getEquipName(equipId))
# inUsed = isEquipInUsed('20190606', '1900', '2000', 'MEETING', equipId)
# print('Equip in used? {}'.format(inUsed))
# %%
# search_available_equips('MEETING', '20190624', '0900', '1200')
# %%
# search_available_time('MEETING', 'CF01-9F', '20190624')
# %%
# if not isLogin():
# login(account, password)
# meeting_rooms = getEquipList('MEETING')
# massage_rooms = getEquipList('MASSAGE')
#
# for x in meeting_rooms:
# print(x, meeting_rooms.get(x))
# print('\n')
# for x in massage_rooms:
# print(x, massage_rooms.get(x))
# %%
if __name__ == '__main__':
pass
def list_rented_equips(fulfillment):
rented_list = get_rented_equips()
if len(rented_list) == 0:
return util.simple_response(text_content=u'您目前沒有預約任何的設備')
else:
str_rented_list = u'您預約的設備如下:\n'
str_rented_list += ', \n'.join([x[2] + ' ' + x[3] + ' ' + x[1] for x in rented_list])
return util.simple_response(text_content=str_rented_list)
def list_all_meeting_rooms(fulfillment):
global meeting_rooms
str_meeting_rooms = ', \n'.join([x['id'] + x['name'] for x in meeting_rooms.values()])
return util.simple_response(text_content=str_meeting_rooms)
def check_equip_in_use(fulfillment):
try:
date_pattern = '%Y-%m-%dT%H%M%S%z'
params = fulfillment.get('queryResult').get('parameters')
meeting_room = params.get('meeting_room')
date = datetime.strptime(params.get('date').replace(':', ''), date_pattern)
start_time = datetime.strptime(params.get('time-period').get('startTime').replace(':', ''), date_pattern)
end_time = datetime.strptime(params.get('time-period').get('endTime').replace(':', ''), date_pattern)
meeting_room_id = next([x['id'] for x in meeting_rooms if x['name'].find(meeting_room) >= 0], None)
if is_equip_in_use(meeting_room_id, date, start_time, end_time):
return util.simple_response(text_content=meeting_room+u'已經被人預約')
else:
return util.simple_response(text_content=meeting_room+u'尚未被預約')
except Exception as e:
return util.simple_response(text_content=str(e))
pass
def greet_cancel(fulfillment):
util.reset_all_contexts(fulfillment)
return util.simple_response(fulfillmentObj={
'fulfillmentText': '好的,沒有問題!',
'outputContexts': fulfillment.get('queryResult').get('outputContexts')
})
def init_app(app):
global password, account, meeting_rooms
account = app.config['WHL_FAMILY_ID']
password = app.config['WHL_FAMILY_PW']
login(account, password)
meeting_rooms = get_equip_list()

5
back_end/config.py

@ -10,9 +10,12 @@ BASE_DIR = os.path.abspath(os.path.dirname(__file__))
# SQLite for this example
SQLALCHEMY_DATABASE_URI = 'oracle+cx_oracle://whpr:w2t2pr0614@tpe3.wanhai.com:1526/whl2'
DATABASE_CONNECT_OPTIONS = {
"PRE_CONNECT":True
"PRE_CONNECT": False
}
WHL_FAMILY_ID = 'M1933'
WHL_FAMILY_PW = 'Whlm1933'
# Application threads. A common general assumption is
# using 2 per available processor cores - to handle
# incoming requests using one and performing background

12
credential/qa_bot_auth.json

@ -1,12 +0,0 @@
{
"type": "service_account",
"project_id": "test-bot-wsdwyh",
"private_key_id": "54df4317d1f679ce3c5a5c533c5ad64b20f5d238",
"private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCij2tnfO1/kbq2\naROOVYTT1rIKMuf6G4wcUnOYaS0gLvu1w6WqO0zVN+nafIFGlAkgD7kHwJD8yv8Z\nH1/+4n3TQg5pJCthSB4NLHYwbP3p3tlVyJgdZ+MG8Qx04qLeQzaenq9l4MgL26qs\nGROVeeVfNNxugW7q2UHwmRZ89QtVhZxoHvjcmFLZD85duhifE+6JDBUe+SHUBfyl\nLIiKOD0+8c99IY+VLB+OEzFotEO1DWU7KKRIwVhW0qHChgXRzOmo1X5V1fIqyLaC\nouZkIdLK93nYkIO4S+H2j9svrMCyh3lH/iSxQtt/A+JmKnuCIed+rgKkLQJHaxes\n3uZZaLxFAgMBAAECggEAHu/tkGHxryQUZS/FNYLoBwrmklNS28IPXbqBXmGx4Vyf\nsd18s1Oa0T9VZavpTH3S6MOlQqjuzvVxLB5Q/iirqp95L6BfEyIO+hHaomezwSUU\ntqM48+u4BLOuW7ZgKa2gAPsRRXHMkJkrN5qEJB/xO7fLNcqzScW0K25vHbPjBtDb\nXqF21Uvf3IFrCc+qfS2YlommO0D2kiQP2IM8q4x0nESSyClyX37TurfbTYjQDIn9\nVR8fQG8YriWewJ8O/cxKoZ3y5fzdplj+UbFvbYJEMWl6VREvuYP+gHlfqDawtwYE\n60a8Y6tIkN9qpye7wOiPPwHgsgXsXSH/Gzjt4DXGAQKBgQDeStq6ZQJWGOVrzBHD\nS1fzAMfBb9KAmRb+Jku2K4N4LDTh9ON9CMKMCdgk10btPBrGUYaRAksUQJ3Bg3JB\nuSYr1Clj9UgDoXbkWyCgEIU5EsLF2NmuM3UOTkLslSGWSrC0Vy5MC2m63kxYusyX\nrjxCd51BHuPGBQR3eLk2VmxNRQKBgQC7NdQN45XCH30pfnuc8+vPmxAle+qGhlxc\n2SVpv1NijEDfb9VXlgY62NAktTh5OX5RTgMm0GTmOwCCEnBaSCQHTWuNFVMFkk6D\nUDm/IOkdNdY7J/axLMrB9INSLf/c5fNxseDreKsylYf1vj3xxYslY/r0PYcXG5H1\nsl2tm3wjAQKBgQCEdKAOzx9sRBt4dzniX+PBJabhqYsKG66qtBELNLR7CARe27gu\nCek63qbPlQNrWxQtNej0QSSRpcsawwNzDCsllJ8xM7e8ihq5CV/QYOexUW+Dyqoy\n9fB7HMEeDeLclhbi7svkfix7L/jYKj685xJ7HKE0a36XwOefdO0P5sFT7QKBgF0d\nf/TMjw94BBQgcjF17YNcWCKcyODScZxI8V/wpvPsWNQJ1u5yk3SvpI+th4JcQ2UD\nTXP/0T/mdvE7ZKCzIyBytJz+z0WFKQINZDuZjflWbtELppsncU4ZZTv53zqrMXQK\nipn0cgp975seXcckf3pAiXD0LX4j22x+pDOWk58BAoGAYcywt3jifvKdXbcRE+Wo\nJ/jAgWY2p722bESE2DD0hpsOEwdFPPwG8vr5reEb+PegxLsv7c4vXdemOmj52PEC\nxPDvQEmuKTnA/ORkJT3jEVKYx7Hu9KODlSDTjWM5G9HPevWuJKV6qrmXIbum6L3U\nq7w75gocGx4de/uY0w5Ysyw=\n-----END PRIVATE KEY-----\n",
"client_email": "dialogflow-joojtu@test-bot-wsdwyh.iam.gserviceaccount.com",
"client_id": "118072988943548920832",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/dialogflow-joojtu%40test-bot-wsdwyh.iam.gserviceaccount.com"
}

back_end/bot_app/fulfillment/detect_intent_texts.py → front_end/detect_intent_texts.py

1
resources/assets/qa_bot dialog flow.drawio
File diff suppressed because it is too large
View File

Loading…
Cancel
Save