mtgbot/modules/apiact/line/line.go

239 lines
4.7 KiB
Go

package line
import (
"bytes"
"errors"
"fmt"
"io"
"net/http"
"net/url"
"path"
"git.trj.tw/golang/mtgbot/modules/apiact"
"git.trj.tw/golang/mtgbot/modules/config"
jsoniter "github.com/json-iterator/go"
)
var json = jsoniter.ConfigCompatibleWithStandardLibrary
// Line -
type Line struct {
URL string
APIVersion string
AccessToken string
}
// Message -
type Message struct {
Type string `json:"type"`
}
// TextMessage -
type TextMessage struct {
Message
Text string `json:"text"`
}
// ImageMessage -
type ImageMessage struct {
Message
OriginalContentURL string `json:"originalContentUrl"`
PreviewImageURL string `json:"previewImageUrl"`
}
// VideoMessage -
type VideoMessage struct {
Message
OriginalContentURL string `json:"originalContentUrl"`
PreviewImageURL string `json:"previewImageUrl"`
}
// UserInfo -
type UserInfo struct {
DisplayName string `json:"displayName"`
UserID string `json:"userId"`
}
type pushBody struct {
To string `json:"to"`
Messages []interface{} `json:"messages"`
}
type replyBody struct {
ReplyToken string `json:"replyToken"`
Messages []interface{} `json:"messages"`
}
// NewLineApi -
func NewLineApi(apiVersion string) (line *Line, err error) {
if len(apiVersion) == 0 {
apiVersion = "v2"
}
line = &Line{}
line.URL = "https://api.line.me"
line.APIVersion = apiVersion
conf := config.GetConf()
if len(conf.Line.Access) == 0 {
return nil, errors.New("access token is empty")
}
line.AccessToken = conf.Line.Access
return
}
func (p *Line) getAPIURL(urlPath string) (apiURL string, err error) {
u, err := url.Parse(p.URL)
if err != nil {
return "", err
}
u.Path = path.Join(u.Path, p.APIVersion, urlPath)
return u.String(), nil
}
func (p *Line) getHeader() (header map[string]string) {
header = make(map[string]string)
header["Content-Type"] = "application/json"
header["Authorization"] = fmt.Sprintf("Bearer %s", p.AccessToken)
return
}
// NewTextMessage -
func NewTextMessage(text string) (msg TextMessage, err error) {
msg = TextMessage{}
if len(text) == 0 {
return msg, errors.New("message is empty")
}
msg.Type = "text"
msg.Text = text
return
}
// NewImageMessage -
func NewImageMessage(originalURL, previewURL string) (msg ImageMessage, err error) {
msg = ImageMessage{}
if len(originalURL) == 0 || len(previewURL) == 0 {
return msg, errors.New("original url or preview url is empty")
}
msg.Type = "image"
msg.OriginalContentURL = originalURL
msg.PreviewImageURL = previewURL
return
}
// NewVideoMessage -
func NewVideoMessage(originalURL, previewURL string) (msg VideoMessage, err error) {
msg = VideoMessage{}
if len(originalURL) == 0 || len(previewURL) == 0 {
return msg, errors.New("original url or preview url is empty")
}
msg.Type = "video"
msg.OriginalContentURL = originalURL
msg.PreviewImageURL = previewURL
return
}
func checkMessageStruct(msg interface{}) (valid bool) {
switch msg.(type) {
case TextMessage:
case ImageMessage:
case VideoMessage:
return true
}
return false
}
// PushMessage -
func (p *Line) PushMessage(to string, msg interface{}) (err error) {
if len(to) == 0 {
return errors.New("target is empty")
}
apiURL, err := p.getAPIURL("/bot/message/push")
if err != nil {
return err
}
if !checkMessageStruct(msg) {
return errors.New("message struct validate fail")
}
body := &pushBody{To: to}
body.Messages = append(body.Messages, msg)
dataByte, err := json.Marshal(body)
if err != nil {
return err
}
dataReader := bytes.NewReader(dataByte)
resp, err := p.sendAPI(apiURL, "POST", dataReader)
if err != nil {
return err
}
defer resp.Body.Close()
return
}
// ReplyMessage -
func (p *Line) ReplyMessage(token string, msg interface{}) (err error) {
if len(token) == 0 {
return errors.New("reply token is empty")
}
apiURL, err := p.getAPIURL("/bot/message/reply")
if err != nil {
return err
}
if !checkMessageStruct(msg) {
return errors.New("message struct validate fail")
}
body := &replyBody{ReplyToken: token}
body.Messages = append(body.Messages, msg)
dataByte, err := json.Marshal(body)
if err != nil {
return err
}
dataReader := bytes.NewReader(dataByte)
resp, err := p.sendAPI(apiURL, "POST", dataReader)
if err != nil {
return err
}
defer resp.Body.Close()
return
}
func (p *Line) sendAPI(apiURL, method string, body io.Reader) (resp *http.Response, err error) {
if len(apiURL) == 0 {
return nil, errors.New("api url is empty")
}
reqObj := apiact.RequestObject{
Method: method,
URL: apiURL,
Body: body,
Headers: p.getHeader(),
}
req, err := apiact.GetRequest(reqObj)
if err != nil {
return nil, err
}
resp, err = http.DefaultClient.Do(req)
if err != nil {
return nil, err
}
return
}