Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

77 feature request support for returning pause ads #86

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion api/Session.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const { VastBuilder } = require("../utils/vast-maker");
const { VmapBuilder } = require("../utils/vmap-maker");
const { v4: uuid } = require("uuid");
const constants = require("../utils/constants");
const { PauseAdVastBuilder } = require("../utils/pause-ad-vast-maker");

class Session {
// Public Fields
Expand All @@ -18,6 +19,7 @@ class Session {
#user;
#vastXml;
#vmapXml;
#pauseAdVast;
#eventTracker;

constructor(params) {
Expand All @@ -33,7 +35,16 @@ class Session {
this.#clientRequest = new ClientRequest(params);
this.#eventTracker = new EventTracker();

if (this.responseFormat === constants.RESPONSE_FORMATS.VMAP) {
if (this.responseFormat === constants.RESPONSE_FORMATS.PAUSE_AD) {
const pauseAdObj = PauseAdVastBuilder({
sessionId: this.sessionId,
adserverHostname: this.host,
width: params.width,
height: params.height,
version: params.v || null,
});
this.#pauseAdVast = pauseAdObj.xml;
} else if (this.responseFormat === constants.RESPONSE_FORMATS.VMAP) {
// Create VMAP object.
let vmapObj;
vmapObj = VmapBuilder({
Expand Down Expand Up @@ -74,6 +85,10 @@ class Session {
return this.#user.getUserId();
}

getPauseAdVast() {
return this.#pauseAdVast;
}

getXmlResponse() {
if (this.#vastXml) {
return this.getVastXml();
Expand Down
98 changes: 98 additions & 0 deletions api/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -657,6 +657,41 @@ const schemas = {
},
security: [{ apiKey: [] }],
},
"GET/pause-ad": {
description: "Send a VAST response for a Pause Ad and create a new session for the given User ID",
tags: ["vast"],
produces: ["application/xml"],
query: {
type: "object",
properties: {
uid: {
type: "string",
description: "User ID.",
example: "asbc-242-fsdv-123",
},
v: {
type: "string",
description: "VAST version to use. Default is 4. Supported values are 2, 3 and 4",
example: "4",
},
width: {
type: "integer",
description: "Width of the pause ad image. Default is 300.",
example: 400,
},
height: {
type: "integer",
description: "Height of the pause ad image. Default is 167.",
example: 225,
},
},
},
response: {
200: XmlResponseSchema("VAST"),
404: BadRequestSchema("Error creating VAST response for Pause Ad"),
},
security: [{ apiKey: [] }],
},
"GET/vmap": {
description:
"Send a VMAP response, then create a new session for the given User ID",
Expand Down Expand Up @@ -1181,6 +1216,69 @@ module.exports = (fastify, opt, next) => {
}
});

/**
* GET endpoint to retrieve VAST XML for Pause Ads.
*/
fastify.get("/pause-ad", { schema: schemas["GET/pause-ad"] }, async (req, reply) => {
try {
logger.info(req.query, {
label: req.headers["host"],
});
CloudWatchLog("PAUSE_AD_REQUESTED", req.headers["host"], {});

const params = Object.assign(req.query, {
acceptLang: req.headers["accept-language"] || "Not Found",
host: req.headers["host"],
userAgent: req.headers["user-agent"] || "Not Found",
uip: req.headers["x-forwarded-for"] || req.socket.remoteAddress || "Not Found",
rf: RESPONSE_FORMATS.PAUSE_AD,
width: req.query.width ? parseInt(req.query.width) : undefined,
height: req.query.height ? parseInt(req.query.height) : undefined,
});

const session = new Session(params);
const result = await DBAdapter.AddSessionToStorage(session);
if (!result) {
logger.error("Could not store new session", {
label: params.host,
sessionId: session.sessionId,
});
reply.code(404).send({
message: "Could not store new session",
});
return;
}

const pauseAdVast = session.getPauseAdVast();
if (!pauseAdVast) {
logger.error("Pause Ad VAST not found", {
label: params.host,
sessionId: session.sessionId,
});
reply.code(404).send({
message: "Pause Ad VAST not found",
});
return;
}

logger.info("Returned Pause Ad VAST and created a session", {
label: req.headers["host"],
sessionId: session.sessionId,
});
CloudWatchLog("PAUSE_AD_RETURNED", req.headers["host"], {
session: session.sessionId,
});

reply.header("Content-Type", "application/xml; charset=utf-8");
reply.code(200).send(pauseAdVast);
} catch (exc) {
logger.error(exc, {
label: req.headers["host"],
});
reply.code(500).send({ message: exc.message });
}
});

/**
* Planned to do two things:
* 1) Create and Send a VMAP response.
Expand Down
3 changes: 2 additions & 1 deletion utils/constants.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@

const RESPONSE_FORMATS = {
VMAP: "vmap1",
VAST: "vast4"
VAST: "vast4",
PAUSE_AD: "pause_ad"
}

const EMPTY_VAST_MSG = `.--------------- WARNING ---------------.
Expand Down
54 changes: 54 additions & 0 deletions utils/pause-ad-vast-maker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
const createVast = require('vast-builder');

function PauseAdVastBuilder(params) {
let vast = null;

switch (params.version) {
case "2":
vast = createVast.v2();
break;
case "3":
vast = createVast.v3();
break;
default:
vast = createVast.v4();
break;
}

const adId = vast.attrs.version === "4.0" ? "adId" : "adID";

// Use provided width and height, or default to 300x167
const width = params.width || 300;
const height = params.height || 167;

vast
.attachAd({ id: "pause-ad-1" })
.attachInLine()
.addAdSystem("Test Adserver")
.addAdTitle("Pause Ad")
.addImpression(`http://${params.adserverHostname}/api/v1/sessions/${params.sessionId}/tracking?${adId}=pause-ad&progress=vast`, { id: "pause-ad-impression-1" })
.attachCreatives()
.attachCreative({ id: "pause-ad-creative-1", [adId]: "pause-ad" })
.attachNonLinearAds()
.attachTrackingEvents()
.addTracking(`http://${params.adserverHostname}/api/v1/sessions/${params.sessionId}/tracking?${adId}=pause-ad&progress=0`, { event: "start" })
.addTracking(`http://${params.adserverHostname}/api/v1/sessions/${params.sessionId}/tracking?${adId}=pause-ad&progress=100`, { event: "complete" })
.addTracking(`http://${params.adserverHostname}/api/v1/sessions/${params.sessionId}/tracking?${adId}=pause-ad&event=pause`, { event: "pause" })
.and()
.attachNonLinear({
id: "pause-ad-1",
width: width,
height: height,
scalable: true,
maintainAspectRatio: true,
minSuggestedDuration: "00:00:05",
apiFramework: "static",
})
.addStaticResource("https://testcontent.eyevinn.technology/ads/STSWE_AD_001.jpg", {creativeType:"image/jpeg"})
.addNonLinearClickThrough("https://github.com/Eyevinn/test-adserver");

const vastXml = vast.toXml();
return { xml: vastXml };
}

module.exports = { PauseAdVastBuilder };
Loading