package main import ( "encoding/json" "fmt" "github.com/gin-gonic/gin" "math/rand" "miads/adslib" "miads/adslib/addata" "miads/adslib/ads_checker" "miads/adslib/city" "miads/adslib/device" "miads/adslib/encrypt" "miads/adslib/graylog" "miads/adslib/ip2region" "miads/adslib/redis_data" "miads/adslib/utils" "net/url" "strconv" "strings" "time" log "github.com/sirupsen/logrus" ) type Response struct { Result int `json:"result"` Msg string `json:"msg"` AdsResult string `json:"ads_result"` addata.AdData } func adsHandler(c *gin.Context) { c.Header("Content-Type", "application/json") request := adslib.Request{} request.Parse(c) log.Printf("%+v", request) // 放这里主要为了拿到request id做日志记录 dspInfo := utils.DspParam{} dspInfo.Init() advertiser := "xiaomi" uaClient := request.UaClient // 获取ua if uaClient == "" { uaClient = c.GetHeader("User-Agent") if uaClient == "" { uaClient = "Dalvik/2.1.0 (Linux; U; Android 6.0.1; MI 4LTE MIUI/6.9.1)" } } // 获取ip checkReqSourceFlag, err := ads_checker.CheckReqSource(request.ReqSource) if err != nil { c.String(404, "check req source failed: %s", err) return } ip := "" if checkReqSourceFlag { ip = request.ReqSourceIp } if ip == "" { ip = c.GetHeader("X-Forwarded-For") } if ip == "" { ip = c.GetHeader("X-Real-IP") } if ip == "" { ip = c.Request.RemoteAddr } if strings.Index(ip, ",") != -1 { ip = strings.Split(ip, ",")[0] } ipInfo, err := ip2region.Ip2Region(ip) if err != nil { c.String(404, "ip 2 region failed: %s", err) return } log.WithField("request_id", dspInfo.RequestId).Infof("ip 2 region: %s, %+v", ip, ipInfo) // 上報 if request.NewAdsFlag == 1 { grayLogData := struct { Ip string Imei string Model string NetworkType int `json:"network_type"` Province string City string ScreeSize string `json:"screen_size"` Ua string Brand string Androidid string `json:"android_id"` ShortMessage string `json:"short_message"` ReqSource string `json:"req_source"` Hehe string `json:"hehe"` }{ Ip: ip, Imei: request.Imei, Model: request.Model, NetworkType: request.NetworkType, Province: ipInfo.Province, City: ipInfo.City, ScreeSize: request.ScreenSize, Ua: request.UaClient, Brand: request.Brand, Androidid: request.Androidid, ShortMessage: "ads_api_log", ReqSource: "zhiku", Hehe: "heheheheh", } graylog.Log(grayLogData) } // 定制city code cityCode, err := city.GetCityCode(ipInfo.City) log.WithField("request_id", dspInfo.RequestId).Infof("got city code: %d", cityCode) if err != nil { c.String(404, "get city code failed: %s", err) return } freqControlInterval := 600 // 深圳,东莞强行用600秒控制, 其他地区从配置读取 if strings.Index(ipInfo.City, "深圳") == -1 && strings.Index(ipInfo.City, "东莞") == -1 { // 频率控制 freqControlConf, err := redis_data.GetFreqControlConf(request.ReqSource) if err != nil { log.WithField("request_id", dspInfo.RequestId).Errorf("get freq control conf failed: %s", err) c.String(404, "get freq control conf failed: %s", err) return } log.WithField("request_id", dspInfo.RequestId).Infof("freq control conf: %+v", freqControlConf) hour, _ := strconv.Atoi(time.Now().Format("01")) tmpControlInterval, ok := freqControlConf.GetControlTime(hour) if ok { freqControlInterval = tmpControlInterval } } lastReqTime, err := device.GetIpReqTime(ip) if err != nil { fmt.Println(err) c.String(404, "get last req time failed: %s", err) return } needControl := false if request.ReqSource != "wzb_h5" && lastReqTime != 0 && time.Now().Unix()-lastReqTime < int64(freqControlInterval) { // 需要凭空 log.WithField("request_id", dspInfo.RequestId).Infof("need control: %d", lastReqTime) needControl = true } else { device.SetIpReqTime(ip, time.Now().Unix()) } //### 检查是否是ip黑名单 isIpBlack, err := ads_checker.CheckBlackIp(ip) if err != nil { log.WithField("request_id", dspInfo.RequestId).Errorf("check black ip failed: %s", err) c.String(404, "check black ip failed: %s", err) return } if isIpBlack { device.SetAdsTagLog(advertiser, request.ReqSource, "DS_BLACK_IP", cityCode) } // 获取渠道的黑白性 reqChannelFlag, err := redis_data.GetChannelFlag(request.ReqSource, "ads_req") if err != nil { log.WithField("request_id", dspInfo.RequestId).Errorf("get req channel flag failed: %s", err) c.String(404, "get req channel flag failed: %s", err) return } flowWeight := reqChannelFlag.Weigth flowRandomNum := rand.Intn(100) flowFlag := 0 // 有效的百分比 if flowRandomNum <= flowWeight { flowFlag = 1 } if reqChannelFlag.ChannelFlag == 1 { device.SetAdsTagLog(advertiser, request.ReqSource, fmt.Sprintf("DS_REQ_SOURCE_{%d}", reqChannelFlag.ChannelFlag), cityCode) } // 替换成小米的设备 replaceFlag := 0 imei := request.Imei sendPhoneType := 0 userFlag := 0 originImei := "" // 检查是否是小米的设备 specialDeviceNum := 0 if request.ReqSource == "wzb_h5" { specialDeviceNum = 6 // wzb_h5渠道只綁定一个imei, 具体愿意不知道 } if request.ReqSource == "moyuntv" || (!request.IsMiDevice() && (!isIpBlack && !needControl && reqChannelFlag.ChannelFlag == 1) && flowFlag == 1) { randomNum := 3 deviceConf, realRedisKey, err := device.GetMiDeviceConf(ip, randomNum, specialDeviceNum) if err != nil { log.WithField("request_id", dspInfo.RequestId).Errorf("get mi device conf failed: %s", err) c.String(404, "get mi device conf failed: %s", err) return } if deviceConf != nil { log.WithField("request_id", dspInfo.RequestId).Infof("use cache imei: %+v", deviceConf) device.SetAdsTagLog(advertiser, request.ReqSource, "DS_CACHE", cityCode) // 通过缓存请求 imei = deviceConf.Imei uaClient = deviceConf.Ua originImei = deviceConf.OriginImei if imei != "" { replaceFlag = 1 userFlag = 1 } } else { // 先从对应的城市找,找不到在走原来的逻辑 // 上报事件 graylog.LogApi("city_search_city_code", strconv.Itoa(cityCode), ipInfo.City, request.ReqSource) device.SetAdsTagLog(advertiser, request.ReqSource, "DS_CODE_REQ", cityCode) // 可做城市替换 if cityCode != 0 { device.SetAdsTagLog(advertiser, request.ReqSource, "DS_CODE", cityCode) // 替换成功 fakeImei := "" fakeDeviceConf, leftCnt, err := device.GetDailyFakeDeviceConfByCityCode(cityCode) if err != nil { log.WithField("request_id", dspInfo.RequestId).Errorf("get device conf failed: %s", err) c.String(404, "get device conf failed: %s", err) return } // 0 没有获取到, 1 获取到了 gotCityFakeDeviceConfFlag := 0 replaceUa := "" if fakeDeviceConf != nil { device.SetAdsTagLog(advertiser, request.ReqSource, "DS_REPL", cityCode) err := device.SetMiDeviceConf(realRedisKey, *fakeDeviceConf) if err != nil { log.WithField("request_id", dspInfo.RequestId).Errorf("set mi device conf failed: %s", err) } imei = fakeDeviceConf.Imei uaClient = fakeDeviceConf.Ua originImei = fakeDeviceConf.OriginImei fakeImei = fakeDeviceConf.Imei if fakeDeviceConf.Imei != "" { gotCityFakeDeviceConfFlag = 1 userFlag = 2 replaceFlag = 1 } } grayLogData := struct { ReqSource string `json:"req_source"` OldImei string `json:"old_imei"` NewImei string `json:"new_imei"` IP string `json:"ip"` City string `json:"city"` CityCode int `json:"city_code"` Province string `json:"province"` HitFlag int `json:"hit_flag"` LeftCnt int `json:"left_cnt"` ReplaceUa string `json:"replace_ua"` ShortMessage string `json:"short_message"` }{ ReqSource: request.ReqSource, OldImei: request.Imei, NewImei: fakeImei, IP: ip, City: ipInfo.City, CityCode: cityCode, Province: ipInfo.Province, HitFlag: gotCityFakeDeviceConfFlag, LeftCnt: leftCnt, ReplaceUa: replaceUa, ShortMessage: "", } // 进行日志的上报 graylog.Log(grayLogData) } } // 解码ua_client uaClient, _ = url.QueryUnescape(uaClient) } else if request.IsMiDevice() { log.WithField("request_id", dspInfo.RequestId).Info("real mi") device.SetAdsTagLog(advertiser, request.ReqSource, "DS_MI_REAL", cityCode) // 是小米设备 userFlag = 3 sendPhoneType = 1 } // 检查下,替换后的设备是否是黑名单, 再次检查, 防止放入cache后, 新增了黑名单 checkImei := imei // 替换过的imei从redis取的, 都是md5后的, 不需要再md5 if replaceFlag != 1 { checkImei = utils.Md5(imei) } isBlackImei, err := device.CheckIsBlackImei(checkImei) if err != nil { log.WithField("request_id", dspInfo.RequestId).Errorf("get device conf failed: %s", err) c.String(404, "get device conf failed: %s", err) return } log.WithField("request_id", dspInfo.RequestId).Tracef("replace flag: %d", replaceFlag) if isBlackImei { if replaceFlag == 1 { log.WithField("request_id", dspInfo.RequestId).Trace("replace") device.SetAdsTagLog(advertiser, request.ReqSource, "DS_BLACK_IMEI_REPLACE", cityCode) } else { log.WithField("request_id", dspInfo.RequestId).Trace("not replace") device.SetAdsTagLog(advertiser, request.ReqSource, "DS_BLACK_IMEI", cityCode) } } // 组装公共的dsp_info dspInfo.DspCityCode = cityCode dspInfo.Imei = imei dspInfo.OriginImei = originImei dspInfo.OsVersion = request.OsVersion dspInfo.Mac = strings.ToUpper(request.Mac) dspInfo.OriginMac = request.Mac dspInfo.Idfa = request.Idfa dspInfo.Model = request.Model dspInfo.Brand = request.Brand dspInfo.ScreenSize = request.ScreenSize dspInfo.NetworkType = request.NetworkType dspInfo.Androidid = request.Androidid dspInfo.Platform = request.Platform dspInfo.Ip = ip dspInfo.Ua = uaClient dspInfo.City = ipInfo.City dspInfo.Province = ipInfo.Province dspInfo.UaOrigin = request.UaClient dspInfo.ReqSource = request.ReqSource if request.IsMiDevice() { dspInfo.RealMiFlag = 1 } dspInfo.ReplaceFlag = replaceFlag dspInfo.RealReqSource = request.ReqSource dspInfo.SendPhoneType = sendPhoneType md5Imei := imei if dspInfo.OriginImei != "" { md5Imei = utils.Md5(dspInfo.OriginImei) } dspInfo.RealMd5Imei = md5Imei log.WithField("request_id", dspInfo.RequestId).Infof("dsp: %+v", dspInfo) //ads_item = None //xiaomi_response = [] hour, _ := strconv.Atoi(time.Now().Format("01")) canRequest := true if 0 <= hour && hour <= 1 { randNum := rand.Intn(100) if randNum > 5 { canRequest = false } } log.WithField("request_id", dspInfo.RequestId).Infof("can request: %t", canRequest) var adData *addata.AdData // 非频率控制,设备黑名单,ip黑名单,白名单渠道,并且替换了小米设备的 if canRequest && !isBlackImei && reqChannelFlag.ChannelFlag == 1 && flowFlag == 1 && !isIpBlack && advertiser == "xiaomi" && request.ReqSource != "" && !needControl && (replaceFlag == 1 || request.IsMiDevice()) { adData, err = addata.GetAdsInfos(&dspInfo, advertiser) if err != nil { log.WithField("request_id", dspInfo.RequestId).Errorf("get mi ad data failed: %s", err) c.String(404, "get mi ad data failed: %s", err) return } log.WithField("request_id", dspInfo.RequestId).Infof("get mi ads data: %+v", adData) } canMixFlag := 1 xiaomiResponseFlag := 0 response := Response{} response.Msg = "ok" if adData != nil && len(adData.TargetAddition) > 1 { log.WithField("request_id", dspInfo.RequestId).Infof("add target js order") xiaomiResponseFlag = 1 realTarget := "" if adData.Target != "" { md5Skip := utils.Md5(adData.Target) conf := adslib.GetConf() realTarget = conf.Host + fmt.Sprintf("?action=LOADING&req_source=%s&advertiser=video&skip=%s&brand=%s&request_id=%s&skip_other=%s", dspInfo.ReqSource, "", dspInfo.Brand, dspInfo.RequestId, md5Skip) // 塞入Redis中 redis_data.SetSkipInfo(md5Skip, adData.Target) } adData.Target = realTarget adData.JsOrderId, err = redis_data.GetMinScriptOrderByAdv(advertiser) if err != nil { log.WithField("request_id", dspInfo.RequestId).Errorf("get min script order by adv failed: %s", err) c.String(404, "get min script order by adv failed: %s", err) return } log.WithField("request_id", dspInfo.RequestId).Infof("got min script order: %d", adData.JsOrderId) adData.UserAgent = uaClient if dspInfo.ReqSource == "kuxin" && adData.Target != "" { adData.DpReport = fmt.Sprintf("%s?action=DP_CLICK&advertiser=video&req_source=%s", adslib.GetConf().HostIos, dspInfo.ReqSource) adData.Dp = adslib.GetConf().DpTest } if dspInfo.SendPhoneType == 0 { device.SetAdsTagLog(advertiser, dspInfo.ReqSource, "ADS_GET", cityCode) // 广告获取成功 } else if dspInfo.SendPhoneType == 1 { device.SetAdsTagLog(advertiser, dspInfo.ReqSource, "ADS_GET_1", cityCode) // 广告获取成功 } device.SetAdsTagLog(advertiser, dspInfo.ReqSource, fmt.Sprintf("ADS_USER_%d", userFlag), cityCode) // 广告类型,缓存,新用户,小米手机 // // 判断这个渠道是否要去融合和融合的流量占比 // mixChannelFlag, err := redis_data.GetChannelFlag(dspInfo.ReqSource, "ads_mix") // if err != nil { // log.WithField("request_id", dspInfo.RequestId).Errorf("get device conf failed: %s", err) // c.String(404, "get device conf failed: %s", err) // return // } // flowRandomNum = rand.Intn(100) //isOverFlow := false //if flowRandomNum > mixChannelFlag.Weigth { // isOverFlow = true //} //if mixChannelFlag.ChannelFlag != 1 || isOverFlow { // //extra_infos = [] //} // 组装返回去的action serverActionResponse := map[string]int{"server_view": 0, "server_click": 0, "server_close": 0, "server_video_finish": 0, "server_video_timer": 0} for _, targetInfo := range adData.TargetAddition { if targetInfo.Type == "VIEW" { serverActionResponse["server_view"] = 1 redis_data.SetReqSourceView(advertiser, dspInfo.ReqSource, "xiafa") } else if targetInfo.Type == "CLICK" { serverActionResponse["server_click"] = 1 } else if targetInfo.Type == "CLOSE" { serverActionResponse["server_close"] = 1 } else if targetInfo.Type == "VIDEO_FINISH" { serverActionResponse["server_video_finish"] = 1 } else if targetInfo.Type == "VIDEO_TIMER" { serverActionResponse["server_video_timer"] = 1 } } log.WithField("request_id", dspInfo.RequestId).Infof("server action response: %+v", serverActionResponse) // 增加跟随订单 if len(adData.TargetAddition) == 2 && serverActionResponse["server_video_finish"] == 1 && (dspInfo.ReqSource == "kuxin" || dspInfo.ReqSource == "zhiku") { log.WithField("request_id", dspInfo.RequestId).Infof("add more order") adData, err = addata.CombineOrderBy(adData, &dspInfo) if err != nil { log.WithField("request_id", dspInfo.RequestId).Errorf("combine order failed: %s", err) c.String(404, "combine order failed: %s", err.Error()) return } log.WithField("request_id", dspInfo.RequestId).Infof("get custom order: %+v", adData) } //# 检查最后是否有click log.WithField("request_id", dspInfo.RequestId).Infof("check ads item new: %+v", adData) for _, targetAddition := range adData.TargetAddition { if targetAddition.Type == "CLICK" || targetAddition.Type == "VIDEO_TIMER" { log.WithField("request_id", dspInfo.RequestId).Infof("can't mix, targetAddition: %+v", targetAddition) canMixFlag = 0 break } } if request.NewAdsFlag == 0 { response.AdData = *adData log.WithField("request_id", dspInfo.RequestId).Infof("update response: +%v", response) } else { jsonBytes, err := json.Marshal(*adData) if err != nil { c.String(404, "marshal AdData failed: %s", err.Error()) return } encryptData, _ := encrypt.Encrypt(jsonBytes, []byte(adslib.GetConf().SecretKey)) response.AdsResult = encryptData } } log.WithField("request_id", dspInfo.RequestId).Infof("can mix: %d, xiaomi rsp flag: %d", canMixFlag, xiaomiResponseFlag) if canMixFlag == 1 { response.Result = 2 response.Msg = "no ads" if xiaomiResponseFlag == 1 { response.Result = 0 response.Msg = "ok" } // 增加打底广告 if (dspInfo.ReqSource == "kuxin" || dspInfo.ReqSource == "zhiku") && !needControl && !isBlackImei { shortMessage := "kong" // 先跑定投 customAdData, err := addata.GetCustomAdsInfos(&dspInfo, 0, 0, xiaomiResponseFlag) if err != nil { log.WithField("request_id", dspInfo.RequestId).Infof("get custom ads info failed: %s", err) c.String(404, "get custom ads info failed: %s", err.Error()) return } log.WithField("request_id", dspInfo.RequestId).Infof("dingtou: %+v", customAdData) // 定投没有就跑其他的 if customAdData == nil { customAdData, err = addata.GetCustomAdsInfos(&dspInfo, 0, 1, xiaomiResponseFlag) if err != nil { log.WithField("request_id", dspInfo.RequestId).Errorf("get fix custom ads info failed: %s", err) c.String(404, "get fix custom ads info failed: %s", err.Error()) return } } device.SetAdsTagLog(advertiser, dspInfo.ReqSource, "ADS_ZIYOU_GET", cityCode) // 广告获取成功 if customAdData != nil { shortMessage = "ads_tt_thirds" } if customAdData != nil && (shortMessage == "ads_vast_response" || shortMessage == "ads_tt_thirds") { adDataBytes, err := json.Marshal(*customAdData) if err != nil { log.WithField("request_id", dspInfo.RequestId).Errorf("marshal adData failed: %s\n", err) } grayLogData := struct { Ip string ShortMessage string `json:"short_message"` ReqSource string `json:"req_source"` ResponseVast string `json:"response_vast"` OrderName string `json:"order_name"` Advertiser string `json:"advertiser"` }{ Ip: ip, ShortMessage: "ads_api_log", ReqSource: "zhiku", ResponseVast: string(adDataBytes), OrderName: customAdData.OrderName, Advertiser: advertiser, } graylog.Log(grayLogData) } if shortMessage == "ads_tt_thirds" { // 组装最后的信息 lastAdData := addata.AdData{} rspTargetAddition := make([]addata.AdAction, 0, 50) // 当小米有填充的时候 if len(response.TargetAddition) != 0 && len(customAdData.TargetAddition) != 0 { rspTargetAddition = response.TargetAddition lastAdData.UserAgent = response.UserAgent // 当只有view的时候 if len(customAdData.TargetAddition) == 1 { for _, targetUrl := range customAdData.TargetAddition[0].Urls { rspTargetAddition[0].Urls = append(rspTargetAddition[0].Urls, targetUrl) } } else { // 当自由订单有view和click的时候 for _, targetUrl := range customAdData.TargetAddition[0].Urls { rspTargetAddition[0].Urls = append(rspTargetAddition[0].Urls, targetUrl) } for _, targetUrl := range customAdData.TargetAddition[1].Urls { rspTargetAddition[1].Urls = append(rspTargetAddition[1].Urls, targetUrl) } rspTargetAddition[1].Type = "CLICK" } lastAdData.Target = customAdData.Target lastAdData.JsOrderId = customAdData.JsOrderId lastAdData.TargetAddition = rspTargetAddition lastAdData.DpReport = response.DpReport lastAdData.Dp = response.Dp adDataBytes, err := json.Marshal(lastAdData) if err != nil { log.WithField("request_id", dspInfo.RequestId).Errorf("marshal adData failed: %s", err) } grayLogData := struct { ShortMessage string `json:"short_message"` ResponseVast string `json:"response_vast"` }{ ShortMessage: "third_mix_xiaomi", ResponseVast: string(adDataBytes), } graylog.Log(grayLogData) log.WithField("request_id", dspInfo.RequestId).Infof("replace addata: %+v", lastAdData) customAdData = &lastAdData } } if customAdData != nil { device.SetAdsTagLog(advertiser, dspInfo.ReqSource, "ADS_ZIYOU_HAVE", cityCode) // 广告获取成功 if dspInfo.ReqSource == "zhiku" { response.Result = 0 response.Msg = "ok" log.WithField("request_id", dspInfo.RequestId).Infof("rsp1: %+v", customAdData) jsonBytes, err := json.Marshal(customAdData) if err != nil { log.WithField("request_id", dspInfo.RequestId).Errorf("marshal rsp1 custom ad failed: %s", err) c.String(404, "marsha custom addata failed: %s", err.Error()) return } log.WithField("request_id", dspInfo.RequestId).Infof("rsp1: %s", jsonBytes) encryptData, _ := encrypt.Encrypt(jsonBytes, []byte(adslib.GetConf().SecretKey)) response.AdsResult = encryptData log.WithField("request_id", dspInfo.RequestId).Infof("encrypt: %s", encryptData) s, err := encrypt.Decrypt(encryptData, []byte(adslib.GetConf().SecretKey)) log.WithField("request_id", dspInfo.RequestId).Info(s, err) graylog.ReportGrayLog(request, dspInfo, 0, 0) rspBytes, err := json.Marshal(response) if err != nil { log.WithField("request_id", dspInfo.RequestId).Errorf("marshal rsp1 failed: %s", err) c.String(404, "marshal Response failed: %s", err.Error()) return } log.WithField("request_id", dspInfo.RequestId).Infof("rsp1: %s", rspBytes) c.String(200, string(rspBytes)) return } else { customAdData.Result = 0 customAdData.Msg = "ok" graylog.ReportGrayLog(request, dspInfo, 0, 0) rspBytes, err := json.Marshal(customAdData) if err != nil { log.WithField("request_id", dspInfo.RequestId).Errorf("marshal rsp2 failed: %s", err) c.String(404, err.Error()) return } log.WithField("request_id", dspInfo.RequestId).Infof("rsp2: %s", rspBytes) c.String(200, string(rspBytes)) return } } } } redis_data.SetAdsRealRequestNum(advertiser) rspBytes, err := json.Marshal(response) if err != nil { log.WithField("request_id", dspInfo.RequestId).Errorf("marshal rsp3 failed: %s", err) c.String(404, err.Error()) return } if request.NewAdsFlag == 0 { graylog.ReportGrayLog(request, dspInfo, 0, 0) } device.SetAdsTagLog(advertiser, dspInfo.ReqSource, "DS_REQ", cityCode) // 所有请求 log.WithField("request_id", dspInfo.RequestId).Infof("rsp3: %s", rspBytes) c.String(200, string(rspBytes)) }