import Auth from "./managers/auth";
import Http from "./http";
import {Storage} from "./storage";
import BanInfo from "./models/BanInfo";
import AuthResponse from "./models/AuthResponse";
import Thrift from "./_thrift";
import "./thrift/Hades";
import "./thrift/exceptions_types";
import CurrentUser from './CurrentUser';
window.Thrift = Thrift;
/**
* @class GetSocial
*/
export default class GetSocial {
/**
* Initializes the SDK.
*
* @memberof GetSocial
* @param {Object} config
* @param {string} config.appId - GetSocial App ID
* @param {string} config.appName - App Name
* @param {string} [config.appVersion] - App Version
* @param {string} [config.language="en"] - SDK language
* @returns {Promise<AuthResponse|null>} Promise with the authenticated user and referral information (if any)
*/
static init (config) {
GetSocial._config = config || {};
GetSocial._baseUrl = GetSocial._config.baseUrl || SERVICE_URL;
// Smart Invites service url.
//
// Smart Banners and Smart Widget work directly from SI,
// they are not part of the HTTP API.
GetSocial._siUrl = GetSocial._config.siUrl || SI_URL;
GetSocial._http = Http;
GetSocial._sessionId = "";
GetSocial._appId = GetSocial._config.appId;
// Store click ID, if any.
let cid = GetSocial.getQueryParam("_gs_cid");
if (cid !== "") {
GetSocial._cid = cid;
Storage.storeClickID(cid);
}
// Set super properties to be used in some requests
const nav = window.navigator || {};
let tz = (new Date()).getTimezoneOffset() * -1 / 60 * 100;
tz = Math.abs(tz) < 1000
? (tz < 0
? `-0${Math.abs(tz)}`
: `+0${tz}`)
: (tz < 0
? tz
: `+${tz}`);
GetSocial.superProps = new THSuperProperties({
appName: config.appName || null,
appVersionPublic: config.appVersion || null,
sdkVersion: '7.12.7',
sdkLanguage: config.language || 'en',
deviceTimezone: 'GMT' + tz,
deviceOs: THDeviceOs.WEB_DESKTOP,
deviceOsVersion: nav.appVersion,
deviceLanguage: nav.language,
deviceModel: nav.platform
})
// Init Hades Client
let transport = new Thrift.TXHRTransport(HADES_URL);
let protocol = new Thrift.TJSONProtocol(transport);
GetSocial._hades = new HadesClient(protocol);
GetSocial._initialized = true;
const auth = Storage.getAuth();
if (!auth || !auth.sessionId ||
!auth.expiresAt || auth.expiresAt < new Date()) {
if (GetSocial.onInitListener) {
GetSocial.onInitListener();
}
Auth.logout();
return Promise.resolve(null);
} else {
GetSocial.onAuth(auth, Storage.getProviders());
return GetSocial.getCurrentUser().refresh()
.then(() => {
// Process app open if click ID is set
if (cid) {
return GetSocial.request(
'processAppOpen',
new THProcessAppOpenRequest({
referrerData: {
[THAppOpenSource.API]: {
[THAppOpenKey.Url]: cid
}
}
})
).then((tokenInfo) => {
// Persist referral data
GetSocial._referral = tokenInfo;
return {
user: GetSocial.getCurrentUser(),
referral: tokenInfo
}
});
} else {
return {
user: GetSocial.getCurrentUser(),
referral: null
}
}
})
.catch((e) => {
console.error(e);
Auth.logout();
return null;
})
.finally(() => {
if (GetSocial.onInitListener) {
GetSocial.onInitListener();
}
});
}
}
/**
* Initializes the SDK.
*
* @memberof GetSocial
* @param {string} appId - GetSocial App ID
* @returns {Promise<AuthResponse|null>} Promise with the authenticated user and referral information (if any)
*/
static initWithAppId(appId) {
return GetSocial.init({ appId });
}
/**
* Notifies callers when SDK finished initialization.
*
* @memberof GetSocial
* @param {function} onInit - Function to be invoked.
*/
static addOnInitializedListener(onInit) {
GetSocial.onInitListener = onInit || null;
}
/**
* Returns if SDK is initialized or not.
*
* @memberof GetSocial
* @return {boolean} true, if initialized, otherwise false.
*/
static isInitialized() {
return GetSocial._initialized;
}
/**
* Returns current language of GetSocial plugin.
*
* @memberof GetSocial
* @return {string} currently used language.
*/
static getLanguage() {
return GetSocial.superProps
? GetSocial.superProps.sdkLanguage
: 'en';
}
/**
* Sets the language of GetSocial plugin.
* If provided value is incorrect, sets the default language.
*
* @memberof GetSocial
* @param {string} language
* @return {Promise<string>} language code or error
*/
static setLanguage(language) {
if (!GetSocial.superProps) {
GetSocial.superProps = new THSuperProperties();
}
GetSocial.superProps.sdkLanguage = language;
const idt = Storage.getIdentity();
if (idt) {
// Re-authenticate user to update sdkLanguage in session
return Auth.authenticate({
identity_type: idt.providerId,
token: idt.accessToken
})
.then(() => GetSocial.superProps.sdkLanguage);
} else {
return Promise.resolve(GetSocial.superProps.sdkLanguage);
}
}
/**
* Returns version of GetSocial SDK.
*
* @memberof GetSocial
* @return {string} : version as string.
*/
static getSdkVersion() {
return GetSocial.superProps
? GetSocial.superProps.sdkVersion
: null;
}
/**
* Current user.
*
* @memberof GetSocial
* @return {CurrentUser} current user or null if SDK is not initialized.
*/
static getCurrentUser() {
return GetSocial._currentUser || null;
}
/**
* Makes an HTTP request to the API using the Hades client.
*
* @ignore
* @memberof GetSocial
* @param {string} endpoint - Method defined on Hades client, e.g <code>/authenticateSdk</code>
* @param {object} parameters - Parameters to pass onto the endpoint
* @return {Promise} - Promise from Hades client
*/
static request(endpoint, ...parameters) {
const guestEndpoints = [
'authenticateSdkAllInOne'
];
if (guestEndpoints.indexOf(endpoint) < 0) {
if (!GetSocial._sessionId) {
return Promise.reject(new Error('User not authenticated'));
} else if (parameters[0] && parameters[0].sessionId !== undefined) {
parameters[0].sessionId = GetSocial._sessionId;
} else {
parameters.unshift(GetSocial._sessionId);
}
}
if (!GetSocial._hades) {
return Promise.reject(new Error('SDK not initalized'));
}
if (!GetSocial._hades[endpoint]) {
return Promise.reject(new Error('Endpoint doesn\'t exist'));
}
return new Promise ((resolve, reject) => {
GetSocial._hades[endpoint].apply(GetSocial._hades, parameters)
.then(resolve)
.catch((res) => {
if (res.errors && Array.isArray(res.errors)) {
res.errors = res.errors.pop();
}
if (res.errors &&
res.errors.errorCode === THErrorCode.InvalidSession) {
// Logout
Auth.logout();
if (Storage.getIdentity()) {
// Try to reauthenticate
const params = Storage.getIdentity().getParams();
Auth.authenticate(params)
.then(() => {
// Attempt to make the request again
GetSocial.request(endpoint, parameters)
.then(resolve, reject);
})
.catch(reject);
} else {
reject(new Error('User not authenticated'));
}
} else {
reject(res && res.errors
? res.errors
: res);
}
})
});
}
/**
* Makes an HTTP request to the given API path with the given options.
*
* @ignore
* @param {string} path - Request URI, e.g <code>/authenticate/user</code>
* @param {object} options - Request options like method, query params etc.
* @return {Promise<Http>|undefined} - Promise of an XMLHttpRequest.
*/
static rawRequest(path, options) {
options = options || {};
options.method = options.method || "GET";
let uri;
try {
uri = new URL(options.url || options.isSI ? `${GetSocial._siUrl}${path}` : `${GetSocial._baseUrl}${path}`);
} catch (e) {
console.log(e);
return;
}
if (GetSocial._accessToken !== "") {
options.accessToken = GetSocial._accessToken;
}
if (typeof options.queryParams === "object") {
/** @var {Object} options.queryParams */
for (let key in options.queryParams) {
if (options.queryParams.hasOwnProperty(key)) {
uri.searchParams.set(key, options.queryParams[key]);
}
}
}
if (options.useAppId) {
uri.searchParams.set("app_id", GetSocial._appId);
}
options.url = uri.toString();
return GetSocial._http(options);
}
/**
* Returns the query string parameter with the given name, or an empty string.
*
* @ignore
* @param {string} name - Name of the parameter
* @return {string}
*/
static getQueryParam(name) {
name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]');
const regex = new RegExp('[\\?&]' + name + '=([^&#]*)');
const results = regex.exec(window.location.href);
return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' '));
}
/**
* Sets the User's session ID to the given value.
*
* @ignore
* @param {string} sessionId
*/
static setSessionId(sessionId) {
GetSocial._sessionId = sessionId;
}
/**
* Set internal props related to auth and providers
*
* @ignore
*/
static onAuth(auth, inviteProviders) {
const user = auth.user;
GetSocial._sessionId = auth.sessionId;
GetSocial._banInfo = user.internalPrivateProperties.ban_expiry
? new BanInfo({
expiration: user.internalPrivateProperties.ban_expiry,
reason: user.internalPrivateProperties.ban_reason
})
: null;
GetSocial._currentUser = CurrentUser.create({
...user,
verified: user.internalPublicProperties &&
!!user.internalPublicProperties.verified
});
GetSocial._defaultInviteContent = inviteProviders
.defaultInviteContent;
GetSocial._inviteProviders = inviteProviders.providers;
GetSocial._appInfo = auth.applicationInfo;
GetSocial._uploadEndpoint = auth.uploadEndpoint;
GetSocial._uploadChunkSize = auth.uploadChunkSize;
GetSocial._uploadFileSizeLimit = auth.uploadFileSizeLimit;
}
}