push.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. package esports
  2. import (
  3. "bytes"
  4. "context"
  5. "crypto/md5"
  6. "encoding/hex"
  7. "fmt"
  8. "io"
  9. "mime/multipart"
  10. "net/http"
  11. "net/url"
  12. "sort"
  13. "strconv"
  14. "time"
  15. mdlesp "go-common/app/job/main/web-goblin/model/esports"
  16. "go-common/library/log"
  17. "go-common/library/xstr"
  18. )
  19. const (
  20. _pinkVersion = 1
  21. _linkLive = 3
  22. )
  23. type _response struct {
  24. Code int `json:"code"`
  25. Data int `json:"data"`
  26. }
  27. // NoticeUser pushs the notification to users.
  28. func (d *Dao) NoticeUser(mids []int64, body string, contest *mdlesp.Contest) (err error) {
  29. var strMids string
  30. if d.c.Push.OnlyMids == "" {
  31. strMids = xstr.JoinInts(mids)
  32. } else {
  33. strMids = d.c.Push.OnlyMids
  34. }
  35. uuid := d.getUUID(strMids, contest)
  36. buf := new(bytes.Buffer)
  37. w := multipart.NewWriter(buf)
  38. w.WriteField("app_id", strconv.Itoa(_pinkVersion))
  39. w.WriteField("business_id", strconv.Itoa(d.c.Push.BusinessID))
  40. w.WriteField("alert_title", d.c.Push.Title)
  41. w.WriteField("alert_body", body)
  42. w.WriteField("mids", strMids)
  43. w.WriteField("link_type", strconv.Itoa(_linkLive))
  44. w.WriteField("link_value", strconv.FormatInt(contest.LiveRoom, 10))
  45. w.WriteField("uuid", uuid)
  46. w.Close()
  47. //签名
  48. query := map[string]string{
  49. "ts": strconv.FormatInt(time.Now().Unix(), 10),
  50. "appkey": d.c.App.Key,
  51. }
  52. query["sign"] = d.signature(query, d.c.App.Secret)
  53. url := fmt.Sprintf("%s?ts=%s&appkey=%s&sign=%s", d.pushURL, query["ts"], query["appkey"], query["sign"])
  54. req, err := http.NewRequest(http.MethodPost, url, buf)
  55. if err != nil {
  56. log.Error("http.NewRequest(%s) error(%v)", url, err)
  57. return
  58. }
  59. req.Header.Set("Content-Type", w.FormDataContentType())
  60. req.Header.Set("Authorization", fmt.Sprintf("token=%s", d.c.Push.BusinessToken))
  61. res := &_response{}
  62. if err = d.http.Do(context.TODO(), req, &res); err != nil {
  63. log.Error("httpClient.Do() error(%v)", err)
  64. return
  65. }
  66. if res.Code != 0 || res.Data == 0 {
  67. log.Error("push failed mids_total(%d) body(%s) response(%+v)", len(mids), body, res)
  68. } else {
  69. log.Info("push success mids_total(%d) body(%s) response(%+v)", len(mids), body, res)
  70. }
  71. return
  72. }
  73. //signature 加密算法
  74. func (d *Dao) signature(params map[string]string, secret string) string {
  75. keys := []string{}
  76. for k := range params {
  77. keys = append(keys, k)
  78. }
  79. sort.Strings(keys)
  80. buf := bytes.Buffer{}
  81. for _, k := range keys {
  82. if buf.Len() > 0 {
  83. buf.WriteByte('&')
  84. }
  85. buf.WriteString(url.QueryEscape(k) + "=")
  86. buf.WriteString(url.QueryEscape(params[k]))
  87. }
  88. //加密
  89. h := md5.New()
  90. io.WriteString(h, buf.String()+secret)
  91. return fmt.Sprintf("%x", h.Sum(nil))
  92. }
  93. func (d *Dao) getUUID(mids string, contest *mdlesp.Contest) string {
  94. var b bytes.Buffer
  95. b.WriteString(strconv.Itoa(d.c.Push.BusinessID))
  96. b.WriteString(strconv.FormatInt(contest.ID, 10))
  97. b.WriteString(strconv.FormatInt(contest.Stime, 10))
  98. b.WriteString(strconv.FormatInt(time.Now().UnixNano(), 10))
  99. b.WriteString(mids)
  100. mh := md5.Sum(b.Bytes())
  101. uuid := hex.EncodeToString(mh[:])
  102. return uuid
  103. }