You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
225 lines
5.6 KiB
225 lines
5.6 KiB
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 |
|
}
|
|
|