var Connect = require('connect'); var wss = require('websocket').server; var wsc = require('websocket').client; var irc = require('irc-js'); var frontend, sendToCensor; /* * Nedap backend connection */ /* TODO: url */ var nedap; function connectNedap() { var nedapClient = new wsc(); nedapClient.on('connect', function(conn) { console.log('NEDAP opened'); nedap = conn; nedap.sendUTF('nedap-RuJejdymmesAktiOdyitEdivRiectij'); nedap.on('close', function() { console.log('NEDAP closed'); connectNedap(); }); nedap.on('error', function(e) { console.log('NEDAP error: ' + e.message); connectNedap(); }); nedap.on('message', function(wsmsg) { try { var msg = JSON.parse(wsmsg.utf8Data); console.log({ fromNedap: msg }); if (msg.gif) { sendToCensor(msg); } else sendToFrontend({ nedap: msg }); } catch (e) { console.error(e.stack); } }); }); nedapClient.on('connectFailed', function(e) { console.error(e.stack || e); setTimeout(connectNedap, 1000); }); nedapClient.connect('ws://nedap.c3d2.de:2342/', 'quiz-nedap'); } connectNedap(); /* * IRC client */ var IRC_SERVER = 'irc.hackint.eu'; var IRC_CHAN = '#pentanews'; function connectChat() { var chat = new irc({ server: IRC_SERVER, encoding: 'utf-8', nick: '[Ceiling]Katze' }); chat.connect(); chat.addListener('376', function() { if (!chat) return; chat.join(IRC_CHAN); }); chat.addListener('366', function(msg) { if (!chat) return; if (msg.params[1] === IRC_CHAN) { console.log('Successfully joined ' + IRC_CHAN); pushIrcInfo(); } }); chat.addListener('privmsg', function(msg) { if (!chat) return; console.log({PRIVMSG:msg}); var nick = msg.person.nick; var channel = msg.params[0]; var text = msg.params[1]; var sText = "", i; for(i = 0; i < text.length; i++) { if (text.charCodeAt(i) >= 32) sText += text[i]; } if (nick && channel === IRC_CHAN && sText && frontend) { sendToFrontend({ irc: { nick: nick, text: sText } }); } }); chat.addListener('disconnected', function() { if (!chat) return; chat = undefined; console.error('Chat disconnected!'); window.setTimeout(connectChat, 1000); }); chat.on('error', connectChat); } connectChat(); function pushIrcInfo() { sendToFrontend({ irc: { server: IRC_SERVER, channel: IRC_CHAN } }); } /* * Buttons */ var buzz = new (require('./buzz_iface/node_lib/buzz').Buzz)('/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_A400gqnA-if00-port0'); buzz.on('button', function(key) { console.log({button:key}); sendToFrontend({ buzzer: key }); }); function setAllLEDs(brightness) { for(var player = 0; player < 3; player++) buzz.set_led(player, brightness); } var MORSE_ALPHABET = { "A": ". -", "B": "- . . .", "C": "- . - .", "D": "- . .", "E": ".", "F": ". . - .", "G": "- - .", "H": ". . . .", "I": ". .", "J": ". - - -", "K": "- . -", "L": ". - . .", "M": "- -", "N": "- .", "O": "- - -", "P": ". - - .", "Q": "- - . -", "R": ". - .", "S": ". . .", "T": "-", "U": ". . -", "V": ". . . -", "W": ". - -", "X": "- . . -", "Y": "- . - -", "Z": "- - . .", "0": "- - - - -", "1": ". - - - -", "2": ". . - - -", "3": ". . . - -", "4": ". . . . -", "5": ". . . . .", "6": "- . . . .", "7": "- - . . .", "8": "- - - . .", "9": "- - - - .", "À": ". - - . -", "Å": ". - - . -", "Ä": ". - . -", "È": ". - . . -", "É": ". . - . .", "Ö": "- - - .", "Ü": ". . - -", "ß": ". . . - - . .", "CH": "- - - -", "Ñ": "- - . - -", ".": ". - . - . -", ",": "- - . . - -", ":": "- - - . . .", ";": "- . - . - .", "?": ". . - - . .", "-": "- . . . . -", "_": ". . - - . -", "(": "- . - - .", ")": "- . - - . -", "'": ". - - - - .", "=": "- . . . -", "+": ". - . - .", "/": "- . . - .", "@": ". - - . - ." }; var DIT_LENGTH = 100; var DAH_LENGTH = 3 * DIT_LENGTH; var PAUSE_LENGTH = DIT_LENGTH; var CHARACTER_PAUSE_LENGTH = 3; var WORD_PAUSE_LENGTH = 7; function morse(text) { /* Assemble sequence */ var sequence = ''; for(var i = 0; i < text.length; i++) { var symbols; if (text[i] === " ") for(var j = 0; j < WORD_PAUSE_LENGTH; j++) sequence += " "; else if ((symbols = MORSE_ALPHABET[text[i].toLocaleUpperCase()])) { sequence += symbols; for(j = 0; j < CHARACTER_PAUSE_LENGTH; j++) sequence += " "; } } sequence += " "; /* clear led at end */ console.log("morse", text, sequence); /* Play */ var playSequence = function() { console.log("playSequence", sequence[0]) var delay; switch(sequence[0]) { case ".": setAllLEDs(1); delay = DIT_LENGTH; break; case "-": setAllLEDs(1); delay = DAH_LENGTH; break; case " ": setAllLEDs(0); delay = PAUSE_LENGTH; break; } sequence = sequence.substr(1); if (sequence && delay) setTimeout(playSequence, delay); }; playSequence(); } /* * Web server */ var server = Connect.createServer( Connect.logger(), Connect.bodyParser(), Connect.static(__dirname, { maxAge: 1000 }), Connect.errorHandler({ dumpExceptions: true, showStack: true }) ); /* * WebSocket server */ var gamestate = {}; new wss({ httpServer: server }).on('request', function(req) { var conn = req.accept(null, req.origin); if (req.requestedProtocols && req.requestedProtocols.indexOf('censor') >= 0) { /* Censor frontend */ sendToCensor = function(obj) { conn.sendUTF(JSON.stringify(obj)); }; conn.on('message', function(wsmsg) { console.log(wsmsg); try { var msg = JSON.parse(wsmsg.utf8Data); if (msg.gif) sendToFrontend(msg); } catch (e) { console.error(e.stack); } }); var reset = function() { sendToCensor = function() { }; }; conn.on('close', reset); conn.on('error', reset); } else { /* Game frontend */ frontend = conn; conn.on('message', function(wsmsg) { console.log(wsmsg); try { var msg = JSON.parse(wsmsg.utf8Data); if (msg.nedap) { console.log({ toNedap: msg.nedap }); if (nedap) nedap.sendUTF(JSON.stringify(msg.nedap)); } else if (msg.irc === "activate") { pushIrcInfo(); } else if (msg.buzzerLED) { buzz.set_led(msg.buzzerLED[0], msg.buzzerLED[1]); } else if (msg.morse) { morse(msg.morse); } else if (msg.gamestate) { gamestate = msg.gamestate; } else if (msg.requestGamestate) { conn.sendUTF(JSON.stringify({ gamestate: gamestate })); } else if (msg.tweet) { tweet(msg.tweet); } } catch (e) { console.error(e.stack); } }); var reset = function() { frontend = null; }; conn.on('close', reset); conn.on('error', reset); } }); function sendToFrontend(obj) { if (!frontend) return; frontend.sendUTF(JSON.stringify(obj)); } server.listen(8081, "::1"); morse("c3d2"); var twit = new (require('twitter'))({ consumer_key: 'sNWvbrAz11vVMwppORKA', consumer_secret: 'MzAhGlzz3qWUIxse8vcHc3zqkPOBuWKJgjazGkeOc', access_token_key: '108923470-KVfqQJc8oIhAYZj2RhL7ggrR5Y9eMGjTQD79Db12', access_token_secret: 'uQ9ljbh5L3NGEuHhKSrrnQv3KmL59d0nS2pJBjiqgL8' }); function tweet(text) { // FIXME: remove next line for production! return; twit.updateStatus(text, function(res) { if (res.statusCode && res.statusCode >= 400) { /* Failure */ var m = text.match(/^(.+) /); if (m) tweet(m[1]); } }); }