ทำบอทลงทะเบียนง่ายๆ กับ Sunday Codelabs 4 กับ LINE Developers Thailand
จาก Sunday Codelabs 3 คราวที่แล้ว ที่เราได้หน้ากากผ้าไปอ่ะ แหะๆ แปปๆเขาประกาศ Sunday Codelabs 4 อย่างไวกับ speaker ที่มีแฟนคลับอยากฟังเขาเยอะอยู่ คือคุณหนึ่ง LAE นั่นเอง
ก่อนอื่น เราแอบไปเล่น popcat ก่อน แต่ก็เตรียมอ่าน codelab ตามหัวข้อเลย เพื่อเตรียมตัวอ่ะเนอะ ซึ่งเราใช้โปรเจกเดิม แต่เริ่มจะเละเทะหล่ะน้าา
ไลฟ์สามารถดูได้ที่นี่เลยจ้า
ส่วนใหญ่วันนี้เลยนั่งดูนั่งจดชิวๆไปเนอะ
ก่อนอื่นเลย มาโหวตกันเลยจ้า โหวตกันรัวๆเลย คำตอบคือหัวใจด้วย
ในวันนี้เราจะรอพี่ๆตบมุขตลกคาเฟ่ เอ้ยย มาทำ codelab Handle Non-Text Event with Dialogflow กันจ้า
เกิดจากคำถามที่ว่า เราจะส่ง event อื่นๆไปยัง DialogFlow ได้อย่างไร เช่น date picker, location ทำอย่างไรให้ DialogFlow เข้าใจ event อื่นๆได้ด้วย ในที่นี้จะเป็นระบบลงทะเบียนเนอะ
มาทำ Codelab ไปพร้อมๆกันเถอะ
จากนั้นเปิดตัวคนที่จะ live coding ในวันนี้ คุณหนึ่งนั่นเองงงง~~~
ก่อนจะมาทำ codelab กันนั้น มีกติกาการร่วมสนุกประจำสัปดาห์ ในสัปดาห์นี้น้านนน ยังได้หน้ากากผ้าเช่นเคย ซึ่งเราได้ของอาทิตย์ก่อนแล้ว เลยอ่ะให้คนอื่นๆเขาบ้างเนอะ ส่วนโจทย์เพิ่มเติมเดี๋ยวมาเฉลยตอนท้ายอีกทีนึงเนอะ ซึ่งมาเริ่มเขียนบล็อกหลังปิดรับฟอร์มแล้วนั่นเอง เย้ๆๆๆๆๆๆๆ (เพราะไปดูสตรีมเมอร์เล่นเกมส์งับ -___-)
flow การทำงานจะเป็นแบบนี้
ให้ user กรอกชื่อด้วย Message Event ประเภท Text จากนั้นใส่ location ด้วย Message Event ประเภท Location และเลือกวันที่จาก DateTime Picker ด้วย Postback Event
โดยให้ตัว Firebase Cloud Functions เป็น API ตัวนึง และใช้ Cloud Firestore เป็น database จ้า
ต่อมาสร้าง LINE OA ในส่วนนี้ขอข้ามเลยแล้วกัน สิ่งที่เราต้องทำก็คือ เพิ่มบอทเป็นเพื่อนรอไว้, ไปปิด auto reply และไป issue access token รอไว้ก่อนเลย
จากนั้นไปสร้างโปรเจก Firebase กัน โดยเปลี่ยนเป็น Blaze Plan เพราะเชื่อมต่อ API ภายนอก ทั้ง DialogFlow และ LINE ซึ่งต้องมีบัตรเครดิต และจำนวน project ที่ใช้บัตรเกินโควต้า หรือผูกบัตรไม่เกิน 5 project ไม่งั้นมันอัพเดต plan ไม่ได้ เราเคยติด กว่าจะหาเจอว่าลบตรงไหน นานมาก คือไปลบใน console ของฝั่ง Cloud พบว่าผูกกับโปรเจกเปล่าๆในนั้นที่ไม่ได้ใช้ 1 ตัวง่ะ
เมื่อสร้างโปรเจกเสร็จแล้วก็ไป create database ใน Cloud Firestore รอก่อนเลย 1 กรุบ โดยเลือกเป็น production mode น้าาา และเลือก region asia-northeast1
ที่ Tokyo เพราะใกล้กับ server LINE มากที่สุด ดังนั้นมันจะวิ่งแค่ hop ประเทศไทยและประเทศญี่ปุ่นเท่านั้น ไม่งั้นวิ่งไปเมกามันก็หลาย hop อ่ะเนอะ
ที่สำคัญ ตั้ง region แล้ว เปลี่ยนไม่ได้น้าาา
ต่อมาไปสร้าง Agent ใน DialogFlow ซึ่ง Agent ก็จะประมาณ chatbot ตัวนึง ที่ข้างในมีการวิเคราะห์ content ต่างๆด้วย AI ให้เรา
ถ้าเรายังไม่เคยใช้ DialogFlow จะต้อง login ด้วย Google Account ก่อนน้า แบบนี้ๆ
เมื่อ login เข้ามาแล้วให้ไปสร้าง Agent เลือกภาษาไทย เลือก project ก็คือเชื่อมกับ project Firebase ที่เราเพิ่งสร้างมะกี้ แล้วก็กด create และรอกินหนมแปปนึง
DialogFlow ที่เราใช้จะเป็นแบบ Essentials เนอะ หรือ ES และอีกแบบคือ Customer Experience หรือ CS นั่นเอง ถามว่าทั้งสองต่างกันอย่างไร? อ่านบล็อกนี้จ้า
Intent ใน DialogFlow คืออะไร? intent แปลว่า ความตั้งใจ เป็นการวิเคราะห์ content ว่า user พิมพ์ message มาว่าอะไร และจะตั้งใจจะสื่อสารอะไรงี้ โดยตัว default มันจะมีให้ 2 ตัวคือ
- Default Welcome Intent : ประโยคทักทาย
- Default Fallback Intent : ถ้าไม่ตรงกับ intent ใดๆจะมาที่นี่
ส่วนสำคัญใน Intent ก็คือ Training phrases เราสอนบอทว่า user พิมพ์ message ว่าอะไร เราสามารถใส่ได้ 2000 ประโยค! ต่อ 1 intent และยิ่งเราใส่หลากหลาย บอทเราจะยิ่งเก่งขึ้นโนะ และก็ Responses คือข้อความที่ bot จะตอบกลับไป
สำหรับคนที่ใช้ครั้งแรก ต้องไปกด accept policy & privacy ที่ cloud console ก่อนนะ
ต่อมาเราจะทำการสร้าง Intent แต่ละตัว ด้วยความระวัดระวัง เพราะถ้าผิด บอทเราจะทำงานไม่ได้น้า เราก็แอบทำล่วงหน้าใน codelab แหละ ในนี้ขอสรุปแบบคร่าวๆแล้วกันเนอะ
register อันนี้ใส่ Training phrases เป็นคำว่า "ลงทะเบียน" แล้วก็ "register" เนอะ ส่วน Responses ก็จะเป็น text ธรรมดาอันนึงให้เรากรอกชื่อ ซึ่ง design จริงๆอาจจะกดลงทะเบียนจาก Rich Menu หรือ Flex Message หรือใดๆก็ได้
จากนั้นสร้าง Intent ใหม่ โดยกดตรง Add Follow Up intent ด้านหลัง Register Intent และเลือกเป็น Custom เพราะว่าทำงานต่อจาก Intent ก่อนหน้านั่นเอง
เปลี่ยนชื่อ Intent นี้เป็น register-name ใส่ Training phrases เป็นชื่อคน และเก็บ parameter ชื่อว่า name
โดยการเก็บชื่อที่ user พิมพ์มาใส่ตัวแปร ระบุ Entity Type เป็น @sys.any
เพื่อความหลากหลาย และกำหนด value เป็น $name
แล้วก็ไป highlight ชื่อที่เราพิมพ์มา เพื่อระบุในการ training ส่วน Responses คือเราต้องการให้ user แชร์ location ต่อนั่นเอง
จากนั้นไปทดสอบที่เราทำมาก่อนที่ด้านขวามือ 1 รอบก่อนจ้า
ต่อมาสร้าง Intent ใหม่เพื่อรับ location โดยทำงานต่อจาก intent register - name เมื่อกี้ ให้ชื่อว่า register - location เราจะพิมพ์สอน Dialogflow ตาม pattern ที่เราต้องการไปก่อนใน Training phrases เป็น LAT : 13.00 , LNG : 100.00
จากนั้นสร้าง parameter ตามรูปนี้เลย รับ latitude
และ longitude
เป็น @sys.number
และรับชื่อจาก Intent ก่อนหน้า จึงใส่ #
จะประมาณว่าตามด้วย Intent นั้น ตามด้วยชื่อตัวแปรนั่นเอง
และ Intent สุดท้าย register - date เราพิมพ์สอน Dialogflow ตาม pattern ที่เราต้องการน Training phrases เช่นเคย เป็น DATE : 2021-07-01
แล้วสร้าง parameter วันที่ที่เราเลือกชื่อว่า selected_date
เป็น @sys.date
ส่วนที่เหลือรับจาก intent ก่อนหน้าทั้งสิ้น ซึ่งต้องส่งเป็นรอบๆ ไม่งั้นมันจะหายหมด
ข้อควรระวังคือ ต้องสะกดให้ถูก ไม่งั้นเราจะตามหาบัคยาก
จากนั้นก็ทดสอบให้เราดูอีกรอบนึง พบว่า parameter ตามมาแล้ว และ intent สุดท้าย ไม่ต้องใส่ Responses แต่ให้เปิด Fulfillment นะ
สำหรับ DialogFlow นั้น Intent ใน 1 Agent มีได้มากสุด 2000 Intents เลยทีเดียว
แล้วก็มีเพิ่มที่เป็น custom payload ของ LINE เพื่อ UX ที่ดีย์ขึ้นเนอะ ไปที่ Intent register - name ไปใส่ตรง Reponses จากนั้นกด + ข้าง Default แล้วก็เลือก LINE เนอะ
โดยตัว Text Message ใน LINE หน้าตามันจะเป็นแบบนี้
{
"type": "text",
"text": "กรุณาแชร์โลเคชั่นของคุณมาหน่อย"
}
และหน้าตาใน payload จะมีตัว line
ครอบมาแบบนี้
{
"line": {
"type": "text",
"text": "กรุณาแชร์โลเคชั่นของคุณมาหน่อย"
}
}
ใน register เราเพิ่ม Quick Reply เข้าไป โดยจะให้กดจาก Location Action ซึ่งเราสามารถดูตามใน LINE Document ได้เลย ซึ่ง Quick Reply จะใส่เป็น item ไปแบบนี้
วิธีการใช้ Quick Reply
หน้าตาทั้งหมดในตอนนี้
{
"line": {
"type": "text",
"text": "ขอบคุณ คุณ$name กรุณาแชร์โลเคชั่นของคุณ",
"quickReply": {
"items": [
{
"action": {
"type": "location",
"label": "แชร์โลเคชั่น"
},
"type": "action"
}
]
}
}
}
และอีกทีคือ register - location ใส่ Quick Reply เป็น Datetime Picker ส่วน data
ไม่ได้ใช้ เลยใส่ชื่อตัวแปรไปก่อน
{
"line": {
"type": "text",
"quickReply": {
"items": [
{
"type": "action",
"action": {
"type": "datetimepicker",
"label": "เลือกวันที่",
"data": "selected_date",
"mode": "date"
}
}
]
},
"text": "ตำแหน่งของคุณคือ $latitude,$longitude ขั้นตอนต่อไปกรุณาเลือกวันที่"
}
}
เมื่อสร้าง intent ทั้งหมดเสร็จแล้ว ทำการเชื่อมต่อ DialogFlow เข้ากับ LINE เนอะ
เราจะต้องลอก Channel ID
, Channel Secret
และ Channel Access Token
จาก LINE OA มาใส่ และเอาตัว webhook
ใน DialogFlow ไปใส่ใน LINE OA ของเรา อีกทีนุง
และทางบ้านติดจ้า ติดตอนเพิ่ม response เป็น LINE วิธีแก้คือไป set integration กับ LINE ก่อน แล้วค่อย refresh อีก 1 รอบ
ตอนทดสอบจะมี message ซ้อนมา
ให้ไปปิดตรงนี้ก่อน
เมื่อเราเทส พอส่ง location ไปแล้ว บอทจะนิ่ง เพราะเราไป connect กับ LINE ตรงๆ แต่ DialogFlow ไม่เข้าจายย ดังนั้นตรง location message เราจะต้องทำ proxy server ขึ้นมาก่อน
ไปที่ Visual Studio Code ที่เรารัก (พอๆกับ Android Studio แหละ) ไปที่ Terminal เพื่อติดตั้ง Firebase CLI สำหรับคนที่ไม่เคยติดตั้ง และก็ login ซึ่งต้องตรงกับ project ที่เราสร้าง และ firebase init
เลือก Firestore, Function และติด Emulator เผื่อไว้เนอะสำหรับเทส แล้วเลือกทั้งหมดเป็น default
จากนั้น shell ไป folder function cd functions
เพื่อติดตั้ง express กับ line-sdk ก่อนเนอะ
npm i express @line/bot-sdk --save
แล้วก็ config environment รอก่อน โดยเก็บ channel access token และ channel secret ของฝั่ง LINE OA มา และ agent id จาก DialogFlow มา โดยเอาจากใน webhook ซึ่งจะอยู่หลังคำว่า webhook นั่นเอง
firebase functions:config:set line.channel_access_token="xxxxx" line.channel_secret="xxxxx" dialogflow.agent_id="xxxxx"
และดูค่าที่เราเก็บไว้ทั้งหมดด้วย firebase functions:config:get
เนอะ
กลับมา coding หล่ะ ก่อนอื่นเราก็ require library ต่างๆเข้ามากันก่อนนะ
const functions = require('firebase-functions');
const line = require('@line/bot-sdk');
const express = require('express');
แล้วก็สร้างตัวแปรเพื่อสร้าง header สำหรับใช้ใน LINE API เนอะ
const config = {
channelAccessToken: functions.config().line.channel_access_token,
channelSecret: functions.config().line.channel_secret
}
และประกาศ Express พร้อมด้วยสร้างตัว Express รับ Post request ที่ path /webhook
และเพิ่ม middleware ของ LINE เข้าไปได้เลย line.middleware(config)
เพื่อ check signature x-line-signature
app.post('/webhook', line.middleware(config), (req, res) => {
//TODO
});
และเข้ารหัสด้วย body ของ channel secret เวลารับ request ก็เอา body มาเข้ารหัสกับ secret channel และ validate ว่าตรงกันไหม
จากนั้น export เส้นที่เราเขียนเมื่อกี้ออกมา โดยเชื่อมกับตัว Cloud Function for Firebase พร้อมด้วยใส่ region ซึ่งก็อันเดียวกันกับตอนที่สร้าง Cloud Firestore นั่นเอง
exports.api = functions
.region('asia-northeast1')
.https
.onRequest(app);
โดยตัว event webhook ที่ได้จะเป็น array เนอะ ก็เติมไปในโค้ดแบบนี้
app.post('/webhook', line.middleware(config), (req, res) => {
const events = req.body.events
events.foreach(event =>
handleEvent(req, event)
)
});
และทุกๆ request โยนให้ handleEvent()
ทำงาน ดูว่าอันนี้เป็น message อะไร?
ข้างในจะทำการแยก type ว่าเป็น type อะไรบ้าง ซึ่งที่เราสนใจก็จะมี text
ซึ่งจะ forward กลับไปให้ DialogFlow ตรงๆเลย และ location
อันนี้จะสร้าง text message ใหม่ส่งกลับไปให้ DialogFlow จ้า อันนี้รวบตึงโค้ดทั้งหมดมาเลยเนาะ แน่นอนว่าแตก เดี๋ยวลง gist รงบทั้งหมดอีกรอบ
async function handleEvent(req, event) {
switch (event.type) {
case 'message':
switch(event.message.type) {
case 'text':
return postToDialogflow(req)
case 'location':
const locationText = `LAT: ${event.message.latitude}, LNG: ${event.message.longitude}`
const locationMsg = createLineTextEvent(req, event, locationText)
return convertToDialogflow(req, locationMsg)
}
case 'postback':
const dateText = `DATE: ${event.postback.params.date}`
const dateMsg = createLineTextEvent(req, event, dateText)
return convertToDialogflow(req, dateMsg)
}
}
ตัว postback
ใช้กับ datetime ticker ที่ user เลือกก็จะอยู่ใน postback params โดยเราสามารถเลือกได้ 3 แบบ คือ date
, time
, datetime
อันนี้เป็นตัว adapter ซึ่งคุณหนึ่งทำเป็น gist ชื่อไฟล์ว่า dialogflow.js
ไว้ให้แล้วจ้า
postToDialogflow()
ส่งไปให้ DialogFlow โดยตรงเล้ยยconvertToDialogflow()
แปลงเป็น text message eventcalculateLineSignature()
คำนวณx-line-signature
ให้ใหม่ ไม่งั้น DialogFlow จะ reject เพราะตัว body ถูกเปลี่ยนแปลง เพื่อให้ DialogFlow รับอันนี้ ซึ่งก็มีการ modified payload และ signatur อีกทีcreateLineTextEvent()
เปลี่ยน type เป็น message event ที่เป็น text message เลียนแบบ request ที่ได้ เพื่อให้ format ตรงกับฝั่ง DialogFlow
ทำการติดตั้ง library ในไฟล์นี้ ก็จะมี request
กับ crypto
เห็นคุณกอล์ฟคอมเมนต์ในช่องแชทในไลฟ์ว่าของดี ซึ่งตัว library นี้เขาบอกกันว่าใช้ง่ายนะ
npm i request crypto --save
จากนั้นทำการ deploy กันอีกสัก 1 รอบเนอะ เพื่อเอา webhook ที่เป็น proxy ไปใช้ต่อใน LINE OA ของเราเนอะ
มีการทำ cleaning คือล้างหน้าให้สะอาด ปราศจากเครื่องสำอาง ไม่ช่ายยย คือก่อนหน้านี้มีไฟล์ image ที่ไม่ได้ใช้ ตอนนี้จะทำการลบ image ที่ไม่ได้ใช้ทุกครั้งในการ deploy นั่นเอง
ในช่องแชทมีคำถามด้วยหล่ะ
สอบถามครับ
event type ของ line มีกี่แบบครับ? ช่วยแนะนำวิธีดูใน line document หน่อยครับใน message
ซึ่งมี LINE Certified Coach ที่เป็นสาย API มั้งถ้าจำไม่ผิด ท่านนึง เข้ามาตอบไว้ว่า
event จะมี type อีก 7 อัน จะมี test, image, video, audio, file, location และ sticker
ส่วนอันนี้ Document
เราสามารถเข้าไปอ่านเรื่อง "15 สัญญาณจาก Webhook Events ที่จะปลุกให้ LINE Bot ของคุณตื่นจากภวังค์" เพิ่มเติมได้ที่บล็อกนี้
กลับมาที่ codelab ของเรา
ทุก request จะถูกเข้าไปใน proxy นี้ก่อนที่จะส่งไปให้ DialogFlow และเปลี่ยน webhook จาก DialogFlow ไปยัง proxy
และอย่าลืมใส่ /webhook
ต่อหลังตัว Cloud Function ที่ได้จากการ deploy ด้วยนะ
จากนั้นทีการ demo อีกครั้งนึง คราวนี้รับ date ได้แล้ว แต่ยังขาด fullfillment เพราะเรายังไม่ได้ implement นั่นเอง
โค้ดในขั้นตอนนี้จะเป็นแบบนี้นะ
ต่อมาทำการเชื่อมต่อข้อมูลกับ Cloud Firebase กันต่อเนอะ ดังนั้นจะต้อง require firebase-admin
เข้าไปนั่นเอง
const admin = require('firebase-admin');
อย่าลืม initialize นิดนึง
admin.initializeApp({});
แล้วก็สร้าง path ใหม่อีกหนึ่งอัน ชื่อว่า fullfillment
ทำหน้าที่รับ request จาก DialogFlow
app.post('/fullfillment', (request, response) => {
//TODO
})
มีการใช้ middleware แปลง body ให้เป็น json เพื่อให้ตัว Express สามารถเข้าใจได้
app.use(express.json());
เมื่อเราจะใช้ DialogFlow ในโปรเจกนี้ของเรา จะต้องไป require dialogflow-fulfillment
เข้ามาในโปรเจก
const { WebhookClient, Payload } = require('dialogflow-fulfillment');
ถ้าใครเคยไปทำ fullfillment ที่ Inline Editor ก็จะเริ่มคุ้นๆหล่ะ ก็คือตัวเดียวกันแหละเนอะ
และทำการ install DialogFlow และควบคู่ด้วย actions-on-google
npm i dialogflow-fulfillment actions-on-google --save
มา implement ใน path fullfillment
กันต่อ ตัว agent รับ request และส่ง response ออกไปได้เลย และตัวชื่อ Intent จะต้องตรงกับที่เราตั้งชื่อใน DialogFlow นะ
app.post('/fullfillment', (request, response) => {
const agent = new WebhookClient({ request, response });
let intentMap = new Map();
intentMap.set('Register - date', handleFullfillment);
agent.handleRequest(intentMap);
});
สร้าง handleFullfillment()
เพื่อทำการ implement ในส่วนสร้าง Document โดยใช้ Cloud Firestore โดย key จะเป็น userId ของคนที่พิมพ์หาบอท ซึ่งมาจาก webhook ของ LINE อีกทีนึง ข้างในชื่อตัวแปรจะต้องตรงกับที่เราตั้งไว้ใน DialogFlow นะ ในที่น้ีจะเก็บผ่าน database ตรงๆ และให้ส่งไปบอกว่าเก็บข้อมูลเรียบร้อยแล้ว
ใน codelab จะเห็น selected_date: Date.parse(selected_date)
ถ้าเก็บ date ที่เป็น long number ก็ convert ได้นะ อันนี้ก็แล้วแต่เราเลย
function handleFullfillment(agent) {
const userId = agent.originalRequest.payload.data.source.userId;
const { name, latitude, longitude, selected_date } = agent.parameters;
const doc = {
uid: userId,
name,
latitude,
longitude,
selected_date
};
firebase.firestore().collection('member').doc(userId).set(doc);
agent.add('บันทึกข้อมูลสำเร็จแล้ว');
}
เมื่อเก็บข้อมูลเรียบร้อยแล้วส่งไปบอก user ได้เลย
การทำงานในส่วนนี้จะมี flow คือ : LINE app -> Proxy Server -> DialogFlow -> Fullfillment
จากนั้น deploy อีก 1 กรุบ สำหรับเส้น fullfillment
และแล้วถึงเวลาตื่นเต้นที่สุด เพราะไม่เคยทำมาก่อน คือการใส่ webhook ที่เราสร้างจาก Cloud Functions ลงใน DialogFlow เว้ยยย เพราะเราทำไม่เป็นไงประเด็น 555
ผลที่ควรจะได้หลัง deploy
ข้อมูลจะถูกเก็บไว้ใน Cloud Firestore แบบนี้
รวบตึงโค้ดสักนิด
แต่พอเป็น text แบบนี้มันก็จะดูแห้งๆไป แน่นอนว่าใน codelab ไม่มี อิอิ ดังนั้นเราจะมาสร้าง Flex Message เมื่อสร้างเสร็จแล้วเอามาแปลงใน EX10 ได้นะ ในที่นี้ให้กด FORMAT AS FLEX MESSAGE นะ
จากนั้นทำการสร้าง payload และส่ง payload ออกไป
const msg = {};
const payload = new Payload(
agent.LINE,
msg,
{
sendAsMessage: true,
rawPayload: false
}
);
agent.add(payload);
ข้อควรระวัง custom payload รองรับ DialogFlow version 0.6.1 ขึ้นไป
และในการ implement payload ครั้งนี้ ไม่ต้องมี line {}
มาครอบนะ
นอกจาก EX10 จะช่วยแปลง Flex Message จาก LINE Bot Designer หรือ Flex Message Simulator ให้เราสามารถใช้งานต่อได้แล้ว ยังมี feature อื่นๆอีก เช่น
- Emoji Selector : ช่วย set index ของ emoji ให้ไปอยู่ใน array ที่ถูกต้อง
- Messages Imagemap : มี resize แล้วให้ url เรากลับไปใช้ด้วย
- Bulk Processor : ใส่ uid เพื่อช่วยยิงเวลาเปลี่ยน Rich Menu ให้กับ user ที่เป็นเพื่อนใน LINE OA นั้นทุกคน โดยจะทยอยยิงไปแหละ แต่เราทำในนี้ครั้งเดียวพอ
- Encode & Decode มีทั้ง url และ base64
โจทย์เพิ่มเติมของการบ้านจ้า
- เมื่อเพิ่มเพื่อนแล้ว จะมีหน้าตาคล้ายๆ Dialog ขึ้นมาให้เราลงทะเบียนเลย
- หลังจากเลือกวันที่ ให้ user ส่งสติ๊กเกอร์เพื่อแสดงความรู้สึกด้วย
- สุดท้ายแสดงผลออกมา เป็นการยืนยันการลงทะเบียน
update : เพิ่มไปในนี้เลยแล้วกันเนาะ
มาเริ่มส่วนที่ง่ายที่สุดก่อน คือเพิ่มให้ user แสดงความรู้สึก แล้วสุดท้ายแสดงทั้งหมดออกมาเป็น Flex Message
ก่อนอื่นเลยเรามาแก้ Intent ใน DialogFlow กันก่อน ชื่อว่า Register - date โดยเราจะใช้ custom payload ในการแสดง text ทั้งสองตัว คือ วันที่ที่เราใส่เข้าไป และ ให้ user ส่ง sticker กลับมานั่นเอง เราจึงต้องเพิ่มเป็น 2 blocks นะ แบบนี้
//custom payload 1
{
"line": {
"text": "คุณเลือกวันที่ $selected_date",
"type": "text"
}
}
//custom payload 2
{
"line": {
"text": "ส่งสติ๊กเกอร์บอกความรู้สึกของคุณในตอนนี้",
"type": "text"
}
}
แล้วอย่าลืมไปปิด fullfilment ออกด้วยนะ
จากนั้นสร้าง follow-up intent ใหม่ที่เป็น custom เหมือนเดิม สร้างต่อจาก Register - date ให้ชื่อว่า Register - sticker ก็แล้วกันเนอะ
เราจะทำการส่งทุก parameter จาก intent ก่อนหน้า เข้ามาใน intent นี้ และสร้าง parameter ใหม่ชื่อว่า sticker_keywords
เพื่อนำ sticker keyword มาแสดง
แล้วก็ครอบใน Training phrases
แล้วเปิด fulfillment ไว้
ในโค้ดเปลี่ยนชื่อ intent ที่ใช้ fulfillment เป็น Register - sticker
app.use(express.json());
app.post('/fullfillment', (request, response) => {
const agent = new WebhookClient({ request, response });
const intentMap = new Map();
intentMap.set('Register - sticker', handleFullfillment);
agent.handleRequest(intentMap);
});
ใน handleFullfillment()
เราจะเพิ่ม parameter sticker_keywords
เพื่อนำไปเก็บไว้ใน Cloud Firestore และนำมาแสดงผลเพิ่มเติมใน Flex Message
และไปเพิ่ม type sticker ใน handleEvent()
โดยตัว sticker เราจะได้เป็น request body มาประมาณนี้ โดยตัว sticker keywords จะเป็น array เราเลยแปลงเป็น String ซะ
จากนั้นลอง deploy 1 รอบ มาดูผลลัพธ์กัน
ปล. กว่าจะเสร็จ คือปาไปหลายวันเลยอ่ะ ฮือออออออ
โค้ดในส่วนนี้
สุดท้ายอันเพิ่มเพื่อนแล้วแสดง Flex Message ซึ่งเราจะใช้ event ที่ชื่อว่า Follow event เนอะ
จากนั้นเราก็ทำ Flex Message ขึ้นมาอันนึงเนอะ แล้วก็เมื่อเจอ event นี้แล้ว ให้ส่ง Flex Message ตัวนี้มาเลย แต่ของเรายังติดโค้ดนิดหน่อย ก็จะประมาณนี้เนอะ ใครจะมาช่วยแก้ก็ได้น้าาา เพราะเรามูฟออนไปเรื่องอื่นแล้วง่าาา
สามารถ support ค่ากาแฟเจ้าของบล็อกได้ที่ปุ่มแดงส้มสุดน่ารักที่มุมซ้ายล่าง หรือกดที่นี่ก็ได้จ้า https://ko-fi.com/mikkipastel
กด follow Twitter เพื่อได้รับข่าวสารก่อนใคร เช่น สปอย content ใหม่ หรือสรุป content เร็วๆในนี้จ้า
ติดตามข่าวสารและบทความใหม่ๆได้ที่
download แอพอ่านบล็อกใหม่ของเราได้ที่นี่