commit
						1b86e1feb6
					
				
					 12 changed files with 209 additions and 19 deletions
				
			
		
							
								
								
									
										
											BIN
										
									
								
								public/gfx/icon_128x128.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								public/gfx/icon_128x128.png
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 8.7 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								public/gfx/icon_128x128_error.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								public/gfx/icon_128x128_error.png
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 8.2 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								public/gfx/icon_128x128_info.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								public/gfx/icon_128x128_info.png
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 7.8 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								public/gfx/icon_16x16.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								public/gfx/icon_16x16.png
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 628 B  | 
							
								
								
									
										
											BIN
										
									
								
								public/gfx/icon_32x32.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								public/gfx/icon_32x32.png
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 1.4 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								public/gfx/icon_64x64.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								public/gfx/icon_64x64.png
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 3.3 KiB  | 
| 
						 | 
				
			
			@ -5,6 +5,11 @@
 | 
			
		|||
	<title>Cryptalk</title>
 | 
			
		||||
 | 
			
		||||
	<link rel="stylesheet" type="text/css" href="css/default.css">
 | 
			
		||||
 | 
			
		||||
	<head profile="http://www.w3.org/2005/10/profile">
 | 
			
		||||
	<link rel="icon" 
 | 
			
		||||
	      type="image/png" 
 | 
			
		||||
	      href="gfx/icon_32x32.png">
 | 
			
		||||
</head>
 | 
			
		||||
<body>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,7 +1,7 @@
 | 
			
		|||
// Main cryptalk module
 | 
			
		||||
define({
 | 
			
		||||
	compiles: ['$'],
 | 
			
		||||
	requires: ['hosts', 'templates', 'sound', 'fandango']
 | 
			
		||||
	requires: ['hosts', 'templates', 'sound', 'fandango','notifications']
 | 
			
		||||
}, function ($, requires, data) {
 | 
			
		||||
	var socket,
 | 
			
		||||
		key,
 | 
			
		||||
| 
						 | 
				
			
			@ -26,10 +26,11 @@ define({
 | 
			
		|||
		},
 | 
			
		||||
 | 
			
		||||
		// Shortcut
 | 
			
		||||
		hosts = requires.hosts.hosts;
 | 
			
		||||
		fandango = requires.fandango;
 | 
			
		||||
		templates = requires.templates;
 | 
			
		||||
		sound = requires.sound;
 | 
			
		||||
		hosts = requires.hosts.hosts,
 | 
			
		||||
		fandango = requires.fandango,
 | 
			
		||||
		templates = requires.templates,
 | 
			
		||||
		sound = requires.sound,
 | 
			
		||||
		notifications = requires.notifications,
 | 
			
		||||
 | 
			
		||||
		lockInput = function () {
 | 
			
		||||
			components.input[0].setAttribute('disabled', 'disabled');
 | 
			
		||||
| 
						 | 
				
			
			@ -42,8 +43,22 @@ define({
 | 
			
		|||
			components.input.focus();
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		showNotification = function (type, nick, text) {
 | 
			
		||||
			if (!mute) {
 | 
			
		||||
				if ( type == 'message') {
 | 
			
		||||
					notifications.notify(nick.substring(0, 20), text.substring(0, 80),'gfx/icon_128x128.png',true);
 | 
			
		||||
				} else if ( type == 'error' ) {
 | 
			
		||||
					notifications.notify('Cryptalk', text.substring(0, 80),'gfx/icon_128x128_error.png',true);
 | 
			
		||||
				} else {
 | 
			
		||||
					notifications.notify('Cryptalk', text.substring(0, 80),'gfx/icon_128x128_info.png',true);
 | 
			
		||||
				}
 | 
			
		||||
				
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		// Adds a new message to the DOM
 | 
			
		||||
		post = function (type, text, clearChat, clearBuffer, nick) {
 | 
			
		||||
 | 
			
		||||
			var tpl = templates.post[type],
 | 
			
		||||
				post,
 | 
			
		||||
				data = fandango.merge({}, settings, {
 | 
			
		||||
| 
						 | 
				
			
			@ -60,6 +75,9 @@ define({
 | 
			
		|||
				clearInput();
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			showNotification(type, nick, text)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
			// Append the post to the chat DOM element
 | 
			
		||||
			components.chat[clearChat ? 'html' : 'append'](post);
 | 
			
		||||
		},
 | 
			
		||||
| 
						 | 
				
			
			@ -196,7 +214,7 @@ define({
 | 
			
		|||
							post('error', templates.messages.unable_to_decrypt);
 | 
			
		||||
						} else {
 | 
			
		||||
							post('message', sanitized, false, false, nick);
 | 
			
		||||
							if( !mute ) sound.playTones(sound.messages.message);
 | 
			
		||||
							//if( !mute && !notifications.windowActive()) sound.playTones(sound.messages.message);
 | 
			
		||||
						}
 | 
			
		||||
					})
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -212,7 +230,7 @@ define({
 | 
			
		|||
								}
 | 
			
		||||
 | 
			
		||||
								// Play sound
 | 
			
		||||
								if (sound.messages[sanitized] !== undefined && !mute ) sound.playTones(sound.messages[sanitized]);
 | 
			
		||||
								//if (sound.messages[sanitized] !== undefined && !mute && !notifications.windowActive() ) sound.playTones(sound.messages[sanitized]);
 | 
			
		||||
 | 
			
		||||
							} else {
 | 
			
		||||
								post('error', templates.server.bogus);
 | 
			
		||||
| 
						 | 
				
			
			@ -500,9 +518,12 @@ define({
 | 
			
		|||
 | 
			
		||||
	unlockInput();
 | 
			
		||||
 | 
			
		||||
	notifications.enableNative();
 | 
			
		||||
 | 
			
		||||
	// It's possible to provide room and key using the hashtag.
 | 
			
		||||
	// The room and key is then seperated by semicolon (room:key).
 | 
			
		||||
	// If there is no semicolon present, the complete hash will be treated as the room name and the key has to be set manually.
 | 
			
		||||
	commands.connect(0, function() {
 | 
			
		||||
		if (host && (hash = window.location.hash)) {
 | 
			
		||||
			parts = hash.slice(1).split(':');
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -510,3 +531,5 @@ define({
 | 
			
		|||
			parts[1] && commands.key(parts[1]);
 | 
			
		||||
		}	
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										133
									
								
								public/js/cryptalk_modules/notifications.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										133
									
								
								public/js/cryptalk_modules/notifications.js
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,133 @@
 | 
			
		|||
/*
 | 
			
		||||
Usage
 | 
			
		||||
 
 | 
			
		||||
Native notifications without fallback:
 | 
			
		||||
	notification.enableNative(); // Once
 | 
			
		||||
	notification.notify("Woop Woop");
 | 
			
		||||
	
 | 
			
		||||
Native notifications with fallback:
 | 
			
		||||
	notification.enableNative(); // Once
 | 
			
		||||
	notification.notify("Woop Woop",true); // True in 2nd parameter enables fallback
 | 
			
		||||
	
 | 
			
		||||
Title blink only:
 | 
			
		||||
	notifications.blinkTitleUntilFocus("Woop Woop",1000);
 | 
			
		||||
	
 | 
			
		||||
*/
 | 
			
		||||
define(function (){
 | 
			
		||||
 
 | 
			
		||||
	var exports = {},
 | 
			
		||||
 
 | 
			
		||||
		window_active,
 | 
			
		||||
		blur_delay_timer,
 | 
			
		||||
		native_supported = false,
 | 
			
		||||
 
 | 
			
		||||
		new_title,
 | 
			
		||||
		original_title,
 | 
			
		||||
		blink_timer,
 | 
			
		||||
		interval,
 | 
			
		||||
 | 
			
		||||
        now = function () {
 | 
			
		||||
            return performance.now() || Date.now();
 | 
			
		||||
        },
 | 
			
		||||
 
 | 
			
		||||
		focusCallback = function() {
 | 
			
		||||
			/* Reset everything after regaining focus */
 | 
			
		||||
			resetState();
 | 
			
		||||
		},
 | 
			
		||||
 
 | 
			
		||||
		resetState = function() {
 | 
			
		||||
			clearTimeout(blur_delay_timer);
 | 
			
		||||
			clearTimeout(blink_timer);
 | 
			
		||||
			if (original_title !== undefined) setTitle(original_title);
 | 
			
		||||
			original_title = undefined;
 | 
			
		||||
			new_title = undefined;
 | 
			
		||||
			window_active = true;
 | 
			
		||||
		},
 | 
			
		||||
 
 | 
			
		||||
		blurCallback = function() {
 | 
			
		||||
			/* Apply a slight delay to prevent notifications from popping when the notifications
 | 
			
		||||
			   cause the windows to lose focus */
 | 
			
		||||
			clearTimeout(blur_delay_timer);
 | 
			
		||||
			blur_delay_timer = setTimeout(function() { window_active = false; },1000);
 | 
			
		||||
		},
 | 
			
		||||
 
 | 
			
		||||
		setTitle = function(t) 	{ document.title = t; },
 | 
			
		||||
		getTitle = function() 	{ return document.title; },
 | 
			
		||||
 
 | 
			
		||||
		doBlink = function() {
 | 
			
		||||
			if(!window_active) {
 | 
			
		||||
				if( getTitle() == original_title )
 | 
			
		||||
					setTitle( new_title );
 | 
			
		||||
				else
 | 
			
		||||
					setTitle( original_title);
 | 
			
		||||
 
 | 
			
		||||
				blink_timer = setTimeout(doBlink,interval);
 | 
			
		||||
			} else {
 | 
			
		||||
				resetState();
 | 
			
		||||
			}
 | 
			
		||||
		};
 | 
			
		||||
 
 | 
			
		||||
	exports.enableNative = function() {
 | 
			
		||||
		if( native_supported && Notification.permission !== 'denied' ) {
 | 
			
		||||
			Notification.requestPermission(function (status) {
 | 
			
		||||
				Notification.permission = status;
 | 
			
		||||
			});
 | 
			
		||||
		}
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	exports.windowActive = function() {
 | 
			
		||||
		return window_active;
 | 
			
		||||
	};
 | 
			
		||||
 
 | 
			
		||||
	exports.blinkTitleUntilFocus = function(t,i) {
 | 
			
		||||
		interval = (i == undefined) ? 1000 : i;
 | 
			
		||||
		if (!window_active) {
 | 
			
		||||
			new_title = t;
 | 
			
		||||
			original_title = getTitle();
 | 
			
		||||
			doBlink();
 | 
			
		||||
		}
 | 
			
		||||
	};
 | 
			
		||||
 
 | 
			
		||||
	exports.notify = function(title,body,icon,fallback) {
 | 
			
		||||
		// Only notify while in background
 | 
			
		||||
		if( !window_active ) {
 | 
			
		||||
 | 
			
		||||
			// Set default value for fallback parameter
 | 
			
		||||
			if ( fallback === undefined) fallback = false;
 | 
			
		||||
 | 
			
		||||
			if ( native_supported && Notification.permission === "granted") {
 | 
			
		||||
 | 
			
		||||
				// Create notification
 | 
			
		||||
				var n = new Notification(title, {body: body, icon:icon});
 | 
			
		||||
 | 
			
		||||
				// Handle on show event
 | 
			
		||||
				n.onshow = function () { 
 | 
			
		||||
				  	// Automatically close the notification after 5000ms
 | 
			
		||||
					setTimeout(function(){n.close();},3000);
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
			} else if ( fallback ) {
 | 
			
		||||
				exports.blinkTitleUntilFocus("Attention",1000);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	};
 | 
			
		||||
 
 | 
			
		||||
	native_supported = (window.Notification !== undefined);
 | 
			
		||||
 
 | 
			
		||||
	// Keep track of document focus/blur
 | 
			
		||||
	if (window.addEventListener){
 | 
			
		||||
		// Normal browsers
 | 
			
		||||
		window.addEventListener("focus", focusCallback, true);
 | 
			
		||||
		window.addEventListener("blur", blurCallback, true);
 | 
			
		||||
	} else {
 | 
			
		||||
		// IE
 | 
			
		||||
		window.observe("focusin", focusCallback);
 | 
			
		||||
		window.observe("focusout", blurCallback);
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
	// Make sure we are at square one
 | 
			
		||||
	resetState();
 | 
			
		||||
 
 | 
			
		||||
	return exports;
 | 
			
		||||
 
 | 
			
		||||
});
 | 
			
		||||
| 
						 | 
				
			
			@ -79,8 +79,8 @@ define({
 | 
			
		|||
		leave_from_nowhere: 	'How are you supposed to leave, while being nowhere?',
 | 
			
		||||
 | 
			
		||||
		// Sounds
 | 
			
		||||
		muted: 					'Notification sounds is now muted.',
 | 
			
		||||
		unmuted: 				'Notifications sounds is now on.',
 | 
			
		||||
		muted: 					'Notifications and sounds are now muted.',
 | 
			
		||||
		unmuted: 				'Notifications and sounds are now on.',
 | 
			
		||||
 | 
			
		||||
		// Extra variables: 'commandName'
 | 
			
		||||
		unrecognized_command: 	'Unrecognized command: "{commandName}"',
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										33
									
								
								server.js
									
										
									
									
									
								
							
							
						
						
									
										33
									
								
								server.js
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,5 +1,5 @@
 | 
			
		|||
var express = require('express.io'),
 | 
			
		||||
    uuid = require('node-uuid');
 | 
			
		||||
    uuid = require('node-uuid'),
 | 
			
		||||
 | 
			
		||||
    app = express();app.http().io();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -43,9 +43,38 @@ app.io.route('room', {
 | 
			
		|||
 | 
			
		||||
app.io.route('message', {
 | 
			
		||||
    send: function(req) {
 | 
			
		||||
      if(req.data && req.data.room) req.socket.broadcast.to(req.data.room).emit('message:send', { msg: req.data.msg, nick: req.data.nick} );
 | 
			
		||||
 | 
			
		||||
      // Check that the user is in a room
 | 
			
		||||
      if(req.data && req.data.room) {
 | 
			
		||||
 | 
			
		||||
        // Check that the message size is within bounds
 | 
			
		||||
        var total_msg_size = (req.data.msg) ? req.data.msg.length : 0 + (req.data.nick) ? req.data.nick.length : 0;
 | 
			
		||||
        if( total_msg_size <= 4096) {
 | 
			
		||||
 | 
			
		||||
          // Check that at least 100ms has passed since last message
 | 
			
		||||
          if( req.socket.last_message === undefined || new Date().getTime() - req.socket.last_message > 100 ) {
 | 
			
		||||
 | 
			
		||||
            req.socket.broadcast.to(req.data.room).emit('message:send', { msg: req.data.msg, nick: req.data.nick} );
 | 
			
		||||
            req.socket.emit('message:send', { msg: req.data.msg, nick: req.data.nick} );
 | 
			
		||||
 | 
			
		||||
            req.socket.last_message = new Date().getTime();
 | 
			
		||||
 | 
			
		||||
          } else {
 | 
			
		||||
 | 
			
		||||
            // Do not complain if message rate is too fast, that would only generate more traffic
 | 
			
		||||
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
        } else {
 | 
			
		||||
 | 
			
		||||
          // Message size is out of bounds, complain
 | 
			
		||||
          req.socket.emit('message:server', {msg:'command_failed'} );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      } 
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
app.io.sockets.on('connection', function(socket) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue