3.2 處理使用者輸入的內容
在 3.1 的範例中我們看到了可以使用 builder.Prompts
來提示使用者輸入文字資料,不過 builder.Prompts
不僅能處理使用者的文字內容,也可以提示使用者輸入數字、清單選項、時間、確認、甚至是多媒體內容 (附件)。這一篇就是介紹如何處理使用者的輸入。
輸入內容的對話流程
在 Bot Framework 中,提示使用者輸入內容時,就要到對話的下一個流程來接收輸入的結果,而輸入的內容就會放在下一個對話流程中的參數裡。
dialog('greeting', [
(session) => {
builder.Prompts.text('請問您叫什麼名字?');
},
(session, results) => {
session.endDialog(`您的名字是${results.response}`);
}
]);
上面這個例子示範了在前一個對話流程中提示使用者輸入他的名字(一段文字),而在下一個對話流程中再以 results
去接輸入的內容,而文字資料就放在 results.response
中。
提示使用者輸入的資料類別
目前 builder.Prompts
支援下面幾種資料類別:
提示輸入的類型 | 說明 |
---|---|
Prompts.text | 輸入純文字內容。 |
Prompts.confirm | 請使用者確認動作。 |
Prompts.number | 輸入數字內容。 |
Prompts.time | 輸入時間內容。 |
Prompts.choice | 提供給使用者一個清單做選擇。 |
Prompts.attachment | 輸入附件資料,如圖片、檔案等多媒體內容。 |
Prompts.text
提示使用者輸入一段文字,回傳的內容會是 string 型態。
builder.Prompts.text(session, '請問怎麼稱呼您?');
這樣會顯示「請問怎麼稱呼您?」後等待使用者輸入內容,results.response
會是一個字串內容的資料。
Prompts.confirm
請使用者用 yes 或 no (也可以是 Y/y 或 N/n)的回答來進行確認。
builder.Prompts.confirm(session, '您確定要修改嗎?');
用戶回覆的內容會是一個 boolean 值,所以回答 yes 時 results.response
會是 true
否則則為 false
。
但若用戶輸入預期以外的內容時,它預設會顯示「I didn’t understand. Please answer ‘yes’ or ‘no’.」如果要修改這段提示文字,可以在 Prompts.confirm
呼叫中加入 retryPrompt
的選項,像是這樣:
builder.Prompts.confirm(session, '您確定要修改嗎?', {
retryPrompt: '不好意思,請輸入 yes 或是 no 來回答'
});
這樣就會用設定的文字訊息來提示使用者該怎麼輸入。
所有的 Prompts 都可以用相同的方式來設定 retryPrompt。
Prompts.number
請使用者輸入數值資料(包含整數及浮點數),results.response
的資料就是 number 型態。
builder.Prompts.number(session, '請問您想買幾個呢?', {
retryPrompt: '不好意思,請輸入數字'
});
Prompts.time
請使用者輸入時間資料,這個功能是使用 Chrono 這套時間格式解析的函式庫實作的(支援中文!),所以支援的時間格式與此函式庫相同,支援絕對時間以及相對時間的描述。而要將使用者輸入的時間資料轉換為 JavaScript 的 Date 型態則需要使用 builder.EntityRecognizer.resolveTime()
來做轉換。
時間會被轉換成 UTC 時間。
bot.dialog('reserve', [
(session) => {
builder.Prompts.time(session, '請問要訂幾點呢?', {
retryPrompt: '請輸入正確的時間格式'
});
},
(session, results) => {
let time = builder.EntityRecognizer.resolveTime([results.response]);
session.endDialogWithResult({ time: time });
}
]);
results.response.entity 會拿到使用者原始的輸入資料,例如使用者輸入「三天後」就會直接拿到
三天後
。
Prompts.choice
讓使用者從一個清單中選取一個選項來回答。決定選項的方式可以使用 |
分隔的字串:
builder.Prompts.choice(session, "請問您要點什麼飲料呢?", "綠茶|紅茶|奶茶");
或是字串陣列:
builder.Prompts.choice(session, '請問您要點什麼飲料呢?', ['綠茶', '紅茶', '奶茶']);
或是 JSON 物件:
builder.Prompts.choice(session, '請問您要點什麼飲料呢?', {
"綠茶": {
"Price": 30
},
"紅茶": {
"Price": 30
},
"奶茶": {
"Price": 35
}
});
而選擇的結果會放在 results.response.entity
中,內容就是清單上的文字。或者也可以從 results.response.index
中拿到清單陣列的索引值 (從 0 開始)。
而清單選項的選擇方式也可以由幾個常數來設定樣式:
索引值 | 常數名稱 | 樣式效果 |
---|---|---|
0 | builder.ListStyle.none |
不特別顯示清單,變成提示文字的一部份。 |
1 | builder.ListStyle.inline |
直顯顯示一行清單,並以數字編排。 |
2 | builder.ListStyle.list |
顯示一個有數字編號的清單。 |
3 | builder.ListStyle.button |
如果通訊平台支援就將選項顯示成按鈕,否則顯示成文字。 |
4 | builder.ListStyle.auto |
自動根據通訊平台或清單數量來決定顯示樣式。 |
樣式在 bot framework emulator 中看起來都一樣,必須要部署到通訊平台上才會顯示出不同的樣式。
Prompts.attachment
提示使用者上傳圖片、檔案或是其它多媒體檔案,而上傳的資料就跟處理訊息的附件一樣(可參考 2.2 的範例),只是 results.response
就是 attachments
的附件資料內容。
bot.dialog('editAvatar', [
(session) => {
builder.Prompts.attachment(session, "請上傳一張照片作為您的大頭貼");
},
(session, results) => {
if (results.response.length > 0) {
session.dialogData.file = results.response[0];
builder.Prompts.confirm(session, "您是否要用這張照片作為大頭貼呢?");
} else {
session.endDialog('發生錯誤');
}
},
(session, results) => {
let endingMessage;
if (results.response) {
// 使用 session.dialogData.file 修改照片
endingMessage = '好的,已為您修改大頭貼';
} else {
endingMessage = '瞭解,動作已取消';
}
session.endDialog(endingMessage);
}
]);