tokebot/lib/eventhandlers.js
2021-12-06 19:59:30 -05:00

1149 lines
38 KiB
JavaScript

"use strict";
const path = require("path");
const fs = require("fs");
const ent = require("html-entities").AllHtmlEntities;
const C = require("cli-color");
const chatcmd = require("./chatcommands.js");
const utils = require("./utils.js");
const strings = require("./strings.js");
/**
* Binds event handlers to the socket and gives each one easy access to the Bot.
*
* @param {Bot} bot Bot object
* @param {Object} socket Socket
* @param {Object} config Bot configuration object
*/
function setHandlers(bot, socket, config) {
if (socket._callbacks.length > 2) return false;
bot.logger.debug(strings.format(bot, "DBG_SETTING_HANDLERS"));
socket.on("addUser", function(data) {
var now = Date.now();
data["lastRoomtimeCheck"] = now;
data["timeWentAFK"] = -1;
data["joinTime"] = now;
if (bot.userRankDBCheck(data.rank)) {
bot.db.run("userJoin", [data.name], function(res) {
if (bot.cfg.moderation.notifyNewUser && res && res.rowCount > 0 && res.rows[0].joins <= 1 && !bot.userIsBot(data.name) && data.rank <= bot.RANKS.USER) {
bot.broadcastModPM(strings.format(bot, "NEW_USER_JOIN", [data.name]));
}
});
}
let joinLog = "";
if (data.meta) {
if (data.meta.hasOwnProperty("aliases")) {
let i = 0,
al = data.meta.aliases,
alreadyDisallowed = false;
for (;i < al.length; i++) {
if (al[i] === data.name) {
utils.unsortedRemove(al, i);
i--;
} else if (bot.cfg.moderation.autoDisallow && !alreadyDisallowed && bot.disallowed(al[i])) {
alreadyDisallowed = true;
bot.disallowUser(data.name);
}
}
if (data.meta.aliases.length > 0) {
joinLog = strings.format(bot, "USER_JOINED_ROOM_ALIASES", [utils.colorUsername(bot, data), data.meta.aliases.join(", ")]);
}
}
if (data.meta.afk) {
data["timeWentAFK"] = now;
}
if (data.meta.hasOwnProperty("ip")) {
let ipMatches = bot.matchSubnet(data.meta.ip, true);
if (ipMatches.length > 0) {
let msg = strings.format(bot, "SUBNET_MATCH", [data.name, ipMatches.join(", ")]);
if (bot.cfg.moderation.notifyBannedSubnets)
bot.broadcastModPM(msg);
if (bot.cfg.moderation.autoShadowmuteOnSubnetMatch)
bot.muteUser(data.name, true);
bot.logger.mod(msg + " (" + data.meta.ip + ")");
}
}
}
if (data.name) {
if (joinLog === "") joinLog = strings.format(bot, "USER_JOINED_ROOM", [utils.colorUsername(bot, data)]);
if (data.meta && data.meta.ip) {
joinLog += C.blackBright(" (ip: "+data.meta.ip+")");
}
bot.logger.log(joinLog);
}
if (data.profile) {
let img = data.profile.image.toLowerCase();
if (img && img.trim() !== "" && bot.cfg.moderation.notifyBlacklistedAvatar) {
let bl = bot.cfg.misc.blacklistedAvatarHosts, i = 0,
host = utils.getHostname(img);
for (; i < bl.length; i++) {
if (bl[i].toLowerCase() === host) {
bot.sendPM(data.name, strings.format(bot, "AVATAR_BLACKLIST"));
break;
}
}
}
}
bot.CHANNEL.users.push(data);
bot.setFlatSkiprate();
});
socket.on("announcement", function(data) {
bot.logger.cylog(strings.format(bot, "CY_ANNOUNCEMENT", [
data.title,
data.text,
data.from
]));
});
socket.on("banlist", function(data) {
bot.CHANNEL.banlist = data;
bot.logger.verbose(strings.format(bot, "RECV_BANLIST"));
bot.gettingBanList = false;
});
socket.on("banlistRemove", function(data) {
let bl = bot.CHANNEL.banlist,
tb = bot.settings.timeBans[bot.CHANNEL.room],
i = 0,
banObj = null;
for (; i < bl.length; i++) {
if (bl[i].id === data.id) {
bot.logger.mod(strings.format(bot, "UNBANNED", [bl[i].name, bl[i].id, bl[i].ip]));
banObj = bl.splice(i,1)[0];
break;
}
}
if (!banObj) return;
i = 0;
let _name = banObj.name.toLowerCase(),
changed = false;
for (;i < tb.length && !changed;i++) {
if (_name === tb[i].name.toLowerCase()) {
tb.splice(i,1);
changed = true;
}
}
if (changed) bot.writeSettings();
});
socket.on("cancelNeedPassword", function() {
bot.logger.verbose(strings.format(bot, "PWD_ACCEPTED"));
});
socket.on("changeMedia", function(media) {
bot.leadFinishingMedia = false;
clearTimeout(bot.timeouts.playingNext);
if (!media) {
bot.logger.media(strings.format(bot, "NO_VIDEO"));
bot.CHANNEL.currentMedia = null;
} else {
bot.CHANNEL.currentMedia = media;
bot.notifyVideoState();
if (bot.leader) {
bot.stopLeadTimer();
let timers = bot.timeouts;
clearTimeout(timers.changeMediaLead);
timers.changeMediaLead = setTimeout(()=>{
bot.startLeadTimer();
}, 2000);
}
}
cleanUpcomingUIDsFromBumpList();
bot.resetCurrentVidData();
if (bot.cfg.advanced.automaticChannelLog) bot.readChanLog();
bot.setProgTitle();
});
socket.on("channelRanks", function(data) {
if (!bot.first.grabbedChannelRanks) return;
bot.first.grabbedChannelRanks = false;
bot.logger.verbose(strings.format(bot, "RECV_RANKS"));
let ranks = [],
i = 0,
room = bot.CHANNEL.room.toLowerCase();
for (;i < data.length; i++) {
if (data[i].channel.toLowerCase() === room)
ranks.push({name: data[i].name, rank: data[i].rank});
}
bot.CHANNEL.rankList = ranks;
});
/*data: Object
{
meta: Object (can have modflair: int...)
msg: String
time: int (uses cytube's time which can be off a bit)
username: String
}*/
socket.on("chatMsg", function(data) {
//prevent backlogging messages
if (data.time < bot.started) return;
if (!data.msg) return;
var username = data.username;
let isInvalidUsername = !utils.isValidUserName(username);
let me = data.meta.action;
let user = null;
let isServer = false;
var decodedMsg = ent.decode(data.msg),
cleanMsg = ent.decode(utils.removeExcessWhitespace(utils.removeHtmlTags(data.msg))).trim(),
outputMsg = cleanMsg;
if (username === "[server]") { //ignore server join msg (sym)
isServer = true;
if (/[\w-]{1,20} joined/i.test(cleanMsg)) {
return
}
let split = cleanMsg.split(" ");
if (split.length > 1 && ~split[1].indexOf("banned")) {
bot.getBanList();
}
//<[voteskip]> Voteskip passed: 12/36 skipped; eligible voters: 36 = total (95) - AFK (50) - no permission (9); ratio = 0.325
} else if (username === "[voteskip]") {
bot.logger.media(data.msg);
return;
} else if (!isInvalidUsername) {
user = bot.getUser(username);
}
let isMuted = (user && (user.meta.muted || user.meta.smuted) && bot.cfg.chat.ignoreMutedUsers);
let cmdPart = "";
if (!isMuted && !bot.userIsBot(data.username)) {
if (cleanMsg.substr(0,1) === bot.trigger)
cmdPart = cleanMsg.substr(1);
else if (bot.cfg.chat.allowInlineCmd)
cmdPart = utils.inlineCmdCheck(bot.trigger, cleanMsg);
if (!me
&& cmdPart !== ""
&& user
&& cmdPart.length > 0) {
if (/^(((?:user)?emotecount)|(?:u?ec)|(?:top5emotes)|(?:top5emoteusers))/i.test(cmdPart) || !user || !bot.userRankDBCheck(user.rank)) {
outputMsg = utils.execEmotes(bot, cleanMsg);
} else {
outputMsg = utils.execEmotes(bot, cleanMsg, username);
}
try {
bot.logger.verbose(strings.format(bot, "COMMAND_ATTEMPT", [
utils.colorUsername(bot, user),
cmdPart
]));
chatcmd.exec(bot, user, cmdPart, false);
} catch (e) {
bot.logger.error(e.stack);
bot.sendPM(username, strings.format(bot, "COMMAND_RUNTIME_ERROR"));
return
}
} else if (username === bot.username || !user || !bot.userRankDBCheck(user.rank)) {
outputMsg = utils.execEmotes(bot, cleanMsg);
} else {
outputMsg = utils.execEmotes(bot, cleanMsg, username);
}
if (cmdPart === ""
&& !bot.getSavedUserData(username).quoteExempt
&& utils.isValidUserName(username)
&& user
&& bot.userRankDBCheck(user.rank)
&& cleanMsg.length >= bot.cfg.chat.minimumQuoteLength) {
let msg = cleanMsg;
if (me) msg = "/me " + msg;
bot.db.run("addNewChat", [username, data.time/1000, msg.substr(0,320)]);
}
}
if (bot.cfg.interface.colorUsernames) {
if (user && user.rank > 1 && (!data.hasOwnProperty("meta") || !data.meta.hasOwnProperty("modflair"))) {
username = C.whiteBright(username);
} else {
if (username.indexOf("[") >= 0)
username = utils.colorUsername(bot, username);
else if (!user)
username = C.blackBright(username);
else
username = utils.colorUsername(bot, user);
}
}
if (isServer) {
bot.logger.cylog(outputMsg);
} else {
if (me) {
bot.logger.log(C.blackBright("<") + username + " " + C.blackBright(outputMsg + "> "));
} else {
let endBracket = "> ";
if (isMuted && bot.cfg.interface.indicateMutedUsers) endBracket = " (MUTED)" + endBracket;
bot.logger.log(C.blackBright("<") + username + C.blackBright(endBracket) + outputMsg);
}
}
});
socket.on("channelCSSJS", function(data) {
if (bot.cfg.advanced.automaticChannelLog) bot.readChanLog();
});
socket.on("channelNotRegistered", function() {
bot.logger.info(strings.format(bot, "CHANNEL_NOT_REGISTERED"));
});
socket.on("channelOpts", function(opts) {
if (bot.first.grabbedChannelOpts) {
bot.first.grabbedChannelOpts = false;
} else {
var old = bot.CHANNEL.opts;
var changed = [];
for (var i in old) {
if (opts.hasOwnProperty(i) && !utils.compareObjects(old[i], opts[i]) && old[i] !== opts[i]) {
changed.push(i);
}
}
if (changed.length > 0) {
var changedStr = "";
for (var i = 0; i < changed.length; i++) {
var oldopt = old[changed[i]],
newopt = opts[changed[i]];
if (typeof(oldopt) === "object") oldopt = JSON.stringify(oldopt);
if (typeof(newopt) === "object") newopt = JSON.stringify(newopt);
if (changed[i].toLowerCase() === "voteskip_ratio") {
bot.setFlatSkiprate();
if (bot.cfg.moderation.notifySkipRateChange && !bot.settings.flatSkiprate.managing) {
bot.sendChatMsg(strings.format(bot, "SKIPRATE_CHANGE", [(oldopt*100), (newopt*100)]));
}
}
changedStr += changed[i] + " ("+oldopt+" => "+newopt+")";
if (i < changed.length - 1) changedStr += ", ";
}
bot.logger.mod(strings.format(bot, "CHANNEL_OPTS_CHANGED", [changedStr]));
}
}
bot.CHANNEL.opts = opts;
});
socket.on("closePoll", function() {
const POLL = bot.CHANNEL.poll;
if (!POLL.active) return;
POLL.active = false;
let timeOpen = Date.now() - POLL.timestamp,
threeMins = (timeOpen >= 175000 && timeOpen < 185000 && POLL.options.length > 1 && bot.cfg.chat.announcePollResults);
var options = "";
var embed = null;
var title = POLL.title;
if (bot.DiscordBot && bot.cfg.discord.sendPollResultMessages && bot.cfg.discord.pollResultChannelID.trim() !== "") {
embed = bot.DiscordBot.createEmbed()
.setColor(bot.cfg.discord.pollClosedColor)
.setAuthor(strings.format(bot, "DISCORD_EMBED_CLOSE_POLL_AUTHOR").substr(0,256), bot.cfg.discord.iconUrl, 'https://'+bot.cfg.connection.hostname+'/r/' + bot.CHANNEL.room)
.setTitle(title.substr(0,256))
.setDescription(strings.format(bot, "DISCORD_EMBED_POLL_TIMESTAMP", [
POLL.initiator,
utils.getUTCTimestamp(POLL.timestamp)
]).substr(0,256))
.setTimestamp();
}
let bestOpt = {opt: POLL.options[0], count: POLL.counts[0]},
total = 0,
tie = false;
for (var i = 0; i < POLL.options.length; i++) {
var count = POLL.counts[i],
option = ent.decode(POLL.options[i].trim());
total += count;
if (count > bestOpt.count) {
bestOpt = {opt: option, count: count};
tie = false;
} else if (i > 0 && count === bestOpt.count) {
tie = true;
}
if (embed) {
var voteCount = count + " votes";
if (count > 0) voteCount += " (" + ((count/total)*100).toFixed(2) + "%)";
embed.addField(option.substr(0,256), voteCount, true);
}
options += "<[" + count + "] " + option + "> ";
}
if (embed) {
bot.DiscordBot.getChannel(bot.cfg.discord.pollResultChannelID).send(embed);
}
if (threeMins && total > 0) {
let resultStr = "",
percent = ((bestOpt.count/total)*100).toFixed(2) + "%";
if (!tie) resultStr = strings.format(bot, "POLL_CLOSED_RESULT", [title, bestOpt.opt, bestOpt.count, percent]);
else resultStr = strings.format(bot, "POLL_CLOSED_TIE", [title, bestOpt.count, percent]);
bot.sendChatMsg(resultStr);
}
bot.logger.mod(strings.format(bot, "POLL_CLOSED", [
utils.colorUsername(bot, POLL.initiator),
title,
options
]));
});
socket.on("connect", function() {
bot.hasConnectedBefore = true;
bot.logger.log(strings.format(bot, "CONNECT_SUCCESS", [bot.cfg.connection.hostname]));
bot.logger.info(strings.format(bot, "JOINING_ROOM", [bot.CHANNEL.room]));
socket.emit("joinChannel", {name: bot.CHANNEL.room});
if (!config.login.guest) {
socket.emit("login", {
name: config.login.username,
pw: config.login.password
});
}
bot.minuteTick();
bot.setupReadline();
});
socket.on("connect_error", function() {
if (bot.hasConnectedBefore) return;
bot.socketConnErrors++;
if (bot.socketConnErrors >= 3) {
bot.logger.error(strings.format(bot, "SOCKET_CONN_ERR"));
return;
}
});
socket.on("delete", function(data) {
var media = bot.getMediaIndex(data.uid);
if (media < 0) return false;
removeUIDFromBumpList(data.uid);
bot.CHANNEL.playlist.splice(media, 1);
if (bot.CHANNEL.playlist.length <= 0) {
bot.CHANNEL.currentMedia = null;
bot.logger.media(strings.format(bot, "NO_VIDEO"));
}
//bot.logger.debug(strings.format(bot, "DBG_REMOVEUID", [data.uid]));
bot.setProgTitle();
});
socket.on("deleteChatFilter", function(f) {
bot.logger.mod(strings.format(bot, "CHATFILTER_DELETE", [f.name]));
if (bot.cfg.advanced.automaticChannelLog) bot.readChanLog();
});
socket.on("disconnect", async function() {
if (bot.KICKED) return;
bot.logger.log(strings.format(bot, "DISCONNECTED"));
//bot.kill(strings.format(bot, "KILL_GENERIC_DISCONNECT"));
if (!bot.killed) {
bot.setProgTitle("(!DISCONNECTED!) | ");
bot.stopAllTimers(true);
await bot.updateUserRoomTimeAll();
bot.cleanState();
}
});
socket.on("emoteList", function(data) {
if (!bot.cfg.chat.parseEmotes) return;
bot.CHANNEL.emotes = [];
bot.CHANNEL.emoteMap = {};
bot.CHANNEL.badEmotes = [];
data.forEach(function (e) {
if (e.image && e.name) {
e.regex = new RegExp(e.source, "gi");
var _emote = {name:e.name, regex:e.regex};
bot.CHANNEL.emotes.push(_emote);
if (/\s/g.test(e.name)) {
// Emotes with spaces can't be hashmapped
bot.CHANNEL.badEmotes.push(_emote);
} else {
bot.CHANNEL.emoteMap[ent.encode(e.name)] = _emote;
}
} else {
bot.logger.error(strings.format(bot, "EMOTE_REJECTED", ["emoteList", JSON.stringify(e)]));
}
});
});
socket.on("error", function(err) {
bot.logger.error(strings.format(bot, "CONNECT_ERROR", [err]));
});
socket.on("kick", function(data) {
bot.KICKED = true;
var reason = data.reason ? " Reason: " + data.reason : "";
bot.logger.log(C.redBright("[KICKED] " + strings.format(bot, "KICKED", [reason])));
bot.kill("kicked", 10000);
});
socket.on("login", function(data) {
if (!data.success) {
bot.logger.error(strings.format(bot, "UNABLE_TO_LOGIN", [data.error]));
} else {
bot.guest = data.guest;
bot.username = data.name;
bot.logged_in = true;
bot.logger.info(strings.format(bot, "LOGIN_SUCCESS", [data.name]));
if (bot.cfg.misc.autoAFK === 1) bot.sendChatMsg("/afk", true, true);
bot.setProgTitle();
}
});
socket.on("mediaUpdate", function(data) {
if (!bot.CHANNEL.currentMedia) return;
bot.CHANNEL.currentMedia.currentTime = data.currentTime;
bot.CHANNEL.currentMedia.paused = data.paused;
bot.mediaUpdateTick(data);
});
socket.on("moveVideo", function(data) {
var index = bot.getMediaIndex(data.from);
if (index < 0) return false;
var mediaToMove = bot.CHANNEL.playlist.splice(index, 1)[0],
indexOfOtherMedia, otherMedia;
let bumping = bot.bumpStats.bumpingUIDs.shift();
let bumpedUIDs = bot.bumpStats.lastBumpedUIDs;
let i = bumpedUIDs.length-1;
let count = 0;
for (; i >= 0; i--) {
if (bumpedUIDs[i] === data.from) {
count++;
if ((count > 1 && bumping && bumping === data.from) || !bumping || bumping !== data.from)
bumpedUIDs.splice(i, 1);
}
}
if (data.after === "prepend") {
indexOfOtherMedia = -1;
otherMedia = null;
} else {
indexOfOtherMedia = bot.getMediaIndex(data.after);
otherMedia = bot.CHANNEL.playlist[indexOfOtherMedia];
}
++indexOfOtherMedia;
bot.CHANNEL.playlist.splice(indexOfOtherMedia, 0, mediaToMove);
if (indexOfOtherMedia === 0) ++indexOfOtherMedia;
if (data.after === "prepend") {
bot.logger.mod(strings.format(bot, "MEDIA_MOVE_TOP", [
mediaToMove.media.title,
(index+1),
indexOfOtherMedia
]));
} else {
bot.logger.mod(strings.format(bot, "MEDIA_MOVE_AFTER", [
mediaToMove.media.title,
otherMedia.media.title,
(index+1),
(indexOfOtherMedia+1)
]));
}
});
socket.on("needPassword", function(wrongpw) {
if (wrongpw) {
bot.logger.error(strings.format(bot, "WRONG_PWD", [bot.CHANNEL.room]));
bot.kill(strings.format(bot, "KILL_WRONG_PWD"));
} else {
bot.logger.verbose(strings.format(bot, "PWD_REQUIRED", [bot.CHANNEL.room]));
socket.emit("channelPassword", config.login.roomPassword);
}
});
socket.on("newPoll", function(poll) {
poll["active"] = true;
bot.CHANNEL.poll = poll;
var options = "";
var inProgress = false;
var embed = null;
var title = ent.decode(utils.removeExcessWhitespace(utils.removeHtmlTags(poll.title)));
bot.CHANNEL.poll.title = title;
if (bot.DiscordBot && bot.cfg.discord.sendPollResultMessages && bot.cfg.discord.pollResultChannelID.trim() !== "") {
embed = bot.DiscordBot.createEmbed()
.setColor(bot.cfg.discord.pollOpenedColor)
.setAuthor(strings.format(bot, "DISCORD_EMBED_NEW_POLL_AUTHOR").substr(0,256), bot.cfg.discord.iconUrl, 'https://'+bot.cfg.connection.hostname+'/r/' + bot.CHANNEL.room)
.setTitle(title.substr(0,256))
.setDescription(strings.format(bot, "DISCORD_EMBED_POLL_TIMESTAMP", [
poll.initiator,
utils.getUTCTimestamp(poll.timestamp)
]).substr(0,256))
.setTimestamp();
}
if ((new Date()).getTime() - poll.timestamp >= 4000) inProgress = true;
for (var i = 0; i < poll.options.length; i++) {
var option = ent.decode(utils.removeExcessWhitespace(utils.removeHtmlTags(poll.options[i]))),
count = poll.counts[i];
bot.CHANNEL.poll.options[i] = option;
if (!inProgress && ((typeof count === "string" && count !== "0?" && count !== "?") || count > 0)) inProgress = true;
if (embed) {
embed.addField(option.substr(0,256), count + " votes", true);
}
options += "<[" + count + "] " + option + "> ";
}
if (embed) {
if (inProgress) {
embed.author.name = strings.format(bot, "DISCORD_EMBED_POLL_INPROGRESS_AUTHOR").substr(0,256);
embed.setColor(bot.cfg.discord.pollInProgressColor);
}
bot.DiscordBot.getChannel(bot.cfg.discord.pollResultChannelID).send(embed);
}
var time = utils.getTimestamp(bot.useTwentyFourHourTime, poll.timestamp);
bot.logger.mod(strings.format(bot, "NEW_POLL", [
utils.colorUsername(bot, poll.initiator),
time,
title,
options
]));
});
socket.on("noflood", function(data) {
bot.logger.log(strings.format(bot, "NO_FLOOD", [
data.action,
data.msg
]));
});
socket.on("partitionChange", function(socketConfig) {
bot.logger.warn(strings.format(bot, "PARTITION_CHANGE"));
bot.logger.debug("socketConfig from partitionChange: " + JSON.stringify(socketConfig));
bot.changingPartition = true;
bot.hardReconnect(socketConfig);
});
/* example playlist info
{
"media":{
"id": String (vid ID),
"title": String,
"seconds": int,
"duration":"00:19", time string
"type":"yt",
"meta":{}
},
"uid": int (playlist ID)
"temp":true,
"queueby": String (person who added the media)
}
*/
socket.on("playlist", function(data) {
bot.CHANNEL.playlist = data;
bot.bumpStats.lastBumpedUIDs = [];
bot.bumpStats.bumpingUIDs = [];
bot.logger.verbose(strings.format(bot, "PLAYLIST_RECEIVED"));
if (bot.CHANNEL.playlist.length <= 0) {
bot.logger.media(strings.format(bot, "PLAYLIST_EMPTY"));
} else {
bot.cleanBlacklistedMedia();
}
bot.setProgTitle();
});
/*{
username: String, (sender)
msg: String,
meta: object,
time: cytube timestamp (int),
to: String (receiver)
}*/
socket.on("pm", function(data) {
let cleanMsg = ent.decode(utils.removeExcessWhitespace(utils.removeHtmlTags(data.msg))).trim();
if (data.to === bot.username) {
let sender = null;
if (~data.username.indexOf("[")) sender = data.username;
else sender = bot.getUser(data.username);
if (!sender) return;
bot.logger.info(strings.format(bot, "PM_RECV", [
utils.colorUsername(bot, sender),
cleanMsg
]));
let username = data.username;
let isInvalidUsername = !utils.isValidUserName(username);
let isMuted = (sender && (sender.meta.muted || sender.meta.smuted) && bot.cfg.chat.ignoreMutedUsers);
if (!isMuted && !bot.userIsBot(data.username)) {
let cmdPart = "";
if (cleanMsg.substr(0,1) === bot.trigger)
cmdPart = cleanMsg.substr(1);
else if (bot.cfg.chat.allowInlineCmd)
cmdPart = utils.inlineCmdCheck(bot.trigger, cleanMsg);
if (cmdPart !== "" && username !== bot.username && !isInvalidUsername && cmdPart.length > 0) {
try {
bot.logger.verbose(strings.format(bot, "COMMAND_ATTEMPT", [
utils.colorUsername(bot, sender),
cmdPart
]));
chatcmd.exec(bot, sender, cmdPart, true);
} catch (e) {
bot.logger.error(e.stack);
bot.sendPM(username, strings.format(bot, "COMMAND_RUNTIME_ERROR"));
return
}
}
}
} else {
bot.logger.info(strings.format(bot, "PM_SENT", [
utils.colorUsername(bot, data.to),
cleanMsg
]));
}
});
socket.on("queue", function(data) {
var media = data.item,
username = media.queueby;
if (username === "") username = "(anon)";
username = utils.colorUsername(bot, username);
if (data.after === "prepend") {
bot.CHANNEL.playlist.splice(0, 0, media);
bot.logger.media(strings.format(bot, "MEDIA_ADD_TOP", [
username,
media.media.title
]));
} else if (data.after === "append") {
bot.CHANNEL.playlist.push(media);
bot.logger.media(strings.format(bot, "MEDIA_ADD_BOTTOM", [
username,
media.media.title
]));
} else {
var after = bot.getMediaIndex(data.after);
if (after < 0) return;
bot.CHANNEL.playlist.splice(after+1, 0, media);
bot.logger.media(strings.format(bot, "MEDIA_ADD_POS", [
username,
media.media.title,
(after+2)
]));
}
if (bot.mediaIsBlacklisted(media)) {
if (bot.deleteVideo(media.uid)) {
let mediaStr = utils.formatLink(media.media.id, media.media.type, true);
if (media.queueby !== "")
bot.sendPM(media.queueby, strings.format(bot, "BLACKLIST_MSG", [mediaStr]));
//if (mediaStr !== "") bot.sendChatMsg("Deleted blacklisted video: " + mediaStr);
}
} else if (~bot.settings.userBlacklist.indexOf(media.queueby.toLowerCase())) {
bot.purgeUser(media.queueby);
bot.sendPM(media.queueby, strings.format(bot, "BLACKLIST_USER"));
}
});
socket.on("queueFail", function(data) {
bot.logger.error(strings.format(bot, "QUEUE_FAIL", [data.msg + " ["+data.link+"]"]));
});
socket.on("queueWarn", function(data) {
bot.logger.warn(strings.format(bot, "QUEUE_WARN", [data.msg]));
});
socket.on("rank", function(data) {
bot.rank = data;
bot.logger.verbose(strings.format(bot, "RANK_SET", [data]));
bot.getBanList();
bot.requestChannelRanks();
bot.setFlatSkiprate();
bot.setProgTitle();
});
socket.on("readChanLog", function(data) {
bot.logger.log(strings.format(bot, "CHANLOG_READING"));
if (data.success) {
var streamOpts = {
flags: 'w',
encoding: 'utf8',
fd: null,
mode: 0o660,
autoClose: true
};
var chanStream = fs.createWriteStream(path.join(bot.ROOTPATH, "logs", bot.CHANNEL.room, "chan.log"), streamOpts);
chanStream.end("" + data.data);
bot.logger.log(strings.format(bot, "CHANLOG_WRITTEN"));
} else {
bot.logger.error(strings.format(bot, "CHANLOG_ERROR"));
}
});
//https://github.com/calzoneman/sync/blob/a53f65a1d5529a592d7d1bd760f3cd70e157ec8b/www/js/callbacks.js#L1082
socket.on("removeEmote", function(data) {
bot.logger.mod(strings.format(bot, "EMOTE_REMOVE", [data.name]));
var found = -1;
for (var i = 0; i < bot.CHANNEL.emotes.length; i++) {
if (bot.CHANNEL.emotes[i].name === data.name) {
found = i;
break;
}
}
if (found !== -1) {
bot.CHANNEL.emotes.splice(i, 1);
delete bot.CHANNEL.emoteMap[data.name];
for (var i = 0; i < bot.CHANNEL.badEmotes.length; i++) {
if (bot.CHANNEL.badEmotes[i].name === data.name) {
bot.CHANNEL.badEmotes.splice(i, 1);
break;
}
}
}
});
//https://github.com/calzoneman/sync/blob/a53f65a1d5529a592d7d1bd760f3cd70e157ec8b/www/js/callbacks.js#L1030
socket.on("renameEmote", function(data) {
bot.logger.mod(strings.format(bot, "EMOTE_RENAME", [data.old, data.name]));
var badBefore = /\s/g.test(data.old);
var badAfter = /\s/g.test(data.name);
var oldName = data.old;
data.regex = new RegExp(data.source, "gi");
data = {name:data.name, regex:data.regex};
for (var i = 0; i < bot.CHANNEL.emotes.length; i++) {
if (bot.CHANNEL.emotes[i].name === oldName) {
bot.CHANNEL.emotes[i] = data;
break;
}
}
// Now bad
if(badAfter){
// But wasn't bad before: Add it to bad list
if(!badBefore){
bot.CHANNEL.badEmotes.push(data);
delete bot.CHANNEL.emoteMap[oldName];
}
// Was bad before too: Update
else {
for (var i = 0; i < bot.CHANNEL.badEmotes.length; i++) {
if (bot.CHANNEL.badEmotes[i].name === oldName) {
bot.CHANNEL.badEmotes[i] = data;
break;
}
}
}
}
// Not bad now
else {
// But was bad before: Drop from list
if(badBefore){
for (var i = 0; i < bot.CHANNEL.badEmotes.length; i++) {
if (bot.CHANNEL.badEmotes[i].name === oldName) {
bot.CHANNEL.badEmotes.splice(i, 1);
break;
}
}
} else {
delete bot.CHANNEL.emoteMap[oldName];
}
bot.CHANNEL.emoteMap[data.name] = data;
}
});
socket.on("setCurrent", function(uid) {
clearTimeout(bot.timeouts.playingNext);
if (bot.CHANNEL.currentUID === uid) return;
bot.CHANNEL.currentUID = uid;
});
socket.on("setLeader", function(name) {
bot.leader = false;
bot.stopLeadTimer();
if (name === "") {
bot.logger.mod(strings.format(bot, "LEADER_REMOVED", [bot.CHANNEL.leader]));
} else {
bot.logger.mod(strings.format(bot, "LEADER_GIVEN", [name]));
if (name === bot.username) {
bot.leader = true;
if (bot.seek.time >= 0) {
bot.sendVideoUpdate(bot.seek.time);
bot.seek.time = -1;
if (bot.seek.autoUnassign) {
bot.assignLeader("");
bot.seek.autoUnassign = false;
}
} else {
bot.startLeadTimer();
}
}
}
bot.CHANNEL.leader = name;
});
socket.on("setMotd", function(motd) {
if (bot.first.motdChange) {
bot.first.motdChange = false;
} else {
bot.logger.mod(strings.format(bot, "MOTD_CHANGED"));
}
});
socket.on("setPermissions", function(perms) {
if (!bot.first.grabbedPermissions)
bot.logger.mod(strings.format(bot, "CHANNEL_PERMS_UPDATED"));
bot.first.grabbedPermissions = false;
bot.CHANNEL.perms = perms;
bot.setFlatSkiprate();
});
socket.on("setPlaylistLocked", function(locked) {
bot.CHANNEL.playlistIsLocked = locked;
if (bot.first.playlistLock) {
bot.first.playlistLock = false;
if (locked)
bot.logger.media(strings.format(bot, "PLAYLIST_IS_LOCKED"));
else
bot.logger.media(strings.format(bot, "PLAYLIST_IS_UNLOCKED"));
} else {
if (locked)
bot.logger.media(strings.format(bot, "PLAYLIST_LOCKED"));
else
bot.logger.media(strings.format(bot, "PLAYLIST_UNLOCKED"));
}
bot.setProgTitle();
});
socket.on("setPlaylistMeta", function(data) {
bot.CHANNEL.playlistMeta = data;
if (bot.cfg.moderation.notifyLowPlaylistTime) {
let now = Date.now();
if (!bot.notifiedLowPlaylistTime && (now - bot.lastLowPlaylistNotification >= 300000) && bot.cfg.misc.lowPlaylistTime > data.rawTime) {
bot.notifiedLowPlaylistTime = true;
bot.lastLowPlaylistNotification = now;
bot.sendChatMsg(strings.format(bot, "PLAYLIST_LOW"));
} else if (bot.cfg.misc.lowPlaylistTime <= data.rawTime){
bot.notifiedLowPlaylistTime = false;
}
}
bot.logger.media(data.count + " videos in the playlist. [" + data.time + "]");
bot.setProgTitle();
});
socket.on("setTemp", function(data) {
var media = bot.getMedia(data.uid);
if (!media) return;
media.temp = data.temp;
});
socket.on("setUserMeta", function(data) {
var user = bot.getUser(data.name);
if (!user) return;
if (data.meta.hasOwnProperty("smuted") && data.meta.smuted !== user.meta.smuted) {
bot.logger.mod(data.name + " has been " + (!data.meta.smuted ? "un" : "") + "shadowmuted");
} else if (data.meta.hasOwnProperty("muted") && data.meta.muted !== user.meta.muted) {
bot.logger.mod(data.name + " has been " + (!data.meta.muted ? "un" : "") + "muted");
}
var now = new Date();
user["meta"] = data.meta;
if (data.meta) {
let setSkipRate = ()=>{
if ((bot.cfg.misc.autoAFK === 0 && user.name === bot.username) || user.name !== bot.username) {
bot.setFlatSkiprate();
}
};
if (data.meta.afk) {
user["timeWentAFK"] = now;
if (bot.cfg.misc.autoAFK === 2 && user.name === bot.username) {
bot.sendChatMsg("/afk", true, true);
} else {
setSkipRate();
}
} else {
if (bot.cfg.misc.autoAFK === 1 && user.name === bot.username) {
bot.sendChatMsg("/afk", true, true);
} else {
setSkipRate();
}
if (user["timeWentAFK"] > 0) {
var delta = now - user.timeWentAFK;
user.timeWentAFK = -1;
if (delta >= 3000 && bot.userRankDBCheck(user.rank)) {
bot.db.run("updateUserAfkTime", [delta, user.name]);
}
}
}
}
bot.setProgTitle();
});
socket.on("setUserProfile", function(data) {
var user = bot.getUser(data.name);
if (!user) return;
user.profile = data.profile;
});
socket.on("setUserRank", function(data) {
var user = bot.getUser(data.name),
oldRank = -1,
changedByUser = data.hasOwnProperty("userrank");
if (user) {
if (user.rank === data.rank) return;
oldRank = user.rank;
user.rank = data.rank;
}
if (data.name === bot.username) {
bot.handlePermissionChange();
}
var rankstr = data.rank;
if (changedByUser) {
var oldLabel = oldRank, newLabel = data.rank;
if (bot.cfg.rankNames.hasOwnProperty(oldRank))
oldLabel += " [" + bot.cfg.rankNames[oldRank] + "]";
if (bot.cfg.rankNames.hasOwnProperty(data.rank))
newLabel += " [" + bot.cfg.rankNames[data.rank] + "]";
rankstr += " (" + oldLabel + " -> " + newLabel + ")"
}
let i = 0,
nameFound = false,
rl = bot.CHANNEL.rankList;
for (;i < rl.length && !nameFound; i++) {
if (rl[i].name === data.name) {
nameFound = true;
if (data.rank < 2) {
rl.splice(i,1);
} else {
rl[i].rank = data.rank;
}
}
}
if (!nameFound) {
rl.push({name: data.name, rank: data.rank});
}
if (rankstr === data.rank) return;
if (changedByUser) {
let _name = user ? utils.colorUsername(bot, user) : data.name;
bot.logger.mod(strings.format(bot, "RANK_SET_USER", [
_name,
rankstr
]));
}
});
socket.on("spamFiltered", function(data) {
var reason = data.reason;
if (reason !== "NEW_USER_CHAT" && reason !== "NEW_USER_CHAT_LINK") reason = "SPAM_FILTERED";
bot.logger.error(strings.format(bot, reason));
});
socket.on("updateChatFilter", function(f) {
bot.logger.mod(strings.format(bot, "CHATFILTER_UPDATE", [f.name]));
if (bot.cfg.advanced.automaticChannelLog) bot.readChanLog();
});
//https://github.com/calzoneman/sync/blob/a53f65a1d5529a592d7d1bd760f3cd70e157ec8b/www/js/callbacks.js#L998
socket.on("updateEmote", function(data) {
bot.logger.mod(strings.format(bot, "EMOTE_UPDATE", [data.name]));
data.regex = new RegExp(data.source, "gi");
data = {name:data.name, regex:data.regex};
var found = false;
for (var i = 0; i < bot.CHANNEL.emotes.length; i++) {
if (bot.CHANNEL.emotes[i].name === data.name) {
found = true;
bot.CHANNEL.emotes[i] = data;
break;
}
}
for (var i = 0; i < bot.CHANNEL.badEmotes.length; i++) {
if (bot.CHANNEL.badEmotes[i].name === data.name) {
bot.CHANNEL.badEmotes[i] = data;
break;
}
}
if (!found) {
bot.CHANNEL.emotes.push(data);
if (/\s/g.test(data.name)) {
bot.CHANNEL.badEmotes.push(data);
} else {
bot.CHANNEL.emoteMap[data.name] = data;
}
} else {
bot.CHANNEL.emoteMap[data.name] = data;
}
});
socket.on("updatePoll", function(poll) {
bot.CHANNEL.poll.counts = poll.counts;
});
socket.on("usercount", function(count) {
bot.CHANNEL.usercount = count;
bot.logger.verbose(count + " users online.");
bot.setFlatSkiprate();
bot.setProgTitle();
});
socket.on("userLeave", function(data) {
var username = data.name;
var coloredName = utils.colorUsername(bot, username);
var duel = bot.getUserDuel(data.name, true);
var now = Date.now();
if (duel) {
let other = duel[0];
if (other === data.name) other = duel[1];
bot.sendChatMsg(strings.format(bot, "DUEL_USER_LEFT", [data.name, other]));
}
let idx = bot.getUserIndex(data.name);
let rank = bot.CHANNEL.users[idx].rank;
if (bot.userRankDBCheck(rank))
bot.updateUserRoomTime(username, true);
utils.unsortedRemove(bot.CHANNEL.users, idx);
let dupe = bot.getUser(data.name);
if (dupe) {
if (dupe.timeWentAFK > 0)
dupe.timeWentAFK = now;
if (dupe.joinTime > now)
dupe.joinTime = now;
dupe.lastRoomtimeCheck = now;
}
bot.logger.log(strings.format(bot, "USER_LEFT_ROOM", [coloredName]));
bot.setFlatSkiprate();
});
socket.on("userlist", function(userlist) {
bot.logger.verbose(strings.format(bot, "RECV_USERLIST"));
bot.CHANNEL.users = userlist;
var now = Date.now();
let users = bot.CHANNEL.users;
let end = users.length;
let newUsers = [];
for (var i = 0; i < users.length; i++) {
let _USER = users[i],
j = i;
_USER["lastRoomtimeCheck"] = now;
_USER["timeWentAFK"] = _USER.meta.afk ? now : -1;
_USER["joinTime"] = now;
if (bot.userRankDBCheck(_USER.rank)) {
bot.db.run("addNewUser", [_USER.name], function(res) {
if (bot.cfg.moderation.notifyNewUser) {
if (res && res.rowCount > 0 && res.rows[0].joins <= 1 && _USER.name !== bot.username) {
newUsers.push(_USER.name);
}
if (j >= end-1 && newUsers.length > 0) {
bot.broadcastModPM(strings.format(bot, "NEW_USERS", [newUsers.join(", ")]));
}
}
});
}
}
bot.getBanList();
bot.setProgTitle();
});
socket.on("voteskip", function(data) {
bot.CHANNEL.voteskip.count = data.count;
bot.CHANNEL.voteskip.need = data.need;
bot.setProgTitle();
});
function removeUIDFromBumpList(uid) {
let uids = bot.bumpStats.lastBumpedUIDs,
i = uids.length-1;
for (; i >= 0; i--) {
if (uids[i] === uid) uids.splice(i, 1);
}
}
function cleanUpcomingUIDsFromBumpList() {
let i = 0;
for (; i < bot.CHANNEL.playlist.length && i < bot.cfg.media.bumpCap-1; i++) {
removeUIDFromBumpList(bot.CHANNEL.playlist[i].uid);
}
}
}
module.exports = {
"setHandlers": setHandlers
}