Skip to content

Commit ffdd75f

Browse files
authored
New Adapter: AdTonos (#3853)
1 parent c02ee8c commit ffdd75f

File tree

12 files changed

+706
-0
lines changed

12 files changed

+706
-0
lines changed

adapters/adtonos/adtonos.go

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
package adtonos
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"net/http"
7+
"text/template"
8+
9+
"github.com/prebid/openrtb/v20/openrtb2"
10+
"github.com/prebid/prebid-server/v2/adapters"
11+
"github.com/prebid/prebid-server/v2/config"
12+
"github.com/prebid/prebid-server/v2/errortypes"
13+
"github.com/prebid/prebid-server/v2/macros"
14+
"github.com/prebid/prebid-server/v2/openrtb_ext"
15+
)
16+
17+
type adapter struct {
18+
endpointTemplate *template.Template
19+
}
20+
21+
func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) {
22+
template, err := template.New("endpointTemplate").Parse(config.Endpoint)
23+
if err != nil {
24+
return nil, fmt.Errorf("unable to parse endpoint url template: %v", err)
25+
}
26+
27+
bidder := &adapter{
28+
endpointTemplate: template,
29+
}
30+
return bidder, nil
31+
}
32+
33+
func (a *adapter) MakeRequests(request *openrtb2.BidRequest, requestInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) {
34+
var bidderExt adapters.ExtImpBidder
35+
if err := json.Unmarshal(request.Imp[0].Ext, &bidderExt); err != nil {
36+
return nil, []error{&errortypes.BadInput{
37+
Message: fmt.Sprintf("Invalid imp.ext for impression index %d. Error Infomation: %s", 0, err.Error()),
38+
}}
39+
}
40+
var impExt openrtb_ext.ImpExtAdTonos
41+
if err := json.Unmarshal(bidderExt.Bidder, &impExt); err != nil {
42+
return nil, []error{&errortypes.BadInput{
43+
Message: fmt.Sprintf("Invalid imp.ext.bidder for impression index %d. Error Infomation: %s", 0, err.Error()),
44+
}}
45+
}
46+
47+
endpoint, err := a.buildEndpointURL(&impExt)
48+
if err != nil {
49+
return nil, []error{err}
50+
}
51+
52+
requestJson, err := json.Marshal(request)
53+
if err != nil {
54+
return nil, []error{err}
55+
}
56+
57+
headers := http.Header{}
58+
headers.Add("Content-Type", "application/json;charset=utf-8")
59+
headers.Add("Accept", "application/json")
60+
61+
requestData := &adapters.RequestData{
62+
Method: "POST",
63+
Uri: endpoint,
64+
Body: requestJson,
65+
Headers: headers,
66+
ImpIDs: openrtb_ext.GetImpIDs(request.Imp),
67+
}
68+
69+
return []*adapters.RequestData{requestData}, nil
70+
}
71+
72+
func (a *adapter) buildEndpointURL(params *openrtb_ext.ImpExtAdTonos) (string, error) {
73+
endpointParams := macros.EndpointTemplateParams{PublisherID: params.SupplierID}
74+
return macros.ResolveMacros(a.endpointTemplate, endpointParams)
75+
}
76+
77+
func (a *adapter) MakeBids(request *openrtb2.BidRequest, requestData *adapters.RequestData, responseData *adapters.ResponseData) (*adapters.BidderResponse, []error) {
78+
if adapters.IsResponseStatusCodeNoContent(responseData) {
79+
return nil, nil
80+
}
81+
82+
if err := adapters.CheckResponseStatusCodeForErrors(responseData); err != nil {
83+
return nil, []error{err}
84+
}
85+
86+
var response openrtb2.BidResponse
87+
if err := json.Unmarshal(responseData.Body, &response); err != nil {
88+
return nil, []error{err}
89+
}
90+
91+
bidResponse := adapters.NewBidderResponseWithBidsCapacity(len(request.Imp))
92+
bidResponse.Currency = response.Cur
93+
var errors []error
94+
for _, seatBid := range response.SeatBid {
95+
for i := range seatBid.Bid {
96+
bidType, err := getMediaTypeForBid(seatBid.Bid[i], request.Imp)
97+
if err != nil {
98+
errors = append(errors, err)
99+
continue
100+
}
101+
b := &adapters.TypedBid{
102+
Bid: &seatBid.Bid[i],
103+
BidType: bidType,
104+
}
105+
bidResponse.Bids = append(bidResponse.Bids, b)
106+
}
107+
}
108+
return bidResponse, errors
109+
}
110+
111+
func getMediaTypeForBid(bid openrtb2.Bid, requestImps []openrtb2.Imp) (openrtb_ext.BidType, error) {
112+
if bid.MType != 0 {
113+
// If present, use explicit markup type annotation from the bidder:
114+
switch bid.MType {
115+
case openrtb2.MarkupAudio:
116+
return openrtb_ext.BidTypeAudio, nil
117+
case openrtb2.MarkupVideo:
118+
return openrtb_ext.BidTypeVideo, nil
119+
case openrtb2.MarkupBanner:
120+
return openrtb_ext.BidTypeBanner, nil
121+
case openrtb2.MarkupNative:
122+
return openrtb_ext.BidTypeNative, nil
123+
}
124+
}
125+
// As a fallback, guess markup type based on requested type - AdTonos is an audio company so we prioritize that.
126+
for _, requestImp := range requestImps {
127+
if requestImp.ID == bid.ImpID {
128+
if requestImp.Audio != nil {
129+
return openrtb_ext.BidTypeAudio, nil
130+
} else if requestImp.Video != nil {
131+
return openrtb_ext.BidTypeVideo, nil
132+
} else {
133+
return "", &errortypes.BadInput{
134+
Message: fmt.Sprintf("Unsupported bidtype for bid: \"%s\"", bid.ImpID),
135+
}
136+
}
137+
}
138+
}
139+
return "", &errortypes.BadInput{
140+
Message: fmt.Sprintf("Failed to find impression: \"%s\"", bid.ImpID),
141+
}
142+
}

adapters/adtonos/adtonos_test.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package adtonos
2+
3+
import (
4+
"testing"
5+
6+
"github.com/prebid/prebid-server/v2/adapters/adapterstest"
7+
"github.com/prebid/prebid-server/v2/config"
8+
"github.com/prebid/prebid-server/v2/openrtb_ext"
9+
"github.com/stretchr/testify/assert"
10+
)
11+
12+
func TestJsonSamples(t *testing.T) {
13+
bidder, buildErr := Builder(openrtb_ext.BidderAdTonos, config.Adapter{
14+
Endpoint: "http://exchange.example.com/bid/{{.PublisherID}}"},
15+
config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"})
16+
17+
if buildErr != nil {
18+
t.Fatalf("Builder returned unexpected error %v", buildErr)
19+
}
20+
21+
adapterstest.RunJSONBidderTest(t, "adtonostest", bidder)
22+
}
23+
24+
func TestEndpointTemplateMalformed(t *testing.T) {
25+
_, buildErr := Builder(openrtb_ext.BidderAdTonos, config.Adapter{
26+
Endpoint: "{{Malformed}}"},
27+
config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"})
28+
29+
assert.Error(t, buildErr)
30+
}
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
{
2+
"mockBidRequest": {
3+
"id": "some-request-id",
4+
"tmax": 1000,
5+
"imp": [
6+
{
7+
"id": "some-impression-id",
8+
"bidfloor": 4.2,
9+
"ext": {
10+
"bidder": {
11+
"supplierId": "777XYZ123"
12+
}
13+
},
14+
"audio": {
15+
"mimes": [
16+
"audio/mpeg"
17+
]
18+
}
19+
}
20+
],
21+
"test": 1,
22+
"site": {
23+
"publisher": {
24+
"id": "1"
25+
},
26+
"page": "http://www.example.com",
27+
"domain": "www.example.com"
28+
},
29+
"device": {}
30+
},
31+
"httpCalls": [
32+
{
33+
"expectedRequest": {
34+
"uri": "http://exchange.example.com/bid/777XYZ123",
35+
"headers": {
36+
"Content-Type": [
37+
"application/json;charset=utf-8"
38+
],
39+
"Accept": [
40+
"application/json"
41+
]
42+
},
43+
"body": {
44+
"id": "some-request-id",
45+
"tmax": 1000,
46+
"imp": [
47+
{
48+
"id": "some-impression-id",
49+
"bidfloor": 4.2,
50+
"ext": {
51+
"bidder": {
52+
"supplierId": "777XYZ123"
53+
}
54+
},
55+
"audio": {
56+
"mimes": [
57+
"audio/mpeg"
58+
]
59+
}
60+
}
61+
],
62+
"site": {
63+
"publisher": {
64+
"id": "1"
65+
},
66+
"page": "http://www.example.com",
67+
"domain": "www.example.com"
68+
},
69+
"device": {},
70+
"test": 1
71+
},
72+
"impIDs":["some-impression-id"]
73+
},
74+
"mockResponse": {
75+
"status": 200,
76+
"body": {
77+
"id": "some-request-id",
78+
"cur": "USD",
79+
"seatbid": [
80+
{
81+
"bid": [
82+
{
83+
"id": "1",
84+
"impid": "some-impression-id",
85+
"crid": "some-creative-id",
86+
"adm": "<VAST>TAG</VAST>",
87+
"price": 6.5,
88+
"mtype": 3
89+
}
90+
]
91+
}
92+
]
93+
}
94+
}
95+
}
96+
],
97+
"expectedBidResponses": [
98+
{
99+
"currency": "USD",
100+
"bids": [
101+
{
102+
"bid": {
103+
"id": "1",
104+
"impid": "some-impression-id",
105+
"crid": "some-creative-id",
106+
"adm": "<VAST>TAG</VAST>",
107+
"price": 6.5,
108+
"mtype": 3
109+
},
110+
"type": "audio"
111+
}
112+
]
113+
}
114+
]
115+
}

0 commit comments

Comments
 (0)