Facebook Bot API + Go でオウム作ってみた
Tags: facebook, bot, go
Published: 2020-03-26 02:25:13

---
title: Facebook Bot API + Go でオウム作ってみた
published: true
description: 
tags: Facebook, bot, Go 
---

今度はFacebook Bot試してみる

https://developers.facebook.com/docs/messenger-platform/quickstart

ここに作り方書いてあるので、書いてある手順で設定する。

1. Verify Tokenは自分が決めて設定、herokuのenvに反映
2. Access Tokenはfacebook pageごとに違うので、コピーしてheorkuのenvに反映

Goコードは以下ようにすれば、オウムbotはできる。

```go
package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"os"
	"time"
)

var accessToken = os.Getenv("ACCESS_TOKEN")
var verifyToken = os.Getenv("VERIFY_TOKEN")

// const ...
const (
	EndPoint = "https://graph.facebook.com/v2.6/me/messages"
)

// ReceivedMessage ...
type ReceivedMessage struct {
	Object string  `json:"object"`
	Entry  []Entry `json:"entry"`
}

// Entry ...
type Entry struct {
	ID        int64       `json:"id"`
	Time      int64       `json:"time"`
	Messaging []Messaging `json:"messaging"`
}

// Messaging ...
type Messaging struct {
	Sender    Sender    `json:"sender"`
	Recipient Recipient `json:"recipient"`
	Timestamp int64     `json:"timestamp"`
	Message   Message   `json:"message"`
}

// Sender ...
type Sender struct {
	ID int64 `json:"id"`
}

// Recipient ...
type Recipient struct {
	ID int64 `json:"id"`
}

// Message ...
type Message struct {
	MID  string `json:"mid"`
	Seq  int64  `json:"seq"`
	Text string `json:"text"`
}

// SendMessage ...
type SendMessage struct {
	Recipient Recipient `json:"recipient"`
	Message   struct {
		Text string `json:"text"`
	} `json:"message"`
}

func main() {
	http.HandleFunc("/", helloHandler)
	http.HandleFunc("/webhook", webhookHandler)
	port := os.Getenv("PORT")
	addr := fmt.Sprintf(":%s", port)
	http.ListenAndServe(addr, nil)
}

func helloHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello, Facebook Bot")
}

func webhookHandler(w http.ResponseWriter, r *http.Request) {
	if r.Method == "GET" {
		if r.URL.Query().Get("hub.verify_token") == verifyToken {
			fmt.Fprintf(w, r.URL.Query().Get("hub.challenge"))
		} else {
			fmt.Fprintf(w, "Error, wrong validation token")
		}
	}
	if r.Method == "POST" {
		var receivedMessage ReceivedMessage
		b, err := ioutil.ReadAll(r.Body)
		if err != nil {
			log.Print(err)
		}
		if err = json.Unmarshal(b, &receivedMessage); err != nil {
			log.Print(err)
		}
		messagingEvents := receivedMessage.Entry[0].Messaging
		for _, event := range messagingEvents {
			senderID := event.Sender.ID
			if &event.Message != nil && event.Message.Text != "" {
				sentTextMessage(senderID, event.Message.Text)
			}
		}
		fmt.Fprintf(w, "Success")
	}
}

func sentTextMessage(senderID int64, text string) {
	recipient := new(Recipient)
	recipient.ID = senderID
	m := new(SendMessage)
	m.Recipient = *recipient
	m.Message.Text = text
	b, err := json.Marshal(m)
	if err != nil {
		log.Print(err)
	}
	req, err := http.NewRequest("POST", EndPoint, bytes.NewBuffer(b))
	if err != nil {
		log.Print(err)
	}
	values := url.Values{}
	values.Add("access_token", accessToken)
	req.URL.RawQuery = values.Encode()
	req.Header.Add("Content-Type", "application/json; charset=UTF-8")
	client := &http.Client{Timeout: time.Duration(30 * time.Second)}
	res, err := client.Do(req)
	if err != nil {
		log.Print(err)
	}
	defer res.Body.Close()
	var result map[string]interface{}
	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		log.Print(err)
	}
	if err := json.Unmarshal(body, &result); err != nil {
		log.Print(err)
	}
	log.Print(result)
}
```

基本的な流れは以下のようになります。
1. Facebook APP作成
2. verify tokenと決めてWebhooksになるものを用意する。herokuデプロイ
3. Facebook上でwebhook(callback url)を設定
4. Facebook上で対象facebook pageを選択してaccess tokenを取得
5. Subscribe the App to the Page
`curl -ik -X POST "https://graph.facebook.com/v2.6/me/subscribed_apps?access_token=<token>"`
6. access tokenをコードに反映（herokuのenv）してもう一回デプロイ
7. 対象facebook page行って「Message」してみる

<img width="276" alt="Screen Shot 2016-04-13 at 6.15.59 PM.png" src="https://qiita-image-store.s3.amazonaws.com/0/15490/a629f85d-e7ba-f49d-80e5-2f88f9bba214.png">

作ったbotをfacebookに申請して承認されて一般公開されないと開発者との会話しかwebhookに反応しない。友達に見せたいのであれば、facebookアカウントをTestersに追加しても反応する。

facebook pageの管理者であれば、botアカウントでユーザーに返信することもできる。