Gin(Golan)製で作った今話題のLINE BOT APIをHeroku上で動かしてみた!

[LINE BOT API Trial Account](https://business.line.me/services/products/4/introduction)が、10,000名まで先行申し込み受付中！とあったので、公開直後にアカウント作って、遊んでみた

とりあえずよくあるオウムさんを作りました。


## 使った物
* Golang
* Gin
* Heroku
* Fixie(Heroku Addon)

## cmd/go-getting-started/main.go

```
package main

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

	"github.com/gin-gonic/gin"
)

//BotRequestBody リクエスト内容を格納
type BotRequestBody struct {
	Request BotRequest `json:"Request"`
}

//BotRequest
type BotRequest struct {
	Result []BotResult `json:"result"`
}

type BotResult struct {
	From        string   `json:"from"`
	FromChannel string   `json:"fromChannel"`
	To          []string `json:"to"`
	ToChannel   string   `json:"toChannel"`
	EventType   string   `json:"eventType"`
	ID          string   `json:"id"`
	Content     Content  `json:"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"`
}

type SendRequest struct {
	To        []string `json:"to"`
	ToChannel int      `json:"toChannel"`
	EventType string   `json:"eventType"`
	Content   Content  `json:"content"`
}

const (
	EndPoint  = "https://trialbot-api.line.me/v1/events"
	ToChannel = 1383378250
	EventType = "138311608800106203"
)

func main() {
	router := gin.New()
	router.Use(gin.Logger())
	router.POST("/linebot/callback", callbackHandler)
	router.Run(":" + os.Getenv("PORT"))
}

func callbackHandler(c *gin.Context) {
	var botRequest BotRequest
	if c.Bind(&botRequest) == nil {
		c.JSON(http.StatusOK, gin.H{"status": fmt.Sprintf("request convert error, request data is %+v", botRequest)})
		return
	}

	for _, result := range botRequest.Result {

		request := SendRequest{
			To:        []string{result.Content.From},
			ToChannel: ToChannel,
			EventType: EventType,
			Content: Content{
				ContentType: result.Content.ContentType,
				ToType:      result.Content.ToType,
				Text:        result.Content.Text,
			},
		}

		if _, err := post(request); err != nil {
			log.Printf("Error: %s", err.Error())
		}
	}

	c.JSON(http.StatusOK, gin.H{"status": "end"})
}

func post(r SendRequest) (*http.Response, error) {
	b, _ := json.Marshal(r)
	req, _ := http.NewRequest(
		"POST",
		EndPoint,
		bytes.NewBuffer(b),
	)

	req = setHeader(req)

	proxyURL, _ := url.Parse(os.Getenv("FIXIE_URL"))
	client := &http.Client{
		Timeout:   time.Duration(15 * time.Second),
		Transport: &http.Transport{Proxy: http.ProxyURL(proxyURL)},
	}

	return client.Do(req)
}

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("LINE_CHANNEL_ID"))
	req.Header.Add("X-Line-ChannelSecret", os.Getenv("LINE_CHANNEL_SECRET"))
	req.Header.Add("X-Line-Trusted-User-With-ACL", os.Getenv("LINE_CHANNEL_MID"))
	return req
}
```

![line bot.gif](https://qiita-image-store.s3.amazonaws.com/0/8529/2d41e0d9-f38e-d3fd-52d9-99326e4b4b6a.gif)
![oli2310i.png](https://qiita-image-store.s3.amazonaws.com/0/8529/0de5f0c5-c871-4905-a5dc-af78765ee55c.png)