function displayMessage(data) { const messages = document.getElementById("window-messages"); const message = document.createElement("p"); message.classList.add("message"); if ("nick" in data && data.nick.length > 0) { const nickElement = document.createElement("span"); nickElement.classList.add("nick"); nickElement.textContent = `${data.nick}: `; if ("color" in data.tags) { nickElement.style.color = data.tags["color"]; } message.append(nickElement); } const messageContent = document.createElement("span"); messageContent.classList.add("content"); messageContent.textContent = data.params[1]; message.append(messageContent); messages.append(message); } function displaySystemMessage(channelName, message, nick = "System") { displayMessage({ "nick": nick, "prefix": nick, "command": "PRIVMSG", "params": [channelName, message], "tags": {} }); } class TwitchIRCClient { constructor (host, nick, pass) { this.joinedChannels = []; this.socket = null; this.host = host; this.nick = nick; this.pass = pass; } connect() { this.socket = new WebSocket(this.host); this.socket.addEventListener("open", () => { this.socket.send(`NICK ${this.nick}`); this.socket.send(`PASS ${this.pass}`); this.socket.send(`CAP REQ :twitch.tv/tags twitch.tv/membership`); }); this.socket.addEventListener("message", (e) => { const lines = e.data.split("\r\n"); for (const line of lines) { if (line.trim().length == 0) { continue; } if (line.includes("001")) { for (const c of this.joinedChannels) { this.join(c); } displaySystemMessage("*", "Connected!"); } displaySystemMessage("forsen", line, "Message"); } }); this.socket.addEventListener("error", (e) => { console.error(e); }); this.socket.addEventListener("close", (e) => { for (const c of this.joinedChannels) { displaySystemMessage(c, `Disconnected! Reason: ${e.reason}`); displaySystemMessage(c, "Reconnecting in 10 seconds..."); } setTimeout(() => this.connect(), 10000); }); } say(channelName, message) { this.socket.send(`PRIVMSG #${channelName} :${message}`); } join(channelName) { if (this.socket != null && this.socket.readyState == this.socket.OPEN) { this.socket.send(`JOIN #${channelName}`); } if (!this.joinedChannels.includes(channelName)) { this.joinedChannels.push(channelName); } } }