วิธีทำ LINE Chatbot สำหรับ developer มือใหม่ ไม่ง้อ DialogFlow

Programming Aug 6, 2021

หลายๆคนอาจจะเพิ่งลองทำ LINE chatbot แล้วประสบปัญหาทำใน DialogFlow แต่ใช้ไม่ได้เพราะไม่มีบัตรเครดิต ถ้าอยากลองเขียนต้องทำยังไงบ้างนะ?

เนื่องจากบล็อกที่แล้ว ก็ค่อนข้างยาวแหละ เป็นครั้งแรกที่ทำ LINE Chatbot โดยไม่ใช้ DialogFlow  และเขียนด้วยภาษา Javascript นะ

2-in-1 ดูราคาหุ้น Stock Token ผ่าน Google Sheet และส่งไปไลน์บอท
เราสามารถดูราคาหุ้นที่ขายอยู่ใน Stock Token ผ่าน Google Sheet ด้วย Google Finance ได้นะ แบบง่ายๆเลยหล่ะ สำหรับ developer เราจะมาเรียนรู้ในการดึงข้อมูลจาก Google Sheet เข้าไลน์บอทของเราอีกรอบนึง

ดังนั้นเราเลยทำบล็อกนี้มาเพื่อให้มือใหม่นำไปใช้ตามได้ เหมือนช่วยจับมือทำทางไกลเลยทีเดียว

ในตอนนี้เรามา checklist กันก่อน ว่ามีขั้นตอนหลักๆอะไรบ้าง

  • สร้าง LINE OA
  • สร้างโปรเจก Firebase
  • ทำการ setup Firebase Project ให้เรียบร้อย
  • มาเขียน echo chatbot กันเถอะ
  • ทำการตั้งค่าเพื่อทำ Firebase Emulator Suite
  • ทดสอบใน localhost ด้วย Firebase Emulator Suite และ ngrok
  • ทำการ deploy จริง และนำ webhook เพื่อให้ LINE Chatbot ใช้งานได้

ดังนั้นให้ลืม DialogFlow ไปก่อน เพราะเราทำการ implement chatbot ผ่าน Cloud Functions for Firebase ซึ่งสะดวกกว่าทำผ่าน inline editor ของ DialogFlow และทำการทดสอบด้วย Firebase Emulator Suite และ ngrok แล้วนำตัว url ที่ได้จาก ngrok มาใส่ใน LINE chatbot ของเรานั่นเอง


สร้าง LINE OA

ขออนุญาติลักไก่แปะลิ้งนี้เนอะ

ปฐมบทการสร้าง LINE Bot
บทความนี้เป็นบทความสำหรับผู้เริ่มต้นสร้าง LINE Bot ซึ่งผมตั้งใจเขียนแยกออกมา เนื่องจากบทความนี้จะกลายเป็น Prerequisite…

สร้างโปรเจก Firebase

ไปที่ Firebase Console กันก่อนเลย เพื่อกด Add project เพื่อสร้างโปรเจกใหม่นี้กัน

ตั้งชื่อโปรเจกที่เราต้องการ เมื่อตั้งชื่อแล้วสามารถเปลี่ยน id ของ project ได้ด้วยนะ โดยกดเปลี่ยนที่ปากกา ใต้ชื่อ project name ของเรา

ต่อมาปิด Analytics ไปก่อน แล้วกดปุ่ม Continue

จากนั้นรอสร้างโปรเจกแปปนึง

เสร็จแล้วจะได้หน้าตาแบบนี้

กด Continue เสร็จแล้วจะได้หน้าตาแบบนี้เนอะ

ทำการ setup Firebase Project ให้เรียบร้อย

ก่อนอื่น ให้ทำการ install Node.js และ Firebase CLI ให้เรียบร้อยก่อนเนอะ ผ่าน command line ด้วยคำสั่งนี้

npm install -g firebase-tools

สร้าง folder เปล่าๆที่เป็นชื่อโปรเจกของเรามาอันนึง และ copy pathname เก็บเอาไว้

จากนั้นทำการเข้าถึง path ของที่ตั้งของ folder นี้ด้วย Terminal ด้วยคำสั่ง command line

แล้วทำการ login Firebase ผ่าน Firebase CLI

firebase login

และทำการ initial project ของเรา ในที่นี้เราจะใช้ Cloud Functions for Firebase นะ

firebase init functions

เมื่อกี้เราสร้าง project ใน Firebase มาแล้ว ดังนั้นเราจะเลือก Use an existing project เน้อ

จากนั้นเลือกโปรเจกที่เราเพิ่งสร้างได้เลย

ตัว Cloud Functions for Firebase รองรับ JavaScript  และ TypeScript ก็ต้องเลือก JavaScript สิค๊าบบ เพราะเราเขียน TypeScript ไม่เป็น ตึ๋งโป๊ะ!!~

ตอนนี้ยังไม่ใช้ ESLint นะ ข้ามไปก่อน

ถามต่ออีกว่าจะ install dependencies ต่างๆที่จะใช้ด้วย npm หรือไม่ เอาสิรอรัย~

และตอนนี้ก็เสร็จแล้วจ้า วิ้งๆ

มาดู folder ของโปรเจกกันคร่าวๆ เราจะเจอ folder ของ functions ซึ่งเราจะมาเขียนโค้ดกันในนี้ ข้างใน functions จะมี package.json ขึ้นมา และตัว dependencies ต่างๆจะอยู่ใน node_modules นะ

Reference :

Get started: write, test, and deploy your first functions | Firebase

มาเขียน echo chatbot กันเถอะ

เปิดไฟล์ index.js ซึ่งจะอยู่ใน folder functions จะเป็นดังนี้

ให้ทำการลบ comment เขียวๆทิ้งไป เดี๋ยวเราจะค่อยๆเล่าทีละส่วนเนอะ

ก่อนอื่นทำการ import ตัว Cloud Functions for Firebase และเราทำการ set region เป็นที่สิงคโปร หรือ asia-southeast1 เนอะ เพราะใกล้สุดนั่นเอง

Cloud Functions locations | Firebase

ดังนั้นเราจะทำการ import ตัว Cloud Functions for Firebase เข้ามา พร้อมระบุ region ที่ใกล้ที่สุดเข้ามานั่นเอง

const functions = require("firebase-functions");
const region = "asia-southeast1";

นำ access token จากฝั่ง LINE OA เอามาใช้เพื่อทำการ authentication โดยไปที่หน้า console ที่ LINE OA ของเรา ไปที่แท็บ Messaging API

จากนั้นเลื่อนไปที่ข้างล่าง จะเจอ Channel access token เนอะ ในที่นี้ใช้แบบ long-lived ไปก่อนเนอะ แต่จริงๆสามารถเปลี่ยนเป็นแบบอื่นๆได้ทีหลังเนอะ ทำการกด Issue เพื่อ get token ไปใช้ต่อในบอทของเราจ้า

โค้ดในส่วน authentication จะเป็นดังนี้

const LINE_MESSAGING_API = "https://api.line.me/v2/bot";
const LINE_HEADER = {
  "Content-Type": "application/json",
  Authorization: `Bearer ${LINE_ACCESS_TOKEN}`
};

ต่อมา ทำการ import library เข้าไปอีกตัว คือ axios เข้าไป โดยทำการ import ผ่าน npm โดยเราเข้าไป import ใน folder functions เนอะ เพื่อความถูกต้องเนอะ และใช้คำสั่ง

npm install axios --save

ผลที่ได้คือ ใน package.json ต้องมี axios เพิ่มขึ้นมาเนอะ

ต่อมา สร้าง function ที่เป็น export ชื่อว่า อะไรดีน้าาา การตั้งชื่อเป็นอะไรที่อาจจะไม่ง่าย และควรตั้งให้เราและทีมเข้าใจได้ง่าย ในที่นี้ชื่อว่า lineBot แล้วกันเนอะ โค้ดในส่วนนี้จะเป็นแบบนี้เนอะ เดี๋ยวเราจะมาอธิบายในแต่ละส่วนกัน

exports.lineBot = functions.region(region).https.onRequest((request, response) => {
  if (request.method === "POST") {
    const messageType = request.body.events[0].message.type;
    console.log(request.body.events[0]);

    if (messageType == 'text') {
      const textMessage = request.body.events[0].message.text;
      reply(
        request.body.events[0].replyToken,
        { type: "text", text: textMessage }
      );
    }
  }
  return response.status(200).send(request.method)
});

const reply = (token, payload) => {
  return axios({
    method: "post",
    url: `${LINE_MESSAGING_API}/message/reply`,
    headers: LINE_HEADER,
    data: JSON.stringify({
      replyToken: token,
      messages: [payload]
    })
  });
};
  • exports.lineBot เป็นการ export function ที่ชื่อว่า lineBot เพื่อนำไปใช้ต่อ ในที่นี้คือเป็น webhook ในการเชื่อมต่อระหว่าง LINE OA ที่เป็น LINE bot ของเรา กับตัวบอทเนอะ
  • region(region) ใส่ region ที่เราต้องการ เน้นใกล้เราไว้ก่อน จะได้โหลดไวๆ
  • request.method === "POST" ดักว่าเป็น method ที่เป็น POST ไหม ถ้าใช้เราจะทำงานต่อนะ
  • ตัว request.body.event[0] ที่ได้ จะเป็นประมาณนี้
อันนี้รูปเก่าแหละ ขี้เกียจแคปรูปใหม่

จากการทดลองรันใน Firebase Emulator นะ สิ่งที่เราสนใจ คือ type ที่เป็น message.type เพื่อเอามาใช้ในการส่งข้อความที่เราพิมพ์กลับไปเป็น echo bot เนอะ และ replyToken ใช้ในการส่งข้อความจากบอทไปให้ user เนอะ

  • เราจะต้องดักก่อนว่า message ที่ได้มานั้น มี type เป็น text ถึงจะทำงานต่อ เพราะถ้าเราไม่ได้ดักไว้ อาจจะมีข้อความ type อื่นเช่น sticker จะทำให้โค้ดที่เราเขียนนั้น crash ได้จ้า เพราะเราไม่สามารถดึง message.text ได้นั่นเอง
  • เรานำข้อความที่ได้จากการที่ user พิมพ์เข้ามา ซึ่งก็คือ request.body.events[0].message.text ทำการส่งกลับให้เป็น echo bot ซะ
  • ทำการปั้นข้อความ แล้ว reply ส่งไปให้ user โดยจะส่ง replyToken และตัว payload ไปกับตัว json ที่เป็น message โดยใช้ axios เข้าช่วยจ้า ซึ่งแยกเป็น reply ออกมา เผื่อใช้หลาย function เนอะ โดยการส่งจะเป็นตามใน document นี้นะ
Sending messages
The LINE Developers site is a portal site for developers. It contains documents and tools that will help you use our various developer products. Creating LINE Login and Messaging API applications and services has never been easier!

และโค้ด echo bot ทั้งหมดจะอยู่ในนี้นะ

แน่นอนว่าคนอ่านไม่น่าจะทำ echo bot แหละเนอะ ดังนั้นการ implement ต่างๆนั้น คนอ่านสามารถเอาไปต่อยอดได้เลยจ้าว่าอยากทำบอทอะไร

ตัวอย่างสดๆร้อนๆก็คือ การทำแชทบอทแมวทิพย์ของเราในงาน Stupid Hackathon Thailand ครั้งที่ 5 นั่นเอง โดยต่อยอดจาก echobot เมื่อกี้นี่แหละ

เราจะให้น้องแมวทิพย์ที่ชื่อว่าลิลลี่ทำการตอบกลับแบบเมี้ยวๆไปให้ ซึ่งเราจะมี wording ต่างๆที่เราทำเป็นลักษณะที่เรียกว่ากาชาดังนี้

.

เราเลยเขียนไฟล์ใหม่แยกไปโดยเฉพาะ สร้าง class ใหม่ขึ้นมา ชื่อว่า Preset ในนั้นจะมี word และ weight ของแต่ละคำ และมีผลรวมกันเป็น 100

จากนั้นเราทำการ  random เลขออกมาตัวนึงระหว่าง 0 - 100 จากนั้นวนลูปหาว่าเลขนี้มันตกในช่วงไหน ที่พิเศษคือถ้าสุ่มได้ช่วงคำว่า meow เราจะเติม w ให้มันดูเสียงยาวๆหน่อย

สุดท้ายอย่าลืม export มันออกมาเนาะ

กลับไปที่ index.js เพื่อ import ที่เราทำเมื่อกี้เข้ามา แล้วที่นี้อ่ะ แมวมันไม่ค่อยมี wording เยอะ และตัวนึงที่เราสนใจก็คือ Purrrr ซึ่งเป็นเสียงจากการลูกแมว จึงแยกอีก condition นึงไว้ต่างหาก แต่ที่นี้เรารู้สึกว่าส่ง text มันดูแห้งๆไปอ่ะ ก็เลยให้ส่งเป็นเสียงไป ให้รู้สึกว่าเราลูบมันจริงๆ 555

การส่ง message type ต่างๆ สามารถดูได้เพิ่มเติมที่นี่จ้า

รู้จักกับ Message ใน LINE ที่คนส่งได้ LINE Bot ก็ส่งได้
หลายคนคงคิดว่าการคุยกับ Chatbot จะสามารถโต้ตอบกันได้เพียง Text เท่านั้น แต่สำหรับ Chatbot ใน LINE เราสามารถส่งข้อความได้หลากหลายรูปแบบ…

ถ้าอยากให้น้องลิลลี่ทำอะไรเพิ่มบอกได้เลยน้าา~~~ และสามารถเล่นกับน้องได้ที่นี่เลย

github ของโค้ดทั้งหมด ผ่านการเซ็นเซอร์ key ต่างๆด้วย Firebase Environment configuration จ้า

GitHub - mikkipastel/meowbot: แชทบอทสำหรับคนที่ไม่มีแมว?!?!
แชทบอทสำหรับคนที่ไม่มีแมว?!?! Contribute to mikkipastel/meowbot development by creating an account on GitHub.

โค้ดทั้งหมดอ้างอิงจากของพี่ตี๋ในนี้แหละจ้า

linedevth/LINE-Bot-101-Cloud-Functions-for-Firebase
Code sample for creating LINE Bot by Messaging API and Cloud Functions for Firebase - linedevth/LINE-Bot-101-Cloud-Functions-for-Firebase

ทำการตั้งค่าเพื่อทำ Firebase Emulator Suite

ไปที่ไฟล์ firebase.json ซึ่งอยู่ชั้นนอกสุด เข้าไปจะเจอ json เปล่าๆอยู่

ให้ทำการใส่อันนี้ลงไป เพื่อเป็นการ setup local port ในการรัน Cloud Functions for Firebase ผ่าน Firebase Emulator Suite จ้า

ทดสอบใน localhost ด้วย Firebase Emulator Suite และ ngrok

เป็นการทดสอบโดยใช้ Firebase Emulator Suite ร่วมกันกับ ngrok ก็ตามบล็อกนี้ของพี่ตี๋เลย

เผยวิธีพัฒนา LINE Chatbot ด้วย Cloud Functions for Firebase แบบไม่ต้อง Deploy
Pain point หนึ่งในการพัฒนา LINE Chatbot ด้วย Cloud Functions for Firebase ก็คือการ Deploy เพราะแต่ละครั้งจะต้องใช้เวลาประมาณ 40–60 วินาที

อันนี้เราจะมา wrap-up สรุปขั้นตอนให้เลยว่าทำอย่างไรเนอะ

เมื่อเราเขียนบอทจนพอใจในระดับนึงแล้ว อยากเทส local ก่อน ใช้ Firebase Emulator Suite ได้เลย แบบนี้

firebase emulators:start --only functions

ผลที่ได้คือ เราจะได้ path ที่เป็น localhost พร้อม port ที่สามารถใช้งานได้หล่ะ โดยเราจะใช้ port 5001 เพราะตัว emulator functions จะเป็น localhost:5001 นั่นเอง

ลองเปิดเว็บ UI ดูสิว่าเป็นอย่างไร เราสามารถดูหน้า UI ของ Firebase Emulator Suite ได้ด้วยนะ

แต่ด้วยความ localhost คือเทส API ไว้ดูอ่ะได้ แต่เทสบอทเนี่ย ตัว LINE OA ของเราจะรู้จักเจ้า localhost ไหม? ก็ไม่

ดังนั้นทำการเชื่อมอุโมงด้วย ngrok จ้า ติดตั้งโปรแกรมให้เรียบร้อย โดยการแตกซิปผ่าน command line เน้อ

จากนั้นทำการเชื่อมต่อกับตัว ngrok โดยไป get token ของ account ของเราจากตัว dashboard มา แล้วใส่ token ที่ได้ตามหลังแบบนี้

/ngrok authtoken YOUR_AUTH_TOKEN

ซึ่งทำเฉพาะครั้งแรกพอนะในการเชื่อมต่อ account หน่ะนะ

สุดท้าย ทำการเปิด Terminal อีกหน้าต่างนึง เพื่อทำการเชื่อมต่อ localhost ของเรากับอุโมง ซึ่ง localhostดังนั้นเราจะเชื่อมต่อกันด้วย port 5001นะ

./ngrok http 5001

เราก็จะได้ url ที่ผ่านการเข้าอุโมง นำไปใช้ต่อใน chatbot ของเราแล้วจ้า

เราสามารถตรวจสอบได้ด้วยการเข้าไปที่ url path ที่ผ่านการต่ออุโมงมา ซึ่งจะต้องเข้าหน้า console ของ Firebase Emulator Suite ได้เหมือนกัน

จากนั้นนำไปใส่ใน webhook url บนหน้า console ของ LINE OA เนอะ

มาดู url ที่ได้จากการ run Firebase Emulator Suite กันก่อนเลยจ้า

http://localhost:5001/{project_id}/asia-northeast1/lineBot

ถ้าเราเอาไป deploy จริง สิ่งที่เปลี่ยนก็คือตรง root ที่เปลี่ยนไปเนอะ

เอา url ที่ได้จากการเชื่อมอุโมงเมื่อสักครู่ไปใส่แทน localhost จะได้ดังนี้

https://47fcb2a3a8e7.ngrok.io/{project_id}/asia-northeast1/lineBot

เราก็ก้อปปี้ตัว path ที่เป็น https นี้ไปใส่ได้เลย เมื่อใส่ถูกต้องแล้วทำการกด Update เลยจ้า

จะเซ็นเซอร์แล้วทำให้สุดไปเลยจ้า

แล้วก็อย่าลืมเปิดให้ใช้ webhook ด้วยนะ

และก่อนใช้ อย่าลืมปิด auto-response messages ก่อนด้วยนะ

ทดสอบการทำงาน เพิ่มเพื่อน LINE OA ที่เป็น chatbot ตัวนี้กันไปก่อนนะ ผ่าน QR Code

ผลที่ได้จะเป็นประมาณนี้

แมวทิพย์ใน My Talking Tom 2 ชื่อทิมมี่ บางทีก็เรียกติม

ในระหว่างการทดสอบเราจะเห็น log ต่างๆที่เราทำการตั้งไว้ด้วยหล่ะ ถ้ามีตรงไหน crash เราสามารถแก้โค้ด แล้วเซฟ และทดสอบใหม่ได้เลยไม่ต้อง deploy ใหม่เลย

สามารถเข้าไปอ่าน document เพิ่มเติมได้ด้านล่างจ้า

Connect your app to the Cloud Functions Emulator | Firebase

พวก key ต่างๆที่เราใช้และอยากเก็บให้เป็นระเบียบ สามารถดูได้ที่นี่นะ (เพราะมันใช้ Environment configuration ไม่ได้อ่ะ แงงง)

Run functions locally | Firebase

ทำการ deploy จริง และนำ webhook เพื่อให้ LINE Chatbot ใช้งานได้

ถ้าอยากใช้งานจริงๆ อย่าลืม upgrade project ของ Firebase ให้เป็น Blaze Plan เสียก่อน เพราะตัว Cloud Functions for Firebase มันเชื่อมต่อ service ฝั่ง Google Cloud ด้วย

Firebase มี 2 plans คือ Spark Plan อันนี้ฟรี และ Blaze Plan เป็น Pay as you go เนอะ

Firebase Pricing
Get started with Firebase for free, and scale worldwide to millions of users, paying only for what you use.

สุดท้ายใช้คำสั่งนี้บน command เพื่อ deploy จริง

firebase deploy --only functions:lineBot

และเราก็ได้เส้น webhook มาใช้จริงได้เลย หน้าตาจะเป็นดังนี้

https://{region}-{project_id}.cloudfunctions.net/lineBot

การเก็บ key ต่างๆบน production สามารถดูได้ที่นี่ได้เลยจ้า

Environment configuration | Firebase

สุดท้าย ถ้าอยากรู้ว่า Firebase Emulator Suite ทำอะไรได้บ้าง มาดูในนี้ได้เลย

หรือถ้าอยากไปลองเล่นก็เล่น codelab ได้เน้อ

Local Development with the Firebase Emulator Suite
Learn how to develop a web app with the Firebase Emulator Suite.

download แอพอ่านบล็อกใหม่ของเราได้ที่นี่

MikkiPastel - Apps on Google Play
First application from “MikkiPastel” on play store beta feature- read blog from https://www.mikkipastel.com by this application- read blog content by chrome custom tab- update or refresh new content by pull to refresh- share content to social network
https://play.google.com/store/apps/details?id=com.mikkipastel.blog

ติดตามข่าวสารและบทความใหม่ๆได้ที่

อย่าลืมกด like กด share บทความกันด้วยนะคะ :)

Posted by MikkiPastel on Sunday, 10 December 2017

และช่องทางใหม่ใน Twiter จ้า

Tags

Minseo Chayabanjonglerd

I am a full-time Android Developer and part-time contributor with developer community and web3 world, who believe people have hard skills and soft skills to up-skill to da moon.