Skip to content

Commit

Permalink
Bigoad: Add bidder (#3328)
Browse files Browse the repository at this point in the history
  • Loading branch information
CTMBNara authored Jul 30, 2024
1 parent 101be17 commit 5c2c4d8
Show file tree
Hide file tree
Showing 20 changed files with 667 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ private static BidType getBidType(Integer mType) {
case 3 -> BidType.audio;
case 4 -> BidType.xNative;

default -> throw new PreBidException("Unsupported mType " + mType);
case null, default -> throw new PreBidException("Unsupported mType " + mType);
};
}
}
150 changes: 150 additions & 0 deletions src/main/java/org/prebid/server/bidder/bigoad/BigoadBidder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
package org.prebid.server.bidder.bigoad;

import com.fasterxml.jackson.core.type.TypeReference;
import com.iab.openrtb.request.BidRequest;
import com.iab.openrtb.request.Imp;
import com.iab.openrtb.response.Bid;
import com.iab.openrtb.response.BidResponse;
import com.iab.openrtb.response.SeatBid;
import io.vertx.core.MultiMap;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.prebid.server.bidder.Bidder;
import org.prebid.server.bidder.model.BidderBid;
import org.prebid.server.bidder.model.BidderCall;
import org.prebid.server.bidder.model.BidderError;
import org.prebid.server.bidder.model.HttpRequest;
import org.prebid.server.bidder.model.HttpResponse;
import org.prebid.server.bidder.model.Result;
import org.prebid.server.exception.PreBidException;
import org.prebid.server.json.DecodeException;
import org.prebid.server.json.JacksonMapper;
import org.prebid.server.proto.openrtb.ext.ExtPrebid;
import org.prebid.server.proto.openrtb.ext.request.bigoad.ExtImpBigoad;
import org.prebid.server.proto.openrtb.ext.response.BidType;
import org.prebid.server.util.BidderUtil;
import org.prebid.server.util.HttpUtil;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;

public class BigoadBidder implements Bidder<BidRequest> {

private static final TypeReference<ExtPrebid<?, ExtImpBigoad>> BIGOAD_EXT_TYPE_REFERENCE =
new TypeReference<>() {
};
private static final String SSP_ID_MACRO = "{{SspId}}";
private static final String OPEN_RTB_VERSION = "2.5";

private final String endpointUrl;
private final JacksonMapper mapper;

public BigoadBidder(String endpointUrl, JacksonMapper mapper) {
this.endpointUrl = HttpUtil.validateUrl(Objects.requireNonNull(endpointUrl));
this.mapper = Objects.requireNonNull(mapper);
}

@Override
public Result<List<HttpRequest<BidRequest>>> makeHttpRequests(BidRequest request) {
final List<Imp> modifiedImps = new ArrayList<>(request.getImp());

final Imp firstImp = modifiedImps.getFirst();
final ExtImpBigoad extImpBigoad;
try {
extImpBigoad = parseImpExt(firstImp);
} catch (PreBidException e) {
return Result.withError(BidderError.badInput(e.getMessage()));
}

modifiedImps.set(0, modifyImp(firstImp, extImpBigoad));
return Result.withValue(BidderUtil.defaultRequest(
updateBidRequest(request, modifiedImps),
headers(),
makeEndpointUrl(extImpBigoad),
mapper));
}

private ExtImpBigoad parseImpExt(Imp imp) throws PreBidException {
try {
return mapper.mapper().convertValue(imp.getExt(), BIGOAD_EXT_TYPE_REFERENCE).getBidder();
} catch (IllegalArgumentException e) {
throw new PreBidException("imp %s: unable to unmarshal ext.bidder: %s"
.formatted(imp.getId(), e.getMessage()));
}
}

private Imp modifyImp(Imp imp, ExtImpBigoad extImpBigoad) {
return imp.toBuilder().ext(mapper.mapper().valueToTree(extImpBigoad)).build();
}

private static BidRequest updateBidRequest(BidRequest bidRequest, List<Imp> imps) {
return bidRequest.toBuilder().imp(imps).build();
}

private static MultiMap headers() {
return HttpUtil.headers().add(HttpUtil.X_OPENRTB_VERSION_HEADER, OPEN_RTB_VERSION);
}

private String makeEndpointUrl(ExtImpBigoad extImpBigoadx) {
final String safeSspId = HttpUtil.encodeUrl(StringUtils.trimToEmpty(extImpBigoadx.getSspId()));
return endpointUrl.replace(SSP_ID_MACRO, safeSspId);
}

@Override
public Result<List<BidderBid>> makeBids(BidderCall<BidRequest> httpCall, BidRequest bidRequest) {
try {
final List<BidderError> errors = new ArrayList<>();
final BidResponse bidResponse = parseBidResponse(httpCall.getResponse());
return Result.of(extractBids(bidResponse, errors), errors);
} catch (PreBidException e) {
return Result.withError(BidderError.badServerResponse(e.getMessage()));
}
}

private BidResponse parseBidResponse(HttpResponse response) {
try {
return mapper.decodeValue(response.getBody(), BidResponse.class);
} catch (DecodeException e) {
throw new PreBidException("Bad server response: " + e.getMessage());
}
}

private static List<BidderBid> extractBids(BidResponse bidResponse, List<BidderError> errors) {
if (bidResponse == null || CollectionUtils.isEmpty(bidResponse.getSeatbid())) {
throw new PreBidException("Empty SeatBid array");
}

return bidResponse.getSeatbid().stream()
.filter(Objects::nonNull)
.map(SeatBid::getBid)
.filter(Objects::nonNull)
.flatMap(Collection::stream)
.filter(Objects::nonNull)
.map(bid -> makeBid(bid, bidResponse.getCur(), errors))
.filter(Objects::nonNull)
.toList();
}

private static BidderBid makeBid(Bid bid, String currency, List<BidderError> errors) {
final BidType bidType;
try {
bidType = resolveBidType(bid.getMtype(), bid.getImpid());
} catch (PreBidException e) {
errors.add(BidderError.badServerResponse(e.getMessage()));
return null;
}

return BidderBid.of(bid, bidType, currency);
}

private static BidType resolveBidType(Integer mType, String impId) {
return switch (mType) {
case 1 -> BidType.banner;
case 2 -> BidType.video;
case 4 -> BidType.xNative;
case null, default -> throw new PreBidException("unrecognized bid type in response from bigoad " + impId);
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,8 @@ private static BidType resolveBidType(Integer mType, String impId) {
case 2 -> BidType.video;
case 3 -> BidType.audio;
case 4 -> throw new PreBidException("native media types are not yet supported");
default -> throw new PreBidException("Failed to parse media type for bid: \"%s\"".formatted(impId));
case null, default ->
throw new PreBidException("Failed to parse media type for bid: \"%s\"".formatted(impId));
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -171,13 +171,13 @@ private static BidType getBidType(Bid bid, List<Imp> imps) {
}

private static Optional<BidType> getBidTypeFromMtype(Integer mType) {
final BidType bidType = mType != null ? switch (mType) {
final BidType bidType = switch (mType) {
case 1 -> BidType.banner;
case 2 -> BidType.video;
case 3 -> BidType.audio;
case 4 -> BidType.xNative;
default -> null;
} : null;
case null, default -> null;
};

return Optional.ofNullable(bidType);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ private static BidType getBidType(Bid bid) {
case 2 -> BidType.video;
case 3 -> BidType.audio;
case 4 -> BidType.xNative;
default -> throw new PreBidException(
case null, default -> throw new PreBidException(
"Unsupported mtype %d for impression with ID: \"%s\"".formatted(bid.getMtype(), bid.getImpid()));
};
}
Expand Down
6 changes: 3 additions & 3 deletions src/main/java/org/prebid/server/bidder/ix/IxBidder.java
Original file line number Diff line number Diff line change
Expand Up @@ -297,13 +297,13 @@ private static BidType getBidType(Bid bid, List<Imp> imps) {
}

private static Optional<BidType> getBidTypeFromMtype(Integer mType) {
final BidType bidType = mType != null ? switch (mType) {
final BidType bidType = switch (mType) {
case 1 -> BidType.banner;
case 2 -> BidType.video;
case 3 -> BidType.audio;
case 4 -> BidType.xNative;
default -> null;
} : null;
case null, default -> null;
};

return Optional.ofNullable(bidType);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public Result<List<HttpRequest<BidRequest>>> makeHttpRequests(BidRequest request
}

final List<Imp> modifiedImps = new ArrayList<>();
for (Imp imp: request.getImp()) {
for (Imp imp : request.getImp()) {
final Imp modifiedImp = imp.toBuilder().banner(modifyBanner(imp.getBanner())).build();
modifiedImps.add(modifiedImp);
}
Expand Down Expand Up @@ -195,11 +195,11 @@ private static BidType getBidType(Bid bid, List<Imp> imps) {
}

private static Optional<BidType> getBidTypeFromMtype(Integer mType) {
final BidType bidType = mType != null ? switch (mType) {
final BidType bidType = switch (mType) {
case 1 -> BidType.banner;
case 4 -> BidType.xNative;
default -> null;
} : null;
case null, default -> null;
};

return Optional.ofNullable(bidType);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ private static BidType getBidType(Integer mType) {
case 3 -> BidType.audio;
case 4 -> BidType.xNative;

default -> throw new PreBidException("Unsupported mType " + mType);
case null, default -> throw new PreBidException("Unsupported mType " + mType);
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ private static BidType getBidType(Integer mType) {
case 3 -> BidType.audio;
case 4 -> BidType.xNative;

default -> throw new PreBidException("Unsupported mType " + mType);
case null, default -> throw new PreBidException("Unsupported mType " + mType);
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.prebid.server.proto.openrtb.ext.request.bigoad;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Value;

@Value(staticConstructor = "of")
public class ExtImpBigoad {

@JsonProperty("sspid")
String sspId;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package org.prebid.server.spring.config.bidder;

import org.prebid.server.bidder.BidderDeps;
import org.prebid.server.bidder.bigoad.BigoadBidder;
import org.prebid.server.json.JacksonMapper;
import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties;
import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler;
import org.prebid.server.spring.config.bidder.util.UsersyncerCreator;
import org.prebid.server.spring.env.YamlPropertySourceFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

import jakarta.validation.constraints.NotBlank;

@Configuration
@PropertySource(value = "classpath:/bidder-config/bigoad.yaml", factory = YamlPropertySourceFactory.class)
public class BigoadConfiguration {

private static final String BIDDER_NAME = "bigoad";

@Bean("bigoadConfigurationProperties")
@ConfigurationProperties("adapters.bigoad")
BidderConfigurationProperties configurationProperties() {
return new BidderConfigurationProperties();
}

@Bean
BidderDeps bigoadBidderDeps(BidderConfigurationProperties bigoadConfigurationProperties,
@NotBlank @Value("${external-url}") String externalUrl,
JacksonMapper mapper) {

return BidderDepsAssembler.forBidder(BIDDER_NAME)
.withConfig(bigoadConfigurationProperties)
.usersyncerCreator(UsersyncerCreator.create(externalUrl))
.bidderCreator(config -> new BigoadBidder(config.getEndpoint(), mapper))
.assemble();
}
}
26 changes: 26 additions & 0 deletions src/main/resources/bidder-config/bigoad.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
adapters:
bigoad:
endpoint: https://api.imotech.tech/Ad/GetAdOut?sspid={{SspId}}
geoscope:
- USA
- RUS
- JPN
- BRA
- KOR
- IDN
- TUR
- SAU
- MEX
endpoint-compression: gzip
meta-info:
maintainer-email: [email protected]
app-media-types:
- banner
- video
- native
site-media-types:
- banner
- video
- native
supported-vendors:
vendor-id: 0
15 changes: 15 additions & 0 deletions src/main/resources/static/bidder-params/bigoad.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "BigoAd Adapter Params",
"description": "A schema which validates params accepted by the BigoAd adapter",
"type": "object",
"properties": {
"sspid": {
"type": "string",
"description": "Special id provided by BigoAd"
}
},
"required": [
"sspid"
]
}
Loading

0 comments on commit 5c2c4d8

Please sign in to comment.