oceanEngine.go 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. package service
  2. import (
  3. "bytes"
  4. "context"
  5. "designs/global"
  6. "encoding/json"
  7. "fmt"
  8. "go.mongodb.org/mongo-driver/v2/bson"
  9. "io"
  10. "net/http"
  11. "net/url"
  12. "time"
  13. )
  14. type EReportType string
  15. type EReportResCode = int
  16. const (
  17. ERTypeGameAddiction EReportType = "game_addiction" //关键行为
  18. ReportOk EReportResCode = 0 //上报成功
  19. ReportIOErr EReportResCode = -50
  20. Reported EReportResCode = -100 //已经上报过
  21. ReportNoNeed EReportResCode = -200 //不需要上报,一般为非广告来源用户
  22. ReportParseErr EReportResCode = -300
  23. ReportRequestErr EReportResCode = -300
  24. )
  25. // 需要核对bson的值是否与数据库中的字段一致
  26. type AdDataDetail struct {
  27. Pid string `json:"pid"`
  28. Aid string `json:"aid"`
  29. Cid string `json:"cid"`
  30. ReportUrl string `json:"reportUrl"`
  31. Reported bool `json:"reported"`
  32. Duration int64 `json:"duration"`
  33. AdReqCount uint8 `json:"adReqCount"`
  34. AdEposedcount uint8 `json:"adEposedcount"`
  35. CreateTime int `json:"createTime"`
  36. }
  37. type UserBehavior struct {
  38. Id string `bson:"_id,omitempty"`
  39. Gid string `bson:"gid"`
  40. Pf string `bson:"pf"`
  41. OpenId string `bson:"openId"`
  42. AdData *AdDataDetail `bson:"adData"`
  43. AdFromCount int `bson:"adFromCount"`
  44. TotalDuration int `bson:"totalDuration"`
  45. TotalAdReqCount int `bson:"totalAdReqCount"`
  46. TotalAdEposedCount int `bson:"totalAdEposedCount"`
  47. }
  48. // ReportResult 执行巨量引擎上报函数的返回结果的数据结构
  49. type ReportResult struct {
  50. Code int
  51. Message string
  52. }
  53. // ReportResponse 执行巨量引擎上报时请求结果的数据结构
  54. type ReportResponse struct {
  55. Code int `json:"code"`
  56. Message string `json:"message"`
  57. }
  58. // ReportData 巨量引擎上报时提交的数据结构
  59. type ReportData struct {
  60. EventType string `json:"event_type"`
  61. Context struct {
  62. Ad struct {
  63. Callback string `json:"callback"`
  64. } `json:"ad"`
  65. } `json:"context"`
  66. Timestamp int64 `json:"timestamp"`
  67. }
  68. func createReportData(evtType EReportType, clickId string) *ReportData {
  69. dat := &ReportData{}
  70. dat.EventType = string(evtType)
  71. dat.Context.Ad.Callback = clickId
  72. dat.Timestamp = time.Now().UnixMilli()
  73. return dat
  74. }
  75. func OceanReportAction(behavior string) *ReportResult {
  76. collection := global.App.MongoDB.Database("chunhao").Collection("userBehavior")
  77. //
  78. filter := bson.M{"_id": behavior}
  79. result := make(map[string]interface{})
  80. collection.FindOne(context.Background(), filter).Decode(&result)
  81. //转换成合适的格式
  82. var user UserBehavior
  83. resultString, _ := json.Marshal(result)
  84. json.Unmarshal(resultString, &user)
  85. if user.AdData.AdReqCount < 1 {
  86. //没有看过广告,无需上传
  87. return &ReportResult{Code: ReportNoNeed, Message: "没有看过广告,无需上报"}
  88. }
  89. if user.AdData == nil {
  90. //非广告来源的用户,无需上传
  91. return &ReportResult{Code: ReportNoNeed, Message: "非广告用户,无需上报"}
  92. }
  93. if user.AdData.Reported {
  94. //已经上传过了
  95. return &ReportResult{Code: Reported, Message: "已经上报过"}
  96. }
  97. //后续通过广告的不同优化目标判断不同上报行为的逻辑判断模块,暂时仅上传关键行为数据
  98. //if !specialReportType("Action", user.AdData.Pid, user.AdData.Aid) {
  99. // return false, nil
  100. //}
  101. //事件上报详见:
  102. //https://event-manager.oceanengine.com/docs/8650/app_api_docs#%E8%AF%B7%E6%B1%82%E6%96%B9%E6%B3%95
  103. //https://event-manager.oceanengine.com/docs/8650/api_docs
  104. //事件取值详见https://event-manager.oceanengine.com/docs/8650/all_events
  105. reportDat := createReportData(ERTypeGameAddiction, user.AdData.Cid)
  106. //payload, err := json.Marshal(reportDat)
  107. //if err != nil {
  108. // return &ReportResult{Code: ReportParseErr, Message: err.Error()}
  109. //}
  110. content, err := CurlPost("https://analytics.oceanengine.com/api/v2/conversion", reportDat, nil)
  111. if err != nil {
  112. return &ReportResult{Code: ReportRequestErr, Message: err.Error()}
  113. }
  114. resp := &ReportResponse{}
  115. if str2oErr := json.Unmarshal([]byte(content), resp); str2oErr != nil {
  116. return &ReportResult{Code: ReportParseErr, Message: str2oErr.Error()}
  117. }
  118. if resp.Code != 0 {
  119. return &ReportResult{Code: resp.Code, Message: resp.Message}
  120. }
  121. //数据上传后更新用户数据
  122. //更新到MongoDB 中
  123. user.AdData.Reported = true
  124. update := bson.M{
  125. "$set": struct {
  126. Gid string `bson:"gid"`
  127. Pf string `bson:"pf"`
  128. OpenId string `bson:"openId"`
  129. AdData interface{} `bson:"adData"`
  130. AdFromCount int `bson:"adFromCount"`
  131. TotalDuration int `bson:"totalDuration"`
  132. TotalAdReqCount int `bson:"totalAdReqCount"`
  133. TotalAdEposedCount int `bson:"totalAdEposedCount"`
  134. }{
  135. Gid: user.Gid,
  136. Pf: user.Pf,
  137. OpenId: user.OpenId,
  138. AdData: user.AdData,
  139. AdFromCount: user.AdFromCount,
  140. TotalDuration: user.TotalDuration,
  141. TotalAdReqCount: user.TotalAdReqCount,
  142. TotalAdEposedCount: user.TotalAdEposedCount,
  143. },
  144. }
  145. _, err = collection.UpdateOne(context.Background(), filter, update)
  146. if err != nil {
  147. return &ReportResult{Code: resp.Code, Message: err.Error()}
  148. }
  149. return &ReportResult{Code: ReportOk, Message: resp.Message}
  150. }
  151. func CurlPost(requestUrl string, requestBody interface{}, headerMap map[string]string) (string, error) {
  152. //转换json
  153. jsonBytes, err := json.Marshal(requestBody)
  154. if err != nil {
  155. return "", err
  156. }
  157. //创建请求
  158. req, err := http.NewRequest("POST", requestUrl, bytes.NewReader(jsonBytes))
  159. if err != nil {
  160. return "", err
  161. }
  162. //设置请求头
  163. req.Header.Set("Content-Type", "application/json;charset=UTF-8")
  164. for k, v := range headerMap {
  165. //req.Header.Set("Accept-Encoding", "gzip, deflate, br")
  166. req.Header.Set(k, v)
  167. }
  168. //发送请求
  169. clt := http.Client{Timeout: 30 * time.Second}
  170. res, err := clt.Do(req)
  171. if err != nil {
  172. return "", err
  173. }
  174. //获取结果
  175. body, err := io.ReadAll(res.Body)
  176. data := string(body)
  177. return data, err
  178. }
  179. // specialReportType 是否时指定上传的类型
  180. func specialReportType(reportType EReportType, pid string, aid string) bool {
  181. //通过pid和aid查找广告,判断其是否
  182. return true
  183. }
  184. func CurlGet(url string, values url.Values, header http.Header) (string, error) {
  185. req, reqErr := http.NewRequest(http.MethodGet, url, nil)
  186. if reqErr != nil {
  187. return "", reqErr
  188. }
  189. if header != nil {
  190. req.Header = header
  191. }
  192. if values != nil {
  193. req.URL.RawQuery = values.Encode()
  194. }
  195. fmt.Println(req.URL.Host, req.URL.RawQuery)
  196. resp, resErr := http.DefaultClient.Do(req)
  197. if resErr != nil {
  198. return "", resErr
  199. }
  200. defer func() { _ = resp.Body.Close() }()
  201. content, readErr := io.ReadAll(resp.Body)
  202. if readErr != nil {
  203. return "", readErr
  204. }
  205. //if decodeErr := json.Unmarshal(content, result); decodeErr != nil {
  206. // return "", decodeErr
  207. //}
  208. return string(content), nil
  209. }
  210. type HttpResult struct {
  211. Code int `bson:"code"`
  212. Msg string `bson:"msg"`
  213. }