226 lines
5.6 KiB
Go
226 lines
5.6 KiB
Go
|
package mi
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"encoding/json"
|
||
|
"io"
|
||
|
"io/ioutil"
|
||
|
"net/http"
|
||
|
"strings"
|
||
|
"time"
|
||
|
|
||
|
"go-common/library/log"
|
||
|
"go-common/library/stat"
|
||
|
"go-common/library/stat/prom"
|
||
|
)
|
||
|
|
||
|
// Client Xiaomi http client.
|
||
|
type Client struct {
|
||
|
Header http.Header
|
||
|
HTTPClient *http.Client
|
||
|
Package string
|
||
|
URL string
|
||
|
Stats stat.Stat
|
||
|
}
|
||
|
|
||
|
// NewClient returns a Client with request header and auth.
|
||
|
func NewClient(pkg, auth string, timeout time.Duration) *Client {
|
||
|
header := http.Header{}
|
||
|
header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||
|
header.Set("Authorization", AuthPrefix+auth)
|
||
|
// transport := &http.Transport{
|
||
|
// Proxy: func(_ *http.Request) (*url.URL, error) {
|
||
|
// return url.Parse("http://10.28.10.11:80")
|
||
|
// },
|
||
|
// DialContext: (&net.Dialer{
|
||
|
// Timeout: 30 * time.Second,
|
||
|
// KeepAlive: 30 * time.Second,
|
||
|
// DualStack: true,
|
||
|
// }).DialContext,
|
||
|
// MaxIdleConns: 100,
|
||
|
// IdleConnTimeout: 90 * time.Second,
|
||
|
// ExpectContinueTimeout: 1 * time.Second,
|
||
|
// }
|
||
|
return &Client{
|
||
|
Header: header,
|
||
|
HTTPClient: &http.Client{Timeout: timeout},
|
||
|
// HTTPClient: &http.Client{Timeout: timeout, Transport: transport},
|
||
|
Package: pkg,
|
||
|
Stats: prom.HTTPClient,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// SetProductionURL sets Production URL.
|
||
|
func (c *Client) SetProductionURL(url string) {
|
||
|
c.URL = ProductionHost + url
|
||
|
}
|
||
|
|
||
|
// SetDevelopmentURL sets Production URL.
|
||
|
func (c *Client) SetDevelopmentURL(url string) {
|
||
|
c.URL = DevHost + url
|
||
|
}
|
||
|
|
||
|
// SetVipURL sets VIP URL.
|
||
|
func (c *Client) SetVipURL(url string) {
|
||
|
c.URL = VipHost + url
|
||
|
}
|
||
|
|
||
|
// SetStatusURL sets feedback URL.
|
||
|
func (c *Client) SetStatusURL() {
|
||
|
c.URL = ProductionHost + StatusURL
|
||
|
}
|
||
|
|
||
|
// Push sends a Notification to Xiaomi push service.
|
||
|
func (c *Client) Push(xm *XMMessage) (response *Response, err error) {
|
||
|
if c.Stats != nil {
|
||
|
now := time.Now()
|
||
|
defer func() {
|
||
|
c.Stats.Timing(c.URL, int64(time.Since(now)/time.Millisecond))
|
||
|
log.Info("mi stats timing: %v", int64(time.Since(now)/time.Millisecond))
|
||
|
if err != nil {
|
||
|
c.Stats.Incr(c.URL, "failed")
|
||
|
}
|
||
|
}()
|
||
|
}
|
||
|
var req *http.Request
|
||
|
if req, err = http.NewRequest(http.MethodPost, c.URL, bytes.NewBuffer([]byte(xm.xmuv.Encode()))); err != nil {
|
||
|
log.Error("http.NewRequest() error(%v)", err)
|
||
|
return
|
||
|
}
|
||
|
req.Header = c.Header
|
||
|
var res *http.Response
|
||
|
if res, err = c.HTTPClient.Do(req); err != nil {
|
||
|
log.Error("HTTPClient.Do() error(%v)", err)
|
||
|
return
|
||
|
}
|
||
|
defer res.Body.Close()
|
||
|
response = &Response{}
|
||
|
var bs []byte
|
||
|
bs, err = ioutil.ReadAll(res.Body)
|
||
|
if err != nil {
|
||
|
log.Error("ioutil.ReadAll() error(%v)", err)
|
||
|
return
|
||
|
} else if len(bs) == 0 {
|
||
|
return
|
||
|
}
|
||
|
if e := json.Unmarshal(bs, &response); e != nil {
|
||
|
if e != io.EOF {
|
||
|
log.Error("json decode body(%s) error(%v)", string(bs), e)
|
||
|
}
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// MockPush mock push.
|
||
|
func (c *Client) MockPush(xm *XMMessage) (response *Response, err error) {
|
||
|
if c.Stats != nil {
|
||
|
now := time.Now()
|
||
|
defer func() {
|
||
|
c.Stats.Timing(c.URL, int64(time.Since(now)/time.Millisecond))
|
||
|
if err != nil {
|
||
|
c.Stats.Incr(c.URL, "mi push mock")
|
||
|
}
|
||
|
}()
|
||
|
}
|
||
|
time.Sleep(200 * time.Millisecond)
|
||
|
response = &Response{Code: ResultCodeOk, Result: ResultOk}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// InvalidTokens get invalid tokens.
|
||
|
func (c *Client) InvalidTokens() (response *Response, err error) {
|
||
|
if c.Stats != nil {
|
||
|
now := time.Now()
|
||
|
defer func() {
|
||
|
c.Stats.Timing(c.URL, int64(time.Since(now)/time.Millisecond))
|
||
|
log.Info("mi invalidTokens timing: %v", int64(time.Since(now)/time.Millisecond))
|
||
|
if err != nil {
|
||
|
c.Stats.Incr(c.URL, "failed")
|
||
|
}
|
||
|
}()
|
||
|
}
|
||
|
req, err := http.NewRequest(http.MethodGet, feedbackHost+feedbackURI, nil)
|
||
|
if err != nil {
|
||
|
log.Error("http.NewRequest(%s) error(%v)", c.URL, err)
|
||
|
return
|
||
|
}
|
||
|
req.Header = c.Header
|
||
|
c.HTTPClient.Timeout = time.Minute
|
||
|
res, err := c.HTTPClient.Do(req)
|
||
|
if err != nil {
|
||
|
log.Error("HTTPClient.Do() error(%v)", err)
|
||
|
return
|
||
|
}
|
||
|
defer res.Body.Close()
|
||
|
response = &Response{}
|
||
|
bs, err := ioutil.ReadAll(res.Body)
|
||
|
if err != nil {
|
||
|
log.Error("ioutil.ReadAll() error(%v)", err)
|
||
|
return
|
||
|
} else if len(bs) == 0 {
|
||
|
return
|
||
|
}
|
||
|
if e := json.Unmarshal(bs, &response); e != nil {
|
||
|
if e != io.EOF {
|
||
|
log.Error("json decode body(%s) error(%v)", string(bs), e)
|
||
|
}
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// UninstalledTokens get uninstalled tokens.
|
||
|
func (c *Client) UninstalledTokens() (response *UninstalledResponse, err error) {
|
||
|
if c.Stats != nil {
|
||
|
now := time.Now()
|
||
|
defer func() {
|
||
|
c.Stats.Timing(c.URL, int64(time.Since(now)/time.Millisecond))
|
||
|
log.Info("mi UninstalledTokens timing: %v", int64(time.Since(now)/time.Millisecond))
|
||
|
if err != nil {
|
||
|
c.Stats.Incr(c.URL, "mi uninstalled tokens")
|
||
|
}
|
||
|
}()
|
||
|
}
|
||
|
req, err := http.NewRequest(http.MethodGet, emqHost+uninstalledURI+"?package_name="+c.Package, nil)
|
||
|
if err != nil {
|
||
|
log.Error("http.NewRequest(%s) error(%v)", c.URL, err)
|
||
|
return
|
||
|
}
|
||
|
req.Header = c.Header
|
||
|
c.HTTPClient.Timeout = time.Minute
|
||
|
res, err := c.HTTPClient.Do(req)
|
||
|
if err != nil {
|
||
|
log.Error("HTTPClient.Do() error(%v)", err)
|
||
|
return
|
||
|
}
|
||
|
defer res.Body.Close()
|
||
|
response = &UninstalledResponse{}
|
||
|
bs, err := ioutil.ReadAll(res.Body)
|
||
|
if err != nil {
|
||
|
log.Error("ioutil.ReadAll() error(%v)", err)
|
||
|
return
|
||
|
} else if len(bs) == 0 {
|
||
|
return
|
||
|
}
|
||
|
if e := json.Unmarshal(bs, &response); e != nil {
|
||
|
if e != io.EOF {
|
||
|
log.Error("json decode body(%s) error(%v)", string(bs), e)
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
for _, s := range response.Result {
|
||
|
s = strings.Replace(s, `\`, "", -1)
|
||
|
s = strings.TrimPrefix(s, `"`)
|
||
|
s = strings.TrimSuffix(s, `"`)
|
||
|
ud := UninstalledData{}
|
||
|
if e := json.Unmarshal([]byte(s), &ud); e != nil {
|
||
|
log.Error("json unmarshal(%s) error(%v)", s, e)
|
||
|
continue
|
||
|
}
|
||
|
if ud.Token == "" {
|
||
|
continue
|
||
|
}
|
||
|
response.Data = append(response.Data, ud.Token)
|
||
|
}
|
||
|
return
|
||
|
}
|