@textback/notification-widget
Version:
TODO: Give a short introduction of your project. Let this section explain the objectives or the motivation behind this project.
203 lines (171 loc) • 6.18 kB
JavaScript
import UUID from 'uuid-js';
import assign from 'lodash/assign';
import apiErrorHandler from '../utils/apiErrorHandler.js';
import loadConfig from '../utils/loadConfig.js';
import loadDeepLink from '../utils/loadDeepLink.js';
import loadSubscriptions from '../utils/loadSubscriptions.js';
import cookies from '../utils/cookies.js';
import constants from '../utils/constants.js';
import parseQueryString from '../utils/parseQueryString.js';
import find from '../utils/find.js';
import appInsights from '../utils/appInsights.js';
import channelsFactory from '../channels/factory.js';
const INITIAL_CONFIG_DEFAULTS = {
apiPath: 'https://api.textback.io/api',
};
export default class Widget {
constructor(config, sdk) {
this.initialConfig = assign({}, INITIAL_CONFIG_DEFAULTS, config);
this.sdk = sdk;
this.config = {};
this.channels = [];
this.initialized = false;
this.initPromise = null;
this.id = this.initialConfig.widgetId;
this.widgetUserId = Widget.getWidgetUserId();
this.insecureContext = Widget.createInsecureContext(this.initialConfig.insecureContext);
this.secureContextToken = this.initialConfig.secureContextToken;
}
getConfig() {
return this.config;
}
initialize() {
this.initPromise = Promise.all([
this.initializeConfig(),
loadSubscriptions(this.widgetUserId, this.initialConfig.widgetId, this.initialConfig.apiPath),
]).then(([config, subscriptions]) => {
this.config = config.$value;
this.subscriptions = subscriptions.$items;
this.useVKApi = this.config.type === constants.WIDGET_TYPE_API_CALL;
this.aiKey = Widget.getAiKey(config);
let customDeeplinkData = this.config.channels.filter(
c => c.hasOwnProperty('additionalProperties') && c.additionalProperties.hasOwnProperty('customDeeplinkValue')
).filter(
c => c.channel === 'whatsapp' || c.channel === 'whatsappb'
).filter(
c => c.enabled
).map(
({additionalProperties, channel, channelId}) => {
return {
channel: channel,
channelId: channelId,
customDeeplinkValue: additionalProperties.customDeeplinkValue
};
}
);
let deeplinkData = {
accountId: this.config.accountId,
insecureContext: this.insecureContext,
widgetId: this.config.id,
secureContextToken: this.secureContextToken,
user: {
id: this.widgetUserId
}
};
if(customDeeplinkData.length > 0) {
deeplinkData.customDeeplinkValue = customDeeplinkData;
}
return Promise.all([
loadDeepLink(
this.initialConfig.apiPath,
deeplinkData
),
appInsights.init(this.aiKey, this.widgetUserId, this.config.accountId)
]);
}).then(([deeplink, ai]) => {
this.deeplink = `subscribe_${deeplink.$value.id}`;
this.channels = this.config.channels.map(channel => channelsFactory.create(channel, this.deeplink, this))
.filter(channel => !!channel);
const channelInitPromises = this.channels.filter(
channel => !!channel.initPromise
).map(
channel => channel.initPromise
);
return Promise.all(channelInitPromises);
}).then(channelPromises => {
return this;
}, err => {
appInsights.trackWidgetEvent(this.config.id, 'Widget.initialize.error', err);
return Promise.reject(err);
});
return this.initPromise;
}
initializeConfig() {
let promise;
if (!this.initialConfig.overrideConfig) {
promise = loadConfig(this.initialConfig.widgetId, this.initialConfig.apiPath);
} else {
promise = Promise.resolve({ $value: this.initialConfig.overrideConfig });
}
return promise;
}
subscribe(channelCode) {
const channel = find(this.getEnabledChannels(), chan => chan.channel === channelCode);
if (channel) {
channel.subscribe();
}
}
getChannels() {
return this.channels;
}
getEnabledChannels() {
return this.channels.filter(channel => channel.enabled && !channel.hasError);
}
runWahunter(phoneNumber, sendPersonalType, sendMarketingType) {
const body = {
notificationWidgetId: this.initialConfig.widgetId,
phone: phoneNumber,
insecureContext: this.insecureContext,
deeplinkId: this.deeplink,
consentsGranted: [],
};
if (sendPersonalType) {
body.consentsGranted.push({type: 'personal'})
}
if (sendMarketingType) {
body.consentsGranted.push({type: 'marketing'})
}
return fetch(`${this.initialConfig.apiPath}/wahunter`, {
method: 'POST',
headers: {
'Content-Type': 'application/json;charset=utf-8'
},
body: JSON.stringify(body),
}).then((resp) => {
if (resp.ok) {
cookies.setCookie(`${constants.COOKIE_NAME_PREFIX + this.id}_wahunter_was_run`, true, this.config.showWidgetSetting.showSessionLength * 60);
} else {
return Promise.reject(resp);
}
})
}
static getWidgetUserId() {
let widgetUserId = cookies.getCookie(constants.COOKIE_WIDGET_USER_ID);
if (widgetUserId === null) {
let uuid = UUID.create(4);
widgetUserId = uuid.hex;
cookies.setCookie(constants.COOKIE_WIDGET_USER_ID, widgetUserId, constants.WIDGET_USER_ID_COOKIE_TTL);
}
return widgetUserId;
}
static createInsecureContext(insecureContext = {}) {
const ctx = assign({}, insecureContext);//Object.assign({}, insecureContext);
ctx.pageTitle = window.document.title;
ctx.pageUrl = window.location.protocol + '//' + window.location.host + window.location.pathname;
ctx.params = parseQueryString(window.location.search.substring(1));
ctx.timezoneOffset = new Date().getTimezoneOffset();
ctx.cookies = cookies.getCookieObject();
const roistatVisitCookie = cookies.getCookie("roistat_visit");
if (roistatVisitCookie) {
ctx.roistatVisit = roistatVisitCookie;
}
return ctx;
}
static getAiKey(config) {
let aiKey = undefined;
try {
aiKey = config.headers.get('X-TB-AIKEY');
} catch (e) { }
return aiKey;
}
}