Skip to content

Commit

Permalink
New Adapter: AdUp Tech (#4076)
Browse files Browse the repository at this point in the history
  • Loading branch information
danygielow authored Jan 30, 2025
1 parent 7045683 commit 502a438
Show file tree
Hide file tree
Showing 21 changed files with 1,435 additions and 0 deletions.
161 changes: 161 additions & 0 deletions adapters/aduptech/aduptech.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
package aduptech

import (
"errors"
"fmt"
"net/http"
"strings"

"github.com/prebid/openrtb/v20/openrtb2"
"github.com/prebid/prebid-server/v3/adapters"
"github.com/prebid/prebid-server/v3/config"
prebidcurrency "github.com/prebid/prebid-server/v3/currency"
"github.com/prebid/prebid-server/v3/errortypes"
"github.com/prebid/prebid-server/v3/openrtb_ext"
"github.com/prebid/prebid-server/v3/util/jsonutil"
"golang.org/x/text/currency"
)

type adapter struct {
endpoint string
extraInfo ExtraInfo
}

type ExtraInfo struct {
TargetCurrency string `json:"target_currency,omitempty"`
}

func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) {
var extraInfo ExtraInfo
if err := jsonutil.Unmarshal([]byte(config.ExtraAdapterInfo), &extraInfo); err != nil {
return nil, fmt.Errorf("invalid extra info: %w", err)
}

if extraInfo.TargetCurrency == "" {
return nil, errors.New("invalid extra info: TargetCurrency is empty, pls check")
}

parsedCurrency, err := currency.ParseISO(extraInfo.TargetCurrency)
if err != nil {
return nil, fmt.Errorf("invalid extra info: invalid TargetCurrency %s, pls check", extraInfo.TargetCurrency)
}
extraInfo.TargetCurrency = parsedCurrency.String()

bidder := &adapter{
endpoint: config.Endpoint,
extraInfo: extraInfo,
}

return bidder, nil
}

func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) {
for i := range request.Imp {
imp := &request.Imp[i]
// Check if imp comes with bid floor amount defined in a foreign currency
if imp.BidFloor > 0 && imp.BidFloorCur != "" && strings.ToUpper(imp.BidFloorCur) != a.extraInfo.TargetCurrency {

convertedValue, err := a.convertCurrency(imp.BidFloor, imp.BidFloorCur, reqInfo)
if err != nil {
return nil, []error{err}
}

imp.BidFloorCur = a.extraInfo.TargetCurrency
imp.BidFloor = convertedValue
}
}

requestJSON, err := jsonutil.Marshal(request)
if err != nil {
return nil, []error{err}
}

requestData := &adapters.RequestData{
Method: http.MethodPost,
Uri: a.endpoint,
Body: requestJSON,
ImpIDs: openrtb_ext.GetImpIDs(request.Imp),
}

return []*adapters.RequestData{requestData}, nil
}

// convertCurrency attempts to convert a given value from the specified currency (cur) to the
// target currency specified in the adapter's extraInfo. If the conversion directly to the
// target currency fails due to a ConversionNotFoundError, it attempts an intermediate conversion
// through USD. Returns the converted value or an error if conversion fails.
func (a *adapter) convertCurrency(value float64, cur string, reqInfo *adapters.ExtraRequestInfo) (float64, error) {
convertedValue, err := reqInfo.ConvertCurrency(value, cur, a.extraInfo.TargetCurrency)

if err != nil {
var convErr prebidcurrency.ConversionNotFoundError
if !errors.As(err, &convErr) {
return 0, err
}

// try again by first converting to USD
// then convert to target_currency
convertedValue, err = reqInfo.ConvertCurrency(value, cur, "USD")

if err != nil {
return 0, fmt.Errorf("Currency conversion rate not found from '%s' to '%s'. Error converting from '%s' to 'USD': %w", cur, a.extraInfo.TargetCurrency, cur, err)
}

convertedValue, err = reqInfo.ConvertCurrency(convertedValue, "USD", a.extraInfo.TargetCurrency)

if err != nil {
return 0, fmt.Errorf("Currency conversion rate not found from '%s' to '%s'. Error converting from 'USD' to '%s': %w", cur, a.extraInfo.TargetCurrency, a.extraInfo.TargetCurrency, err)
}
}
return convertedValue, nil
}

func (a *adapter) MakeBids(request *openrtb2.BidRequest, requestData *adapters.RequestData, responseData *adapters.ResponseData) (*adapters.BidderResponse, []error) {
if adapters.IsResponseStatusCodeNoContent(responseData) {
return nil, nil
}

if err := adapters.CheckResponseStatusCodeForErrors(responseData); err != nil {
return nil, []error{err}
}

var response openrtb2.BidResponse
if err := jsonutil.Unmarshal(responseData.Body, &response); err != nil {
return nil, []error{err}
}

bidResponse := adapters.NewBidderResponseWithBidsCapacity(len(request.Imp))
bidResponse.Currency = response.Cur

var errs []error
for i := range response.SeatBid {
seatBid := &response.SeatBid[i]
for j := range seatBid.Bid {
bid := &seatBid.Bid[j]
bidType, err := getBidType(bid.MType)
if err != nil {
errs = append(errs, err)
continue
}
bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{
Bid: bid,
BidType: bidType,
})
}
}

return bidResponse, errs
}

func getBidType(markupType openrtb2.MarkupType) (openrtb_ext.BidType, error) {
switch markupType {
case openrtb2.MarkupNative:
return openrtb_ext.BidTypeNative, nil
case openrtb2.MarkupBanner:
return openrtb_ext.BidTypeBanner, nil
default:
return "", &errortypes.BadServerResponse{
Message: fmt.Sprintf("Unknown markup type: %d", markupType),
}
}
}
65 changes: 65 additions & 0 deletions adapters/aduptech/aduptech_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package aduptech

import (
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/prebid/prebid-server/v3/adapters/adapterstest"
"github.com/prebid/prebid-server/v3/config"
"github.com/prebid/prebid-server/v3/openrtb_ext"
)

func TestJsonSamples(t *testing.T) {
bidder, buildErr := Builder(
openrtb_ext.BidderAdUpTech,
config.Adapter{
Endpoint: "https://example.com/rtb/bid",
ExtraAdapterInfo: `{"target_currency": "EUR"}`,
},
config.Server{
ExternalUrl: "http://hosturl.com",
GvlID: 1,
DataCenter: "2",
},
)

require.NoError(t, buildErr, "Builder returned unexpected error")

adapterstest.RunJSONBidderTest(t, "aduptechtest", bidder)
}

func TestInvalidExtraAdapterInfo(t *testing.T) {
_, buildErr := Builder(
openrtb_ext.BidderAdUpTech,
config.Adapter{
Endpoint: "https://example.com/rtb/bid",
ExtraAdapterInfo: `{"foo": "bar"}`,
},
config.Server{
ExternalUrl: "http://hosturl.com",
GvlID: 1,
DataCenter: "2",
},
)

assert.EqualError(t, buildErr, "invalid extra info: TargetCurrency is empty, pls check")
}

func TestInvalidTargetCurrency(t *testing.T) {
_, buildErr := Builder(
openrtb_ext.BidderAdUpTech,
config.Adapter{
Endpoint: "https://example.com/rtb/bid",
ExtraAdapterInfo: `{"target_currency": "INVALID"}`,
},
config.Server{
ExternalUrl: "http://hosturl.com",
GvlID: 1,
DataCenter: "2",
},
)

assert.EqualError(t, buildErr, "invalid extra info: invalid TargetCurrency INVALID, pls check")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
{
"mockBidRequest": {
"id": "test-request-id",
"site": {
"page": "https://good.site/url"
},
"imp": [{
"id": "test-imp-id",
"bidfloor": 1.0,
"bidfloorcur": "AUD",
"banner": {
"format": [{
"w": 300,
"h": 250
}]
},
"ext": {
"bidder": {
"publisher": "123456",
"placement": "234567"
}
}
}],
"ext": {
"prebid": {
"currency": {
"rates": {
"EUR": {
"USD": 0.05
},
"USD": {
"AUD": 2.0
}
},
"usepbsrates": false
}
}
}
},
"httpCalls": [{
"expectedRequest": {
"uri": "https://example.com/rtb/bid",
"body": {
"id": "test-request-id",
"site": {
"page": "https://good.site/url"
},
"imp": [
{
"id": "test-imp-id",
"bidfloor": 10,
"bidfloorcur": "EUR",
"banner": {
"format": [
{
"w": 300,
"h": 250
}
]
},
"ext": {
"bidder": {
"publisher": "123456",
"placement": "234567"
}
}
}
],
"ext": {
"prebid": {
"currency": {
"rates": {
"EUR": {
"USD": 0.05
},
"USD": {
"AUD": 2.0
}
},
"usepbsrates": false
}
}
}
},
"impIDs":["test-imp-id"]
},
"mockResponse": {
"status": 200,
"body": {
"id": "test-request-id",
"seatbid": [
{
"seat": "958",
"bid": [{
"id": "7706636740145184841",
"impid": "test-imp-id",
"price": 0.500000,
"adm": "some-test-ad",
"adomain": ["example.com"],
"crid": "29681110",
"h": 250,
"w": 300,
"mtype": 1
}]
}
],
"cur": "EUR"
}
}
}],

"expectedBidResponses": [{
"currency": "EUR",
"bids": [{
"bid": {
"id": "7706636740145184841",
"impid": "test-imp-id",
"price": 0.500000,
"adm": "some-test-ad",
"adomain": ["example.com"],
"crid": "29681110",
"h": 250,
"w": 300,
"mtype": 1
},
"type": "banner"
}]
}]
}
Loading

0 comments on commit 502a438

Please sign in to comment.