From f70d11517cd71fbe3d42fe4e1b68a770741f323b Mon Sep 17 00:00:00 2001 From: Jay Date: Wed, 12 Sep 2018 00:29:38 +0800 Subject: [PATCH] add twitch api --- model/twitch_channel.go | 6 + module/apis/apis.go | 6 +- module/apis/line/line.go | 4 +- module/apis/twitch/twitch.go | 209 +++++++++++++++++++++++++++++++- module/background/background.go | 1 + module/background/twitch.go | 32 +++++ 6 files changed, 250 insertions(+), 8 deletions(-) create mode 100644 module/background/twitch.go diff --git a/model/twitch_channel.go b/model/twitch_channel.go index 050bf2b..0771def 100644 --- a/model/twitch_channel.go +++ b/model/twitch_channel.go @@ -12,3 +12,9 @@ type TwitchChannel struct { Ctime time.Time `db:"ctime" cc:"ctime"` Mtime time.Time `db:"mtime" cc:"ctime"` } + +// GetAllChannel - +func GetAllChannel() (channels []*TwitchChannel, err error) { + err = x.Select(&channels, `select * from "public"."twitch_channel"`) + return +} diff --git a/module/apis/apis.go b/module/apis/apis.go index 5d66536..13c36bc 100644 --- a/module/apis/apis.go +++ b/module/apis/apis.go @@ -5,16 +5,18 @@ import ( "net/http" ) +// RequestObj - type RequestObj struct { Method string - Url string + URL string Body io.Reader Headers map[string]string } +// GetRequest - func GetRequest(r RequestObj) (req *http.Request, err error) { - req, err = http.NewRequest(r.Method, r.Url, r.Body) + req, err = http.NewRequest(r.Method, r.URL, r.Body) if err != nil { return } diff --git a/module/apis/line/line.go b/module/apis/line/line.go index 94bc942..1f684d9 100644 --- a/module/apis/line/line.go +++ b/module/apis/line/line.go @@ -98,7 +98,7 @@ func PushMessage(target string, message interface{}) { reqObj := apis.RequestObj{ Method: "POST", - Url: apiURL, + URL: apiURL, Headers: getHeaders(), Body: byteReader, } @@ -158,7 +158,7 @@ func ReplyMessage(replyToken string, message interface{}) { reqObj := apis.RequestObj{ Method: "POST", - Url: apiURL, + URL: apiURL, Headers: getHeaders(), Body: byteReader, } diff --git a/module/apis/twitch/twitch.go b/module/apis/twitch/twitch.go index f46ca95..f66c815 100644 --- a/module/apis/twitch/twitch.go +++ b/module/apis/twitch/twitch.go @@ -1,13 +1,34 @@ package twitch import ( + "encoding/json" "fmt" + "io/ioutil" + "net/http" "net/url" + "strings" + + "git.trj.tw/golang/mtfosbot/module/apis" + "git.trj.tw/golang/mtfosbot/module/config" ) +// UserInfo - twitch user info data +type UserInfo struct { + ID string `json:"id"` + Login string `json:"login"` + DisplayName string `json:"display_name"` + Type string `json:"type"` + BroadcasterType string `json:"broadcaster_type"` + Description string `json:"description"` + ProfileImageURL string `json:"profile_image_url"` + OfflineImageURL string `json:"offline_image_url"` + ViewCount int `json:"view_count"` + Email string `json:"email"` +} + var baseURL = "https://api.twitch.tv" -func getURL(p string) (string, bool) { +func getURL(p string, querystring ...interface{}) (string, bool) { u, err := url.Parse(baseURL) if err != nil { return "", false @@ -16,20 +37,200 @@ func getURL(p string) (string, bool) { if err != nil { return "", false } + + if len(querystring) > 0 { + switch querystring[0].(type) { + case string: + ref, err = ref.Parse(fmt.Sprintf("?%s", (querystring[0].(string)))) + if err != nil { + return "", false + } + break + default: + } + } + str := ref.String() return str, true } -func getHeaders(token string) map[string]string { +func getHeaders(token ...interface{}) map[string]string { m := make(map[string]string) + conf := config.GetConf() m["Content-Type"] = "application/json" - m["Authorization"] = fmt.Sprintf("Bearer %s", token) + if len(token) > 0 { + switch token[0].(type) { + case string: + m["Authorization"] = fmt.Sprintf("Bearer %s", (token[0].(string))) + break + default: + } + } + m["Client-ID"] = conf.Twitch.ClientID return m } -func GetUserData(token string) { +// GetUserDataByToken - get token own user data +func GetUserDataByToken(token string) (userInfo *UserInfo) { + if len(token) == 0 { + return + } url, ok := getURL("/helix/users") if !ok { return } + + reqObj := apis.RequestObj{} + reqObj.Headers = getHeaders(token) + reqObj.Method = "GET" + reqObj.URL = url + req, err := apis.GetRequest(reqObj) + if err != nil { + return + } + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return + } + defer resp.Body.Close() + + if !strings.HasPrefix(resp.Header.Get("Content-Type"), "application/json") { + return + } + + apiData := struct { + Data []*UserInfo `json:"data"` + }{} + bodyBytes, err := ioutil.ReadAll(resp.Body) + if err != nil { + return + } + + err = json.Unmarshal(bodyBytes, &apiData) + if err != nil { + return + } + + if len(apiData.Data) == 0 { + return + } + + return apiData.Data[0] +} + +// GetUserDataByName - +func GetUserDataByName(login string) (userInfo *UserInfo) { + if len(login) == 0 { + return + } + qsValue := url.Values{} + qsValue.Add("login", login) + url, ok := getURL("/helix/users", qsValue.Encode()) + if !ok { + return + } + + reqObj := apis.RequestObj{} + reqObj.Headers = getHeaders() + reqObj.Method = "GET" + reqObj.URL = url + req, err := apis.GetRequest(reqObj) + if err != nil { + return + } + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return + } + defer resp.Body.Close() + + if !strings.HasPrefix(resp.Header.Get("Content-Type"), "application/json") { + return + } + + apiData := struct { + Data []*UserInfo `json:"data"` + }{} + + bodyBytes, err := ioutil.ReadAll(resp.Body) + if err != nil { + return + } + + err = json.Unmarshal(bodyBytes, &apiData) + if err != nil { + return + } + + if len(apiData.Data) == 0 { + return + } + + return apiData.Data[0] +} + +// StreamInfo - +type StreamInfo struct { + ID string `json:"id"` + UserID string `json:"user_id"` + GameID string `json:"game_id"` + Type string `json:"type"` + Title string `json:"title"` + ViewerCount int `json:"viewer_count"` + StartedAt string `json:"started_at"` + Language string `json:"language"` + ThumbnailURL string `json:"thumbnail_url"` +} + +// GetUserStreamStatus - +func GetUserStreamStatus(ids []string) (info []*StreamInfo) { + if len(ids) == 0 { + return + } + + apiData := struct { + Data []*StreamInfo `json:"data"` + }{} + + qsValue := url.Values{} + for _, v := range ids { + qsValue.Add("user_id", v) + } + url, ok := getURL("/helix/streams", qsValue.Encode()) + if !ok { + return + } + + reqObj := apis.RequestObj{} + reqObj.Headers = getHeaders() + reqObj.Method = "GET" + reqObj.URL = url + req, err := apis.GetRequest(reqObj) + if err != nil { + return + } + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return + } + defer resp.Body.Close() + + if !strings.HasPrefix(resp.Header.Get("Content-Type"), "application/json") { + return + } + + bodyBytes, err := ioutil.ReadAll(resp.Body) + if err != nil { + return + } + + err = json.Unmarshal(bodyBytes, &apiData) + if err != nil { + return nil + } + + return apiData.Data } diff --git a/module/background/background.go b/module/background/background.go index 9afdc6c..542601f 100644 --- a/module/background/background.go +++ b/module/background/background.go @@ -10,5 +10,6 @@ var c *cron.Cron func SetBackground() { c = cron.New() c.AddFunc("0 * * * * *", readFacebookPage) + c.AddFunc("*/20 * * * * *", getStreamStatus) c.Start() } diff --git a/module/background/twitch.go b/module/background/twitch.go new file mode 100644 index 0000000..7a65838 --- /dev/null +++ b/module/background/twitch.go @@ -0,0 +1,32 @@ +package background + +import ( + "fmt" + + "git.trj.tw/golang/mtfosbot/module/utils" + + "git.trj.tw/golang/mtfosbot/model" + "git.trj.tw/golang/mtfosbot/module/apis/twitch" +) + +func getStreamStatus() { + fmt.Println("run twitch check") + channels, err := model.GetAllChannel() + if err != nil { + return + } + var ids []string + for _, v := range channels { + ids = append(ids, v.ID) + } + + info := twitch.GetUserStreamStatus(ids) + fmt.Printf("info len: %d\n", len(info)) + for _, v := range info { + fmt.Println(utils.ToMap(v)) + } +} + +func checkStream(ch *model.TwitchChannel) { + +}