[Line] GoodBuy on Line
วันนี้เจมส์จะมาเขียน Line bot เล็ก ๆ เล่นครับ แต่คิดว่ามีประโยชน์ไม่ใช่เล่น ๆ นะครับ เจมส์คิดว่าเพื่อน ๆ คงเคยมีปัญหาเกี่ยวกับการเลือกซื้อของว่า ซื้ออันนี้ถูกกว่า หรือว่าซื้ออันนี้ถูกกว่ากันมาบ้าง เดี๋ยววันนี้เจมส์จะมาเขียน Line bot ให้มันเช็คให้เลยว่า ซื้ออันไหนถูกกว่า จะเป็นประมาณนี้เน้อครับ
วางแผนกันก่อน
เราจะมาแบ่งก่อนว่าจะรับ Message เป็นยังไง มี Field อะไรบ้าง
- Unit — คือ จำนวนของชิ้นนั้น ๆ
- Volume — คือ ปริมาตรของชิ้นนั้น ๆ เช่น 1000 มิลลิลิตร, 1 ลิตร
- Price — คือ ราคารวม เพราะปกติเวลาเดินซื้อของมันก็จะเป็นราคารวมแล้ว เช่น ปลาเส้น 2 แถม 1 ราคา 50 บาท
- Measurement — คือ หน่วยวัดปริมาตรในที่นี้เราจะมี 4 แบบก่อนครับ
g (กรัม), kg (กิโลกรัม), l (ลิตร), ml(มิลลิลิตร)
และคิดว่าเวลาพิมพ์จะให้พิมพ์เข้ามาได้ 2 แบบคือ แบบรวดเดียวเลย หรือไม่ก็พิมพ์แบบทีละครั้ง เช่น เราเจอโปรโมชั่น
น้ำยาปรับผ้านุ่มซื้อ 2 แถม 1 มีปริมาตรถุงละ 700 มิลลิลิตร ราคา 157 บาท
อยากเปรียบเทียบกับ
น้ำยาปรับผ้านุ่มซื้อ 1 แถม 1 มีปริมาตรถุงละ 1 ลิตร ราคา 200 บาท
พิมพ์แบบรวดเดียวเราจะพิมพ์ดังนี้
3,700,157,ml 2,1,200,l
พิมพ์แบบทีละครั้ง
3,700,157,ml2,1,200,l
ซึ่งคิดว่าจะทำให้เป็นได้ทั้งสองแบบ พิมพ์แบบรวดเดียวจะแบ่งโดยการเว้นวรรค ซึ่งจะเปรียบเทียบกี่อันก็ได้ ส่วนพิมพ์แบบทีละครั้งก็คือพอพิมพ์เสร็จ เราก็กดส่ง Message bot ก็จะตอบกลับมาให้สามารถพิมพ์ต่อได้ (คิดว่าจะทำให้แบบผสมกันก็ได้ครับ ก็คืออาจจะพิมพ์รวดเดียวไปแล้ว แล้วก็พิมพ์แบบทีละครั้งต่อก็ได้)
แต่ถ้าเกิดเราอยากเปรียบเทียบ ก็สามารถกดที่ Rich menu compare เลย ซึ่งเมื่อ Compare ไปแล้ว ข้อมูลที่พิมพ์ก็จะถูก Reset หมด และแสดงข้อมูลที่ราคาถูกที่สุดออกมา
มาเริ่มกันเลยครับ
ตั้งค่าและสร้าง Line channel
ขั้นแรกเรามาสร้าง Line bot กันก่อนครับ https://developers.line.biz/console/
ถ้าหากเพื่อน ๆ มี Provider แล้วอาจจะเลือกใช้ Provider เดิมก็ได้เน้อครับ แต่ถ้าหากไม่มีก็สามารถสร้าง Provider ใหม่ได้เลย จากนั้นก็สร้าง Channel เป็น Messaging API
เพื่อน ๆ สามารถหาวิธีการสร้าง Line bot ได้จาก Internet เลยครับ หรือจากในส่วน Reference ด้านล่างก็ได้ เพื่อไม่ให้บทความยาวไป ผมก็จะอธิบายในส่วนที่จำเป็น หลังจากสร้าง Channel เรียบร้อยแล้ว ให้เราเลือก Tab มาที่ Messaging API ในส่วน Greeting messages ให้เลือกที่ Edit
มันจะแสดงหน้าใหม่ขึ้นมา ให้เราเลือกให้เราปรับตามนี้
- Greeting messages ให้เป็น Disabled
- Auto-response ให้เป็น Disabled
- Webhooks ให้เป็น Enabled
สร้าง Project firebase เราสามารถดูจากบทความใน Link ได้เลยครับในหัวข้อ ติดตั้ง Firebase และ set up firebase cloud function
Set up firebase cloud function
เราจะสร้าง firebase cloud function ขึ้นมาครับ โดยขั้นแรกจะสร้าง directory ขึ้นมาก่อน ในที่นี้เจมส์จะสร้างชื่อว่า goodbuy-on-line และเข้าไปในนั้นครับ
mkdir goodbuy-on-line && cd goodbuy-on-line
ในขั้นถัดไปเราจะ initial firebase cloud function เข้ามาด้วยคำสั่ง
firebase init functions
มันจะมีให้เลือกว่าจะสร้าง project ใหม่ หรือเลือก project ที่สร้างอยู่แล้ว ในที่นี้เจมส์เลือก Use an existing project ก็คือเลือก project ที่สร้างอยู่แล้ว แล้วก็เลือก project ในที่เจมส์สร้างไว้ครับ
จากนั้นจะมีให้เราเลือกว่าจะใช้ภาษาอะไรเขียน cloud functions จะมี JavaScript และ TypeScript ในที่นี้เจมส์เลือก JavaScript จากนั้นก็กด enter
จากนั้นระบบจะถามว่าจะใช้ ESLint ไหมในการจัด Style ประมาณว่าถ้า style ไม่ถูกต้องก็จะ deploy ไม่ได้ ในที่นี้เจมส์จะพิมพ์ N แล้วกด enter คือ ไม่ใช้งาน ESLint
ระบบก็จะถามอีกว่าต้องการ install dependencies ตอนนี้เลยไหม ก็ตอบ Y แล้วก็ enter ได้เลยครับ
สิ่งที่เราต้อง Install เพิ่มเข้ามาคือ axios ครับ ซึ่งเราจะเอาไว้ใช้สำหรับเรียกไปที่ API ของ Line เพื่อส่ง Message ตอบกลับมา โดยให้เราเข้าไปที่ directory functions และ install axios
cd functions && install --save axios
เดี๋ยวเราจะมาไล่สร้างไปทีละอย่างเน้อครับ ขั้นแรกจะสร้าง directory ชื่อ helpers มาก่อนครับ ในนั้นเราจะสร้างไฟล์ดังนี้ครับ
- general.js — เป็น helper ที่เราไม่จำเป็นต้อง import อะไรจาก ด้านนอกมา
- index.js — เป็น helper ที่เรา import อะไรจาก ด้านนอกมาประกอบด้วย
- line.js — เป็น helper ที่เราจะเขียน function ไว้สำหรับที่เกี่ยวกับ Line
- firestore.js — เป็น helper ที่เราจะเขียน function ไว้เกี่ยวกับ firestore
- messages.js — เป็น helper ที่เราจะจัดการเกี่ยวกับ messages ต่าง ๆ
helpers/general.js
ใน helpers/general.js เดี๋ยวเจมส์จะอธิบายว่าแต่ละอันไว้ทำอะไรนะครับ
- compare — เป็น function ใช้สำหรับเปรียบเทียบว่าอันไหนราคาถูกสุดโดยคำนวณแบบเทียบบัญญัติไตรยางค์ แบบราคา 1 บาทได้กี่หน่วย โดยในตอนแรกจะเช็คก่อนว่าค่าใน items ที่ส่งมานั้นสามารถเปรียบเทียบได้หรือเปล่า (จะเปรียบเทียบไม่ได้เมื่อ อันนึงเป็น kg หรือ g แล้วเอามาเปรียบเทียบกับ l หรือ ml ถ้าเปรียบเทียบไม่ได้เจมส์จะ return false ออกไป แต่ถ้าเปรียบเทียบได้ ก็จะ return ค่า Object ที่ราคาต่อปริมาตรมากที่สุดออกมา (อันที่คุ้มสุดถ้าเปรียบเทียบในเชิงปริมาณกับราคา)
- getItems — เป็น function ที่รับ message ที่ตรงตาม format เข้ามาแล้ว return เป็น Array object ออกไป
- checkCanBeMeasured — เป็น function สำหรับตรวจสอบว่า items ทั้งหมดหน่วยความจุนั้นสามารถเปรียบเทียบได้หรือเปล่า คือ l กับ ml สามารถเปรียบเทียบกันได้ แต่ ml กับ kg จะไม่สามารถเปรียบเทียบกันได้
- calculateVolumePerPrice — เป็น function สำหรับคำนวณว่า ปริมาตรต่อราคาของ item
- strCalculateVolumePerPrice — เป็น function สำหรับแสดงข้อความที่คำนวณค่า ปริมาตรต่อราคาของ item โดยมีหน่วยแสดงด้วย
helpers/index.js
ใน helpers/index.js จะมี function ต่าง ๆ ดังนี้ครับ
- showHelp — สำหรับแสดง flex message help
- showItems — สำหรับแสดง flex message แสดงรายการ items
- compareItems — ดึง items มาเปรียบเทียบและแสดง flex message รายการของ items ที่เปรียบเทียบแล้วคุ้มที่สุด แต่ถ้าหากเปรียบเทียบไม่ได้จะแสดง message ว่า หน่วยการวัดไม่ถูกต้อง
- defaultMessage — เป็น function สำหรับดู message ที่ส่งเข้ามา ถ้าหากตรงกับ format สำหรับการ add item ที่จะเปรียบเทียบ ก็จะไปเพิ่ม item ใน firestore แต่ถ้าตรงกับ message ที่ตรงกับการ remove index ก็จะไป remove item ใน firestore แต่ถ้าหากไม่ตรงกับอะไรก็ไม่ทำอะไร
- removeItemFromIndex — เป็น function สำหรับ remove items จาก index
helpers/line.js
ในส่วนนี้จะมี function reply สำหรับส่ง message ไปที่ line โดยจะมีแค่ 2 แบบคือเป็นแบบ text กับแบบ flex
helpers/firestore.js
เป็น function ที่จัดการกับ firestore
- addItems — เป็น function สำหรับ add items ใส่ใน firestore
- clearItem — เป็น function สำหรับ set items เป็น array ว่าง
- updateItems — เป็น function สำหรับ update items (ใช้ตอน remove item)
- getItemsFromUserID — สำหรับดึงค่า items จาก userID
helpers/messages.js
เป็น flex message รูปแบบต่าง ๆ คือ help message, list items, compare result
src/config.js
ในส่วนนี้เราจะต้องปรับค่า ‘ค่า Channel access token’ โดยเอามาจากใน line channel เน้อครับ
index.js
ใน index.js นี้เราจะให้ Line webhook ยิงมาที่นี่ โดยเราจะเช็คว่าค่าที่ส่งมาเป็น message หรือเปล่า จากนั้นเราก็จะเช็คว่า message ที่ส่งมาตรงกับ case ไหน เราก็จะเรียก function ที่เราได้อธิบายไปแล้วในก่อนหน้านี้ครับ
Deploy ขึ้น firebase cloud function
หลังจากที่เพื่อน ๆ ใส่ code ต่าง ๆ ตามที่กล่าวไว้แล้ว ขั้นต่อไปคือ deploy ขึ้น firebase cloud function ครับ โดยการพิมพ์
firebase deploy
เมื่อ Deploy เรียบร้อยแล้วให้เข้าไปในหน้า https://console.firebase.google.com แล้วเลือกโปรเจค firebase ที่เราใช้สร้างตอนที่เรา init ในตอนต้น
จากนั้นให้เข้าไปดูที่เมนู functions
ให้เรา Copy URL ที่แสดง เพื่อเอาไปใส่ในหน้าของ Line channel ในส่วนของ Webhook settings > Webhook URL ก็เป็นอันเรียบร้อยแล้วครับ ^^
ถ้าหากบทความนี้มีส่วนไหนผิดพลาดประการใดก็ขออภัยมา ณ ที่นี้ด้วยเน้อครับ หรือหากเพื่อน ๆ สงสัยส่วนไหน ก็สามารถพิมพ์ไว้ใน comment ได้เน้อครับ
ตัวอย่างโปรเจคทั้งหมด