HEX
Server: LiteSpeed
System: Linux linux31.centraldnserver.com 4.18.0-553.83.1.lve.el8.x86_64 #1 SMP Wed Nov 12 10:04:12 UTC 2025 x86_64
User: salamatk (1501)
PHP: 8.1.33
Disabled: show_source, system, shell_exec, passthru, exec, popen, proc_open
Upload Files
File: /home/salamatk/public_html/wp-content/plugins/woodmart-plus/assets/js/chat-bot.js
(function($) {
    'use strict';

    $(document).ready(function() {
        
        const STORAGE_KEY = 'chatBotMessages';
        const MAX_STORED_MESSAGES = 200;

        const INPUT_DEFAULT_HEIGHT = 44;

        const $toggle = $('#chatBotToggle');
        const $container = $('#chatBotContainer');
        const $messages = $('#chatBotMessages');
        const $input = $('#chatBotInput');
        const $sendBtn = $('#chatBotSend');
        const $resetBtn = $('#chatBotReset');

        let isOpen = false;
        let storedMessages = loadMessagesFromStorage();
        const initialMessageTemplate = $messages.find('.chat-initial-message').first().prop('outerHTML') || '';

        restoreStoredMessages();

        function toggleChat() {
            isOpen = !isOpen;
            $toggle.toggleClass('active', isOpen);
            $container.toggleClass('active', isOpen);
            
            if (isOpen) {
                $input.focus();
                const duration = storedMessages.length ? 1000 : 300;
                scrollToBottom({ duration });
            }
        }

        $toggle.on('click', function(e) {
            e.preventDefault();
            toggleChat();
        });

        function sendMessage(messageOverride) {
            const message = typeof messageOverride === 'string' ? messageOverride.trim() : $input.val().trim();
            
            if (!message) {
                return;
            }

            $sendBtn.prop('disabled', true);

            addMessage(message, 'user');

            if (typeof messageOverride !== 'string') {
                $input.val('');
                resetInputHeight();
            }

            showTypingIndicator();

            $.ajax({
                dataType:'json',type:'post',url : chatBotAi.ajaxUrl,
                data: {
                    action: 'ai_send_message',
                    message : message,
                    history : storedMessages,
                    nonce : chatBotAi.nonce
                },  
                success:function(responses)
                {
                    removeTypingIndicator();
                    
                    addMessage(responses.message, 'bot');
                    $sendBtn.prop('disabled', false);
                    $input.focus();
                },
                error:function (error)
                {
                    removeTypingIndicator();
                    addMessage(error.responseJSON.message, 'bot',{
                        save : false
                    });
                    $sendBtn.prop('disabled', false);
                    $input.focus();
                }
            });
        }

        $sendBtn.on('click', function(e) {
            e.preventDefault();
            sendMessage();
        });

        $input.on('keypress', function(e) {
            if (e.which === 13 && !e.shiftKey) {
                e.preventDefault();
                sendMessage();
            }
        });
        $input.on('input', function() {
            adjustInputHeight();
        });
        adjustInputHeight();

        function addMessage(text, type, options = {}) {
            const messageTime = options.time || getCurrentTime();
            const messageClass = type === 'user' ? 'user-message' : 'bot-message';
            const senderName = type === 'user' ? chatBotAi.chatbot_txt.user_title : chatBotAi.chatbot_txt.chatbot_name;
            const enableActions = type === 'bot' && options.enableActions !== false;
            const safeText = (type === 'bot') ? text : escapeHtml(text);

            
            let actionsHTML = '';
            if (enableActions) {
                actionsHTML = `
                    <div class="message-actions">
                        <div class="message-action-btn" data-action="copy" title="${chatBotAi.chatbot_txt.title_copy_btn}">
                            <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                <rect x="9" y="9" width="13" height="13" rx="2" ry="2" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                                <path d="M5 15H4C2.89543 15 2 14.1046 2 13V4C2 2.89543 2.89543 2 4 2H13C14.1046 2 15 2.89543 15 4V5" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                            </svg>
                        </div>
                        <div class="message-action-btn" data-action="resend" title="${chatBotAi.chatbot_txt.title_resend_btn}">
                            <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                <path d="M1 4V10H7" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                                <path d="M23 20V14H17" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                                <path d="M20.49 9C19.81 4.81 16.05 1.5 11.64 1.5C6.87 1.5 2.64 5.36 2.05 10.01M3.51 15C4.19 19.19 7.95 22.5 12.36 22.5C17.13 22.5 21.36 18.64 21.95 13.99" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                            </svg>
                        </div>
                    </div>
                `;
            }
    
            const messageHTML = `
                <div class="message ${messageClass}">
                    <div class="message-content">
                        <div class="message-text">${safeText}</div>
                    </div>
                    <div class="message-footer">
                        ${actionsHTML}
                        <div class="message-footer-left">
                            <div class="message-avatar">
                                <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                    <path d="M20 21V19C20 17.9391 19.5786 16.9217 18.8284 16.1716C18.0783 15.4214 17.0609 15 16 15H8C6.93913 15 5.92172 15.4214 5.17157 16.1716C4.42143 16.9217 4 17.9391 4 19V21" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                                    <circle cx="12" cy="7" r="4" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                                </svg>
                            </div>
                            <span class="message-sender">${senderName}</span>
                            <span class="message-time-header">${messageTime}</span>
                        </div>
                    </div>
                </div>
            `;

            $messages.append(messageHTML);

            if (options.scroll !== false) {
                scrollToBottom();
            }

            if (options.save !== false) {
                const meta = typeof options.meta === 'object' ? options.meta : { enableActions };

                persistMessage({
                    text: text,
                    type: type,
                    time: messageTime,
                    meta: meta
                });
            }
        }
        
        function copyToClipboard(text) {
            const textarea = document.createElement('textarea');
            textarea.value = text;
            textarea.style.position = 'fixed';
            textarea.style.opacity = '0';
            document.body.appendChild(textarea);
            textarea.select();
            try {
                document.execCommand('copy');
                showToast(chatBotAi.chatbot_txt.when_copy);
            } catch (err) {
                console.error(chatBotAi.chatbot_txt.when_copy_error, err);
            }
            document.body.removeChild(textarea);
        }
        
        function showToast(message) {
            const toast = $('<div class="toast-message">' + message + '</div>');
            $('body').append(toast);
            setTimeout(function() {
                toast.addClass('show');
            }, 10);
            setTimeout(function() {
                toast.removeClass('show');
                setTimeout(function() {
                    toast.remove();
                }, 300);
            }, 2000);
        }

        function showTypingIndicator() {
            const typingHTML = `
                <div class="message bot-message typing-message">
                    <div class="message-content">
                        <div class="typing-indicator">
                            <span></span>
                            <span></span>
                            <span></span>
                        </div>
                    </div>
                    <div class="message-footer">
                        <div class="message-footer-left">
                            <div class="message-avatar">
                                <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                    <path d="M20 21V19C20 17.9391 19.5786 16.9217 18.8284 16.1716C18.0783 15.4214 17.0609 15 16 15H8C6.93913 15 5.92172 15.4214 5.17157 16.1716C4.42143 16.9217 4 17.9391 4 19V21" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                                    <circle cx="12" cy="7" r="4" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                                </svg>
                            </div>
                            <span class="message-sender">${chatBotAi.chatbot_txt.chatbot_name}</span>
                            <span class="message-time-header">${chatBotAi.chatbot_txt.when_type}</span>
                        </div>
                    </div>
                </div>
            `;
            $messages.append(typingHTML);
            scrollToBottom();
        }

        function removeTypingIndicator() {
            $messages.find('.typing-message').remove();
        }

        function scrollToBottom(options = {}) {
            const duration = typeof options.duration === 'number' ? options.duration : 300;

            if (!duration) {
                $messages.scrollTop($messages[0].scrollHeight);
                return;
            }

            $messages.stop(true).animate({
                scrollTop: $messages[0].scrollHeight
            }, duration, 'swing');
        }

        function getCurrentTime() {
            const now = new Date();
            const hours = now.getHours().toString().padStart(2, '0');
            const minutes = now.getMinutes().toString().padStart(2, '0');
            return `${hours}:${minutes}`;
        }

        function adjustInputHeight() {
            const inputEl = $input[0];
            if (!inputEl) {
                return;
            }
            inputEl.style.height = 'auto';
            inputEl.style.height = Math.min(inputEl.scrollHeight, 120) + 'px';
        }

        function resetInputHeight() {
            const inputEl = $input[0];
            if (!inputEl) {
                return;
            }
            inputEl.style.height = 'auto';
            inputEl.style.height = INPUT_DEFAULT_HEIGHT + 'px';
        }

        function loadMessagesFromStorage() {
            try {
                const saved = localStorage.getItem(STORAGE_KEY);
                return saved ? JSON.parse(saved) : [];
            } catch (e) {
                console.error('Failed to load chat history:', e);
                return [];
            }
        }

        function persistMessage(message) {
            storedMessages.push(message);

            if (storedMessages.length > MAX_STORED_MESSAGES) {
                storedMessages = storedMessages.slice(-MAX_STORED_MESSAGES);
            }

            saveMessagesToStorage();
        }

        function saveMessagesToStorage() {
            try {
                localStorage.setItem(STORAGE_KEY, JSON.stringify(storedMessages));
            } catch (e) {
                console.error('Failed to save chat history:', e);
            }
        }

        function removeMessageFromHistory(text, type) {
            if (!text || !type) {
                return;
            }

            let removed = false;

            for (let i = storedMessages.length - 1; i >= 0; i--) {
                const record = storedMessages[i];
                if (record && record.text === text && record.type === type) {
                    storedMessages.splice(i, 1);
                    removed = true;
                    break;
                }
            }

            if (removed) {
                saveMessagesToStorage();
            }
        }

        function removeMessageElement($element) {
            if (!$element || !$element.length) {
                return;
            }

            $element.stop(true).animate({
                opacity: 0,
                marginTop: 0,
                marginBottom: 0
            }, 150, function() {
                $(this).remove();
            });
        }

        function restoreStoredMessages() {
            if (!storedMessages.length) {
                return;
            }

            storedMessages.forEach(function(message) {
                if (message && message.text && message.type) {
                    const enableActions = !(message.meta && message.meta.enableActions === false);

                    addMessage(message.text, message.type, {
                        time: message.time,
                        save: false,
                        scroll: false,
                        enableActions: enableActions,
                        meta: message.meta || {}
                    });
                }
            });
        }

        function escapeHtml(text) {
            const map = {
                '&': '&amp;',
                '<': '&lt;',
                '>': '&gt;',
                '"': '&quot;',
                "'": '&#039;'
            };
            return text.replace(/[&<>"']/g, function(m) { return map[m]; });
        }

        $(document).on('click', function(e) {
            if (isOpen && 
                !$container.is(e.target) && 
                $container.has(e.target).length === 0 &&
                !$toggle.is(e.target) &&
                $toggle.has(e.target).length === 0) {
                toggleChat();
            }
        });

        $container.on('click', function(e) {
            e.stopPropagation();
        });

        function sendQuickQuestion(question) {
            if (!question) {
                return;
            }
            
            $input.val('');
            resetInputHeight();
            $sendBtn.prop('disabled', false);

            const answer = findPredefinedAnswer(question);

            if (answer) {
                addMessage(question, 'user');
                showTypingIndicator();

                setTimeout(function() {
                    removeTypingIndicator();
                    addMessage(answer, 'bot', {
                        enableActions: false,
                        meta: { enableActions: false }
                    });
                }, 400);
                return;
            }

            sendMessage(question);
        }

        function findPredefinedAnswer(rawQuestion) {
            if (!rawQuestion) {
                return '';
            }

            const question = rawQuestion.trim().toLowerCase();
            const data = chatBotAi.pre_question_answer || [];

            if (Array.isArray(data)) {
                const match = data.find(function(item) {
                    if (!item || !item.question || !item.answer) {
                        return false;
                    }
                    return item.question.trim().toLowerCase() === question;
                });

                return match && match.answer ? match.answer : '';
            }

            if (typeof data === 'object') {
                for (const key in data) {
                    if (!Object.prototype.hasOwnProperty.call(data, key)) {
                        continue;
                    }

                    if (key.trim().toLowerCase() === question) {
                        return data[key];
                    }
                }
            }

            return '';
        }

        $container.on('click', '.quick-question-btn', function(e) {
            e.preventDefault();
            const question = $(this).text();
            sendQuickQuestion(question);
        });

        $container.on('click', '.message-action-btn[data-action="copy"]', function(e) {
            e.preventDefault();
            const $message = $(this).closest('.message');
            const text = $message.find('.message-text').text();
            copyToClipboard(text);
        });
        
        $container.on('click', '.message-action-btn[data-action="resend"]', function(e) {
            e.preventDefault();

            const $botMessage = $(this).closest('.message.bot-message');
            const $userMessage = $botMessage.prevAll('.message.user-message').first();

            if (!$botMessage.length || !$userMessage.length) {
                return;
            }

            const userText = $userMessage.find('.message-text').text().trim();
            const botText = $botMessage.find('.message-text').text().trim();

            if (!userText) {
                return;
            }

            removeTypingIndicator();

            removeMessageElement($botMessage);
            removeMessageElement($userMessage);

            removeMessageFromHistory(botText, 'bot');
            removeMessageFromHistory(userText, 'user');

            setTimeout(function() {
                sendMessage(userText);
            }, 180);
        });

        if ($resetBtn.length) {
            $resetBtn.on('click', function(e) {
                e.preventDefault();
                resetConversation();
            });
        }

        function resetConversation() {
            if ($resetBtn.prop('disabled')) {
                return;
            }

            removeTypingIndicator();
            $resetBtn.prop('disabled', true);
            storedMessages = [];
            localStorage.removeItem(STORAGE_KEY);
            $input.val('');
            resetInputHeight();
            $sendBtn.prop('disabled', false);

            $messages.stop(true).animate({ opacity: 0 }, 180, function() {
                $messages.empty();
                if (initialMessageTemplate) {
                    $messages.append(initialMessageTemplate);
                }

                $messages.css('opacity', 0).animate({ opacity: 1 }, 220, function() {
                    $resetBtn.prop('disabled', false);
                    if (isOpen) {
                        scrollToBottom({ duration: 200 });
                    }
                });
            });
        }
    });

})(jQuery);