158 lines
3.2 KiB
Go
158 lines
3.2 KiB
Go
|
package google
|
||
|
|
||
|
import (
|
||
|
"encoding/json"
|
||
|
"errors"
|
||
|
"fmt"
|
||
|
"io/ioutil"
|
||
|
"net/http"
|
||
|
"net/url"
|
||
|
"strings"
|
||
|
|
||
|
"git.trj.tw/golang/mtfosbot/module/apis"
|
||
|
|
||
|
"git.trj.tw/golang/mtfosbot/module/config"
|
||
|
)
|
||
|
|
||
|
var baseURL = "https://www.googleapis.com"
|
||
|
|
||
|
func getURL(p string, querystring ...interface{}) (string, bool) {
|
||
|
u, err := url.Parse(baseURL)
|
||
|
if err != nil {
|
||
|
return "", false
|
||
|
}
|
||
|
ref, err := u.Parse(p)
|
||
|
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 ...interface{}) map[string]string {
|
||
|
m := make(map[string]string)
|
||
|
m["Content-Type"] = "application/json"
|
||
|
return m
|
||
|
}
|
||
|
|
||
|
type channelItem struct {
|
||
|
ID string `json:"id"`
|
||
|
Sinppet channelSinppet `json:"sinppet"`
|
||
|
}
|
||
|
type channelSinppet struct {
|
||
|
Title string `json:"title"`
|
||
|
Description string `json:"description"`
|
||
|
CustomURL string `json:"customUrl"`
|
||
|
}
|
||
|
|
||
|
// QueryYoutubeName -
|
||
|
func QueryYoutubeName(id string) (n string, err error) {
|
||
|
conf := config.GetConf()
|
||
|
if len(id) == 0 {
|
||
|
return "", errors.New("id is empty")
|
||
|
}
|
||
|
qs := url.Values{}
|
||
|
qs.Add("id", id)
|
||
|
qs.Add("key", conf.Google.APIKey)
|
||
|
qs.Add("part", "snippet")
|
||
|
|
||
|
apiURL, ok := getURL("/youtube/v3/channels", qs.Encode())
|
||
|
if !ok {
|
||
|
return "", errors.New("url parser fail")
|
||
|
}
|
||
|
reqObj := apis.RequestObj{
|
||
|
Method: "GET",
|
||
|
URL: apiURL,
|
||
|
Headers: getHeaders(),
|
||
|
}
|
||
|
|
||
|
req, err := apis.GetRequest(reqObj)
|
||
|
if err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
|
||
|
resp, err := http.DefaultClient.Do(req)
|
||
|
if err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
defer resp.Body.Close()
|
||
|
|
||
|
if resp.StatusCode != 200 || !strings.HasPrefix(resp.Header.Get("Content-Type"), "application/json") {
|
||
|
return "", errors.New("api response fail")
|
||
|
}
|
||
|
|
||
|
bodyBytes, err := ioutil.ReadAll(resp.Body)
|
||
|
if err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
|
||
|
apiRes := struct {
|
||
|
Items []channelItem `json:"items"`
|
||
|
}{}
|
||
|
|
||
|
err = json.Unmarshal(bodyBytes, &apiRes)
|
||
|
if err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
|
||
|
if len(apiRes.Items) == 0 {
|
||
|
return "", errors.New("channel data not found")
|
||
|
}
|
||
|
|
||
|
for _, v := range apiRes.Items {
|
||
|
if v.ID == id {
|
||
|
return v.Sinppet.Title, nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return "", errors.New("channel data not found")
|
||
|
}
|
||
|
|
||
|
// SubscribeYoutube -
|
||
|
func SubscribeYoutube(id string) {
|
||
|
if len(id) == 0 {
|
||
|
return
|
||
|
}
|
||
|
conf := config.GetConf()
|
||
|
apiURL := "https://pubsubhubbub.appspot.com/subscribe"
|
||
|
cbURL, err := url.Parse(conf.URL)
|
||
|
if err != nil {
|
||
|
return
|
||
|
}
|
||
|
cbURL, err = cbURL.Parse(fmt.Sprintf("/google/youtube/webhook?id=%s", id))
|
||
|
if err != nil {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
qs := url.Values{}
|
||
|
qs.Add("hub.mode", "subscribe")
|
||
|
qs.Add("hub.verify", "async")
|
||
|
qs.Add("hub.topic", fmt.Sprintf("https://www.youtube.com/xml/feeds/videos.xml?channel_id=%s", id))
|
||
|
qs.Add("hub.callback", cbURL.String())
|
||
|
qs.Add("hub.lease_seconds", "86400")
|
||
|
|
||
|
req, err := http.NewRequest("POST", apiURL, strings.NewReader(qs.Encode()))
|
||
|
if err != nil {
|
||
|
return
|
||
|
}
|
||
|
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
||
|
resp, err := http.DefaultClient.Do(req)
|
||
|
if err != nil {
|
||
|
return
|
||
|
}
|
||
|
defer resp.Body.Close()
|
||
|
return
|
||
|
}
|