User:Jono Bean/common.js: Difference between revisions
From DQWiki
Jump to navigationJump to search
mNo edit summary |
mNo edit summary |
||
| Line 1: | Line 1: | ||
/* Lorekeeper Standalone Terminal | /* Lorekeeper Standalone Terminal v4 - Premium Streaming */ | ||
(function() { | (function() { | ||
var checkCount = 0; | var checkCount = 0; | ||
var initTimer = setInterval(function() { | var initTimer = setInterval(function() { | ||
if (document.body) { | if (document.body) { | ||
clearInterval(initTimer); | clearInterval(initTimer); | ||
setupLore(); | setupLore(); | ||
} | } | ||
if (checkCount > 100) clearInterval(initTimer); | if (checkCount++ > 100) clearInterval(initTimer); | ||
}, 100); | }, 100); | ||
| Line 14: | Line 13: | ||
if (document.getElementById('lore-terminal-btn')) return; | if (document.getElementById('lore-terminal-btn')) return; | ||
// 1. Create Floating Button | // 1. Inject Styles | ||
var style = document.createElement('style'); | |||
style.innerHTML = | |||
'#lore-chat::-webkit-scrollbar { width: 4px; }' + | |||
'#lore-chat::-webkit-scrollbar-thumb { background: #8b5cf6; border-radius: 10px; }' + | |||
'.lore-msg { margin-bottom: 15px; padding: 12px 16px; border-radius: 15px; font-size: 14px; position: relative; animation: fadeIn 0.3s ease; }' + | |||
'.lore-user { background: #8b5cf6; color: #fff; align-self: flex-end; margin-left: 40px; border-bottom-right-radius: 4px; }' + | |||
'.lore-ai { background: #1a1a24; color: #e2e8f0; align-self: flex-start; margin-right: 40px; border-left: 4px solid #8b5cf6; border-bottom-left-radius: 4px; }' + | |||
'@keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }'; | |||
document.head.appendChild(style); | |||
// 2. Create Floating Button | |||
var btn = document.createElement('div'); | var btn = document.createElement('div'); | ||
btn.id = 'lore-terminal-btn'; | btn.id = 'lore-terminal-btn'; | ||
btn.innerHTML = ' | btn.innerHTML = '?'; | ||
btn.setAttribute('style', 'position:fixed !important; bottom: | btn.setAttribute('style', 'position:fixed !important; bottom:25px !important; right:25px !important; width:65px !important; height:65px !important; background:linear-gradient(135deg, #8b5cf6, #6d28d9) !important; border-radius:50% !important; display:flex !important; align-items:center !important; justify-content:center !important; font-size:32px !important; cursor:pointer !important; box-shadow:0 10px 30px rgba(139,92,246,0.5) !important; z-index:999999 !important; border:2px solid rgba(255,255,255,0.4) !important; transition:0.3s ease;'); | ||
// | // 3. Create Chat Box | ||
var box = document.createElement('div'); | var box = document.createElement('div'); | ||
box.id = 'lore-terminal-box'; | box.id = 'lore-terminal-box'; | ||
box.setAttribute('style', 'position:fixed !important; bottom: | box.setAttribute('style', 'position:fixed !important; bottom:105px !important; right:25px !important; width:420px !important; height:650px !important; background:rgba(10,10,15,0.98) !important; backdrop-filter:blur(15px); border:1px solid rgba(139,92,246,0.4) !important; border-radius:30px !important; display:none; flex-direction:column !important; box-shadow:0 30px 60px rgba(0,0,0,0.8) !important; z-index:999999 !important; color:#fff !important; font-family:system-ui, sans-serif !important; overflow:hidden;'); | ||
box.innerHTML = | box.innerHTML = | ||
'<div style="padding: | '<div style="padding:20px; border-bottom:1px solid rgba(139,92,246,0.2); background:rgba(139,92,246,0.1); display:flex; justify-content:space-between; align-items:center;">' + | ||
'<b style="color:#a78bfa">Lorekeeper | '<div><b style="color:#a78bfa; font-size:16px;">The Lorekeeper</b><br><small style="opacity:0.6; font-size:10px; text-transform:uppercase; letter-spacing:1px;">Royal Archives</small></div>' + | ||
'<span id="lore-close" style="cursor:pointer; | '<span id="lore-close" style="cursor:pointer; font-size:24px; opacity:0.5;">×</span>' + | ||
'</div>' + | '</div>' + | ||
'<div id="lore-chat" style="flex:1; overflow-y:auto; padding: | '<div id="lore-chat" style="flex:1; overflow-y:auto; padding:20px; display:flex; flex-direction:column; gap:5px;">' + | ||
'<div | '<div class="lore-msg lore-ai">Greetings, Traveler. I am the Scribe of the Western Kingdom. What knowledge do you seek from the archives?</div>' + | ||
'</div>' + | '</div>' + | ||
'<div style="padding: | '<div style="padding:20px; background:rgba(0,0,0,0.4); border-top:1px solid rgba(255,255,255,0.05); display:flex; gap:10px;">' + | ||
'<input id="lore-input" | '<input id="lore-input" placeholder="Inquire about the world..." style="flex:1; background:rgba(255,255,255,0.05); border:1px solid rgba(139,92,246,0.3); padding:12px 18px; border-radius:15px; color:#fff; outline:none; font-size:14px;">' + | ||
'<button id="lore-send" style=" | '<button id="lore-send" style="background:#8b5cf6; color:#fff; border:none; width:50px; height:45px; border-radius:12px; cursor:pointer; font-weight:bold; font-size:18px;">→</button>' + | ||
'</div>'; | '</div>'; | ||
| Line 41: | Line 51: | ||
document.body.appendChild(box); | document.body.appendChild(box); | ||
var input = document.getElementById('lore-input'); | |||
btn.onclick = function() { | var chat = document.getElementById('lore-chat'); | ||
var convId = 'anon-' + Math.random().toString(36).substring(7); | |||
btn.onclick = function() { box.style.display = (box.style.display == 'none') ? 'flex' : 'none'; }; | |||
document.getElementById('lore-close').onclick = function() { box.style.display = 'none'; }; | document.getElementById('lore-close').onclick = function() { box.style.display = 'none'; }; | ||
var | function addMessage(text, isAi) { | ||
var m = document.createElement('div'); | |||
m.className = 'lore-msg ' + (isAi ? 'lore-ai' : 'lore-user'); | |||
m.innerText = text; | |||
chat.appendChild(m); | |||
chat.scrollTop = chat.scrollHeight; | |||
return m; | |||
} | |||
async function handleAsk() { | |||
var | var q = input.value.trim(); | ||
if (! | if (!q) return; | ||
input.value = ''; | input.value = ''; | ||
addMessage(q, false); | |||
var | var aMsg = addMessage('', true); | ||
aMsg.innerHTML = '<i style="opacity:0.5">Consulting the Scribe Notes...</i>'; | |||
try { | |||
const response = await fetch('https://npc-forge--npc-forge-qh4gc.asia-southeast1.hosted.app/api/lore/stream', { | |||
method: 'POST', | |||
headers: { 'Content-Type': 'application/json' }, | |||
body: JSON.stringify({ question: q, conversationId: convId }) | |||
}); | |||
const reader = response.body.getReader(); | |||
const decoder = new TextDecoder(); | |||
aMsg.innerText = ''; | |||
var content = ''; | |||
while (true) { | |||
if ( | const { done, value } = await reader.read(); | ||
if (done) break; | |||
content += decoder.decode(value); | |||
aMsg.innerText = content; | |||
chat.scrollTop = chat.scrollHeight; | |||
} | } | ||
}; | } catch (e) { aMsg.innerText = "The archives are sealed for now. Please try again later."; } | ||
} | |||
document.getElementById('lore-send').onclick = handleAsk; | |||
input.onkeydown = function(e) { if (e.key === 'Enter') handleAsk(); }; | |||
} | } | ||
})(); | })(); | ||
Revision as of 08:00, 25 February 2026
/* Lorekeeper Standalone Terminal v4 - Premium Streaming */
(function() {
var checkCount = 0;
var initTimer = setInterval(function() {
if (document.body) {
clearInterval(initTimer);
setupLore();
}
if (checkCount++ > 100) clearInterval(initTimer);
}, 100);
function setupLore() {
if (document.getElementById('lore-terminal-btn')) return;
// 1. Inject Styles
var style = document.createElement('style');
style.innerHTML =
'#lore-chat::-webkit-scrollbar { width: 4px; }' +
'#lore-chat::-webkit-scrollbar-thumb { background: #8b5cf6; border-radius: 10px; }' +
'.lore-msg { margin-bottom: 15px; padding: 12px 16px; border-radius: 15px; font-size: 14px; position: relative; animation: fadeIn 0.3s ease; }' +
'.lore-user { background: #8b5cf6; color: #fff; align-self: flex-end; margin-left: 40px; border-bottom-right-radius: 4px; }' +
'.lore-ai { background: #1a1a24; color: #e2e8f0; align-self: flex-start; margin-right: 40px; border-left: 4px solid #8b5cf6; border-bottom-left-radius: 4px; }' +
'@keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }';
document.head.appendChild(style);
// 2. Create Floating Button
var btn = document.createElement('div');
btn.id = 'lore-terminal-btn';
btn.innerHTML = '?';
btn.setAttribute('style', 'position:fixed !important; bottom:25px !important; right:25px !important; width:65px !important; height:65px !important; background:linear-gradient(135deg, #8b5cf6, #6d28d9) !important; border-radius:50% !important; display:flex !important; align-items:center !important; justify-content:center !important; font-size:32px !important; cursor:pointer !important; box-shadow:0 10px 30px rgba(139,92,246,0.5) !important; z-index:999999 !important; border:2px solid rgba(255,255,255,0.4) !important; transition:0.3s ease;');
// 3. Create Chat Box
var box = document.createElement('div');
box.id = 'lore-terminal-box';
box.setAttribute('style', 'position:fixed !important; bottom:105px !important; right:25px !important; width:420px !important; height:650px !important; background:rgba(10,10,15,0.98) !important; backdrop-filter:blur(15px); border:1px solid rgba(139,92,246,0.4) !important; border-radius:30px !important; display:none; flex-direction:column !important; box-shadow:0 30px 60px rgba(0,0,0,0.8) !important; z-index:999999 !important; color:#fff !important; font-family:system-ui, sans-serif !important; overflow:hidden;');
box.innerHTML =
'<div style="padding:20px; border-bottom:1px solid rgba(139,92,246,0.2); background:rgba(139,92,246,0.1); display:flex; justify-content:space-between; align-items:center;">' +
'<div><b style="color:#a78bfa; font-size:16px;">The Lorekeeper</b><br><small style="opacity:0.6; font-size:10px; text-transform:uppercase; letter-spacing:1px;">Royal Archives</small></div>' +
'<span id="lore-close" style="cursor:pointer; font-size:24px; opacity:0.5;">×</span>' +
'</div>' +
'<div id="lore-chat" style="flex:1; overflow-y:auto; padding:20px; display:flex; flex-direction:column; gap:5px;">' +
'<div class="lore-msg lore-ai">Greetings, Traveler. I am the Scribe of the Western Kingdom. What knowledge do you seek from the archives?</div>' +
'</div>' +
'<div style="padding:20px; background:rgba(0,0,0,0.4); border-top:1px solid rgba(255,255,255,0.05); display:flex; gap:10px;">' +
'<input id="lore-input" placeholder="Inquire about the world..." style="flex:1; background:rgba(255,255,255,0.05); border:1px solid rgba(139,92,246,0.3); padding:12px 18px; border-radius:15px; color:#fff; outline:none; font-size:14px;">' +
'<button id="lore-send" style="background:#8b5cf6; color:#fff; border:none; width:50px; height:45px; border-radius:12px; cursor:pointer; font-weight:bold; font-size:18px;">→</button>' +
'</div>';
document.body.appendChild(btn);
document.body.appendChild(box);
var input = document.getElementById('lore-input');
var chat = document.getElementById('lore-chat');
var convId = 'anon-' + Math.random().toString(36).substring(7);
btn.onclick = function() { box.style.display = (box.style.display == 'none') ? 'flex' : 'none'; };
document.getElementById('lore-close').onclick = function() { box.style.display = 'none'; };
function addMessage(text, isAi) {
var m = document.createElement('div');
m.className = 'lore-msg ' + (isAi ? 'lore-ai' : 'lore-user');
m.innerText = text;
chat.appendChild(m);
chat.scrollTop = chat.scrollHeight;
return m;
}
async function handleAsk() {
var q = input.value.trim();
if (!q) return;
input.value = '';
addMessage(q, false);
var aMsg = addMessage('', true);
aMsg.innerHTML = '<i style="opacity:0.5">Consulting the Scribe Notes...</i>';
try {
const response = await fetch('https://npc-forge--npc-forge-qh4gc.asia-southeast1.hosted.app/api/lore/stream', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ question: q, conversationId: convId })
});
const reader = response.body.getReader();
const decoder = new TextDecoder();
aMsg.innerText = '';
var content = '';
while (true) {
const { done, value } = await reader.read();
if (done) break;
content += decoder.decode(value);
aMsg.innerText = content;
chat.scrollTop = chat.scrollHeight;
}
} catch (e) { aMsg.innerText = "The archives are sealed for now. Please try again later."; }
}
document.getElementById('lore-send').onclick = handleAsk;
input.onkeydown = function(e) { if (e.key === 'Enter') handleAsk(); };
}
})();