* Module dependencies.
*/
-var errorHandler = require('./lib/middleware/errorHandler')
+var banHandler = require('./lib/middleware/ban-handler')
+ , errorHandler = require('./lib/middleware/error-handler')
, express = require('express')
, favicon = require('serve-favicon')
, http = require('http')
app.set('view engine', 'jade');
app.use('/static', express.static(pub, {maxAge: 2419200000})); // 4 weeks = 2419200000 ms
app.use(favicon(pub + '/img/favicon.ico', {maxAge: 2419200000}));
+app.use(banHandler);
app.use(urlencoded());
app.use(cookieParser);
app.use(session({
--- /dev/null
+/**
+ * Module dependencies.
+ */
+
+var db = require('../redis-clients').users
+ , forwarded = require('forwarded-for')
+ , utils = require('../utils');
+
+/**
+ * Expose a middleware to filter banned IPs.
+ */
+
+module.exports = function(req, res, next) {
+ var address = forwarded(req, req.headers);
+
+ db.ttl(['ban:' + address.ip], function(err, ttl) {
+ if (err) {
+ return next(err);
+ }
+
+ if (ttl < 0) {
+ return next();
+ }
+
+ res.render('banned', {
+ slogan: utils.randomSlogan(),
+ ttl: Math.round(ttl / 60)
+ });
+ });
+};
*/
Room.prototype.onIgnore = function(who, executor, callback) {
- // Check if the player to be ignored is in the room
+ // Check if the player is in the room
if (this.usersData[who]) {
sparks[who].send('chatmsg', executor + ' is ignoring you.', 'binb', who);
return callback(true, who);
};
/**
- * Kick a player.
+ * Kick and optionally ban a player.
*/
-Room.prototype.onKick = function(who, why, executor, callback) {
+Room.prototype.onKick = function(who, why, executor, duration, callback) {
var room = this;
+ if (typeof duration === 'function') {
+ callback = duration;
+ duration = 0;
+ }
+
usersdb.hget(['user:' + executor, 'role'], function(err, role) {
if (err) {
console.error(err.message);
return callback(true);
}
- // Check role
- if (role > 0) {
- if (room.usersData[who]) {
- if (why) {
- why = ' (' + why + ')';
- }
- var notice = 'you have been kicked by ' + executor + why + '.'
- , recipient = sparks[who];
- recipient.send('chatmsg', notice, 'binb', who);
- recipient.end();
+ // Check if the sender can kick other players
+ if ((role || 0) < 1) {
+ return callback(false);
+ }
+
+ // Check if the target player is in the room
+ if (room.usersData[who]) {
+ var notice = 'you have been kicked by ' + executor +
+ (why && ' (' + why + ')') + '.';
+ var target = sparks[who];
+
+ if (duration) {
+ usersdb.setex(['ban:' + target.address.ip, duration, who], function(err) {
+ if (err) {
+ console.error(err.message);
+ }
+ });
}
- return callback(true);
+
+ target.send('chatmsg', notice, 'binb', who);
+ target.end();
}
- callback(false);
+
+ callback(true);
});
};
*/
var config = require('../config')
+ , db = require('../lib/redis-clients').users
+ , forwarded = require('forwarded-for')
, fs = require('fs')
, minify = require('uglify-js').minify
, Primus = require('primus')
, sessionstore
, sparks = Object.create(null) // Sparks of all rooms
, utils = require('./utils')
+ , banDuration = utils.banDuration
, isFunction = utils.isFunction
, isString = utils.isString;
console.error(err.message);
return authorized(err);
}
- req.user = session.user;
- authorized();
+ var address = forwarded(req, req.headers);
+ db.exists(['ban:' + address.ip], function(err, exists) {
+ if (err) {
+ console.error(err.message);
+ return authorized(err);
+ }
+ if (exists) {
+ return authorized(new Error('banned IP address'));
+ }
+ req.user = session.user;
+ authorized();
+ });
});
};
var joinRoom = function(room, spark) {
room = rooms[room];
+ spark.on('ban', function(who, why, duration, callback) {
+ if (
+ isString(who) &&
+ isString(why) &&
+ isString(duration) &&
+ isFunction(callback)
+ ) {
+ room.onKick(who, why, spark.nickname, banDuration(duration), callback);
+ }
+ });
spark.on('chatmsg', function(msg, to) {
if (isString(msg)) {
room.onChatMessage(msg, spark, to);
+/**
+ * Convert the duration of a ban from minutes to seconds and return the value.
+ * Default duration is 15 minutes.
+ */
+
+exports.banDuration = function(str) {
+ return /^[1-9][0-9]*$/.test(str) ? str * 60 : 900;
+};
+
/**
* Helper function used to build leaderboards.
* Rearrange database results in an object.
"cookie-parser": "1.1.x",
"express": "4.3.x",
"express-session": "1.2.x",
+ "forwarded-for": "0.0.x",
"jade": "1.3.x",
"nodemailer": "0.6.x",
"primus": "2.2.x",
});
};
- // Kick a player
- var kickPlayer = function(args, outcome) {
- outcome.append('you are not allowed to kick a player.');
- if (!subscriber) {
- return addChatEntry(outcome);
- }
- var why = args[1] || '';
- primus.send('kick', args[0], why, function(success) {
- if (!success) {
- addChatEntry(outcome);
- }
- });
- };
-
var loadTrack = function(previewUrl) {
jplayer.jPlayer('mute');
jplayer.jPlayer('setMedia', {m4a: previewUrl});
addFeedback('What is this song?');
};
+ // Return a function that will kick or ban a player
+ var punishPlayer = function(punishment) {
+ return function(tokens, outcome) {
+ outcome.append('you are not allowed to ' + punishment + ' a player.');
+ if (!subscriber) {
+ return addChatEntry(outcome);
+ }
+
+ var args = [punishment, tokens[0]];
+
+ if (punishment === 'kick') {
+ args.push(tokens[1] || '');
+ }
+ else if (!tokens[1]) {
+ args.push('', '');
+ }
+ else if (!tokens[2]) {
+ if (/^[1-9][0-9]*$/.test(tokens[1])) {
+ args.push('', tokens[1]);
+ }
+ else {
+ args.push(tokens[1], '');
+ }
+ }
+ else {
+ args.push(tokens[1], tokens[2]);
+ }
+
+ args.push(function(success) {
+ if (!success) {
+ addChatEntry(outcome);
+ }
+ });
+
+ primus.send.apply(primus, args);
+ };
+ };
+
// Return a function that will add a random text from the given set, with the given style
var randomFeedback = function(set, style) {
var card = set.length;
};
var slashcommands = {
+ ban: {
+ checkrecipient: true,
+ fn: punishPlayer('ban'),
+ minargs: 1,
+ usage: 'usage: /ban <player name> [message] [duration]'
+ },
clear: {
fn: function() {
DOM.chat.empty();
},
kick: {
checkrecipient: true,
- fn: kickPlayer,
+ fn: punishPlayer('kick'),
minargs: 1,
usage: 'usage: /kick <player name> [message]'
},
volume: 1
});
primus.on('alreadyinaroom', alreadyInARoom);
+ primus.on('close', disconnect);
primus.on('invalidnickname', invalidNickName);
primus.on('ready', ready);
primus.on('updateoverview', updateRoomsOverview);
primus.send('getoverview', roomsOverview);
});
- primus.on('close', disconnect);
})();
--- /dev/null
+extends layout
+
+block title
+ title binb :: banned
+
+block sections
+ section
+ .row
+ .span12.offset2
+ .alert.alert-error.alert-block
+ h4.alert-heading Error!
+ | Yuo have been banned.
+ br
+ | Your ban will expire in #{ttl} minutes.
+
+block scripts