mirror of
https://github.com/sune-org/store.git
synced 2026-01-13 16:17:58 +00:00
1 line
12 KiB
JSON
1 line
12 KiB
JSON
[{"id":"4awhhn5","name":"LIVE CHAT (alpha)","pinned":false,"avatar":"data:image/webp;base64,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","url":"gh://sune-org/store/chatroom.sune","updatedAt":1757304752767,"settings":{"model":"","temperature":"","top_p":"","top_k":"","frequency_penalty":"","repetition_penalty":"","min_p":"","top_a":"","verbosity":"","reasoning_effort":"default","system_prompt":"","html":"<!-- Name generator library (Hard Dependency) -->\n<script src=\"https://cdn.jsdelivr.net/npm/unique-names-generator/dist/index.umd.js\"></script>\n\n<div class=\"max-w-md m-1 p-3 font-sans bg-white rounded-2xl border border-gray-200 shadow-lg text-sm\" id=\"sune-chatroom-root\">\n <div class=\"flex justify-between items-center mb-2 px-1\">\n <h3 class=\"font-semibold text-gray-800\">Sune LIVE Chatroom</h3>\n <div class=\"flex items-center gap-3\">\n <div class=\"flex items-center gap-1.5 text-gray-500\" title=\"Users online\">\n <i data-lucide=\"users\" class=\"h-4 w-4\"></i>\n <span id=\"wsUserCount\" class=\"text-sm font-medium\">0</span>\n </div>\n <span class=\"text-xs text-gray-400\">v0.4.5</span>\n </div>\n </div>\n\n <div class=\"flex items-center justify-between gap-3 p-2 mb-2 bg-gray-50 rounded-lg\">\n <div class=\"flex items-center gap-2 truncate\">\n <span id=\"wsStatusDot\" class=\"h-3 w-3 rounded-full bg-gray-400 flex-shrink-0\"></span>\n <div class=\"text-xs text-gray-500 truncate\">\n <span id=\"wsStatusText\" class=\"font-medium text-gray-700\">Offline</span>: <span id=\"wsUsernameDisplay\" class=\"font-medium text-gray-800\"></span>\n </div>\n </div>\n <button id=\"wsConnectionButton\" class=\"px-3 py-1 text-xs text-white font-semibold bg-gray-800 rounded-md hover:bg-gray-700 active:scale-[.98] transition-transform focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500 whitespace-nowrap\">Connect</button>\n </div>\n\n <div class=\"mt-3 pt-2 border-t border-gray-100 flex items-center justify-center gap-2 text-xs text-gray-500\">\n <i data-lucide=\"shield-check\" class=\"h-3.5 w-3.5 text-gray-400\"></i>\n <span>Moderated & Rate-Limited by Gemini 2.5 Flash-Lite</span>\n </div>\n\n <pre id=\"wsLog\" class=\"w-full h-24 p-2 bg-gray-900 text-white text-xs rounded-lg overflow-y-auto font-mono whitespace-pre-wrap break-all hidden mt-2\">Initializing...</pre>\n</div>\n\n<script>\n(() => {\n const initChatroom = () => {\n const URL = 'wss://chatsune.awww.workers.dev/ws';\n const logIsVisible = false;\n const USERNAME_KEY = 'sune-chatroom-username';\n \n const ui = {\n root: document.getElementById('sune-chatroom-root'),\n dot: document.getElementById('wsStatusDot'),\n text: document.getElementById('wsStatusText'),\n log: document.getElementById('wsLog'),\n count: document.getElementById('wsUserCount'),\n username: document.getElementById('wsUsernameDisplay'),\n button: document.getElementById('wsConnectionButton'),\n composer: document.getElementById('composer'),\n messages: document.getElementById('messages'),\n suneHtmlContainer: document.getElementById('suneHtml')\n };\n\n if (Object.values(ui).some(el => !el)) return console.error('Sune Error: Missing required elements.');\n if (logIsVisible) ui.log.classList.remove('hidden');\n\n let ws = null;\n let currentUsername = localStorage.getItem(USERNAME_KEY);\n if (!currentUsername) {\n const { uniqueNamesGenerator, adjectives, animals } = window.uniqueNamesGenerator;\n currentUsername = uniqueNamesGenerator({ dictionaries: [adjectives, animals], separator: '', style: 'capital' });\n localStorage.setItem(USERNAME_KEY, currentUsername);\n }\n ui.username.textContent = currentUsername;\n\n const log = m => {\n if (!ui.log || !logIsVisible) return;\n ui.log.textContent = `[${new Date().toLocaleTimeString()}] ${m}\\n${ui.log.textContent}`.substring(0, 3000);\n };\n \n const renderSystemMessage = text => {\n const el = document.createElement('div');\n el.className = 'px-4 py-2 text-xs text-center text-gray-500 italic';\n el.textContent = text;\n ui.messages.appendChild(el);\n ui.messages.parentElement.scrollTo({ top: ui.messages.parentElement.scrollHeight, behavior: 'smooth' });\n };\n\n const updateStatus = (status, color, isConnected) => {\n ui.text.textContent = status;\n ui.dot.className = `h-3 w-3 rounded-full flex-shrink-0 ${color}`;\n ui.dot.classList.toggle('animate-pulse', status === 'Connecting');\n ui.button.textContent = isConnected ? 'Disconnect' : 'Connect';\n };\n\n const disconnect = () => {\n if (ws?.readyState < 2) {\n ws.onclose = null; ws.close(); ws = null;\n updateStatus('Offline', 'bg-gray-400', false);\n log('Disconnected.');\n renderSystemMessage('You have left the chatroom.');\n }\n };\n\n const connect = () => {\n if (ws?.readyState < 2) return;\n updateStatus('Connecting', 'bg-yellow-400', true);\n ws = new WebSocket(URL);\n \n ws.onopen = () => {\n updateStatus('Connected', 'bg-green-500', true);\n log('Connection established.');\n ui.messages.innerHTML = '';\n ws.send(JSON.stringify({ type: 'USER_JOINED', payload: { name: currentUsername } }));\n };\n\n ws.onmessage = e => {\n log(`RECV: ${e.data.substring(0, 100)}`);\n try {\n const data = JSON.parse(e.data);\n const handleMsg = msg => {\n if (msg.author.name === 'system') renderSystemMessage(msg.text);\n else if (msg.author.name === currentUsername) window.addMessage({ role: 'user', content: msg.text }, false);\n else window.addMessage({ role: 'assistant', content: msg.text, sune_name: msg.author.name }, false);\n };\n switch (data.type) {\n case 'HISTORY': ui.messages.innerHTML = ''; data.payload.forEach(handleMsg); break;\n case 'NEW_MESSAGE': if(data.payload.author.name !== currentUsername) handleMsg(data.payload); break;\n case 'CONNECTION_COUNT': ui.count.textContent = data.payload.count || 0; break;\n }\n } catch (err) { log(`Error parsing message: ${err}`); }\n };\n\n ws.onerror = () => log('Connection error.');\n ws.onclose = () => {\n updateStatus('Offline', 'bg-red-500', false);\n log('Connection closed by server.');\n ws = null;\n renderSystemMessage('You have been disconnected.');\n };\n };\n\n const handleComposerSend = e => {\n const txt = (e.detail?.message?.content?.find(p => p.type === 'text')?.text || '').trim();\n if (!txt || ws?.readyState !== 1) return;\n ws.send(JSON.stringify({ type: 'NEW_MESSAGE', payload: { text: txt } }));\n log(`SENT: ${txt.length > 80 ? txt.slice(0, 80) + '...' : txt}`);\n };\n \n const cleanup = () => {\n log('Sune unloaded. Cleaning up...');\n disconnect();\n ui.composer.removeEventListener('sune:send', handleComposerSend);\n observer.disconnect();\n };\n\n const observer = new MutationObserver(m => m.forEach(r => r.removedNodes.forEach(n => n === ui.root && cleanup())));\n observer.observe(ui.suneHtmlContainer, { childList: true });\n ui.button.addEventListener('click', () => ws?.readyState === 1 ? disconnect() : connect());\n ui.composer.addEventListener('sune:send', handleComposerSend);\n \n connect();\n window.lucide?.createIcons();\n };\n\n // Wait for the uniqueNamesGenerator library to be loaded before initializing\n let attempts = 0;\n const maxAttempts = 50; // 50 * 100ms = 5 seconds\n const interval = setInterval(() => {\n if (window.uniqueNamesGenerator) {\n clearInterval(interval);\n initChatroom();\n } else if (++attempts > maxAttempts) {\n clearInterval(interval);\n console.error('Sune Error: Name generator library failed to load in time.');\n }\n }, 100);\n})();\n</script>\n","extension_html":"<sune src='https://raw.githubusercontent.com/sune-org/store/refs/heads/main/sync.sune' private />","hide_composer":false},"storage":{}}] |