หมายเหตุ เนื่องจากความแตกต่างในรายละเอียดปลีกย่อยของการใช้คำสั่งบางคำสั่งระหว่างระบบปฏิบัติการ หากต้องให้รายละเอียดทุกระบบปฏิบัติการจะทำให้เนื้อหาเยิ่นเย้อเกินไป จึงขอใช้สภาพแวดล้อมของผู้เขียนคือ Linux
พฤติกรรมที่เราจะสร้างให้กับ Chatbot ของเราคือการนำความที่เข้าส่งเข้ามาตอบกลับออกไปหาผู้ส่งหรือที่เรียกว่า Echo Server นั่นเอง ถือว่าเป็นพฤติกรรมที่ง่ายที่สุดและนิยมทำกันเป็นตัวอย่าง
หมายเหตุ เครื่องหมาย @ที่วางไว้ข้างหน้า app นั้นหมายถึงการทำ decoration ให้กับฟังก์ชั่น route ด้วยฟังก์ชั่น hello_world()
ในบรรทัด app.run(host='') คือการสั่งให้ Flask เริ่มการทำงาน โดยจะมีเปิดพอร์ตสื่อสารเลขที่ 5000 (default port) host='' มีความหมายเดียวกับ host="0.0.0.0" ซึ่งเป็นอนุญาตให้ผู้ใช้สามารถใช้คอมพิวเตอร์เครื่องอื่น (ที่ไม่ใช่เครื่องที่ Flask ทำงาน) ติดต่อเข้ามาได้ ครับ นี่คือหลักการทำงานแบบคร่าว ๆ ของ Flask ครับ ให้ท่านทำการสำเนา code นี้แล้วบันทึกไว้ในไฟล์ชื่อ hello.py แล้วเรียกใช้งานด้วยคำสั่ง
และหากท่านใช้ Web Browser เปิดดูด้วย URL นี้ http://<ip addressของเครื่่องที่ใช้งาน>:5000/
ที่นี้มาดูการใช้ประโยชน์จาก Gunicorn กันบ้าง ครับ ทำไมเราต้องพึง Gunicorn ก็เพราะว่า Heroku ต้องติดต่อ client และ service หลากหลาย (เขาเป็น Clound ) ดังนั้น Service ที่ทำงานบน Heroku ก็ควรจะรองรับการทำงานแบบนั้นด้วย ข้อจำกัดของ Flask หรือ DJango คือรองรับการเรียกใช้บริการ request by request  (เพราะมันคือ application) หากให้ Heroku ส่ง request ไปหา Flask หรือ DJango โดยตรง มันจะเกิดการรองานเกิดขึ้น ดังนั้นเราจึงต้องมีตัวกลาวคือ Gunicorn มารับหน้าเสื่อแทนนั้นเอง  การเรียกใช้ Gunicorn ให้พิมพ์คำสั่งดังนี้
หมายเหตุ : 'XXXXX' คือ ข้อมูลที่เราต้องให้ไว้กับ Facebook ในขั้นตอนการสมัครใช้ Chatbot
4.2 ) เมื่อมีผู้ส่งข้อความเข้ามาทาง Facebook Messenger จะทำการส่งข้อมูลของผู้ส่ง มาให้ Chatbot ในรูปแบบของ POST request (อ่านเพิ่มเติม https://developers.facebook.com/docs/messenger-platform/webhook-reference) สิ่งที่เราต้องทำคือ 4.2.1 รับข้อมูลแล้วทำการตอบรับกลับไปยัง Facebook Messenger ด้วยสถานะ 200 OK ตามมาตรฐานของ HTTP Status ไม่เช่นนั้นทาง Facebook Messenger จะถือว่าการส่งข้อความครั้งนั้นล้มเหลว 4.2.2 ทำการแยกแยะข้อมูลต่าง ๆ ประมวลผล แล้วทำการส่งผลการทำงานของเราผ่านไปที่ Facebook Messenger โดยทำตามวิธีการ send request ขอให้พิจารณาดูโครงสร้างข้อมูลที่ทาง Facebook ทำการส่งมาให้จะอยู่ในรูปแบบของ JSON
[ตอนที่ 1] [ตอนที่ 3] [ตอนที่ 4]
พฤติกรรมที่เราจะสร้างให้กับ Chatbot ของเราคือการนำความที่เข้าส่งเข้ามาตอบกลับออกไปหาผู้ส่งหรือที่เรียกว่า Echo Server นั่นเอง ถือว่าเป็นพฤติกรรมที่ง่ายที่สุดและนิยมทำกันเป็นตัวอย่าง
1. สร้างสภาพแวดล้อมการทำงานด้วย VirtualEnv
1.1 สร้าง Folder สำหรับทำงานขึ้นมาก่อน สมมุติให้ชื่อว่า fb-chatbot
mkdir fb-chatbot
virtualenv fb-chatbot
cd fb-chatbot
source bin/activate 
bin/activate
2. ติดตั้งซอฟต์แวร์
pip install Flask gunicorn requests
- Flask คือ Python Web Framework ที่เราจะใช้ในการสร้างซอฟต์แวร์
- Gunicorn คือ Python WSGI HTTP Server ซึ่งเราต้องนำมาใช้เพื่อให้ Flask สามารถทำงานบน Heroku ได้
- requests คือ utility ใช้ในการส่งความต้องการไปยัง Facebook Messenger
3. เรียนรู้ Flask และ Gunicorn สักนิด
เรามาทดลองสร้าง Web Application ง่าย ๆ ด้วย Flask กันดูนะครับ โดยผมจะลอกมาจากตัวอย่างของ Flask เลย
from flask import Flask,request
app = Flask(__name__)
@app.route('/')
def hello_world():
    return 'Hello World!'
if __name__ == '__main__':
    app.run(host='')
หมายเหตุ เครื่องหมาย @ที่วางไว้ข้างหน้า app นั้นหมายถึงการทำ decoration ให้กับฟังก์ชั่น route ด้วยฟังก์ชั่น hello_world()
ในบรรทัด app.run(host='') คือการสั่งให้ Flask เริ่มการทำงาน โดยจะมีเปิดพอร์ตสื่อสารเลขที่ 5000 (default port) host='' มีความหมายเดียวกับ host="0.0.0.0" ซึ่งเป็นอนุญาตให้ผู้ใช้สามารถใช้คอมพิวเตอร์เครื่องอื่น (ที่ไม่ใช่เครื่องที่ Flask ทำงาน) ติดต่อเข้ามาได้ ครับ นี่คือหลักการทำงานแบบคร่าว ๆ ของ Flask ครับ ให้ท่านทำการสำเนา code นี้แล้วบันทึกไว้ในไฟล์ชื่อ hello.py แล้วเรียกใช้งานด้วยคำสั่ง
python hello.py
gunicorn -w 1 -b 0.0.0.0:5000 hello:app
4. สร้าง Echo Bot
Facebook Messenger ได้กำหนดวิธีการติดต่อกับ Chatbot ของเราโดยการส่ง HTTP Requests พร้อมกับข้อมูล เพื่อให้รองรับการทำงานร่วมกับ Facebook Messenger ได้ เราต้องมีการปรับปรุงชุดคำสั่งให้สอดคล้องกับที่ Facebook กำหนดมาดังนี้ (อ่านเพิ่มเติม https://developers.facebook.com/docs/graph-api/webhooks ) 4.1 ) Facebook Messenger จะส่ง "GET" request เข้ามาเพื่อทำการตรวจสอบและยืนยันการมีตัวตน โดยข้อมูลที่ถูกส่งมาประกอบด้วย- hub.mode
- hub.challenge
- hub.verify_token
@app.route('/',methods=['GET'])
def verification_handle():
     verify_token = request.args.get('hub.verify_token','')
     challenge = request.args.get('hub.challenge', '') 
     if verify_token == 'xxxxxx' :
         return challenge
     else :
         return "Wrong validation"
หมายเหตุ : 'XXXXX' คือ ข้อมูลที่เราต้องให้ไว้กับ Facebook ในขั้นตอนการสมัครใช้ Chatbot
4.2 ) เมื่อมีผู้ส่งข้อความเข้ามาทาง Facebook Messenger จะทำการส่งข้อมูลของผู้ส่ง มาให้ Chatbot ในรูปแบบของ POST request (อ่านเพิ่มเติม https://developers.facebook.com/docs/messenger-platform/webhook-reference) สิ่งที่เราต้องทำคือ 4.2.1 รับข้อมูลแล้วทำการตอบรับกลับไปยัง Facebook Messenger ด้วยสถานะ 200 OK ตามมาตรฐานของ HTTP Status ไม่เช่นนั้นทาง Facebook Messenger จะถือว่าการส่งข้อความครั้งนั้นล้มเหลว 4.2.2 ทำการแยกแยะข้อมูลต่าง ๆ ประมวลผล แล้วทำการส่งผลการทำงานของเราผ่านไปที่ Facebook Messenger โดยทำตามวิธีการ send request ขอให้พิจารณาดูโครงสร้างข้อมูลที่ทาง Facebook ทำการส่งมาให้จะอยู่ในรูปแบบของ JSON
{
  "object":"page",
  "entry":[
    {
      "id":"PAGE_ID",
      "time":1458692752478,
      "messaging":[
        {
          "sender":{
            "id":"USER_ID"
          },
          "recipient":{
            "id":"PAGE_ID"
          },
          "message":{
            "text":"...."
          },
          ...
        }
      ]
    }
  ]
}   
@app.route('/',methods=['POST'])
def incoming_message_handle():
    #get data from request
    payload = request.get_data()
    
    #turn payload to json
    json_data = json.loads(payload)
    #extract entry, entry is an array
    entry = json_data['entry']
    #extract messaging from entry, messaging is an array
    messaging = entry[0]["messaging"]
    @app.route('/',methods=['POST'])
def incoming_message_handle():
    #get data from request
    payload = request.get_data()
    
    #turn payload to json
    json_data = json.loads(payload)
    #extract entry, entry is an array
    entry = json_data['entry']
    #extract messaging from entry, messaging is an array
    messaging = entry[0]["messaging"]
    for item in messaging :
      if "message" in item and "text" in item["message"] :
        #extract sender from messaging
        sender = item["sender"]
        #extract incoming message from messaging
        msg = item["message"]
        #echo back to sender
        echo_to_sender(sender["id"],msg["text"].encode('unicode_escape'))
    #tell Facebook that every is alright
    return json.dumps({'success':True}),200,{'Content-Type':'application/json'}
def echo_to_sender(sender_id,msg_txt):
    # get this from Facebook manual
        req = requests.post(
      "https://graph.facebook.com/v2.6/me/messages",
      params = {"access_token":access_token},
      data = json.dumps({
          "recipient":sender_id,
          "message": msg_txt
         }), 
      headers = {'Content-Type':'application/json'} )
from flask import Flask,request
import requests
import json
app = Flask(__name__)
@app.route('/',methods=['GET'])
def verification_handle():
     verify_token = request.args.get('hub.verify_token','')
     challenge = request.args.get('hub.challenge', '') 
     if verify_token == 'xxxxxx' :
         return challenge
     else :
         return "Wrong validation"
@app.route('/',methods=['POST'])
def incoming_message_handle():
    #get data from request
    payload = request.get_data()
    
    #turn payload to json
    json_data = json.loads(payload)
    #extract entry, entry is an array
    entry = json_data['entry']
    #extract messaging from entry, messaging is an array
    messaging = entry[0]["messaging"]
@app.route('/',methods=['POST'])
def incoming_message_handle():
    #get data from request
    payload = request.get_data()
    
    #turn payload to json
    json_data = json.loads(payload)
    #extract entry, entry is an array
    entry = json_data['entry']
    #extract messaging from entry, messaging is an array
    messaging = entry[0]["messaging"]
    for item in messaging :
      if "message" in item and "text" in item["message"] :
        #extract sender from messaging
        sender = item["sender"]
        #extract incoming message from messaging
        msg = item["message"]
        #echo back to sender
        echo_to_sender(sender["id"],msg["text"].encode('unicode_escape'))
    #tell Facebook that every is alright
    return json.dumps({'success':True}),200,{'Content-Type':'application/json'}
def echo_to_sender(sender_id,msg_txt):
    # get this from Facebook manual
    req = requests.post(
      "https://graph.facebook.com/v2.6/me/messages",
      params = {"access_token":access_token},
      data = json.dumps({
          "recipient":sender_id,
          "message": msg_txt
         }), 
      headers = {'Content-Type':'application/json'} )
[ตอนที่ 1] [ตอนที่ 3] [ตอนที่ 4]



ความคิดเห็น
แสดงความคิดเห็น