bilibili-backup/app/service/main/push/dao/mi/client.go
2019-04-22 02:59:20 +00:00

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
}