PageSourceSearch

https://webkul.chatwhizz.com/chat-support/js/new-liveChat.js

js chatwhizz.com collected 2026-10-07 09:40:23 UTC 164,165 bytes, 3,289 lines download raw bytes

1// wkli_socket = io(`${WKprotocol}${WKscript}`, {
2//     'reconnection': true,
3//     'reconnectionDelay': 1000,
4//     'reconnectionDelayMax': 5000,
5//     'reconnectionAttempts': 5,
6//     'transports': ['websocket'],
7//     'rememberUpgrade': true 
8// });
9var wkli_socket;
10var wkli_isSocketConnected = false
11const initializeSocket = () => {
12    return new Promise((resolve, reject) => {
13        if(!wkli_socket) {
14            wkli_socket = io(`${WKprotocol}${WKscript}`, {
15                'reconnection': true,
16                'reconnectionDelay': 1000,
17                'reconnectionDelayMax': 5000,
18                // 'reconnectionAttempts': 5,
19                'transports': ['websocket'],
20                'rememberUpgrade': true 
21            });
22            user.getMessageFromOperator()
23            user.socketRejoin();
24            setTimeout(()=>{
25                if(typeof media == 'object' && media)
26                    media.connectingSocket();
27            },3000)
28        }
29        resolve(wkli_socket)
30    })
31}
32const Ids = {
33    MAIN_COINTAINER: "wk-cw-liveChatCointainer",
34    OPTION_CONTAINER: "wk-cw-livechatOptionModel",
35    MODEL_COINTAINER: "wk-cw-liveChatModel",
36    MAINTENANCE_CONTAINER: "wk-cw-maintenanceModel",
37    REGISTRATION_FROM_ID: "wk-ch-livechat-registrationFrom",
38    REGISTRATION_FROM_CLOSE_BTN_ID: "wk-ch-livechat-registrationFrom-close",
39    OPEN_CHAT_MODEL_BTN_ID: "wk-cw-openChatModelButton",
40    SKIP_REGISTRATIONFORM_ID: "wk-cw-skip-to-chat",
41    SEND_MSG_BTN_ID: "wk-cw-chatbot-sendMessage-button",
42    CHATBOT: "wk-cw-chatbot",
43    MESSAGE: "wk-cw-message",
44    user_operator_chat_holder: "wk-cw-user-operator-chat",
45    formSubmit: "wk-cw-submit-form-control",
46    normalChatBtn: "wk-cw-normal-chat-btn",
47    whatsappChatBtn: "wk-cw-whatsapp-chat-btn",
48    wkEndChat: "wkEndChat",
49    wkConfirmationCancel: "wk-confirmation-cancel",
50    wkConfirmationConfirm: "wk-confirmation-confirm",
51    unreadMessage: "wk-ch-unreadMessageCount",
52    sendEndMail: 'wk-confirmation-confirm-sendMail',
53    attachmentButton: 'wk-cw-attachment-button',
54    attachmentClose: "wk-ch-chatbot-attachment-close",
55    replyBlockClose: "wk-ch-chatbot-replyBlock-close",
56    cancleNewSendEmail: "wk-confirmation-cancle-sendMail-newEmail",
57    confirmNewSendEmail: "wk-confirmation-confirm-sendMail-newEmail",
58    chatWithAgent: "wk-cw-chatbot-chatWithAgent",
59    Text_Container: "wk-cw-chatbot-textCointainer",
60    start_autoResponse: "wk-cw-start-autoResponse",
61    autoResponseAction: "wk-cw-autoResponse-action",
62    circleWidget: "wk-cw-circleWidget",
63    chatHistory: 'wk-cw-chat-history',
64    progressBar: 'wk-progress-bar',
65    countDown: 'wk-countdown',
66    chatWithChatbot: "wk-cw-chat-with-chatbot",
67    agentChat: "wk-cw-agetChat-button"
68}
69
70let is_Typing = '';
71let localStorageVar = "ChatSupport";
72let localAutoChat = "autoChat";
73let query_status = false;
74//"chat with agent" clicked before the client is registered: the request waits here until
75//sendMessageAckOfUser() has written the client record, then startChatWithAgent() replays it
76let wkli_pending_agent_chat = null;
77let wkli_chat = [];
78let wkli_modalVisiblity = false;
79let wkli_selectedChatOption = 'normal' // normal or whatsapp
80let wkli_whatsappFormField = document.getElementById(wkli_wa_form_field_id);
81let wkli_normalReplyData = '';
82let ai_message = {}
83let disconnectAt = -1;
84var wkli_isChatwithchatbot = false
85let wkli_mailRegex = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
86let wkli_maintenance_mode = false;
87let preventSendingMsg = false;
88//set once verify-client refuses this ip/email, stops every further registration attempt
89let wkli_client_blocked = false;
90//restart on change: the pending conversation-end-ack should open a new chat instead of closing the widget
91let wkli_restart_chat_pending = false;
92
93class Helper {
94    constructor() {
95        this.user_operator_conversation = [];
96        this.reSendMessages=[]
97        this.isOffline = false;
98        this.unreadMessageCount = 0;
99        this.http_regex = new RegExp('(http|https|www)://([^ ])*', 'g');
100        this.image_regex = /\.(?:jpe?g|gif|png|svg)/i;
101        this.link_exp = /(\b(www|http|https|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;;
102        this.checkAttachment = ['csv', 'pdf', 'application/pdf', 'txt', 'jpg', 'jpeg', 'png', 'gif', 'ods', 'xls', 'xlsx', 'php', 'js', 'odt', 'ott', 'odm', 'html', 'oth', 'ots', 'odg', 'otg', 'odp', 'otp', 'odf', 'odb', 'oxt', 'mp3'];
103        this.checkImg = ['jpeg', 'jpg', 'png', 'PNG', 'svg', 'SVG', 'gif', 'GIF'];
104        this.storage = false;
105        this.in_queue = false;
106    }
107
108    getElement(id) {
109        if (id) {
110            return document.getElementById(id);
111        }
112        return false;
113    }
114    //history is fetched by the client email, so the three dot menu shows only once getOldChatHistory() has one to send
115    toggleChatHistory() {
116        let dropdown = this.getElement('wk-cw-chat-history-dropdown');
117        if (!dropdown)
118            return;
119        let session = JSON.parse(localStorage.getItem(localStorageVar));
120        let restricted = JSON.parse(localStorage.getItem('restrictChatHistory'));
121        let hasEmail = session ? session.clientEmail && session.senderId : restricted && restricted.clientEmail;
122        dropdown.style.display = wkli_show_chat_history && !wkli_client_blocked && hasEmail ? '' : 'none';
123    }
124    setClickListener(id, callback) {
125        let element = this.getElement(id);
126        if (element)
127            element.addEventListener('click', callback);
128    }
129    setKeyListener(id, callback) {
130        let element = this.getElement(id);
131        if (element)
132            element.addEventListener('keydown', callback);
133    }
134    changeDisplayProperty(id, property = '') {
135        let element = helper.getElement(id)
136        if(!wkli_showUvdeskWidget || id == Ids.MODEL_COINTAINER || id == Ids.OPEN_CHAT_MODEL_BTN_ID) {
137            if (property == '') {
138                let css = getComputedStyle(element)
139                if (element.style.display == 'none' || css.display == "none") {
140                    element.style.display = "block"
141                } else {
142                    element.style.display = "none"
143                }
144            } else {
145                element.style.display = property
146            }
147        }
148    }
149    showHoverMsg() {
150        if(document.querySelector('.wk-cw-openChatModelButton').classList.contains("wk-cw-checked")) {
151            helper.getElement(Ids.circleWidget).removeAttribute("title");
152        } else {
153            helper.getElement(Ids.circleWidget).setAttribute('title', wkli_hoverMsg);
154        }
155    }
156    startNewSession() {
157        if(wkli_client_blocked)
158            return false;
159        // document.getElementById("startNewChat").remove();
160        let enableAutoChatApi = false;
161        wkli_autoChatBotType = wkli_autoChatBotType_db
162        let autoChatApi = JSON.parse(localStorage.getItem('autoChatApi'))
163        if(wkli_autoChatBotType && wkli_autoChatBotType == '2'){
164            if(!autoChatApi){
165                localStorage.setItem('autoChatApi',true)
166            }
167            enableAutoChatApi = true;
168        } else {
169            localStorage.removeItem('autoChatApi')
170        }
171        wkli_registration_in_process = false
172        document.getElementById("wk-cw-chatbot-textCointainer").style.display = "grid";
173        helper.getElement(Ids.user_operator_chat_holder).innerHTML = "";
174        document.getElementById("wk-ch-operatorOnline").style.display = enableAutoChatApi ? "inline-block" : "none";
175        document.getElementById("operatorName").textContent = enableAutoChatApi ? wkli_botName : wkli_welcomeText;
176        if (wkli_showForm) {
177            helper.changeDisplayProperty(Ids.CHATBOT, 'none');
178            helper.changeDisplayProperty(Ids.REGISTRATION_FROM_ID, 'block')
179        } else {
180            if (new URL(location.href).searchParams.get('name'))
181                wkli_socket.emit('sendAutoResponseInNoReg', { domain: new URL(location.href).searchParams.get('name'), enableAutoResponse: wkli_enableAutoResponse, organisationId: wkli_organisationId, AI_chatbot: wkli_AI_chatbot, enableAutoChatApi });
182            else
183                wkli_socket.emit('sendAutoResponseInNoReg', { domain: location.hostname, enableAutoResponse: wkli_enableAutoResponse, organisationId: wkli_organisationId, AI_chatbot: wkli_AI_chatbot, enableAutoChatApi });
184        }
185        user.disableChatWithAgent()
186        if(document.getElementById('wkli_technicalError')) {
187            document.getElementById('wkli_technicalError').remove()
188        }
189    }
190    
191    chnageQuestionView(element){
192        element.style.background = wkli_theamColor;
193        element.style.color = '#ffffff';
194        element.style.borderColor = wkli_theamColor;
195    }
196
197    resetQuestionView(element){
198        element.style.background = "#ffffff";
199        element.style.color = wkli_theamColor;
200    }
201
202    clearAllTimeoutAndInterval() {
203        clearTimeout(wkli_chat_timeout)
204        clearTimeout(wkli_confirm_timeout)
205        clearInterval(wkli_countdownInterval);
206    }
207
208    startChatTimeout() {
209        this.clearAllTimeoutAndInterval()
210        if(wkli_auto_chat_end && localStorage.getItem(localStorageVar)) {
211            // console.log('timeout start')
212            wkli_chat_timeout = setTimeout(() => {helper.getElement(Ids.wkEndChat).click()}, wkli_chat_timeout_duration);
213        }
214    }
215
216    startConfirmTimeout() {
217        this.clearAllTimeoutAndInterval()
218        if(wkli_auto_chat_end && localStorage.getItem(localStorageVar)) {
219            // console.log('confirm timeout start')
220            this.startCountDown()
221            if(!document.querySelector('.wk-cw-openChatModelButton').classList.contains("wk-cw-checked")) { // this code for when widget is closed and need to open widget while start countDown
222                user.openChatBlock();
223            }
224            wkli_confirm_timeout = setTimeout(() => {helper.getElement(Ids.wkConfirmationConfirm).click()}, wkli_confirm_timeout_duration)
225        }
226    }
227
228    startCountDown() {
229        wkli_countDownValue = wkli_confirm_timeout_duration/1000;
230        const countdownElement = helper.getElement(Ids.countDown);
231        countdownElement.display = 'block';
232        const progressBar = helper.getElement(Ids.progressBar);
233        progressBar.display = 'block';
234        progressBar.max = wkli_countDownValue
235        progressBar.value = wkli_countDownValue;
236        wkli_countdownInterval = setInterval(() => {
237            wkli_countDownValue--;
238
239            if (wkli_countDownValue >= 0) {
240                countdownElement.innerText = `${wkli_countdownText}${wkli_countDownValue}`;
241                this.updateProgressBar();
242            } else {
243                clearInterval(wkli_countdownInterval);
244                countdownElement.innerText = wkli_timesUpText;
245                progressBar.value = 0;
246            }
247        }, 1000);
248    }
249
250    updateProgressBar() {
251        const progressBar = document.getElementById("wk-progress-bar");
252        progressBar.value = wkli_countDownValue;
253    }
254
255    refreshBasicChatbot() {
256        setWkli_isChatwithchatbot(true)
257        wkli_option_event = null
258        wkli_option_step = 'label'
259        wkli_orderId = ''
260        wkli_reason = ''
261    }
262
263    checkRestrictAgentChatCondition() {
264        let liveChatPermission = document.getElementById('wk-ch-liveChatPermission');
265        let autoChatApi = JSON.parse(localStorage.getItem('autoChatApi'))
266        if(wkli_agentChatPermission && liveChatPermission && liveChatPermission.value && liveChatPermission.value == '1' && (wkli_autoChatBotType != 2 || (wkli_autoChatBotType == 2 && !autoChatApi))) {
267            return true
268        } else {
269            return false;
270        }
271    }
272}
273
274const helper = new Helper()
275
276class Form {
277
278    isMobile () {
279        let isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
280        if (isMobile) {
281            return true;
282        } else {
283            let webkitVer = parseInt(/WebKit\/([0-9]+)|$/.exec(navigator.appVersion)[1], 10); // also matches AppleWebKit
284            let isGoogle = webkitVer && navigator.vendor.indexOf('Google') === 0; // Also true for Opera Mobile and maybe others
285            let isAndroid = isGoogle && navigator.userAgent.indexOf('Android') > 0; // Careful - Firefox and Windows Mobile also have Android in user agent
286            let androidDesktopMode = !isAndroid && isGoogle && (navigator.platform.indexOf('Linux a') === 0) && 'ontouchstart' in document.documentElement;
287
288            let iOSAgent = window.navigator.userAgent.match(/iPhone|iPod|iPad/);
289            let iOSPlatform = window.navigator.platform && window.navigator.platform.match(/iPhone|iPod|iPad/);
290            let iOSRequestDesktop = (!iOSAgent && iOSPlatform);
291
292            let androidDesktopModeUsingFireFox = (navigator.vendor == '') && (navigator.appVersion.includes('Android'))
293
294            if (androidDesktopMode || iOSRequestDesktop || androidDesktopModeUsingFireFox)
295                return true;
296            else
297                return false;
298        }
299    }
300
301    changeWidgetIcon(preOpenOption = false) {
302        let img = document.querySelector('.wk-cw-openChatModelButton img').src;
303        let file_name = img.substring(img.lastIndexOf('/') + 1);
304        if (file_name != "down-arrow.svg" || wkli_modalVisiblity) {
305            document.querySelector('.wk-cw-openChatModelButton img').src = ''
306            if(!preOpenOption) {
307                document.getElementById(Ids.MODEL_COINTAINER).classList.add('wk-cw-show')
308            }
309            else {
310                document.getElementById(Ids.OPTION_CONTAINER).classList.add('wk-cw-show')
311                if(helper.checkRestrictAgentChatCondition()){
312                    document.getElementById(Ids.whatsappChatBtn).classList.add('wk-cw-hideWhatsapp')
313                }else{
314                    document.getElementById(Ids.whatsappChatBtn).classList.remove('wk-cw-hideWhatsapp')
315                }
316            }
317            document.querySelector('.wk-cw-openChatModelButton img').src = wkli_down_arrow_svg
318            document.querySelector('.wk-cw-openChatModelButton').classList.add("wk-cw-checked");
319            document.querySelector('.wk-cw-openChatModelButton').style.border = '1px solid' + wkli_theamColor
320            sessionStorage.setItem('auto_open_widget', 'true')
321            if(user.isMobile() && !JSON.parse(localStorage.getItem(localStorageVar)) && !preOpenOption){
322                document.getElementById(Ids.REGISTRATION_FROM_CLOSE_BTN_ID).style.display = 'block';
323                helper.changeDisplayProperty(Ids.circleWidget, 'none')
324                document.getElementById(Ids.MODEL_COINTAINER).style.bottom = '0px'
325            } else if(user.isMobile()){
326                document.getElementById(Ids.REGISTRATION_FROM_CLOSE_BTN_ID).style.display = 'none';
327                helper.changeDisplayProperty(Ids.circleWidget, 'block')
328                document.getElementById(Ids.MODEL_COINTAINER).style.bottom = '80px'
329            }
330        } else {
331            document.querySelector('.wk-cw-openChatModelButton img').src = ''
332            document.getElementById(Ids.MODEL_COINTAINER).classList.remove('wk-cw-show')
333            document.getElementById(Ids.OPTION_CONTAINER).classList.remove('wk-cw-show')
334            if(wkli_icon)
335                document.querySelector('.wk-cw-openChatModelButton img').src = wkli_icon
336            else
337                document.querySelector('.wk-cw-openChatModelButton img').src = wkli_message_svg
338            document.querySelector('.wk-cw-openChatModelButton').classList.remove("wk-cw-checked");
339            sessionStorage.setItem('auto_open_widget', 'false')
340            if(user.isMobile()){
341                document.getElementById(Ids.REGISTRATION_FROM_CLOSE_BTN_ID).style.display = 'none';
342                helper.changeDisplayProperty(Ids.circleWidget, 'block')
343                document.getElementById(Ids.MODEL_COINTAINER).style.bottom = '80px'
344            }
345            if(!(localStorage.getItem(localStorageVar))){
346                helper.startNewSession()
347            }
348        }
349    }
350
351    preOpenchatBlockOption() {
352        wkli_modalVisiblity = !wkli_modalVisiblity;
353        if(JSON.parse(localStorage.getItem(localStorageVar))){
354            // normal chat continue
355            this.openChatBlock();
356        } else{
357            new Form().changeWidgetIcon(true);
358        }
359
360    }
361
362    actionOnSelectedChatOption(chatOption) {
363        wkli_selectedChatOption = chatOption
364        document.getElementById(Ids.OPTION_CONTAINER).classList.remove('wk-cw-show')
365        if(chatOption == 'normal') {
366            if(wkli_whatsappFormField)
367                wkli_whatsappFormField.style.display = 'none';
368            document.getElementById("wk-cw-submit-form-control").innerText = wkli_buttonText.normalChatSubmitButton
369            document.getElementById("wk-cw-submit-form-control").classList.remove('wk-whatsapp-button')
370            // socket already opened by a whatsapp registration: its one-time no-reg auto response was
371            // dropped by the whatsapp guard in getAllMessages, so ask for it again for this normal chat
372            if(wkli_socket && !wkli_showForm && !JSON.parse(localStorage.getItem(localStorageVar)))
373                helper.startNewSession();
374        }else if(chatOption == 'whatsapp') {
375            if(wkli_whatsappFormField)
376                wkli_whatsappFormField.style.display = 'block';
377            let wa_button = `<div style='display: flex;justify-content: center;'><img src = "${wkli_whatsapp_message_icon}"><span style='margin: auto 0; margin-left: 5px'>${wkli_buttonText.whatsappChatSubmitButton}</span></div>`
378            document.getElementById("wk-cw-submit-form-control").innerHTML = wa_button
379            document.getElementById("wk-cw-submit-form-control").classList.add('wk-whatsapp-button')
380            // WhatsApp always registers through the form - it needs the visitor's number. openChatBlock()
381            // would skip the form for an existing session or when auto registration turned wkli_showForm off.
382            this.openWhatsappRegistration();
383            return;
384        }
385        this.openChatBlock();
386    }
387
388    openWhatsappRegistration() {
389        helper.getElement(Ids.unreadMessage).style.display = "none"
390        helper.getElement(Ids.unreadMessage).innerHTML = ""
391        new Form().changeWidgetIcon();
392        helper.changeDisplayProperty(Ids.CHATBOT, 'none');
393        helper.changeDisplayProperty(Ids.REGISTRATION_FROM_ID, 'block');
394        let element = helper.getElement("wk-chat-end-confirmation")
395        if(element && element.style.display != 'none')
396            element.style.display = 'none'
397        helper.showHoverMsg();
398    }
399
400    openChatBlock() {
401        helper.getElement(Ids.unreadMessage).style.display = "none"
402        helper.getElement(Ids.unreadMessage).innerHTML = ""
403        
404        new Form().changeWidgetIcon();
405        
406        if(JSON.parse(localStorage.getItem(localStorageVar))) {
407            helper.changeDisplayProperty(Ids.REGISTRATION_FROM_ID, 'none')
408            // helper.changeDisplayProperty(Ids.CHATBOT, 'block');
409
410            if(document.getElementById(Ids.MODEL_COINTAINER).classList.contains('wk-cw-show')) {              
411                let user = JSON.parse(localStorage.getItem(localStorageVar))
412                user.enable = true;
413                localStorage.setItem(localStorageVar, JSON.stringify(user))
414                if (JSON.parse(localStorage.getItem(localStorageVar)).senderId && helper.unreadMessageCount > 0) {
415                    wkli_socket.emit("getAllMessageAck", {
416                        receiverId: JSON.parse(localStorage.getItem(localStorageVar)).senderId,
417                        seenTimestamp: new Date().toISOString(),
418                        domain: JSON.parse(localStorage.getItem(localStorageVar)).domain,
419                        userId: JSON.parse(localStorage.getItem(localStorageVar)).senderId
420                    })
421                    helper.unreadMessageCount = 0
422                }
423                if(document.getElementById("wk-incoming-call"))
424                    document.getElementById("wk-incoming-call").style.display = "none";
425            } else {
426                if(document.getElementById("wk-incoming-call") && document.getElementById('wk-media-model').style.display == 'flex') {
427                    document.getElementById("wk-incoming-call").style.display = "block";
428                }
429                let user = JSON.parse(localStorage.getItem(localStorageVar))
430                user.enable = false;
431                localStorage.setItem(localStorageVar, JSON.stringify(user))
432            }
433        } else {
434            if(wkli_showForm) {
435                helper.changeDisplayProperty(Ids.CHATBOT, 'none');
436                helper.changeDisplayProperty(Ids.REGISTRATION_FROM_ID, 'block')
437            } else {
438                initializeSocket().then(() => {
439                    helper.changeDisplayProperty(Ids.CHATBOT, 'block');
440                    helper.changeDisplayProperty(Ids.REGISTRATION_FROM_ID, 'none')
441                }).catch(err => console.log(err))
442            }
443            let element = helper.getElement("wk-chat-end-confirmation")
444            if(element && element.style.display != 'none') {
445                element.style.display = 'none'
446            }
447        }
448        this.scrollHeight();
449        helper.showHoverMsg();
450        // code comment due to on open chat block or close chat widget should be in privious state
451        // let element = helper.getElement("wk-chat-end-confirmation")
452        // if(element && element.style.display != 'none') {
453        //     element.style.display = 'none'
454        // }
455    }
456
457    showChatBlock(showDirectChatBoard) {
458        if (showDirectChatBoard) {
459            helper.changeDisplayProperty(Ids.REGISTRATION_FROM_ID, 'none')
460            helper.changeDisplayProperty(Ids.CHATBOT, 'block')
461        } else {
462            new Form().changeWidgetIcon();
463        }
464        if (JSON.parse(localStorage.getItem(localStorageVar)) && JSON.parse(localStorage.getItem(localStorageVar)).senderId) {
465            wkli_socket.emit("getAllMessageAck", {
466                receiverId: JSON.parse(localStorage.getItem(localStorageVar)).senderId,
467                seenTimestamp: new Date().toISOString(),
468                domain: JSON.parse(localStorage.getItem(localStorageVar)).domain,
469                userId: JSON.parse(localStorage.getItem(localStorageVar)).senderId,
470            })
471        }
472
473        if (JSON.parse(localStorage.getItem(localStorageVar))) {
474            let user = JSON.parse(localStorage.getItem(localStorageVar))
475            user.enable = helper.getElement(Ids.CHATBOT).style.display == 'none' ? false : true;
476            localStorage.setItem(localStorageVar, JSON.stringify(user))
477        }
478        helper.showHoverMsg();
479    }
480
481    getMessageFromUser(e) {
482        if (e.keyCode == 8) {
483            helper.getElement("wk-cw-message").rows = 1;
484        } else if (e.keyCode == 13 && !e.shiftKey) {
485            if (helper.getElement("wk-cw-message").value || (helper.getElement("wk-cw-attachment-button-hide").value && helper.getElement("wk-cw-attachment-button-hide").files.length)) {
486                this.getMessageInfo();
487            }
488            e.preventDefault();
489        } else {
490            helper.getElement("wk-cw-message").rows = 2;
491        }
492    }
493
494
495    buildMessage(msg, type, callback) {
496        let data = {
497            message: msg.replace(/</g, "&lt;").replace(/>/g, "&gt;"),
498            messageId: '_' + Math.random().toString(36).substr(2, 16),
499            sendTimestamp: new Date().toISOString(),
500            // domain: location.host.split(".")[0],
501            domain: location.host,
502            type: type,
503            reply: wkli_normalReplyData != '' ? wkli_normalReplyData : null,
504            chatInitiateNoti: true,
505            uniqueId: '_' + Math.random().toString(36).substr(2, 16) + '_',
506            end: 'sender',
507            isOffline: helper.isOffline
508        }
509        if (document.getElementsByClassName("wk-cw-user-to-operator-msg").length > 1) {
510            data.isOffline = false;
511        }
512        callback(data);
513    }
514
515    chnageMessageDetails(data, callback) {
516        if (JSON.parse(localStorage.getItem(localStorageVar))) {
517            data.senderId = JSON.parse(localStorage.getItem(localStorageVar)).senderId
518            if (JSON.parse(localStorage.getItem(localStorageVar)).departmentId)
519                data.departmentId = JSON.parse(localStorage.getItem(localStorageVar)).departmentId
520            data.uniqueId = JSON.parse(localStorage.getItem(localStorageVar)).uniqueId
521            if (JSON.parse(localStorage.getItem(localStorageVar)).operator)
522                data.receiverId = JSON.parse(localStorage.getItem(localStorageVar)).operator
523        } else
524            data.uniqueId = '_' + Math.random().toString(36).substr(2, 16);
525        callback(data)
526    }
527
528    getMessageInfo() {
529        if(preventSendingMsg || wkli_client_blocked){
530            return false;
531        }
532        //for ai chatbot and basic chatbot
533        if(wkli_option_event) {
534            if(helper.getElement("wk-cw-message").value.trim()) {
535                if(['question', 'optionalQuestion', 'reason', 'email', 'otp'].includes(wkli_option_step)) {
536                    if(wkli_option_step == 'email') {
537                        let email = helper.getElement("wk-cw-message").value.trim()
538                        if(!wkli_mailRegex.test(email)) {
539                            helper.getElement("wk-cw-attachment-error").style.display = "block";
540                            helper.getElement("wk-cw-attachment-error").textContent = 'Invalid Email Id'
541                            return false
542                        }
543                        helper.getElement("wk-cw-attachment-error").style.display = "none";
544                        helper.getElement("wk-cw-attachment-error").textContent = ''
545                        if (localStorage.getItem(localStorageVar) && JSON.parse(localStorage.getItem(localStorageVar))) {
546                            let user = JSON.parse(localStorage.getItem(localStorageVar))
547                            user.clientEmail = email
548                            localStorage.setItem(localStorageVar, JSON.stringify(user))
549                            helper.toggleChatHistory()
550                        }
551                    }
552                    this.processingNextOption(helper.getElement("wk-cw-message").value.trim())
553                }
554            }
555            return false
556        }
557        // end
558        if (helper.getElement("wk-cw-message").value.trim() || (helper.getElement("wk-cw-attachment-button-hide").value && helper.getElement("wk-cw-attachment-button-hide").files.length)) {
559            if (document.getElementsByClassName("wk-cw-user-to-operator-msg").length == 0 && !wkli_showForm) {
560                if(!wkli_registration_in_process) {
561                    wkli_registration_in_process = true
562                    let clientEmail = this.getRegistrationEmail()
563                    this.getClientToken(false, clientEmail, cb => {
564                        if(cb && cb.data) {
565                            this.sendChatInitiateNoti(cb.data, clientEmail);
566                        } else {
567                            //blocked client or verification failure, release the lock to allow a retry
568                            wkli_registration_in_process = false
569                        }
570                    })
571                }
572            }
573            if (helper.getElement("wk-cw-attachment-button-hide").value && helper.getElement("wk-cw-attachment-button-hide").files.length) {
574                helper.getElement("wk-cw-chatbot-attachment-name").style.display = "none"
575                helper.getElement("wk-cw-chatbot-reply-block").style.display = "none"
576                helper.getElement("wk-cw-attachment-error").style.display = "block";
577                helper.getElement("wk-cw-attachment-error").textContent = wkli_sendingText
578                let fd = new FormData();
579                let msg = (helper.getElement("wk-cw-message").value).trim();
580                fd.append('file', helper.getElement("wk-cw-attachment-button-hide").files[0]);
581                helper.getElement("wk-cw-message").value = "";
582                helper.getElement("wk-cw-message").rows = 1;
583                document.getElementById("wk-cw-attachment-button-hide").value = "";
584                let senderId = JSON.parse(localStorage.getItem(localStorageVar)).senderId
585                if(senderId){
586                    fd.append('senderId',senderId)
587                }
588                fetch(`${WKprotocol}${WKscript}/wkcs/uploadClientFile`, {
589                    method: 'POST',
590                    processData: false,
591                    contentType: false,
592                    body: fd
593                }).then(res => res.json())
594                    .then(response => {
595                        if (response.status == 1) {
596                            helper.getElement("wk-cw-attachment-error").textContent = ''
597                            helper.getElement("wk-cw-attachment-error").style.display = "none"
598                            this.buildMessage(msg, 1, (data) => {
599                                this.chnageMessageDetails(data, (updatedMessage) => {
600                                    helper.user_operator_conversation.push(updatedMessage)
601                                    updatedMessage.message = `${response.link} \n${updatedMessage.message}`;
602                                    this.buildMessageInDom(updatedMessage)
603                                })
604                            })
605                        } else {
606                            console.log(response)
607                        }
608                    })
609                    .catch(error => {
610                        console.error('Error:', error)
611                        inValidFile('File sending failed..try again')
612                    });
613            }
614            else {
615                if (document.getElementsByClassName("wk-cw-user-to-operator-msg").length > 0 || wkli_showForm) {
616                    if ((helper.getElement("wk-cw-message").value).trim()) {
617                        let msg = (helper.getElement("wk-cw-message").value).trim();
618                        this.buildMessage(msg, 1, (data) => {
619                            this.chnageMessageDetails(data, (updatedMessage) => {
620                                helper.user_operator_conversation = [];
621                                helper.user_operator_conversation.push(updatedMessage)
622                                this.buildMessageInDom(updatedMessage)
623                            })
624                        })
625    
626                    }
627                    helper.getElement("wk-cw-message").value = "";
628                    helper.getElement("wk-cw-message").rows = 1;
629                    helper.getElement("wk-cw-message").focus();
630                    document.getElementById("wk-cw-attachment-button-hide").value = "";
631                }
632            }
633        }
634
635    }
636
637    buildMessageInDom(data, statusForSendMsgBysendOperatorMessage = true) {
638        if (data.type == 1) {
639            let parentClass = helper.user_operator_conversation[0].end == 'sender' ? "wk-cw-user-to-operator-msg" : "wk-cw-operator-to-user-msg"
640            let childClass = helper.user_operator_conversation[0].end == 'sender' ? "user-to-operator-msg" : "o
640perator-to-user-msg"
641            let msg = helper.user_operator_conversation[0].message.replace(/</g, "&lt;").replace(/>/g, "&gt;").split(' \n');
642            let getext = msg[0].split('.')
643            let ext = getext[getext.length - 1]
644            if (helper.link_exp.test(helper.user_operator_conversation[0].message) || (helper.checkAttachment.includes(ext))) {
645                if (msg[0].includes(".s3.amazonaws.com")) {
646                    this.buildAttachmentInDom(1, helper.user_operator_conversation[0], parentClass, childClass);
647                } else {
648                    this.buildAttachmentInDom(2, helper.user_operator_conversation[0], parentClass, childClass);
649                }
650            } else {
651                this.buildAttachmentInDom(2, helper.user_operator_conversation[0], parentClass, childClass);
652            }
653        }
654        if(statusForSendMsgBysendOperatorMessage)
655            this.sendMessage()
656        else{
657            if(new URL(location.href).searchParams.get('name'))
658                helper.user_operator_conversation[0].domain = new URL(location.href).searchParams.get('name');
659            wkli_socket.emit("getQueryResult",helper.user_operator_conversation[0]);
660        }
661    }
662
663    /**
664     * The token minted by getClientToken() is bound to this address and registerUser() rejects
665     * the registration when the two differ, so the token call and the registration payload have
666     * to resolve the email the same way. The form input wins when it exists because it already
667     * carries the url parameter over injected page value precedence.
668     */
669    getRegistrationEmail() {
670        if (wkli_userEmail && document.getElementById(wkli_userEmail))
671            return document.getElementById(wkli_userEmail).value.trim();
672        return wkli_shopify_customer.email ? wkli_shopify_customer.email : '';
673    }
674
675    getRegistrationName() {
676        if (wkli_userName && document.getElementById(wkli_userName))
677            return document.getElementById(wkli_userName).value.trim();
678        return wkli_shopify_customer.name ? wkli_shopify_customer.name : '';
679    }
680
681    /**
682     * Resolves the department select to the id the backend expects. The select is built and
683     * prefilled even when the form is skipped, so this works for the auto register flow too.
684     */
685    getSelectedDepartmentId() {
686        if (!wkli_depRegistration || !wkli_userDepartment)
687            return '';
688        let element = document.getElementById(wkli_userDepartment);
689        if (!element || !element.value || element.value == 'SELECT')
690            return '';
691        let department = (wkli_departmentArr || []).filter(x => x.handleName == element.value)
692        return department.length ? department[0].departmentId : '';
693    }
694
695    /**
696     * Custom registration fields are not stored on the client record, they are pushed to the
697     * operator as the first chat message. Shared by the form flow and the auto register flow.
698     * Do NOT clear the inputs after reading: every registration path is already gated on the
699     * empty ".wk-cw-user-to-operator-msg" list, so this runs once per chat session anyway, and
700     * a "Start New" chat (no page reload) must re-read the page-injected/auto values instead of
701     * finding them wiped.
702     */
703    sendCustomFieldMessage(useQueryResult = false) {
704        if (!wkli_customInput || !document.getElementsByClassName("customInput").length)
705            return false;
706        let customMsg = '';
707        Array.from(document.getElementsByClassName('customInput')).forEach(
708            function (element, index, array) {
709                customMsg += `${element.name}: ${element.value.replace(/</g, "&lt;").replace(/>/g, "&gt;")} \n`;
710            }
711        );
712        this.buildMessage(customMsg, 1, (data) => {
713            data.chatInitiateNoti = true;
714            this.chnageMessageDetails(data, (updatedMessage) => {
715                helper.user_operator_conversation = [];
716                helper.user_operator_conversation.push(updatedMessage)
717                if(useQueryResult){
718                    updatedMessage.tick = true;
719                    this.buildMessageInDom(updatedMessage, false)
720                }
721                else
722                    this.buildMessageInDom(updatedMessage)
723            })
724        })
725        return true;
726    }
727
728    /**
729     * Custom registration fields as a { handleName: value } object, persisted on the client
730     * record (chatSupportUser.customFields) at register time. Ke
730yed by the field handleName
731     * (data-handle, stamped by the loader); same escaping as the custom field chat message.
732     * Returns null when there are no custom inputs.
733     */
734    getCustomFieldsObject() {
735        if (!wkli_customInput || !document.getElementsByClassName("customInput").length)
736            return null;
737        let customFields = {};
738        Array.from(document.getElementsByClassName('customInput')).forEach(
739            function (element) {
740                let key = element.dataset.handle || element.name;
741                customFields[key] = element.value.replace(/</g, "&lt;").replace(/>/g, "&gt;");
742            }
743        );
744        return customFields;
745    }
746
747    sendChatInitiateNoti(tokenData = null, clientEmail = null) {
748        if(helper.checkRestrictAgentChatCondition()){
749            return
750        }
751        if(document.getElementById('wkli_technicalError')) {
752            document.getElementById('wkli_technicalError').remove()
753        }
754        let msg = `<------ ${location.href} ------>`
755        this.buildMessage(msg, 2, (data) => {
756            data.chatInitiateNoti = false;
757            if(tokenData && !wkli_showForm) {
758                data.clientToken = tokenData
759                data.in_queue = helper.in_queue
760                //must match the address the token was minted with or registerUser() rejects it
761                data.email = clientEmail !== null ? clientEmail : this.getRegistrationEmail()
762                data.name = this.getRegistrationName()
763                let departmentId = this.getSelectedDepartmentId()
764                if(departmentId)
765                    data.departmentId = departmentId
766                let customFields = this.getCustomFieldsObject()
767                if(customFields)
768                    data.customFields = customFields
769            }
770            this.chnageMessageDetails(data, (updatedMessage) => {
771                if (updatedMessage.departmentId && wkli_departmentArr?.length && wkli_departmentNamePermission) {
772                    let dept = wkli_departmentArr.find(
773                        d => d.departmentId == updatedMessage.departmentId
774                    );
775                    if (dept?.name) {
776                        updatedMessage.message += `<br><strong>Chat initiated for Department:</strong> ${dept.name}`;
777                    }
778                }
779                helper.user_operator_conversation.push(updatedMessage);
780                if(wkli_enableAutoResponse && wkli_showForm && wkli_selectedChatOption != 'whatsapp'){
781                    if(new URL(location.href).searchParams.get('name'))
782                        updatedMessage.domain = new URL(location.href).searchParams.get('name');
783                    wkli_socket.emit("getQueryResult",updatedMessage);
784                    helper.user_operator_conversation.pop()
785                }else{
786                    this.sendMessage()
787                }
788            })
789        })
790        setTimeout(() => {
791            wkli_registration_in_process = false
792            //whatsapp custom fields already went out as customMsg, and its session is dropped on ack
793            if (document.getElementsByClassName("wk-cw-user-to-operator-msg").length == 0 && !wkli_showForm && wkli_selectedChatOption != 'whatsapp') {
794                //custom fields came from the page instead of the form, push them before the query
795                this.sendCustomFieldMessage()
796                if ((helper.getElement("wk-cw-message").value).trim()) {
797                    let msg = (helper.getElement("wk-cw-message").value).trim();
798                    this.buildMessage(msg, 1, (data) => {
799                        this.chnageMessageDetails(data, (updatedMessage) => {
800                            helper.user_operator_conversation = [];
801                            helper.user_operator_conversation.push(updatedMessage)
802                            this.buildMessageInDom(updatedMessage)
803                            helper.getElement("wk-cw-message").value = "";
804                            helper.getElement("wk-cw-message").rows = 1
805                        })
806                    })
807
808                }
809            }
810        }, 1000)
811    }
812
813    sendMessage() {
814        this.scrollHeight();
815        if (new URL(location.href).searchParams.get('name'))
816            helper.user_operator_conversation[0].domain = new URL(location.href).searchParams.get('name')
817        if (document.getElementsByClassName("wk-cw-user-to-operator-msg").length > 1 || (wkli_customInput && document.getElementsByClassName("wk-cw-user-to-operator-msg").length <= 1)) {
818            helper.user_operator_conversation[0].isOffline = false;
819        }
820        if (wkli_customInput && document.getElementsByClassName("wk-cw-user-to-operator-msg").length == 2) {
821            if (helper.isOffline)
822                helper.user_operator_conversation[0].isOffline = true;
823            else {
824                helper.user_operator_conversation[0].isOffline = false;
825            }
826        }
827        if (!wkli_showForm && !wkli_prefill['Email']) {
828            helper.user_operator_conversation[0].isOffline = false;
829        }
830        if(wkli_basic_chatbot && document.getElementsByClassName("wk-cw-user-to-operator-msg").length == 1 && wkli_shopify_customer.email) {
831            helper.user_operator_conversation[0].isOffline = helper.isOffline
832        }
833        let localAutoReponseData = JSON.parse(localStorage.getItem(localAutoChat));
834        let queries = document.getElementsByClassName("wk-cw-operator-to-user-queries");
835        let agentFirstMsg = JSON.parse(localStorage.getItem('agentChatFirstMsg'));
836        if(localAutoReponseData || (queries && queries.length) || agentFirstMsg){
837            Array.from(queries).forEach(el=>el.remove());
838            helper.user_operator_conversation[0].updateChatStatus = true;
839            helper.user_operator_conversation[0].organisationId = wkli_organisationId
840            if(localAutoReponseData || agentFirstMsg) 
841                helper.user_operator_conversation[0].isFirstMsg = true;
842            localStorage.removeItem(localAutoChat);
843            let data = JSON.parse(localStorage.getItem(localStorageVar))
844            if(data && data.operator){
845                delete data.operator;
846                delete data.operatorStatus;
847                data.name = wkli_requestedText
848                document.getElementById("operatorName").textContent = wkli_requestedText
849                localStorage.setItem(localStorageVar, JSON.stringify(data));
850                document.getElementById("wk-ch-operatorOnline").style.display = "none";
851                // delete helper.user_operator_conversation[0].receiverId;
852            }
853            localStorage.removeItem('agentChatFirstMsg');
854        }
855        if(wkli_AI_chatbot && !helper.user_operator_conversation[0].message.includes('http')) {
856            // if(!ai_message.question) {
857            //     ai_message = {
858            //         question: helper.user_operator_conversation[0].message,
859            //         history: []
860            //     }
861            // } else if(ai_message.question) {
862            //     if(!ai_message.history) 
863            //         ai_message.history = []
864            //     ai_message.history.splice(0, ai_message.history.length-4)
865            //     ai_message.history.push({
866            //         "type": "human",
867            //         "text": helper.user_operator_conversation[0].message
868            //     })
869            // }
870            ai_message.question = helper.user_operator_conversation[0].message
871            helper.user_operator_conversation[0].AI_chatbot = wkli_AI_chatbot
872            helper.user_operator_conversation[0].ai_message = ai_message
873        }
874        helper.reSendMessages.push(helper.user_operator_conversation[0])
875        if(helper.user_operator_conversation[0].updateChatStatus)
876        helper.user_operator_conversation[0].isOffline = helper.isOffline;
877        if(helper.user_operator_conversation[0].senderId)
878            helper.user_operator_conversation[0].userId = helper.user_operator_conversation[0].senderId
879        let autoChatApi = JSON.parse(localStorage.getItem('autoChatApi'))
880        if(wkli_autoChatBotType && wkli_autoChatBotType == '2' && autoChatApi && wkli_selectedChatOption == 'normal'){
881            let prevMsg = [];
882            let firstUserMessageFound = false;
883            let user = JSON.parse(localStorage.getItem(localStorageVar));
884            wkli_chat.filter(el => {
885                if (!user) {
886                    return;
887                }
888                let domain = user.domain;
889                if(el.senderId){
890                    if(['sp-seller.webkul.com','docs.qloapps.com','sakshi-p-store1.myshopify.com','rupesh-trunk-subscription.myshopify.com'].includes(domain)) {
891                        if (firstUserMessageFound && el.senderId) {
892                            if (el.senderId == (user.senderId)) {
893                                prevMsg.push({ 'role': 'user', 'content': el.message });
894                            } else if (el.senderId != (user.senderId)) {
895                                prevMsg.push({ 'role': 'assistant', 'content': el.message });
896                            }
897                        }
898                        if (!firstUserMessageFound) {
899                            if (el.senderId == (user.senderId)) {
900                                firstUserMessageFound = true;
901                            }
902                        }
903                    } else {
904                        if (el.senderId == (user.senderId)) {
905                            prevMsg.push({ 'role': 'user', 'content': el.message });
906                        } else if (el.senderId != (user.senderId)) {
907                            prevMsg.push({ 'role': 'assistant', 'content': el.message });
908                        }
909                    }
910                }
911            })
912            helper.user_operator_conversation[0].prevMsg = prevMsg
913            helper.user_operator_conversation[0].is_operator_online = user?.is_operator_online
914            document.getElementById("operatorName").textContent = wkli_botName;
915            document.getElementById("wk-ch-operatorOnline").style.background = "chartreuse";
916            let liveChatPermission = document.getElementById('wk-ch-l
916iveChatPermission');
917            if(wkli_agentChatPermission && liveChatPermission && liveChatPermission.value && liveChatPermission.value == '1') {
918                helper.user_operator_conversation[0].botToAgentRestrict = true;
919            }
920            preventSendingMsg = true;
921            if (wkli_customInput && document.getElementsByClassName("wk-cw-user-to-operator-msg").length <= 1) {
922                helper.user_operator_conversation[0].botCustomeMsg = true;
923                preventSendingMsg = false;
924            }
925            wkli_socket.emit('sendAutoMessage', helper.user_operator_conversation[0]);
926        }else{
927            wkli_socket.emit('sendOperatorMessage', helper.user_operator_conversation[0]);
928        }
929        setWkli_isChatwithchatbot(true)
930        helper.user_operator_conversation.pop();
931        helper.getElement("wk-cw-chatbot-reply-block").style.display = "none";
932        wkli_normalReplyData = '';
933        let active = document.querySelectorAll('.wk-cw-active')
934        if(active.length){
935            active.forEach((chat) => {
936                chat.classList.remove('wk-cw-active')
937            })
938        }
939        user.replyButtonAct();
940        helper.startChatTimeout();
941    }
942
943    getUserOperatorData() {
944        if (JSON.parse(localStorage.getItem(localStorageVar))) {
945
946        }
947    }
948
949    formatChatMessage(message, isBotMessage, textColor) {
950        if (!message) return '';
951        if (/<\/?[a-z][\s\S]*>/i.test(message)) {
952            return message.replace(
953                /<a /g,
954                '<a class="wk-ch-seller-buyer-url" '
955            );
956        }
957        let safeMsg = message.replace(/</g, "&lt;").replace(/>/g, "&gt;");
958        
959        safeMsg = safeMsg.replace(
960            helper.link_exp,
961            `<a href="$1" class="wk-ch-seller-buyer-url" target="_blank">$1</a>`
962        );
963        safeMsg = safeMsg.replace(/\n/g, "<br>");
964        return safeMsg;
965    }
966
967    buildAttachmentInDom(type, data, parentClass, childClass, msgColor = 3) {
968        console.log('updatedMessage', data);
969        const isBotMessage = data.opSenderName === 'Bot' || data.responseBy === 'ai';
970        wkli_chat.push(data);
971        // translate chat notices for display only, wkli_chat keeps the saved message
972        data = Object.assign({}, data, { message: wkli_translateLog(data.message) });
973        let div = document.createElement('div');
974        let usrData = JSON.parse(localStorage.getItem(localStorageVar));
975        div.className = parentClass;
976        
977        let childDiv = document.createElement("div");
978        childDiv.classList.add(childClass);
979        
980        if(data.messageId) {
981            childDiv.setAttribute('id', 'wkli'+data.messageId)
982        }
983        data.message = data.message.replace(/  /g, '');
984        if(data.reply) {
985            let replyDiv = document.createElement("div");
986            replyDiv.classList.add('wk-cw-replyMsg');
987            replyDiv.setAttribute('id', 'wk-cw-replyMsg')
988            let replyData = JSON.stringify(data.reply)
989            childDiv.setAttribute("onclick",`wkli_gotoMsgReplyFor(${replyData})`);
990            let senderName = wkli_replyYouText
991
992            if(data.reply.senderId == usrData.operator) {
993                senderName = wkli_replySupportText
994            }
995
996            // the sender label is admin configured text, so it goes in as text and never as markup
997            let replyNameEl = document.createElement('small')
998            replyNameEl.className = 'wk-cw-reply-sender-name'
999            replyNameEl.textContent = senderName
1000            let replyMsgEl = document.createElement('small')
1001            replyMsgEl.className = 'wk-cw-reply-chat-msg'
1002            replyMsgEl.innerHTML = this.buildReplyMessage(data.reply.message)
1003            replyDiv.appendChild(replyNameEl)
1004            replyDiv.appendChild(document.createElement('br'))
1005            replyDiv.appendChild(replyMsgEl)
1006            div.appendChild(replyDiv);
1007            childDiv.appendChild(replyDiv);
1008        }
1009
1010        if (type == 1) {
1011            console.log("typeone hai")
1012            // let msg = data.message.replace(/</g, "&lt;").replace(/>/g, "&gt;").split(' \n')
1013            let msg;
1014            if (isBotMessage && /<\/?[a-z][\s\S]*>/i.test(data.message)) {
1015                msg = [data.message]; // keep HTML intact
1016            } else {
1017                msg = isBotMessage
1018                    ? data.message.split('\n')
1019                    : data.message.replace(/</g, "&lt;").replace(/>/g, "&gt;").split('\n');
1020            }
1021            let getext = msg[0].split('/')
1022            let checkImgExt = msg[0].split('.')
1023            let attachmentName = getext[getext.length - 1]
1024            const audioTypes = ['mp3','ogg','wav']
1025            if (helper.checkImg.includes(checkImgExt[checkImgExt.length - 1])) {
1026                let img = document.createElement("img");
1027                img.setAttribute('src', msg[0]);
1028                img.classList.add('wk-ch-livechat-image');
1029                let br = document.createElement("br");
1030                childDiv.appendChild(img)
1031                childDiv.appendChild(br)
1032            } else if(audioTypes.indexOf(checkImgExt.pop()) !== -1) {
1033                childDiv.style.minWidth = '230px'
1034                let audio = document.createElement("audio");
1035                audio.style.width = "100%";
1036                audio.setAttribute('src', msg[0]);
1037                audio.setAttribute('controls', '');
1038                let br = document.createElement("br");
1039                childDiv.appendChild(audio)
1040                childDiv.appendChild(br)
1041            }
1042            let anchor = document.createElement("A");
1043            anchor.setAttribute("href", msg[0]);
1044            anchor.setAttribute("download", attachmentName);
1045            let downloadDiv = document.createElement("div");
1046            downloadDiv.classList.add("wk-ch-livechat-download-button")
1047            let attachmentNameDiv = document.createElement("div");
1048            attachmentNameDiv.appendChild(document.createTextNode(attachmentName.replace(/</g, "&lt;").replace(/>/g, "&gt;")));
1049            attachmentNameDiv.classList.add("wk-ch-livechat-attachmentName");
1050            anchor.appendChild(downloadDiv)
1051            anchor.appendChild(attachmentNameDiv)
1052            anchor.style.textDecoration = 'none'
1053            let textColor = "#111111"
1054            if (msgColor == 1) {
1055                if ((usrData && usrData.senderId && usrData.senderId != data.senderId) || data.onlineStatus)
1056                    childDiv.style.background = wkli_theamColor;
1057                if (childClass == "user-to-operator-msg" && parentClass == "wk-cw-user-to-operator-msg") {
1058                    textColor = '#111111'
1059                } else {
1060                    textColor = '#ffffff'
1061                }
1062            } else if (msgColor == 2) {
1063                childDiv.style.background = wkli_theamColor;
1064                textColor = '#ffffff'
1065            }
1066            anchor.style.color = textColor;
1067            childDiv.appendChild(anchor)
1068            if (msg.length > 1 && msg[1] != "") {
1069                let br = document.createElement("br");
1070                childDiv.appendChild(br)
1071                let childDivForTxt = document.createElement('div');
1072                // childDivForTxt.innerHTML = msg[1].replace(helper.link_exp, `<a href="$1" class="wk-ch-seller-buyer-url" target="_blank" style="color:${textColor}">$1</a>`);
1073                childDivForTxt.innerHTML = this.formatChatMessage(msg[1], isBotMessage, textColor);
1074                childDivForTxt.style.color = textColor;
1075                childDivForTxt.classList.add("wk-ch-livechat-textWithAttachment")
1076                childDiv.appendChild(childDivForTxt)
1077            }
1078            div.appendChild(childDiv)
1079        }else if(type == 3){
1080            // let textColor = "#111111"
1081            let textColor = "#fff"
1082            if (msgColor == 3) {
1083                childDiv.style.background = wkli_theamColor;
1084                textColor = '#ffffff'
1085            }
1086            // childDiv.innerHTML += data.message.replace(helper.link_exp, `<a href="$1" class="wk-ch-seller-buyer-url" target="_blank" style="color:${textColor}">$1</a>`);
1087            childDiv.innerHTML += this.formatChatMessage(data.message, isBotMessage, textColor);
1088            div.appendChild(childDiv);
1089        } else if(type == 4) {
1090            let textColor = "#ffffff"
1091            childDiv.innerHTML += data.message
1092            div.appendChild(childDiv);
1093            textColor = '#ffffff'
1094            let br = document.createElement("br");
1095            childDiv.appendChild(br)
1096            let imgTag = new DOMParser().parseFromString(data.message,'text/xml')
1097            if(imgTag.getElementsByTagName('img')?.[0]?.getAttribute('src')) {
1098                let imgSrc= imgTag.getElementsByTagName('img')[0].getAttribute('src')
1099                let getext = imgSrc.split('/')
1100                let attachmentNames = getext[getext.length - 1]
1101                var length = 25;
1102                var attachmentName = attachmentNames.substring(0, length);
1103                let anchor = document.createElement("A");
1104                anchor.setAttribute("href", imgSrc);
1105                anchor.setAttribute("download", attachmentName);
1106                let downloadDiv = document.createElement("div");
1107                downloadDiv.classList.add("wk-ch-livechat-download-button")
1108                let attachmentNameDiv = document.createElement("div");
1109                attachmentNameDiv.appendChild(document.createTextNode(attachmentName.replace(/</g, "&lt;").replace(/>/g, "&gt;")));
1110                attachmentNameDiv.classList.add("wk-ch-livechat-attachmentName");
1111                anchor.appendChild(downloadDiv)
1112                anchor.appendChild(attachmentNameDiv)
1113                anchor.style.textDecoration = 'none'
1114                textColor = "#ffffff"
1115                anchor.style.color = textColor;
1116                childDiv.appendChild(anchor)
1117            }
1118        }
1119        else {
1120            let textColor = "#111111"
1121            if (msgColor == 1) {
1122                if ((usrData && usrData.senderId && usrData.senderId != data.senderId) || data.onlineStatus || data.type == 3)
1123                    childDiv.style.background = wkli_theamColor;
1124                if (childClass == "user-to-operator-msg" && parentClass == "wk-cw-user-to-operator-msg") {
1125                    textColor = '#111111'
1126                } else {
1127                    textColor = '#ffffff'
1128                }
1129            } else if (msgColor == 2) {
1130                childDiv.style.background = wkli_theamColor;
1131                textColor = '#ffffff'
1132            }
1133            if(data.forClient || data.allreadyTicketCreated){
1134                const ticketContent = data.message
1135                const lines = ticketContent.split("/");
1136                const ticketNumber = lines[lines.length - 1];
1137                if(data.allreadyTicketCreated){
1138                    childDiv.innerHTML += data.message
1139                }else{
1140                    childDiv.innerHTML += data.message.replace(helper.link_exp, `Thank you for reaching out to us. Unfortunately, none of our operators are available at the moment. But don't worry! We are creating a ticket on your behalf, and you will be notified over email once the team gets back to you.\n\n <a href=${data.message} class="wk-ch-seller-buyer-url" target="_blank" style="color:${textColor}"><u>Click here to access the ticket #${ticketNumber}</u></a>`);
1141                }
1142            }else{
1143                // childDiv.innerHTML += data.message.replace(helper.link_exp, `<a href="$1" class="wk-ch-seller-buyer-url" target="_blank" style="color:${textColor}">$1</a>`);
1144                childDiv.innerHTML += this.formatChatMessage(data.message, isBotMessage, textColor);
1145            }
1146            div.appendChild(childDiv);
1147        }
1148        let dateTime = document.createElement("div");
1149        dateTime.classList.add('wk-cw-parent-dateTime');
1150        let replyButton = document.createElement("span");
1151        replyButton.classList.add('wk-cw-reply-button');
1152        let d1 = JSON.stringify(data);
1153        replyButton.setAttribute("id","rep"+data.messageId);
1154        replyButton.setAttribute("onclick",`wkli_replyButtonBody(${d1})`);
1155
1156        let span = document.createElement("span");
1157        span.classList.add('wk-cw-dateTime')
1158
1159        let messageStatusTrue = document.createElement("span");
1160        messageStatusTrue.classList.add('wk-cw-message-send');
1161    
1162        let messageStatusWait = document.createElement("span");
1163        messageStatusWait.classList.add('wk-cw-message-wait');
1164
1165        // span.innerHTML = new Date().toLocaleString();
1166        if(data.sendTimestamp) {
1167            span.innerHTML = getLocalTimestamp(data.sendTimestamp)
1168        } else {
1169            span.innerHTML = getLocalTimestamp(new Date())
1170        }
1171        if(data.tick) {
1172            dateTime.appendChild(messageStatusTrue);
1173        } else {
1174            dateTime.appendChild(messageStatusWait);
1175        }
1176        dateTime.appendChild(span);
1177        if(data.messageId && !data.forClient){
1178            dateTime.appendChild(replyButton);
1179        }
1180        div.appendChild(dateTime);
1181        helper.getElement(Ids.user_operator_chat_holder).appendChild(div);
1182    }
1183
1184    buildQueriesInDom(type, data, parentClass, childClass, msgColor = 3){
1185        let div = document.createElement('div');
1186        div.className = parentClass;
1187        let childDiv = document.createElement("div");
1188        childDiv.classList.add(childClass);
1189        // childDiv.style.color = wkli_theamColor;
1190        // childDiv.setAttribute("onmouseover","helper.chnageQuestionView(this)");
1191        // childDiv.setAttribute("onmouseout","helper.resetQuestionView(this)"); 
1192        childDiv.setAttribute("onclick",`new Form().getQueryResult(this)`);
1193        childDiv.setAttribute("id", data._id);
1194        childDiv.style.background = wkli_theamColor;
1195        childDiv.innerHTML = data.question.replace(helper.link_exp, `<a href="$1" class="wk-ch-seller-buyer-url" target="_blank" style="color:${wkli_theamColor}">$1</a>`);
1196        div.appendChild(childDiv);
1197        let dateTime = document.createElement("div");
1198        dateTime.classList.add('wk-cw-parent-dateTime');
1199        let span = document.createElement("span");
1200        span.classList.add('wk-cw-dateTime')
1201        // span.innerHTML = new Date().toLocaleString();
1202        if(data.sendTimestamp) {
1203            span.innerHTML = getLocalTimestamp(data.sendTimestamp)
1204        }
1205        dateTime.appendChild(span);
1206        div.appendChild(dateTime);
1207        helper.getElement(Ids.user_operator_chat_holder).appendChild(div);
1208    }
1209
1210    //for ai chatbot and basic chatbot
1211    buildOptionsInDom(data, parentClass, childClass) {
1212        let div = document.createElement('div');
1213        div.className = parentClass;
1214        let childDiv = document.createElement("div");
1215        childDiv.classList.add(childClass);
1216        childDiv.setAttribute("onclick",`new Form().processingNextOption(this)`);
1217        childDiv.setAttribute("id", data.id);
1218        childDiv.style.background = wkli_theamColor;
1219        childDiv.innerHTML = data.label.replace(helper.link_exp, `<a href="$1" class="wk-ch-seller-buyer-url" target="_blank" style="color:${wkli_theamColor}">$1</a>`);
1220        div.appendChild(childDiv);
1221        helper.getElement(Ids.user_operator_chat_holder).appendChild(div);
1222    }
1223
1224    proceedToRegistration() {
1225        return new Promise((resolve, reject) => {
1226            let customer_email = this.getRegistrationEmail()
1227            let customer_name = this.getRegistrationName()
1228            this.getClientToken(false, customer_email, cb => {
1229                if(cb && cb.data) {
1230                    let msg = `<------ ${location.href} ------>`
1231                    this.buildMessage(msg, 2, (data) => {
1232                        data.chatInitiateNoti = false;
1233                        data.clientToken = cb.data;
1234                        this.chnageMessageDetails(data, (updatedMessage) => {
1235                            if(customer_email)
1236                                updatedMessage.email = customer_email
1237                            if(customer_name)
1238                                updatedMessage.name = customer_name
1239                            let departmentId = this.getSelectedDepartmentId()
1240                            if(departmentId)
1241                                updatedMessage.departmentId = departmentId
1242                            let customFields = this.getCustomFieldsObject()
1243                            if(customFields)
1244                                updatedMessage.customFields = customFields
1245                            let option = {
1246                                method: 'POST',
1247                                headers: {'Content-Type': 'application/json'},
1248                                body: JSON.stringify(updatedMessage)
1249                            }
1250                            fetch(`${WKprotocol}${WKscript}/wkcs/register-client`,option).then(res => res.json()).then(data => {
1251                                console.log(data)
1252                                if(data && data.status == 1 && data.data) {
1253                                    let client = data.data
1254                                    let save = {
1255                                        domain: client.domain,
1256                                        senderId: client.senderId,
1257                                        uniqueId: client.uniqueId,
1258                                        enable: true
1259                                    }
1260                                    if(client.saveOperatorData) {
1261                                        save.name = wkli_showOperatorName ? wkli_botName : wkli_opName;
1262                                        save.operator = client.receiverId;
1263                                        save.operatorStatus = true;
1264                                        document.getElementById("wk-ch-operatorOnline").style.display = "inline-block";
1265                                        document.getElementById("wk-ch-operatorOnline").style.background = "chartreuse";
1266                                        document.getElementById("operatorName").textContent = wkli_showOperatorName ? wkli_botName : wkli_opName;
1267                                    }
1268                                    if(client.email)
1269                                        save.clientEmail = client.email
1270                                    if(client.name)
1271                                        save.clientName = client.name
1272                                    if (!JSON.parse(localStorage.getItem(localStorageVar))) {
1273                                        if (wkli_restart_chat_field)
1274                                            save.restartChatValue = wkli_getInjectedValue(wkli_restart_chat_field)
1275                                        localStorage.setItem(localStorageVar, JSON.stringify(save));
1276                                        helper.toggleChatHistory()
1277                                        if(typeof(media) == 'object') {
1278                                            media.senderName = client.name ? client.name : client.uniqueId;
1279                                            media.senderId = client.uniqueId;
1280                                            media.senderEmail = client.email ? client.email : client.uniqueId;
1281                                        }
1282                                    }
1283                                }
1284                                resolve(true)
1285                            }).catch(error => {
1286                                console.log(error)
1287                                resolve(false)
1288                            })
1289                        })
1290                    })
1291                } else {
1292                    resolve(false)
1293                }
1294            })
1295        })
1296    }
1297
1298    async processingNextOption(element) {
1299        if(wkli_client_blocked)
1300            return false;
1301        let reg_status = false
1302        if(!JSON.parse(localStorage.getItem(localStorageVar))) {
1303            reg_status = await this.proceedToRegistration();
1304            if(!reg_status)
1305                return false
1306            this.sendCustomFieldMessage()
1307        }
1308        if(!wkli_option_event && element.getAttribute('id')) {
1309            wkli_option_event = element.getAttribute('id')
1310            if ((element.textContent).trim()) {
1311                let msg = (element.textContent).trim();
1312                this.buildMessage(msg, 1, (data) => {
1313                    this.chnageMessageDetails(data, (updatedMessage) => {
1314                        updatedMessage.tick = true
1315                        this.buildAttachmentInDom(3, updatedMessage, "wk-cw-user-to-operator-msg", "user-to-operator-msg", 2);
1316                        this.scrollHeight();
1317                        updatedMessage.reg_status = reg_status
1318                        updatedMessage.option_id = wkli_option_event;
1319                        updatedMessage.option_step = wkli_option_step;
1320                        updatedMessage.domainName = location.hostname
1321                        updatedMessage.Shopify_shop_name = Shopify ? Shopify.shop : location.hostname
1322                        if (location.hostname.includes('localhost'))
1323                            updatedMessage.domainName = 'saurabh-store-openai.myshopify.com'
1324                        localStorage.setItem(localAutoChat, JSON.stringify({id: wkli_option_event}));
1325                        if(localStorage.getItem(localStorageVar) && JSON.parse(localStorage.getItem(localStorageVar))) {
1326                            updatedMessage.customer_email = JSON.parse(localStorage.getItem(localStorageVar)).clientEmail
1327                        }
1328                        if(wkli_shopify_customer.email) {
1329                            updatedMessage.customer_email = wkli_shopify_customer.email
1330                        }
1331                        wkli_socket.emit("processSelfService",updatedMessage);
1332                        this.disableChatWithAgent()
1333                    })
1334                })
1335            }
1336        } else if(wkli_option_event) {
1337            this.buildMessage(element, 1, (data) => {
1338                this.chnageMessageDetails(data, (updatedMessage) => {
1339                    updatedMessage.tick = true
1340                    this.buildAttachmentInDom(3, updatedMessage, "wk-cw-user-to-operator-msg", "user-to-operator-msg", 2);
1341                    this.scrollHeight();
1342                    updatedMessage.option_id = wkli_option_event;
1343                    updatedMessage.option_step = wkli_option_step;
1344                    updatedMessage.orderId = wkli_orderId
1345                    updatedMessage.reason = wkli_reason
1346                    updatedMessage.domainName = location.hostname
1347                    updatedMessage.Shopify_shop_name = Shopify ? Shopify.shop : location.hostname
1348                    if (location.hostname.includes('localhost')) {
1349                        updatedMessage.domainName = 'saurabh-store-openai.myshopify.com'
1350                        updatedMessage.customerId = ''
1351                    }
1352                    // localStorage.setItem(localAutoChat, JSON.stringify({id: wkli_option_event}));
1353                    if(wkli_shopify_customer.id) {
1354                        updatedMessage.customerId = wkli_shopify_customer.id
1355                    }
1356                    if(localStorage.getItem(localStorageVar) && JSON.parse(localStorage.getItem(localStorageVar))) {
1357                        updatedMessage.customer_email = JSON.parse(localStorage.getItem(localStorageVar)).clientEmail
1358                    }
1359                    if(wkli_shopify_customer.email) {
1360                        updatedMessage.customer_email = wkli_shopify_customer.email
1361                    }
1362                    wkli_socket.emit("processSelfService",updatedMessage);
1363                    if(document.getElementById("wk-cw-typing-loader"))
1364                        document.getElementById("wk-cw-typing-loader").remove()
1365                    this.buildTypingLoaderInDom()
1366                    this.disableChatWithAgent()
1367                })
1368            })
1369        }
1370    }
1371    //end
1372
1373    showAITyping() {
1374        if(wkli_AI_chatbot) {
1375            let div = document.createElement('div')
1376            div.classList.add('wk-cw-livechat-opeTyping')
1377            div.innerHTML = `<span class="wk-cw-livechat-dot"></span><span class="wk-cw-livechat-dot"></span><span class="wk-cw-livechat-dot"></span>`
1378            helper.getElement(Ids.user_operator_chat_holder).appendChild(div)
1379        }
1380    }
1381
1382    removeAITyping() {
1383        const typingDiv = document.querySelectorAll('.wk-cw-livechat-opeTyping');
1384        typingDiv.forEach(div => {
1385            div.remove();
1386        });
1387    }
1388
1389    buildReplyMessage(data) {
1390        if(data.includes('chatwhizz-new.s3.amazonaws.com')) {
1391            let arr = data.split('/')
1392            if(arr && arr.length) {
1393                return arr[arr.length-1]
1394            } else
1395                return data
1396        } else 
1397            return data
1398    }
1399
1400    buildTypingLoaderInDom(){
1401        let div = document.createElement('div');
1402        let span1 = document.createElement('span');
1403        let span2 = document.createElement('span');
1404        let span3 = document.createElement('span');
1405
1406        div.classList.add("wk-cw-typing-loader");
1407        div.setAttribute("id", "wk-cw-typing-loader");
1408
1409        span1.classList.add("wk-cw-typing-loader-first-child", "wk-cw-typing-loader-child");
1410        span1.setAttribute("id", "wk-cw-typing-loader-first-child");
1411        div.appendChild(span1);
1412
1413        span2.classList.add("wk-cw-typing-loader-second-child", "wk-cw-typing-loader-child");
1414        span2.setAttribute("id", "wk-cw-typing-loader-second-child");
1415        div.appendChild(span2);
1416
1417        span3.classList.add("wk-cw-typing-loader-third-child", "wk-cw-typing-loader-child");
1418        span3.setAttribute("id", "wk-cw-typing-loader-third-child");
1419        div.appendChild(span3);
1420
1421        helper.getElement(Ids.user_operator_chat_holder).appendChild(div);
1422        this.scrollHeight()
1423    }
1424
1425    preClientQueries () {
1426        //for ai chatbot and basic chatbot
1427        if(!wkli_basic_chatbot) {
1428            wkli_question.forEach((data,i)=>{
1429                setTimeout(()=>{
1430                    this.buildQueriesInDom(2, data, 'wk-cw-operator-to-user-queries', 'operator-to-user-queries', 1);
1431                    this.scrollHeight();
1432                },(i+1) * 1000);
1433            })
1434        } else {
1435            console.log('running self serivce')
1436            helper.refreshBasicChatbot()
1437            wkli_basic_chatbot_option.forEach((data, i) => {
1438                if(data.status) {
1439                    setTimeout(()=>{
1440                        this.buildOptionsInDom(data, 'wk-cw-operator-to-user-queries', 'operator-to-user-queries');
1441                        this.scrollHeight();
1442                    });
1443                }
1444            })
1445        }
1446    }
1447    //end
1448    reconnectResendMessage(){
1449        setTimeout(() => {
1450            if (helper.reSendMessages.length && localStorage.getItem(localStorageVar)) {
1451                helper.reSendMessages.forEach((msg)=>{
1452                    helper.user_operator_conversation.push(msg)
1453                    this.sendMessage()
1454                })
1455                helper.user_operator_conversation = [];
1456            } else {
1457                helper.reSendMessages.forEach((msg)=>{
1458                    document.querySelector(`#wkli${msg.messageId}`).parentElement.remove();
1459                })
1460            }
1461        }, 2000);
1462    }
1463
1464    getOldChatHistory() {
1465        if(wkli_client_blocked)
1466            return false;
1467        if(localStorage.getItem(localStorageVar) && JSON.parse(localStorage.getItem(localStorageVar))) {
1468            let localData = JSON.parse(localStorage.getItem(localStorageVar))
1469            if(localData.clientEmail && localData.clientEmail && localData.senderId) {
1470                let clientEmail = localData.clientEmail;
1471                let domain = localData.domain;
1472                let senderId = localData.senderId
1473                wkli_socket.emit('get-chat-history', {clientEmail: clientEmail, domain: domain, senderId: senderId})
1474            }
1475        }else if(JSON.parse(localStorage.getItem('restrictChatHistory')) && JSON.parse(localStorage.getItem('restrictChatHistory')).clientEmail){
1476            let localDataRestrictChat = JSON.parse(localStorage.getItem('restrictChatHistory'))
1477            let clientEmail = localDataRestrictChat.clientEmail;
1478            let domain = localDataRestrictChat.domain;
1479            wkli_socket.emit('get-chat-history', {clientEmail: clientEmail, domain: domain})
1480        }
1481    }
1482
1483    getMessageFromOperator() {
1484
1485        this.getUserOperatorData()
1486
1487        wkli_socket.on('connect', () => {
1488            if (JSON.parse(localStorage.getItem(localStorageVar)) && JSON.parse(localStorage.getItem(localStorageVar)).uniqueId) {
1489                wkli_socket.emit('socketReconnect', JSON.parse(localStorage.getItem(localStorageVar)));
1490                this.reconnectResendMessage()
1491                
1492                if(disconnectAt >= 0) {
1493                    setTimeout(() => {
1494                        // document.getElementById('wk-cw-user-operator-chat').innerHTML = '';
1495                        user.socketRejoin(true);
1496                    }, 4000);
1497                    fetch(`${WKprotocol}${WKscript}/wkcs/reconnected-client`).then(res => res.json()).then(data => {
1498                        console.log(data)
1499                        if(data.maintenance) {
1500                            this.switchMaintenanceMode();
1501                            setTimeout(() => {
1502                                document.getElementById(Ids.MAIN_COINTAINER).remove(); 
1503                                createMaintenanceWidget();          
1504                            }, 5000)
1505                        }
1506                    }).catch(error => {
1507                        console.log(error)
1508                    })
1509                }
1510                disconnectAt ++;
1511            }
1512            wkli_isSocketConnected = true
1513            wkli_checkRestartChat()
1514            let wifiDissconnect = document.getElementById('wkInternetDissconnect');
1515            wifiDissconnect.style.display ="none";
1516        })
1517
1518        wkli_socket.on('disconnect', () => {
1519            wkli_isSocketConnected = false 
1520            let wifiDissconnect = document.getElementById('wkInternetDissconnect');
1521            wifiDissconnect.style.display ="flex";
1522        });
1523
1524        wkli_socket.on("sendMessageAckOfUser", (data) => {
1525            if(data && data.isChatEnd && data.messageId && document.querySelector(`#wkli${data.messageId}`)){
1526                document.querySelector(`#wkli${data.messageId}`).parentElement.remove();
1527                return
1528            }
1529
1530            if (data.sendTimestamp && data.messageId && helper.reSendMessages.length) {
1531                helper.reSendMessages = helper.reSendMessages.filter((msg) => {
1532                    if (data.messageId !== msg.messageId) {
1533                        return true; // Keep the element in the filtered array
1534                    }
1535                    return false; // Exclude the element from the filtered array
1536                });
1537            }
1538            if(data.type == 6 && data.agentChataInitiated){
1539                let user = JSON.parse(localStorage.getItem(localStorageVar))
1540                user.operator = '';
1541                localStorage.setItem(localStorageVar, JSON.stringify(user));
1542                return;
1543            }
1544            if(wkli_selectedChatOption == 'whatsapp'){
1545                localStorage.removeItem(localStorageVar);
1546                return;
1547            }
1548            
1549            if(data && data.messageId && document.querySelector(`#wkli${data.messageId}`)){
1550                document.querySelector(`#wkli${data.messageId}`).nextElementSibling.children[0].classList.remove('wk-cw-message-wait');
1551                document.querySelector(`#wkli${data.messageId}`).nextElementSibling.children[0].classList.add('wk-cw-message-send');
1552            }
1553            let save = {
1554                domain: data.domain,
1555                senderId: data.senderId,
1556                uniqueId: data.uniqueId,
1557                enable: true
1558            }
1559            if(data.name)
1560                save.clientName=data.name
1561            if(data.email)
1562                save.clientEmail=data.email
1563                
1564            if(data.saveOperatorData){
1565                save.name = wkli_showOperatorName ? wkli_botName : wkli_opName;
1566                save.operator = data.receiverId;
1567                save.operatorStatus = true;
1568                document.getElementById("wk-ch-operatorOnline").style.display = "inline-block";
1569                document.getElementById("wk-ch-operatorOnline").style.background = "chartreuse";
1570                document.getElementById("operatorName").textContent = wkli_showOperatorName ? wkli_botName : wkli_opName;
1571            }
1572            let autoChatApi = JSON.parse(localStorage.getItem('autoChatApi'))
1573            if(wkli_autoChatBotType && wkli_autoChatBotType == '2' && autoChatApi){
1574                document.getElementById("operatorName").textContent = wkli_botName;
1575            }
1576            if (!JSON.parse(localStorage.getItem(localStorageVar))) {
1577                if (wkli_restart_chat_field)
1578                    save.restartChatValue = wkli_getInjectedValue(wkli_restart_chat_field)
1579                localStorage.setItem(localStorageVar, JSON.stringify(save));
1580                helper.toggleChatHistory()
1581                if(typeof(media) == 'object') {
1582                    media.senderName = data.name ? data.name : data.uniqueId;
1583                    media.senderId = data.uniqueId;
1584                    media.senderEmail = data.email ? data.email : data.uniqueId;
1585                }
1586            }
1587            if(data.isbotOperator && !JSON.parse(localStorage.getItem(localStorageVar)).operator){
1588                let user = JSON.parse(localStorage.getItem(localStorageVar))
1589                user.operator = data.receiverId;
1590                user.botOpStatus = true;
1591                localStorage.setItem(localStorageVar, JSON.stringify(user));
1592            }
1593
1594            if (!wkli_showForm && document.getElementsByClassName("wk-cw-user-to-operator-msg").length == 0 && data.saveOperatorData) {
1595                if ((helper.getElement("wk-cw-message").value).trim()) {
1596                    let msg = (helper.getElement("wk-cw-message").value).trim();
1597                    this.buildMessage(msg, 1, (data) => {
1598                        this.chnageMessageDetails(data, (updatedMessage) => {
1599                            helper.user_operator_conversation.push(updatedMessage)
1600                            this.buildMessageInDom(updatedMessage)
1601                            helper.getElement("wk-cw-message").value = "";
1602                            helper.getElement("wk-cw-message").rows = 1
1603                        })
1604                    })
1605
1606                }
1607            }
1608
1609            //the client record exists now, so the agent request that triggered this registration
1610            //can go out with its senderId
1611            if (wkli_pending_agent_chat && JSON.parse(localStorage.getItem(localStorageVar))) {
1612                let pendingAgentChat = wkli_pending_agent_chat;
1613                wkli_pending_agent_chat = null;
1614                this.startChatWithAgent(pendingAgentChat.initType, pendingAgentChat.msgData);
1615            }
1616
1617            let endChat = document.getElementById('wkEndChat');
1618            endChat.style.display = "flex";
1619
1620            // helper.isOffline = false;
1621        })
1622        //for ai chatbot and basic chatbot
1623        wkli_socket.on("processSelfService", (data) => {
1624            wkli_option_step = data.option_step
1625            wkli_orderId = data.orderId ? data.orderId : ''
1626            wkli_reason = data.reason ? data.reason : ''
1627            if(['question', 'response', 'optionalQuestion', 'reason', 'email', 'otp'].includes(data.option_step)) {
1628                if(document.getElementById("wk-cw-typing-loader"))
1629                    document.getElementById("wk-cw-typing-loader").remove()
1630                this.buildAttachmentInDom(3, data, "wk-cw-operator-to-user-msg", "operator-to-user-msg", 3);
1631                this.scrollHeight();
1632                if(!data.orderno && data.event == 'getOrderNo' || data.option_step == 'question' || data.option_step == 'optionalQuestion' || data.option_step == 'reason' || data.option_step == 'email' || data.option_step == 'otp') {
1633                    this.enableChatWithAgent()
1634                }
1635            }
1636        })
1637        //to initiate operator agent chat if ai failed
1638        wkli_socket.on('initiateAgetChat',(data)=>{
1639            let user = JSON.parse(localStorage.getItem(localStorageVar))
1640            if(data.operatorOnline){
1641                this.startChatWithAgent(2,data)
1642                if(user?.is_operator_online == false){
1643                    user.is_operator_online = true
1644                }
1645            }else{
1646                user.is_operator_online = false
1647                document.getElementById("wk-ch-operatorOnline").style.background = "chartreuse";
1648            }
1649            localStorage.setItem(localStorageVar, JSON.stringify(user))
1650        })
1651        // socket reconnect check operator
1652        wkli_socket.on('reconnectionOp',(data)=>{
1653            this.assignOperatorChat(data)
1654        }) 
1655        //end
1656
1657        wkli_socket.on("msgToFrontUser", (data) => {
1658            if(!document.getElementById(Ids.MODEL_COINTAINER).classList.contains('wk-cw-show')) {
1659                helper.getElement(Ids.unreadMessage).style.display = "inline-block"
1660                helper.getElement(Ids.unreadMessage).innerHTML = helper.unreadMessageCount + 1
1661                helper.unreadMessageCount += 1
1662            }
1663            document.getElementById("wk-cw-isTyping").style.display = "none"
1664            let autoChatApi = JSON.parse(localStorage.getItem('autoChatApi'))
1665            //a reply landed, so the send lock goes regardless of who answered. assignOperatorChat()
1666            //clears autoChatApi on operator takeover, and gating this on it left the client locked out
1667            preventSendingMsg = false;
1668            if(wkli_autoChatBotType && wkli_autoChatBotType == '2' && autoChatApi){
1669                document.getElementById("operatorName").textContent = wkli_botName;
1670                document.getElementById("wk-ch-operatorOnline").style.background = "chartreuse";
1671
1672            }
1673            if (data.type != 2) {
1674                // let msg = data.message.replace(/</g, "&lt;").replace(/>/g, "&gt;").split(' \n');
1675                let msg;
1676                if (data.responseBy === 'ai' || data.opSenderName === 'Bot') {
1677                    msg = data.message.split('\n');
1678                } else {
1679                    msg = data.message.replace(/</g, "&lt;").replace(/>/g, "&gt;").split(' \n');
1680                }
1681                let getext = msg[0].split('.')
1682                let ext = getext[getext.length - 1]
1683                if (/<img[^>]+src="([^">]+)/.test(data.message)) {
1684                    this.buildAttachmentInDom(4, data, "wk-cw-operator-to-user-msg", "operator-to-user-msg", 1);
1685                }
1686                else if (helper.link_exp.test(data.message) || (helper.checkAttachment.includes(ext))) {
1687                    if (msg[0].includes(".s3.amazonaws.com")) {
1688                        this.buildAttachmentInDom(1, data, "wk-cw-operator-to-user-msg", "operator-to-user-msg", 2);
1689                    } else {
1690                        this.buildAttachmentInDom(2, data, "wk-cw-operator-to-user-msg", "operator-to-user-msg", 2);
1691                    }
1692                } else {
1693                    this.buildAttachmentInDom(2, data, "wk-cw-operator-to-user-msg", "operator-to-user-msg", 2);
1694                }
1695            }
1696            this.scrollHeight();
1697            // let component = helper.getElement(Ids.CHATBOT)
1698            // let css = getComputedStyle(component)
1699            if (document.getElementById(Ids.MODEL_COINTAINER).classList.contains('wk-cw-show'))
1700                data.seenTimestamp = new Date().toISOString();
1701            else
1702                data.delieverdTimestamp = new Date().toISOString();
1703
1704            // this.messageSound(100, 520, 200)
1705            this.messageSound();
1706            data.userId = data.receiverId
1707            wkli_socket.emit("operatormsgRecieveAck", data);
1708
1709            if(wkli_AI_chatbot) {
1710                if(ai_message.question) {
1711                    ai_message.history.push({"type": "human", "text": ai_message.question})
1712                    ai_message.history.push({"type": "ai", "text": data.message})
1713                }
1714                if(data.responseBy == 'ai') {
1715                    this.removeAITyping()
1716                }
1717            }
1718
1719            if(helper.getElement("wk-chat-end-confirmation").style.display == 'block') {
1720                helper.getElement(Ids.wkConfirmationCancel).click()
1721            } else {
1722                helper.startChatTimeout()
1723            }
1724        })
1725
1726        wkli_socket.on('getAllMessages', (response) => {
1727            preventSendingMsg = false;
1728            if(wkli_selectedChatOption == 'whatsapp')
1729                return;
1730            if(helper.checkRestrictAgentChatCondition()){
1731                helper.getElement(Ids.Text_Container).style.display = "none";
1732                let data = {
1733                    message: wkli_errorPermissionMsg
1734                }
1735                this.buildErrorAttachInDom(data)
1736                return
1737            }
1738            if (response.unseenCount > 0 && response.messages) {
1739                helper.getElement(Ids.unreadMessage).style.display = "inline-block"
1740                helper.getElement(Ids.unreadMessage).innerHTML = response.unseenCount
1741                helper.unreadMessageCount = response.unseenCount
1742            }
1743            let usrData = JSON.parse(localStorage.getItem(localStorageVar));
1744            if(response.isOperatorOnline && usrData) {
1745                usrData.isOperatorOnline = response.isOperatorOnline;
1746                localStorage.setItem(localStorageVar, JSON.stringify(usrData))
1747                document.getElementById("wk-ch-operatorOnline").style.background = "chartreuse";
1748            }
1749            let parentClass, childClass;
1750            let endChat = document.getElementById('wkEndChat');
1751            if(response.reconnect)
1752                document.getElementById('wk-cw-user-operator-chat').innerHTML = '';
1753            if(response.messages && response.messages.length){
1754                if(helper.getElement("wk-chat-end-confirmation").style.display == 'block') {
1755                    helper.getElement(Ids.wkConfirmationCancel).click()
1756                } else {
1757                    helper.startChatTimeout()
1758                }
1759                response.messages.forEach(data => {
1760                    if (usrData && usrData.senderId && usrData.senderId == data.senderId && data.type != 3) {4
1761                        endChat.style.display = 'flex';
1762                        parentClass = "wk-cw-user-to-operator-msg";
1763                        childClass = "user-to-operator-msg";
1764                        data.tick = true;
1765                    } else if(data.type == 3 || true) {
1766                        parentClass = "wk-cw-operator-to-user-msg";
1767                        childClass = "operator-to-user-msg";
1768                    }
1769                    if (data.type != 2 && data.message) {
1770                        let msg = data.message.replace(/</g, "&lt;").replace(/>/g, "&gt;").split(' \n');
1771                        let getext = msg[0].split('.')
1772                        let ext = getext[getext.length - 1]
1773                        if (/<img[^>]+src="([^">]+)/.test(data.message)) {
1774                            this.buildAttachmentInDom(4, data, "wk-cw-operator-to-user-msg", "operator-to-user-msg", 1);
1775                        }
1776                        else if (helper.link_exp.test(data.message) || (helper.checkAttachment.includes(ext))) {
1777                            if (msg[0].includes(".s3.amazonaws.com")) {
1778                                this.buildAttachmentInDom(1, data, parentClass, childClass, 1);
1779                            } else {
1780                                this.buildAttachmentInDom(2, data, parentClass, childClass, 1);
1781                            }
1782                        } else {
1783                            data.onlineStatus = response.onlineStatus
1784                            this.buildAttachmentInDom(2, data, parentClass, childClass, 1)
1785                        }
1786                        if(wkli_AI_chatbot && data.responseBy && data.responseBy != 'ai-init') {
1787                            // if(!ai_message.question) {
1788                            //     ai_message.question = data.message
1789                            // } else {
1790                                if(!ai_message.history)
1791                                    ai_message.history = []
1792                                ai_message.history.push({
1793                                    "type": data.responseBy,
1794                                    "text": data.message
1795                                })
1796                            // }
1797                        }
1798                    }
1799                    // if(data.message.includes("Ticket has been created")){
1800                    //     this.ticketCreatedByOperator(data)
1801                    // }
1802                });
1803            }
1804            if (document.getElementById("loader-skin"))
1805                document.getElementById("loader-skin").style.display = "none";
1806            this.scrollHeight();
1807            let autoChatApi = JSON.parse(localStorage.getItem('autoChatApi'))
1808            if (response.offline && !autoChatApi) {
1809                helper.isOffline = true;
1810                document.getElementById("wk-ch-operatorOnline").style.background = "red";
1811            } else {
1812                helper.isOffline = false;
1813            }
1814            if (response.isChatEnd) {
1815                let data = {
1816                    message: "<------ Your chat has been ended ------>"
1817                }
1818                this.chatEndByOperatorNotification(data)
1819            }
1820            let localAutoReponseData = JSON.parse(localStorage.getItem(localAutoChat));
1821            if(localAutoReponseData && typeof(localAutoReponseData) == "object"){
1822                localAutoReponseData.domain = location.host;
1823                localAutoReponseData.onlyQuestion = true;
1824                wkli_socket.emit("getOnlyQuestion", localAutoReponseData);
1825            } else if(localAutoReponseData) {
1826                this.preClientQueries();
1827            }
1828            this.disableChatWithAgent()
1829            if(response.in_queue) {
1830                helper.in_queue = response.in_queue
1831            }
1832            if(response.hasOwnProperty('autoChatEnd')) {
1833                this.autoChatEndChangedByOperator(response.autoChatEnd)
1834            }
1835        })
1836
1837        wkli_socket.on('preClientQueries', ()=>{
1838            //for ai chatbot and basic chatbot
1839            if(wkli_autoChatBotType != '2'){
1840                if(!wkli_basic_chatbot && wkli_autoChatBotType != '2') {
1841                    wkli_question.forEach((data,i)=>{
1842                        setTimeout(()=>{
1843                            this.buildQueriesInDom(2, data, 'wk-cw-operator-to-user-queries', 'operator-to-user-queries', 1);
1844                            this.scrollHeight();
1845                            // document.getElementById("wk-cw-typing-loader").remove();
1846                        },(i+1) * 1000);
1847                        // if(i <= question.length-1){
1848                        //     setTimeout(()=>{
1849                        //         this.buildTypingLoaderInDom()
1850                        //     },(i+1) * 700);
1851                        // }
1852                    })
1853                } else {
1854                    console.log('running self serivce')
1855                    helper.refreshBasicChatbot()
1856                    helper.getElement(Ids.autoResponseAction).style.display = "grid";
1857                    wkli_basic_chatbot_option.forEach((data, i) => {
1858                        if(data.status) {
1859                            setTimeout(()=>{
1860                                this.buildOptionsInDom(data, 'wk-cw-operator-to-user-queries', 'operator-to-user-queries');
1861                                this.scrollHeight();
1862                            });
1863                        }
1864                    })
1865                }
1866            }
1867            //end
1868            if (document.getElementById("loader-skin"))
1869                document.getElementById("loader-skin").style.display = "none";
1870        })
1871
1872        wkli_socket.on('queryNextLevel', result => {
1873            result.forEach((data,i)=>{
1874                if(!data.isAnswer){
1875                    setTimeout(()=>{
1876                        this.buildQueriesInDom(2, data, 'wk-cw-operator-to-user-queries', 'operator-to-user-queries', 1);
1877                        this.scrollHeight();
1878                    },(1+i)*1000)
1879                }
1880            })
1881            query_status = false
1882        })
1883
1884        wkli_socket.on('queryResult', result => {
1885            result.forEach((data,i)=>{
1886                setTimeout(()=>{
1887                    data.message = data.answer;
1888                    delete data.answer;
1889                    data.senderId = "";
1890                    this.buildAttachmentInDom(2, data, 'wk-cw-operator-to-user-msg', 'operator-to-user-msg', 2);
1891                    this.scrollHeight();
1892                    // document.getElementById("wk-cw-typing-loader").remove();
1893                },(1+i)*1000)
1894                // if(i <= question.length-1){
1895                //     setTimeout(()=>{
1896                //         this.buildTypingLoaderInDom()
1897                //     },(i+1) * 700);
1898                // }
1899            })
1900        })
1901
1902        wkli_socket.on('noQueryResponseData', result => {
1903            query_status = false
1904        })
1905
1906        wkli_socket.on('assineOperatorToUserReqAck', (data) => {
1907            this.assignOperatorChat(data)
1908        })
1909
1910
1911        wkli_socket.on("transferClient", data => {
1912            // the new operator's display name is used only while the domain is configured for it
1913            let operatorName = (wkli_useOperatorDisplayName && data.displayName) ? data.displayName : data.name
1914            if (wkli_showOperatorName) {
1915                document.getElementById("operatorName").innerHTML = operatorName
1916            }
1917            if (data && JSON.parse(localStorage.getItem(localStorageVar))) {
1918                if (JSON.parse(localStorage.getItem(localStorageVar)).uniqueId == data.uniqueId) {
1919                    document.getElementById("wk-ch-operatorOnline").style.display = "inline-block"
1920                    let user = JSON.parse(localStorage.getItem(localStorageVar))
1921                    user.operator = data.operatorId;
1922                    user.name = operatorName
1923                    if (data.operatorStatus == 1) {
1924                        document.getElementById("wk-ch-operatorOnline").style.background = "chartreuse";
1925                        user.operatorStatus = true;
1926                    } else {
1927                        document.getElementById("wk-ch-operatorOnline").style.background = "red";
1928                        user.operatorStatus = false;
1929                    }
1930                    localStorage.setItem(localStorageVar, JSON.stringify(user))
1931                    this.getUserOperatorData()
1932                }
1933            }
1934        })
1935
1936        wkli_socket.on('sendUserDetailsAck', (data) => {
1937            wkli_registration_in_process = false
1938            let save = {
1939                // name: data.name,
1940                clientName: data.name,
1941                clientEmail: data.email,
1942                departmentId: data.departmentId,
1943                domain: data.domainName,
1944                senderId: data.senderId,
1945                uniqueId: data.uniqueId,
1946                enable: true,
1947            }
1948            if(data?.operator){
1949                save.operator = data.operator.botOperatorId
1950            }
1951            if (new URL(location.href).searchParams.get('name'))
1952                save.domain = new URL(location.href).searchParams.get('name')
1953            if (!JSON.parse(localStorage.getItem(localStorageVar))) {
1954                if (wkli_restart_chat_field)
1955                    save.restartChatValue = wkli_getInjectedValue(wkli_restart_chat_field)
1956                localStorage.setItem(localStorageVar, JSON.stringify(save))
1957                if(typeof(media) == 'object') {
1958                    media.senderName = data.name;
1959                    media.senderId = data.uniqueId;
1960                    media.senderEmail = data.email;
1961                }
1962            }
1963            if (document.getElementsByClassName("wk-cw-user-to-operator-msg").length == 0) {
1964                this.sendChatInitiateNoti();
1965                if(data.isWhatsAppClient) {
1966                    // let msg = `email: ${data.email}`
1967                    // if(user.isMobile()){
1968                    //     window.open(`https://api.whatsapp.com/send?phone=${wkli_waba_number}&text=Hi`,"_blank");
1969                    // } else{
1970                    //     window.open(`https://web.whatsapp.com/send?phone=${wkli_waba_number}&text=Hi`,"_blank");
1971                    // }
1972                    wkli_modalVisiblity = false;
1973                    user.openChatBlock();
1974                    return;
1975                }
1976            }
1977            if (wkli_customInput && document.getElementsByClassName("customInput").length > 0) {
1978                setTimeout(() => {
1979                    this.sendCustomFieldMessage(wkli_enableAutoResponse)
1980                    if(wkli_enableAutoResponse)
1981                        this.preClientQueries();
1982                }, 1000)
1983
1984            }
1985        })
1986
1987        wkli_socket.on("conversation-end-ack", data => {
1988            ai_message = {}
1989            helper.getElement(Ids.user_operator_chat_holder).innerHTML = "";
1990            let endChat = document.getElementById('wkEndChat');
1991            document.getElementById("wk-ch-operatorOnline").style.display = "none"
1992            endChat.style.display = 'none';
1993            helper.getElement("wk-cw-attachment-button-hide").value = '';
1994            helper.getElement("wk-cw-chatbot-attachment-name").style.display = "none";
1995            helper.getElement("wk-cw-chatbot-reply-block").style.display = "none";
1996            helper.getElement("wk-cw-attachment-error").style.display = "none";
1997            helper.getElement("operatorName").innerHTML = wkli_welcomeText;
1998            localStorage.removeItem(localStorageVar);
1999            helper.toggleChatHistory()
2000            localStorage.removeItem(localAutoChat);
2001            if (wkli_restart_chat_pending) {
2002                //ended because the tracked custom input changed, keep the widget as it is and open a fresh chat
2003                wkli_restart_chat_pending = false;
2004                helper.startNewSession();
2005            } else
2006                new Form().showChatBlock(false);
2007            if (new URL(location.href).searchParams.get('name'))
2008                location.reload();
2009            // if (!wkli_showForm) {
2010            //     if (new URL(location.href).searchParams.get('name'))
2011            //         wkli_socket.emit('sendAutoResponseInNoReg', { domain: new URL(location.href).searchParams.get('name'), enableAutoResponse: wkli_enableAutoResponse, organisationId: wkli_organisationId, AI_chatbot: wkli_AI_chatbot });
2012            //     else
2013            //         wkli_socket.emit('sendAutoResponseInNoReg', { domain: location.hostname, enableAutoResponse: wkli_enableAutoResponse, organisationId: wkli_organisationId, AI_chatbot: wkli_AI_chatbot });
2014            // }
2015            if(wkli_enableAutoResponse){
2016                // question = conf.autoGenerateQuestions
2017                if(!JSON.parse(localStorage.getItem(localAutoChat)) && !JSON.parse(localStorage.getItem(localStorageVar))) {
2018                    localStorage.setItem(localAutoChat, JSON.stringify(true));
2019                    this.disableChatWithAgent();
2020                }
2021            }
2022            if(typeof(media) == 'object') {
2023                media.disconnectCallOnChatEnd();
2024            }
2025            wkli_autoChatBotType = wkli_autoChatBotType_db
2026            let autoChatApi = JSON.parse(localStorage.getItem('autoChatApi'))
2027            if(wkli_autoChatBotType && wkli_autoChatBotType == '2'){
2028                if(!autoChatApi){
2029                    localStorage.setItem('autoChatApi',true)
2030                    createLoadingWidget('enable') 
2031                }
2032                let user = JSON.parse(localStorage.getItem(localStorageVar))
2033                if(user?.is_operator_online == false){
2034                    user.is_operator_online = true
2035                    localStorage.setItem(localStorageVar, JSON.stringify(user))
2036                }
2037            } else {
2038                localStorage.removeItem('autoChatApi')
2039            }
2040        })
2041
2042        wkli_socket.on("conversation-end-by-operator", data => {
2043            this.chatEndByOperatorNotification(data)
2044        })
2045
2046        wkli_socket.on("operator-IsTyping-ToUser", (data) => {
2047            if (JSON.parse(localStorage.getItem(localStorageVar))) {
2048                if (data.receiverId == JSON.parse(localStorage.getItem(localStorageVar)).senderId) {
2049                    document.getElementById("wk-cw-isTyping").style.display = "block"
2050                    is_Typing = new Date().valueOf();
2051                    this.disableIsTyping()
2052                }
2053            }
2054        })
2055
2056        wkli_socket.on("signOut-Operator-Status", data => {
2057            if (JSON.parse(localStorage.getItem(localStorageVar)) && JSON.parse(localStorage.getItem(localStorageVar)).uniqueId == data) {
2058                document.getElementById("wk-ch-operatorOnline").style.background = "red"
2059                let user = JSON.parse(localStorage.getItem(localStorageVar))
2060                user.operatorStatus = false;
2061                localStorage.setItem(localStorageVar, JSON.stringify(user))
2062            }
2063        })
2064
2065        wkli_socket.on("operatorConnection", data => {
2066            if (JSON.parse(localStorage.getItem(localStorageVar)) && JSON.parse(localStorage.getItem(localStorageVar)).uniqueId == data.id) {
2067                if (data.status)
2068                    document.getElementById("wk-ch-operatorOnline").style.background = "chartreuse"
2069                else
2070                    document.getElementById("wk-ch-operatorOnline").style.background = "red"
2071                let user = JSON.parse(localStorage.getItem(localStorageVar))
2072                user.operatorStatus = true;
2073                localStorage.setItem(localStorageVar, JSON.stringify(user))
2074            }
2075        })
2076
2077        wkli_socket.on('technicalError', data => {
2078            wkli_registration_in_process = false
2079            //registration failed, no sendMessageAckOfUser is coming to replay it
2080            wkli_pending_agent_chat = null
2081            console.log('technicalError')
2082            document.getElementById('wk-cw-chatbot-textCointainer').innerHTML = '';
2083            helper.getElement(Ids.user_operator_chat_holder).innerHTML = "";
2084            let div = document.createElement('i')
2085            div.id="wkli_technicalError"
2086            div.style.color = '#FF5252'
2087            let errorMessage = data.errorMsg ? data.errorMsg : 'You are not providing email address. Kindly reload this page and try again.'
2088            div.innerHTML = `<h5 style="text-align: center;">ERROR</h5><p>${errorMessage}</p>`
2089            helper.getElement(Ids.user_operator_chat_holder).appendChild(div);
2090        })
2091
2092        wkli_socket.on('ai-typing', (data) => {
2093            if (JSON.parse(localStorage.getItem(localStorageVar))) {
2094                if (data.senderId == JSON.parse(localStorage.getItem(localStorageVar)).senderId) {
2095                    this.showAITyping()
2096                }
2097            }
2098        })
2099        wkli_socket.on('old-chat-history', data => {
2100            let msg = ''
2101            if(data && data.link && data.link.length) {
2102                msg = wkli_chatHistoryLinkText + ' \n\n'
2103                data.link.forEach(i => {
2104                    let a = document.createElement('a')
2105                    a.href = `${WKprotocol}${WKscript}/wkcs/live-chat/${i._id}`
2106                    a.target="_blank"
2107                    a.text = 'Click Here'
2108                    // console.log(a)
2109                    msg += getLocalTimestamp(i.createdAt) + '     ' + a + '\n\n'
2110                })
2111            } else {
2112                msg = wkli_chatHistoryEmptyText
2113            }
2114            let parentClass = "wk-cw-operator-to-user-msg";
2115            let childClass = "operator-to-user-msg";
2116            this.buildAttachmentInDom(2, {message: msg}, parentClass, childClass, 1)
2117            this.scrollHeight();
2118        })
2119
2120        wkli_socket.on('autoChatEndByOperator', data => {
2121            if(data.clientId && localStorage.getItem(localStorageVar)) {
2122                let senderId = JSON.parse(localStorage.getItem(localStorageVar)).senderId;
2123                if(data.clientId == senderId) {
2124                    this.autoChatEndChangedByOperator(data.autoChatEnd)
2125                }
2126            }
2127        })
2128
2129        wkli_socket.on('underMaintainance', data => {
2130            this.switchMaintenanceMode();
2131            setTimeout(() => {
2132                document.getElementById(Ids.MAIN_COINTAINER).remove(); 
2133                createMaintenanceWidget();          
2134            }, 5000)
2135        })
2136    }
2137
2138    switchMaintenanceMode() {
2139        document.getElementById(Ids.MODEL_COINTAINER).style.display = "none"
2140        document.getElementById(Ids.OPTION_CONTAINER).style.display = "none"
2141        document.getElementById(Ids.MAINTENANCE_CONTAINER).style.display = "block"
2142    }
2143
2144    autoChatEndChangedByOperator(autoChatEnd) {
2145        if(autoChatEnd) {
2146            wkli_auto_chat_end = true
2147            helper.getElement("wk-countdown-div").style.display = 'block'
2148        } else {
2149            wkli_auto_chat_end = false;
2150            helper.getElement("wk-countdown-div").style.display = 'none'
2151        }
2152        if(helper.getElement("wk-chat-end-confirmation").style.display == 'block') {
2153            helper.getElement(Ids.wkConfirmationCancel).click()
2154        } else {
2155            helper.startChatTimeout()
2156        }
2157    }
2158
2159    chatEndByOperatorNotification(data) {
2160        helper.clearAllTimeoutAndInterval()
2161        document.getElementById("wk-cw-chatbot-textCointainer").style.display = "none";
2162        let endChat = document.getElementById('wkEndChat');
2163        endChat.style.display = 'none';
2164        document.getElementById("wk-ch-operatorOnline").style.background = "red"
2165        helper.storage = JSON.parse(localStorage.getItem(localStorageVar));
2166        localStorage.removeItem(localStorageVar);
2167        helper.toggleChatHistory()
2168        localStorage.removeItem(localAutoChat);
2169        let div = document.createElement('i')
2170        div.className = 'wk-cw-notify-User'
2171        div.innerHTML = wkli_translateLog(data.message).replace(/</g, "&lt;").replace(/>/g, "&gt;");
2172        helper.getElement(Ids.user_operator_chat_holder).appendChild(div);
2173        let button = document.createElement('button');
2174        var buttonTxt = document.createTextNode(wkli_startNewText);
2175        button.appendChild(buttonTxt);
2176        button.className = 'wk-ch-livechat-startNewChat'
2177        button.style.background = wkli_theamColor;
2178        button.setAttribute("onclick", 'helper.startNewSession()');
2179        helper.getElement(Ids.user_operator_chat_holder).appendChild(button);
2180        if (!document.getElementById("sendMailButton") && wkli_endConversionMail) {
2181            let sendMailButton = document.createElement('button');
2182            var sendMailButtonTxt = document.createTextNode(wkli_sendMailText);
2183            sendMailButton.setAttribute("title", wkli_sendMailTitle);
2184            sendMailButton.appendChild(sendMailButtonTxt);
2185            sendMailButton.className = 'wk-ch-livechat-startNewChat';
2186            sendMailButton.style.background = wkli_theamColor
2187            sendMailButton.id = "sendMailButton";
2188            sendMailButton.setAttribute("onclick", 'new Form().endConversationSendM
2188ail(false)');
2189            helper.getElement(Ids.user_operator_chat_holder).appendChild(sendMailButton);
2190        }
2191        helper.getElement("wk-cw-attachment-button-hide").value = '';
2192        helper.getElement("wk-cw-chatbot-attachment-name").style.display = "none";
2193        helper.getElement("wk-cw-attachment-error").style.display = "none";
2194        this.scrollHeight();
2195
2196        if(wkli_enableAutoResponse){
2197            // question = conf.autoGenerateQuestions
2198            if(!JSON.parse(localStorage.getItem(localAutoChat)) && !JSON.parse(localStorage.getItem(localStorageVar))) {
2199                localStorage.setItem(localAutoChat, JSON.stringify(true));
2200                this.disableChatWithAgent();
2201            }
2202        }
2203        let elem = helper.getElement("wk-chat-end-confirmation")
2204        if(elem.style.display == 'block') {
2205            elem.style.display = 'none';
2206            elem.classList.remove('wk-cw-show')
2207            helper.changeDisplayProperty(Ids.CHATBOT)
2208        }
2209        if(wkli_auto_chat_end) {
2210            helper.getElement("wk-countdown-div").style.display = 'block'
2211        }
2212        helper.getElement(Ids.chatWithChatbot).style.display = 'none'
2213    }
2214
2215    messageSound() {
2216        let playPromise;
2217        if(wkli_clientNotifySoundStatus) {
2218            playPromise = aud.play()
2219        }
2220        if(playPromise) {
2221            playPromise.catch((e) => {
2222                if (e.name === 'NotAllowedError' || e.name === 'NotSupportedError') { 
2223                    console.log(e.name);
2224               }
2225            }).then(()=>{})
2226        }
2227        
2228    }
2229
2230    disableIsTyping() {
2231        setTimeout(() => {
2232            if (new Date().valueOf() - is_Typing > 1800) {
2233                document.getElementById("wk-cw-isTyping").style.display = "none"
2234            }
2235        }, 2000);
2236    }
2237
2238    scrollHeight() {
2239        let element = helper.getElement("wk-cw-user-operator-chat");
2240        if (element)
2241            element.scrollTop = element.scrollHeight;
2242    }
2243
2244    endAutoChat(){
2245        if(wkli_enableAutoResponse){
2246            document.getElementById(Ids.Text_Container).style.display = "none"
2247        }
2248        helper.getElement(Ids.user_operator_chat_holder).innerHTML = "";
2249    }
2250    //for ai chatbot and basic chatbot
2251    enableChatWithAgent() {
2252        if(wkli_client_blocked)
2253            return false;
2254        helper.getElement(Ids.MESSAGE).value = "";
2255        document.getElementById(Ids.Text_Container).style.display = "grid"
2256        helper.getElement(Ids.autoResponseAction).style.display = "none";
2257        helper.getElement("wk-cw-attachment-button-hide").disabled = true
2258        helper.getElement(Ids.MESSAGE).focus();
2259    }
2260    //end
2261
2262    socketRejoin(reconnect = 'false') {
2263        let enableAutoChatApi = false;
2264        let autoChatApi = JSON.parse(localStorage.getItem('autoChatApi'))
2265        if(wkli_autoChatBotType && wkli_autoChatBotType == '2' && autoChatApi){
2266            enableAutoChatApi = true;
2267        }
2268        preventSendingMsg = false;
2269        if (!new URL(location.href).searchParams.get('name')){
2270            helper.getElement(Ids.MAIN_COINTAINER).style.display = "block"
2271        }
2272        if (JSON.parse(localStorage.getItem(localStorageVar)) && JSON.parse(localStorage.getItem(localStorageVar)).uniqueId) {
2273            if (JSON.parse(localStorage.getItem(localStorageVar)).enable == true && !new URL(location.href).searchParams.get('name'))
2274                new Form().showChatBlock(true);
2275            if (JSON.parse(localStorage.getItem(localStorageVar)).operatorStatus == true)
2276                document.getElementById("wk-ch-operatorOnline").style.background = "chartreuse"
2277            else
2278                document.getElementById("wk-ch-operatorOnline").style.background = "red"
2279            if (JSON.parse(localStorage.getItem(localStorageVar)).operator)
2280                document.getElementById("wk-ch-operatorOnline").style.display = "inline-block"
2281            if (document.getElementById("loader-skin"))
2282                document.getElementById("loader-skin").style.display = "block";
2283            wkli_socket.emit('socketRejoin', {localData: JSON.parse(localStorage.getItem(localStorageVar)), enableAutoResponse: wkli_enableAutoResponse, reconnect: reconnect, AI_chatbot: wkli_AI_chatbot,enableAutoChatApi});
2284            wkli_socket.emit("getAllMessageAck", {
2285                receiverId: JSON.parse(localStorage.getItem(localStorageVar)).senderId,
2286                delieverdTimestamp: new Date().toISOString(),
2287                domain: JSON.parse(localStorage.getItem(localStorageVar)).domain,
2288                userId: JSON.parse(localStorage.getItem(localStorageVar)).senderId
2289            })
2290        } else {
2291            if (!wkli_showForm) {
2292                if (new URL(location.href).searchParams.get('name'))
2293                    wkli_socket.emit('sendAutoResponseInNoReg', { domain: new URL(location.href).searchParams.get('name'),enableAutoResponse: wkli_enableAutoResponse, organisationId: wkli_organisationId, AI_chatbot: wkli_AI_chatbot,enableAutoChatApi });
2294                else
2295                    wkli_socket.emit('sendAutoResponseInNoReg', { domain: location.hostname, enableAutoResponse: wkli_enableAutoResponse, organisationId: wkli_organisationId, AI_chatbot: wkli_AI_chatbot,enableAutoChatApi });
2296            }
2297        }
2298    }
2299
2300
2301    sendUserDetails() {
2302        let mailRegex = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
2303        let contactRegex = /(^|\s|[^0-9])[\+]?[(]?[0-9]{3}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4,6}(\s|[^0-9]|$)/ig;
2304        // let contactRegex = /^[0-9]{10}$/;
2305
2306        //new validation code
2307        let status = true;
2308        Array.from(document.querySelectorAll('#wk-ch-livechat-content .wk-cw-input')).forEac
2308h(
2309            function (element, index, array) {
2310                let warning = document.getElementById('warning-' + element.id);
2311                let field = element.dataset.label || element.name;
2312                if(element.id == 'wk-cw-selected-cc')
2313                    warning = document.querySelector('.warning-wk-cw-selected-cc')
2314                if (element.required) {
2315                    if (element.type == 'text' && status && !element.value.trim() && element.value.trim() == '' && element.id != 'wk-cw-selected-cc') {
2316                        warning.innerText = wkli_requiredFieldText.split('{field}').join(field);
2317                        wkli_scrollToElement(element.id)
2318                        document.getElementById(element.id).focus()
2319                        status = false;
2320                        return false;
2321                    } else if (wkli_selectedChatOption == 'whatsapp' && element.type == 'number' && element.value.trim() == '' && status) {
2322                        warning.innerText = wkli_invalidFieldText.split('{field}').join(field);
2323                        wkli_scrollToElement(element.id)
2324                        document.getElementById(element.id).focus()
2325                        status = false;
2326                        return false;
2327                    } else if (element.type == 'email' && !mailRegex.test(element.value) && status) {
2328                        warning.innerText = wkli_invalidFieldText.split('{field}').join(field);
2329                        wkli_scrollToElement(element.id)
2330                        document.getElementById(element.id).focus()
2331                        status = false;
2332                        return false;
2333                    } else if (element.type == 'select-one' && status && (element.value == "SELECT" || element.value == '')) {
2334                        warning.innerText = wkli_requiredFieldText.split('{field}').join(field);
2335                        wkli_scrollToElement(element.id)
2336                        document.getElementById(element.id).focus()
2337                        status = false;
2338                        return false;
2339                    } else if (wkli_selectedChatOption == 'whatsapp' && status && !wkli_country_code_list.some(country => country.dial_code == element.value) && element.id == 'wk-cw-selected-cc') {
2340                        document.querySelector('.warning-wk-cw-selected-cc').innerHTML = `Please select valid country code from list`;
2341                        wkli_scrollToElement(element.id)
2342                        document.getElementById(element.id).focus()
2343                        status = false;
2344                        return false;
2345                    }
2346                }
2347                if (status) {
2348                    warning.innerHTML = ''
2349                }
2350            }
2351        );
2352
2353        if (status && !wkli_registration_in_process) {
2354            wkli_registration_in_process = true
2355            let domainName = ''
2356            if (location.hostname.includes('localhost'))
2357                domainName = 'chatwhizz.com'
2358            else if (new URL(location.href).searchParams.get('name'))
2359                domainName = new URL(location.href).searchParams.get('name')
2360            else
2361                domainName = location.hostname
2362            
2363            // form input when present, page injected value otherwise - the whatsapp form can be
2364            // built with the number field alone, so the name/email still come from the page
2365            let clientEmail = this.getRegistrationEmail()
2366            this.getClientToken(domainName, clientEmail, cb => {
2367                if(cb && cb.data) {
2368                    initializeSocket().then(() => {
2369                        if(wkli_selectedChatOption != 'whatsapp')
2370                            new Form().showChatBlock(true);
2371            
2372                        let clientName = this.getRegistrationName();
2373                        if (clientName)
2374                            clientName = clientName.replace(/</g, "&lt;").replace(/>/g, "&gt;");
2375                        let userData = {
2376                            email: clientEmail,
2377                            name: clientName,
2378                            type: 1,
2379                            uniqueId: '_' + Math.random().toString(36).substr(2, 16) + '_',
2380                            domainName: domainName,
2381                            customInput: wkli_customInput,
2382                            clientToken: cb.data
2383                        }
2384                        if (wkli_depRegistration && document.getElementById(wkli_userDepartment) && document.getElementById(wkli_userDepartment).value && wkli_showForm) {
2385                            let handleName = document.getElementById(wkli_userDepartment).value;
2386                            let department = wkli_departmentArr.filter(x => {
2387                                return x.handleName == handleName
2388                            })
2389                            userData.departmentId = department[0].departmentId;
2390                            // userData.departmentId = document.getElementById(wkli_userDepartment).value;
2391                        }
2392                        userData.enableAutoResponse = wkli_enableAutoResponse;
2393                        let customFields = this.getCustomFieldsObject();
2394                        if (customFields)
2395                            userData.customFields = customFields;
2396                        // userData.domainName = "admin.webkul.com";
2397                        if(wkli_selectedChatOption == 'whatsapp') {
2398                            // read without clearing - the next whatsapp registration (no page reload)
2399                            // must still find the page injected / prefilled values, same as sendCustomFieldMessage()
2400                            let customMsg = ''
2401                            Array.from(document.getElementsByClassName('customInput')).forEach(
2402                                function (element, index, array) {
2403                                    customMsg += `${element.name}: ${element.value.replace(/</g, "&lt;").replace(/>/g, "&gt;")} \n`;
2404                                }
2405                            );
2406                            userData.customMsg = customMsg;
2407                            userData.isWhatsAppClient = true;
2408                            userData.whatsAppDetails = {
2409                                number: document.getElementById(wkli_phoneNumber) ? document.getElementById('wk-cw-selected-cc').value.trim().substr(1) + document.getElementById(wkli_phoneNumber).value.trim().replace('+','').replace('-','') : null,
2410                                isChatEnd: false,
2411                                domainWaBusinessNumber: wkli_waba_number
2412                            }
2413                            if(!userData.whatsAppDetails.number){
2414                                if(!document.getElementById('wk-cw-no-wa')){
2415                                    let error = document.createElement('small');
2416                                    error.innerHTML = "you can't proceed without whatsapp number"
2417                                    error.style.color = 'red';
2418                                    error.id = 'wk-cw-no-wa'
2419                                    document.getElementById('wk-cw-userDetails').insertBefore(error, document.getElementById('wk-cw-submit-form-control'))
2420                                }
2421                                wkli_registration_in_process = false;   // release the lock, the visitor has to retry
2422                                return false;
2423                            }
2424            
2425                            if(user.isMobile()){
2426                                window.open(`https://api.whatsapp.com/send?phone=${wkli_waba_number}&text=Hi`,"_blank");
2427                            } else{
2428                                window.open(`https://web.whatsapp.com/send?phone=${wkli_waba_number}&text=Hi`,"_blank");
2429                            }
2430                        }
2431                        userData.AI_chatbot = wkli_AI_chatbot
2432                        helper.getElement(Ids.user_operator_chat_holder).innerHTML = "";
2433                        let autoChatApi = JSON.parse(localStorage.getItem('autoChatApi'))
2434                        if(helper.checkRestrictAgentChatCondition() && !wkli_enableAutoResponse){
2435                            helper.getElement(Ids.Text_Container).style.display = "none";
2436                            let data = {
2437                                message: wkli_errorPermissionMsg
2438                            }
2439                            this.buildErrorAttachInDom(data)
2440                            if(domainName && clientEmail){
2441                                let dataForRestrictChat = {
2442                                    clientEmail:clientEmail,
2443                                    domain: domainName
2444                                }
2445                                localStorage.setItem('restrictChatHistory', JSON.stringify(dataForRestrictChat));
2446                                helper.toggleChatHistory()
2447                            }
2448                            return
2449                        }
2450                        if(wkli_autoChatBotType && wkli_autoChatBotType == '2' && autoChatApi){
2451                            userData.enableAutoChatApi = true;
2452                        }
2453                        let liveChatPermission = document.getElementById('wk-ch-liveChatPermission');
2454                        if(wkli_agentChatPermission && liveChatPermission && liveChatPermission.value && liveChatPermission.value == '1') {
2455                            userData.botToAgentRestrict = true;
2456
2457                        }
2458                        wkli_socket.emit('sendUserDetails', userData)
2459                        // Array.from(document.getElementsByClassName('wk-cw-input')).forEac
2459h(
2460                        //     function (element, index, array) {
2461                        //         if (element.type == 'select-one') {
2462                        //             element.value = "SELECT";
2463                        //         } else {
2464                        //             element.value = "";
2465                        //         }
2466                        //     }
2467                        // );
2468                        if(user.isMobile()){
2469                            document.getElementById(Ids.REGISTRATION_FROM_CLOSE_BTN_ID).style.display = 'none';
2470                            helper.changeDisplayProperty(Ids.circleWidget, 'block')
2471                            document.getElementById(Ids.MODEL_COINTAINER).style.bottom = '80px'
2472                        }
2473                    }).catch((err) => {
2474                        wkli_registration_in_process = false
2475                        console.log(err)
2476                    })
2477                } else {
2478                    wkli_registration_in_process = false
2479                }
2480            })
2481        }
2482
2483    }
2484
2485    getClientToken(domain, email, cb) {
2486        if(wkli_autoChatBotType_db != 2) {
2487            localStorage.removeItem('autoChatApi')
2488            wkli_autoChatBotType = wkli_autoChatBotType_db
2489            // a new chat goes straight to an agent, hide the agent button left from an earlier bot chat
2490            createLoadingWidget('disable')
2491        } else {
2492            localStorage.setItem('autoChatApi', true)
2493            createLoadingWidget('enable')
2494        }
2495        if(!domain) {
2496            if (location.hostname.includes('localhost'))
2497                domain = 'chatwhizz.com'
2498            else if (new URL(location.href).searchParams.get('name'))
2499                domain = new URL(location.href).searchParams.get('name')
2500            else
2501                domain = location.hostname
2502        }
2503        let option = {
2504            method: 'POST',
2505            headers: {'Content-Type': 'application/json'},
2506            body: JSON.stringify({
2507                    domain: domain,
2508                    email: email,
2509                    organisationId: wkli_organisationId,
2510                })
2511        }
2512        fetch(`${WKprotocol}${WKscript}/wkcs/verify-client`,option).then(res => {
2513            return res.json().then(data => { return {ok: res.ok, data: data} })
2514        }).then(response => {
2515            let data = response.data
2516            if(data.maintenance) {
2517                this.switchMaintenanceMode();
2518                setTimeout(() => {
2519                    document.getElementById(Ids.MAIN_COINTAINER).remove();
2520                    createMaintenanceWidget();
2521                }, 5000)
2522                return
2523            }
2524            if(!response.ok) {
2525                //blocked ip or email, the response carries an error string and never a token
2526                this.showClientBlockedError(data.data)
2527                cb(false)
2528                return
2529            }
2530            if(wkli_autoChatBotType_db != data?.autoChatBotType) {
2531                if(data?.autoChatBotType == 2) {
2532                    if(data?.autoChatBotConfig?.showAgentChatButton)
2533                        wkli_agentChatButtonStatus = true
2534                    switchToAutoChatBot("enable");
2535                }
2536                else
2537                    switchToAutoChatBot("disable")
2538            }
2539            cb(data)
2540        }).catch(error => {
2541            console.log(error)
2542            cb(false)
2543        })
2544    }
2545
2546    /**
2547     * verify-client answers 404 for a blocked client. fetch() does not reject on 404, so the
2548     * caller has to be told explicitly rather than being handed the error text as a token.
2549     */
2550    showClientBlockedError(message) {
2551        if (wkli_client_blocked)
2552            return;
2553        wkli_client_blocked = true;
2554        createLoadingWidget('disable')
2555        //drop the textarea itself, not just its display - several flows put the container
2556        //back on screen and a blocked client must have nothing left to type into
2557        if(helper.getElement(Ids.Text_Container))
2558            helper.getElement(Ids.Text_Container).remove();
2559        helper.getElement(Ids.autoResponseAction).style.display = "none";
2560        helper.getElement(Ids.chatWithChatbot).style.display = "none";
2561        //three dot menu only holds chat history, a blocked client must not reach it
2562        if(helper.getElement('wk-cw-chat-history-dropdown'))
2563            helper.getElement('wk-cw-chat-history-dropdown').style.display = "none";
2564        //drop the chatbot option buttons, a blocked client must not be able to keep selecting them
2565        Array.from(document.getElementsByClassName("wk-cw-operator-to-user-queries")).forEac
2565h(el => el.remove());
2566        this.buildErrorAttachInDom({
2567            message: message && typeof message == 'string' ? message : 'You are not allowed to chat'
2568        })
2569        this.scrollHeight();
2570    }
2571
2572    endConversation() {
2573        if(!wkli_isSocketConnected) {
2574            return false
2575        }
2576        wkli_modalVisiblity = false
2577        let arr = JSON.parse(localStorage.getItem(localStorageVar));
2578        if (arr) {
2579            let msg = (helper.getElement("wk-cw-message").value).trim();
2580            let data = {
2581                isChatEnd: true,
2582                message: msg.replace(/</g, "&lt;").replace(/>/g, "&gt;"),
2583                sendTimestamp: new Date().toISOString(),
2584                domain: location.host,
2585                type: 2,
2586                end: 'sender',
2587                receiverId: arr.operator || '',
2588                senderId: arr.senderId,
2589                uniqueId: arr.uniqueId,
2590                chatInitiateNoti: true,
2591                addonUniqueName: wkli_addOnUniqueName
2592            }
2593            if (new URL(location.href).searchParams.get('name'))
2594                data.domain = new URL(location.href).searchParams.get('name')
2595            if (arr.departmentId && wkli_showForm) {
2596                data.departmentId = arr.departmentId
2597            }
2598            if(arr.isOperatorOnline) {
2599                data.isOperatorOnline = arr.isOperatorOnline
2600            }
2601            if(arr.clientName) {
2602                data.clientName = arr.clientName
2603            }
2604            if(arr.clientEmail) {
2605                data.clientEmail = arr.clientEmail
2606            }
2607            if(location.host.includes('localhost'))
2608                data.domain = 'chatwhizz.com' 
2609            wkli_socket.emit("conversation-end", data);
2610            ai_message = {}
2611        }
2612        let element = helper.getElement("wk-chat-end-confirmation");
2613        element.style.display = 'none';
2614        if(wkli_auto_chat_end) {
2615            helper.getElement("wk-countdown-div").style.display = 'block'
2616        }
2617        helper.getElement(Ids.chatWithChatbot).style.display = 'none'
2618    }
2619
2620    endConversationSendMail(clientEnd = true) {
2621        if(!wkli_isSocketConnected) {
2622            return false
2623        }
2624        if(JSON.parse(localStorage.getItem(localStorageVar)) && JSON.parse(localStorage.getItem(localStorageVar)).senderId)
2625            helper.storage = JSON.parse(localStorage.getItem(localStorageVar))
2626        let storage = helper.storage ? helper.storage : JSON.parse(localStorage.getItem(localStorageVar))
2627        //the address the client registered with - form input, or the page injected / auto registered
2628        //one when there is no form. Only ask for an email when none of them is known.
2629        let registeredEmail = (storage && storage.clientEmail) ? storage.clientEmail : this.getRegistrationEmail()
2630        if (storage && registeredEmail) {
2631            if (clientEnd) {
2632                new Form().endConversation();
2633            } else {
2634                document.getElementById("sendMailButton").style.display = "none";
2635            }
2636            storage.clientEmail = registeredEmail
2637            wkli_socket.emit("ClientConversationMailOnEndChat", storage)
2638        } else {
2639            helper.getElement("wk-cw-displayEmail-errMsg").innerHtml = ""
2640            helper.getElement("wk-chat-end-confirmation").style.display = "flex"
2641            document.getElementById("wk-confirmation-child").style.display = 'none';
2642            document.getElementById("wk-cw-email-withoutRegistration-parent").style.display = 'block';
2643        }
2644    }
2645
2646    closeNewEmailPopUp() {
2647        if (JSON.parse(localStorage.getItem(localStorageVar))) {
2648            document.getElementById("wk-confirmation-child").style.display = 'block';
2649        } else {
2650            helper.getElement("wk-chat-end-confirmation").style.display = "none";
2651        }
2652        document.getElementById("wk-cw-email-withoutRegistration-parent").style.display = 'none';
2653    }
2654
2655    confirmNewSendEmailChat() {
2656        if(!wkli_isSocketConnected) {
2657            return false
2658        }
2659        let mailRegex = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
2660        let email = document.getElementById("wk-cw-email-withoutRegistration")
2661        if (email && !mailRegex.test(email.value)) {
2662            document.getElementById("wk-cw-displayEmail-errMsg").innerText = wkli_invalidEmailText;
2663            return false;
2664        } else {
2665            document.getElementById("wk-cw-displayEmail-errMsg").innerHTML = ''
2666            document.getElementById("wk-cw-email-withoutRegistration-parent").style.display = 'none';
2667            document.getElementById("wk-confirmation-child").style.display = 'block';
2668            new Form().endConversation();
2669            if(JSON.parse(localStorage.getItem(localStorageVar)) && JSON.parse(localStorage.getItem(localStorageVar)).senderId)
2670                helper.storage = JSON.parse(localStorage.getItem(localStorageVar))
2671            let data = helper.storage ? helper.storage : JSON.parse(localStorage.getItem(localStorageVar));
2672            data.clientEmail = email.value.replace(/</g, "&lt;").replace(/>/g, "&gt;")
2673            wkli_socket.emit("ClientConversationMailOnEndChat", data)
2674            if (helper.getElement("sendMailButton")) {
2675                helper.getElement("sendMailButton").style.display = "none";
2676            }
2677        }
2678    }
2679
2680    openAttachmentBox() {
2681        if(localStorage.getItem(localStorageVar) && JSON.parse(localStorage.getItem(localStorageVar)).senderId) {
2682            helper.getElement("wk-cw-attachment-error").textContent = ''
2683            helper.getElement("wk-cw-attachment-error").style.display = "none"
2684            document.getElementById("wk-cw-attachment-button-hide").click();
2685        } else {
2686            let is_chatwithchatbot_enable = 0
2687            if(helper.getElement(Ids.chatWithChatbot).style.display == 'block') {
2688                is_chatwithchatbot_enable = 1
2689            }
2690            helper.getElement("wk-cw-attachment-error").style.display = "block";
2691            helper.getElement("wk-cw-attachment-error").textContent = wkli_startChatFirstText
2692            helper.getElement(Ids.chatWithChatbot).style.display = "none"
2693            setTimeout(() => {
2694                helper.getElement("wk-cw-attachment-error").textContent = ''
2695                helper.getElement("wk-cw-attachment-error").style.display = "none"
2696                if(is_chatwithchatbot_enable && !wkli_option_event) {
2697                    helper.getElement(Ids.chatWithChatbot).style.display = "block"
2698                }
2699            }, 2000)
2700        }
2701    }
2702
2703    closeAttachment() {
2704        helper.getElement("wk-cw-chatbot-attachment-name").style.display = "none";
2705        document.getElementById("wk-cw-attachment-button-hide").value = '';
2706        user.replyButtonAct();
2707    }
2708
2709    closeReplyBlock() {
2710        helper.getElement("wk-cw-chatbot-reply-block").style.display = "none";
2711        helper.getElement("wk-cw-user-operator-chat").style.maxHeight = "370px";
2712        wkli_normalReplyData = '';
2713        let active = document.querySelectorAll('.wk-cw-active')
2714        if(active.length){
2715            active.forEach((chat) => {
2716                chat.classList.remove('wk-cw-active')
2717            })
2718        }
2719    }
2720
2721    isTyping(data) {
2722        wkli_socket.emit("clientIsTyping", data)
2723    }
2724
2725    getQueryResult(element){
2726        if(query_status || wkli_client_blocked)
2727            return false;
2728        query_status = true;
2729        if(!JSON.parse(localStorage.getItem(localStorageVar))){
2730            //pass the resolved email so the blocklist can match on it, not just on the ip
2731            this.getClientToken(false, this.getRegistrationEmail(), cb => {
2732                if(!cb || !cb.data) {
2733                    query_status = false;
2734                    return false;
2735                }
2736                if(cb && cb.data) {
2737                    let msg = `<------ ${location.href} ------>`
2738                    this.buildMessage(msg, 2, (data) => {
2739                        data.chatInitiateNoti = false;
2740                        data.clientToken = cb.data;
2741                        this.chnageMessageDetails(data, (updatedMessage) => {
2742                            //registration rides on this message, same as proceedToRegistration():
2743                            //the email must match the address the token was minted with or registerUser() rejects it
2744                            let customer_email = this.getRegistrationEmail()
2745                            let customer_name = this.getRegistrationName()
2746                            if(customer_email)
2747                                updatedMessage.email = customer_email
2748                            if(customer_name)
2749                                updatedMessage.name = customer_name
2750                            let departmentId = this.getSelectedDepartmentId()
2751                            if(departmentId)
2752                                updatedMessage.departmentId = departmentId
2753                            let customFields = this.getCustomFieldsObject()
2754                            if(customFields)
2755                                updatedMessage.customFields = customFields
2756                            if(new URL(location.href).searchParams.get('name'))
2757                                updatedMessage.domain = new URL(location.href).searchParams.get('name');
2758                            wkli_socket.emit("getQueryResult",updatedMessage);
2759                        })
2760                    })
2761                    setTimeout(()=>{
2762                        if ((element.textContent).trim()) {
2763                            let msg = (element.textContent).trim();
2764                            this.buildMessage(msg, 1, (data) => {
2765                                this.chnageMessageDetails(data, (updatedMessage) => {
2766                                    updatedMessage.tick= true;
2767                                    this.buildAttachmentInDom(3, updatedMessage, "wk-cw-user-to-operator-msg", "user-to-operator-msg", 2);
2768                                    this.scrollHeight();
2769                                    updatedMessage.id = element.getAttribute('id');
2770                                    localStorage.setItem(localAutoChat, JSON.stringify({id: element.getAttribute('id')}));
2771                                    if(new URL(location.href).searchParams.get('name'))
2772                                        updatedMessage.domain = new URL(location.href).searchParams.get('name');
2773                                    wkli_socket.emit("getQueryResult",updatedMessage);
2774                                    this.disableChatWithAgent()
2775                                })
2776                            })
2777                        }
2778                    },1000);
2779                }
2780            })
2781        } else {
2782            setTimeout(()=>{
2783                if ((element.textContent).trim()) {
2784                    let msg = (element.textContent).trim();
2785                    this.buildMessage(msg, 1, (data) => {
2786                        this.chnageMessageDetails(data, (updatedMessage) => {
2787                            updatedMessage.tick= true;
2788                            this.buildAttachmentInDom(3, updatedMessage, "wk-cw-user-to-operator-msg", "user-to-operator-msg", 2);
2789                            this.scrollHeight();
2790                            updatedMessage.id = element.getAttribute('id');
2791                            localStorage.setItem(localAutoChat, JSON.stringify({id: element.getAttribute('id')}));
2792                            if(new URL(location.href).searchParams.get('name'))
2793                                updatedMessage.domain = new URL(location.href).searchParams.get('name');
2794                            wkli_socket.emit("getQueryResult",updatedMessage);
2795                            this.disableChatWithAgent()
2796                        })
2797                    })
2798                }
2799            },1000);
2800        }
2801    }
2802    buildErrorAttachInDom(data){
2803        let div = document.createElement('div');
2804        div.className = ".wk-cw-plan-upgrade-error-msg";
2805        
2806        let childDiv = document.createElement("div");
2807        childDiv.classList.add("plan-upgrade-error-msg");
2808        let textColor = "#111111"
2809        // childDiv.innerHTML += data.message.replace(helper.link_exp, `<a href="$1" class="wk-ch-seller-buyer-url" target="_blank" style="color:${textColor}">$1</a>`);
2810        childDiv.innerHTML += data.message
2811        div.appendChild(childDiv);
2812        helper.getElement(Ids.user_operator_chat_holder).appendChild(div);
2813    }
2814
2815    chatWithAgent() { // while click on chat with agent button
2816        if(wkli_client_blocked)
2817            return false;
2818        let liveChatPermission = document.getElementById('wk-ch-liveChatPermission');
2819        if(wkli_agentChatPermission && liveChatPermission && liveChatPermission.value && liveChatPermission.value == '1'){
2820            this.displayAndFadeOutErrorMessage()
2821            return false
2822        }else{
2823            helper.getElement(Ids.Text_Container).style.display = "grid";
2824            helper.getElement(Ids.autoResponseAction).style.display = "none";
2825            helper.getElement(Ids.MESSAGE).value = "";
2826            helper.getElement(Ids.MESSAGE).focus()
2827            helper.refreshBasicChatbot()
2828            setWkli_isChatwithchatbot(false)
2829            let active = document.querySelectorAll('.wk-cw-reply-button')
2830            if(active && active.length){
2831                active.forEach((chat) => {
2832                    chat.style.display ="block";
2833                })
2834            }
2835        }
2836    }
2837    assignOperatorChat(data){
2838        // an operator's display name replaces the real name only while the domain is configured for it
2839        let operatorName = (wkli_useOperatorDisplayName && data.name.displayName) ? data.name.displayName : data.name.firstName + ' ' + data.name.lastName
2840        document.getElementById("operatorName").innerHTML = wkli_showOperatorName ? operatorName : wkli_opName
2841        if (data && JSON.parse(localStorage.getItem(localStorageVar))) {
2842            document.getElementById("wk-ch-operatorOnline").style.display = "inline-block";
2843            document.getElementById("wk-ch-operatorOnline").style.background = "chartreuse";
2844            let user = JSON.parse(localStorage.getItem(localStorageVar))
2845            user.operator = data.operatorId;
2846            user.name = operatorName;
2847            user.operatorStatus = true
2848            localStorage.setItem(localStorageVar, JSON.stringify(user))
2849            this.getUserOperatorData()
2850            let autoChatApi = JSON.parse(localStorage.getItem('autoChatApi'))
2851            if (autoChatApi) {
2852                localStorage.setItem('autoChatApi', JSON.stringify(false))
2853                createLoadingWidget('disable')
2854            }
2855
2856        }
2857    }
2858    displayAndFadeOutErrorMessage() {
2859        const errMsg = document.getElementsByClassName(".wk-cw-plan-upgrade-error-msg");
2860        if (errMsg.length > 0) {
2861            return;
2862        }
2863        const data = {
2864            message: wkli_errorPermissionMsg,
2865        };
2866        this.buildErrorAttachInDom(data);
2867    
2868        const chatWithChatbotElement = helper.getElement(Ids.chatWithChatbot);
2869        if (chatWithChatbotElement) {
2870            chatWithChatbotElement.style.display = 'none';
2871        }
2872        setTimeout(() => {
2873            const divs = document.getElementsByClassName('.wk-cw-plan-upgrade-error-msg');
2874
2875            Array.from(divs).forEach(div => {
2876                div.classList.add('wk-cw-fade-out'); 
2877                setTimeout(() => {
2878                    div.remove();
2879                }, 700); 
2880            });
2881        }, 4000);
2882    
2883        this.scrollHeight();
2884    }
2885    disableChatWithAgent() {
2886        if(wkli_client_blocked)
2887            return false;
2888        let localAutoResponseData = JSON.parse(localStorage.getItem(localAutoChat));
2889        if(localAutoResponseData) {
2890            helper.getElement(Ids.Text_Container).style.display = "none";
2891            if (localAutoResponseData && typeof (localAutoResponseData) == "object") {
2892                helper.getElement(Ids.autoResponseAction).style.display = "grid";
2893            } else if (localAutoResponseData) {
2894                helper.getElement(Ids.autoResponseAction).style.display = "none";
2895            }
2896            let active = document.querySelectorAll('.wk-cw-reply-button')
2897            if(active && active.length){
2898                active.forEach((chat) => {
2899                    chat.style.display ="none";
2900                    
2901                })
2902            }
2903        } else {
2904            helper.getElement(Ids.Text_Container).style.display = "grid";
2905            helper.getElement(Ids.MESSAGE).focus()
2906        }
2907        if(helper.getElement("wk-cw-attachment-button-hide"))
2908            helper.getElement("wk-cw-attachment-button-hide").disabled = false
2909        helper.getElement(Ids.chatWithChatbot).style.display = 'none';
2910    }
2911
2912    startChatWithAgent(initType=1,msgData={}) {
2913        let liveChatPermission = document.getElementById('wk-ch-liveChatPermission');
2914        if(wkli_agentChatPermission && liveChatPermission && liveChatPermission.value && liveChatPermission.value == '1'){
2915            this.displayAndFadeOutErrorMessage()
2916            preventSendingMsg = false;
2917            return false;
2918        }else{
2919            if(!wkli_isSocketConnected) {
2920                return false
2921            }
2922            //auto registration builds no form, so the bot can be answering while the client record
2923            //does not exist yet. getMessageInfo() registers on the first typed message, but this
2924            //button bypasses it - without the token/email the request reaches registerUser() with
2925            //nothing and a regMandatory domain answers with technicalError. Register, then replay.
2926            if(!wkli_showForm && !JSON.parse(localStorage.getItem(localStorageVar))) {
2927                if(!wkli_registration_in_process) {
2928                    wkli_registration_in_process = true
2929                    let clientEmail = this.getRegistrationEmail()
2930                    this.getClientToken(false, clientEmail, cb => {
2931                        if(cb && cb.data) {
2932                            wkli_pending_agent_chat = {initType: initType, msgData: msgData}
2933                            this.sendChatInitiateNoti(cb.data, clientEmail)
2934                        } else {
2935                            //blocked client or verification failure, release the lock to allow a retry
2936                            wkli_registration_in_process = false
2937                        }
2938                    })
2939                }
2940                return false
2941            }
2942            let autoChatApi = JSON.parse(localStorage.getItem('autoChatApi'))
2943            if(autoChatApi){
2944                localStorage.setItem('autoChatApi',false)
2945                localStorage.setItem('agentChatFirstMsg',true)
2946            }
2947            createLoadingWidget('disable')
2948            preventSendingMsg = false;
2949            let msg;
2950            if(initType == 1){
2951                msg = "<------ The client requested to connect with a live agent. ------>"
2952            }else{
2953                msg = "<------ The chat is automatically switched to a live agent  ------>"
2954            }
2955            let allMsgArr = []
2956            allMsgArr.push(msg)
2957            if(msgData && msgData.onlineOpName){
2958                let usernameMsg = `Live Agents <------ ${msgData.onlineOpName} ------>`
2959                allMsgArr.push(usernameMsg)
2960            }
2961            allMsgArr.forEach((el)=>{
2962                this.buildMessage(el, 1, (data) => {
2963                    this.chnageMessageDetails(data, (updatedMessage) => {
2964                        updatedMessage.agentChataInitiated = true
2965                        helper.user_operator_conversation.push(updatedMessage)
2966                        this.sendMessage()
2967                    })
2968                })
2969            })
2970            return
2971        }
2972
2973    }
2974    
2975
2976    replyButtonAct(){
2977        let file = helper.getElement("wk-cw-attachment-button-hide")
2978        if(file.value && file.files.length > 0){
2979            helper.getElement("wk-cw-chatbot-reply-block").style.display = "none";
2980            wkli_normalReplyData = '';
2981            let active = document.querySelectorAll('.wk-cw-reply-button')
2982            if(active.length){
2983                active.forEach((chat) => {
2984                    chat.style.display ="none";
2985                    chat.classList.remove('wk-cw-active')
2986                })
2987            }
2988            
2989        }else{
2990            let active = document.querySelectorAll('.wk-cw-reply-button')
2991            if(active.length){
2992                active.forEach((chat) => {
2993                    chat.style.display ="block";
2994                })
2995            }
2996        }
2997    }
2998}
2999
3000const user = new Form();
3001
3002if(wkli_showUvdeskWidget){
3003    helper.setClickListener(Ids.OPEN_CHAT_MODEL_BTN_ID, () => user.openChatBlock())
3004}else{
3005    helper.setClickListener(Ids.OPEN_CHAT_MODEL_BTN_ID, wkli_waba_number ? () => user.preOpenchatBlockOption() : () => user.openChatBlock())
3006}
3007
3008helper.setClickListener(Ids.REGISTRATION_FROM_CLOSE_BTN_ID, wkli_waba_number ? () => user.preOpenchatBlockOption() : () => user.openChatBlock())
3009
3010helper.setClickListener(Ids.SEND_MSG_BTN_ID, () => user.getMessageInfo());
3011
3012helper.setClickListener(Ids.formSubmit, () => user.sendUserDetails());
3013
3014helper.setClickListener(Ids.normalChatBtn, () => user.actionOnSelectedChatOption('normal'));
3015helper.setClickListener(Ids.whatsappChatBtn, () => user.actionOnSelectedChatOption('whatsapp'));
3016
3017
3018helper.setClickListener(Ids.wkEndChat, () => {
3019    if(!wkli_isSocketConnected) {
3020        return false
3021    }
3022    let element = helper.getElement("wk-chat-end-confirmation");
3023    element.style.display = 'block';
3024    element.classList.add('wk-cw-show')
3025    helper.changeDisplayProperty(Ids.CHATBOT, 'none')
3026    helper.startConfirmTimeout()
3027});
3028
3029helper.setClickListener(Ids.wkConfirmationCancel, () => {
3030    console.log('resume chat')
3031    let element = helper.getElement("wk-chat-end-confirmation");
3032    element.style.display = 'none';
3033    element.classList.remove('wk-cw-show')
3034    helper.changeDisplayProperty(Ids.CHATBOT, 'block')
3035    helper.startChatTimeout()
3036});
3037
3038helper.setClickListener(Ids.wkConfirmationConfirm, () => user.endConversation());
3039
3040helper.setClickListener(Ids.sendEndMail, () =>
3040 user.endConversationSendMail());
3041
3042helper.setClickListener(Ids.attachmentButton, () => user.openAttachmentBox());
3043
3044helper.setClickListener(Ids.attachmentClose, () => user.closeAttachment());
3045
3046helper.setClickListener(Ids.replyBlockClose, () => user.closeReplyBlock());
3047
3048helper.setClickListener(Ids.cancleNewSendEmail, () => user.closeNewEmailPopUp())
3049
3050helper.setClickListener(Ids.confirmNewSendEmail, () => user.confirmNewSendEmailChat())
3051
3052helper.setKeyListener(Ids.MESSAGE, (e) => {
3053    if (e.keyCode == 13 || e.keyCode == 8)
3054        user.getMessageFromUser(e)
3055    else {
3056        if (JSON.parse(localStorage.getItem(localStorageVar)) && JSON.parse(localStorage.getItem(localStorageVar)).senderId && JSON.parse(localStorage.getItem(localStorageVar)).operator && document.getElementById("wk-cw-message").value != "") {
3057            user.isTyping({
3058                senderId: JSON.parse(localStorage.getItem(localStorageVar)).senderId,
3059                receiverId: JSON.parse(localStorage.getItem(localStorageVar)).operator
3060            });
3061        }
3062    }
3063});
3064
3065helper.setClickListener(Ids.chatWithAgent, () => user.chatWithAgent())
3066
3067helper.setClickListener(Ids.start_autoResponse, () => user.preClientQueries())
3068
3069helper.setClickListener(Ids.chatHistory, () => user.getOldChatHistory())
3070helper.toggleChatHistory()
3071
3072helper.setClickListener(Ids.chatWithChatbot, () => user.disableChatWithAgent())
3073helper.setClickListener(Ids.agentChat, () => user.startChatWithAgent())
3074
3075
3076function validateAttachment() {
3077    let file = helper.getElement("wk-cw-attachment-button-hide")
3078    let txt = '';
3079    let status = true;
3080    let ValidFileTypes = ["text/plain", "text/csv", "application/pdf", "image/png", "image/jpeg", "image/gif", "application/vnd.oasis.opendocument.spreadsheet", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "application/vnd.ms-excel", "text/javascript", "application/x-php", "application/vnd.oasis.opendocument.text", "application/vnd.oasis.opendocument.text-template", "application/vnd.oasis.opendocument.text-master", "text/html", "application/vnd.oasis.opendocument.text-web", "application/vnd.oasis.opendocument.spreadsheet-template", "application/vnd.oasis.opendocument.graphics", "application/vnd.oasis.opendocument.graphics-template", "application/vnd.oasis.opendocument.presentation", "application/vnd.oasis.opendocument.presentation-template", "application/vnd.oasis.opendocument.formula", "application/vnd.oasis.opendocument.database", "application/vnd.openofficeorg.extension", "audio/mpeg"];
3081    if (file.value && file.files.length > 0) {
3082        if ('files' in file) {
3083            for (var i = 0; i < file.files.length; i++) {
3084                var fileContent = file.files[i];
3085                if ('name' in fileContent) {
3086                    txt = fileContent.name;
3087                }
3088                if ('size' in fileContent) {
3089                    if (fileContent.size > 10485760) {
3090                        status = false;
3091                        txt = wkli_fileSizeText;
3092                    }
3093                }
3094                if (!ValidFileTypes.includes(fileContent.type)) {
3095                    status = false;
3096                    txt = wkli_invalidFileText;
3097                }
3098            }
3099            if (status) {
3100                helper.getElement("wk-cw-chatbot-attachment-name").style.display = "block"
3101                helper.getElement("wk-ch-chatbot-attachment-close").style.display = "block"
3102                helper.getElement("wk-ch-chatbot-fileAttachment-name").textContent = txt;
3103                user.replyButtonAct();
3104            }
3105            else {
3106                helper.getElement("wk-cw-attachment-button-hide").value = '';
3107                inValidFile(txt);
3108            }
3109            helper.getElement(Ids.MESSAGE).focus()
3110        } else {
3111            if (file.value == "") {
3112                inValidFile(wkli_selectFileText)
3113            }
3114        }
3115    } else {
3116        inValidFile(wkli_selectFileText)
3117    }
3118}
3119
3120function inValidFile(txt) {
3121    helper.getElement("wk-cw-chatbot-attachment-name").style.display = "none"
3122    helper.getElement("wk-cw-attachment-error").style.display = "block";
3123    helper.getElement("wk-cw-attachment-error").textContent = txt
3124    setTimeout(() => {
3125        helper.getElement("wk-cw-attachment-error").textContent = ''
3126        helper.getElement("wk-cw-attachment-error").style.display = "none"
3127    }, 3000);
3128}
3129let aud;
3130if(wkli_clientNotifySoundStatus) {
3131    if(wkli_clientNotifySound == '1') {
3132        aud = new Audio(`${WKprotocol}${WKscript}/uploads/1.wav`);
3133    } else if(wkli_clientNotifySound == '2') {
3134        aud = new Audio(`${WKprotocol}${WKscript}/uploads/2.wav`);
3135    } else {
3136        aud = new Audio(`${WKprotocol}${WKscript}/uploads/3.wav`);
3137    }
3138}
3139
3140function getLocalTimestamp(date = false) {
3141    let today = new Date();
3142    // the admin picked language, or the visitor's own browser locale when none is set
3143    let locale = (typeof wkli_locale != 'undefined' && wkli_locale) ? wkli_locale : undefined;
3144    date = date ? new Date(date) : new Date();
3145    if (date.toDateString() == today.toDateString()) {
3146        let todayText = (typeof wkli_todayText != 'undefined' && wkli_todayText) ? wkli_todayText : 'Today';
3147        return todayText + ', ' + date.toLocaleTimeString(locale);
3148    }
3149    return date.toLocaleString(locale);
3150}
3151function wkli_replyButtonBody(data){
3152    let active = document.querySelectorAll('.wk-cw-active')
3153    if(active.length){
3154        active.forEach((chat) => {
3155            chat.classList.remove('wk-cw-active')
3156        })
3157    }
3158    if(wkli_normalReplyData != '' && data.sendTimestamp && wkli_normalReplyData.message == data.message && wkli_normalReplyData.timestamp == data.sendTimestamp) {
3159        wkli_normalReplyData = '';
3160        
3161    }else{
3162        wkli_normalReplyData = {
3163            message :  data.message,
3164            senderId : data.senderId,
3165            timestamp : data.sendTimestamp,
3166            messageId: data.messageId
3167        };
3168        let elem = document.getElementById("rep"+data.messageId)
3169        if(elem){
3170            elem.classList.add('wk-cw-active');
3171        }
3172    }
3173    if(wkli_normalReplyData != ''){
3174        let usrData = JSON.parse(localStorage.getItem(localStorageVar));
3175        let senderName = wkli_replyYouText
3176        if(wkli_normalReplyData.senderId == usrData.operator) {
3177            senderName = wkli_replySupportText
3178        }
3179        let replyMessage 
3180        let msg = data.message.replace(/</g, "&lt;").replace(/>/g, "&gt;").split(' \n');
3181        let getText = msg[0].split('/')
3182        let checkImgExt = msg[0].split('.')
3183        let imgName = getText[getText.length - 1]
3184        const audioTypes = ['mp3','ogg','wav']
3185        if(helper.checkImg.includes(checkImgExt[checkImgExt.length - 1]) || (helper.checkAttachment.includes(checkImgExt[checkImgExt.length - 1])) || audioTypes.indexOf(checkImgExt.pop()) !== -1){
3186            replyMessage = imgName;
3187        }else{
3188            replyMessage = data.message;
3189        } 
3190        helper.getElement("wk-cw-chatbot-reply-block").style.display = "block"
3191        helper.getElement("wk-ch-chatbot-replyBlock-name").textContent = senderName;
3192        helper.getElement("wk-ch-chatbot-replyBlock-message").innerHTML = replyMessage;
3193        helper.getElement('wk-cw-message').focus();
3194        helper.getElement("wk-cw-user-operator-chat").style.maxHeight = "305px";
3195    }else{
3196        helper.getElement("wk-cw-chatbot-reply-block").style.display = "none"
3197        helper.getElement("wk-cw-user-operator-chat").style.maxHeight = "370px";
3198    }
3199}
3200
3201function wkli_gotoMsgReplyFor(msg) {
3202    wkli_chat.forEach((chat) => {
3203        if(chat.messageId == msg.messageId || (chat.message == msg.message && chat.sendTimestamp == msg.timestamp)) {
3204            let elem = document.getElementById('wkli'+chat.messageId)
3205            if(elem && elem.parentNode) {
3206                elem.parentNode.classList.add('wk-cw-msg-highlighter');
3207                setTimeout(() => elem.parentNode.classList.remove('wk-cw-msg-highlighter'), 3000)
3208                wkli_scrollToMsg('wkli'+chat.messageId);
3209            }
3210        }
3211    })
3212}
3213
3214function wkli_scrollToMsg(msgId) {
3215    let scrollTo = document.querySelector('#'+msgId);
3216    let element = helper.getElement("wk-cw-user-operator-chat");
3217    element.scrollTop = scrollTo.offsetTop -150
3218    // let container = document.querySelectorAll('#wk-cw-user-operator-chat');
3219    // if(scrollTo.length)
3220    //     container.scrollTop(scrollTo.offset().top - container.offset().top + container.scrollTop() - 15);
3221}
3222
3223function wkli_scrollToElement(id) {
3224    // center the field wrapper (input + warning) in whatever scrolls the form
3225    document.getElementById(id).parentElement.scrollIntoView({ block: 'center' });
3226}
3227
3228function setWkli_isChatwithchatbot(newValue) {
3229    console.log(newValue)
3230    if(newValue != wkli_isChatwithchatbot) {
3231        wkli_isChatwithchatbot = newValue
3232        if(newValue) {
3233            console.log('disable')
3234            helper.getElement(Ids.chatWithChatbot).style.display = 'none'
3235        } else {
3236            console.log('enable')
3237            helper.getElement(Ids.chatWithChatbot).style.display = 'block'
3238        }
3239    }
3240}
3241
3242if(wkli_autoOpenWidget && !new URL(location.href).searchParams.get('name')){
3243    if(wkli_showUvdeskWidget){
3244        user.openChatBlock()
3245    }else{
3246        wkli_waba_number ? user.preOpenchatBlockOption() : user.openChatBlock()
3247    }
3248}
3249
3250if(JSON.parse(localStorage.getItem(localStorageVar))) {
3251    initializeSocket().then(()=> {
3252    }).catch(err => console.log(err))
3253}
3254
3255/**
3256 * Restart chat on change. A chat belongs to the value of one page-injected custom input
3257 * (wkli_chatwhizz_<handleName>), stamped on the session as restartChatValue when the chat registers.
3258 * The page only changes that value on reload, so this runs when the socket connects: a different
3259 * value ends the chat and opens a new one. An empty/missing input is no signal and never ends the chat.
3260 */
3261function wkli_checkRestartChat() {
3262    if (!wkli_restart_chat_field || wkli_restart_chat_pending || wkli_client_blocked)
3263        return;
3264    let value = wkli_getInjectedValue(wkli_restart_chat_field);
3265    let session = JSON.parse(localStorage.getItem(localStorageVar));
3266    if (!value || !session)
3267        return;
3268    if (!session.restartChatValue) {
3269        //chat registered before the setting was on, or on a page without the input
3270        session.restartChatValue = value;
3271        localStorage.setItem(localStorageVar, JSON.stringify(session));
3272        return;
3273    }
3274    if (session.restartChatValue == value)
3275        return;
3276    wkli_restart_chat_pending = true;
3277    helper.clearAllTimeoutAndInterval();
3278    user.endConversation();
3279}
3280
3281let wkli_liveChatContent = document.getElementById('wk-ch-livechat-content');
3282
3283wkli_liveChatContent.addEventListener('scroll', function(e) {
3284    if(wkli_liveChatContent.scrollTop != 0) {
3285        document.getElementById('wk-cw-welcomeText').style.borderBottom = '1px solid #999';
3286    } else {
3287        document.getElementById('wk-cw-welcomeText').style.borderBottom = '1px solid #fff';
3288    }
3289})

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.