diff --git a/main.go b/main.go index 4e60c98..6203c83 100644 --- a/main.go +++ b/main.go @@ -8,6 +8,7 @@ import ( "git.trj.tw/golang/mtfosbot/model" "git.trj.tw/golang/mtfosbot/module/background" "git.trj.tw/golang/mtfosbot/module/config" + twitchirc "git.trj.tw/golang/mtfosbot/module/twitch-irc" "git.trj.tw/golang/mtfosbot/router/routes" "github.com/gin-gonic/gin" ) @@ -33,5 +34,10 @@ func main() { } defer db.Close() + err = twitchirc.InitIRC() + if err != nil { + log.Println(err) + } + server.Run(strings.Join([]string{":", strconv.Itoa(config.GetConf().Port)}, "")) } diff --git a/model/commands.go b/model/commands.go index 525ccfe..18bf604 100644 --- a/model/commands.go +++ b/model/commands.go @@ -1,6 +1,10 @@ package model -import "time" +import ( + "database/sql" + "errors" + "time" +) // Commands - struct type Commands struct { @@ -10,3 +14,36 @@ type Commands struct { Ctime time.Time `db:"ctime" cc:"ctime"` Mtime time.Time `db:"mtime" cc:"ctime"` } + +// GetAllCommands - +func GetAllCommands() (cmds []*Commands, err error) { + err = x.Select(&cmds, `select * from "public"."commands"`) + return +} + +// GetGroupCommand - +func GetGroupCommand(c, g string) (cmd *Commands, err error) { + if len(c) == 0 { + return nil, errors.New("command is empty") + } + tmpCmd := struct { + Commands + Message2 sql.NullString `db:"message2"` + }{} + query := `select c.*, c2.message as message2 from "public"."commands" c + left join "public"."commands" c2 + on c2.cmd = c.cmd and c2."group" = $2 + where c."cmd" = $1 + and c."group" = ''` + err = x.Get(&tmpCmd, query, c, g) + if err != nil { + return nil, err + } + + cmd = &tmpCmd.Commands + if tmpCmd.Message2.Valid { + cmd.Message = tmpCmd.Message2.String + } + + return +} diff --git a/model/key_commands.go b/model/key_commands.go index cc8b536..1064114 100644 --- a/model/key_commands.go +++ b/model/key_commands.go @@ -1,6 +1,10 @@ package model -import "time" +import ( + "database/sql" + "errors" + "time" +) // KeyCommands - struct type KeyCommands struct { @@ -10,3 +14,30 @@ type KeyCommands struct { Ctime time.Time `db:"ctime" cc:"ctime"` Mtime time.Time `db:"mtime" cc:"ctime"` } + +// GetKeyCommand - +func GetKeyCommand(c, g string) (cmd *KeyCommands, err error) { + if len(c) == 0 { + return nil, errors.New("command is empty") + } + tmpCmd := struct { + KeyCommands + Message2 sql.NullString `db:"message2"` + }{} + query := `select c.*, c2.message as message2 from "public"."key_commands" c + left join "public"."key_commands" c2 + on c2.key = c.key and c2."group" = $2 + where c."key" = $1 + and c."group" = ''` + err = x.Get(&tmpCmd, query, c, g) + if err != nil { + return nil, err + } + + cmd = &tmpCmd.KeyCommands + if tmpCmd.Message2.Valid { + cmd.Message = tmpCmd.Message2.String + } + + return +} diff --git a/model/line_group.go b/model/line_group.go index 2ff0a89..1cdf240 100644 --- a/model/line_group.go +++ b/model/line_group.go @@ -11,3 +11,16 @@ type LineGroup struct { Ctime time.Time `db:"ctime" cc:"ctime"` Mtime time.Time `db:"mtime" cc:"ctime"` } + +// CheckGroup - +func CheckGroup(g string) (exists bool, err error) { + ss := struct { + C int `db:"c"` + }{} + + err = x.Get(&ss, `select count(*) as c from "public"."line_group" where "id" = $1`, g) + if err != nil { + return false, err + } + return ss.C > 0, nil +} diff --git a/model/twitch_channel.go b/model/twitch_channel.go index 0587437..81a1bb2 100644 --- a/model/twitch_channel.go +++ b/model/twitch_channel.go @@ -26,6 +26,12 @@ func GetAllTwitchChannel() (channels []*TwitchChannel, err error) { return } +// GetJoinChatChannel - +func GetJoinChatChannel() (channels []*TwitchChannel, err error) { + err = x.Select(&channels, `select * from "public"."twitch_channel" where "join" = true`) + return +} + // UpdateStream - func (p *TwitchChannel) UpdateStream(streamID string) (err error) { query := `update "public"."twitch_channel" set "laststream" = $1 where "id" = $2` diff --git a/module/line-message/line-object/line-object.go b/module/line-message/line-object/line-object.go new file mode 100644 index 0000000..a82fb11 --- /dev/null +++ b/module/line-message/line-object/line-object.go @@ -0,0 +1,17 @@ +package lineobj + +// EventObject - +type EventObject struct { + Source *SourceObject `json:"source" cc:"source"` + Type string `json:"type" cc:"type"` + Timestamp int32 `json:"timestamp" cc:"timestamp"` + ReplyToken string `json:"replyToken" cc:"replyToken"` + Message map[string]interface{} `json:"message" cc:"message"` +} + +// SourceObject - +type SourceObject struct { + Type string `json:"type" cc:"type"` + UserID string `json:"userId" cc:"userId"` + GroupID string `json:"groupId" cc:"groupId"` +} diff --git a/module/line-message/message-event.go b/module/line-message/message-event.go new file mode 100644 index 0000000..c478550 --- /dev/null +++ b/module/line-message/message-event.go @@ -0,0 +1,19 @@ +package linemsg + +import ( + "fmt" + + lineobj "git.trj.tw/golang/mtfosbot/module/line-message/line-object" + "git.trj.tw/golang/mtfosbot/module/utils" +) + +// MessageEvent - +func MessageEvent(e *lineobj.EventObject) { + fmt.Println(utils.ToMap(e)) + + switch e.Type { + case "message": + messageType(e) + break + } +} diff --git a/module/line-message/message-type.go b/module/line-message/message-type.go new file mode 100644 index 0000000..dd62aaf --- /dev/null +++ b/module/line-message/message-type.go @@ -0,0 +1,39 @@ +package linemsg + +import ( + lineobj "git.trj.tw/golang/mtfosbot/module/line-message/line-object" +) + +func messageType(e *lineobj.EventObject) { + msg := e.Message + mtype, ok := msg["type"] + if !ok { + return + } + + if t, ok := mtype.(string); ok { + switch t { + case "text": + break + case "image": + break + } + } + return +} + +func textMsg(e *lineobj.EventObject) { + msg := e.Message + mtxt, ok := msg["text"] + if !ok { + return + } + + // group action + if e.Source.Type == "group" { + if _, ok := mtxt.(string); ok { + + } + } + return +} diff --git a/module/twitch-irc/twitch-irc.go b/module/twitch-irc/twitch-irc.go index a35fb19..8db255e 100644 --- a/module/twitch-irc/twitch-irc.go +++ b/module/twitch-irc/twitch-irc.go @@ -36,6 +36,26 @@ func InitIRC() (err error) { return } +// SendMessage - +func SendMessage(ch, msg string) { + if len(ch) == 0 { + return + } + + if indexOf(channels, ch) == -1 { + return + } + + m := &MsgObj{ + Command: "PRIVMSG", + Params: []string{ + fmt.Sprintf("#%s", ch), + fmt.Sprintf(":%s", msg), + }, + } + queue.Add(m) +} + // JoinChannel - func JoinChannel(ch string) { if len(ch) == 0 { @@ -88,21 +108,29 @@ func runQueue() { msg := &irc.Message{} msg.Command = m.Command msg.Params = m.Params - err := client.WriteMessage(msg) - if err == nil { - if m.Command == "JOIN" { - - } else if m.Command == "PART" { + if m.Command == "JOIN" { + if indexOf(channels, m.Params[0][1:]) != -1 { + continue } + channels = append(channels, m.Params[0][1:]) + } else if m.Command == "PART" { + if indexOf(channels, m.Params[0][1:]) == -1 { + continue + } + idx := indexOf(channels, m.Params[0][1:]) + channels = append(channels[:idx], channels[idx+1:]...) } + fmt.Println("< ", msg.String()) + client.WriteMessage(msg) } + time.Sleep(time.Microsecond * 1500) } } func ircHandle(c *irc.Client, m *irc.Message) { - + fmt.Println("> ", m.String()) } func indexOf(c []string, data string) int { diff --git a/router/line/line.go b/router/line/line.go index 6c9027f..4fa872c 100644 --- a/router/line/line.go +++ b/router/line/line.go @@ -1,8 +1,93 @@ package line -import "context" +import ( + "crypto/hmac" + "crypto/sha256" + "encoding/base64" + "encoding/json" + "fmt" + "io/ioutil" + + "git.trj.tw/golang/mtfosbot/module/config" + "git.trj.tw/golang/mtfosbot/module/context" + "git.trj.tw/golang/mtfosbot/module/line-message" + lineobj "git.trj.tw/golang/mtfosbot/module/line-message/line-object" +) + +// GetRawBody - line webhook body get +func GetRawBody(c *context.Context) { + byteBody, err := ioutil.ReadAll(c.Request.Body) + if err != nil { + c.DataFormat("body read fail") + return + } + c.Set("rawbody", byteBody) + c.Next() +} + +// VerifyLine - middleware +func VerifyLine(c *context.Context) { + rawbody, ok := c.Get("rawbody") + if !ok { + c.DataFormat("body read fail") + return + } + var raw []byte + if raw, ok = rawbody.([]byte); !ok { + c.DataFormat("body type error") + return + } + sign := c.GetHeader("X-Line-Signature") + if len(sign) == 0 { + c.Next() + return + } + + conf := config.GetConf() + + hash := hmac.New(sha256.New, []byte(conf.Line.Secret)) + _, err := hash.Write(raw) + if err != nil { + c.ServerError(nil) + return + } + hashSign := base64.StdEncoding.EncodeToString(hash.Sum(nil)) + if hashSign != sign { + c.CustomRes(403, map[string]string{ + "message": "sign verify fail", + }) + return + } + c.Next() +} // GetLineMessage - func GetLineMessage(c *context.Context) { + rawbody, ok := c.Get("rawbody") + if !ok { + c.DataFormat("body read fail") + } + var raw []byte + if raw, ok = rawbody.([]byte); !ok { + c.DataFormat("body type error") + } + events := struct { + Events []*lineobj.EventObject `json:"events"` + }{} + + err := json.Unmarshal(raw, &events) + if err != nil { + fmt.Println("parse line message error ::: ", err) + c.ServerError(nil) + return + } + + if len(events.Events) > 0 { + for _, v := range events.Events { + go linemsg.MessageEvent(v) + } + } + + c.Success(nil) }