adaptorex
Version:
Connect all your live interactive storytelling devices and software
211 lines (188 loc) • 5.87 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"
}
}