Start working on emotes

This commit is contained in:
calzoneman 2014-02-09 23:53:46 -06:00
parent 0f9bfe1429
commit 53138fe1f0
5 changed files with 209 additions and 2 deletions

View File

@ -103,6 +103,7 @@ function Channel(name) {
html: "" // Filtered MOTD text (XSS removed; \n replaced by <br>)
};
self.filters = DEFAULT_FILTERS;
self.emotes = [];
self.logger = new Logger.Logger(path.join(__dirname, "../chanlogs",
self.uniqueName + ".log"));
self.css = ""; // Up to 20KB of inline CSS
@ -264,6 +265,15 @@ Channel.prototype.loadState = function () {
}
}
// Emotes
if ("emotes" in data) {
data.emotes.forEach(function (e) {
self.emotes.push(e);
});
self.updateEmote({ name: ":test:", source: ":test:", image: "http://imgs.xkcd.com/comics/mobile_marketing.png" });
}
// MOTD
if ("motd" in data) {
self.motd = {
@ -315,6 +325,7 @@ Channel.prototype.saveState = function () {
opts: self.opts,
permissions: self.permissions,
filters: filters,
emotes: self.emotes,
motd: self.motd,
playlistLock: self.playlistLock,
chatbuffer: self.chatbuffer,
@ -555,6 +566,7 @@ Channel.prototype.join = function (user) {
self.sendMediaUpdate([user]);
self.sendPlaylistLock([user]);
self.sendUserlist([user]);
self.sendEmoteList([user]);
self.sendRecentChat([user]);
self.sendCSSJS([user]);
self.sendPoll([user]);
@ -1013,6 +1025,16 @@ Channel.prototype.sendChatFilters = function (users) {
});
};
/**
* Sends the emote list
*/
Channel.prototype.sendEmoteList = function (users) {
var self = this;
users.forEach(function (u) {
u.socket.emit("emoteList", self.emotes);
});
};
/**
* Sends the channel permissions
*/
@ -2444,6 +2466,138 @@ Channel.prototype.handleMoveFilter = function (user, data) {
this.moveFilter(data.from, data.to);
};
/**
* Imports a list of emotes, replacing the current list
*/
Channel.prototype.importEmotes = function (emotes) {
this.emotes = emotes;
this.sendEmoteList(this.users);
};
/**
* Handles a user message to import a list of emotes
*/
Channel.prototype.handleImportEmotes = function (user, data) {
if (!this.hasPermission(user, "emoteimport")) {
return;
}
if (!(data instanceof Array)) {
return;
}
this.emotes = data.map(this.validateEmote.bind(this))
.filter(function (f) { return f !== false; });
this.sendEmoteList(this.users);
};
/**
* Validates data for an emote
*/
Channel.prototype.validateEmote = function (f) {
if (typeof f.source !== "string" || typeof f.image !== "string") {
return false;
}
if (typeof f.name !== "string") {
f.name = f.source;
}
f.image = f.image.substring(0, 1000);
f.image = XSS.sanitizeText(f.image);
try {
new RegExp(f.regex, "gi");
} catch (e) {
return false;
}
return f;
};
/**
* Updates an emote, or adds a new one if the emote does not exist
*/
Channel.prototype.updateEmote = function (emote) {
var self = this;
if (!emote.name) {
emote.name = emote.source;
}
var found = false;
for (var i = 0; i < self.emotes.length; i++) {
if (self.emotes[i].name === emote.name) {
found = true;
self.emotes[i] = emote;
break;
}
}
if (!found) {
self.emotes.push(emote);
}
self.users.forEach(function (u) {
u.socket.emit("updateEmote", emote);
});
};
/**
* Handles a user message to update an emote
*/
Channel.prototype.handleUpdateEmote = function (user, f) {
if (!this.hasPermission(user, "emoteedit")) {
user.kick("Attempted updateEmote with insufficient permission");
return;
}
var emote = this.validateEmote(f);
if (!emote) {
return;
}
this.logger.log("[mod] " + user.name + " updated emote: " + f.name + " -> " +
f.image);
this.updateEmote(emote);
};
/**
* Removes an emote
*/
Channel.prototype.removeEmote = function (emote) {
var self = this;
for (var i = 0; i < self.emotes.length; i++) {
if (self.emotes[i].name === emote.name) {
self.emotes.splice(i, 1);
self.users.forEach(function (u) {
u.socket.emit("deleteEmote", emote);
});
break;
}
}
};
/**
* Handles a user message to delete an emote
*/
Channel.prototype.handleRemoveEmote = function (user, f) {
if (!this.hasPermission(user, "emoteedit")) {
user.kick("Attempted removeEmote with insufficient permission");
return;
}
if (typeof f.name !== "string") {
return;
}
this.logger.log("[mod] " + user.name + " removed emote: " + f.name);
this.removeFilter(f);
};
/**
* Handles a user message to change the channel permissions
*/

View File

@ -1032,7 +1032,31 @@ Callbacks = {
}
}
}
},
emoteList: function (data) {
loadEmotes(data);
},
updateEmote: function (data) {
data.regex = new RegExp(data.source, "gi");
var found = false;
for (var i = 0; i < CHANNEL.emotes.length; i++) {
if (CHANNEL.emotes[i].name === data.name) {
found = true;
CHANNEL.emotes[i] = data;
break;
}
}
if (!found) {
CHANNEL.emotes.push(data);
}
},
deleteEmote: function (data) {
},
}
var SOCKET_DEBUG = true;

View File

@ -32,7 +32,8 @@ var CHANNEL = {
motd: "",
motd_text: "",
name: false,
usercount: 0
usercount: 0,
emotes: []
};
var PLAYER = false;

View File

@ -1270,6 +1270,8 @@ function formatChatMessage(data) {
if (data.meta.forceShowName)
skip = false;
data.msg = execEmotes(data.msg);
LASTCHATNAME = data.username;
LASTCHATTIME = data.time;
var div = $("<div/>");
@ -2180,3 +2182,24 @@ function formatUserPlaylistList() {
});
});
}
function loadEmotes(data) {
CHANNEL.emotes = [];
data.forEach(function (e) {
e.regex = new RegExp(e.source, "gi");
CHANNEL.emotes.push(e);
});
}
function execEmotes(msg) {
if (USEROPTS.no_emotes) {
return msg;
}
CHANNEL.emotes.forEach(function (e) {
msg = msg.replace(e.regex, '<img class="channel-emote" src="' +
e.image + '" title="' + e.name + '">');
});
return msg;
}

View File

@ -483,3 +483,8 @@ li.ui-sortable-helper, li.ui-sortable-placeholder + li.queue_entry {
border-top-left-radius: 0;
border-top-right-radius: 0;
}
.channel-emote {
max-width: 200px;
max-height: 200px;
}