123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237 |
- package service
- import (
- "bytes"
- "context"
- "designs/global"
- "encoding/json"
- "fmt"
- "go.mongodb.org/mongo-driver/v2/bson"
- "io"
- "net/http"
- "net/url"
- "time"
- )
- type EReportType string
- type EReportResCode = int
- const (
- ERTypeGameAddiction EReportType = "game_addiction" //关键行为
- ReportOk EReportResCode = 0 //上报成功
- ReportIOErr EReportResCode = -50
- Reported EReportResCode = -100 //已经上报过
- ReportNoNeed EReportResCode = -200 //不需要上报,一般为非广告来源用户
- ReportParseErr EReportResCode = -300
- ReportRequestErr EReportResCode = -300
- )
- // 需要核对bson的值是否与数据库中的字段一致
- type AdDataDetail struct {
- Pid string `json:"pid"`
- Aid string `json:"aid"`
- Cid string `json:"cid"`
- ReportUrl string `json:"reportUrl"`
- Reported bool `json:"reported"`
- Duration int64 `json:"duration"`
- AdReqCount uint8 `json:"adReqCount"`
- AdEposedcount uint8 `json:"adEposedcount"`
- CreateTime int `json:"createTime"`
- }
- type UserBehavior struct {
- Id string `bson:"_id,omitempty"`
- Gid string `bson:"gid"`
- Pf string `bson:"pf"`
- OpenId string `bson:"openId"`
- AdData *AdDataDetail `bson:"adData"`
- AdFromCount int `bson:"adFromCount"`
- TotalDuration int `bson:"totalDuration"`
- TotalAdReqCount int `bson:"totalAdReqCount"`
- TotalAdEposedCount int `bson:"totalAdEposedCount"`
- }
- // ReportResult 执行巨量引擎上报函数的返回结果的数据结构
- type ReportResult struct {
- Code int
- Message string
- }
- // ReportResponse 执行巨量引擎上报时请求结果的数据结构
- type ReportResponse struct {
- Code int `json:"code"`
- Message string `json:"message"`
- }
- // ReportData 巨量引擎上报时提交的数据结构
- type ReportData struct {
- EventType string `json:"event_type"`
- Context struct {
- Ad struct {
- Callback string `json:"callback"`
- } `json:"ad"`
- } `json:"context"`
- Timestamp int64 `json:"timestamp"`
- }
- func createReportData(evtType EReportType, clickId string) *ReportData {
- dat := &ReportData{}
- dat.EventType = string(evtType)
- dat.Context.Ad.Callback = clickId
- dat.Timestamp = time.Now().UnixMilli()
- return dat
- }
- func OceanReportAction(behavior string) *ReportResult {
- collection := global.App.MongoDB.Database("chunhao").Collection("userBehavior")
- //
- filter := bson.M{"_id": behavior}
- result := make(map[string]interface{})
- collection.FindOne(context.Background(), filter).Decode(&result)
- //转换成合适的格式
- var user UserBehavior
- resultString, _ := json.Marshal(result)
- json.Unmarshal(resultString, &user)
- if user.AdData.AdReqCount < 1 {
- //没有看过广告,无需上传
- return &ReportResult{Code: ReportNoNeed, Message: "没有看过广告,无需上报"}
- }
- if user.AdData == nil {
- //非广告来源的用户,无需上传
- return &ReportResult{Code: ReportNoNeed, Message: "非广告用户,无需上报"}
- }
- if user.AdData.Reported {
- //已经上传过了
- return &ReportResult{Code: Reported, Message: "已经上报过"}
- }
- //后续通过广告的不同优化目标判断不同上报行为的逻辑判断模块,暂时仅上传关键行为数据
- //if !specialReportType("Action", user.AdData.Pid, user.AdData.Aid) {
- // return false, nil
- //}
- //事件上报详见:
- //https://event-manager.oceanengine.com/docs/8650/app_api_docs#%E8%AF%B7%E6%B1%82%E6%96%B9%E6%B3%95
- //https://event-manager.oceanengine.com/docs/8650/api_docs
- //事件取值详见https://event-manager.oceanengine.com/docs/8650/all_events
- reportDat := createReportData(ERTypeGameAddiction, user.AdData.Cid)
- //payload, err := json.Marshal(reportDat)
- //if err != nil {
- // return &ReportResult{Code: ReportParseErr, Message: err.Error()}
- //}
- content, err := CurlPost("https://analytics.oceanengine.com/api/v2/conversion", reportDat, nil)
- if err != nil {
- return &ReportResult{Code: ReportRequestErr, Message: err.Error()}
- }
- resp := &ReportResponse{}
- if str2oErr := json.Unmarshal([]byte(content), resp); str2oErr != nil {
- return &ReportResult{Code: ReportParseErr, Message: str2oErr.Error()}
- }
- if resp.Code != 0 {
- return &ReportResult{Code: resp.Code, Message: resp.Message}
- }
- //数据上传后更新用户数据
- //更新到MongoDB 中
- user.AdData.Reported = true
- update := bson.M{
- "$set": struct {
- Gid string `bson:"gid"`
- Pf string `bson:"pf"`
- OpenId string `bson:"openId"`
- AdData interface{} `bson:"adData"`
- AdFromCount int `bson:"adFromCount"`
- TotalDuration int `bson:"totalDuration"`
- TotalAdReqCount int `bson:"totalAdReqCount"`
- TotalAdEposedCount int `bson:"totalAdEposedCount"`
- }{
- Gid: user.Gid,
- Pf: user.Pf,
- OpenId: user.OpenId,
- AdData: user.AdData,
- AdFromCount: user.AdFromCount,
- TotalDuration: user.TotalDuration,
- TotalAdReqCount: user.TotalAdReqCount,
- TotalAdEposedCount: user.TotalAdEposedCount,
- },
- }
- _, err = collection.UpdateOne(context.Background(), filter, update)
- if err != nil {
- return &ReportResult{Code: resp.Code, Message: err.Error()}
- }
- return &ReportResult{Code: ReportOk, Message: resp.Message}
- }
- func CurlPost(requestUrl string, requestBody interface{}, headerMap map[string]string) (string, error) {
- //转换json
- jsonBytes, err := json.Marshal(requestBody)
- if err != nil {
- return "", err
- }
- //创建请求
- req, err := http.NewRequest("POST", requestUrl, bytes.NewReader(jsonBytes))
- if err != nil {
- return "", err
- }
- //设置请求头
- req.Header.Set("Content-Type", "application/json;charset=UTF-8")
- for k, v := range headerMap {
- //req.Header.Set("Accept-Encoding", "gzip, deflate, br")
- req.Header.Set(k, v)
- }
- //发送请求
- clt := http.Client{Timeout: 30 * time.Second}
- res, err := clt.Do(req)
- if err != nil {
- return "", err
- }
- //获取结果
- body, err := io.ReadAll(res.Body)
- data := string(body)
- return data, err
- }
- // specialReportType 是否时指定上传的类型
- func specialReportType(reportType EReportType, pid string, aid string) bool {
- //通过pid和aid查找广告,判断其是否
- return true
- }
- func CurlGet(url string, values url.Values, header http.Header) (string, error) {
- req, reqErr := http.NewRequest(http.MethodGet, url, nil)
- if reqErr != nil {
- return "", reqErr
- }
- if header != nil {
- req.Header = header
- }
- if values != nil {
- req.URL.RawQuery = values.Encode()
- }
- fmt.Println(req.URL.Host, req.URL.RawQuery)
- resp, resErr := http.DefaultClient.Do(req)
- if resErr != nil {
- return "", resErr
- }
- defer func() { _ = resp.Body.Close() }()
- content, readErr := io.ReadAll(resp.Body)
- if readErr != nil {
- return "", readErr
- }
- //if decodeErr := json.Unmarshal(content, result); decodeErr != nil {
- // return "", decodeErr
- //}
- return string(content), nil
- }
- type HttpResult struct {
- Code int `bson:"code"`
- Msg string `bson:"msg"`
- }
|