adaptorex
Version:
Connect all your live interactive storytelling devices and software
189 lines (165 loc) • 5.84 kB
JavaScript
let base_url = window.location.origin
const urlParams = new URLSearchParams(window.location.search)
let game = urlParams.get('game')
let plugin = urlParams.get('plugin') || "socketio"
let plugin_namespace = urlParams.get('namespace')
// let session = urlParams.get('session') // The session specific socket is deprecated
let level = urlParams.get('level')
let log_level = urlParams.get('log')
let user = urlParams.get('user')
let password = urlParams.get('password')
let headers = {}
if( user && password ) {
headers.auth = {token: btoa(`${user}:${password}`)}
}
let namespaces = {
adaptor: io(base_url)
}
if(log_level) {
namespaces.log_socket = io(`${base_url}/log/${log_level}`, headers)
}
if(game) {
namespaces.game_socket = io(`${base_url}/game/${game}`, headers)
namespaces.sessions_socket = io(`${base_url}/game/${game}/live/sessions`, headers)
namespaces.items_socket = io(`${base_url}/game/${game}/live/items`, headers)
/* The session socket is deprecated
if(session) {
namespaces.session_socket = io(`${base_url}/game/${game}/session/${session}`)
}
*/
if(level) {
namespaces.level_socket = io(`${base_url}/game/${game}/level/${level}`, headers)
}
if(plugin_namespace) {
namespaces.plugin_socket = io(`${base_url}/${game}/${plugin}/${plugin_namespace}`, headers)
}
} else {
log(`⚠️ Add the game parameter to the url to connect to a game. For example:`, `${window.location.href}?game=TestGame`)
}
function log(line, details) {
let log_el = document.getElementById("log")
let log_item = document.createElement("div")
log_item.style.padding = "5px"
let date = new Date()
let date_str = `${date.toLocaleTimeString()}`
log_item.innerHTML = `${date_str} ${line}`
console.log(line)
if(typeof details === "object") {
const size = new TextEncoder().encode(JSON.stringify(details)).length
const kiloBytes = size / 1024;
const megaBytes = kiloBytes / 1024;
log_item.innerHTML += `<details><summary>${typeof details} (${kiloBytes.toFixed(2)} KB / ${megaBytes.toFixed(2)} MB)</summary><pre>${JSON.stringify(details, null, 2)}</pre></details>`
console.log(details)
} else if(details) {
log_item.innerHTML += `<br>${details}`
console.log(details)
}
log_el.insertBefore(log_item, log_el.firstChild)
log_el.scrollTop = log_el.scrollHeight
}
function createMessageInput() {
const container = document.getElementById("send");
const namespaceSelect = document.createElement("select");
Object.keys(namespaces).slice().reverse().forEach(namespace => {
const title = namespace.replace(/_socket$/, '');
const option = document.createElement("option");
option.value = namespace;
option.textContent = title;
namespaceSelect.appendChild(option);
});
const topicInput = document.createElement("input");
topicInput.type = "text";
topicInput.placeholder = "topic";
const input = document.createElement("input");
input.type = "text";
input.placeholder = "message";
const sendButton = document.createElement("button");
sendButton.textContent = "Send";
sendButton.addEventListener("click", () => {
const namespace = namespaceSelect.value;
const topic = topicInput.value.trim() || "";
let message = input.value.trim();
if (topic) {
if(message.startsWith("{") || message.startsWith("[")) {
message = JSON.parse(message)
}
namespaces[namespace].emit(topic, message, (response) => {
log(`↩️ Response on topic <b>${topic}</b> in ${namespace}:`, response);
});
// input.value = ""; // Clear input field after sending
}
});
container.appendChild(namespaceSelect);
container.appendChild(topicInput);
container.appendChild(input);
container.appendChild(sendButton);
}
function onConnected() {
Object.keys(namespaces).forEach(namespace => {
const title = namespace.replace(/_socket$/, '');
log(`⏳ <b>${title}</b> socket trying to connect to ${base_url}<b>${namespaces[namespace].nsp}</b>`)
namespaces[namespace].on('connect', data => {
log(`✅ <b>${title}</b> socket connected</b>`)
})
})
}
function onDisconnected() {
Object.keys(namespaces).forEach(namespace => {
const title = namespace.replace(/_socket$/, '');
namespaces[namespace].on('disconnect', data => {
log(`🚫 <b>${title}</b> socket is disconnected</b>`)
})
})
}
function onMessage() {
Object.keys(namespaces).forEach(namespace => {
const title = namespace.replace(/_socket$/, '');
namespaces[namespace].onAny((topic, msg) => {
log(`💬 incoming message from <b>${title}</b> socket on topic <b>${topic}</b>:`, msg)
})
})
}
log(`🦖 connecting to ${base_url} on ${identifyBrowser()}`, urlParams.entries().toArray())
onConnected()
onDisconnected()
onMessage()
createMessageInput();
/**
* use userAgent to find out what Browser is in use (not reliable)
*
* see https://code-boxx.com/detect-browser-with-javascript/
*/
function identifyBrowser() {
// CHROME
if (navigator.userAgent.indexOf("Chrome") != -1 ) {
return("Google Chrome");
}
// FIREFOX
else if (navigator.userAgent.indexOf("Firefox") != -1 ) {
return("Mozilla Firefox");
}
// INTERNET EXPLORER
else if (navigator.userAgent.indexOf("MSIE") != -1 ) {
return("Internet Explorer");
}
// EDGE
else if (navigator.userAgent.indexOf("Edge") != -1 ) {
return("Edge Browser");
}
// SAFARI
else if (navigator.userAgent.indexOf("Safari") != -1 ) {
return("Safari");
}
// OPERA
else if (navigator.userAgent.indexOf("Opera") != -1 ) {
return("Opera");
}
// YANDEX BROWSER
else if (navigator.userAgent.indexOf("YaBrowser") != -1 ) {
return("YaBrowser");
}
// OTHERS
else {
return("Unknown");
}
}