Skip to content

Commit a7a9b7d

Browse files
committed
v3.3.0: renew richmenu, forward email
1 parent 1c9b30c commit a7a9b7d

File tree

10 files changed

+111
-152
lines changed

10 files changed

+111
-152
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ ID: @096oeofl
1515

1616
## 版本更新紀錄
1717

18+
```v3.3.0``` 新增留言寄信功能,更新圖文選單,選單新增收藏的食譜。
19+
1820
```v3.2.0``` 新增 LIFF 留言功能
1921

2022
```v3.1.4``` 收藏的食譜頁版面更新

__pycache__/app.cpython-39.pyc

810 Bytes
Binary file not shown.

app.py

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
channel_access_token=os.environ["LINE_CHANNEL_ACCESS_TOKEN"])
4040
handler = WebhookHandler(channel_secret=os.environ["LINE_CHANNEL_SECRET"])
4141
os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = "keys/aitouille-adam.json"
42+
# EMAIL_PW = os.environ["GMAIL_PASSWORD"]
4243

4344
# 載入Follow事件
4445
from linebot.models.events import (
@@ -168,19 +169,6 @@ def form():
168169
# print(data)
169170
return render_template('form.html', myliffid=liffid)
170171

171-
172-
# @handler.add(MessageEvent, message=TextMessage)
173-
# def handle_message(event):
174-
# mtext = event.message.text
175-
# if mtext == '@彈性配置':
176-
# sendFlex(event)
177-
#
178-
# elif mtext[:3] == '###' and len(mtext) > 3:
179-
# manageForm(event, mtext)
180-
181-
182-
183-
184172
# =================== LIFF靜態頁面(終) ===================
185173

186174

controllers/line_bot_controller.py

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,12 @@
99
'''
1010

1111
from linebot import (
12-
LineBotApi, WebhookHandler
12+
LineBotApi
1313
)
1414
from linebot.models import TextSendMessage
1515
import os
1616

1717
# 載入Follow事件
18-
from linebot.models.events import (
19-
FollowEvent, UnfollowEvent, PostbackEvent
20-
)
2118

2219
line_bot_api = LineBotApi(channel_access_token=os.environ["LINE_CHANNEL_ACCESS_TOKEN"])
2320

@@ -26,15 +23,12 @@
2623
from services.video_service import VideoService
2724
from services.audio_service import AudioService
2825
from services.text_service import TextService
29-
from services.email_sevice import EmailService
3026

3127
from google.cloud import bigquery as bq
3228
import os
3329

3430
os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = "keys/aitouille-adam.json"
3531

36-
from urllib.parse import parse_qs
37-
3832
bq_client = bq.Client()
3933

4034
class LineBotController:
@@ -73,16 +67,7 @@ def handle_video_message(cls, event):
7367
def handle_audio_message(cls, event):
7468
AudioService.line_user_upload_audio(event)
7569
return "OK"
76-
# ================== 施工區分隔線 ======================
77-
# 2021/12/24 USER留言轉寄EMAIL
78-
79-
@classmethod
80-
def handle_user_message(cls, event):
81-
EmailService.line_user_leave_message(event)
82-
return "OK"
8370

84-
# ================== 施工區分隔線 ======================
85-
# 2021/12/21 Charles
8671
@classmethod
8772
def handle_postback_event(cls, event):
8873
# 寫一個判斷處理給建議的postback data: 因為處理格式不同會出錯,需另外處理(暫時先用MessageTemplateAction,待處理)

richmenu.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
## ========== 新增 Rich menus,並透過line API 取得 rich_menu_link ==========
1010
## (! 配合圖片格式修改參數)
1111

12-
import requests , json
12+
import requests, json
1313

1414
headers = {"Authorization":"Bearer "+CHANNEL_ACCESS_TOKEN,"Content-Type":"application/json"}
1515

@@ -24,22 +24,27 @@
2424
"action": {"type": "uri", "uri": "https://line.me/R/nv/camera/"}
2525
},
2626
{
27-
"bounds": {"x": 625, "y": 0, "width": 625, "height": 635},
27+
"bounds": {"x": 500, "y": 0, "width": 625, "height": 635},
2828
"action": {"type": "uri", "uri": "https://line.me/R/nv/cameraRoll/multi"},
2929
},
30+
# TODO: 先傳文字開啟收藏的食譜,之後改用Postback試試看藏網址直接開網頁
3031
{
31-
"bounds": {"x": 1250, "y": 0, "width": 625, "height": 635},
32+
"bounds": {"x": 1000, "y": 0, "width": 625, "height": 635},
33+
"action": {"type": "message", "text": "收藏的食譜"},
34+
},
35+
{
36+
"bounds": {"x": 1500, "y": 0, "width": 625, "height": 635},
3237
"action": {"type": "uri", "uri": "https://line.me/R/nv/recommendOA/@096oeofl"}
3338
},
3439
{
35-
"bounds": {"x": 1875, "y": 0, "width": 625, "height": 635},
40+
"bounds": {"x": 2000, "y": 0, "width": 625, "height": 635},
3641
"action": {"type": "uri", "uri": "https://liff.line.me/1656700369-VlnBxlo4"}
3742
}
3843
]
3944
}
4045

4146
req = requests.request('POST', 'https://api.line.me/v2/bot/richmenu',
42-
headers=headers,data=json.dumps(body).encode('utf-8'))
47+
headers=headers, data=json.dumps(body).encode('utf-8'))
4348

4449
richmenuId = json.loads(req.text).get("richMenuId")
4550

@@ -52,7 +57,7 @@
5257
line_bot_api = LineBotApi(CHANNEL_ACCESS_TOKEN)
5358

5459
## (! 配合圖片修改檔名"richmenu.jpg"及圖片形式"image/jpeg")
55-
with open("pic/richmenu.jpg",'rb') as f:
60+
with open("pic/richmenu_5.jpg",'rb') as f:
5661
line_bot_api.set_rich_menu_image(richmenuId, "image/jpeg", f)
5762

5863

@@ -63,7 +68,7 @@
6368

6469
req = requests.request('POST', 'https://api.line.me/v2/bot/user/all/richmenu/'+richmenuId,
6570
headers=headers)
66-
print(req.text)
71+
# print(req.text)
6772

6873

6974
# # ========== 查看所有 Rich menus(最多100組) ==========

services/audio_service.py

Lines changed: 5 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
# 修改紀錄:
2-
# 2021/12/21 Charles
31
'''
42
用戶上傳音訊檔時,將音訊檔從Line取回,轉成文字訊息,
53
並將音訊檔放入CloudStorage
@@ -67,10 +65,10 @@ def line_user_upload_audio(cls, event):
6765
# 從雲端取值的作法
6866
gcs_uri = 'gs://' + bucket_name + '/' + destination_blob_name
6967
audio = speech.RecognitionAudio(uri=gcs_uri)
70-
68+
reply_transcript = ""
7169
config = speech.RecognitionConfig(
7270
{
73-
"encoding": speech.RecognitionConfig.AudioEncoding.MP3, # 這邊卡關超久, 官方文件這邊有說明MP3檔要使用v1p1beta版本才行
71+
"encoding": speech.RecognitionConfig.AudioEncoding.MP3, # 官方文件這邊有說明MP3檔要使用v1p1beta版本才行
7472
"sample_rate_hertz": 16000,
7573
"language_code": "zh-TW"
7674
}
@@ -83,34 +81,20 @@ def line_user_upload_audio(cls, event):
8381
# 移除本地檔案
8482
os.remove(temp_file_path)
8583

86-
# option:1 ----- 將reply_transcript截取出食材,把每一個食材分別進資料庫做搜尋 ------ #
87-
88-
# test_voice_input = "我有雞肉白蘿蔔香菇玉米洋蔥,可以煮什麼?"
89-
# utils.text_parsing裡面的方法,將一句話裡面有的食材切出來回傳一個list
90-
9184
# 引用utils/text_parsing.py裡面的方法來把食材切出來
9285
ingredients_from_audio = TextService.get_ingredients(reply_transcript)
93-
86+
# print(ingredients_from_audio)
9487
reply_msg = [TextSendMessage(f"語音輸入: {reply_transcript}")]
9588

9689
if len(ingredients_from_audio) == 0:
97-
# TODO: 如果user傳來的文字訊息不包含可辨識的食材,回覆user一句話
90+
# 如果user傳來的文字訊息不包含可辨識的食材,回覆user一句話
9891
reply_message = TextService.get_intent(reply_transcript)
9992
cls.line_bot_api.reply_message(
10093
event.reply_token,
10194
TextSendMessage(reply_message)
10295
)
10396
else:
104-
# TODO ~~~~~~~~~~~~~~~~~開發中 以下為原版~~~~~~~~~~~~~~~~~~~~~~~
105-
# TODO: 串接資料庫->複數食材搜尋
106-
# dishes = multiple_ingredient_search(ingredients_from_audio, len(ingredients_from_audio))
107-
# reply_msg += dishes
108-
# # 回覆訊息給使用者
109-
# cls.line_bot_api.reply_message(
110-
# event.reply_token,
111-
# reply_msg
112-
# )
113-
# TODO: 串接資料庫->複數食材搜尋
97+
# 串接資料庫->複數食材搜尋
11498
# 2021/12/21 Charles 新增user_id參數
11599
dishes = multiple_ingredient_search(ingredients_from_audio, len(ingredients_from_audio), event.source.user_id)
116100
new_template = TextService.make_template(dishes)
@@ -119,5 +103,3 @@ def line_user_upload_audio(cls, event):
119103
event.reply_token,
120104
reply_msg
121105
)
122-
123-
# option:2 ----- 將reply_transcript截取出食材,進資料庫做複數食材搜尋 ------ #

services/email_sevice.py

Lines changed: 0 additions & 66 deletions
This file was deleted.

services/text_service.py

Lines changed: 35 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,13 @@
1212
import os
1313
import random
1414
import jieba
15-
from daos.user_dao import UserDAO
1615
from linebot.models import (
17-
TextSendMessage, CarouselTemplate, CarouselColumn, URITemplateAction, PostbackAction, TemplateSendMessage,
18-
MessageTemplateAction
16+
TextSendMessage, CarouselTemplate, CarouselColumn, URITemplateAction, PostbackAction, TemplateSendMessage
1917
)
2018
# 搜尋食譜
21-
19+
from services.user_service import UserService
2220
from utils.search_recipe import multiple_ingredient_search
21+
from utils.send_email import send_email
2322

2423

2524
class TextService:
@@ -43,20 +42,26 @@ def line_user_send_text_message(cls, event):
4342
cls.line_bot_api.reply_message(
4443
event.reply_token,
4544
TextSendMessage(f"我收藏的食譜: https://ai-touille-6qzlayuaza-de.a.run.app/my_cookbook/{user_id}")
46-
# TextSendMessage(f"我收藏的食譜: https://8a57-180-218-204-111.ngrok.io/my_cookbook/{user_id}")
45+
# TextSendMessage(f"我收藏的食譜: https://1854-180-218-204-111.ngrok.io/my_cookbook/{user_id}")
4746
)
48-
# TODO: 施工區:處理官網留言
47+
# 處理官網&form留言
4948
elif user_message[:3] == "###":
50-
print("this is a message form")
51-
msg = cls.manageForm(user_message)
49+
# 取得用戶名字
50+
user_object = UserService.get_user(event.source.user_id)
51+
user_nickname = user_object.line_user_nickname
52+
# print("this is a message form")
53+
# 處理成易讀的格式回覆用戶收到訊息
54+
msg = cls.manageForm(mtext=user_message)
5255
cls.line_bot_api.reply_message(
5356
event.reply_token,
5457
msg
5558
)
59+
# 寄信到客服信箱
60+
send_email(msg=user_message[3:], user_nickname=user_nickname)
5661
else:
5762
ingredients = cls.get_ingredients(user_message)
5863
if len(ingredients) == 0:
59-
# TODO: 如果user傳來的文字訊息不包含可辨識的食材,回覆user一句話
64+
# 如果user傳來的文字訊息不包含可辨識的食材,回覆user一句話
6065
reply_message = cls.get_intent(user_message)
6166
cls.line_bot_api.reply_message(
6267
event.reply_token,
@@ -76,6 +81,20 @@ def line_user_send_text_message(cls, event):
7681
new_template
7782
)
7883

84+
@classmethod
85+
def manageForm(cls, mtext):
86+
try:
87+
flist = mtext[3:].split('/')
88+
text = '姓名:' + flist[0] + '\n'
89+
text += '建議:' + flist[1] + '\n'
90+
text += '感謝您的留言,我們已經收到囉!😃'
91+
message = TextSendMessage(
92+
text=text
93+
)
94+
return message
95+
except:
96+
return "發生錯誤!"
97+
7998
# 用結巴分詞抓出資料庫中有的食材的新方法
8099
@classmethod
81100
def get_ingredients(cls, text):
@@ -147,7 +166,9 @@ def get_intent(cls, text):
147166
result = "你可以傳食材照片或是用打字的告訴我你有哪些食材,我會推薦適合的食譜給你,開啟麥克風傳語音訊息也可以喔!"
148167
# TODO: 可以針對Give feedback做另外的對話處理
149168
elif intent == "give_feedback":
150-
result = "好的,請說 😊 https://liff.line.me/1656700369-MrdvmrAb"
169+
result = "好的,請說 😊 https://liff.line.me/1656700369-9wG4ra7O"
170+
elif intent == "":
171+
result = "聽不到你的聲音喔!"
151172
else:
152173
result = "收到~ 更多功能開發中,敬請期待未來的AI服務!"
153174

@@ -198,9 +219,11 @@ def make_template(cls, dishes):
198219
label='沒有我要的食譜',
199220
uri='https://icook.tw/' # TODO 這邊先放icook的連結
200221
),
201-
MessageTemplateAction(
222+
URITemplateAction(
202223
label='給建議',
203-
text='我要留言'
224+
# uri='https://liff.line.me/1656700369-MrdvmrAb' # 愛廚易官方留言form的LIFF URL
225+
# 開發版,串到Beta的機器人
226+
uri='https://liff.line.me/1656700369-9wG4ra7O'
204227
)
205228
]
206229
)
@@ -230,16 +253,3 @@ def get_tip(cls):
230253
]
231254
random.shuffle(tips)
232255
return tips[0]
233-
234-
@classmethod
235-
def manageForm(cls, mtext):
236-
try:
237-
flist = mtext[3:].split('/')
238-
text1 = '姓名:' + flist[0] + '\n'
239-
text1 += '建議:' + flist[1]
240-
message = TextSendMessage(
241-
text=text1
242-
)
243-
return message
244-
except:
245-
return "發生錯誤!"

0 commit comments

Comments
 (0)