Created
January 13, 2025 02:11
-
-
Save Jonghakseo/019864751290ce43663d325b026083a4 to your computer and use it in GitHub Desktop.
Zendesk chatbot sdk AI로 난독화 제거
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(() => { | |
// Module definitions | |
var moduleCache, | |
moduleExports, | |
moduleDefinitions = { | |
271: (module) => { | |
function getQueryParamsString(url) { | |
const link = document.createElement('a'); | |
link.href = url; | |
return link.search.split('?').at(1) || ''; | |
} | |
module.exports = { | |
getQueryParamsString: getQueryParamsString, | |
parseUrlParams: function (url) { | |
const queryString = getQueryParamsString(url); | |
return queryString === '' | |
? {} | |
: queryString.split('&').reduce((params, paramString) => { | |
const paramParts = paramString.split('='); | |
params[paramParts.at(0)] = decodeURIComponent(paramParts.at(1)); | |
return params; | |
}, {}); | |
}, | |
loadScript: function (src, callback = () => {}) { | |
const script = document.createElement('script'); | |
script.type = 'text/javascript'; | |
script.onerror = function () { | |
callback(new Error('Script failed to load')); | |
}; | |
script.readyState | |
? (script.onreadystatechange = function () { | |
if (script.readyState === 'loaded' || script.readyState === 'complete') { | |
script.onreadystatechange = null; | |
callback(); | |
} | |
}) | |
: (script.onload = function () { | |
callback(); | |
}); | |
script.src = src; | |
document.getElementsByTagName('head').at(0)?.appendChild(script); | |
}, | |
}; | |
}, | |
}, | |
moduleContainer = {}; | |
function requireModule(moduleId) { | |
var cachedModule = moduleContainer[moduleId]; | |
if (cachedModule !== undefined) { | |
return cachedModule.exports; | |
} | |
var newModule = (moduleContainer[moduleId] = { id: moduleId, loaded: false, exports: {} }); | |
moduleDefinitions[moduleId](newModule, newModule.exports, requireModule); | |
newModule.loaded = true; | |
return newModule.exports; | |
} | |
// Webpack bootstrap | |
requireModule.m = moduleDefinitions; | |
requireModule.d = (module, exports) => { | |
for (var key in exports) { | |
if (requireModule.o(exports, key) && !requireModule.o(module, key)) { | |
Object.defineProperty(module, key, { enumerable: true, get: exports[key] }); | |
} | |
} | |
}; | |
requireModule.f = {}; | |
requireModule.e = (chunkId) => | |
Promise.all( | |
Object.keys(requireModule.f).reduce((promises, key) => { | |
requireModule.f[key](chunkId, promises); | |
return promises; | |
}, []), | |
); | |
requireModule.u = (chunkId) => 'sentry-browser.min.js'; | |
requireModule.hmd = (module) => { | |
module = Object.create(module); | |
if (!module.children) { | |
module.children = []; | |
} | |
Object.defineProperty(module, 'exports', { | |
enumerable: true, | |
set: () => { | |
throw new Error( | |
'ES Modules may not assign module.exports or exports.*, Use ESM export syntax, instead: ' + | |
module.id, | |
); | |
}, | |
}); | |
return module; | |
}; | |
requireModule.o = (object, property) => Object.prototype.hasOwnProperty.call(object, property); | |
// Chunk loading | |
var chunkLoadingGlobal = (globalThis.zEWebpackACJsonp = globalThis.zEWebpackACJsonp || []); | |
function webpackJsonpCallback(parentChunkLoadingFunction, data) { | |
var [chunkIds, moreModules, runtime] = data; | |
var moduleId, | |
chunkId, | |
i = 0; | |
if (chunkIds.some((id) => ((moduleId = id), 0 !== moduleCache[moduleId]))) { | |
for (moduleId in moreModules) { | |
if (requireModule.o(moreModules, moduleId)) { | |
requireModule.m[moduleId] = moreModules[moduleId]; | |
} | |
} | |
if (runtime) { | |
var result = runtime(requireModule); | |
} | |
} | |
if (parentChunkLoadingFunction) { | |
parentChunkLoadingFunction(data); | |
} | |
for (; i < chunkIds.length; i++) { | |
chunkId = chunkIds.at(i); | |
if (requireModule.o(moduleCache, chunkId) && moduleCache[chunkId]) { | |
moduleCache[chunkId].at(0)(); | |
} | |
moduleCache[chunkId] = 0; | |
} | |
} | |
chunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0)); | |
chunkLoadingGlobal.push = webpackJsonpCallback.bind( | |
null, | |
chunkLoadingGlobal.push.bind(chunkLoadingGlobal), | |
); | |
// Zendesk Embeddable Product Loader | |
class EmbeddableProductError extends Error { | |
constructor(message = '', properties = {}, isUserError = false) { | |
super(message); | |
this.props = properties; | |
this.isUserError = isUserError; | |
this.fingerprint = message; | |
} | |
} | |
const productAssets = {}, | |
zopimAssets = {}, | |
productLoaders = {}; | |
class ProductIframe { | |
constructor(product, window) { | |
this.name = product.name; | |
this.id = product.id; | |
this.features = product.features; | |
this.bootstrap = product.bootstrap; | |
this.win = window; | |
this.doc = window.document; | |
} | |
ready() { | |
return new Promise((resolve, reject) => { | |
this.createIframeElement().then((iframe) => { | |
iframe.addEventListener('load', () => { | |
const { contentWindow } = iframe; | |
if (contentWindow && contentWindow.document) { | |
resolve(contentWindow.document); | |
} else { | |
reject(this.error()); | |
} | |
}); | |
iframe.src = 'about:blank'; | |
this.doc.body.appendChild(iframe); | |
}); | |
}); | |
} | |
injectMetadata(document, queue) { | |
if (document) { | |
document.zendesk = { | |
[this.name]: { | |
id: this.id, | |
features: this.features, | |
bootstrap: this.bootstrap, | |
}, | |
}; | |
Object.freeze(document.zendesk); | |
document.zEQueue = queue; | |
} | |
} | |
injectAssets(document, assets) { | |
if (!document) { | |
return; | |
} | |
const head = document.getElementsByTagName('head').at(0); | |
assets.scripts.forEach((script) => { | |
head.appendChild(this.createScriptElement(document, script.src)); | |
}); | |
} | |
parentDocumentReady() { | |
return new Promise((resolve, reject) => { | |
if (this.doc.readyState !== 'loading' && this.doc.body) { | |
resolve(); | |
} else { | |
this.doc.addEventListener('DOMContentLoaded', () => { | |
const { body } = this.doc; | |
body | |
? resolve() | |
: reject(new EmbeddableProductError('host page document.body not available')); | |
}); | |
} | |
}); | |
} | |
createIframeElement() { | |
return this.parentDocumentReady().then(() => { | |
const iframe = this.doc.createElement('iframe'); | |
iframe.dataset.product = this.name; | |
iframe.title = 'No content'; | |
iframe.role = 'presentation'; | |
iframe.tabIndex = -1; | |
iframe.allow = 'microphone *'; | |
iframe.setAttribute('aria-hidden', true); | |
iframe.style.cssText = 'width: 0; height: 0; border: 0; position: absolute; top: -9999px'; | |
return iframe; | |
}); | |
} | |
createScriptElement(document, src) { | |
if (!document) { | |
return null; | |
} | |
const script = document.createElement('script'); | |
script.type = 'text/javascript'; | |
script.src = src; | |
return script; | |
} | |
error() { | |
const properties = { product: this.name, id: this.id, features: this.features }; | |
return new EmbeddableProductError( | |
'iframe document not available to load product', | |
properties, | |
); | |
} | |
} | |
class ProductLoader { | |
constructor(product, window) { | |
this.product = product; | |
this.productIframe = new ProductIframe(this.product, window); | |
} | |
getProductAssets(forceReload = false) { | |
return forceReload ? zopimAssets[this.product.name].assets : this.product.assets; | |
} | |
load(assets, queue) { | |
return this.productIframe | |
.ready() | |
.then((document) => { | |
this.productIframe.injectMetadata(document, queue); | |
this.productIframe.injectAssets(document, assets); | |
}) | |
.catch(() => Promise.reject(this.loadProductError())); | |
} | |
loadProductError() { | |
const { name, id, features } = this.product; | |
return new EmbeddableProductError('failed to load product', { | |
product: name, | |
id: id, | |
features: features, | |
}); | |
} | |
} | |
var scriptUtils = requireModule(271); | |
class ZopimLoader { | |
constructor(zopimKey, window) { | |
this.zopimKey = zopimKey; | |
this.win = window; | |
this.doc = window.document; | |
} | |
getProductAssets() { | |
return { zopimSrc: `https://v2.zopim.com/w?${this.zopimKey}` }; | |
} | |
load(assets) { | |
return new Promise((resolve, reject) => { | |
try { | |
scriptUtils.loadScript(assets.zopimSrc); | |
resolve(); | |
} catch (error) { | |
reject(error); | |
} | |
}); | |
} | |
} | |
const versionStorageKey = '__zE_ac_version'; | |
class VersionManager { | |
constructor(window, snippetKey) { | |
this.version = this.getVersion(window); | |
this.baseUrl = `https://ekr.zdassets.com/compose/${snippetKey}`; | |
this.snippetKey = snippetKey; | |
} | |
resolveComposeUrl(forceReload = false) { | |
let url = this.baseUrl; | |
if (this.version) { | |
url += `?${this.getSerializedVersionQueryParam()}`; | |
this.displayWarning(); | |
} | |
return decodeURI(url); | |
} | |
displayWarning() { | |
console.warn(`You are loading ${this.version.name} version ${this.version.string}`); | |
} | |
getSerializedVersionQueryParam() { | |
return `${versionStorageKey}=${this.version.name}/${this.version.string}`; | |
} | |
getVersion(window) { | |
let versionString; | |
try { | |
versionString = window.localStorage.getItem('ZD-ac-version'); | |
} catch {} | |
const versionQuery = | |
scriptUtils.parseUrlParams(window.location.href)[versionStorageKey] || versionString; | |
if (versionQuery) { | |
const versionParts = versionQuery.split('/'); | |
if (this.validVersion(versionParts.at(1))) { | |
return { name: versionParts.at(0), string: versionParts.at(1) }; | |
} | |
} | |
return null; | |
} | |
validVersion(version) { | |
return version && /^\w+$/.test(version); | |
} | |
} | |
class ProductManager { | |
constructor(snippet) { | |
this.snippet = snippet; | |
} | |
getProducts(snippetKey, forceReload = false) { | |
return new Promise((resolve, reject) => { | |
const parentWindow = this.snippet.getParentWindow(); | |
if (forceReload) { | |
parentWindow.zEACLoaded = true; | |
parentWindow.$zopim ? resolve(zopimAssets.products) : resolve(productAssets.products); | |
} else { | |
const handleResponse = (response) => { | |
if (response.status === 200) { | |
response | |
.json() | |
.then(({ products }) => { | |
parentWindow.zEACLoaded = true; | |
resolve(products); | |
}) | |
.catch(() => reject(this.error(snippetKey))); | |
} else { | |
reject(this.error(snippetKey)); | |
} | |
}; | |
const composeUrl = new VersionManager(parentWindow, snippetKey).resolveComposeUrl(); | |
fetch(composeUrl) | |
.then(handleResponse) | |
.catch(() => reject(this.error(snippetKey))); | |
} | |
}); | |
} | |
loadProducts(products, forceReload = false) { | |
return products.map((productLoader) => { | |
const assets = productLoader.getProductAssets(forceReload); | |
return productLoader | |
.load(assets, this.snippet.getZEQueue()) | |
.catch((error) => Promise.reject(error)); | |
}); | |
} | |
getProductLoaders(products) { | |
const parentWindow = this.snippet.getParentWindow(); | |
return products.map((product) => | |
'zopim_chat' === product.name | |
? new ZopimLoader(product.id, parentWindow) | |
: new ProductLoader(product, parentWindow), | |
); | |
} | |
error(snippetKey) { | |
return new EmbeddableProductError('compose request failed', { key: snippetKey }); | |
} | |
} | |
class Snippet { | |
constructor(window) { | |
this.win = window; | |
this.doc = window.document; | |
} | |
getKey() { | |
return new Promise((resolve, reject) => | |
reject(new EmbeddableProductError('Key is missing from snippet', {}, true)), | |
); | |
} | |
getZEQueue() { | |
return null; | |
} | |
getParentWindow() { | |
return this.win; | |
} | |
} | |
class WebWidgetSnippet extends Snippet { | |
getKey() { | |
return new Promise((resolve, reject) => { | |
const { zendeskHost } = this.doc; | |
if (zendeskHost) { | |
if (this._isHostMapped(zendeskHost)) { | |
fetch(`https://${zendeskHost}/embeddable/zendesk_host`) | |
.then((response) => { | |
if (response.status === 200) { | |
response | |
.json() | |
.then(({ zendesk_host }) => { | |
resolve(`web_widget/${zendesk_host}`); | |
}) | |
.catch((error) => reject(new EmbeddableProductError(error.message))); | |
} else { | |
reject(new EmbeddableProductError('zendesk_host request failed')); | |
} | |
}) | |
.catch((error) => reject(new EmbeddableProductError(error.message))); | |
} else { | |
resolve(`web_widget/${zendeskHost}`); | |
} | |
} else { | |
reject(Error('Zendesk host is not defined')); | |
} | |
}); | |
} | |
getZEQueue() { | |
return this.doc.zEQueue; | |
} | |
getParentWindow() { | |
return this.win.parent; | |
} | |
_isHostMapped(host) { | |
return host.indexOf('.zendesk.com') === -1 && host.indexOf('.zendesk-staging.com') === -1; | |
} | |
} | |
class SnippetUtil { | |
static isSnippetPresent(window) { | |
return window.document.getElementById('ze-snippet'); | |
} | |
getKey() { | |
return new Promise((resolve, reject) => { | |
const script = this._getScript(this.win.zE); | |
if (script) { | |
const params = scriptUtils.parseUrlParams(script.src); | |
if (params && params.key) { | |
return resolve(params.key); | |
} | |
} | |
return reject(new EmbeddableProductError('Key is missing from snippet', {}, true)); | |
}); | |
} | |
getZEQueue() { | |
return this.win.zE._; | |
} | |
_getScript(zE) { | |
return SnippetUtil.isSnippetPresent(this.win) || (zE && zE.s ? zE.s : undefined); | |
} | |
} | |
class ZopimSnippet extends Snippet { | |
getKey() { | |
return new Promise((resolve) => | |
resolve( | |
`zopim_chat/${scriptUtils.getQueryParamsString(ZopimSnippet.getScriptSrc(this.win))}`, | |
), | |
); | |
} | |
static getScriptSrc(win) { | |
if (win.$zopim && win.$zopim.s) { | |
return win.$zopim.s.src; | |
} | |
const scripts = document.getElementsByTagName('script'); | |
const zopimRegex = /.*zopim.(com|net|org)\//; | |
let src; | |
for (let i = 0, len = scripts.length; i < len; i++) { | |
src = scripts.at(i)?.src || ''; | |
if (zopimRegex.test(src)) { | |
return src; | |
} | |
} | |
} | |
static isSnippetPresent(win) { | |
return !!ZopimSnippet.getScriptSrc(win); | |
} | |
} | |
let sentryClient = null; | |
const sentryConfig = { | |
autoSessionTracking: false, | |
enabled: | |
!window.zESettings || window.zESettings.errorReporting !== undefined | |
? Boolean(window.zESettings.errorReporting) | |
: true, | |
dsn: 'https://aba337625608d678c785a8649566e231@o4507427284123728.ingest.de.sentry.io/4507427362963540', | |
environment: 'production', | |
release: 'asset-composer@v79', | |
sampleRate: 0.001, | |
defaultIntegrations: false, | |
}; | |
const initSentryClient = () => | |
new Promise((resolve) => { | |
if (sentryClient) { | |
resolve(sentryClient); | |
} else { | |
requireModule | |
.e(996) | |
.then(requireModule.bind(null, 858)) | |
.then((sentry) => { | |
const { BrowserClient, makeFetchTransport, defaultStackParser, Hub, Integrations } = | |
sentry; | |
const client = new BrowserClient({ | |
...sentryConfig, | |
integrations: [ | |
new Integrations.InboundFilters(), | |
new Integrations.FunctionToString(), | |
new Integrations.HttpContext(), | |
], | |
transport: makeFetchTransport, | |
stackParser: defaultStackParser, | |
}); | |
sentryClient = new Hub(client); | |
resolve(sentryClient); | |
}); | |
} | |
}); | |
function reportError(error) { | |
if (error && error instanceof EmbeddableProductError) { | |
initSentryClient().then((client) => { | |
client.withScope((scope) => { | |
if (error.fingerprint) { | |
scope.setFingerprint(error.fingerprint); | |
} | |
scope.setLevel('warning'); | |
client.captureException(error.error); | |
}); | |
if (window.console && error.isUserError) { | |
window.console.error(error.message); | |
} | |
}); | |
} else { | |
initSentryClient().then((client) => { | |
client.captureException(error); | |
}); | |
} | |
} | |
(function () { | |
try { | |
if (typeof window.zE !== 'function') { | |
const zEStub = function () { | |
const callQueue = []; | |
const stubFn = function () { | |
callQueue.push(arguments); | |
}; | |
stubFn._ = callQueue; | |
stubFn.t = Date.now(); | |
return stubFn; | |
}; | |
window.zE = zEStub(); | |
window.zEmbed = window.zE; | |
} | |
if (window.zEACLoaded) { | |
return; | |
} | |
const snippet = (function (win) { | |
if (SnippetUtil.isSnippetPresent(win)) { | |
return new SnippetUtil(win); | |
} else if (win.document.zendeskHost && win.document.zEQueue) { | |
return new WebWidgetSnippet(win); | |
} else if (ZopimSnippet.isSnippetPresent(win)) { | |
return new ZopimSnippet(win); | |
} else { | |
return new SnippetUtil(win); | |
} | |
})(window); | |
const productManager = new ProductManager(snippet); | |
const forceReload = false; | |
snippet | |
.getKey() | |
.then((key) => productManager.getProducts(key, forceReload)) | |
.then((products) => { | |
if (products && products.length) { | |
return Promise.all( | |
productManager.loadProducts(productManager.getProductLoaders(products), forceReload), | |
); | |
} | |
}) | |
.catch((error) => reportError(error)); | |
} catch (error) { | |
reportError(error); | |
} | |
})(); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment