github.com/prebid/prebid-server/v2@v2.18.0/adapters/adtelligent/adtelligent.go (about) 1 package adtelligent 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "net/http" 7 8 "github.com/prebid/openrtb/v20/openrtb2" 9 "github.com/prebid/prebid-server/v2/adapters" 10 "github.com/prebid/prebid-server/v2/config" 11 "github.com/prebid/prebid-server/v2/errortypes" 12 "github.com/prebid/prebid-server/v2/openrtb_ext" 13 ) 14 15 type AdtelligentAdapter struct { 16 endpoint string 17 } 18 19 type adtelligentImpExt struct { 20 Adtelligent openrtb_ext.ExtImpAdtelligent `json:"adtelligent"` 21 } 22 23 func (a *AdtelligentAdapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { 24 25 totalImps := len(request.Imp) 26 errors := make([]error, 0, totalImps) 27 imp2source := make(map[int][]int) 28 29 for i := 0; i < totalImps; i++ { 30 31 sourceId, err := validateImpression(&request.Imp[i]) 32 33 if err != nil { 34 errors = append(errors, err) 35 continue 36 } 37 38 if _, ok := imp2source[sourceId]; !ok { 39 imp2source[sourceId] = make([]int, 0, totalImps-i) 40 } 41 42 imp2source[sourceId] = append(imp2source[sourceId], i) 43 44 } 45 46 totalReqs := len(imp2source) 47 if 0 == totalReqs { 48 return nil, errors 49 } 50 51 headers := http.Header{} 52 headers.Add("Content-Type", "application/json;charset=utf-8") 53 headers.Add("Accept", "application/json") 54 55 reqs := make([]*adapters.RequestData, 0, totalReqs) 56 57 imps := request.Imp 58 request.Imp = make([]openrtb2.Imp, 0, len(imps)) 59 for sourceId, impIds := range imp2source { 60 request.Imp = request.Imp[:0] 61 62 for i := 0; i < len(impIds); i++ { 63 request.Imp = append(request.Imp, imps[impIds[i]]) 64 } 65 66 body, err := json.Marshal(request) 67 if err != nil { 68 errors = append(errors, fmt.Errorf("error while encoding bidRequest, err: %s", err)) 69 return nil, errors 70 } 71 72 reqs = append(reqs, &adapters.RequestData{ 73 Method: "POST", 74 Uri: a.endpoint + fmt.Sprintf("?aid=%d", sourceId), 75 Body: body, 76 Headers: headers, 77 ImpIDs: openrtb_ext.GetImpIDs(request.Imp), 78 }) 79 } 80 81 if 0 == len(reqs) { 82 return nil, errors 83 } 84 85 return reqs, errors 86 87 } 88 89 func (a *AdtelligentAdapter) MakeBids(bidReq *openrtb2.BidRequest, unused *adapters.RequestData, httpRes *adapters.ResponseData) (*adapters.BidderResponse, []error) { 90 91 if httpRes.StatusCode == http.StatusNoContent { 92 return nil, nil 93 } 94 95 var bidResp openrtb2.BidResponse 96 if err := json.Unmarshal(httpRes.Body, &bidResp); err != nil { 97 return nil, []error{&errortypes.BadServerResponse{ 98 Message: fmt.Sprintf("error while decoding response, err: %s", err), 99 }} 100 } 101 102 bidResponse := adapters.NewBidderResponse() 103 var errors []error 104 105 var impOK bool 106 for _, sb := range bidResp.SeatBid { 107 for i := 0; i < len(sb.Bid); i++ { 108 109 bid := sb.Bid[i] 110 111 impOK = false 112 mediaType := openrtb_ext.BidTypeBanner 113 for _, imp := range bidReq.Imp { 114 if imp.ID == bid.ImpID { 115 116 impOK = true 117 118 if imp.Video != nil { 119 mediaType = openrtb_ext.BidTypeVideo 120 break 121 } 122 } 123 } 124 125 if !impOK { 126 errors = append(errors, &errortypes.BadServerResponse{ 127 Message: fmt.Sprintf("ignoring bid id=%s, request doesn't contain any impression with id=%s", bid.ID, bid.ImpID), 128 }) 129 continue 130 } 131 132 bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{ 133 Bid: &bid, 134 BidType: mediaType, 135 }) 136 } 137 } 138 139 return bidResponse, errors 140 } 141 142 func validateImpression(imp *openrtb2.Imp) (int, error) { 143 144 if imp.Banner == nil && imp.Video == nil { 145 return 0, &errortypes.BadInput{ 146 Message: fmt.Sprintf("ignoring imp id=%s, Adtelligent supports only Video and Banner", imp.ID), 147 } 148 } 149 150 if 0 == len(imp.Ext) { 151 return 0, &errortypes.BadInput{ 152 Message: fmt.Sprintf("ignoring imp id=%s, extImpBidder is empty", imp.ID), 153 } 154 } 155 156 var bidderExt adapters.ExtImpBidder 157 158 if err := json.Unmarshal(imp.Ext, &bidderExt); err != nil { 159 return 0, &errortypes.BadInput{ 160 Message: fmt.Sprintf("ignoring imp id=%s, error while decoding extImpBidder, err: %s", imp.ID, err), 161 } 162 } 163 164 impExt := openrtb_ext.ExtImpAdtelligent{} 165 err := json.Unmarshal(bidderExt.Bidder, &impExt) 166 if err != nil { 167 return 0, &errortypes.BadInput{ 168 Message: fmt.Sprintf("ignoring imp id=%s, error while decoding impExt, err: %s", imp.ID, err), 169 } 170 } 171 172 // common extension for all impressions 173 var impExtBuffer []byte 174 175 impExtBuffer, err = json.Marshal(&adtelligentImpExt{ 176 Adtelligent: impExt, 177 }) 178 if err != nil { 179 return 0, &errortypes.BadInput{ 180 Message: fmt.Sprintf("ignoring imp id=%s, error while marshaling impExt, err: %s", imp.ID, err), 181 } 182 } 183 184 if impExt.BidFloor > 0 { 185 imp.BidFloor = impExt.BidFloor 186 } 187 188 imp.Ext = impExtBuffer 189 190 return impExt.SourceId, nil 191 } 192 193 // Builder builds a new instance of the Adtelligent adapter for the given bidder with the given config. 194 func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) { 195 bidder := &AdtelligentAdapter{ 196 endpoint: config.Endpoint, 197 } 198 return bidder, nil 199 }