追記 (2016/04/12)
Botの機能追加+ソースコードリファクタリングしてるうちにライブラリ化しました
https://github.com/dongri/line-bot-sdk-go
今のところ、text, sticker, image, video簡単に送れます。プロフィールも簡単に取得可能です。
まずコードから。メッセージを送るとそのメッセージをそのまま返すサンプル。下にちゃんとしたやつもあります。
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"net/url"
"os"
"time"
)
// ReceivedMessage ...
type ReceivedMessage struct {
Result []Result `json:"result"`
}
// Result ...
type Result struct {
ID string `json:"id"`
From string `json:"from"`
FromChannel int `json:"fromChannel"`
To []string `json:"to"`
ToChannel int `json:"toChannel"`
EventType string `json:"eventType"`
Content Content `json:"content"`
}
// SendMessage ..
type SendMessage struct {
To []string `json:"to"`
ToChannel int `json:"toChannel"`
EventType string `json:"eventType"`
Content Content `json:"content"`
}
// Content ...
type Content struct {
ID string `json:"id"`
ContentType int `json:"contentType"`
From string `json:"from"`
CreatedTime int `json:"createdTime"`
To []string `json:"to"`
ToType int `json:"toType"`
Text string `json:"text"`
}
// const ...
const (
EndPoint = "https://trialbot-api.line.me"
ToChannel = 1383378250
EventType = "138311608800106203"
)
func main() {
http.HandleFunc("/", helloHandler)
http.HandleFunc("/callback", callbackHandler)
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, LINE Bot")
}
func callbackHandler(w http.ResponseWriter, r *http.Request) {
decoder := json.NewDecoder(r.Body)
var m ReceivedMessage
err := decoder.Decode(&m)
if err != nil {
log.Println(err)
}
apiURI := EndPoint + "/v1/events"
for _, result := range m.Result {
from := result.Content.From
text := result.Content.Text
content := new(Content)
content.ContentType = result.Content.ContentType
content.ToType = result.Content.ToType
content.Text = text
request(apiURI, "POST", []string{from}, *content)
}
}
func request(endpointURL string, method string, to []string, content Content) {
m := &SendMessage{}
m.To = to
m.ToChannel = ToChannel
m.EventType = EventType
m.Content = content
b, err := json.Marshal(m)
if err != nil {
log.Print(err)
}
req, err := http.NewRequest(method, endpointURL, bytes.NewBuffer(b))
if err != nil {
log.Print(err)
}
req = setHeader(req)
client := &http.Client{
Transport: &http.Transport{Proxy: http.ProxyURL(getProxyURL())},
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)
}
func setHeader(req *http.Request) *http.Request {
req.Header.Add("Content-Type", "application/json; charset=UTF-8")
req.Header.Add("X-Line-ChannelID", os.Getenv("ChannelID"))
req.Header.Add("X-Line-ChannelSecret", os.Getenv("ChannelSecret"))
req.Header.Add("X-Line-Trusted-User-With-ACL", os.Getenv("MID"))
return req
}
func getProxyURL() *url.URL {
proxyURL, err := url.Parse(os.Getenv("ProxyURL"))
if err != nil {
log.Print(err)
}
return proxyURL
}
やってるうちに詰まったところをまとめ
callback URLはhttpsのみ
今まで簡単なサンプルは自前のサーバーでやってて、当然https対応してない。しかしLINE Botのcallbackはhttpsにportを443に指定しないといけない。let's encryptでhttps化。しかしcallbackにリクエストが来ない。herokuでなんとかすると決める。許可したipしかsendmessageできない
herokuにデプロイしてログを見てるとipで弾かれてる。指定したipでしかpostできないみたい。bot管理ページにwhitelistがあってそこに自分のサーバーip追加しないといけないらしい。しかし、herokuはデプロイする度にipが変わってて使いものにならない。こちらの記事( http://qiita.com/yuya_takeyama/items/0660a59d13e2cd0b2516 )にもかいてあるようにproxyを使ってproxyのipを指定すれば解決できる。contentTypeで弾かれてる
headerのcontent-typeかと思ったがメッセージcontentのcontentTypeをちゃんと指定しないといけない先着1万と書いてあるのが怪しい
1万枠外でもBotの登録できるんじゃないかと疑ってる。自分のアカウントは昨日早めに登録したので、使えるが、1アカウント1Botの制限のため今日嫁のアカウントで登録したけど、callbackが来ない。
とりあえず電車でも haskell
Top comments (0)