diff --git a/lib/channel-new.js b/lib/channel-new.js index 3f5e258d..4d5c58e7 100644 --- a/lib/channel-new.js +++ b/lib/channel-new.js @@ -5,6 +5,7 @@ var Filter = require("./filter").Filter; var Logger = require("./logger"); var AsyncQueue = require("./asyncqueue"); var MakeEmitter = require("./emitter"); +var InfoGetter = require("./get-info"); var fs = require("fs"); var path = require("path"); @@ -30,6 +31,7 @@ function Channel(name) { self.users = []; self.mutedUsers = new util.Set(); self.playlist = new Playlist(self); + self.plmeta = { count: 0, time: "00:00:00" }; self.plqueue = new AsyncQueue(); // For synchronizing playlist actions self.drinks = 0; self.leader = null; @@ -117,6 +119,15 @@ function Channel(name) { }); }; +Channel.prototype.isMuted = function (name) { + return this.mutedUsers.contains(name.toLowerCase()) || + this.mutedUsers.contains("[shadow]" + name.toLowerCase()); +}; + +Channel.prototype.isShadowMuted = function (name) { + return this.mutedUsers.contains("[shadow]" + name.toLowerCase()); +}; + Channel.prototype.mutedUsers = function () { var self = this; return self.users.filter(function (u) { @@ -212,6 +223,7 @@ Channel.prototype.loadState = function () { if ("playlist" in data) { self.playlist.load(data.playlist, function () { self.sendPlaylist(self.users); + self.updatePlaylistMeta(); self.sendPlaylistMeta(self.users); self.playlist.startPlayback(data.playlist.time); }); @@ -455,11 +467,9 @@ Channel.prototype.join = function (user, password) { user.whenLoggedIn(function () { var lname = user.name.toLowerCase(); for (var i = 0; i < self.users.length; i++) { - if (self.users[i] === user) { - Logger.errlog.log("Wat: join() called on user already in channel"); - break; + if (self.users[i] !== user) { + self.users[i].kick("Duplicate login"); } - self.users[i].kick("Duplicate login"); } self.getRank(user.name, function (err, rank) { @@ -474,7 +484,7 @@ Channel.prototype.join = function (user, password) { } user.socket.emit("rank", user.rank); - self.sendUserJoin(self.users); + self.sendUserJoin(self.users, user); }); }); @@ -500,6 +510,7 @@ Channel.prototype.join = function (user, password) { * Cleans up and sends appropriate updates to other users */ Channel.prototype.part = function (user) { + var self = this; user.channel = null; // Clear poll vote @@ -602,7 +613,7 @@ Channel.prototype.cacheMedia = function (media) { /** * Attempts to ban a user by name */ -Channel.prototype.tryNameBan = function (actor, name, reason) { +Channel.prototype.handleNameBan = function (actor, name, reason) { var self = this; if (!self.hasPermission(actor, "ban")) { return false; @@ -671,7 +682,7 @@ Channel.prototype.tryNameBan = function (actor, name, reason) { /** * Removes a name ban */ -Channel.prototype.tryUnbanName = function (actor, name) { +Channel.prototype.handleUnbanName = function (actor, name) { if (!this.hasPermission(actor, "ban")) { return; } @@ -691,7 +702,7 @@ Channel.prototype.tryUnbanName = function (actor, name) { /** * Bans all IP addresses associated with a username */ -Channel.prototype.tryBanAllIP = function (actor, name, reason, range) { +Channel.prototype.handleBanAllIP = function (actor, name, reason, range) { var self = this; if (!self.hasPermission(actor, "ban")) { return; @@ -730,7 +741,7 @@ Channel.prototype.tryBanAllIP = function (actor, name, reason, range) { /** * Bans an individual IP */ -Channel.prototype.tryBanIP = function (actor, ip, name, reason, range) { +Channel.prototype.banIP = function (actor, ip, name, reason, range) { if (range) { ip = ip.replace(/(\d+)\.(\d+)\.(\d+)\.(\d+)/, "$1.$2.$3"); } @@ -789,7 +800,7 @@ Channel.prototype.tryBanIP = function (actor, ip, name, reason, range) { /** * Removes an IP ban */ -Channel.prototype.unbanIP = function (actor, ip) { +Channel.prototype.handleUnbanIP = function (actor, ip) { if (!this.hasPermission(actor, "ban")) { return; } @@ -861,6 +872,40 @@ Channel.prototype.sendChatFilters = function (users) { }); }; +/** + * Sends the current poll + */ +Channel.prototype.sendPoll = function (users, sendNew) { + var self = this; + if (!self.poll) { + return; + } + + sendNew = sendNew || false; + var msg = sendNew ? "newPoll" : "updatePoll"; + + var obscured = self.poll.packupdate(true); + var unobscured = self.poll.packupdate(false); + + users.forEach(function (u) { + if (self.hasPermission(u, "viewpollresults")) { + u.socket.emit(msg, unobscured); + } else { + u.socket.emit(msg, obscured); + } + }); +}; + +/** + * Sends the channel permissions + */ +Channel.prototype.sendPermissions = function (users) { + var perms = this.permissions; + users.forEach(function (u) { + u.socket.emit("setPermissions", perms); + }); +}; + /** * Sends the playlist */ @@ -934,6 +979,16 @@ Channel.prototype.sendMediaUpdate = function (users) { } }; +/** + * Sends the drink count + */ +Channel.prototype.sendDrinkCount = function (users) { + var drinks = this.drinks; + users.forEach(function (u) { + u.socket.emit("drinkCount", drinks); + }); +}; + /** * Send the userlist */ @@ -1018,11 +1073,11 @@ Channel.prototype.sendUserJoin = function (users, user) { return; } - if (self.mutedUsers.contains("[shadow]"+user.name.toLowerCase())) { + if (self.isShadowMuted(user.name)) { user.meta.muted = true; user.meta.shadowmuted = true; user.meta.icon = "icon-volume-off"; - } else if (self.mutedUsers.contains(user.name.toLowerCase())) { + } else if (self.isMuted(user.name)) { user.meta.muted = true; user.meta.shadowmuted = false; user.meta.icon = "icon-volume-off"; @@ -1063,6 +1118,19 @@ Channel.prototype.sendUserJoin = function (users, user) { }); }; +/** + * Sends a notification that a user left + */ +Channel.prototype.sendUserLeave = function (users, user) { + var data = { + name: user.name + }; + + users.forEach(function (u) { + u.socket.emit("userLeave", data); + }); +}; + /** * Sends a poll notification */ @@ -1221,7 +1289,7 @@ Channel.prototype.handleQueue = function (user, data) { } // Verify the user has permission to add livestreams, if relevant - if (isLive(type) && !this.hasPermission(user, "playlistaddlive")) { + if (util.isLive(type) && !this.hasPermission(user, "playlistaddlive")) { user.socket.emit("queueFail", { msg: "You don't have permission to add livestreams", link: link @@ -1282,6 +1350,7 @@ Channel.prototype.handleQueue = function (user, data) { maxlength: this.hasPermission(user, "exceedmaxlength") ? 0 : this.opts.maxlength }, function (err, media) { if (err) { + console.log(err); user.socket.emit("queueFail", { msg: err, link: link @@ -1315,7 +1384,7 @@ Channel.prototype.addMedia = function (data, callback) { } if (data.pos === "end") { - data.pos === "append"; + data.pos = "append"; } var afterLookup = function (lock, shouldCache, media) { @@ -1346,6 +1415,7 @@ Channel.prototype.addMedia = function (data, callback) { u.socket.emit("queue", packet); }); + self.updatePlaylistMeta(); self.sendPlaylistMeta(self.users); if (shouldCache) { @@ -1360,7 +1430,7 @@ Channel.prototype.addMedia = function (data, callback) { if (data.type !== "cu" && typeof data.title === "string") { self.plqueue.queue(function (lock) { var m = new Media(data.id, data.title, data.seconds, data.type); - afterData(lock, false, m); + afterLookup(lock, false, m); }); return; } @@ -1392,7 +1462,7 @@ Channel.prototype.addMedia = function (data, callback) { }; for (var i = 0; i < vids.length; i++) { - afterData(dummy, true, vids[i]); + afterLookup(dummy, true, vids[i]); } lock.release(); @@ -1411,7 +1481,7 @@ Channel.prototype.addMedia = function (data, callback) { return; } - afterData(lock, false, media); + afterLookup(lock, false, media); }); }); return; @@ -1435,7 +1505,7 @@ Channel.prototype.addMedia = function (data, callback) { return; } - afterData(lock, true, media); + afterLookup(lock, true, media); }); }; @@ -1452,11 +1522,13 @@ Channel.prototype.addMedia = function (data, callback) { lock.release(); return; } - }); - if (item !== null) { - afterData(lock, true, item); - } + if (item !== null) { + afterLookup(lock, true, item); + } else { + lookupNewMedia(); + } + }); }); }; @@ -2622,4 +2694,13 @@ Channel.prototype.readLog = function (filterIp, callback) { }); }; +/** + * Broadcasts a message to the entire channel + */ +Channel.prototype.sendAll = function (msg, data) { + this.users.forEach(function (u) { + u.socket.emit(msg, data); + }); +}; + module.exports = Channel; diff --git a/lib/emitter.js b/lib/emitter.js index 05654beb..7670cbde 100644 --- a/lib/emitter.js +++ b/lib/emitter.js @@ -34,7 +34,10 @@ function MakeEmitter(obj) { args.shift(); handlers.forEach(function (handler) { - handler.fn.apply(self, args); + setImmediate(function () { + handler.fn.apply(self, args); + }); + if (handler.remove) { var i = self.__evHandlers[ev].indexOf(handler); if (i >= 0) { diff --git a/lib/playlist.js b/lib/playlist.js index 4d590b5c..d1f2bc90 100644 --- a/lib/playlist.js +++ b/lib/playlist.js @@ -69,7 +69,7 @@ function Playlist(chan) { pl.die(); return; } - chan.onVideoChange(); + chan.resetVideo(); chan.sendAll("setCurrent", pl.current.uid); chan.sendAll("changeMedia", m.fullupdate()); }); @@ -78,7 +78,8 @@ function Playlist(chan) { pl.die(); return; } - chan.broadcastPlaylistMeta(); + chan.updatePlaylistMeta(); + chan.sendPlaylistMeta(chan.users); chan.sendAll("delete", { uid: item.uid }); diff --git a/lib/user.js b/lib/user.js index d4fc98fc..d566b94f 100644 --- a/lib/user.js +++ b/lib/user.js @@ -2,6 +2,8 @@ var Logger = require("./logger"); var Server = require("./server"); var util = require("./utilities"); var MakeEmitter = require("./emitter"); +var db = require("./database"); +var InfoGetter = require("./get-info"); function User(socket) { var self = this; @@ -33,6 +35,24 @@ function User(socket) { self.initChannelCallbacks(); }); + self.socket.on("login", function (data) { + data = (typeof data === "object") ? data : {}; + + var name = data.name; + if (typeof name !== "string") { + return; + } + + var pw = data.pw || ""; + if (typeof pw !== "string") { + pw = ""; + } + + if (!pw) { + self.guestLogin(name); + } + }); + var announcement = Server.getServer().announcement; if (announcement != null) { self.socket.emit("announcement", announcement); @@ -148,7 +168,7 @@ User.prototype.initChannelCallbacks = function () { } if (self.inChannel()) { - self.channel.leave(self); + self.channel.part(self); } }); diff --git a/lib/utilities.js b/lib/utilities.js index f076c735..ed4f078b 100644 --- a/lib/utilities.js +++ b/lib/utilities.js @@ -192,5 +192,20 @@ module.exports = { } }, + isLive: function (type) { + switch (type) { + case "li": + case "tw": + case "jt": + case "us": + case "rt": + case "cu": + case "jw": + return true; + default: + return false; + } + }, + Set: Set }; diff --git a/www/assets/js/ui.js b/www/assets/js/ui.js index 26ac9ca8..3a063ed2 100644 --- a/www/assets/js/ui.js +++ b/www/assets/js/ui.js @@ -95,6 +95,14 @@ $("#usercount").mouseleave(function () { $("#messagebuffer").mouseenter(function() { SCROLLCHAT = false; }); $("#messagebuffer").mouseleave(function() { SCROLLCHAT = true; }); +$("#guestname").keydown(function (ev) { + if (ev.keyCode === 13) { + socket.emit("login", { + name: $("#guestname").val() + }); + } +}); + $("#chatline").keydown(function(ev) { // Enter/return if(ev.keyCode == 13) {