add pre group one bot setting

This commit is contained in:
Jay 2019-06-25 17:02:03 +08:00
parent c605b2d9e9
commit 8c432b9b68
13 changed files with 185 additions and 56 deletions

37
model/line_bot.go Normal file
View File

@ -0,0 +1,37 @@
package model
import (
"database/sql"
"errors"
"time"
)
// LineBot -
type LineBot struct {
ID string `db:"id" cc:"id"`
Name string `db:"name" cc:"name"`
AccessToken string `db:"access_token" cc:"access_token"`
Secret string `db:"secret" cc:"secret"`
Ctime time.Time `db:"ctime" cc:"ctime"`
Mtime time.Time `db:"mtime" cc:"mtime"`
}
// GetBotInfo -
func GetBotInfo(id string) (bot *LineBot, err error) {
if len(id) == 0 {
return nil, errors.New("id is emptu")
}
query := `select
"id", "name", "access_token", "secret", "ctime", "mtime"
from public."line_bot"
where
"id" = $1`
bot = &LineBot{}
err = x.Get(bot, query, id)
if err == sql.ErrNoRows {
return nil, nil
}
return
}

View File

@ -2,17 +2,19 @@ package model
import ( import (
"database/sql" "database/sql"
"errors"
"time" "time"
) )
// LineGroup - struct // LineGroup - struct
type LineGroup struct { type LineGroup struct {
ID string `db:"id" cc:"id"` ID string `db:"id" cc:"id"`
Name string `db:"name" cc:"name"` Name string `db:"name" cc:"name"`
Notify bool `db:"notify" cc:"notify"` Notify bool `db:"notify" cc:"notify"`
Owner string `db:"owner" cc:"owner"` Owner string `db:"owner" cc:"owner"`
Ctime time.Time `db:"ctime" cc:"ctime"` Ctime time.Time `db:"ctime" cc:"ctime"`
Mtime time.Time `db:"mtime" cc:"ctime"` Mtime time.Time `db:"mtime" cc:"ctime"`
BotID sql.NullString `db:"bot_id" cc:"bot_id"`
} }
// CheckGroup - // CheckGroup -
@ -75,3 +77,18 @@ func (p *LineGroup) DeleteGroup() (err error) {
_, err = x.Exec(`delete from "public"."line_group" where "id" = $1`, p.ID) _, err = x.Exec(`delete from "public"."line_group" where "id" = $1`, p.ID)
return return
} }
// GetBot - get group binding bot
func (p *LineGroup) GetBot() (bot *LineBot, err error) {
id, err := p.BotID.Value()
if err != nil {
return nil, err
}
var botid string
var ok bool
if botid, ok = id.(string); !ok {
return nil, errors.New("botid get fail")
}
bot, err = GetBotInfo(botid)
return
}

View File

@ -13,7 +13,6 @@ import (
"strings" "strings"
"git.trj.tw/golang/mtfosbot/module/apis" "git.trj.tw/golang/mtfosbot/module/apis"
"git.trj.tw/golang/mtfosbot/module/config"
) )
// TextMessage - line text message object // TextMessage - line text message object
@ -66,11 +65,10 @@ func getURL(p string) (string, bool) {
return str, true return str, true
} }
func getHeaders() map[string]string { func getHeaders(token string) map[string]string {
m := make(map[string]string) m := make(map[string]string)
conf := config.GetConf()
m["Content-Type"] = "application/json" m["Content-Type"] = "application/json"
m["Authorization"] = fmt.Sprintf("Bearer %s", conf.Line.Access) m["Authorization"] = fmt.Sprintf("Bearer %s", token)
return m return m
} }
@ -104,7 +102,7 @@ func checkMessageObject(m interface{}) interface{} {
} }
// PushMessage - // PushMessage -
func PushMessage(target string, message ...interface{}) { func PushMessage(accessToken, target string, message ...interface{}) {
log.Println("push target :::: ", target) log.Println("push target :::: ", target)
if len(target) == 0 || len(message) == 0 { if len(target) == 0 || len(message) == 0 {
return return
@ -145,7 +143,7 @@ func PushMessage(target string, message ...interface{}) {
reqObj := apis.RequestObj{ reqObj := apis.RequestObj{
Method: "POST", Method: "POST",
URL: apiURL, URL: apiURL,
Headers: getHeaders(), Headers: getHeaders(accessToken),
Body: byteReader, Body: byteReader,
} }
@ -163,7 +161,7 @@ func PushMessage(target string, message ...interface{}) {
} }
// ReplyMessage - // ReplyMessage -
func ReplyMessage(replyToken string, message ...interface{}) { func ReplyMessage(accessToken, replyToken string, message ...interface{}) {
if len(replyToken) == 0 || len(message) == 0 { if len(replyToken) == 0 || len(message) == 0 {
return return
} }
@ -201,7 +199,7 @@ func ReplyMessage(replyToken string, message ...interface{}) {
reqObj := apis.RequestObj{ reqObj := apis.RequestObj{
Method: "POST", Method: "POST",
URL: apiURL, URL: apiURL,
Headers: getHeaders(), Headers: getHeaders(accessToken),
Body: byteReader, Body: byteReader,
} }
@ -217,9 +215,9 @@ func ReplyMessage(replyToken string, message ...interface{}) {
} }
// GetUserInfo - // GetUserInfo -
func GetUserInfo(u, g string) (user *LineUserInfo, err error) { func GetUserInfo(accessToken, u, g string) (user *LineUserInfo, err error) {
urlPath := fmt.Sprintf("/v2/bot/group/%s/member/%s", g, u) urlPath := fmt.Sprintf("/v2/bot/group/%s/member/%s", g, u)
header := getHeaders() header := getHeaders(accessToken)
apiURL, ok := getURL(urlPath) apiURL, ok := getURL(urlPath)
if !ok { if !ok {
return nil, errors.New("url parser fail") return nil, errors.New("url parser fail")
@ -263,9 +261,9 @@ func GetUserInfo(u, g string) (user *LineUserInfo, err error) {
} }
// GetContentHead - // GetContentHead -
func GetContentHead(id string) (mime string, err error) { func GetContentHead(accessToken, id string) (mime string, err error) {
urlPath := fmt.Sprintf("/v2/bot/message/%s/content", id) urlPath := fmt.Sprintf("/v2/bot/message/%s/content", id)
header := getHeaders() header := getHeaders(accessToken)
u, ok := getURL(urlPath) u, ok := getURL(urlPath)
if !ok { if !ok {
return "", errors.New("get url fail") return "", errors.New("get url fail")
@ -294,9 +292,9 @@ func GetContentHead(id string) (mime string, err error) {
} }
// DownloadContent - // DownloadContent -
func DownloadContent(id string, w io.Writer) (err error) { func DownloadContent(accessToken, id string, w io.Writer) (err error) {
urlPath := fmt.Sprintf("/v2/bot/message/%s/content", id) urlPath := fmt.Sprintf("/v2/bot/message/%s/content", id)
header := getHeaders() header := getHeaders(accessToken)
u, ok := getURL(urlPath) u, ok := getURL(urlPath)
if !ok { if !ok {
return errors.New("get url fail") return errors.New("get url fail")

View File

@ -2,6 +2,7 @@ package background
import ( import (
"fmt" "fmt"
"log"
"net/http" "net/http"
"regexp" "regexp"
"sort" "sort"
@ -138,6 +139,11 @@ func getPageHTML(page *model.FacebookPage) {
for _, v := range page.Groups { for _, v := range page.Groups {
if v.Notify { if v.Notify {
bot, err := v.GetBot()
if err != nil || bot == nil {
log.Println("get group binding bot fail :: ", err)
continue
}
tmpl := v.Tmpl tmpl := v.Tmpl
if len(tmpl) > 0 { if len(tmpl) > 0 {
tmpl = strings.Replace(tmpl, "{link}", lastData.Link, -1) tmpl = strings.Replace(tmpl, "{link}", lastData.Link, -1)
@ -148,7 +154,7 @@ func getPageHTML(page *model.FacebookPage) {
msg := line.TextMessage{ msg := line.TextMessage{
Text: tmpl, Text: tmpl,
} }
line.PushMessage(v.ID, msg) line.PushMessage(bot.AccessToken, v.ID, msg)
} }
} }
} }

View File

@ -2,6 +2,7 @@ package background
import ( import (
"fmt" "fmt"
"log"
"strings" "strings"
"time" "time"
@ -61,6 +62,11 @@ func checkStream(ch *model.TwitchChannel, info *twitch.StreamInfo) {
link := fmt.Sprintf("https://twitch.tv/%s", ch.Name) link := fmt.Sprintf("https://twitch.tv/%s", ch.Name)
for _, v := range ch.Groups { for _, v := range ch.Groups {
if v.Notify { if v.Notify {
bot, err := v.GetBot()
if err != nil || bot == nil {
log.Println("get group binding bot fail :: ", err)
continue
}
tmpl := v.Tmpl tmpl := v.Tmpl
if len(tmpl) > 0 { if len(tmpl) > 0 {
tmpl = strings.Replace(tmpl, "{txt}", info.Title, -1) tmpl = strings.Replace(tmpl, "{txt}", info.Title, -1)
@ -71,7 +77,7 @@ func checkStream(ch *model.TwitchChannel, info *twitch.StreamInfo) {
msg := line.TextMessage{ msg := line.TextMessage{
Text: tmpl, Text: tmpl,
} }
line.PushMessage(v.ID, msg) line.PushMessage(bot.AccessToken, v.ID, msg)
} }
} }
} }

View File

@ -7,11 +7,13 @@ import (
) )
// MessageEvent - // MessageEvent -
func MessageEvent(e *lineobj.EventObject) { func MessageEvent(botid string, e *lineobj.EventObject) {
if len(botid) == 0 {
return
}
switch e.Type { switch e.Type {
case "message": case "message":
messageType(e) messageType(botid, e)
break break
default: default:
fmt.Println("line webhook type not match") fmt.Println("line webhook type not match")

View File

@ -16,7 +16,7 @@ import (
msgcmd "git.trj.tw/golang/mtfosbot/module/message-command" msgcmd "git.trj.tw/golang/mtfosbot/module/message-command"
) )
func messageType(e *lineobj.EventObject) { func messageType(botid string, e *lineobj.EventObject) {
msg := e.Message msg := e.Message
mtype, ok := msg["type"] mtype, ok := msg["type"]
if !ok { if !ok {
@ -26,17 +26,17 @@ func messageType(e *lineobj.EventObject) {
if t, ok := mtype.(string); ok { if t, ok := mtype.(string); ok {
switch t { switch t {
case "text": case "text":
textMsg(e) textMsg(botid, e)
break break
case "image": case "image":
imageMsg(e) imageMsg(botid, e)
break break
} }
} }
return return
} }
func textMsg(e *lineobj.EventObject) { func textMsg(botid string, e *lineobj.EventObject) {
msg := e.Message msg := e.Message
mtxt, ok := msg["text"] mtxt, ok := msg["text"]
if !ok { if !ok {
@ -46,14 +46,14 @@ func textMsg(e *lineobj.EventObject) {
// group action // group action
if e.Source.Type == "group" { if e.Source.Type == "group" {
if txt, ok := mtxt.(string); ok { if txt, ok := mtxt.(string); ok {
msgcmd.ParseLineMsg(txt, e.ReplyToken, e.Source) msgcmd.ParseLineMsg(botid, txt, e.ReplyToken, e.Source)
saveTextMsgToLog(txt, e.Source) saveTextMsgToLog(botid, txt, e.Source)
} }
} }
return return
} }
func imageMsg(e *lineobj.EventObject) { func imageMsg(botid string, e *lineobj.EventObject) {
msg := e.Message msg := e.Message
imgID, ok := msg["id"] imgID, ok := msg["id"]
if !ok { if !ok {
@ -62,19 +62,19 @@ func imageMsg(e *lineobj.EventObject) {
// group action // group action
if e.Source.Type == "group" { if e.Source.Type == "group" {
if id, ok := imgID.(string); ok { if id, ok := imgID.(string); ok {
saveImageMsgToLog(id, e.Source) saveImageMsgToLog(botid, id, e.Source)
} }
} }
} }
func getSourceUser(uid, gid string) (u *model.LineUser, err error) { func getSourceUser(accessToken, uid, gid string) (u *model.LineUser, err error) {
userData, err := model.GetLineUserByID(uid) userData, err := model.GetLineUserByID(uid)
if err != nil { if err != nil {
return return
} }
if userData == nil { if userData == nil {
tmpu, err := line.GetUserInfo(uid, gid) tmpu, err := line.GetUserInfo(accessToken, uid, gid)
if err != nil || tmpu == nil { if err != nil || tmpu == nil {
return nil, err return nil, err
} }
@ -87,7 +87,7 @@ func getSourceUser(uid, gid string) (u *model.LineUser, err error) {
} }
} else { } else {
if userData.Mtime.Unix() < (time.Now().Unix() - 86400) { if userData.Mtime.Unix() < (time.Now().Unix() - 86400) {
tmpu, err := line.GetUserInfo(uid, gid) tmpu, err := line.GetUserInfo(accessToken, uid, gid)
if err != nil || tmpu == nil { if err != nil || tmpu == nil {
return nil, err return nil, err
} }
@ -102,8 +102,13 @@ func getSourceUser(uid, gid string) (u *model.LineUser, err error) {
return userData, nil return userData, nil
} }
func saveTextMsgToLog(txt string, s *lineobj.SourceObject) { func saveTextMsgToLog(botid, txt string, s *lineobj.SourceObject) {
u, err := getSourceUser(s.UserID, s.GroupID) bot, err := model.GetBotInfo(botid)
if err != nil || bot == nil {
fmt.Println("get bot info fail :: ", err)
return
}
u, err := getSourceUser(bot.AccessToken, s.UserID, s.GroupID)
if err != nil || u == nil { if err != nil || u == nil {
return return
} }
@ -112,13 +117,18 @@ func saveTextMsgToLog(txt string, s *lineobj.SourceObject) {
model.AddLineMessageLog(s.GroupID, s.UserID, txt, "text") model.AddLineMessageLog(s.GroupID, s.UserID, txt, "text")
} }
func saveImageMsgToLog(id string, s *lineobj.SourceObject) { func saveImageMsgToLog(botid, id string, s *lineobj.SourceObject) {
u, err := getSourceUser(s.UserID, s.GroupID) bot, err := model.GetBotInfo(botid)
if err != nil || bot == nil {
fmt.Println("get bot info fail :: ", err)
return
}
u, err := getSourceUser(bot.AccessToken, s.UserID, s.GroupID)
if err != nil || u == nil { if err != nil || u == nil {
return return
} }
mime, err := line.GetContentHead(id) mime, err := line.GetContentHead(bot.AccessToken, id)
if err != nil || len(mime) == 0 { if err != nil || len(mime) == 0 {
return return
} }
@ -150,7 +160,7 @@ func saveImageMsgToLog(id string, s *lineobj.SourceObject) {
} }
defer w.Close() defer w.Close()
err = line.DownloadContent(id, w) err = line.DownloadContent(bot.AccessToken, id, w)
if err != nil { if err != nil {
return return
} }

View File

@ -1,6 +1,7 @@
package msgcmd package msgcmd
import ( import (
"fmt"
"regexp" "regexp"
"strings" "strings"
@ -22,10 +23,15 @@ func parseCMD(in string) (c [][]string) {
} }
// ParseLineMsg - // ParseLineMsg -
func ParseLineMsg(txt, replyToken string, source *lineobj.SourceObject) { func ParseLineMsg(botid, txt, replyToken string, source *lineobj.SourceObject) {
if source.Type != "group" { if source.Type != "group" {
return return
} }
bot, err := model.GetBotInfo(botid)
if err != nil || bot == nil {
fmt.Println("get bot err or no bot :: ", err)
return
}
strs := strings.Split(strings.Trim(txt, " "), " ") strs := strings.Split(strings.Trim(txt, " "), " ")
// skip empty string // skip empty string
@ -57,7 +63,7 @@ func ParseLineMsg(txt, replyToken string, source *lineobj.SourceObject) {
m := parseResult(v) m := parseResult(v)
msgs = append(msgs, m) msgs = append(msgs, m)
} }
line.ReplyMessage(replyToken, msgs...) line.ReplyMessage(bot.AccessToken, replyToken, msgs...)
} else { } else {
// key cmd // key cmd
@ -72,7 +78,8 @@ func ParseLineMsg(txt, replyToken string, source *lineobj.SourceObject) {
m := parseResult(v) m := parseResult(v)
msgs = append(msgs, m) msgs = append(msgs, m)
} }
line.ReplyMessage(replyToken, msgs...)
line.ReplyMessage(bot.AccessToken, replyToken, msgs...)
} }
} }

View File

@ -27,7 +27,20 @@ func PushLineMessage(c *context.Context) {
textObj := line.TextMessage{} textObj := line.TextMessage{}
textObj.Text = bodyData.Message textObj.Text = bodyData.Message
line.PushMessage(bodyData.Group, textObj) group, err := model.GetLineGroup(bodyData.Group)
if err != nil {
c.ServerError(nil)
log.Println("get group :: ", err)
return
}
bot, err := group.GetBot()
if err != nil || bot == nil {
log.Println("get group binding bot fail :: ", err)
c.ServerError(nil)
return
}
line.PushMessage(bot.AccessToken, bodyData.Group, textObj)
c.Success(nil) c.Success(nil)
} }

View File

@ -129,6 +129,11 @@ func GetNotifyWebhook(c *context.Context) {
for _, v := range yt.Groups { for _, v := range yt.Groups {
log.Println("group data :::: ", v, v.Notify, v.Name, v.ID) log.Println("group data :::: ", v, v.Notify, v.Name, v.ID)
bot, err := v.GetBot()
if err != nil || bot == nil {
log.Println("get group binding bot fail :: ", err)
continue
}
if v.Notify == true { if v.Notify == true {
str := v.Tmpl str := v.Tmpl
log.Println("template :::: ", str) log.Println("template :::: ", str)
@ -144,7 +149,7 @@ func GetNotifyWebhook(c *context.Context) {
} }
log.Println("msg ::::: ", msg) log.Println("msg ::::: ", msg)
lineapi.PushMessage(v.ID, msg) lineapi.PushMessage(bot.AccessToken, v.ID, msg)
} }
} }

View File

@ -7,9 +7,9 @@ import (
"encoding/json" "encoding/json"
"io/ioutil" "io/ioutil"
"git.trj.tw/golang/mtfosbot/module/config" "git.trj.tw/golang/mtfosbot/model"
"git.trj.tw/golang/mtfosbot/module/context" "git.trj.tw/golang/mtfosbot/module/context"
"git.trj.tw/golang/mtfosbot/module/line-message" linemsg "git.trj.tw/golang/mtfosbot/module/line-message"
lineobj "git.trj.tw/golang/mtfosbot/module/line-message/line-object" lineobj "git.trj.tw/golang/mtfosbot/module/line-message/line-object"
) )
@ -42,10 +42,21 @@ func VerifyLine(c *context.Context) {
return return
} }
conf := config.GetConf() botid, ok := c.GetQuery("id")
if !ok || len(botid) == 0 {
c.CustomRes(403, map[string]string{
"message": "no bot data",
})
}
hash := hmac.New(sha256.New, []byte(conf.Line.Secret)) bot, err := model.GetBotInfo(botid)
_, err := hash.Write(raw) if err != nil {
c.ServerError(nil)
return
}
hash := hmac.New(sha256.New, []byte(bot.Secret))
_, err = hash.Write(raw)
if err != nil { if err != nil {
c.ServerError(nil) c.ServerError(nil)
return return
@ -70,6 +81,12 @@ func GetLineMessage(c *context.Context) {
if raw, ok = rawbody.([]byte); !ok { if raw, ok = rawbody.([]byte); !ok {
c.DataFormat("body type error") c.DataFormat("body type error")
} }
botid, ok := c.GetQuery("id")
if !ok || len(botid) == 0 {
c.CustomRes(403, map[string]string{
"message": "no bot data",
})
}
events := struct { events := struct {
Events []*lineobj.EventObject `json:"events"` Events []*lineobj.EventObject `json:"events"`
@ -83,7 +100,7 @@ func GetLineMessage(c *context.Context) {
if len(events.Events) > 0 { if len(events.Events) > 0 {
for _, v := range events.Events { for _, v := range events.Events {
go linemsg.MessageEvent(v) go linemsg.MessageEvent(botid, v)
} }
} }

View File

@ -2,6 +2,7 @@ package private
import ( import (
"fmt" "fmt"
"log"
"strings" "strings"
"git.trj.tw/golang/mtfosbot/model" "git.trj.tw/golang/mtfosbot/model"
@ -107,6 +108,11 @@ func UpdateFacebookPagePost(c *context.Context) {
for _, g := range page.Groups { for _, g := range page.Groups {
if g.Notify { if g.Notify {
bot, err := g.GetBot()
if err != nil || bot == nil {
log.Println("get group binding bot fail ::: ", err)
continue
}
tmpl := g.Tmpl tmpl := g.Tmpl
if len(tmpl) > 0 { if len(tmpl) > 0 {
tmpl = strings.Replace(tmpl, "{link}", v.Link, -1) tmpl = strings.Replace(tmpl, "{link}", v.Link, -1)
@ -117,7 +123,7 @@ func UpdateFacebookPagePost(c *context.Context) {
msg := line.TextMessage{ msg := line.TextMessage{
Text: tmpl, Text: tmpl,
} }
line.PushMessage(g.ID, msg) line.PushMessage(bot.AccessToken, g.ID, msg)
} }
} }
} }
@ -169,6 +175,11 @@ func UpdateInstagramPost(c *context.Context) {
for _, g := range ig.Groups { for _, g := range ig.Groups {
if g.Notify { if g.Notify {
bot, err := g.GetBot()
if err != nil || bot == nil {
log.Println("get group binding bot fail :: ", err)
continue
}
tmpl := g.Tmpl tmpl := g.Tmpl
if len(tmpl) > 0 { if len(tmpl) > 0 {
tmpl = strings.Replace(tmpl, "{link}", v.Link, -1) tmpl = strings.Replace(tmpl, "{link}", v.Link, -1)
@ -178,7 +189,7 @@ func UpdateInstagramPost(c *context.Context) {
} }
msg := line.TextMessage{Text: tmpl} msg := line.TextMessage{Text: tmpl}
line.PushMessage(g.ID, msg) line.PushMessage(bot.AccessToken, g.ID, msg)
} }
} }
} }

2
schema

@ -1 +1 @@
Subproject commit f0a256f088c78dcd6d7d576e768724de656f5a53 Subproject commit 3bdfd83583b60d443e0c958e7991c579176f298e