diff --git a/src/Channel.js b/src/Channel.js index 5d6a66b..790e5e2 100644 --- a/src/Channel.js +++ b/src/Channel.js @@ -16,7 +16,16 @@ class Channel extends EventEmitter { this.server = server; this.crown; this.crowndropped = false; - this.settings = settings; + + if (this.isLobby(this._id)) { + this.settings = new RoomSettings(this.server.lobbySettings); + // this.settings.lobby = true; + // this.settings.color = this.server.lobbySettings.color; + // this.settings.color2 = this.server.lobbySettings.color2; + } else { + this.settings = new RoomSettings(settings, 'user'); + } + this.chatmsgs = []; this.ppl = new Map(); this.connections = []; @@ -71,26 +80,28 @@ class Channel extends EventEmitter { this.crown = new Crown(cl.participantId, cl.user._id); this.crowndropped = false; - this.settings = new RoomSettings(set, 'user'); + // this.settings = new RoomSettings(set, 'user'); } else { //cl.quotas.a.setParams(Quota.PARAMS_A_NORMAL); if (this.isLobby(this._id) && this.settings.lobby !== true) { - this.settings = new RoomSettings(this.server.lobbySettings, 'user'); - this.settings.visible = true; - this.settings.crownsolo = false; - this.settings.color = this.server.lobbySettings.color; - this.settings.color2 = this.server.lobbySettings.color2; - this.settings.lobby = true; + this.settings.changeSettings(this.server.lobbySettings, 'user'); + // this.settings.visible = true; + // this.settings.crownsolo = false; + // this.settings.lobby = true; + // this.settings.color = this.server.lobbySettings.color; + // this.settings.color2 = this.server.lobbySettings.color2; } else { - if (typeof(set) == 'undefined') { - if (typeof(this.settings) == 'undefined') { - this.settings = new RoomSettings(this.server.defaultRoomSettings, 'user'); + if (!this.isLobby) { + if (typeof(set) == 'undefined') { + if (typeof(this.settings) == 'undefined') { + this.settings = new RoomSettings(this.server.defaultRoomSettings, 'user'); + } else { + this.settings = new RoomSettings(cl.channel.settings, 'user'); + } } else { - this.settings = new RoomSettings(cl.channel.settings, 'user'); + this.settings = new RoomSettings(set, 'user'); } - } else { - this.settings = new RoomSettings(set, 'user'); } } } @@ -99,7 +110,7 @@ class Channel extends EventEmitter { this.connections.push(cl); - if (!cl.hidden) { + if (cl.hidden !== true) { this.sendArray([{ color: this.ppl.get(cl.participantId).user.color, id: this.ppl.get(cl.participantId).participantId, @@ -109,11 +120,11 @@ class Channel extends EventEmitter { y: this.ppl.get(cl.participantId).y || 100, _id: cl.user._id }], cl, false) - cl.sendArray([{ - m: "c", - c: this.chatmsgs.slice(-1 * 32) - }]); } + cl.sendArray([{ + m: "c", + c: this.chatmsgs.slice(-1 * 32) + }]); this.updateCh(cl, this.settings); } else { cl.user.id = otheruser.participantId; @@ -126,9 +137,40 @@ class Channel extends EventEmitter { }]) this.updateCh(cl, this.settings); } + + if (this.flags.spin == true) { + this.spin(cl); + } } - remove(p) { //this is complicated too + spin(cl) { // speeeeeeen + let id = cl.user._id; + if (!id) id = "room"; + this.Notification(id, + "", + ``, + ``, + 1, + "#names", + "short" + ); + } + + stopSpin(cl) { + let id = cl.user._id; + if (!id) id = "room"; + this.Notification(id, + "", + ``, + ``, + 1, + "#names", + "short" + ); + } + + remove(p) { // remove user + if (!p) return; let otheruser = this.connections.filter((a) => a.user._id == p.user._id); if (!(otheruser.length > 1)) { this.ppl.delete(p.participantId); @@ -212,6 +254,8 @@ class Channel extends EventEmitter { this.connections.forEach((usr) => { if (!not || (usr.participantId != not.participantId && !onlythisparticipant) || (usr.connectionid != not.connectionid && onlythisparticipant)) { try { + let cl = this.server.connections.get(usr.connectionid); + if (!cl) return; this.server.connections.get(usr.connectionid).sendArray(arr) } catch (e) { console.log(e); @@ -435,6 +479,14 @@ class Channel extends EventEmitter { this.chown(id); } break; + case "!chlist": + case "!channellist": + if (!isAdmin) return; + this.adminChat("Channels:"); + for (let ch of this.server.rooms) { + this.adminChat(`- ${ch._id}`); + } + break; } } @@ -541,8 +593,10 @@ class Channel extends EventEmitter { this.remove(participant); }) - this.on("m", (participant, x, y) => { - this.setCoords(participant, x, y); + this.on("m", msg => { + let p = this.ppl.get(msg.p); + if (!p) return; + this.setCoords(p, msg.x, msg.y); }) this.on("a", (participant, msg) => { @@ -552,6 +606,24 @@ class Channel extends EventEmitter { this.on("update", (cl) => { this.updateCh(cl); }); + + this.on("remove crown", () => { + this.crown = undefined; + delete this.crown; + this.emit('update'); + }); + + this.on("flag spin", spin => { + if (spin) { + for (let cl of this.connections) { + this.spin(cl); + } + } else { + for (let cl of this.connections) { + this.stopSpin(cl); + } + } + }); } verifySet(_id, msg) { diff --git a/src/Client.js b/src/Client.js index c13de7a..56ece3d 100644 --- a/src/Client.js +++ b/src/Client.js @@ -73,9 +73,7 @@ class Client extends EventEmitter { if (channel) this.channel.updateCh(this); this.channel = this.server.rooms.get(_id); - if (!this.user.hasFlag("hidden", true)) { - this.channel.join(this); - } + this.channel.join(this); } else { let room = new Channel(this.server, _id, settings); this.server.rooms.set(_id, room); @@ -112,6 +110,7 @@ class Client extends EventEmitter { } destroy() { + this.user.stopFlagEvents(); this.ws.close(); if (this.channel) { this.channel.emit("bye", this); diff --git a/src/Message.js b/src/Message.js index f00d773..c4db196 100644 --- a/src/Message.js +++ b/src/Message.js @@ -66,14 +66,28 @@ module.exports = (cl) => { }); cl.on("m", (msg, admin) => { - if (!cl.hasOwnProperty('channel')) return; + // nobody will see our cursor if we're not somewhere + if (!('channel' in cl)) return; + + // check against cursor rate limit if (!cl.quotas.cursor.attempt() && !admin) return; - if (!(cl.channel && cl.participantId)) return; + + // if we are nobody, we don't have a cursor + if (!cl.participantId) return; + + // no values? null, not undefined if (!msg.hasOwnProperty("x")) msg.x = null; if (!msg.hasOwnProperty("y")) msg.y = null; if (isNaN(parseFloat(msg.x))) msg.x = null; if (isNaN(parseFloat(msg.y))) msg.y = null; - cl.channel.emit("m", cl, msg.x, msg.y); + + let m = { + p: cl.participantId, + x: msg.x, + y: msg.y + } + + cl.channel.emit("m", m); }); cl.on("chown", (msg, admin) => { @@ -128,7 +142,7 @@ module.exports = (cl) => { if (!(cl.user._id == cl.channel.crown.userId)) return; } if (!msg.hasOwnProperty("set") || !msg.set) msg.set = new RoomSettings(cl.channel.settings, 'user'); - cl.channel.settings.changeSettings(msg.set); + cl.channel.settings.changeSettings(msg.set, admin); cl.channel.updateCh(); }); @@ -312,6 +326,7 @@ module.exports = (cl) => { try { let ch = cl.server.rooms.get(msg._id); ch.flags[msg.key] = msg.value; + ch.emit('flag ' + msg.key, msg.value); } catch(err) { console.error(err); } @@ -358,4 +373,18 @@ module.exports = (cl) => { } } }); + + cl.on('channel message', (msg, admin) => { + if (!admin) return; + + if (!msg.hasOwnProperty('msg')) return; + if (typeof msg.msg != 'object') return; + + if (!cl.channel) return; + if (!msg.hasOwnProperty('_id')) msg._id = cl.channel._id; + + let ch = cl.server.rooms.get(msg._id); + if (!ch) return; + ch.emit(msg.m, msg); + }); } diff --git a/src/RoomSettings.js b/src/RoomSettings.js index 0e391b3..963b087 100644 --- a/src/RoomSettings.js +++ b/src/RoomSettings.js @@ -126,9 +126,9 @@ class RoomSettings { }); } - static changeSettings(set) { + static changeSettings(set, admin) { Object.keys(set).forEach(key => { - if (RoomSettings.allowedProperties[key].allowedChange) { + if (RoomSettings.allowedProperties[key].allowedChange || admin == true) { set[key] = RoomSettings.verifyPropertyType(key, set[key], RoomSettings.allowedProperties[key].type); } }); diff --git a/src/Server.js b/src/Server.js index c79ad12..dbc00fa 100644 --- a/src/Server.js +++ b/src/Server.js @@ -86,7 +86,8 @@ class Server extends EventEmitter { "sudo", "subscribe to admin stream", "unsubscribe from admin stream", - "data" + "data", + "channel message" ]; this.welcome_motd = config.motd || "You agree to read this message."; @@ -126,6 +127,13 @@ class Server extends EventEmitter { return this.connections.get(id); } + getClientByParticipantID(id) { + for (let cl of Array.from(this.connections.values())) { + if (cl.participantID == id) return cl; + } + return null; + } + getAllClientsByUserID(_id) { let out = []; for (let cl of Array.from(this.connections.values())) { diff --git a/src/User.js b/src/User.js index cd2fe98..507dd09 100644 --- a/src/User.js +++ b/src/User.js @@ -36,7 +36,6 @@ class User { this.cl.server.specialIntervals[this._id] = {}; } if (this.hasFlag('rainbow', true)) { - console.log('rainbow on for ' + this._id); if (!this.cl.server.specialIntervals[this._id].hasOwnProperty('rainbow')) { let h = Math.floor(Math.random() * 360); let s = 50; @@ -65,16 +64,23 @@ class User { Database.updateUser(this._id, this); this.cl.channel.updateParticipant(this._id, this); - }, 1000/15); + }, 1000 / 15); } } else if (this.hasFlag('rainbow', false)) { - console.log('rainbow off for ' + this._id); - clearInterval(this.cl.server.specialIntervals[this._id].rainbow); + this.stopFlagEvents(); } } stopFlagEvents() { - clearInterval(this.cl.server.specialIntervals[this._id].rainbow); + let ints = this.cl.server.specialIntervals[this._id]; + if (!ints) { + this.cl.server.specialIntervals[this._id] = {}; + ints = this.cl.server.specialIntervals[this._id]; + } + if ('rainbow' in ints) { + clearInterval(this.cl.server.specialIntervals[this._id].rainbow); + delete this.cl.server.specialIntervals[this._id].rainbow; + } } hasFlag(flag, val) { @@ -82,6 +88,12 @@ class User { return this.flags.hasOwnProperty(flag) && this.flags[flag] == val; } + setFlag(flag, val) { + if (typeof(this.flags[flag]) == 'undefined') { + this.flags[flag] = val; + } + } + static updateUserModel(cl, user) { let u2 = new User(cl, user); if (typeof(u2) == 'undefined') return;