Code: Select all
(function() {
'use strict';
var STORAGE_KEY_RESULTS = 'dmzx_chatbot_conv';
var STORAGE_KEY_QUERY = 'dmzx_chatbot_last_query';
var STORAGE_KEY_OPEN = 'dmzx_chatbot_open'; // '1' = open, '0' = minimized
var STORAGE_KEY_SUGGESTIONS = 'dmzx_chatbot_suggestions_cache';
var SUGGESTIONS_TTL = 60 * 60; // seconds (1 hour)
var HISTORY_MAX = 3;
if (typeof dmzx_chatbot !== 'undefined' && typeof dmzx_chatbot.lastsearch_limit !== 'undefined') {
var parsedLimit = parseInt(dmzx_chatbot.lastsearch_limit, 10);
if (!isNaN(parsedLimit) && parsedLimit >= 0) {
HISTORY_MAX = parsedLimit;
}
}
var typingTimers = {};
if (typeof dmzx_chatbot !== 'undefined' && (parseInt(dmzx_chatbot.enabled, 10) === 0)) {
return;
}
function saveConv(conv) {
try {
if (!conv || !conv.length) {
sessionStorage.removeItem(STORAGE_KEY_RESULTS);
} else {
sessionStorage.setItem(STORAGE_KEY_RESULTS, JSON.stringify(conv));
}
} catch(e){}
}
function loadConv() {
try {
var raw = sessionStorage.getItem(STORAGE_KEY_RESULTS);
if (raw) return JSON.parse(raw);
} catch(e){}
return [];
}
function saveHistory(query) {
try {
if (!query) return;
if (typeof dmzx_chatbot !== 'undefined' && parseInt(dmzx_chatbot.lastsearch_enabled, 10) === 0) {
return;
}
var key = 'dmzx_chatbot_history';
var arr = JSON.parse(localStorage.getItem(key) || '[]');
arr = arr.filter(function(q){ return q !== query; });
arr.unshift(query);
if (typeof HISTORY_MAX === 'number' && HISTORY_MAX >= 0 && arr.length > HISTORY_MAX) {
arr = arr.slice(0, HISTORY_MAX);
}
localStorage.setItem(key, JSON.stringify(arr));
} catch (e) {}
}
function loadHistory() {
try {
if (typeof dmzx_chatbot !== 'undefined' && parseInt(dmzx_chatbot.lastsearch_enabled, 10) === 0) {
return [];
}
var raw = localStorage.getItem('dmzx_chatbot_history');
if (!raw) return [];
var arr = JSON.parse(raw);
if (!Array.isArray(arr)) return [];
if (typeof HISTORY_MAX === 'number' && HISTORY_MAX >= 0) {
return arr.slice(0, HISTORY_MAX);
}
return arr;
} catch (e) {
return [];
}
}
function saveSuggestionsCache(items) {
try {
var payload = { ts: Math.floor(Date.now()/1000), items: items };
sessionStorage.setItem(STORAGE_KEY_SUGGESTIONS, JSON.stringify(payload));
} catch (e) {}
}
function loadSuggestionsCache() {
try {
var raw = sessionStorage.getItem(STORAGE_KEY_SUGGESTIONS);
if (!raw) return null;
var p = JSON.parse(raw);
if (!p || !p.ts || !p.items) return null;
var now = Math.floor(Date.now()/1000);
if (now - p.ts > SUGGESTIONS_TTL) {
sessionStorage.removeItem(STORAGE_KEY_SUGGESTIONS);
return null;
}
return p.items;
} catch (e) {
return null;
}
}
function appendUserBubble($resultsEl, text) {
var $row = $('<div/>').addClass('dmzx-chat-row user');
var $b = $('<div/>').addClass('dmzx-chat-bubble user').text(text);
$row.append($b);
$resultsEl.append($row);
$resultsEl.scrollTop($resultsEl.prop('scrollHeight'));
}
function createTypingIndicator() {
var $wrap = $('<div/>').addClass('dmzx-typing');
var $indicator = $('<div/>').addClass('typing-indicator').attr('aria-hidden', 'true');
$indicator.append($('<span/>').addClass('typing-dot'));
$indicator.append($('<span/>').addClass('typing-dot'));
$indicator.append($('<span/>').addClass('typing-dot'));
$wrap.append($indicator);
$wrap.append($('<div/>').text(dmzx_chatbot.lang.loading).css({marginLeft:'8px', fontSize:'12px', color:'#666'}));
return $wrap;
}
function appendBotBubble($resultsEl, id, htmlOrText, isTyping) {
var $row = $('<div/>').addClass('dmzx-chat-row bot').attr('data-bubble-id', id);
var $b = $('<div/>').addClass('dmzx-chat-bubble bot').html(htmlOrText);
$row.append($b);
if (isTyping) {
var $t = createTypingIndicator();
$row.append($t);
var timer = setInterval(function() {
}, 800);
typingTimers[id] = {
timer: timer,
el: $t
};
}
$resultsEl.append($row);
$resultsEl.scrollTop($resultsEl.prop('scrollHeight'));
}
function replaceBotBubble($resultsEl, id, newHtml) {
var $row = $resultsEl.find('[data-bubble-id="'+id+'"]');
if ($row.length) {
if (typingTimers[id]) {
try { clearInterval(typingTimers[id].timer); } catch(e){}
try { typingTimers[id].el.remove(); } catch(e){}
delete typingTimers[id];
}
$row.empty();
var $b = $('<div/>').addClass('dmzx-chat-bubble bot').html(newHtml);
$row.append($b);
$resultsEl.scrollTop($resultsEl.prop('scrollHeight'));
}
}
function renderThreadResultsInto($container, threads) {
if (!threads || !threads.length) {
$container.append($('<div/>').addClass('dmzx-chatbot-empty').text(dmzx_chatbot.lang.no_results));
return;
}
function decodeEntitiesInHtml(html) {
var tmp = document.createElement('div');
tmp.innerHTML = html;
var walker = document.createTreeWalker(tmp, NodeFilter.SHOW_TEXT, null, false);
var node;
while ((node = walker.nextNode())) {
node.nodeValue = decodeHtmlEntities(node.nodeValue);
}
return tmp.innerHTML;
}
threads.forEach(function(t){
var $div = $('<div/>').addClass('dmzx-chatbot-thread');
var $a = $('<a/>')
.addClass('dmzx-chatbot-thread-title dmzx-chatbot-link')
.attr({ href: t.url });
if (t.title_html) {
var safeHtml = decodeEntitiesInHtml(t.title_html);
$a.html(safeHtml);
} else {
var title = decodeHtmlEntities(t.title || '');
title = decodeHtmlEntities(title);
$a.text(title);
}
$div.append($a);
if (t.snippet_html) {
var $s = $('<div/>').addClass('dmzx-chatbot-snippet').html(t.snippet_html);
$div.append($s);
}
$container.append($div);
});
}
function renderProfileInto($container, profileObj) {
if (!profileObj || !profileObj.profile) {
$container.append($('<div/>').addClass('dmzx-chatbot-empty').text(dmzx_chatbot.lang.user_not_found));
return;
}
var profile = profileObj.profile;
var posts = profileObj.recent_posts || [];
var $card = $('<div/>').addClass('dmzx-chatbot-profile');
$card.append($('<h3/>').text(profile.username));
$card.append($('<div/>').addClass('meta').html('Joined: ' + profile.joined + ' • Posts: ' + profile.posts + (profile.last_seen ? (' • Last seen: ' + profile.last_seen) : '')));
$card.append($('<div/>').append($('<a/>').attr({href: profile.profile_url, class: 'dmzx-chatbot-link'}).text(dmzx_chatbot.lang.view_profile).css({'color':'#007cba'})));
if (posts.length) {
$card.append($('<div/>').css({marginTop:'8px', marginBottom:'4px', fontSize:'13px'}).text(dmzx_chatbot.lang.recent_posts));
var $ul = $('<ul/>').addClass('recent').css({paddingLeft:'18px', marginTop:'6px'});
posts.forEach(function(p){
var $li = $('<li/>');
var $a = $('<a/>').attr({href: p.url, class: 'dmzx-chatbot-link'}).text(p.topic_title).css({'color':'#007cba'});
$li.append($a);
$li.append($('<div/>').css({fontSize:'12px', color:'#444'}).text(p.snippet));
$ul.append($li);
});
$card.append($ul);
}
$container.append($card);
}
function makeBubbleId() {
return 'b_' + Math.random().toString(36).slice(2,9);
}
function decodeHtmlEntities(str) {
if (!str || typeof str !== 'string') return str;
var txt = document.createElement('textarea');
txt.innerHTML = str;
return txt.value;
}
function ensureHistorySlot($container) {
var $slot = $container.find('.dmzx-history-slot');
if ($slot.length === 0) {
$slot = $('<div/>').addClass('dmzx-history-slot').attr('aria-hidden', 'true');
$container.append($slot);
}
return $slot;
}
function resolveBoardFile(filename) {
try {
var base = (typeof dmzx_chatbot !== 'undefined' && dmzx_chatbot.board_url) ? dmzx_chatbot.board_url : (window.location.protocol + '//' + window.location.host + '/');
try {
base = (new URL(base, window.location.href)).href;
} catch (e) {
}
base = base.replace(/[#?].*$/, '');
base = base.replace(/\/(?:app|index)\.php(?:\/)?$/i, '/');
if (base.charAt(base.length - 1) !== '/') {
base += '/';
}
return new URL(filename, base).href;
} catch (e) {
try {
return new URL(filename, window.location.href).href;
} catch (ee) {
return filename;
}
}
}
function renderInitialGreeting($resultsEl) {
var text = dmzx_chatbot.lang.welcome;
$resultsEl.find('[data-initial]').remove();
var $row = $('<div/>').addClass('dmzx-chat-row');
var $b = $('<div/>').addClass('dmzx-chat-bubble bot').text(text);
$row.append($b);
$resultsEl.append($row);
$resultsEl.scrollTop($resultsEl.prop('scrollHeight'));
}
function clearConversation($resultsEl) {
try {
sessionStorage.removeItem(STORAGE_KEY_RESULTS);
sessionStorage.removeItem(STORAGE_KEY_QUERY);
} catch (e) {}
$resultsEl.empty();
renderInitialGreeting($resultsEl);
$('#dmzx-chatbot-query').val('').focus();
}
function renderDbSuggestions($container, suggestions) {
$container.find('.dmzx-db-suggestion').remove();
if (!suggestions || !suggestions.length) return;
var limit = (typeof dmzx_chatbot !== 'undefined' && dmzx_chatbot.popular_limit) ? parseInt(dmzx_chatbot.popular_limit, 10) : 3;
var limited = suggestions.slice(0, limit);
var $slot = ensureHistorySlot($container);
var $label = $('<div/>').addClass('dmzx-chat-suggestion dmzx-db-suggestion').css({'background':'#fff','border':'1px solid #eee','color':'#444','cursor':'default'}).text(dmzx_chatbot.lang.popular);
$label.insertBefore($slot);
limited.forEach(function(s) {
var $chip = $('<div/>').addClass('dmzx-chat-suggestion dmzx-db-suggestion').text(decodeHtmlEntities(s));
$chip.insertBefore($slot);
});
}
function renderHistoryChips($container) {
try {
var $slot = ensureHistorySlot($container);
$slot.empty();
var history = loadHistory();
if (!history || !history.length) return;
var $wrap = $('<div/>').addClass('dmzx-history-wrapper').css({marginTop:'6px', marginBottom:'6px'});
var $label = $('<div/>').addClass('dmzx-history-header').text(dmzx_chatbot.lang.recent_posts).css({marginBottom:'6px'});
$wrap.append($label);
var $row = $('<div/>').addClass('dmzx-history-row').css({display:'flex', gap:'6px', flexWrap:'wrap'});
history.forEach(function(q) {
var decoded = decodeHtmlEntities(q);
var $chip = $('<div/>').addClass('dmzx-history-chip').text(decoded).attr('data-q', q);
$row.append($chip);
});
$wrap.append($row);
$slot.append($wrap);
} catch (e) {
}
}
function suggestionsUrl(route) {
if (route && route !== '') {
try {
return route.replace(/\/search(\?.*)?$/i, '/suggestions');
} catch (e) {}
}
return resolveBoardFile('chatbot/suggestions');
}
function feedbackUrl(route) {
if (route && route !== '') {
try {
return route.replace(/\/search(\?.*)?$/i, '/feedback');
} catch (e) {}
}
return resolveBoardFile('chatbot/feedback');
}
function loadSuggestions($container, route, force) {
force = !!force;
var cached = loadSuggestionsCache();
if (!force && cached) {
renderDbSuggestions($container, cached);
return;
}
var $loading = $('<div/>').addClass('dmzx-chat-suggestion dmzx-db-suggestion').text(dmzx_chatbot.lang.loading).attr('data-loading','1');
$container.append($loading);
var url = suggestionsUrl(route);
$.ajax({
url: url,
method: 'GET',
dataType: 'json',
timeout: 10000,
headers: { 'X-Requested-With': 'XMLHttpRequest' }
}).done(function(res) {
$container.find('[data-loading="1"]').remove();
if (res && Array.isArray(res.suggestions) && res.suggestions.length) {
var staticTexts = [];
$container.find('.dmzx-chat-suggestion[data-action]').each(function(){
staticTexts.push($(this).text().trim());
});
var out = [];
res.suggestions.forEach(function(s){
var t = decodeHtmlEntities((s || '').trim());
if (!t) return;
if (staticTexts.indexOf(t) !== -1) return;
if (out.indexOf(t) === -1) out.push(t);
});
saveSuggestionsCache(out);
renderDbSuggestions($container, out);
} else {
$container.find('[data-loading="1"]').remove();
}
}).fail(function() {
$container.find('[data-loading="1"]').remove();
});
}
function appendFeedbackControls($resultsEl, bubbleId, logId, route) {
if (!logId) return;
var $bubble = $resultsEl.find('[data-bubble-id="'+bubbleId+'"] .dmzx-chat-bubble');
if (!$bubble.length) return;
if ($bubble.find('.dmzx-feedback').length) return;
var $controls = $('<div/>').addClass('dmzx-feedback');
var $hint = $('<div/>').text(dmzx_chatbot.lang.helpful_label).css({'margin-right':'8px'});
var $up = $('<button/>').addClass('dmzx-feedback-up').attr('title','Yes').html('👍');
var $down = $('<button/>').addClass('dmzx-feedback-down').attr('title','No').html('👎');
$controls.append($hint).append($up).append($down);
$bubble.append($controls);
var fbUrl = feedbackUrl(route);
function sendFeedback(value, $btn) {
$controls.find('button').prop('disabled', true);
$.ajax({
url: fbUrl,
method: 'POST',
data: { log_id: logId, value: value },
dataType: 'json',
timeout: 10000,
headers: { 'X-Requested-With': 'XMLHttpRequest' }
}).done(function(res) {
$controls.empty().append($('<div/>').addClass('thanks').text(dmzx_chatbot.lang.thanks_feedback));
try { sessionStorage.removeItem('dmzx_chatbot_suggestions_cache'); } catch (e) {}
}).fail(function() {
$controls.empty().append($('<div/>').text('Feedback failed.').css({color:'#c0392b'}));
});
}
$up.on('click', function(e) {
e.preventDefault();
sendFeedback(1, $(this));
});
$down.on('click', function(e) {
e.preventDefault();
sendFeedback(-1, $(this));
});
}
function initChatbot($) {
var $container = $('#dmzx-chatbot-widget-container');
$(function() {
var $widget = $('#dmzx-chatbot-widget');
var $minBtn = $('#dmzx-chatbot-minimized');
var $query = $('#dmzx-chatbot-query');
var $results = $('#dmzx-chatbot-results');
var $submit = $('#dmzx-chatbot-submit');
var $suggestions = $('#dmzx-chatbot-suggestions');
var $clearConvBtn = $('#dmzx-chatbot-clear-conv');
var route = (typeof dmzx_chatbot !== 'undefined' && dmzx_chatbot.chatbot_search_url) ? dmzx_chatbot.chatbot_search_url : '{U_CHATBOT_SEARCH}';
try { if (typeof dmzx_chatbot === 'undefined' || parseInt(dmzx_chatbot.popular_enabled,10) === 1) { loadSuggestions($suggestions, route, false); } } catch (e) {}
try { if (typeof dmzx_chatbot === 'undefined' || parseInt(dmzx_chatbot.lastsearch_enabled,10) === 1) { renderHistoryChips($suggestions); } } catch (e) {}
var openState = sessionStorage.getItem(STORAGE_KEY_OPEN);
if (openState === null) {
sessionStorage.setItem(STORAGE_KEY_OPEN, '0');
openState = '0';
}
if (openState === '1') {
$widget.show();
$minBtn.hide();
} else {
$widget.hide();
$minBtn.show();
}
var conv = loadConv();
if (conv && conv.length) {
$results.empty();
conv.forEach(function(item){
if (item.role === 'user') {
appendUserBubble($results, item.text);
} else {
appendBotBubble($results, item.id || makeBubbleId(), item.html || item.text, false);
}
});
} else {
if ($results.children().length === 0) {
renderInitialGreeting($results);
}
}
$container.css('visibility', 'visible');
$suggestions.on('click', '.dmzx-history-chip', function() {
var q = $(this).attr('data-q') || $(this).text();
$query.val(q).focus();
});
$suggestions.on('click', '.dmzx-chat-suggestion', function() {
var action = $(this).data('action');
if (!action) {
$query.val($(this).text()).focus();
return;
}
if (action === 'faq') {
var faqUrl = resolveBoardFile('faq.php');
var bubbleId = makeBubbleId();
var html = '<div><strong>' + dmzx_chatbot.lang.suggest_faq + '</strong><div style="margin-top:6px;"><a class="dmzx-chatbot-link" href="' + faqUrl + '">' + faqUrl + '</a></div></div>';
appendBotBubble($results, bubbleId, html, false);
conv.push({ role: 'bot', id: bubbleId, html: html });
saveConv(conv);
return;
}
if (action === 'latest') {
var latestUrl = resolveBoardFile('search.php?search_id=newposts');
var bubbleId2 = makeBubbleId();
var viewNewest = dmzx_chatbot.lang.view_newest;
var html2 = '<div><strong>' + dmzx_chatbot.lang.suggest_latest + '</strong><div style="margin-top:6px;"><a class="dmzx-chatbot-link" href="' + latestUrl + '">' + viewNewest + '</a></div></div>';
appendBotBubble($results, bubbleId2, html2, false);
conv.push({ role: 'bot', id: bubbleId2, html: html2 });
saveConv(conv);
return;
}
if (action === 'compose_pm') {
var composeId = makeBubbleId();
var composeHtml = '<div><strong>' + dmzx_chatbot.lang.compose_title + '</strong><div style="margin-top:6px;"><input class="dmzx-compose-input" type="text" placeholder="' + dmzx_chatbot.lang.compose_placeholder + '" aria-label="' + dmzx_chatbot.lang.compose_placeholder + '" /> <button class="dmzx-compose-send">' + dmzx_chatbot.lang.compose_button + '</button></div><div style="margin-top:8px;font-size:12px;color:#666;">' + dmzx_chatbot.lang.compose_title + '</div></div>';
appendBotBubble($results, composeId, composeHtml, false);
conv.push({ role: 'bot', id: composeId, html: composeHtml });
saveConv(conv);
$results.find('[data-bubble-id="'+composeId+'"] .dmzx-compose-input').focus();
return;
}
$query.val($(this).text()).focus();
});
$results.on('click', '.dmzx-compose-send', function(e) {
e.preventDefault();
var $btn = $(this);
var $bubble = $btn.closest('[data-bubble-id]');
if (!$bubble.length) return;
var bid = $bubble.attr('data-bubble-id');
var recipient = $bubble.find('.dmzx-compose-input').val() || '';
recipient = recipient.trim();
if (!recipient) {
replaceBotBubble($results, bid, '<div>' + dmzx_chatbot.lang.please_enter + '</div>');
return;
}
replaceBotBubble($results, bid, '<div><em>' + $('<div/>').text(recipient).html() + '…</em></div>', true);
$.ajax({
url: (typeof dmzx_chatbot !== 'undefined' && dmzx_chatbot.chatbot_search_url) ? dmzx_chatbot.chatbot_search_url.replace(/\/search(\?.*)?$/i, '/user') : resolveBoardFile('chatbot/user'),
method: 'GET',
data: { username: recipient },
dataType: 'json',
timeout: 15000,
headers: { 'X-Requested-With': 'XMLHttpRequest' }
}).done(function(res) {
if (res && res.error) {
replaceBotBubble($results, bid, '<div><strong>' + dmzx_chatbot.lang.error_label + '</strong> ' + $('<div/>').text(res.error).html() + '</div>');
conv.push({ role: 'bot', id: bid, text: res.error });
saveConv(conv);
return;
}
if (!res.profile || !res.profile.user_id) {
replaceBotBubble($results, bid, '<div>' + dmzx_chatbot.lang.user_not_found + '</div>');
conv.push({ role: 'bot', id: bid, text: 'User not found.' });
saveConv(conv);
return;
}
var uid = res.profile.user_id;
var uname = res.profile.username;
var composeUrl = resolveBoardFile('ucp.php?i=pm&mode=compose&u=' + encodeURIComponent(uid) + '&username=' + encodeURIComponent(uname));
var outHtml = '<div><strong>' + $('<div/>').text(uname).html() + '</strong>';
outHtml += '<div style="margin-top:6px;"><a class="dmzx-chatbot-link" href="' + composeUrl + '">' + dmzx_chatbot.lang.compose_open + '</a></div>';
outHtml += '<div style="margin-top:6px;font-size:12px;color:#666;">' + dmzx_chatbot.lang.compose_title + '</div>';
outHtml += '</div>';
replaceBotBubble($results, bid, outHtml);
conv.push({ role: 'bot', id: bid, html: outHtml });
saveConv(conv);
}).fail(function(xhr) {
var fallbackUrl = resolveBoardFile('memberlist.php?mode=search&username=' + encodeURIComponent(recipient));
var errHtml = '<div>' + dmzx_chatbot.lang.lookup_failed.replace('%s', '<a class="dmzx-chatbot-link" href="' + fallbackUrl + '">' + dmzx_chatbot.lang.search_memberlist + '</a>') + '</div>';
replaceBotBubble($results, bid, errHtml);
conv.push({ role: 'bot', id: bid, html: errHtml });
saveConv(conv);
}).always(function(){
$results.scrollTop($results.prop('scrollHeight'));
});
});
$results.on('keydown', '.dmzx-compose-input', function(e) {
if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault();
$(this).closest('[data-bubble-id]').find('.dmzx-compose-send').trigger('click');
}
});
$clearConvBtn.on('click', function(e) {
e.preventDefault();
clearConversation($results);
});
$minBtn.on('click keypress', function(e) {
if (e.type === 'keypress' && e.which !== 13 && e.which !== 32) return;
$widget.show();
$minBtn.hide();
try { sessionStorage.setItem(STORAGE_KEY_OPEN, '1'); } catch(e){}
setTimeout(function(){ $query.focus(); }, 50);
});
$('#dmzx-chatbot-close').on('click', function() {
$widget.hide();
$minBtn.show();
try { sessionStorage.setItem(STORAGE_KEY_OPEN, '0'); } catch (e) {}
});
$query.on('keydown', function(e) {
if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault();
$submit.trigger('click');
}
});
$submit.on('click', function(e) {
e.preventDefault();
e.stopPropagation();
var userMsg = $query.val().trim();
if (!userMsg) {
var hintId = makeBubbleId();
appendBotBubble($results, hintId, dmzx_chatbot.lang.please_enter);
setTimeout(function(){
$results.find('[data-bubble-id="'+hintId+'"]').fadeOut(400, function(){ $(this).remove(); });
}, 1800);
return;
}
appendUserBubble($results, userMsg);
conv.push({ role: 'user', text: userMsg });
saveConv(conv);
$query.val('').focus();
try { saveHistory(userMsg); renderHistoryChips($suggestions); } catch (e) {}
var um = userMsg.match(/^\s*(?:user:|u:)\s*(.+)$/i);
var bubbleId = makeBubbleId();
appendBotBubble($results, bubbleId, '<em>' + dmzx_chatbot.lang.searching + '</em>', true);
if (um) {
var username = um[1].trim();
if (!username) {
replaceBotBubble($results, bubbleId, dmzx_chatbot.lang.please_enter);
return;
}
$.ajax({
url: (typeof dmzx_chatbot !== 'undefined' && dmzx_chatbot.chatbot_search_url) ? dmzx_chatbot.chatbot_search_url.replace(/\/search(\?.*)?$/i, '/user') : resolveBoardFile('chatbot/user'),
method: 'GET',
data: { username: username },
dataType: 'json',
timeout: 12000,
headers: { 'X-Requested-With': 'XMLHttpRequest' }
}).done(function(res) {
if (res && res.error) {
replaceBotBubble($results, bubbleId, '<strong>' + dmzx_chatbot.lang.error_label + '</strong> ' + $('<div/>').text(res.error).html());
return;
}
if (!res || !res.profile) {
var fallbackUrl = resolveBoardFile('memberlist.php?mode=search&username=' + encodeURIComponent(username));
var notFoundHtml = '<div>' + dmzx_chatbot.lang.user_not_found + ' Try <a class="dmzx-chatbot-link" href="' + fallbackUrl + '">' + dmzx_chatbot.lang.search_memberlist + '</a></div>';
replaceBotBubble($results, bubbleId, notFoundHtml);
conv.push({ role: 'bot', id: bubbleId, html: notFoundHtml });
saveConv(conv);
return;
}
var $tmp = $('<div/>');
renderProfileInto($tmp, res);
replaceBotBubble($results, bubbleId, $tmp.html());
conv.push({ role: 'bot', id: bubbleId, html: $tmp.html() });
saveConv(conv);
}).fail(function(xhr, status) {
var fallbackUrl = resolveBoardFile('memberlist.php?mode=search&username=' + encodeURIComponent(username));
var errHtml = '<div>' + dmzx_chatbot.lang.lookup_failed.replace('%s', '<a class="dmzx-chatbot-link" href="' + fallbackUrl + '">' + dmzx_chatbot.lang.search_memberlist + '</a>') + '</div>';
replaceBotBubble($results, bubbleId, errHtml);
conv.push({ role: 'bot', id: bubbleId, html: errHtml });
saveConv(conv);
}).always(function(){
$results.scrollTop($results.prop('scrollHeight'));
});
return;
}
var postUrl = (typeof dmzx_chatbot !== 'undefined' && dmzx_chatbot.chatbot_search_url) ? dmzx_chatbot.chatbot_search_url : '{U_CHATBOT_SEARCH}';
replaceBotBubble($results, bubbleId, '<em>' + dmzx_chatbot.lang.searching + '</em>');
$.ajax({
url: postUrl,
method: 'POST',
data: { query: userMsg },
dataType: 'text',
timeout: 20000,
headers: { 'X-Requested-With': 'XMLHttpRequest' }
}).done(function(text) {
var res;
try {
res = JSON.parse(text);
} catch (e) {
replaceBotBubble($results, bubbleId, dmzx_chatbot.lang.invalid_json);
return;
}
if (res.error) {
replaceBotBubble($results, bubbleId, '<strong>' + dmzx_chatbot.lang.error_label + '</strong> ' + $('<div/>').text(res.error).html());
return;
}
if (res.threads && res.threads.length) {
var $tmp = $('<div/>');
renderThreadResultsInto($tmp, res.threads);
var foundMsg = dmzx_chatbot.lang.i_found.replace('%d', res.threads.length);
var lead = '<div style="margin-bottom:6px;font-size:13px;color:#444;">' + foundMsg + '</div>';
replaceBotBubble($results, bubbleId, lead + $tmp.html());
conv.push({ role: 'bot', id: bubbleId, html: lead + $tmp.html() });
saveConv(conv);
try {
if (res.log_id) {
appendFeedbackControls($results, bubbleId, res.log_id, route);
}
} catch (e) {}
try { sessionStorage.removeItem('dmzx_chatbot_suggestions_cache'); } catch (e) {}
} else {
var html = '';
if (res.message) {
html += '<div>' + $('<div/>').text(res.message).html() + '</div>';
} else {
html += '<div>' + dmzx_chatbot.lang.no_results + '</div>';
}
if (res.suggestions && Array.isArray(res.suggestions) && res.suggestions.length) {
html += '<div style="margin-top:8px;font-size:13px;color:#333;">';
html += '<strong>' + dmzx_chatbot.lang.popular + '</strong>';
html += '<ul style="margin:6px 0 0 16px;padding:0;font-size:13px;color:#444;">';
res.suggestions.forEach(function(s) {
var t = $('<div/>').text(s.text || '').html();
var u = s.url || '#';
html += '<li style="margin-bottom:6px;"><a class="dmzx-chatbot-link" href="' + u + '">' + t + '</a></li>';
});
html += '</ul></div>';
}
replaceBotBubble($results, bubbleId, html);
conv.push({ role: 'bot', id: bubbleId, html: html });
saveConv(conv);
try {
if (res.log_id) {
appendFeedbackControls($results, bubbleId, res.log_id, route);
}
} catch (e) {}
}
}).fail(function(xhr, status) {
var body = xhr && xhr.responseText ? xhr.responseText : null;
if (body) {
try {
var parsed = JSON.parse(body);
replaceBotBubble($results, bubbleId, parsed.error || parsed.message || dmzx_chatbot.lang.request_failed.replace('%s', status));
return;
} catch (e) {}
}
replaceBotBubble($results, bubbleId, dmzx_chatbot.lang.request_failed.replace('%s', (xhr && xhr.status ? xhr.status + ' ' + xhr.statusText : status)));
}).always(function(){
$results.scrollTop($results.prop('scrollHeight'));
});
});
$results.on('click', 'a.dmzx-chatbot-link', function(e) {
try {
var curQuery = $query.val() || '';
sessionStorage.setItem(STORAGE_KEY_QUERY, curQuery);
} catch (err) {}
try {
if (window.innerWidth <= 520) {
$widget.hide();
$minBtn.show();
try { sessionStorage.setItem(STORAGE_KEY_OPEN, '0'); } catch (ee) {}
$minBtn.attr('aria-pressed', 'false');
}
} catch (e) {
}
});
$suggestions.on('dblclick', function() {
try { if (typeof dmzx_chatbot === 'undefined' || parseInt(dmzx_chatbot.popular_enabled,10) === 1) loadSuggestions($suggestions, route, true); } catch (e) {}
});
});
}
if (typeof require === 'function') {
try {
require(['jquery'], initChatbot);
} catch (e) {
if (window.jQuery) {
initChatbot(window.jQuery);
} else {
var _pollCount = 0;
var _poll = setInterval(function() {
_pollCount++;
if (window.jQuery) {
clearInterval(_poll);
initChatbot(window.jQuery);
} else if (_pollCount > 50) {
clearInterval(_poll);
}
}, 100);
}
}
} else if (window.jQuery) {
initChatbot(window.jQuery);
} else {
var pollCount = 0;
var pollInterval = setInterval(function() {
pollCount++;
if (window.jQuery) {
clearInterval(pollInterval);
initChatbot(window.jQuery);
} else if (pollCount > 50) {
clearInterval(pollInterval);
}
}, 100);
}
})();