Coverage

98%
464
455
9

/home/lesterpig/workspace/openparty/lib/attrs.js

100%
1
1
0
LineHitsSource
11module.exports = {
2
3 name: {m: true, t: "String"},
4 start: {m: true, t: "Function"},
5 minPlayers: {m: true, t: "Integer"},
6 maxPlayers: {m: true, t: "Integer"},
7
8 init: {t: "Function"},
9 firstStage: {t: "String"},
10 parameters: {t: "Array"},
11 stages: {t: "Object"},
12 processMessage: {t: "Function"},
13 onDisconnect: {t: "Function"},
14 version: {t: "String"},
15 description: {t: "String"},
16 opVersion: {t: "String"},
17 css: {t: "Array"}
18
19};
20

/home/lesterpig/workspace/openparty/lib/loader.js

100%
73
73
0
LineHitsSource
11var path = require('path');
21var fs = require('fs');
31var color = require('colors');
41var sem = require('semver');
51var utils = require('./utils');
61var attrs = require('./attrs');
7
81module.exports = function(basePath, callback) {
9
108 if(!basePath)
111 basePath = path.join(__dirname, "..", "data");
128 if(!callback)
131 callback = function(){};
14
158 var gametypes = {};
16
178 fs.readdir(basePath, function(err, files) {
18
198 if(err) {
201 return callback( "!! Unable to load game definitions\n".red +
21 " Install gameplay definitions in data/ subdirectory\n".red +
22 (" Was: " + err).red, null);
23 }
24
257 var ok = false;
26
277 files.forEach(function(filePath) {
2828 if(fs.statSync(path.join(basePath, filePath)).isDirectory()) {
29
3021 var modulePath = path.join(basePath, filePath, "definition.js");
3121 if(!fs.existsSync(modulePath))
3210 return;
33
3411 if((module = checkFile(modulePath))) {
355 ok = true;
365 gametypes[filePath] = module;
37
38 // Has public files ?
395 var publicPath = path.join(basePath, filePath, "public");
405 if(fs.existsSync(publicPath)) {
415 __app.use(__app.express.static(publicPath));
42 }
43 }
44 }
45 });
46
477 if(!ok) {
482 return callback("!! No gameplay definition was correct. Aborting.".red, null);
49 }
50
515 callback(null, gametypes);
52
53 });
54};
55
561var checkFile = function(path) {
57
5811 var errorLog = [];
59
6011 try {
6111 module = require(path);
6210 var instance = new module();
63
649 checkMissingAttributes(instance, errorLog);
659 checkWrongAttributes(instance, errorLog);
66
679 if(errorLog.length === 1) {
682 throw new Error("One semantic failure");
697 } else if(errorLog.length > 1) {
702 throw new Error(errorLog.length + " semantic failures");
71 }
72
73 // Everything is ok!
745 return module;
75 } catch(e) {
766 console.error(("~~ Cannot load '" + path + "'\n " + e).yellow)
776 errorLog.forEach(function(a) {
7810 console.error((" - " + a).gray.italic);
79 });
806 return null;
81 }
82};
83
841var checkMissingAttributes = function(instance, errorLog) {
85
869 for(var attr in attrs) {
87126 if(!attrs[attr].m) {
8890 continue;
89 }
90
9136 if(!instance[attr]) {
924 errorLog.push("Missing '" + attr + "' mandatory attribute (" + attrs[attr].t + ")");
93 }
94 }
95
96};
97
981var checkType = function(e, t) {
99
10069 var fn;
10169 switch(t) {
10240 case "String": fn = utils.isString; break;
10346 case "Function": fn = utils.isFunction; break;
10432 case "Integer": fn = utils.isInteger; break;
10512 case "Array": fn = utils.isArray; break;
1068 case "Object": fn = utils.isObject; break;
107 }
10869 return fn(e);
109
110};
111
1121var checkWrongAttributes = function(instance, errorLog) {
113
1149 for(var attr in attrs) {
115126 if(instance[attr] && !checkType(instance[attr], attrs[attr].t)) {
1162 errorLog.push("'" + attr + "' must be of type (" + attrs[attr].t + ")");
117 }
118 }
119
1209 if(instance.maxPlayers <= 0) {
1211 errorLog.push("'maxPlayers' must be positive");
122 }
123
1249 if(instance.minPlayers <= 0) {
1251 errorLog.push("'minPlayers' must be positive");
126 }
127
1289 if(instance.maxPlayers < instance.minPlayers) {
1291 errorLog.push("'minPlayers' is greater than 'maxPlayers'");
130 }
131
1329 if(instance.opVersion && !sem.satisfies(__version, instance.opVersion)) {
1331 errorLog.push("This module is not ready for this version of OpenParty (" + __version + " does not satisfy " + instance.opVersion + ")");
134 }
135}
136

/home/lesterpig/workspace/openparty/lib/players.js

98%
94
93
1
LineHitsSource
11var utils = require("/home/lesterpig/workspace/openparty/lib/./utils.js");
2
31var Player = function(socket, room) {
4
5 /**
6 * roles = {
7 * <name>: {channels: {}, actions: {}},
8 * ...
9 * }
10 *
11 */
128 this.roles = {};
13
148 this.channels = {};
158 this.actions = {};
16
178 this.socket = socket; // circular
188 this.room = room; // circular
198 this.username = socket.username;
20
21};
22
2315Player.prototype.join = function(channel) { this.socket.join("room_" + this.room.id + "_" + channel); };
246Player.prototype.leave = function(channel) { this.socket.leave("room_" + this.room.id + "_" + channel); };
25
261Player.prototype.setRole = function(role, value) {
275 if(!value && this.roles[role]) {
28 // Remove all registered channels
291 for(var channel in this.roles[role].channels) {
302 if(this.roles[role].channels[channel].r && !this.channels[channel]) {
312 this.leave(channel);
32 }
33 }
344 } else if(value) {
35 // Join all channels
363 for(var channel in value.channels) {
375 if(value.channels[channel].r) {
384 this.join(channel);
39 }
40 }
41 }
425 setAttributeObject(this, "roles", role, value);
435 this.sendWriteChannels();
44};
45
461Player.prototype.setAction = function(name, value) {
473 setAttributeObject(this, "actions", name, value);
48};
49
501Player.prototype.setChannel = function(name, rights) {
51
5212 if(!rights) {
531 if(this.channels[name]) {
541 this.leave(name);
551 delete this.channels[name];
56 // Refreshing channels
571 for(var role in this.roles) {
581 for(var channel in this.roles[role].channels) {
592 if(channel === name && this.roles[role].channels[channel].r)
601 this.join(channel);
61 }
62 }
63 }
64 }
65
66 else {
6711 if(rights.r) {
689 this.join(name);
69 }
70 else {
712 this.leave(name);
72 }
7311 this.channels[name] = rights;
74 }
7512 this.sendWriteChannels();
76};
77
781Player.prototype.getWriteChannels = function() {
7934 var channels = {};
80
8134 for(var role in this.roles) {
8223 for(var channel in this.roles[role].channels) {
8341 if(this.roles[role].channels[channel].w) {
8423 channels[channel] = this.roles[role].channels[channel];
85 }
86 }
87 }
88
8934 for(var channel in this.channels) { // override "default" behavior
9046 if(this.channels[channel].w) {
9139 channels[channel] = this.channels[channel];
92 }
93 else {
947 delete channels[channel];
95 }
96 }
97
9834 return channels;
99};
100
1011Player.prototype.sendWriteChannels = function() {
10217 return this.emit("setAllowedChannels", this.getWriteChannels());
103};
104
1051Player.prototype.getAvailableActions = function(clone) {
10635 var output = {};
107
108 // role actions
10935 for(var role in this.roles) {
11025 for(var action in this.roles[role].actions) {
11176 if(this.roles[role].actions[action].isAvailable(this)) {
11271 output[action] = this.roles[role].actions[action];
113 }
114 }
115 }
116
117 // personal actions (override)
11835 for(var action in this.actions) {
1196 if(this.actions[action].isAvailable && this.actions[action].isAvailable(this)) {
1205 output[action] = this.actions[action];
121 } else {
1221 delete output[action];
123 }
124 }
125
12635 for(var action in output) {
12775 if(clone) {
12823 output[action] = {
129 type: output[action].type,
130 options: output[action].options
131 };
132 }
133
13475 processActionOptions(output[action], this.room);
135 }
136
13735 return output;
138};
139
1401Player.prototype.sendAvailableActions = function() {
14120 return this.emit("setAvailableActions", this.getAvailableActions(true));
142};
143
1441Player.prototype.emit = function(event, data) {
14538 this.socket.emit(event,data);
14638 return true;
147};
148
1491Player.prototype.message = function(m) {
1500 this.emit("chatMessage", {message: m});
151};
152
1531module.exports = {
154
155 init: function(room) {
1562 room.players.forEach(function(p) {
1578 p.player = new Player(p, room);
1588 p.player.setChannel("general", {r:true, w:true, n:"General"});
159 });
160 },
161
162 Player: Player
163
164};
165
166/** PRIVATE FUNCTIONS **/
167
1681function setAttributeObject(p, attr, name, value) {
1698 if(value === null || value === undefined) {
1703 delete p[attr][name];
171 }
172
173 else {
1745 p[attr][name] = value;
175 }
176}
177
1781function processActionOptions(action, room) {
179
18075 switch(action.type) {
181
182 case "select":
183
18453 if(!action.options.choices) {
1851 action.options.choices = "players";
186 }
187
18853 if(utils.isString(action.options.choices)) {
189
19019 var out = [];
19119 room.players.forEach(function(e) {
19276 out.push(e.username);
193 });
19419 action.options.safeChoices = out;
195
19634 } else if(Array.isArray(action.options.choices)) {
19719 action.options.safeChoices = action.options.choices;
198 } else {
19915 action.options.safeChoices = action.options.choices(room, this);
200 }
201
20253 break;
203
204 default:
20522 break;
206 }
207
208}
209

/home/lesterpig/workspace/openparty/lib/rooms.js

98%
182
180
2
LineHitsSource
11var utils = require("/home/lesterpig/workspace/openparty/lib/./utils.js");
21var players = require("/home/lesterpig/workspace/openparty/lib/./players.js");
31var Player = players.Player;
4
5
61var Room = function(name, password, gameplay) {
7
83 this.isRoom = true;
93 this.id = utils.randomString(20); // TODO make it better...
103 this.players = [];
113 this.name = name;
123 this.size = gameplay.minPlayers;
133 this.creationDate = new Date();
143 this.password = password;
15
163 this.gameplay = gameplay;
173 this.gameplay.room = this; // circular
18
19 // Stages
203 this.started = false;
213 this.timeout = null;
223 this.currentStage = null;
23
243 if(this.gameplay.init) {
253 this.gameplay.init(this);
26 }
27
28};
29
30/**
31 * Broadcast a message to several sockets
32 * @param {String} [channel]
33 * @param {String} event
34 * @param {*} [data]
35 */
361Room.prototype.broadcast = function(channel, event, data) {
37
3839 if(data === undefined && channel) {
3924 data = event;
4024 event = channel;
4124 channel = "";
4215 } else if(channel !== "") {
4311 channel = "_" + channel;
44 }
4539 __app.io.to("room_" + this.id + channel).emit(event, data);
46};
47
48/**
49 * Send more information about a player.
50 * Client-side, it will be displayed in players list.
51 *
52 * @param {String} [channel]
53 * @param {Object} player (socket or Player object)
54 * @param {String} value
55 */
561Room.prototype.playerInfo = function(channel, player, value) {
57
584 if(!value) {
592 if(channel instanceof Player) {
601 channel = channel.socket;
61 }
622 this.broadcast("playerInfo", {username: channel.username, value: player});
63 } else {
642 if(player instanceof Player) {
651 player = player.socket;
66 }
672 this.broadcast(channel, "playerInfo", {username: player.username, value: value});
68 }
69}
70
71/**
72 * Send a chat message to players (system message)
73 * @param {String} [channel]
74 * @param {String} message
75 */
761Room.prototype.message = function(channel, message) {
776 if(!message) {
784 this.broadcast("chatMessage", {message:channel});
79 }
80 else {
812 this.broadcast(channel, "chatMessage", {message:message});
82 }
83};
84
85/**
86 * Get public information about the room and its players
87 * @return {Object}
88 */
891Room.prototype.getPublicInfo = function() {
90
9135 var output = {};
92
9335 output.id = this.id;
9435 output.isRoom = true;
9535 output.name = this.name;
9635 output.players = [];
9735 output.size = this.size;
9835 output.started = this.started;
9935 output.password = !!this.password;
100
10135 for(var i = 0; i < this.players.length; i++) {
10272 output.players.push({username: this.players[i].username});
103 }
104
10535 var parameters = [];
10635 this.gameplay.parameters.forEach(function(p) {
10770 parameters.push({
108 name: p.name,
109 value: p.value,
110 help: p.help,
111 isBoolean: p.type === Boolean
112 });
113 });
114
11535 output.gameplay = {
116 name: this.gameplay.name,
117 description: this.gameplay.description,
118 parameters: parameters,
119 maxPlayers: this.gameplay.maxPlayers,
120 minPlayers: this.gameplay.minPlayers
121 };
122
12335 return output;
124
125};
126
127/**
128 * Set room size
129 * @param {Number} size
130 */
1311Room.prototype.setSize = function(size) {
132
1333 if(size >= this.gameplay.minPlayers && size <= this.gameplay.maxPlayers) {
1342 this.size = size;
1352 sendUpdateRoom(this);
136 }
137};
138
139/**
140 * Set room parameter
141 * @param {} parameter
142 * @param {*} value
143 * @param {Socket} socket
144 */
1451Room.prototype.setParameter = function(parameter, value, socket) {
146
147
1483 this.gameplay.parameters.forEach(function(e) {
1496 if(e.name === parameter) {
1502 e.value = e.type(value); //deal with it.
1512 sendUpdateRoom(this, socket);
1522 return;
153 }
154 }.bind(this));
155};
156
1571Room.prototype.sendMessage = function(channel, message, socket) {
158
15924 var allowed = false;
160
16124 if(channel === "preChat") {
1625 if(this.started) {
1631 return;
164 }
1654 allowed = true;
1664 channel = "";
167 } else {
16819 if(!this.started) {
1692 return;
170 }
17117 var channels = socket.player.getWriteChannels();
17217 allowed = (channels[channel] ? (true === channels[channel].w) : false);
173 }
174
17521 if(allowed) {
17615 socket.emit("messageSent");
17715 if(this.gameplay.processMessage && this.started) {
17811 message = this.gameplay.processMessage(channel, message, socket.player);
17911 if(!message) {
1804 return;
181 }
182 }
18311 this.broadcast(channel, "chatMessage", {message: message, sender: socket.username});
184 }
185};
186
1871Room.prototype.start = function() {
188
1892 players.init(this);
1902 this.gameplay.start(this, function(err) {
191
1922 if(err) {
1931 return this.broadcast("chatMessage", { message: err });
194 }
195
1961 this.started = true;
1971 sendUpdateRoom(this);
1981 this.broadcast("gameStarted");
199
2001 if(this.gameplay.firstStage) {
2011 this.nextStage(this.gameplay.firstStage);
202 }
203
204 }.bind(this));
205};
206
207/**
208 * End the current stage and start another one
209 * @param {String} stage The new stage name
210 * @param {Function} [callback]
211 */
2121Room.prototype.nextStage = function(stage, callback) {
213
2145 this.currentStage = stage;
215
2165 this.gameplay.stages[stage].start(this, function(err, duration) {
217
2185 this.setStageDuration(duration);
219
220 // Send actions to players
221
2225 this.players.forEach(function(player) {
22320 player.player.sendAvailableActions();
224 });
225
2265 if(callback) {
2271 callback(null);
228 }
229
230 }.bind(this));
231
232};
233
234/**
235 * End the current stage, without starting another one
236 */
2371Room.prototype.endStage = function() {
2381 clearTimeout(this.timeout);
2391 this.gameplay.stages[this.currentStage].end(this, function() {});
240};
241
242/**
243 * Change current stage duration
244 * @param {Number} duration (sec)
245 */
2461Room.prototype.setStageDuration = function(duration) {
247
2486 clearTimeout(this.timeout);
249
2506 if(duration < 0) {
2513 this.broadcast("clearTimer");
2523 return;
253 }
254
2553 this.broadcast("setTimer", duration);
2563 this.timeout = setTimeout(this.endStage.bind(this), duration * 1000);
257};
258
259/**
260 * Get player object from username
261 * @param {String} username
262 * @return {Socket}
263 */
2641Room.prototype.resolveUsername = function(username) {
2653 for(var i = 0; i < this.players.length; i++) {
2667 if(this.players[i].username === username) {
2672 return this.players[i];
268 }
269 }
2701 return null;
271};
272
2731var rooms = module.exports = {
274
275 rooms: [],
276
277 getRooms: function() {
278
2791 var output = [];
2801 for(var i = 0; i < this.rooms.length; i++) {
2811 if(!this.rooms[i].started) {
2821 output.push(this.rooms[i].getPublicInfo());
283 }
284 }
285
2861 return output;
287 },
288
289 createRoom: function(name, password, type, socket) {
290
2914 if(!type || type === "default") {
2922 for(var i in __gametypes) {
2932 type = i;
2942 break;
295 }
296 }
297
2984 if(!__gametypes[type]) {
2991 return;
300 }
301
3023 var gameplay = new __gametypes[type]();
303
3043 var room = new Room(name, password, gameplay);
305
3063 this.rooms.push(room);
3073 __app.io.to("lobby").emit("roomCreated", room.getPublicInfo());
3083 this.joinRoom(room.id, password, socket);
309 },
310
311 getRoom: function(id) {
312
31312 for(var i = 0; i < this.rooms.length; i++) {
31412 if(this.rooms[i].id === id) {
31511 return this.rooms[i];
316 }
317 }
318
3191 return null;
320
321 },
322
323 joinRoom: function(id, password, socket) {
324
32512 var room = this.getRoom(id);
32612 if(!room) {
3271 return;
328 }
329
33011 if(room.players.length >= room.size) {
3311 return;
332 }
333
33410 if(room.password && room.password !== password) {
3350 socket.emit("invalidRoomPassword");
3360 return;
337 }
338
33910 if(room.players.indexOf(socket) < 0) {
34010 room.players.push(socket);
341 }
342
34310 sendUpdateRoom(room);
34410 socket.emit("roomJoined", room.getPublicInfo());
34510 socket.join("room_" + id);
34610 socket.currentRoom = room;
347
34810 room.broadcast("chatMessage", {message: socket.username + " has joined the room"});
349
350 },
351
352 leaveRoom: function(socket) {
353
35413 var room = socket.currentRoom;
35513 if(!room) {
3564 return;
357 }
358
3599 var i = room.players.indexOf(socket);
3609 if(i < 0) {
3611 return;
362 }
363
3648 room.players.splice(i, 1);
365
3668 if(room.gameplay.onDisconnect && socket.player) {
3672 room.gameplay.onDisconnect(room, socket.player);
368 }
369
3708 if(room.players.length === 0) {
3712 this.removeRoom(room);
372 } else {
3736 sendUpdateRoom(room);
374 }
375
3768 socket.player = null;
3778 socket.currentRoom = null;
378
379 // Leave concerned socket rooms
380 // Buffered, because socket.rooms is dynamically updated by socket.io
3818 var regex = /^room\_/;
3828 var buffer = socket.rooms.filter(function(r) {
38316 return regex.test(r);
384 });
385
3868 try {
3878 buffer.forEach(function(r) {
3886 socket.leave(r);
389 });
3908 socket.emit("roomLeft");
391 } catch(e) {}
392
393 },
394
395 removeRoom: function(room) {
396
3972 for(var i = 0; i < this.rooms.length; i++) {
3982 if(this.rooms[i].id === room.id) {
3992 clearTimeout(this.rooms[i].timeout);
4002 this.rooms.splice(i, 1);
4012 __app.io.to("lobby").emit("roomRemoved", room.id);
4022 return;
403 }
404 }
405
406 }
407
408};
409
410/** PRIVATE FUNCTIONS **/
411
4121function sendUpdateRoom(room, socket) {
41321 if(!socket) {
41419 __app.io.to("lobby").emit("roomUpdated", room.getPublicInfo());
415 }
416 else {
4172 socket.broadcast.to("lobby").emit("roomUpdated", room.getPublicInfo());
418 }
419}
420

/home/lesterpig/workspace/openparty/lib/router.js

92%
81
75
6
LineHitsSource
11var utils = require("/home/lesterpig/workspace/openparty/lib/./utils");
21var rooms = require("/home/lesterpig/workspace/openparty/lib/./rooms");
3
41module.exports = function(app) {
5
6 /**
7 * ROOT
8 */
91 app.get("/", function(req, res) {
101 req.session.locale = req.getLocale();
111 res.render("index", {passwordRequired: __conf.password !== null });
12 });
13
14 /***
15 * ABOUT
16 */
171 app.get("/about", function(req, res) {
181 res.render("about", {version: __version, locales: __conf.locales, gamemodes: __staticGametypes });
19 });
20
21 /**
22 * IO : Ping
23 */
241 app.io.route("ping", function(socket) {
251 socket.volatile.emit("pong");
26 });
27
28 /**
29 * IO : Disconnect
30 */
311 app.io.route("disconnect", function(socket) {
32
334 var room = utils.isInGame(socket);
345 if(!room) return;
35
363 rooms.leaveRoom(socket);
37 });
38
39 /**
40 * IO : Login
41 */
421 app.io.route("login", function(socket, data) {
43
4418 var locale = socket.session.locale || __conf.defaultLocale;
45
4618 if(data.password !== __conf.password && __conf.password !== null || !data.username) {
474 return socket.emit("loginResult", {err: __i18n({phrase: "Bad Credentials", locale: locale})});
48 }
49
50 // Check username
5114 try {
5214 var username = utils.checkUsername(data.username);
53 } catch(e) {
545 return socket.emit("loginResult", {err: __i18n({phrase: e.message, locale: locale})});
55 }
56
579 socket.join("lobby");
589 socket.username = username;
59
609 socket.emit("loginResult", {err: null, username: username, gametypes: __staticGametypes});
61 });
62
63 /**
64 * IO : Get Rooms
65 */
661 app.io.route("getRooms", function(socket) {
672 if(!utils.isInRoom(socket, "lobby"))
681 return;
691 socket.emit("roomsList", rooms.getRooms());
70 });
71
72 /**
73 * IO : Create Room
74 */
751 app.io.route("createRoom", function(socket, data) {
766 if(!utils.isInRoom(socket, "lobby"))
771 return;
785 if(utils.isInGame(socket))
791 return;
804 rooms.createRoom(data.name, data.password, data.type, socket);
81 });
82
83 /**
84 * IO : Join Room
85 */
861 app.io.route("joinRoom", function(socket, data) {
8711 if(!utils.isInRoom(socket, "lobby"))
881 return;
8910 if(utils.isInGame(socket))
901 return;
919 rooms.joinRoom(data.id, data.password, socket);
92 });
93
94 /**
95 * IO : Leave Room
96 */
971 app.io.route("leaveRoom", function(socket) {
989 rooms.leaveRoom(socket);
99 });
100
101 /**
102 * IO : Kick Player
103 */
1041 app.io.route("kickPlayer", function(socket, username) {
105
1060 var room = utils.isInGame(socket);
1070 var player;
1080 if( !room
109 || room.started
110 || room.players[0] !== socket
111 || !(player = room.resolveUsername(username))) {
1120 return;
113 }
1140 room.message(username + " has been kicked out of this room.");
1150 rooms.leaveRoom(player);
116 });
117
118 /**
119 * IO : Room Parameters
120 */
1211 app.io.route("setRoomSize", function(socket, data) {
1224 var room = utils.isInGame(socket);
1234 if(room && room.players[0] === socket && room.players.length <= +data)
1243 room.setSize(+data);
125 });
126
1271 app.io.route("setRoomParameter", function(socket, data) {
1284 var room = utils.isInGame(socket);
1294 if(room && room.players[0] === socket)
1303 room.setParameter(data.parameter, data.value, socket);
131 });
132
133 /**
134 * IO : Chat Management
135 */
1361 app.io.route("sendMessage", function(socket, data) {
13727 var room = utils.isInGame(socket);
13827 var message = utils.sanitizeHtml(data.message);
13927 if(!message)
1403 return;
14124 if(room)
14224 room.sendMessage(data.channel, message, socket);
143 });
144
145 /**
146 * IO : Start Game !
147 */
1481 app.io.route("startRoom", function(socket) {
1493 var room = utils.isInGame(socket);
1503 if(room && room.players[0] === socket && !room.started && room.size === room.players.length)
1512 room.start();
152 });
153
154 /**
155 * IO : Execute Action
156 */
1571 app.io.route("executeAction", function(socket, data) {
158
15918 if(!socket.player || !data || !data.action)
1603 return; // Not authorized
161
16215 var actions = socket.player.getAvailableActions(false);
163
16415 if(!actions[data.action] || actions[data.action].locked)
1652 return; // Not ready for this action
166
16713 if(actions[data.action].type === "select"
168 && actions[data.action].options.safeChoices.indexOf(data.value) < 0)
1697 return; // Bad value
170
1716 if(actions[data.action].type === "select"
172 && actions[data.action].options.choices === "players") {
1731 data.value = socket.player.room.resolveUsername(data.value).player;
174 }
175
1766 actions[data.action].locked = true;
1776 actions[data.action].execute(socket.player, data.value);
1786 actions[data.action].locked = false;
179 });
180}
181

/home/lesterpig/workspace/openparty/lib/utils.js

100%
33
33
0
LineHitsSource
11var crypto = require("crypto");
2
31global.GET_RANDOM = function(from, to) {
41024 return Math.floor(Math.random() * (to - from + 1)) + from;
5};
6
71module.exports = {
8
9 randomString: function(len) {
103 return crypto.randomBytes(Math.ceil(len * 3 / 4))
11 .toString('base64') // convert to base64 format
12 .slice(0, len) // return required number of characters
13 .replace(/\+/g, '0') // replace '+' with '0'
14 .replace(/\//g, '0'); // replace '/' with '0'
15 },
16
17 isInRoom: function(socket, room) {
1819 return socket.rooms.indexOf(room) >= 0;
19 },
20
21 isInGame: function(socket) {
22
2357 if(!socket.currentRoom)
2414 return false;
25 else
2643 return socket.currentRoom;
27
28 },
29
30 sanitizeHtml: function(string) {
3140 if(!string)
323 return "";
3337 string = string.replace(/</ig,"<");
3437 string = string.replace(/>/ig,">");
3537 return string;
36 },
37
38 checkUsername: function(username) {
3914 if(username.length > 20)
401 throw new Error("Username is too long.");
41
4213 username = this.sanitizeHtml(username);
4313 username = username.trim();
44
4513 if(username.length === 0)
461 throw new Error("Username is invalid.");
47
48 // already connected ?
49
5012 var exists = __app.io.sockets.sockets.some(function(s) {
5163 if(!s.username)
5239 return false;
5324 if(s.username.toLowerCase() === username.toLowerCase())
543 return true;
55 });
56
5712 if(exists)
583 throw new Error("Username is not available.");
59
609 return username;
61
62 },
63
64 /** TYPES */
65
66 isString: function(s) {
6778 return typeof s === 'string' || s instanceof String;
68 },
69
70 isFunction: function(f) {
7123 return typeof f === 'function'
72 },
73
74 isInteger: function(i) {
7516 return i === parseInt(i, 10);
76 },
77
78 isArray: function(a) {
796 return require("util").isArray(a);
80 },
81
82 isObject: function(o) {
834 return typeof o === 'object'
84 }
85}
86