// START TEMPLATING window.store = store; window.checkCookieExists = (cookieName) => { return document.cookie.includes(`${cookieName}=`); } function isMobile() { return /Mobi|Android/i.test(navigator.userAgent); } window.mobileRedirectionCheck = () => { if (isMobile()) { store.main.hideMessenger(); } } function renderTemplate(template, data) { // Replace variables like {{variable}} with their corresponding values in data template = template.replace(/{{\s*(\w+)\s*}}/g, (_, key) => { return data[key] || ''; }); // Handle v-if directives template = template.replace(/<(\w+)\s*v-if="([^"]+)"\s*>([\s\S]*?)<\/\1>/g, (_, tag, condition, truePart) => { // Evaluate the condition in the context of data const conditionValue = eval(condition.replace(/\b(\w+)\b/g, (match) => data[match] !== undefined ? data[match] : match)); // Replace variables with their values if (conditionValue) { // If the condition is true, render the v-if block return `<${tag}>${truePart}${tag}>`; } return ''; // If the condition is false, render nothing }); return template; } // store.isAuthenticated = checkCookieExists("PGXREGSITE_LOGIN"); // allows user to test authentication if they add &testAuth=1 onto the end of the url and refresh store.isAuthenticated = checkCookieExists("PGXREGSITE_LOGIN") || (window.location.href.includes('ivastudio.ai') && window.location.href.includes('testAuth=1')); const template = `${payload.settings.newConversationPlaceholder.code.html}`; payload.settings.newConversationPlaceholder.code.html = renderTemplate(template, { isAuthenticated: store.isAuthenticated }); store.main.setSettings(payload.settings); (() => { let lastData = checkCookieExists("PGXREGSITE_LOGIN"); setInterval(() => { let currentData = store.isAuthenticated = checkCookieExists("PGXREGSITE_LOGIN") || store.isAuthenticated; payload.settings.newConversationPlaceholder.code.html = renderTemplate(template, { isAuthenticated: store.isAuthenticated }); if (store.isAuthenticated && !isLiveChat()) { // disable store.main.disableMessengerInput(); // 2-26-2025 commented out so Travis can test user inputs in Dev only } if (currentData !== lastData) { lastData = currentData; store.main.setSettings(payload.settings); store.conversation.$reset(); store.conversationEvent.$reset(); store.main.setView("main"); } }, 1000); })(); // END TEMPLATING //VERSION 1.1 store.random = true; //console.log("payload", payload); const liveChatOnLaunch = payload.settings.chatOnlyMode == true; const closeBtns = payload.settings.desktopCloseBtn == true; if (closeBtns) { delete store.main.isCloseButtonVisible; payload.settings.desktopCloseBtn = false; } store.main.setSettings(payload.settings); const getCloseSVG = () => { return ``; }; const getMinimizeSVG = () => { return ''; }; const getCloseLiveChatSVG = () => { return ``; }; const addScript = (url, root, callback) => { const script = document.createElement("script"); script.type = "text/javascript"; script.src = url; script.onload = callback; root.appendChild(script); }; const addLink = (url, root) => { const link = document.createElement("link"); link.type = "text/css"; link.href = url; link.rel = "stylesheet"; root.appendChild(link); }; const waitForElm = function (selector) { return new Promise((resolve) => { const root = document.querySelector("body ivas-messenger-ui").shadowRoot; if (root.querySelector(selector)) return resolve(root.querySelector(selector)); const observer = new MutationObserver((mutations) => { if (root.querySelector(selector)) { resolve(root.querySelector(selector)); observer.disconnect(); } }); observer.observe(root, { childList: true, subtree: true, }); }); }; const injectStyle = () => { waitForElm("div.app").then((elem) => { elem.insertAdjacentHTML( "afterbegin", `` ); }); }; const sendLiveChatOnOff = (on) => { let input = on ? "Connecting to live chat" : "Live chat ended"; if (on && !store.main.conversationId) { store.conversationEvent.sendMessage({ input: input, metadata: { liveChat: on, nluSupressDefaultAnswer: true }, }); } else if (store.main.conversationId) { for (const webhook of payload.webhooks) { if (webhook.enabled) { axios({ method: 'post', url: webhook.url, data: { event: { conversationId: store.main.conversationId, input, external: true, metadata: { liveChat: on } } } }); } } } }; const delayLiveChatOnOff = (on, msDelay) => { setTimeout(() => { console.log("livechat startup"); sendLiveChatOnOff(on); }, msDelay); }; let typingTimeout; const TYPING_DELAY_MS = 500; const handleTyping = () => { clearTimeout(typingTimeout); typingTimeout = setTimeout(() => { console.log("TYPING"); console.log("store.main.conversationId"); console.log(store.main.conversationId); try { fetch("https://router.usw.ivastudio.ai/ProxyScript/run/66ce521b47ec88c50fb8adf4/current/userTyping", { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ "event": "TYPING", "sessionId": store.main.conversationId }), }); } catch (error) { console.log("something errored when sending typing event"); } }, TYPING_DELAY_MS); } const showHideLiveChat = (livechat) => { const root = document.querySelector("body ivas-messenger-ui").shadowRoot; const el = root.getElementById("livechat"); if (livechat === true) { waitForElm(".footer").then(() => { let textArea = root.querySelector(".footer textarea"); textArea.addEventListener("input", handleTyping); }); if (!el) { //store.main.enableMessengerInput(); // COMMENTING OUT THE FOLLOWING LINES TO HIDE END LIVE CHAT BUTTON PER CREDITS REQUEST // waitForElm(".footer").then((el) => { // const div = document.createElement("button"); // div.id = "livechat"; // div.setAttribute("aria-label", "End Live Chat"); // div.title = "End Live Chat"; // div.style.color = payload.settings.actionColor; // div.innerHTML = getCloseLiveChatSVG(); // div.style.paddingRight = "10px"; // div.onclick = () => { // sendLiveChatOnOff(false); // if (store.isAuthenticated) { // store.main.disableMessengerInput(); // } // store.conversationEvent.sendMessage("Live Chat Session ended. Can I help you with anything else?"); // //Add a chip titled "Live Chat" // div.remove(); // }; // el.appendChild(div); // }); } } else if (el) { // livechat == false el.remove(); } }; const isLiveChat = () => { let livechat = false; for (const [id, participant] of Object.entries(store.conversationEvent.participants)) { if (participant.type == "agent") livechat = true; } return livechat; }; const debugButtons = (liveChatOn) => { waitForElm(".footer").then((el) => { const div = document.createElement("button"); div.id = "debug"; div.setAttribute("aria-label", "Start Live Chat"); div.innerHTML = "Connect to live chat"; div.title = "Connect to live chat"; div.onclick = () => { store.conversationEvent.sendMessage({ input: "Connect to live chat", metadata: { liveChat: true }, }); }; el.parentNode.insertBefore(div, el.nextSibling); }); }; // state variables: connecting to live chat automatically in the messenger visibility event has a sequencing problem. It will get called before axios is loaded and error out. // This delays the live chat connect until after axios is loaded. let isAxiosLoaded = false; let awaitingConnect = false; addScript("https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js", document.head, () => { if (awaitingConnect) { awaitingConnect = false; delayLiveChatOnOff(true, 1500); } isAxiosLoaded = true; }); window.addEventListener("beforeunload", (event) => { // doesn't work if (liveChatOnLaunch && isLiveChat()) { sendLiveChatOnOff(false); } }); // update the state of livechat based on the participants. If there is an "agent" participant type, it's a live chat. vm.$watch( () => store.conversationEvent.participants, async (participants) => { try { showHideLiveChat(isLiveChat()); } catch (e) { console.error(e); } } ); vm.$watch( () => store.main.isMessengerVisible, async (isVisible) => { try { console.log("messenger visible =", isVisible, store.main.conversationId); if (isVisible == true) { const livechat = isLiveChat(); injectStyle(); showHideLiveChat(livechat); //debugButtons(livechat); if (closeBtns) { waitForElm(".app").then((el) => { const div = document.createElement("button"); div.id = "minimize"; div.title = "Minimize"; div.innerHTML = getMinimizeSVG(); div.onclick = () => { store.main.hideMessenger(); }; el.appendChild(div); }); waitForElm(".app").then((el) => { const div = document.createElement("button"); div.id = "close"; div.title = "Close"; div.innerHTML = getCloseSVG(); div.onclick = () => { //Added the following line and commented out the proceeding if statement at credit's request in order to ONLY minimize the UI when in live chat instead of closing the session store.main.hideMessenger(); // if (!isLiveChat() || window.confirm("Live Chat is running. Are you sure you want to close?")) { // store.main.hideMessenger(); // if (isLiveChat()) { // sendLiveChatOnOff(false); // } // //store.main.setNewUserSession(); // store.conversation.$reset(); // store.conversationEvent.$reset(); // store.main.setView("chat"); // store.main.setNewConversation(true); // } }; el.appendChild(div); }); } if (liveChatOnLaunch) { if (!livechat) { if (isAxiosLoaded === true) { delayLiveChatOnOff(true, 1500); } else { awaitingConnect = true; } } } } } catch (e) { console.error(e); } }, { deep: true, immediate: true } ); window.vm = vm; window.store = store; addScript("https://router.usw.ivastudio.ai/ProxyScript/run/66ce521b47ec88c50fb8adf4/current/adaptiveCardImplementation_64dbc87628bd839f69b0c962", document.head, () => { // Uncomment the following line to load the optional host config script // addScript('https://router.usw.ivastudio.ai/ProxyScript/run/66ce521b47ec88c50fb8adf4/current/adaptiveCardHostConfig_64dbc87628bd839f69b0c962', document.head); }); //supplemental code for feedback functionality including waitForElm lines // const waitForElm = function (selector) { // return new Promise((resolve) => { // const root = document.querySelector('body ivas-messenger-ui').shadowRoot; // if (root.querySelector(selector)) return resolve(root.querySelector(selector)); // const observer = new MutationObserver((mutations) => { // if (root.querySelector(selector)) { // resolve(root.querySelector(selector)); // observer.disconnect(); // } // }); // observer.observe(root, { // childList: true, // subtree: true // }); // }); // }; //END GENERAL ON ENGAGEMENT LOAD CODE //BEGIN FEEDBACK SPECIFIC CODE vm.$watch(() => store.conversationEvent.messages, async (value) => { value.forEach((message, index) => { if (message.sentBy.hasOwnProperty('type')) { if (localStorage.getItem(`feedback-${message._id}`) || message?.metadata?.feedbackable != true) { } else { window.showFeedback(message._id, message.conversationId, message?.metadata?.transactionId); } } }); }, { deep: true }); window.showFeedback = (id, conversationId, transactionId) => { waitForElm(`div#message-${id}`).then((wrap) => { try { // const wrap = document.querySelector("body > se-messenger").shadowRoot.querySelector("#se-messenger-app > div.se-messenger-frame > div > div.se-messenger-body > div"); const scrollToTop = () => { wrap.scrollTop = wrap.scrollHeight; }; let devWrap = wrap.querySelector(`div.feedback-wrap`); if (!devWrap) { devWrap = document.createElement('div'); devWrap.classList.add('feedback-wrap'); devWrap.innerHTML = `
`; wrap.parentElement.querySelector(`div#message-${id} > div`).after(devWrap); } devWrap.querySelector(`a#se-messenger-feedback-like-${id}`).onclick = (e) => { e.preventDefault(); console.log("like!"); devWrap.parentElement.removeChild(devWrap); send("LIKE"); } devWrap.querySelector(`a#se-messenger-feedback-dislike-${id}`).onclick = (e) => { e.preventDefault(); console.log("dislike!"); devWrap.parentElement.removeChild(devWrap); send("DISLIKE"); } wrap.parentElement.parentElement.parentElement.scrollTop = wrap.parentElement.parentElement.parentElement.scrollHeight; const send = (event) => { localStorage.setItem(`feedback-${id}`, true); //update DQ_URL with the URL of the LTS version of your feedback query fetch('https://router.usw.ivastudio.ai/DynamicQuery/run/66ce521b47ec88c50fb8adf4/current/Feedback_6529ac38d8f54e4b61bc0a99', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ "event": event, "_id": transactionId }), }); }; } catch (e) { console.log(e); } }); }; //END FEEDBACK CODE //Watcher to keep IVA Open When in LIVE CHAT vm.$watch(() => store.conversationEvent.messages, async (value) => { try { console.log("Msg received"); const livechat = isLiveChat(); if (livechat) { if (!store.main.isMessengerVisible) { store.main.showMessenger(); } } console.log(livechat); } catch (e) { console.error(e); } }, { deep: true }); window.askIVA = window.askSky = window.askSkyWithData = (input, postBack, configuration, isNew) => { store.main.showMessenger(); if (isNew) { store.conversation.$reset(); store.conversationEvent.$reset(); store.main.setView("chat"); store.main.setNewConversation(true); } else { store.main.setView("chat"); } store.conversationEvent.sendMessage({ input, postBack, configuration }); }; window.openChat = () => { store.main.showMessenger(); // start new store.conversation.$reset(); store.conversationEvent.$reset(); // start new store.main.setView("chat"); // start new store.main.setNewConversation(true); }; window.closeChat = () => { store.main.hideMessenger(); }; //BEGIN MASKING const debounce = (func, timeout = 300) => { let timer; return (...args) => { clearTimeout(timer); timer = setTimeout(() => { func.apply(this, args); }, timeout); }; }; const de = debounce((value) => { value.forEach((message, index) => { if (message.sentBy.hasOwnProperty('type')) { if (localStorage.getItem(`feedback-${message._id}`) || message?.metadata?.feedbackable != true) { } else { window.showFeedback(message._id, message.conversationId, message?.metadata?.transactionId); } } else { if (message.input) { let matchRes = window.isMask(message.input); if (matchRes.includes("####") || matchRes.includes("#%*!")) { message.input = matchRes; } } } }); }, 1000); vm.$watch(() => store.conversationEvent.messages, de, { deep: true }); // sendMessage(input, metadata, conversationId) { // try { // debugLogging(`Sending message ${input} and metadata: ${JSON.stringify(metadata)}`); // window.liveChat.sendLiveChatMessage(input); // const proxyEndpoint = `${store.main.settings.liveChat.apiBaseUrl}/recordUserMessage`; // const id = window.liveChat.convoId; // input = window.isMask(input); // } // }//abbreviated // #region Masking window.isMask = (message) => { const ssnRegex = /\b(\d{3}[-. ]?\d{2}[-. ]?\d{4}|\d{2}[-. ]\d{4}|\d{9}|\d{3}-\d{2}-\d{4})\b/g; const ssnRegex2 = /\b(\d{2}(.)\d{4}|\d{3}([- .])\d{3}\3\d{3})\b/g; const ccRegex = /\b(\d{4}[-. ]?\d{6}[-. ]?\d{4,5}|\d{4}[-. ]?\d{4}[-. ]?\d{4}[-. ]?\d{4})\b/g; const acctNoRegex = /\b(\d{4}[-.\s]?\d{4}[-.\s]?\d{4}[-.\s]?\d{4})\b/g; const emailRegex = /\b[a-z0-9._%\+\-—|]+@[a-z0-9.\-—|]+\.[a-z|]{2,6}\b/g; const birthDateRegex = /\b^(3[01]|[12][0-9]|0?[1-9])(\/|-)(1[0-2]|0?[1-9])\2([0-9]{2})?[0-9]{2}$\b/g; const phoneNumberRegex = /^(\+\d{1,2}\s)?\(?\d{3}\)?[\s.-]\d{3}[\s.-]\d{4}$\b/g; let regexArr = []; //regexArr.push(acctNoRegex); regexArr.push(ccRegex); regexArr.push(ssnRegex); regexArr.push(ssnRegex2); //regexArr.push(emailRegex); //regexArr.push(birthDateRegex); //regexArr.push(phoneNumberRegex); regexArr.forEach((element) => { message = message.replace(element, "####"); }) let badWords = [ "anal", "anus", "arse", "ass", "ballsack", "bastard", "bitch", "biatch", "blowjob", "bollock", "bollok", "buttplug", "clitoris", "cock", "coon", "cunt", "damn", "dick", "Dildo", "dyke", "fag", "faggot", "feck", "fellate", "fellatio", "fuck", "fucking", "fucks", "f u c k", "Goddamn", "God damn", "hell", "homo", "jerk", "jizz", "knobend", "knob end", "labia", "lmao", "lmfao", "nigger", "nigga", "prick", "pube", "pussy", "queer", "retard", "sex", "bullshit", "shit", "slut", "tit", "turd", "twat", "whore", "wtf" ]; const regexbadWords = new RegExp(`\\b(?:${badWords.join('|')})\\b`, 'gi'); message = message.replace(regexbadWords, '#%*!'); return message; }; //END Masking // #region Response Link Click Handling store.conversationEvent.chipOnClick = (data) => { console.log(JSON.stringify(data)); if (data.url) { window.open(data.url, '_blank'); } else if (data.action) { switch (data.action) { case "hideMessenger": console.log('Got to hide messenger'); store.main.hideMessenger(); break; } } else { store.conversationEvent.sendMessage(data); } } // endregion