@swrve/smarttv-sdk
Version:
Swrve marketing engagement platform SDK for SmartTV OTT devices
205 lines (183 loc) • 8.04 kB
text/typescript
import { IQueryParams } from "./IQueryParams";
import { ProfileManager } from "../Profile/ProfileManager";
import SwrveLogger from "../utils/SwrveLogger";
import { ISwrveInternalConfig } from "../Config/ISwrveInternalConfig";
import IResourceDiff from "../WebApi/Resources/IResourceDiff";
import IRestResponse from "./IRestResponse";
import { IPlatform } from "../utils/platforms/IPlatform";
import IEventBatch from "../WebApi/Events/IEventBatch";
import SwrveEvent from "../WebApi/Events/SwrveEvent";
import IIdentityParams from "../WebApi/Identity/IIdentityParams";
import IdentityResponse from "../WebApi/Identity/IIdentityResponse";
export class SwrveRestClient {
public readonly version: number = 3;
public readonly apiVersion: string = "8";
public readonly inAppVersion: string = "10";
public readonly embeddedVersion: string = "1";
public constructor(
private readonly config: ISwrveInternalConfig,
private readonly profileManager: ProfileManager,
private readonly platform: IPlatform,
) {}
public postEvents(events: ReadonlyArray<SwrveEvent>): Promise<Response | Error | void> {
const appId = this.config.appId;
const stack = this.config.stack === "us" ? "api" : "eu-api";
const url =
this.config.contentUrl == null ? `https://${appId}.${stack}.swrve.com/1/batch` : this.config.contentUrl;
const body: IEventBatch = {
user: this.profileManager.currentUser.userId,
app_version: this.config.appVersion,
session_token: this.profileManager.getSessionToken(),
version: this.version,
unique_device_id: this.platform.deviceID,
data: events,
};
return this.fetch(url, {
body: JSON.stringify(body),
cache: "no-cache",
method: "POST",
headers: {
"content-type": "application/json",
},
});
}
public getCampaignsAndResources(): Promise<any> {
const appId = this.config.appId;
const stack = this.config.stack === "us" ? "content" : "eu-content";
const url =
this.config.apiUrl == null ? `https://${appId}.${stack}.swrve.com/api/1/user_content?` : this.config.apiUrl;
const query = this.getQueryString(this.profileManager.currentUser.etag);
SwrveLogger.debug("campaignsAndResourcesUrl: " + url + query);
return this.fetch(url + query)
.then((response) => {
if (response && response.ok) {
return response.json().then((json) => ({
json,
etag: response.headers.get("ETag"),
}));
}
return response
.json()
.then((body: { message?: string; status?: number }) => {
const error = new Error(body?.message || "Request failed") as Error & {
status?: number | null;
body?: { message?: string; status?: number } | null;
};
error.status = response ? response.status : null;
error.body = body ?? null;
throw error;
})
.catch((error) => {
throw error;
});
})
.catch((error) => {
throw error;
});
}
public identify(externalUserId: string, swrveId: string): Promise<IdentityResponse> {
const appId = this.config.appId;
const stack = this.config.stack === "us" ? "identity" : "eu-identity";
const url =
this.config.identityUrl == null ? `https://${appId}.${stack}.swrve.com/identify` : this.config.identityUrl;
const body: IIdentityParams = {
api_key: this.config.apiKey,
swrve_id: swrveId,
external_user_id: externalUserId,
unique_device_id: this.platform.deviceID,
};
return this.fetch(url, {
body: JSON.stringify(body),
cache: "no-cache",
method: "POST",
headers: {
"Content-Type": "application/json",
},
})
.then((response) => {
if (response && response.ok) {
return response.json();
} else {
const theError = new Error(response.status.toString()) as Error & {
status?: number | null;
};
theError.status = response ? response.status : null;
throw theError;
}
})
.catch((error) => {
SwrveLogger.debug(String(error));
throw error;
});
}
public getUserResourcesDiff(): Promise<IRestResponse<ReadonlyArray<IResourceDiff>>> {
const appId = this.config.appId;
const stack = this.config.stack === "us" ? "content" : "eu-content";
const url =
this.config.apiUrl == null
? `https://${appId}.${stack}.swrve.com/api/1/user_resources_diff?`
: this.config.apiUrl;
const query = this.getQueryString();
SwrveLogger.info("url+query " + url + query);
return this.fetch(url + query).then((response) =>
response.json().then((json: ReadonlyArray<IResourceDiff>) => ({
json,
etag: response.headers.get("ETag"),
})),
);
}
public getQueryString(etag?: string): string {
const esc = encodeURIComponent;
const params: IQueryParams = this.getContentRequestParams();
const query = Object.keys(params)
.filter((key) => (<any>params)[key] != null)
.map((k) => esc(k) + "=" + esc((<any>params)[k]))
.join("&");
const etagParam = etag ? "&etag=" + etag : "";
const sessionToken = this.profileManager!.getSessionToken();
const sessionTokenParam = sessionToken ? "&session_token=" + sessionToken : "";
return query + etagParam + sessionTokenParam;
}
public getContentRequestParams(): IQueryParams {
const params: IQueryParams = {
api_key: this.config.apiKey,
user: this.profileManager.currentUser.userId,
app_version: this.config.appVersion,
joined: this.profileManager.currentUser.firstUse.toString(),
version: this.apiVersion,
in_app_version: this.inAppVersion,
embedded_campaign_version: this.embeddedVersion,
language: this.platform.language,
app_store: this.platform.appStore,
device_width: this.platform.screenWidth.toString(),
device_height: this.platform.screenHeight.toString(),
device_dpi: this.platform.screenDPI.toString(),
device_name: this.platform.deviceID,
device_type: "tv",
os: this.platform.os,
os_version: this.platform.osVersion,
orientation: "landscape",
};
return params;
}
public fetch(input: string | Request, init?: RequestInit): Promise<Response> {
const timeout = this.config.httpsTimeoutSeconds;
let controller: AbortController;
let signal;
if ("AbortController" in window) {
controller = new AbortController();
signal = controller.signal;
}
return Promise.race([
fetch(input, { ...init, signal }),
new Promise((_, reject) => {
setTimeout(() => {
reject(new Error("Request timeout after " + timeout + " seconds"));
if (controller) {
controller.abort();
}
}, timeout * 1000);
}) as Promise<Response>,
]);
}
}