Start working on emotes
This commit is contained in:
parent
0f9bfe1429
commit
53138fe1f0
154
lib/channel.js
154
lib/channel.js
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -32,7 +32,8 @@ var CHANNEL = {
|
|||
motd: "",
|
||||
motd_text: "",
|
||||
name: false,
|
||||
usercount: 0
|
||||
usercount: 0,
|
||||
emotes: []
|
||||
};
|
||||
|
||||
var PLAYER = false;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue