11package org .prebid .server .bidder .sspbc ;
22
3- import com .fasterxml .jackson .core .type .TypeReference ;
4- import com .fasterxml .jackson .databind .JsonNode ;
5- import com .fasterxml .jackson .databind .node .ObjectNode ;
6- import com .iab .openrtb .request .Banner ;
73import com .iab .openrtb .request .BidRequest ;
8- import com .iab .openrtb .request .Format ;
9- import com .iab .openrtb .request .Imp ;
10- import com .iab .openrtb .request .Site ;
114import com .iab .openrtb .response .Bid ;
125import com .iab .openrtb .response .BidResponse ;
13- import com .iab .openrtb .response .SeatBid ;
146import org .apache .commons .collections4 .CollectionUtils ;
157import org .apache .commons .lang3 .StringUtils ;
168import org .apache .http .client .utils .URIBuilder ;
2012import org .prebid .server .bidder .model .BidderError ;
2113import org .prebid .server .bidder .model .HttpRequest ;
2214import org .prebid .server .bidder .model .Result ;
23- import org .prebid .server .bidder .sspbc .request .SspbcRequestType ;
2415import org .prebid .server .exception .PreBidException ;
2516import org .prebid .server .json .DecodeException ;
2617import org .prebid .server .json .JacksonMapper ;
27- import org .prebid .server .proto .openrtb .ext .ExtPrebid ;
28- import org .prebid .server .proto .openrtb .ext .request .sspbc .ExtImpSspbc ;
2918import org .prebid .server .proto .openrtb .ext .response .BidType ;
3019import org .prebid .server .util .BidderUtil ;
3120import org .prebid .server .util .HttpUtil ;
32- import org .prebid .server .util .ObjectUtil ;
3321
3422import java .net .URISyntaxException ;
35- import java .util .ArrayList ;
3623import java .util .Collections ;
37- import java .util .Comparator ;
3824import java .util .List ;
39- import java .util .Map ;
4025import java .util .Objects ;
41- import java .util .Optional ;
42- import java .util .function .Function ;
4326import java .util .function .UnaryOperator ;
44- import java .util .stream .Collectors ;
4527
4628public class SspbcBidder implements Bidder <BidRequest > {
4729
48- private static final TypeReference <ExtPrebid <?, ExtImpSspbc >> SSPBC_EXT_TYPE_REFERENCE =
49- new TypeReference <>() {
50- };
51- private static final String ADAPTER_VERSION = "5.8" ;
52- private static final String IMP_FALLBACK_SIZE = "1x1" ;
53- private static final String PREBID_SERVER_INTEGRATION_TYPE = "4" ;
54- private static final String BANNER_TEMPLATE = """
55- <html><head><title></title><meta charset="UTF-8"><meta name="viewport"\
56- content="width=device-width, initial-scale=1.0"><style> body { background-color:\
57- transparent; margin: 0; padding: 0; }</style><script> window.rekid = {{.SiteId}};\
58- window.slot = {{.SlotId}}; window.adlabel = '{{.AdLabel}}'; window.pubid = '{{.PubId}}';\
59- window.wp_sn = 'sspbc_go'; window.page = '{{.Page}}'; window.ref = '{{.Referer}}';\
60- window.mcad = {{.McAd}}; window.inver = '{{.Inver}}'; </script></head><body><div id="c"></div><script\
61- async crossorigin nomodule src="//std.wpcdn.pl/wpjslib/wpjslib-inline.js"\
62- id="wpjslib"></script><script async crossorigin type="module"\
63- src="//std.wpcdn.pl/wpjslib6/wpjslib-inline.js" id="wpjslib6"></script></body></html>""" ;
30+ private static final String ADAPTER_VERSION = "6.0" ;
6431
6532 private final String endpointUrl ;
6633 private final JacksonMapper mapper ;
6734
6835 public SspbcBidder (String endpointUrl , JacksonMapper mapper ) {
69- this .endpointUrl = HttpUtil .validateUrl (Objects .requireNonNull (endpointUrl ));
36+ this .endpointUrl = HttpUtil .validateUrlSyntax (Objects .requireNonNull (endpointUrl ));
7037 this .mapper = Objects .requireNonNull (mapper );
7138 }
7239
7340 @ Override
7441 public Result <List <HttpRequest <BidRequest >>> makeHttpRequests (BidRequest request ) {
75- if (request .getSite () == null ) {
76- return Result .withError (BidderError .badInput ("BidRequest.site not provided" ));
77- }
78-
79- final Map <Imp , ExtImpSspbc > impToExt ;
80-
81- try {
82- impToExt = createImpToExt (request );
83- } catch (PreBidException e ) {
84- return Result .withError (BidderError .badInput (e .getMessage ()));
85- }
86-
87- final SspbcRequestType requestType = getRequestType (impToExt );
88- final List <Imp > imps = new ArrayList <>();
89- String siteId = "" ;
90-
91- for (Imp imp : request .getImp ()) {
92- final ExtImpSspbc extImpSspbc = impToExt .get (imp );
93- final String extImpSspbcSiteId = extImpSspbc .getSiteId ();
94- if (StringUtils .isNotEmpty (extImpSspbcSiteId )) {
95- siteId = extImpSspbcSiteId ;
96- }
97-
98- imps .add (updateImp (imp , requestType , extImpSspbc ));
99- }
100-
10142 try {
102- return Result .withValue (createRequest (updateBidRequest ( request , imps , requestType , siteId ) ));
43+ return Result .withValue (createRequest (request ));
10344 } catch (PreBidException e ) {
10445 return Result .withError (BidderError .badInput (e .getMessage ()));
10546 }
10647 }
10748
108- private Map <Imp , ExtImpSspbc > createImpToExt (BidRequest request ) {
109- return request .getImp ()
110- .stream ()
111- .collect (Collectors .toMap (Function .identity (), this ::parseImpExt ));
112- }
113-
114- private ExtImpSspbc parseImpExt (Imp imp ) {
115- try {
116- return mapper .mapper ().convertValue (imp .getExt (), SSPBC_EXT_TYPE_REFERENCE ).getBidder ();
117- } catch (IllegalArgumentException e ) {
118- throw new PreBidException (e .getMessage ());
119- }
120- }
121-
122- private Imp updateImp (Imp imp , SspbcRequestType requestType , ExtImpSspbc extImpSspbc ) {
123- final String originalImpId = imp .getId ();
124-
125- return imp .toBuilder ()
126- .id (resolveImpId (originalImpId , extImpSspbc .getId (), requestType ))
127- .tagid (originalImpId )
128- .ext (createImpExt (imp ))
129- .build ();
130- }
131-
132- private String resolveImpId (String originalImpId , String extImpId , SspbcRequestType requestType ) {
133- return StringUtils .isNotEmpty (extImpId ) && requestType != SspbcRequestType .REQUEST_TYPE_ONE_CODE
134- ? extImpId
135- : originalImpId ;
136- }
137-
138- private ObjectNode createImpExt (Imp imp ) {
139- return mapper .mapper ().createObjectNode ()
140- .set ("data" , mapper .mapper ().createObjectNode ()
141- .put ("pbslot" , imp .getTagid ())
142- .put ("pbsize" , getImpSize (imp )));
143- }
144-
145- private BidRequest updateBidRequest (BidRequest bidRequest ,
146- List <Imp > imps ,
147- SspbcRequestType requestType ,
148- String siteId ) {
149-
150- return bidRequest .toBuilder ()
151- .imp (imps )
152- .site (updateSite (bidRequest .getSite (), requestType , siteId ))
153- .test (updateTest (requestType , bidRequest .getTest ()))
154- .build ();
155- }
156-
157- private Site updateSite (Site site , SspbcRequestType requestType , String siteId ) {
158- return site .toBuilder ()
159- .id (resolveSiteId (requestType , siteId ))
160- .domain (getUri (site .getPage ()).getHost ())
161- .build ();
162- }
163-
164- private static String resolveSiteId (SspbcRequestType requestType , String siteId ) {
165- return requestType == SspbcRequestType .REQUEST_TYPE_ONE_CODE || StringUtils .isBlank (siteId )
166- ? StringUtils .EMPTY
167- : siteId ;
168- }
169-
170- private static Integer updateTest (SspbcRequestType requestType , Integer test ) {
171- return requestType == SspbcRequestType .REQUEST_TYPE_TEST ? 1 : test ;
172- }
173-
174- private String getImpSize (Imp imp ) {
175- final List <Format > formats = ObjectUtil .getIfNotNull (imp .getBanner (), Banner ::getFormat );
176- if (CollectionUtils .isEmpty (formats )) {
177- return IMP_FALLBACK_SIZE ;
178- }
179-
180- return formats .stream ()
181- .max (Comparator .comparing (SspbcBidder ::formatToArea ))
182- .filter (format -> formatToArea (format ) > 0 )
183- .map (format -> String .format ("%dx%d" , format .getW (), format .getH ()))
184- .orElse (IMP_FALLBACK_SIZE );
185- }
186-
187- private static int formatToArea (Format format ) {
188- final Integer w = ObjectUtil .getIfNotNull (format , Format ::getW );
189- final Integer h = ObjectUtil .getIfNotNull (format , Format ::getH );
190-
191- return w != null && h != null ? w * h : 0 ;
192- }
193-
194- private SspbcRequestType getRequestType (Map <Imp , ExtImpSspbc > impToExt ) {
195- for (ExtImpSspbc extImpSspbc : impToExt .values ()) {
196- if (extImpSspbc .getTest () != 0 ) {
197- return SspbcRequestType .REQUEST_TYPE_TEST ;
198- }
199-
200- if (StringUtils .isAnyEmpty (extImpSspbc .getSiteId (), extImpSspbc .getId ())) {
201- return SspbcRequestType .REQUEST_TYPE_ONE_CODE ;
202- }
203- }
204-
205- return SspbcRequestType .REQUEST_TYPE_STANDARD ;
206- }
207-
20849 private HttpRequest <BidRequest > createRequest (BidRequest request ) {
20950 return BidderUtil .defaultRequest (request , updateUrl (getUri (endpointUrl )), mapper );
21051 }
@@ -222,7 +63,6 @@ private static URIBuilder getUri(String endpointUrl) {
22263 private String updateUrl (URIBuilder uriBuilder ) {
22364 return uriBuilder
22465 .addParameter ("bdver" , ADAPTER_VERSION )
225- .addParameter ("inver" , PREBID_SERVER_INTEGRATION_TYPE )
22666 .toString ();
22767 }
22868
@@ -246,72 +86,33 @@ private List<BidderBid> extractBids(BidResponse bidResponse, BidRequest bidReque
24686 .map (seatBid -> CollectionUtils .emptyIfNull (seatBid .getBid ())
24787 .stream ()
24888 .filter (Objects ::nonNull )
249- .map (bid -> toBidderBid (bid , seatBid .getSeat (), bidResponse .getCur (), bidRequest )))
89+ .map (bid -> toBidderBid (bid , seatBid .getSeat (), bidResponse .getCur ())
90+ ))
25091 .flatMap (UnaryOperator .identity ())
25192 .toList ();
25293 }
25394
254- private BidderBid toBidderBid (Bid bid , String seat , String currency , BidRequest bidRequest ) {
95+ private BidderBid toBidderBid (Bid bid , String seat , String currency ) {
25596 if (StringUtils .isEmpty (bid .getAdm ())) {
25697 throw new PreBidException ("Bid format is not supported" );
25798 }
25899
259- final ObjectNode bidExt = bid .getExt ();
260- final Bid updatedBid = bid .toBuilder ()
261- .impid (getImpTagId (bidRequest .getImp (), bid ))
262- .adm (createBannerAd (
263- bid ,
264- stringOrNull (bidExt , "adlabel" ),
265- stringOrNull (bidExt , "pubid" ),
266- stringOrNull (bidExt , "siteid" ),
267- stringOrNull (bidExt , "slotid" ),
268- seat ,
269- bidRequest ))
270- .build ();
271-
272- return BidderBid .of (updatedBid , BidType .banner , currency );
273- }
274-
275- private static String stringOrNull (ObjectNode bidExt , String property ) {
276- return Optional .ofNullable (bidExt )
277- .map (ext -> ext .get (property ))
278- .map (JsonNode ::asText )
279- .orElse (StringUtils .EMPTY );
280- }
281-
282- private static String getImpTagId (List <Imp > imps , Bid bid ) {
283- return imps .stream ()
284- .filter (imp -> Objects .equals (imp .getId (), bid .getImpid ()))
285- .map (Imp ::getTagid )
286- .findAny ()
287- .orElseThrow (() -> new PreBidException ("imp not found" ));
288- }
289-
290- private String createBannerAd (Bid bid ,
291- String adlabel ,
292- String pubid ,
293- String siteid ,
294- String slotid ,
295- String seat ,
296- BidRequest bidRequest ) {
297- if (bid .getAdm ().contains ("<!--preformatted-->" )) {
298- return bid .getAdm ();
100+ return BidderBid .of (bid , getBidType (bid ), currency );
101+ }
102+
103+ private BidType getBidType (Bid bid ) {
104+ switch (bid .getMtype ()) {
105+ case 1 :
106+ return BidType .banner ;
107+ case 2 :
108+ return BidType .video ;
109+ case 3 :
110+ return BidType .audio ;
111+ case 4 :
112+ return BidType .xNative ;
113+ default :
114+ throw new PreBidException ("Bid type not supported: %s." .formatted (bid .getMtype ()));
299115 }
300-
301- final ObjectNode mcad = mapper .mapper ().createObjectNode ()
302- .put ("id" , bidRequest .getId ())
303- .put ("seat" , seat )
304- .set ("seatbid" , mapper .mapper ()
305- .convertValue (SeatBid .builder ().bid (Collections .singletonList (bid )).build (), JsonNode .class ));
306-
307- return BANNER_TEMPLATE
308- .replace ("{{.SiteId}}" , siteid )
309- .replace ("{{.SlotId}}" , slotid )
310- .replace ("{{.AdLabel}}" , adlabel )
311- .replace ("{{.PubId}}" , pubid )
312- .replace ("{{.Page}}" , bidRequest .getSite ().getPage ())
313- .replace ("{{.Referer}}" , bidRequest .getSite ().getRef ())
314- .replace ("{{.McAd}}" , mcad .toString ())
315- .replace ("{{.Inver}}" , PREBID_SERVER_INTEGRATION_TYPE );
316116 }
117+
317118}
0 commit comments