Bots Home
|
Create an App
htestbot93052057395725823
Author:
_atze_
Description
Source Code
Launch Bot
Current Users
Created by:
_Atze_
var __extends = (this && this.__extends) || (function () { var extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); /** * Provides aliases for emblem emotes */ var emblems; /** * Provides aliases for emblem emotes */ (function (emblems) { "use strict"; emblems.arrow = " :arrow16 "; emblems.ballot = " :ballot16 "; emblems.bb8 = " :miniBB-8 "; /** * Blank "emblem", used to indent since CB eats HT's. */ emblems.blank = " :blank16 "; emblems.bronzemedal = " :bronzemedal16c "; emblems.coppermedal = " :coppermedal16 "; emblems.crown = " :crown16 "; emblems.gavel = " :gavel16 "; emblems.goldmedal = " :goldmedal16 "; emblems.hitachi = " :hitachi16 "; emblems.notice = " :notice16 "; emblems.silvermedal = " :silvermedal16 "; emblems.song = " :song16 "; emblems.timer = " :timer16 "; emblems.tinmedal = " :tinmedal16 "; emblems.tipmenu = " :tipmenu16 "; emblems.token = " :token12 "; emblems.trusted = " :trusted16 "; emblems.whisper = " :whisper16 "; emblems.whispermod = " :whispermod16 "; })(emblems || (emblems = {})); /** * Represents a tipmenu item */ var menuitem = /** @class */ (function () { /** * Create a new menu item * @param name Name of the item * @param cost Cost of the item * @param handler Handler function when this item is tipped for * @param params Parameters for the handler function */ function menuitem(name, cost, handler) { var params = []; for (var _i = 3; _i < arguments.length; _i++) { params[_i - 3] = arguments[_i]; } this.name = name; this.cost = cost; this.handler = handler; this.params = params; } /** * Handle the item, if it has a handler * This will not call the handler if one is not assigned */ menuitem.prototype.handle = function (tip, params) { if (params === void 0) { params = this.params; } if (this.handler != null) { this.handler(tip, params); } }; return menuitem; }()); /** * Represents a tipmenu section */ var menusection = /** @class */ (function () { function menusection(name) { var items = []; for (var _i = 1; _i < arguments.length; _i++) { items[_i - 1] = arguments[_i]; } /** * The actual items of the section */ this.items = []; this.name = name; this.items = items; } /** * Add the item to the section * @param name Name of the item * @param cost Cost of the item * @param active The condition in which the item is active * @param handler Handler for when the item is tipped for * @param params Parameters that should be passed to the handler */ menusection.prototype.add = function (name, cost, handler) { var params = []; for (var _i = 3; _i < arguments.length; _i++) { params[_i - 3] = arguments[_i]; } this.items[this.items.length] = new menuitem(name, cost, handler, params); }; /** * Clear the menu of all items */ menusection.prototype.clear = function () { this.items = []; }; /** * Delete the item from the section * @param name Name of the item */ menusection.prototype.del = function (name) { this.items = cbjs.arrayRemove(this.items, this.lookup(name)); }; /** * List all items in the section */ menusection.prototype.list = function () { return this.items; }; /** * Lookup the item * @param name Name of the item to get */ menusection.prototype.lookup = function (name) { for (var _i = 0, _a = this.items; _i < _a.length; _i++) { var item = _a[_i]; if (item.name.toLowerCase() === name.toLowerCase()) { return item; } } return null; }; /** * Tries to find a match to this section, returning the menuitem if one is found, null otherwise * @param tip Tip to try to find a match for */ menusection.prototype.match = function (tip) { var price; for (var _i = 0, _a = this.items; _i < _a.length; _i++) { var item = _a[_i]; if (tip.amount === price) { return item; } } return null; }; /** * Print this section to chat * @param limit The cost limit of items to print out, this is used to show all items below a certain cost * @param discountMethod The way to apply discounts to the items, if null items are not discounted under any condition */ menusection.prototype.print = function (user, limit, discountMethod) { if (discountMethod === void 0) { discountMethod = null; } notice.add("===== " + this.name + " ====="); var price; for (var _i = 0, _a = this.items; _i < _a.length; _i++) { var item = _a[_i]; // Discount the item's price if appropriate price = discountMethod != null ? discountMethod(item, user) : item.cost; // Skip printing the item if the price is higher than a specified limit // It would be possible to break if we could gaurantee the items were ordered by cost, but this isn't possible, so just continue if (limit != null && price >= limit) continue; notice.add(price + emblems.token + item.name); } notice.apply(emblems.tipmenu); notice.post(user.user); }; return menusection; }()); /** * Manages notices, especially buffering notices */ var notice; /** * Manages notices, especially buffering notices */ (function (notice_1) { "use strict"; /** * Color to use in notices, if none specified */ notice_1.color = "#094E94"; /** * Buffer of notices that haven't been posted */ var buffer = []; /** * Add the notice to the buffer * @param notice Notice to add */ function add(notice) { buffer[buffer.length] = notice; } notice_1.add = add; /** * Add the notices to the buffer * @param notices Notices to add */ function adds() { var notices = []; for (var _i = 0; _i < arguments.length; _i++) { notices[_i] = arguments[_i]; } for (var _a = 0, notices_1 = notices; _a < notices_1.length; _a++) { var notice_2 = notices_1[_a]; add(notice_2); } } notice_1.adds = adds; /** * Apply the emblem to each notice in the buffer * @param emblem Emblem to apply */ function apply(emblem) { for (var _i = 0, buffer_1 = buffer; _i < buffer_1.length; _i++) { var notice_3 = buffer_1[_i]; notice_3 = emblem + notice_3; } } notice_1.apply = apply; /** * Clear the buffer */ function clear() { buffer = []; } notice_1.clear = clear; /** * Print the help menu for notices * @param message Requesting message */ function help(message) { if (permissions.isAtLeastModerator(message)) { add("/note,notice <Message> --Send a notice to chat"); post(message.user); } } notice_1.help = help; /** * Post all notices in the buffer * @param to User to send to * @param textcolor Color of the text * @param weight Weight of the font * @param autoclear Clear the buffer automatically */ function post(to, textcolor, weight, autoclear) { if (to === void 0) { to = ""; } if (textcolor === void 0) { textcolor = notice_1.color; } if (weight === void 0) { weight = "bold"; } if (autoclear === void 0) { autoclear = true; } var message = buffer.join("\n"); cb.sendNotice(message, to, "#FFFFFF", textcolor, weight); if (autoclear) clear(); } notice_1.post = post; /** * Post all notices in the buffer * @param to Group to send to * @param textcolor Color of the text * @param weight Weight of the font */ function postGroup(to, textcolor, weight, autoclear) { if (textcolor === void 0) { textcolor = notice_1.color; } if (weight === void 0) { weight = "bold"; } if (autoclear === void 0) { autoclear = true; } var message = buffer.join("\n"); cb.sendNotice(message, "", "#FFFFFF", textcolor, weight, to); if (autoclear) clear(); } notice_1.postGroup = postGroup; /** * Send a notice * @param message Message to send * @param to User to send to * @param textcolor Color of the text * @param weight Weight of the font */ function send(message, to, textcolor, weight) { if (to === void 0) { to = ""; } if (textcolor === void 0) { textcolor = notice_1.color; } if (weight === void 0) { weight = "bold"; } cb.sendNotice(message, to, "#FFFFFF", textcolor, weight); } notice_1.send = send; /** * Send a notice * @param message Message to send * @param to Group to send to * @param textcolor Color of the text * @param weight Weight of the font */ function sendGroup(message, to, textcolor, weight) { if (textcolor === void 0) { textcolor = notice_1.color; } if (weight === void 0) { weight = "bold"; } cb.sendNotice(message, "", "#FFFFFF", textcolor, weight, to); } notice_1.sendGroup = sendGroup; /** * Try to parse a valid notice command, returning true if a valid command is found * @param message Requesting message */ function tryParse(message) { if (permissions.isAtLeastModerator(message)) { var m = message.m.split(" "); if (m.length === 0) return false; var command = m.shift().toLowerCase(); switch (command) { case "/note": case "/notice": send(emblems.notice + m.join(" ")); return true; default: return false; } } return false; } notice_1.tryParse = tryParse; })(notice || (notice = {})); // Timelock Gray Chat - Script globals var seen = {}; // Tracks which users we've seen // Logging var log = {}; log.DEBUG = 0; log.INFO = 1; log.WARN = 2; log.ERR = 3; log.level = log.WARN; // Default log level // Log to debug level log.debug = function(msg) { if (log.level > log.DEBUG) return; //cb.log("Debug: " + msg); tellOwner("Debug: " + log.format(msg)); }; // Log to info level log.info = function(msg) { if (log.level > log.INFO) return; tellOwner("Info: " + log.format(msg)); }; // Log to warning level log.warn = function(msg) { if (log.level > log.WARN) return; tellOwner("Warning: " + log.format(msg)); }; // Log to info level log.err = function(msg) { if (log.level > log.ERR) return; tellOwner("Error: " + log.format(msg)); }; // Format as string, using JSON to pretty print structures log.format = function(msg) { if (typeof msg === "string") return msg; else return JSON.stringify(msg, null, 4); }; // Utility functions /** * Formats arguments accordingly the formatting string. * Each occurence of the "{\d+}" substring refers to * the appropriate argument. * * From: http://code.fosshub.com/jsxt * * @example * '{0}is not {1} + {2}'.format('JavaScript', 'Java', 'Script'); * * @param mixed * @return string * @access public */ String.prototype.format = function() { var args = arguments; return this.replace(/\{(\d+)\}/g, function($0, $1) { return args[$1] !== void 0 ? args[$1] : $0; }); }; // Have we seen this user before? function isNew(username) { return !seen.hasOwnProperty(username); } // Do we always allow this type of user to speak? function isPermaSpeaker(user) { var username = user.user; // Broadcaster can always speak if (username == cb.room_slug) return true; // Test user is always grey if (user.user == "loremipsumbacongrey") return false; // If blue, green or red they can always speak if (user.has_tokens || user.in_fanclub || user.is_mod) return true; else return false; } // If a user is grey. // Split out to allow isPermaSpeaker to change if needed at some point. function isGrey(user) { return !isPermaSpeaker(user); } // Can the user use admin commands? function isAdmin(user) { var username = user.user; // Broadcasters and mods can run admin commands if (username == cb.room_slug || user.is_mod) return true; else return false; } // Is the user allowed to chat function canSpeak(user) { var username = user.user; // If we haven't seen the user before, add them if (isNew(username)) { addUser(user); if (username != cb.room_slug) log.info("Note: Pre-existing user added (no join seen): " + username); } // If they've been marked as canSpeak, yes if (seen[username].canSpeak) return true; // If the timelock has expired, yes if (expired(seen[username].entered)) { setSpeaker(username); return true; } // If the timelock is set to 0, yes if (cb.settings.timelock_duration == 0) { return true; } return false; } // Set a user function setSpeaker(username) { seen[username].canSpeak = true; } // Check if a timelock has expired function expired(date) { return elapsed(date) > cb.settings.timelock_duration; } // Get elapsed time since a date, in minutes function elapsed(date) { var now = Date.now(); var minutes = Math.floor((now - date) / (1000 * 60)); return minutes; } // Give user the welcome message function welcomeUser(username) { var msg = "TimeLockGreys: Please sit back and enjoy the show! Users without tokens are timelocked. You will be able to chat {0} minutes after joining if Silence Level: 0."; var duration = cb.settings.timelock_duration; tellUser(msg.format(duration), username); } // Start tracking the user function addUser(user) { var username = user.user; var u = {}; // User info u.entered = Date.now(); u.canSpeak = isPermaSpeaker(user); seen[username] = u; if (cb.settings.timelock_duration !== 0) log.info("Added user: " + username + " with values: "); log.info(u); log.debug("DB state:"); log.debug(seen); } // Send text to a given user function tellUser(msg, username) { if (cb.settings.timelock_duration !== 0) cb.sendNotice(msg, username, '#DF0101', '#FFFFFF', 'bolder'); } // Send text to the broadcaster function tellOwner(msg) { tellUser(msg, cb.room_slug); } // How many minutes until a user can speak function timeLeft(username) { var ERR = -1; if (isNew(username)) { log.err("timeLeft called on invalid username: " + username); return ERR; } var entered = seen[username].entered; return cb.settings.timelock_duration - elapsed(entered); } // Does the text look like a command? function isCmd(txt) { if (txt.charAt(0) === "/") return true; else return false; } // Commands // Execute command function runCmd(msg) { var username = msg.user; var user = msg; // Msg includes user info, so we can treat it as such // Only admins can run commands if (!isAdmin(user)) { return false; } // Only run commands if wait time != 0 if (cb.settings.timelock_duration == 0) { return false; } // Check for the tlg prefix, otherwise command is likely meant for another app if (msg.m.search("/tlg") !== 0) return false; // Extract the command name and any parameters var regex = /^\/tlg\s*(\S*)\s*(\S*.*)/i; var cmdSplit = msg.m.match(regex); log.debug("Command split:"); log.debug(cmdSplit); // No command found if (typeof cmdSplit === 'undefined' || cmdSplit === null) { log.err("Invalid command: " + msg.m); return false; } // Command name var cmd = cmdSplit[1]; // Command parameters var args; if (cmdSplit.length > 1) args = cmdSplit[2]; // If no command is provided just display the help if (typeof cmd === "undefined" || cmd === "") { cmdHelp(username); return false; } // Execute the command switch (cmd.toLowerCase()) { case "resetall": cmdResetAll(); break; case "resetuser": cmdResetUser(args); break; case "help": cmdHelp(); break; default: tellUser("Unknown command: " + cmd, username); return false; } return true; } // Show commands function cmdHelp(username) { log.debug("Running cmdHelp"); // If msg is null (such as upon init) assume it's the broadcaster if (typeof username === "undefined") { username = cb.room_slug; } tellUser("TimeLockGreys: /tlg resetuser <user> - reset timelock for speccific user | /tlg resetall - reset timelock for all grays | /tlg help - display this message", username); } // Reset all seen data, as if starting fresh function cmdResetAll() { seen = {}; tellOwner("TimeLockGreys: All user info has been reset. Timelocks for existing users will not start until they rejoin or attempt to speak."); } // Reset data for a specific user function cmdResetUser(username) { if (!isNew(username)) { delete seen[username]; tellOwner("TimeLockGreys: User info for {0} has been reset. Timelocks for existing users will not start until they rejoin or attempt to speak.".format(username)); } else { tellOwner("Unknown user {0}.".format(username)); } } /** * Provides permissions checking * A lot of these are provided by the object anyways, are are implemented for the sake of orthogonality * This is solely for permissions purposes, the levels are: * broadcaster > trusted user > moderator > fanclub > tipped tons > tipped alot > tipped > has tokens > gray */ var permissions; (function (permissions) { "use strict"; /** * List of trusted users; users with elevated permissions */ var trusted = []; /** * Trust the users * @param users Users to trust */ function entrust() { var users = []; for (var _i = 0; _i < arguments.length; _i++) { users[_i] = arguments[_i]; } for (var _a = 0, users_1 = users; _a < users_1.length; _a++) { var user_1 = users_1[_a]; trusted[trusted.length] = user_1; } } permissions.entrust = entrust; /** * Remove trust of the users * @param users Users to detrust */ function detrust() { var users = []; for (var _i = 0; _i < arguments.length; _i++) { users[_i] = arguments[_i]; } for (var _a = 0, users_2 = users; _a < users_2.length; _a++) { var user_2 = users_2[_a]; trusted = cbjs.arrayRemove(trusted, user_2); } } permissions.detrust = detrust; /** * Is the user the broadcaster? * @param user User to check */ function isBroadcaster(user) { return user.user === cb.room_slug; } permissions.isBroadcaster = isBroadcaster; /** * Is the user a trusted user? * @param user User to check */ function isTrusted(user) { return cbjs.arrayContains(trusted, user.user); } permissions.isTrusted = isTrusted; /** * Is the user at least a trusted user? * @param user User to check */ function isAtLeastTrusted(user) { return isBroadcaster(user) || isTrusted(user); } permissions.isAtLeastTrusted = isAtLeastTrusted; /** * Is the user a moderator? * @param user User to check */ function isModerator(user) { return user.is_mod; } permissions.isModerator = isModerator; /** * Is the user at least a moderator? * @param user User to check */ function isAtLeastModerator(user) { return isAtLeastTrusted(user) || isModerator(user); } permissions.isAtLeastModerator = isAtLeastModerator; /** * Is the user in the fanclub? * @param user User to check */ function isInFanclub(user) { return user.in_fanclub; } permissions.isInFanclub = isInFanclub; /** * Is the user at least in the fanclub? * @param user User to check */ function isAtLeastInFanclub(user) { return isAtLeastModerator(user) || isInFanclub(user); } permissions.isAtLeastInFanclub = isAtLeastInFanclub; /** * Has the user tipped tons recently? * @param user User to check */ function hasTippedTons(user) { return user.tipped_tons_recently; } permissions.hasTippedTons = hasTippedTons; /** * Has the user at least tipped tons recently? * @param user User to check */ function hasAtLeastTippedTons(user) { return isAtLeastInFanclub(user) || hasTippedTons(user); } permissions.hasAtLeastTippedTons = hasAtLeastTippedTons; /** * Has the user tipped alot recently? * @param user User to check */ function hasTippedAlot(user) { return user.tipped_alot_recently; } permissions.hasTippedAlot = hasTippedAlot; /** * Has the user at least tipped alot recently? * @param user User to check */ function hasAtLeastTippedAlot(user) { return hasAtLeastTippedTons(user) || hasTippedAlot(user); } permissions.hasAtLeastTippedAlot = hasAtLeastTippedAlot; /** * Has the user tipped recently? * @param user User to check */ function hasTipped(user) { return user.tipped_recently; } permissions.hasTipped = hasTipped; /** * Has the user at least tipped recently? * @param user User to check */ function hasAtLeastTipped(user) { return hasAtLeastTippedAlot(user) || hasTipped(user); } permissions.hasAtLeastTipped = hasAtLeastTipped; /** * Does the user have tokens? * @param user User to check */ function hasTokens(user) { return user.has_tokens; } permissions.hasTokens = hasTokens; /** * Does the user at least have tokens? * @param user User to check */ function hasAtLeastTokens(user) { return hasAtLeastTipped(user) || hasTokens(user); } permissions.hasAtLeastTokens = hasAtLeastTokens; /** * Prints the help for permissions * @param message Requesting message */ function help(message) { if (permissions.isAtLeastTrusted(message)) { notice.add("/trust,trusted"); } if (permissions.isBroadcaster(message)) { notice.add(emblems.blank + "add <User>+ --Entrust the users"); notice.add(emblems.blank + "del,delete,rem,remove <User>+ --Detrust the users"); } if (permissions.isAtLeastTrusted(message)) { notice.add(emblems.blank + "list --List all trusted users"); notice.post(message.user); } } permissions.help = help; /** * Try to parse a permissions command, returning true if a valid command is found * @param message Requesting message */ function tryParse(message) { if (permissions.isBroadcaster(message)) { var m = message.m.split(" "); if (m.length === 0) return false; var command = m.shift().toLowerCase(); switch (command) { case "/detrust": for (var _i = 0, m_1 = m; _i < m_1.length; _i++) { var user_3 = m_1[_i]; detrust(user_3); } return true; case "/entrust": for (var _a = 0, m_2 = m; _a < m_2.length; _a++) { var user_4 = m_2[_a]; entrust(user_4); } return true; case "/trust": case "/trusted": if (m.length === 0) return false; var operation = m.shift().toLowerCase(); switch (operation) { case "add": for (var _b = 0, m_3 = m; _b < m_3.length; _b++) { var user_5 = m_3[_b]; entrust(user_5); } return true; case "del": case "delete": case "rem": case "remove": for (var _c = 0, m_4 = m; _c < m_4.length; _c++) { var user_6 = m_4[_c]; detrust(user_6); } return true; case "help": help(message); return true; case "list": notice.send(trusted.join(", "), message.user); return true; default: return false; } } } return false; } permissions.tryParse = tryParse; })(permissions || (permissions = {})); var filter; (function (filter) { /** * Manages the advertisement filter */ var advertisements; (function (advertisements) { var profileVerbs = ["open", "look", "see", "peek", "tap", "check", "click", "visit"]; var profileNouns = ["profile", "bio", "page", "account"]; var camVerbs = ["open", "look", "see", "peek", "watch", "checl", "join", "lets", "let's", "want", "wants", "do"]; var camNouns = ["cam", "cam2", "2cam", "c2c", "c2", "2c"]; /** * Check a message for possible profile advertisements * @param message Message to check */ function checkProfile(message) { if (message.user === cb.room_slug) return; if (cb.settings.modexception == "on" && message.is_mod) return; if (cb.settings.fcexception == "on" && message.in_fanclub) return; var m = message.m.split(" "); var v = false; var n = false; for (var _i = 0, m_5 = m; _i < m_5.length; _i++) { var candidate = m_5[_i]; for (var _a = 0, profileVerbs_1 = profileVerbs; _a < profileVerbs_1.length; _a++) { var verb = profileVerbs_1[_a]; if (candidate.toLowerCase() === verb) { v = true; break; } } for (var _b = 0, profileNouns_1 = profileNouns; _b < profileNouns_1.length; _b++) { var noun = profileNouns_1[_b]; if (candidate.toLowerCase() === noun) { n = true; break; } } } if (v && n) { message['X-Spam'] = true; if (cb.settings.bcdetails == "on") { notice.send(emblems.gavel + message.user + ": '" + message.m + "' has been filtered for likely profile advertising", cb.room_slug); } else { notice.send(emblems.gavel + message.user + " has been filtered for likely profile advertising", cb.room_slug); } if (cb.settings.moddetails == "on") { notice.sendGroup(emblems.gavel + message.user + ": '" + message.m + "' has been filtered for likely profile advertising", "red"); } else { notice.sendGroup(emblems.gavel + message.user + " has been filtered for likely profile advertising", "red"); } } } advertisements.checkProfile = checkProfile; /** * Check a message for possible profile advertisements * @param message Message to check */ function checkCam(message) { if (message.user === cb.room_slug) return; if (cb.settings.modexception == "on" && message.is_mod) return; if (cb.settings.fcexception == "on" && message.in_fanclub) return; var m = message.m.split(" "); var v = false; var n = false; for (var _i = 0, m_6 = m; _i < m_6.length; _i++) { var candidate = m_6[_i]; for (var _a = 0, camVerbs_1 = camVerbs; _a < camVerbs_1.length; _a++) { var verb = camVerbs_1[_a]; if (candidate.toLowerCase() === verb) { v = true; break; } } for (var _b = 0, camNouns_1 = camNouns; _b < camNouns_1.length; _b++) { var noun = camNouns_1[_b]; if (candidate.toLowerCase() === noun) { n = true; break; } } } if (v && n) { message['X-Spam'] = true; if (cb.settings.bcdetails == "on") { notice.send(emblems.gavel + message.user + ": '" + message.m + "' has been filtered for likely cam advertising", cb.room_slug); } else { notice.send(emblems.gavel + message.user + " has been filtered for likely cam advertising", cb.room_slug); } if (cb.settings.moddetails == "on") { notice.sendGroup(emblems.gavel + message.user + ": '" + message.m + "' has been filtered for likely cam advertising", "red"); } else { notice.sendGroup(emblems.gavel + message.user + " has been filtered for likely cam advertising", "red"); } } } advertisements.checkCam = checkCam; })(advertisements = filter.advertisements || (filter.advertisements = {})); })(filter || (filter = {})); var bouncer; (function (bouncer) { function help(message) { dozer.help(message); notice.help(message); permissions.help(message); silences.help(message); } /** * Try to parse a bouncer command, returning true if a valid command is found * @param message Message to try to parse */ function tryParse(message) { var m = message.m.split(" "); if (m.length === 0) return false; var command = m.shift().toLowerCase(); switch (command) { case "/bouncer": if (m.length === 0) return false; var command_1 = m.shift().toLowerCase(); switch (command_1) { case "help": break; default: return false; } break; // This deliberately falls through case "/bouncerhelp": help(message); return true; default: return false; } } bouncer.tryParse = tryParse; })(bouncer || (bouncer = {})); var filter; (function (filter) { var level; (function (level) { level[level["grey"] = 0] = "grey"; level[level["lightblue"] = 1] = "lightblue"; level[level["darkblue"] = 2] = "darkblue"; level[level["lightpurple"] = 3] = "lightpurple"; level[level["darkpurple"] = 4] = "darkpurple"; level[level["green"] = 5] = "green"; level[level["red"] = 6] = "red"; level[level["orange"] = 7] = "orange"; })(level = filter.level || (filter.level = {})); })(filter || (filter = {})); var filter; (function (filter) { /** * Manages the graphic-level * For users not allowed to use graphics, the filter removes the emote from the message */ var graphiclevel; (function (graphiclevel) { /** * The set level of the filter */ graphiclevel.state = filter.level.grey; /** * Check a message against the set graphic level * @param message Message to check */ function check(message) { switch (graphiclevel.state) { case filter.level.grey: break; case filter.level.lightblue: if (!permissions.hasAtLeastTokens(message)) message.m = removeGraphics(message); break; case filter.level.darkblue: if (!permissions.hasAtLeastTipped(message)) message.m = removeGraphics(message); break; case filter.level.lightpurple: if (!permissions.hasAtLeastTippedAlot(message)) message.m = removeGraphics(message); break; case filter.level.darkpurple: if (!permissions.hasAtLeastTippedTons(message)) message.m = removeGraphics(message); break; case filter.level.green: if (!permissions.isAtLeastInFanclub(message)) message.m = removeGraphics(message); break; case filter.level.red: if (!permissions.isAtLeastModerator(message)) message.m = removeGraphics(message); break; case filter.level.orange: if (!permissions.isBroadcaster(message)) message.m = removeGraphics(message); break; } } graphiclevel.check = check; function removeGraphics(message) { var m = message.m.split(" "); var r = []; for (var _i = 0, m_7 = m; _i < m_7.length; _i++) { var word = m_7[_i]; if (word.charAt(0) != ":") { r[r.length] = word; } } return r.join(" "); } /** * Try to parse a valid graphiclevel command, returning true if a valid comand is found * @param message Requesting message */ function tryParse(message) { var m = message.m.split(" "); if (m.length === 0) return false; var command = m.shift().toLowerCase(); switch (command) { case "/graphic": if (m.length === 0) return false; var command_2 = m.shift().toLowerCase(); switch (command_2) { case "level": break; default: return false; } break; // This deliberately falls through case "/graphiclevel": if (m.length === 0) { notice.send(emblems.gavel + "Graphic Level: " + graphiclevel.state, message.user); return true; } if (!permissions.isAtLeastModerator(message)) return false; var set = m.join(" ").toLowerCase(); switch (set) { case "g": case "grey": case "gray": graphiclevel.state = filter.level.grey; notice.add("Graphic Level has been set"); notice.add("Only 'grey' and above may use graphics"); notice.apply(emblems.gavel); notice.post(); return true; case "lb": case "lightblue": case "light-blue": case "light blue": graphiclevel.state = filter.level.lightblue; notice.add("Graphic Level has been set"); notice.add("Only 'light blue' and above may use graphics"); notice.apply(emblems.gavel); notice.post(); return true; case "db": case "darkblue": case "dark-blue": case "dark blue": graphiclevel.state = filter.level.darkblue; notice.add("Graphic Level has been set"); notice.add("Only 'dark blue' and above may use graphics"); notice.apply(emblems.gavel); notice.post(); return true; case "lp": case "lightpurple": case "light-purple": case "light purple": graphiclevel.state = filter.level.lightpurple; notice.add("Graphic Level has been set"); notice.add("Only 'light purple' and above may use graphics"); notice.apply(emblems.gavel); notice.post(); return true; case "dp": case "darkpurple": case "dark-purple": case "dark purple": graphiclevel.state = filter.level.darkpurple; notice.add("Graphic Level has been set"); notice.add("Only 'dark purple' and above may use graphics"); notice.apply(emblems.gavel); notice.post(); return true; case "green": case "fan": case "fans": case "fanclub": case "fan club": graphiclevel.state = filter.level.green; notice.add("Graphic Level has been set"); notice.add("Only 'green' and above may use graphics"); notice.apply(emblems.gavel); notice.post(); return true; case "red": case "mod": case "mods": case "moderator": case "moderators": graphiclevel.state = filter.level.red; notice.add("Graphic Level has been set"); notice.add("Only 'red' and above may use graphics"); notice.apply(emblems.gavel); notice.post(); return true; case "orange": case "broadcaster": case "model": graphiclevel.state = filter.level.orange; notice.add("Graphic Level has been set"); notice.add("Only 'orange' and above may use graphics"); notice.apply(emblems.gavel); notice.post(); return true; default: return false; } break; default: return false; } } graphiclevel.tryParse = tryParse; })(graphiclevel = filter.graphiclevel || (filter.graphiclevel = {})); })(filter || (filter = {})); /** * Manages silences */ var silences; /** * Manages silences */ (function (silences) { /** * Users who have been silenced */ var silenced = []; /** * Users who have been unsilenced */ var unsilenced = []; function help(message) { if (permissions.isAtLeastModerator(message)) { notice.add("/silence <users>+ --Silence the specified users"); notice.add("/unsilence <users>+ --Unsilence the specified users"); notice.post(message.user); message['X-Spam'] = true; } } silences.help = help; /** * Is the user silenced? * @param user */ function isSilenced(user) { return cbjs.arrayContains(silenced, user); } silences.isSilenced = isSilenced; /** * Is the user unsilenced? * @param user */ function isUnsilenced(user) { return cbjs.arrayContains(unsilenced, user); } silences.isUnsilenced = isUnsilenced; /** * Silence the user * @param user Username of the user */ function silence(user) { if (cbjs.arrayContains(unsilenced, user)) { unsilenced = cbjs.arrayRemove(unsilenced, user); } silenced[silenced.length] = user; } silences.silence = silence; /** * Unsilence the user * @param user Username of the user */ function unsilence(user) { if (cbjs.arrayContains(silenced, user)) { silenced = cbjs.arrayRemove(silenced, user); } unsilenced[unsilenced.length] = user; } silences.unsilence = unsilence; /** * Try to parse a valid silence command, returning true if a valid command is found * @param message Requesting message */ function tryParse(message) { if (!permissions.isAtLeastModerator(message)) return false; var m = message.m.split(" "); if (m.length === 0) return false; var command = m.shift().toLowerCase(); switch (command) { case "/silence": if (m.length === 0) return false; for (var _i = 0, m_8 = m; _i < m_8.length; _i++) { var user_7 = m_8[_i]; silence(user_7); } notice.sendGroup(emblems.gavel + "Silenced users: " + m, "red"); notice.send(emblems.gavel + "Silenced users: " + m, cb.room_slug); return true; case "/unsilence": if (m.length === 0) return false; for (var _a = 0, m_9 = m; _a < m_9.length; _a++) { var user_8 = m_9[_a]; unsilence(user_8); } notice.sendGroup(emblems.gavel + "Unsilenced users: " + m, "red"); notice.send(emblems.gavel + "Unsilenced users: " + m, cb.room_slug); return true; default: return false; } } silences.tryParse = tryParse; })(silences || (silences = {})); var filter; (function (filter) { /** * Manages the dirty talk filter */ var dirtytalk; (function (dirtytalk) { var verbs = ["have", "got", "get", "see", "so", "make", "makes", "cumming", "nice", "sweet"]; var nouns = ["boner", "hardon", "hard", "dick", "load", "cum", "pussy", "cunt", "vagina"]; /** * Check the message for possible dirty talk * @param message Message to check */ function check(message) { if (message.user === cb.room_slug) return; if (cb.settings.modexception == "on" && message.is_mod) return; if (cb.settings.fcexception == "on" && message.in_fanclub) return; var m = message.m.split(" "); var v = false; var n = false; for (var _i = 0, m_10 = m; _i < m_10.length; _i++) { var candidate = m_10[_i]; for (var _a = 0, verbs_1 = verbs; _a < verbs_1.length; _a++) { var verb = verbs_1[_a]; if (candidate.toLowerCase() === verb) { v = true; break; } } for (var _b = 0, nouns_1 = nouns; _b < nouns_1.length; _b++) { var noun = nouns_1[_b]; if (candidate.toLowerCase() === noun) { n = true; break; } } } if (v && n) { if (cb.settings.bcdetails == "on") { notice.send(emblems.gavel + message.user + ": '" + message.m + "' has been filtered for likely dirty talk", cb.room_slug); } else { notice.send(emblems.gavel + message.user + " has been filtered for likely dirty talk", cb.room_slug); } if (cb.settings.moddetails == "on") { notice.sendGroup(emblems.gavel + message.user + ": '" + message.m + "' has been filtered for likely dirty talk", "red"); } else { notice.sendGroup(emblems.gavel + message.user + " has been filtered for likely dirty talk", "red"); } } } dirtytalk.check = check; })(dirtytalk = filter.dirtytalk || (filter.dirtytalk = {})); })(filter || (filter = {})); var filter; (function (filter) { /** * Manages the demand filter */ var demands; (function (demands) { var verbs = ["open", "spread", "show", "finger", "fist", "touch", "zoom", "want", "have"]; var nouns = ["pussy", "cunt", "vagina", "bob", "boob", "tit", "ass", "bum", "butt", "arse", "feet", "foot", "hole", "sex"]; /** * Check the message for possible demands * @param message Message to check */ function check(message) { if (message.user === cb.room_slug) return; if (cb.settings.modexception == "on" && message.is_mod) return; if (cb.settings.fcexception == "on" && message.in_fanclub) return; var m = message.m.split(" "); var v = false; var n = false; for (var _i = 0, m_11 = m; _i < m_11.length; _i++) { var candidate = m_11[_i]; for (var _a = 0, verbs_2 = verbs; _a < verbs_2.length; _a++) { var verb = verbs_2[_a]; if (candidate.toLowerCase() === verb) { v = true; break; } } for (var _b = 0, nouns_2 = nouns; _b < nouns_2.length; _b++) { var noun = nouns_2[_b]; if (candidate.toLowerCase() === noun) { n = true; break; } } } if (v && n) { message['X-Spam'] = true; if (cb.settings.bcdetails == "on") { notice.send(emblems.gavel + message.user + ": '" + message.m + "' has been filtered for likely demanding", cb.room_slug); } else { notice.send(emblems.gavel + message.user + " has been filtered for likely demanding", cb.room_slug); } if (cb.settings.moddetails == "on") { notice.sendGroup(emblems.gavel + message.user + ": '" + message.m + "' has been filtered for likely demanding", "red"); } else { notice.sendGroup(emblems.gavel + message.user + " has been filtered for likely demanding", "red"); } } } demands.check = check; })(demands = filter.demands || (filter.demands = {})); })(filter || (filter = {})); var filter; (function (filter) { /** * Manages the silence-level * For users not allowed to post messages, the filter marks them as spam */ var silencelevel; (function (silencelevel) { /** * The set level of the filter */ silencelevel.state = filter.level.grey; /** * Check a message against the set silence level * @param message Message to check */ function check(message) { switch (silencelevel.state) { case filter.level.grey: break; case filter.level.lightblue: if (!permissions.hasAtLeastTokens(message)) { message['X-Spam'] = true; } break; case filter.level.darkblue: if (!permissions.hasAtLeastTipped(message)) { message['X-Spam'] = true; } break; case filter.level.lightpurple: if (!permissions.hasAtLeastTippedAlot(message)) { message['X-Spam'] = true; } break; case filter.level.darkpurple: if (!permissions.hasAtLeastTippedTons(message)) { message['X-Spam'] = true; } break; case filter.level.green: if (!permissions.isAtLeastInFanclub(message)) { message['X-Spam'] = true; } break; case filter.level.red: if (!permissions.isAtLeastModerator(message)) { message['X-Spam'] = true; } break; case filter.level.orange: if (!permissions.isBroadcaster(message)) { message['X-Spam'] = true; } break; } } silencelevel.check = check; /** * Try to parse a valid graphiclevel command, returning true if a valid comand is found * @param message Requesting message */ function tryParse(message) { var m = message.m.split(" "); if (m.length === 0) return false; var command = m.shift().toLowerCase(); switch (command) { case "/silence": if (m.length === 0) return false; var command_3 = m.shift().toLowerCase(); switch (command_3) { case "level": break; default: return false; } break; // This deliberately falls through case "/silencelevel": if (m.length === 0) { notice.send(emblems.gavel + "Silence Level: " + silencelevel.state, message.user); return true; } if (!permissions.isAtLeastModerator(message)) return false; var set = m.join(" ").toLowerCase(); switch (set) { case "g": case "grey": case "gray": silencelevel.state = filter.level.grey; notice.add("Silence Level has been set"); notice.add("Only 'grey' and above may post messages"); notice.apply(emblems.gavel); notice.post(); return true; case "lb": case "lightblue": case "light-blue": case "light blue": silencelevel.state = filter.level.lightblue; notice.add("Silence Level has been set"); notice.add("Only 'light blue' and above may post messages"); notice.apply(emblems.gavel); notice.post(); return true; case "db": case "darkblue": case "dark-blue": case "dark blue": silencelevel.state = filter.level.darkblue; notice.add("Silence Level has been set"); notice.add("Only 'dark blue' and above may post messages"); notice.apply(emblems.gavel); notice.post(); return true; case "lp": case "lightpurple": case "light-purple": case "light purple": silencelevel.state = filter.level.lightpurple; notice.add("Silence Level has been set"); notice.add("Only 'light purple' and above may post messages"); notice.apply(emblems.gavel); notice.post(); return true; case "dp": case "darkpurple": case "dark-purple": case "dark purple": silencelevel.state = filter.level.darkpurple; notice.add("Silence Level has been set"); notice.add("Only 'dark purple' and above may post messages"); notice.apply(emblems.gavel); notice.post(); return true; case "green": case "fan": case "fans": case "fanclub": case "fan club": silencelevel.state = filter.level.green; notice.add("Silence Level has been set"); notice.add("Only 'green' and above may post messages"); notice.apply(emblems.gavel); notice.post(); return true; case "red": case "mod": case "mods": case "moderator": case "moderators": silencelevel.state = filter.level.red; notice.add("Silence Level has been set"); notice.add("Only 'red' and above may post messages"); notice.apply(emblems.gavel); notice.post(); return true; case "orange": case "broadcaster": case "model": silencelevel.state = filter.level.orange; notice.add("Silence Level has been set"); notice.add("Only 'orange' and above may post messages"); notice.apply(emblems.gavel); notice.post(); return true; default: return false; } break; default: return false; } } silencelevel.tryParse = tryParse; })(silencelevel = filter.silencelevel || (filter.silencelevel = {})); })(filter || (filter = {})); var filter; (function (filter) { /** * Manages the website filter */ var website; (function (website) { /** * Check a message for possible websites * @param message Message to check */ function check(message) { if (message.user === cb.room_slug) return; if (cb.settings.modexception == "on" && message.is_mod) return; if (cb.settings.fcexception == "on" && message.in_fanclub) return; var m = message.m.split(" "); for (var _i = 0, m_12 = m; _i < m_12.length; _i++) { var candidate = m_12[_i]; if (candidate.match(/\w+\.\w+\.\w+/)) { message['X-Spam'] = true; break; } } if (message['X-Spam']) { if (cb.settings.bcdetails == "on") { notice.send(emblems.gavel + message.user + ": '" + message.m + "' has been filtered for likely website links", cb.room_slug); } else { notice.send(emblems.gavel + message.user + " has been filtered for likely website links", cb.room_slug); } if (cb.settings.moddetails == "on") { notice.sendGroup(emblems.gavel + message.user + ": '" + message.m + "' has been filtered for likely website links", "red"); } else { notice.sendGroup(emblems.gavel + message.user + " has been filtered for likely website links", "red"); } } } website.check = check; })(website = filter.website || (filter.website = {})); })(filter || (filter = {})); /** * Initialization Code */ { notice.color = "#C76565"; switch (cb.settings.graphiclevel) { case "grey": filter.graphiclevel.state = filter.level.grey; break; case "lightblue": filter.graphiclevel.state = filter.level.lightblue; break; case "darkblue": filter.graphiclevel.state = filter.level.darkblue; break; case "lightpurple": filter.graphiclevel.state = filter.level.lightpurple; break; case "darkpurple": filter.graphiclevel.state = filter.level.darkpurple; break; case "green": filter.graphiclevel.state = filter.level.green; break; case "red": filter.graphiclevel.state = filter.level.red; break; case "orange": filter.graphiclevel.state = filter.level.orange; break; } switch (cb.settings.silencelevel) { case "grey": filter.silencelevel.state = filter.level.grey; break; case "lightblue": filter.silencelevel.state = filter.level.lightblue; break; case "darkblue": filter.silencelevel.state = filter.level.darkblue; break; case "lightpurple": filter.silencelevel.state = filter.level.lightpurple; break; case "darkpurple": filter.silencelevel.state = filter.level.darkpurple; break; case "green": filter.silencelevel.state = filter.level.green; break; case "red": filter.silencelevel.state = filter.level.red; break; case "orange": filter.silencelevel.state = filter.level.orange; break; } } /** * Manages rotating notices */ var rotater; /** * Manages rotating notices */ (function (rotater) { "use strict"; /** * Number, in minutes, between notices */ rotater.lapse = 3; /** * Notices in rotation */ var pool = []; /** * Index of the notice pool; current position */ var n = 0; /** * Add a notice to rotation * @param notice Notice to add */ function add(message) { pool[pool.length] = message; notice.send(emblems.notice + "'" + message + "' has been added to rotation"); } rotater.add = add; /** * Delete a notice from rotation * @param notice Notice literal or position to delete */ function del(message) { if (typeof message === "string") { pool = cbjs.arrayRemove(pool, message); notice.send(emblems.notice + "'" + message + "' has been removed from rotation"); } else if (typeof message === "number") { notice.send(emblems.notice + "'" + pool[message - 1] + "' has been removed from rotation"); pool = cbjs.arrayRemove(pool, pool[message - 1]); } } rotater.del = del; /** * Print the help menu for rotating notices * @param message Requesting message */ function help(message) { notice.add("/rotater,rotating,rotation"); if (permissions.isAtLeastModerator(message)) { notice.add(emblems.blank + "add <Message> --Add the notice to rotation"); } if (permissions.isAtLeastTrusted(message)) { notice.add(emblems.blank + "del,delete (<Message> | <Position>) --Delete the notice from rotation"); } notice.add(emblems.blank + "list,print --List all notices in rotation"); notice.post(message.user); notice.clear(); } rotater.help = help; /** * List all notices in rotation */ function list() { return pool; } rotater.list = list; function print(user) { var i = 0; for (var _i = 0, pool_1 = pool; _i < pool_1.length; _i++) { var note = pool_1[_i]; notice.add(++i + ") " + note); } notice.post(user.user); notice.clear(); } rotater.print = print; /** * Rotate and post notice */ function rotate() { notice.send(emblems.notice + pool[n++]); n %= pool.length; cb.setTimeout(rotate, rotater.lapse * 60 * 1000); } /** * Start the rotater */ function start() { cb.setTimeout(rotate, rotater.lapse * 60 * 1000); } rotater.start = start; /** * Try to parse a rotater command, returning true if a valid command is found * @param message Requesting message */ function tryParse(message) { var m = message.m.split(" "); if (m.length === 0) return false; var command = m.shift().toLowerCase(); switch (command) { case "/rotater": case "/rotating": case "/rotation": // Command is valid, break out break; default: return false; } if (m.length === 0) return false; var operation = m.shift().toLowerCase(); switch (operation) { case "add": if (permissions.isAtLeastModerator(message)) { rotater.add(m.join(" ")); return true; } return false; case "del": case "delete": if (permissions.isAtLeastTrusted(message)) { var pos = m.shift(); if (isNaN(Number(pos))) { // pos isn't actually a position, so put it back m.unshift(pos); rotater.del(m.join(" ")); } else { rotater.del(Number(pos)); } return true; } return false; case "help": help(message); return true; case "list": case "print": print(message); return true; default: return false; } } rotater.tryParse = tryParse; })(rotater || (rotater = {})); /** * Manages song requests */ var songqueue; /** * Manages song requests */ (function (songqueue) { "use strict"; /** * Whether the queue postings should be public */ var publicPostings = false; /** * The actual queue of song requests */ var queue = []; /** * Add the song to the queue * @param user Who tipped for the request * @param song Song requested */ function add(user, song, type) { if (type === void 0) { type = requesttype.play; } queue[queue.length] = new songrequest(user, song, type); switch (type) { case requesttype.dance: if (publicPostings) { notice.send(emblems.song + "Dance: '" + song + "' queued", cb.room_slug); } else { notice.send(emblems.song + "Dance: '" + song + "' queued"); } break; case requesttype.karaoke: if (publicPostings) { notice.send(emblems.song + "Karaoke: '" + song + "' queued", cb.room_slug); } else { notice.send(emblems.song + "Karaoke: '" + song + "' queued"); } break; case requesttype.play: if (publicPostings) { notice.send(emblems.song + "Song: '" + song + "' queued", cb.room_slug); } else { notice.send(emblems.song + "Song: '" + song + "' queued"); } break; } } songqueue.add = add; /** * Get the next song from the queue * Returns null if no more songs */ function get() { if (queue.length === 0) return null; else return queue.shift(); } songqueue.get = get; /** * Print the help menu for the song queue * @param message Requesting message */ function help(message) { if (permissions.isBroadcaster(message)) { notice.add("/song"); notice.add(emblems.blank + "next --Get the next song from the queue"); notice.post(message.user); notice.clear(); } } songqueue.help = help; /** * Try to parse a song command, returning true if a valid command is found * @param message Requesting message */ function tryParse(message) { var m = message.m.split(" "); if (m.length === 0) return false; var command = m.shift().toLowerCase(); switch (command) { case "/song": // Command is valid, break out break; default: return false; } if (m.length === 0) return false; var operation = m.shift().toLowerCase(); switch (operation) { case "help": help(message); return true; case "next": if (permissions.isBroadcaster(message)) { var request = get(); if (request == null) { notice.send(emblems.song + "No songs in queue"); } else { switch (request.type) { case requesttype.dance: notice.send(emblems.song + request.user + ":Dance: " + request.song); break; case requesttype.karaoke: notice.send(emblems.song + request.user + ":Karaoke: " + request.song); break; case requesttype.play: notice.send(emblems.song + request.user + ":Play: " + request.song); break; } } return true; } return false; default: return false; } } songqueue.tryParse = tryParse; })(songqueue || (songqueue = {})); /** Represents the type of song request */ var requesttype; /** Represents the type of song request */ (function (requesttype) { requesttype[requesttype["dance"] = 0] = "dance"; requesttype[requesttype["karaoke"] = 1] = "karaoke"; requesttype[requesttype["play"] = 2] = "play"; })(requesttype || (requesttype = {})); /** * Represents a song request */ var songrequest = /** @class */ (function () { function songrequest(user, song, type) { if (type === void 0) { type = requesttype.play; } this.user = user; this.song = song; this.type = type; } return songrequest; }()); var tipmenu; (function (tipmenu) { "use strict"; /** * The specials menu section */ tipmenu.specials = new menusection("Specials"); /** * Specials command handler */ var special; (function (special) { /** * Print the help messages for the special manager * @param message Requesting message */ function help(message) { if (permissions.isAtLeastTrusted(message)) { notice.add("/special,specials"); notice.add(emblems.blank + "add <Cost> <Name> --Add the special to the menu"); notice.add(emblems.blank + "clr,clear --Clear all specials"); notice.add(emblems.blank + "del,delete <Name> --Delete the special from the menu"); notice.post(message.user); } } special.help = help; /** * Try to parse a specials command, returning true if a valid command is found * @param message Requesting message */ function tryParse(message) { if (!permissions.isAtLeastTrusted(message)) return false; var m = message.m.split(" "); if (m.length === 0) return false; var command = m.shift().toLowerCase(); switch (command) { case "/special": case "/specials": // Command is valid, break out break; default: return false; } if (m.length === 0) return false; var operation = m.shift().toLowerCase(); var name; // This is assigned while parsing operations switch (operation) { case "add": var cost = m.shift(); if (isNaN(Number(cost))) { // Cost wasn't at the beginning, try finding it at the end m.unshift(cost); cost = m.pop(); if (isNaN(Number(cost))) return false; // No cost found, not a valid command } // We've found the cost, the rest is the name name = m.join(" "); tipmenu.specials.add(name, Number(cost)); notice.send(emblems.tipmenu + "'" + name + "' added as a special for " + cost + emblems.token); return true; case "clr": case "clear": tipmenu.specials.clear(); notice.send(emblems.tipmenu + "All specials have been removed"); return true; case "del": case "delete": name = m.join(" "); tipmenu.specials.del(name); notice.send(emblems.tipmenu + "'" + name + "' has been removed from the specials"); return true; case "help": help(message); return true; default: return false; } } special.tryParse = tryParse; })(special = tipmenu.special || (tipmenu.special = {})); })(tipmenu || (tipmenu = {})); /** * Calculates various stats */ var stats; /** * Calculates various stats */ (function (stats) { "use strict"; function meanHalves(sendTo) { notice.add("Upper Mean: " + tippers.meanUpper()); notice.add("Lower Mean: " + tippers.meanLower()); notice.post(sendTo); } stats.meanHalves = meanHalves; function medianTip(sendTo) { notice.add("Median Tip: " + tippers.median()); notice.post(sendTo); } stats.medianTip = medianTip; function showDuration(sendTo) { var duration = timers.showDuration(); notice.add("Show Duration: " + duration[0] + ":" + duration[1] + ":" + duration[2]); notice.post(sendTo); } stats.showDuration = showDuration; function tippersTotal(sendTo) { notice.add("Tippers Total: " + tippers.count); notice.post(sendTo); } stats.tippersTotal = tippersTotal; function tokensPerHour(sendTo) { var duration = timers.showDuration(); var minutes = duration[0] * 60 + duration[1]; var rate = (tippers.tipped() / minutes) * 60; notice.add("Tokens Per Hour: " + rate); notice.post(sendTo); } stats.tokensPerHour = tokensPerHour; function tokensPerTipper(sendTo) { notice.add("Tokens Per Tipper: " + tippers.tipped() / tippers.count()); notice.post(sendTo); } stats.tokensPerTipper = tokensPerTipper; function tokensTotal(sendTo) { notice.add("Tokens Total: " + tippers.tipped()); notice.post(sendTo); } stats.tokensTotal = tokensTotal; })(stats || (stats = {})); /** * Tallies items within the various managers */ var tallier; /** * Tallies items within the various managers */ (function (tallier) { "use strict"; /** * The actual tallies */ var tallies = []; /** * Add to the tally * @param item Item to add * @param amount Amount to add */ function add(item, amount) { if (amount === void 0) { amount = 1; } var tally = lookup(item); if (tally == null) { tallies[tallies.length] = [item, amount]; } else { tally[1] += amount; } } tallier.add = add; /** * Clear the tallies */ function clear() { tallies = []; } tallier.clear = clear; /** * Calculate the highest tip */ function highest() { if (tallies == null || tallies === []) return null; var high = [null, 0]; for (var _i = 0, tallies_1 = tallies; _i < tallies_1.length; _i++) { var tally = tallies_1[_i]; if (tally[1] > high[1]) high = tally; } return high; } tallier.highest = highest; /** * Lookup the item, and return its tally, if any, null otherwise * @param item Item to look for */ function lookup(item) { for (var _i = 0, tallies_2 = tallies; _i < tallies_2.length; _i++) { var tally = tallies_2[_i]; if (tally[0] === item) return tally; } return null; } tallier.lookup = lookup; })(tallier || (tallier = {})); /** * Represents a teamate, a tipper belonging to a team */ var teamate = /** @class */ (function () { function teamate(tipper, points) { if (points === void 0) { points = 0; } this.tipper = tipper; this.points = points; } teamate.prototype.name = function () { return this.tipper.name; }; teamate.prototype.tipped = function () { return this.tipper.tipped; }; return teamate; }()); /** * Represents a team */ var team = /** @class */ (function () { function team(name, emblem, discount) { if (discount === void 0) { discount = 0; } /** Members of the team */ this.members = []; /** Name of this team */ this.name = ""; /** Emblem applied to members of this teams messages */ this.emblem = ""; /** * Discount inverted-ratio given to members of this team, off of the tipmenu * 0 is no discount, 0.15 is a 15% discount, etc. */ this.discount = 0; this.name = name; this.emblem = emblem; this.discount = discount; } /** * Add a user to the team * Because of a lack of data persistance, this is only temporary * @param user User to add */ team.prototype.add = function (user, points) { if (points === void 0) { points = 0; } var member = this.lookup(user); if (member !== null) return; // Already a member, so don't add again // See if the user is already a tipper var tipper = tippers.lookup(user); if (tipper === null) { // The user isn't a tipper, so create a dummy entry tippers.dummy(user); tipper = tippers.lookup(user); } // Add the tipper, and their points, to the team this.members[this.members.length] = new teamate(tipper, points); }; /** * Add the users to the team * Because of a lack of data persistance, this is only temporary * @param users Users to add */ team.prototype.adds = function () { var users = []; for (var _i = 0; _i < arguments.length; _i++) { users[_i] = arguments[_i]; } if (typeof users[0] === "string") { for (var _a = 0, _b = users; _a < _b.length; _a++) { var user_7 = _b[_a]; this.add(user_7); } } else { for (var _c = 0, _d = users; _c < _d.length; _c++) { var user_8 = _d[_c]; this.add(user_8[0], user_8[1]); } } }; /** * Apply the team emblem to a message if a member * @param message Message to apply emblem */ team.prototype.applyEmblem = function (message) { if (this.isMember(message)) { return this.emblem + message.m; } else { return message.m; } }; /** * Apply the appropriate discount to the cost if a member * @param item Item to discount * @param user Potentially elligable user */ team.prototype.applyDiscount = function (item, user) { // Is the user a member of this team? if (!this.isMember(user)) { // Not a member, so don't discount return item.cost; } else { // Calculate the user discount return Math.floor(item.cost * (1 - this.discount)); } }; /** * Delete the user from the team * @param user User to remove */ team.prototype.del = function (user) { cbjs.arrayRemove(this.members, this.lookup(user)); }; /** * Delete the users from the team * @param user Users to remove */ team.prototype.dels = function (users) { for (var _i = 0, users_3 = users; _i < users_3.length; _i++) { var user_9 = users_3[_i]; cbjs.arrayRemove(this.members, this.lookup(user_9)); } }; /** * Is the user a member of this team? * @param user User to check */ team.prototype.isMember = function (user) { var name; if (typeof user == "string") { name = user; } else { name = user.hasOwnProperty("from_user") ? user.from_user : user.user; } for (var _i = 0, _a = this.members; _i < _a.length; _i++) { var member = _a[_i]; if (member.name() == name) return true; } return false; }; /** * The number of members in the team */ team.prototype.length = function () { return this.members.length; }; /** * List the users in this team */ team.prototype.list = function (withPoints) { if (withPoints === void 0) { withPoints = false; } this.sort(); var result = []; if (withPoints) { var points = void 0; for (var _i = 0, _a = this.members; _i < _a.length; _i++) { var member = _a[_i]; points = member.points + member.tipped(); result[result.length] = "[" + points + "] " + member.name(); } } else { for (var _b = 0, _c = this.members; _b < _c.length; _b++) { var member = _c[_b]; result[result.length] = member.name(); } } return result; }; /** * Load the state string into the team * This is used to implement a sort of data persistance, although it must be managed by the user * @param state State string of the team */ team.prototype.load = function (state) { var users = state.trim().split(","); var name; var points; for (var _i = 0, users_4 = users; _i < users_4.length; _i++) { var user_10 = users_4[_i]; name = user_10.trim().split(" ")[0]; points = Number(user_10.trim().split(" ")[1]); this.add(name, points); } }; /** * Lookup the specified user * @param name Name to lookup */ team.prototype.lookup = function (name) { for (var _i = 0, _a = this.members; _i < _a.length; _i++) { var member = _a[_i]; if (member.name() == name) { return member; } } return null; }; /** * Save the state string for the team * This is used to implement a sort of data persistance, although it must be managed by the user */ team.prototype.save = function () { this.sort(); var state = ""; for (var _i = 0, _a = this.members; _i < _a.length; _i++) { var member = _a[_i]; state += member.name() + " " + (member.points + member.tipped()) + ", "; } state = state.substring(0, state.length - 2); //Removes the trailing comma return state; }; /** * Sort the team by points, most first */ team.prototype.sort = function () { this.members = this.members.sort(function (a, b) { return (b.points + b.tipped()) - (a.points + a.tipped()); }); }; /** * Get the total points of this team */ team.prototype.points = function () { var result; for (var _i = 0, _a = this.members; _i < _a.length; _i++) { var member = _a[_i]; result += member.points; } return result; }; return team; }()); /** * Represents a team of fanclub members * Used to implement team features for the fanclub far more efficiently */ var fanteam = /** @class */ (function (_super) { __extends(fanteam, _super); function fanteam() { return _super !== null && _super.apply(this, arguments) || this; } /** * Is the user a member of this team? * @param user User to check */ fanteam.prototype.isMember = function (user) { return user.hasOwnProperty("from_user") ? user.from_user_in_fanclub : user.in_fanclub; }; return fanteam; }(team)); /** * Represents a team of moderator members * Used to implement team features for the moderatores far more efficiently */ var modteam = /** @class */ (function (_super) { __extends(modteam, _super); function modteam() { return _super !== null && _super.apply(this, arguments) || this; } modteam.prototype.isMember = function (user) { return user.hasOwnProperty("from_user") ? user.from_user_is_mod : user.is_mod; }; return modteam; }(team)); /** * Manages teams and team related features */ var teams; /** * Manages teams and team related features */ (function (teams) { var pool = []; /** * Add the team * @param team Team to add */ function addTeam(team) { pool[pool.length] = team; } teams.addTeam = addTeam; /** * Add the user to the team if the team exists and the user is not already a member * @param user User to add * @param teamName Team name to add to */ function addToTeam(user, teamName) { var name; if (typeof user === "string") { name = user; } else { name = user.hasOwnProperty("from_user") ? user.from_user : user.user; } var team = lookup(teamName); if (team == null) return; if (!team.isMember(user)) team.add(name); } teams.addToTeam = addToTeam; /** * Apply the appropriate discount to the cost if a member * @param item Item to discount * @param user Potentially elligable user */ function applyDiscount(item, user) { cb.log("applyDiscount()"); var result = Number.MAX_VALUE; var discount = Number.MAX_VALUE; for (var _i = 0, pool_2 = pool; _i < pool_2.length; _i++) { var team = pool_2[_i]; discount = team.applyDiscount(item, user); cb.log("discount: " + discount); if (discount < result) { result = discount; cb.log("result: " + result); } } return result; } teams.applyDiscount = applyDiscount; /** * Apply the team emblem to a message if a member * @param message Message to apply emblem to, if applicable */ function applyEmblem(message) { var team = memberOf(message); if (team !== null) { return team.applyEmblem(message); } else { return message.m; } } teams.applyEmblem = applyEmblem; /** * Print the help menu for teams * @param message Requesting message */ function help(message) { if (permissions.isAtLeastModerator(message)) { notice.add("/team list --List the teams"); if (permissions.isAtLeastTrusted(message)) { notice.add("/team <Team> add <Users>+ --Add the specified users to the team"); notice.add("/team <Team> del,delete,rem,remove <Users>+ --Remove the specified users from the team"); } notice.add("/team <Team> list --List the members of the specifed team"); } notice.post(message.user); } teams.help = help; /** * Is the user a member of any team? * @param user User to check */ function isMember(user) { for (var _i = 0, pool_3 = pool; _i < pool_3.length; _i++) { var team = pool_3[_i]; if (team.isMember(user)) return true; } return false; } teams.isMember = isMember; /** * Is the user a member of the specified team? * @param user User to look up * @param teamName Team name to look in * @returns true if a member of the specified team, false if not, or false if the team does not exist */ function isMemberOf(user, teamName) { var team = lookup(teamName); if (team == null) return false; return team.isMember(user); } teams.isMemberOf = isMemberOf; /** * Attempt to look up the team by its name * @param teamName Team name to lookup * @returns The team if found, null otherwise */ function lookup(teamName) { for (var _i = 0, pool_4 = pool; _i < pool_4.length; _i++) { var team = pool_4[_i]; if (team.name == teamName) return team; } return null; } teams.lookup = lookup; /** * Get which team the user is a member of * @param user User to check * @returns The team if found, null otherwise */ function memberOf(user) { for (var _i = 0, pool_5 = pool; _i < pool_5.length; _i++) { var team = pool_5[_i]; if (team.isMember(user)) return team; } return null; } teams.memberOf = memberOf; /** * Try to parse a teams command, returning true if a valid command is found * @param message Requesting message */ function tryParse(message) { var m = message.m.split(" "); if (m.length === 0) return false; var command = m.shift().toLowerCase(); switch (command) { case "/team": case "/teams": break; default: return false; } if (m.length === 0) return false; var operation = m.shift().toLowerCase(); switch (operation) { case "help": help(message); return true; case "list": for (var _i = 0, pool_6 = pool; _i < pool_6.length; _i++) { var p = pool_6[_i]; notice.send(p.name, message.user); } return true; default: // The "command" seems to actually be a team name, so put it back, and begin parsing again m.push(operation); break; } var teamName = m.shift().toLowerCase(); var team = lookup(teamName); if (team == null) { notice.send("The given team '" + teamName + "' does not seem to exist", message.user); return false; } if (m.length === 0) return false; operation = m.shift().toLowerCase(); switch (operation) { case "add": for (var _a = 0, m_5 = m; _a < m_5.length; _a++) { var user = m_5[_a]; team.adds(user); } return true; case "del": case "delete": case "rem": case "remove": for (var _b = 0, m_6 = m; _b < m_6.length; _b++) { var user = m_6[_b]; team.del(user); } break; case "list": case "print": for (var _c = 0, _d = team.list(); _c < _d.length; _c++) { var teamate = _d[_c]; notice.send(teamate, message.user); } return true; default: return false; } } teams.tryParse = tryParse; })(teams || (teams = {})); /** * Represents a timer */ var timer = /** @class */ (function () { /** * Create a new timer * @param name Name of the timer * @param duration Duration of the timer, in seconds * @param delay Delay before the timer starts, in seconds */ function timer(name, duration, delay, onStart, onStop) { if (delay === void 0) { delay = 0; } this.name = name; this.duration = duration; this.remaining = duration; this.delay = delay; this.onStart = onStart; this.onStop = onStop; } /** * Extend the timer * @param seconds Seconds to extend by */ timer.prototype.extend = function (seconds) { this.duration += seconds; this.remaining += seconds; notice.send(emblems.timer + "'" + this.name + "' extended with " + seconds + "sec"); }; /** * Is the timer active? * This is true whether the timer is delayed or running * A timer is only inactive when it has stopped */ timer.prototype.isActive = function () { return this.delay > 0 || this.remaining > 0; }; /** * Is the timer currently delayed? */ timer.prototype.isDelayed = function () { return this.delay > 0; }; /** * Is the timer currently running? */ timer.prototype.isRunning = function () { return this.remaining < this.duration && this.remaining > 0; }; /** * Perform one tick of the timer, and call any events necessary */ timer.prototype.tick = function () { // Check event conditions if (this.delay === 0 && this.remaining === this.duration) { notice.send(emblems.timer + "'" + this.name + "' started with " + this.duration / 60 + "min"); if (this.onStart != null) this.onStart(); } else if (this.delay === 0 && this.remaining === 0) { notice.send(emblems.timer + "'" + this.name + "' has expired"); if (this.onStop != null) this.onStop(); } else if (this.delay === 0 && this.remaining % 60 === 0) { notice.send(emblems.timer + "'" + this.name + "' has " + this.remaining / 60 + "min remaining"); } // Time down as necessary if (this.delay > 0) { this.delay--; } else if (this.remaining > 0) { this.remaining--; } }; return timer; }()); /** * Manages timers */ var timers; /** * Manages timers */ (function (timers) { "use strict"; /** * Pool of running timers */ var pool = []; /** * Duration of the show, in seconds */ var showtime = 0; /** * Add the timer to the pool * @param name Name of the timer * @param duration Duration to run for, in seconds * @param delay Delay before start, in seconds * @param onStart Function to call on start * @param onStop function to call on stop */ function add(name, duration, delay, onStart, onStop) { if (delay === void 0) { delay = 0; } pool[pool.length] = new timer(name, duration, delay, onStart, onStop); if (delay > 0) { notice.send(emblems.timer + "'" + name + "' will start in " + delay + "s"); } } timers.add = add; /** * Clear the pool of all timers */ function clear() { pool = []; } timers.clear = clear; /** * Delete the specified timer without properly stopping it * @param name Timer name or position to delete */ function del(timer) { if (typeof timer === "number") { notice.send(emblems.timer + "'" + pool[timer].name + "' has been removed"); pool = cbjs.arrayRemove(pool, pool[timer]); } else if (typeof timer === "string") { if (cbjs.arrayContains(pool, lookup(timer))) { notice.send(emblems.timer + "'" + timer + "' has been removed"); pool = cbjs.arrayRemove(pool, lookup(timer)); } } } timers.del = del; /** * Extend the timer by duration * @param name Name of the timer * @param duration Duration, in seconds, to extend run for */ function extend(name, duration) { var timer = lookup(name); if (timer != null) { timer.extend(duration); } } timers.extend = extend; /** * Prints the help menu for timers * @param message Requesting message */ function help(message) { if (permissions.isAtLeastModerator(message)) { notice.add("/timer,timers"); notice.add(emblems.blank + "add,start <Duration> <Name> --Add and start the timer"); } if (permissions.isAtLeastTrusted(message)) { notice.add(emblems.blank + "clr,clear --Clear and stop all timers"); notice.add(emblems.blank + "del,delete (<Name> | <Position>) --Delete the timer without any stop events"); notice.add(emblems.blank + "ext,extend <Duration> <Name> --Extend the timer"); } notice.add(emblems.blank + "list,print --List all active timers"); if (permissions.isAtLeastTrusted(message)) { notice.add(emblems.blank + "stop (<Name | <Position>) --Stop the timer next tick"); } notice.post(message.user); } timers.help = help; /** * List all active timers */ function list() { return pool; } timers.list = list; /** * Lookup the timer in the pool, null if not found * @param name Name to lookup */ function lookup(name) { for (var _i = 0, pool_7 = pool; _i < pool_7.length; _i++) { var timer_1 = pool_7[_i]; if (timer_1.name.toLowerCase() == name.toLowerCase()) { return timer_1; } } return null; } timers.lookup = lookup; /** * Get the current duration of the show * This is formatted time: [hours, minutes, seconds] */ function showDuration() { var hours = 0; var minutes = 0; var seconds = showtime; while (seconds >= 3600) { seconds -= 3600; hours += 1; } while (seconds >= 60) { seconds -= 60; minutes += 1; } return [hours, minutes, seconds]; } timers.showDuration = showDuration; /** * Start the timers */ function start() { cb.setTimeout(tick, 1000); } timers.start = start; /** * Set the timer to stop next tick * @param timer Timer to stop */ function stop(timer) { if (typeof timer === "number") { if (pool[timer] != null) pool[timer].remaining = 0; } else if (typeof timer === "string") { var t = lookup(timer); if (t != null) { t.remaining = 0; } } } timers.stop = stop; /** * Count down one interval */ function tick() { var keep = []; showtime += 1; for (var _i = 0, pool_8 = pool; _i < pool_8.length; _i++) { var timer_2 = pool_8[_i]; if (timer_2.isActive()) keep[keep.length] = timer_2; timer_2.tick(); } if (pool !== keep) { pool = keep; } cb.setTimeout(tick, 1000); } /** * Try to parse a timer command, returning true if a valid command is found * @param message Requesting message */ function tryParse(message) { var m = message.m.split(" "); if (m.length === 0) return false; var command = m.shift().toLowerCase(); switch (command) { case "/timer": case "/timers": // Command is valid, break out break; default: return false; } if (m.length === 0) return false; var operation = m.shift().toLowerCase(); var name; // This is assigned while parsing operations var duration; // This is assigned while parsing operations var pos; // This is assigned while parsing operations switch (operation) { case "add": case "start": if (!permissions.isAtLeastModerator(message)) return false; duration = m.shift(); if (isNaN(Number(duration))) { // Duration wasn't at the beginning, try finding it at the end m.unshift(duration); duration = m.pop(); if (isNaN(Number(duration))) return false; // No duration found, not a valid command } // We've found the duration, the rest is the name name = m.join(" "); timers.add(name, Number(duration) * 60); return true; case "clr": case "clear": if (!permissions.isAtLeastTrusted(message)) return false; timers.clear(); return true; case "del": case "delete": if (!permissions.isAtLeastTrusted(message)) return false; pos = m.shift(); if (isNaN(Number(pos))) { // pos isn't actually a position, so put it back m.unshift(pos); timers.del(m.join(" ")); } else { timers.del(Number(pos) - 1); } return true; case "ext": case "extend": if (!permissions.isAtLeastTrusted(message)) return false; duration = m.shift(); if (isNaN(Number(duration))) { // Duration wasn't at the beginning, try finding it at the end m.unshift(duration); duration = m.pop(); if (isNaN(Number(duration))) return false; // No duration found, not a valid command } // We've found the duration, the rest is the name name = m.join(" "); timers.extend(name, Number(duration) * 60); return true; case "help": help(message); return true; case "list": case "print": var i = 0; for (var _i = 0, pool_9 = pool; _i < pool_9.length; _i++) { var timer_3 = pool_9[_i]; notice.add(++i + ") '" + timer_3.name + "' with " + timer_3.remaining + "s"); } notice.apply(emblems.timer); notice.post(message.user); return true; case "stop": if (!permissions.isAtLeastTrusted(message)) return false; pos = m.shift(); if (isNaN(Number(pos))) { // pos isn't actually a position, so put it back m.unshift(pos); timers.stop(m.join(" ")); } else { timers.stop(Number(pos) - 1); } return true; default: return false; } } timers.tryParse = tryParse; })(timers || (timers = {})); /** * Represents a tipper; a user who as tipped */ var tipper = /** @class */ (function () { function tipper(name, tipped) { this.name = name; this.tipped = tipped; } return tipper; }()); /** * Manages and records tippers */ var tippers; /** * Manages and records tippers */ (function (tippers) { "use strict"; /** * All the tippers this show */ var pool = []; /** * Add the tip, incrementing an existing tipper, or adding a new one * @param tip Tip to add */ function add(tip) { var candidate = lookup(tip.from_user); if (candidate == null) { pool[pool.length] = new tipper(tip.from_user, 0); candidate = pool[pool.length - 1]; } candidate.tipped += tip.amount; } tippers.add = add; /** * Get the total amount of tippers */ function count() { return pool.length; } tippers.count = count; /** * Adds a dummy tipper * This creates an entry in the tippers manager, with no tip amount, which is necessary for teams * This should never, ever, be called outside of initialization * @param name Name of the tipper */ function dummy(name) { pool[pool.length] = new tipper(name, 0); } tippers.dummy = dummy; /** * Lookup the user, null if not found * @param user User to look up */ function lookup(user) { for (var _i = 0, pool_10 = pool; _i < pool_10.length; _i++) { var tipper_1 = pool_10[_i]; if (tipper_1.name === user) return tipper_1; } return null; } tippers.lookup = lookup; /** * Return the mean of the lower half */ function meanLower() { sort(); var lower = pool.slice(0, pool.length); var total = 0; for (var _i = 0, lower_1 = lower; _i < lower_1.length; _i++) { var tipper_2 = lower_1[_i]; total += tipper_2.tipped; } return total / lower.length; } tippers.meanLower = meanLower; /** * Return the mean of the upper half */ function meanUpper() { sort(); var upper = pool.slice(pool.length / 2, pool.length); var total = 0; for (var _i = 0, upper_1 = upper; _i < upper_1.length; _i++) { var tipper_3 = upper_1[_i]; total += tipper_3.tipped; } return total / upper.length; } tippers.meanUpper = meanUpper; /** * Return the median tip */ function median() { sort(); if (pool[Math.floor(pool.length / 2)] == null) { return NaN; } else { return pool[Math.floor(pool.length / 2)].tipped; } } tippers.median = median; /** * Sort the tippers, highest first */ function sort() { pool = pool.sort(function (a, b) { return b.tipped - a.tipped; }); } tippers.sort = sort; /** * Return the specified amount of top tippers * This is used to fetch a leaderboard, although it has other uses * @param amount Amount of tippers from the top to get */ function top(amount) { sort(); return pool.slice(0, amount); } tippers.top = top; /** * Get the total amount tipped */ function tipped() { var total = 0; for (var _i = 0, pool_11 = pool; _i < pool_11.length; _i++) { var tipper_4 = pool_11[_i]; total += tipper_4.tipped; } return total; } tippers.tipped = tipped; })(tippers || (tippers = {})); /** * Tracks viewers for stats purposes * Don't take the gender stats too seriously: people lie. This is just a curiousity. */ var viewers; /** * Tracks viewers for stats purposes * Don't take the gender stats too seriously: people lie. This is just a curiousity. */ (function (viewers) { "use strict"; viewers.current = 0; viewers.withTokens = 0; viewers.inFanclub = 0; viewers.claimMale = 0; viewers.claimFemale = 0; viewers.claimTrans = 0; viewers.claimCouple = 0; function enter(user) { viewers.current += 1; if (user.has_tokens) viewers.withTokens += 1; if (user.in_fanclub) viewers.inFanclub += 1; if (user.gender == "m") viewers.claimMale += 1; if (user.gender == "f") viewers.claimFemale += 1; if (user.gender == "s") viewers.claimTrans += 1; if (user.gender == "c") viewers.claimTrans += 1; } viewers.enter = enter; function leave(user) { viewers.current -= 1; if (user.has_tokens) viewers.withTokens -= 1; if (user.in_fanclub) viewers.inFanclub -= 1; if (user.gender == "m") viewers.claimMale -= 1; if (user.gender == "f") viewers.claimFemale -= 1; if (user.gender == "s") viewers.claimTrans -= 1; if (user.gender == "c") viewers.claimTrans -= 1; } viewers.leave = leave; })(viewers || (viewers = {})); /** * Implements whispers */ var whisper; /** * Implements whispers */ (function (whisper) { "use strict"; /** * Print the help messages for whispers * @param message Requesting message */ function help(message) { if (permissions.hasAtLeastTokens(message)) { notice.add("/w,whisper"); notice.add(emblems.blank + "model <Message> --Send a message to the model"); notice.add(emblems.blank + "mod,mods,moderator,moderators <Message> --Send a message to all moderators"); notice.add(emblems.blank + "<User> <Message> --Send a message to the user"); notice.post(message.user); notice.clear(); } } whisper.help = help; /** * Do model whisper specific stuff * @param message Requesting message * @param m Remaining message */ function model(message, m) { // While not the case elsewhere, this command uses the permissions level to color the whisper, not just permit it. if (permissions.isTrusted(message)) notice.send(emblems.whisper + message.user + ": " + m, cb.room_slug, "#DF0400", "bolder"); else if (permissions.isModerator(message)) notice.send(emblems.whisper + message.user + ": " + m, cb.room_slug, "#AC3731", "bolder"); else if (permissions.isInFanclub(message)) notice.send(emblems.whisper + message.user + ": " + m, cb.room_slug, "#5F8D6F"); else if (permissions.hasTokens(message)) notice.send(emblems.whisper + message.user + ": " + m, cb.room_slug, "#0076C0"); } /** * Do mod whisper specific stuff * @param message Requesting message * @param m Remaining message */ function mods(message, m) { notice.add(emblems.whispermod + message.user + ": " + m); notice.post(cb.room_slug, "#C10A00", "bolder", false); notice.postGroup("red", "#BB1515", "bolder", false); notice.clear(); } /** * Try to parse a whisper command, returning true if a valid command is found * @param message Requesting message */ function tryParse(message) { var m = message.m.split(" "); if (m.length === 0) return false; var command = m.shift().toLowerCase(); switch (command) { case "/model": model(message, m.join(" ")); notice.send(emblems.whisper + "Sent to: " + cb.room_slug, message.user); return true; case "/mod": case "/mods": case "/moderator": case "/moderators": mods(message, m.join(" ")); notice.send(emblems.whispermod + "Sent to all moderators", message.user); return true; case "/w": case "/whisper": // Command is valid but needs further parsing, break out break; default: return false; } if (m.length === 0) return false; var target = m.shift().toLowerCase(); switch (target) { case "help": //Not actually a target, but an option, so print help and return help(message); return true; case "model": model(message, m.join(" ")); notice.send(emblems.whisper + "Sent to: " + cb.room_slug, message.user); return true; case "mod": case "mods": case "moderator": case "moderators": mods(message, m.join(" ")); notice.send(emblems.whispermod + "Sent to all moderators", message.user); return true; default: if (target.toLowerCase() === cb.room_slug) { model(message, m.join(" ")); } else if (message.user === cb.room_slug) { notice.send(emblems.whisper + message.user + ": " + m.join(" "), target, "#AC3731"); } else { notice.send(emblems.whisper + message.user + ": " + m.join(" "), target, "#FF3C00", "normal"); } notice.send(emblems.whisper + "Sent to: " + target, message.user); return true; } } whisper.tryParse = tryParse; })(whisper || (whisper = {})); cb.onEnter(function (user) { notice.adds(":welcometomyroom1", "Welcome " + user['user'] + "! My name is Hailey, nice to meet you.", "PM 10tks | PVT 60tks/min | GROUP 18tks/min", "To check out my Tip Menu type /menu", "To see available commands, enter /roomhelp in chat", "If you're new, please don't forgot to hit the :follow button!"); notice.apply(emblems.notice); notice.post(user.user); viewers.enter(user); if (user.is_mod) { teams.addToTeam(user, "mods"); } var modelName = cb.room_slug; var name = user['user']; if (modelName != 'cinderella77' && modelName != '_atze_') { cb.sendNotice('###################################\n ###################################\n\n Hi ' + user['user'] + '!\n\n THIS BOT WAS CREATED FOR cinderella77 \n\nTHIS IS NOT cinderella77\'s ROOM!\n\nFOLLOW HER ON CB: \nhttps://chaturbate.com/cinderella77/\n\n###################################\n ###################################','','#FF0000','#FFFFFF','bold'); } // Welcome and track users as they join - part of timelock gray chat code var username = user['user']; // If new, start tracking if (isNew(username)) { log.info("New user entered: " + username); log.debug(user); addUser(user); // Track enter time } else { log.info("User re-entered: " + username); log.debug(user); } // Send appropriate welcome message to greys if (!canSpeak(user) && cb.settings.timelock_duration !== 0) { welcomeUser(username); // Send welcome msg } });///end timelock gray chat code function notModel() { var modelName = cb.room_slug; var output = '###################################'; output += '\n###################################'; output += '\n\nHEY, ' + modelName + '! \n\nTHIS BOT WAS CREATED FOR '; output += 'cinderella77, \n\nYOU ARE SOMEONE ELSE.\n\n'; output += 'PLEASE CONSIDER USING A DIFFERENT BOT. \nTHANKS.\n\n'; output += '###################################\n'; output += '###################################'; return output; } cb.sendNotice(); var modelName = cb.room_slug; if (modelName !='cinderella77' && modelName != '_atze_') cb.sendNotice(notModel(),modelName, '#FF0000', '#FFFFFF', 'bold'); cb.onLeave(function (user) { if (hightip.name() !== null && hightip.name() === user.user) { notice.send(emblems.notice + "King " + hightip.name() + " has left... Quick, steal the" + emblems.crown); } viewers.leave(user); // Timelock Gray Chat - Leave function is required by CB, but not used by this script. var username = user.user; log.info("User left: " + username);///tlg end }); "use strict"; cb.onMessage(function (message) { ///TLG code var username = message.user; var user = message; // Msg includes user info, so we can treat it as such var txt = message.m; log.debug("Message received:"); log.debug(message); log.debug("User is grey? " + isGrey(user)); // Check if we should hide this message if (!canSpeak(user)) { var left = timeLeft(username); var msg_locked = "TimeLockGreys: You are timelocked and cannot chat for another {0} minutes (if Silence Level: 0)."; message["X-Spam"] = true; // Set flag to hide chat from room tellUser(msg_locked.format(left), username); log.info("Silenced message from " + username); } // If looks like a command, hide it and try running it if (isCmd(txt)) { message["X-Spam"] = true; // Set flag to hide chat from room runCmd(message); }///TLG code end // Mark a message as spam if a foreslash is found at the begining if (message.m.trim().charAt(0) === "/") message['X-Spam'] = true; /** Whether a valid command has been found while parsing */ var validCommand = false; // Attempt to parse a command // This is goal-directed parsing, essentially, JavaScript just doesn't have any good syntax for it // While a command has not been found, keep trying to parse commands // When a command has been found, mark it as spam, which in turn avoids further attempts at parsing if (!validCommand) { validCommand = hightip.tryParse(message); } if (!validCommand) { validCommand = leaderboard.tryParse(message); } if (!validCommand) { validCommand = notice.tryParse(message); } if (!validCommand) { validCommand = room.tryParse(message); } if (!validCommand) { validCommand = rotater.tryParse(message); } if (!validCommand) { validCommand = tipmenu.special.tryParse(message); } if (!validCommand) { validCommand = stats.tryParse(message); } if (!validCommand) { validCommand = timers.tryParse(message); } if (!validCommand) { validCommand = tipmenu.tryParse(message); } if (!validCommand) { validCommand = whisper.tryParse(message); } if (!validCommand) { validCommand = bouncer.tryParse(message); } if (!validCommand) { validCommand = dozer.tryParse(message); } if (!validCommand) { validCommand = filter.graphiclevel.tryParse(message); } if (!validCommand) { validCommand = filter.silencelevel.tryParse(message); } if (!validCommand) { validCommand = permissions.tryParse(message); } if (!validCommand) { validCommand = silences.tryParse(message); } if (message['X-Spam'] || validCommand) return message; // Run the filters on the message filter.silencelevel.check(message); filter.graphiclevel.check(message); if (silences.isSilenced(message.user)) { message['X-Spam'] = true; } if (silences.isUnsilenced(message.user)) { message['X-Spam'] = false; } if (!message['X-Spam'] && cb.settings.botfilter == "on") filter.bot.check(message); if (!message['X-Spam'] && cb.settings.adfilter == "on") filter.advertisements.checkCam(message); if (!message['X-Spam'] && cb.settings.adfilter == "on") filter.advertisements.checkProfile(message); if (!message['X-Spam'] && cb.settings.demandfilter == "on") filter.demands.check(message); if (!message['X-Spam'] && cb.settings.dirtytalkfilter == "on") filter.dirtytalk.check(message); if (!message['X-Spam'] && cb.settings.websitefilter == "on") filter.website.check(message); // Apply Emblems if (permissions.isTrusted(message)) { message.m = " :enchanted14 " + message.m; } else message.m = teams.applyEmblem(message); // Apply Tip Amount var tipper = tippers.lookup(message.user); if (tipper !== null && tipper.tipped !== 0) { message.m = "[" + tippers.lookup(message.user).tipped + "] " + message.m; } //Random Background Colors and Emotjis var emo=[":cutehug",":angel",":heheface3a",":dance3",":blush",":cool",":huh",":roll",":mellow",":ohmy",":smile",":thumbup",":wink",":woot",":bounce",":hello",":angel",":crazy",":thumbsup",":yes",":hearts",":happy1a",":innocent",":gangsta",":dancingbanana",":kissy",":help",":bow",":hello",":huh",":drool",":shi",":twerky1a",":hihi",":shello",":lolll"]; var color=["#ffb6c1","#ff82ab","#ee6aa7","#ff83fa","#d8bfd8","#eeaeee","#6495ed","#bcd2ee","#63b8ff","#87cefa","#8ee5ee","#00f5ff","#8deeee","#00eeee","#76eec6","#4eee94","#b4eeb4","#9aff9a","#7fff00","#adff2f","#bcee68","#9acd32","#cdcdb4","#eeee00","#ffd700","#ffc125","#eecfa1","#e3a869","#eecbad","#ff7256","#eeb4b4","#71c671","#c5c1aa","#ff9999","#fff68f","#f4862a"]; var i=Math.floor((Math.random()*35)+1); var j=Math.floor((Math.random()*35)+1); if (cb.settings.random_bg == "on" && !isCmd(txt)) message.background=color[i]; if (cb.settings.random_emote == "on" && !isCmd(txt)) message.m +=" ... "+emo[j]; // Return the message return message; }); cb.onTip(function (tip) { handleTip(tip.amount, tip.from_user); tippers.add(tip); var match = tipmenu.match(tip); hightip.compare(tip); if (match != null) { notice.send(emblems.tipmenu + tip.from_user + " has tipped for " + match.name); match.handle(tip); } }); var handlers; (function (handlers) { function addEnchante(tip) { teams.addToTeam(tip, "enchanted"); } handlers.addEnchante = addEnchante; function shorts(_tip, amount) { var timer = timers.lookup("No Shorts"); if (timer != null) { timer.extend(amount * 60); } else { timers.add("No Shorts", amount * 60, 15); } } handlers.shorts = shorts; function shirt(_tip, amount) { var timer = timers.lookup("No Shirt"); if (timer != null) { timer.extend(amount * 60); } else { timers.add("No Shirt", amount * 60, 15); } } handlers.shirt = shirt; function mute(_tip, amount) { var timer = timers.lookup("Mute"); if (timer != null) { timer.extend(amount * 60); } else { timers.add("Shirt", amount * 60, 15); } } handlers.mute = mute; function nippleClamps(_tip, amount) { var timer = timers.lookup("Nipple Clamps"); if (timer != null) { timer.extend(amount * 60); } else { timers.add("Nipple Clamps", amount * 60, 30); } } handlers.nippleClamps = nippleClamps; function ballgag() { var timer = timers.lookup("Ballgag"); if (timer != null) { timer.extend(5 * 60); } else { timers.add("Ballgag", 5 * 60, 30); } } handlers.ballgag = ballgag; })(handlers || (handlers = {})); /** * Misc. room stuff */ var room; /** * Misc. room stuff */ (function (room) { /** * Prints the full help menu * @param message Requesting message */ function help(message) { notice.help(message); permissions.help(message); rotater.help(message); tipmenu.special.help(message); stats.help(message); timers.help(message); tipmenu.help(message); whisper.help(message); } /** * Try to parse a room command, returning true if a valid command is found * @param message Requesting message */ function tryParse(message) { var m = message.m.split(" "); if (m.length === 0) return false; var command = m.shift().toLowerCase(); switch (command) { case "/room": if (m.length === 0) return false; var command_1 = m.shift().toLowerCase(); switch (command_1) { case "help": break; default: return false; } // This deliberately falls through break; case "/roomhelp": help(message); return true; } return false; } room.tryParse = tryParse; })(room || (room = {})); var cb; (function (cb) { cb.settings_choices = [ { name: "rotater0", label: "Rotating Notice", type: "str", minLength:1, maxLength:800, defaultValue:'Blow A Kiss(5) | PM(10) | Continue What I\'m Doing(16) | Song Request(24) | Stand Up(25) | Look In Cam(30) | Dance(45) | Spank Booty(50) | Suck Finger(55) | Close-up Booty Shaking(59) | Feet Show(65) | Slap On The Cheek(80) | Wear Very High Heels(90) | Walk Like A Kitty(95) | I Love You, Hailey!(100) | Take Off Shorts For 10 Minutes(120) | Show Ass(130) | Doggy In Panties(140) | Take Off Shirt For 10 Minutes(150) | Change Into Maid Costume(175) | Change Into Policewoman Costume(176) | Show Boobs(190) | Close-up Masturbating In Panties(220) | Join The Enchanted(333) | Make Me Happy(555) | My Best Day(10000)', required: false }, { name: "rotater1", label: "Rotating Notice", type: "str", minLength:1, maxLength:255, defaultValue:'PM 10tks | PVT 60tks/min | GROUP 18tks/min', required: false }, { name: "rotater2", label: "Rotating Notice", type: "str", minLength:1, maxLength:255, defaultValue:':typemenu4a', required: false }, { name: "rotater3", label: "Rotating Notice", type: "str", minLength:1, maxLength:255, defaultValue:':alltipss', required: false }, { name: "rotater4", label: "Rotating Notice", type: "str", minLength:1, maxLength:255, required: false }, { name: "rotater5", label: "Rotating Notice", type: "str", minLength:1, maxLength:255, required: false }, { name: "rotater6", label: "Rotating Notice", type: "str", minLength:1, maxLength:255, required: false }, { name: "rotater7", label: "Rotating Notice", type: "str", required: false }, { name: "rotater8", label: "Rotating Notice", type: "str", required: false }, { name: "silencelevel", label: "Silence Level", type: "choice", choice1: "grey", choice2: "lightblue", choice3: "darkblue", choice4: "lightpurple", choice5: "darkpurple", choice6: "green", choice7: "red", choice8: "orange", defaultValue : "grey", required: true, }, { name: "graphiclevel", label: "Graphic Level", type: "choice", choice1: "grey", choice2: "lightblue", choice3: "darkblue", choice4: "lightpurple", choice5: "darkpurple", choice6: "green", choice7: "red", choice8: "orange", defaultValue : "lightblue", required: true, }, { name: "adfilter", label: "Advertisement Filter", type: "choice", choice1: "on", choice2: "off", defaultValue: "on", required: true, }, { name: "botfilter", label: "Bot Filter", type: "choice", choice1: "on", choice2: "off", defaultValue: "on", required: true, }, { name: "demandfilter", label: "Demand Filter", type: "choice", choice1: "on", choice2: "off", defaultValue: "on", required: true, }, { name: "dirtytalkfilter", label: "Dirty Talk Filter", type: "choice", choice1: "on", choice2: "off", defaultValue: "on", required: true, }, { name: "websitefilter", label: "Website Filter", type: "choice", choice1: "on", choice2: "off", defaultValue: "on", required: true, }, { name: "bcdetails", label: "Filter Details: Broadcaster", type: "choice", choice1: "on", choice2: "off", defaultValue: "on", required: true, }, { name: "moddetails", label: "Filter Details: Moderator", type: "choice", choice1: "on", choice2: "off", defaultValue: "on", required: true, }, { name: "modexception", label: "Filter Exception: Moderators", type: "choice", choice1: "on", choice2: "off", defaultValue: "on", required: true, }, { name: "fcexception", label: "Filter Exception: Fanclub", type: "choice", choice1: "on", choice2: "off", defaultValue: "on", required: true, }, { name: 'rate', type: 'choice', choice1: 'yes', choice2: 'no', defaultValue: 'yes', label: "thumbs up reminder for tips of 25tks or more" }, { name: "timelock_duration", type: "int", minValue: 0, maxValue: 99, defaultValue: 2, label: "grays must wait this many minutes before they can chat (0-99)\n [Silence Level has priority]" }, { name: "random_bg", label: "Random background colors for messages", type: "choice", choice1: "on", choice2: "off", defaultValue: "off", required: true, }, { name: "random_emote", label: "Add random emotes at the end of messages", type: "choice", choice1: "on", choice2: "off", defaultValue: "off", required: true, }, { name: "enchanted", label: "Enchanted Users (space delimited)", type: "str", required: false }, { name: "trusted", label: "Trusted Users (space delimited)", type: "str", required: false } ]; })(cb || (cb = {})); var stats; (function (stats) { "use strict"; /** * Prints the help for stats * @param message Requesting message */ function help(message) { if (permissions.isAtLeastTrusted(message)) { notice.add("/stats,statistics --Get all calculated stats"); notice.post(message.user); message['X-Spam'] = true; } } stats.help = help; /** * Print all the stats * @param message Requesting message */ function print(message) { stats.showDuration(message.user); stats.tokensTotal(message.user); stats.tippersTotal(message.user); stats.tokensPerHour(message.user); stats.tokensPerTipper(message.user); stats.meanHalves(message.user); stats.medianTip(message.user); listViewers(message.user); } stats.print = print; function listViewers(sendTo) { notice.add("Viewers (Signed In): " + viewers.current); notice.add("Viewers (With Tokens): " + viewers.withTokens); notice.post(sendTo); } stats.listViewers = listViewers; /** * Try to parse a stats command, returning true if a valid command is found * @param message Requesting message */ function tryParse(message) { if (permissions.isAtLeastTrusted(message)) { var m = message.m.split(" "); if (m.length === 0) return false; var command = m.shift().toLowerCase(); switch (command) { case "/stats": case "/statistcs": print(message); return true; default: return false; } } return false; } stats.tryParse = tryParse; })(stats || (stats = {})); /** * Manages the tipmenu as well as related functions * Unlike with most other implementations, in this instance we actually need "tables" of the correct items and prices, and to lookup the correct item and price in the correct table based on the person */ var tipmenu; /** * Manages the tipmenu as well as related functions * Unlike with most other implementations, in this instance we actually need "tables" of the correct items and prices, and to lookup the correct item and price in the correct table based on the person */ (function (tipmenu) { tipmenu.customSelector = false; tipmenu.normalTable = new menusection("Main", new menuitem("Blow A Kiss", 5), new menuitem("PM", 10), new menuitem("Continue What I'm Doing", 16), new menuitem("Song Request", 24), new menuitem("Stand Up", 25), new menuitem("Look In Cam", 30), new menuitem("Dance", 45), new menuitem("Spank Booty", 50), new menuitem("Suck Finger", 55), new menuitem("Close-up Booty Shaking", 29), new menuitem("Feet Show", 65), new menuitem("Slap Cheek", 80), new menuitem("Wear Very High Heels", 90), new menuitem("Walk Like A Kitty", 95), new menuitem("I Love You, Hailey!", 100), new menuitem("Take Off Shorts (10mins)", 120, handlers.shorts, 10), new menuitem("Show Ass", 130), new menuitem("Doggy In Panties", 140), new menuitem("Take Off Shirt (10mins)", 150, handlers.shirt, 10), new menuitem("Change Into Maid Costume", 175), new menuitem("Change Into Policewoman Costume", 176), new menuitem("Show Boob", 190), new menuitem("Close-up Masturbating in Panties", 220), new menuitem("Join The Enchanted", 333, handlers.addEnchante), new menuitem("Make Me Happy", 555), new menuitem("My Best Day", 10000)); tipmenu.customTable = new menusection("Main"); tipmenu.enchantedTable = new menusection("Main", new menuitem("Blow A Kiss", 5), new menuitem("PM", 10), new menuitem("Continue What I'm Doing", 16), new menuitem("Song Request", 24), new menuitem("Stand Up", 25), new menuitem("Look In Cam", 30), new menuitem("Dance", 45), new menuitem("Spank Booty", 50), new menuitem("Suck Finger", 55), new menuitem("Close-up Booty Shaking", 29), new menuitem("Feet Show", 65), new menuitem("Slap Cheek", 80), new menuitem("Wear Very High Heels", 90), new menuitem("Walk Like A Kitty", 95), new menuitem("I Love You, Hailey!", 100), new menuitem("Take Off Shorts (10mins)", 120, handlers.shorts, 10), new menuitem("Show Ass", 130), new menuitem("Doggy In Panties", 140), new menuitem("Take Off Shirt (10mins)", 150, handlers.shirt, 10), new menuitem("Change Into Maid Costume", 175), new menuitem("Change Into Policewoman Costume", 176), new menuitem("Show Boob", 190), new menuitem("Close-up Masturbating in Panties", 220), new menuitem("Join The Enchanted", 333, handlers.addEnchante), new menuitem("Make Me Happy", 555), new menuitem("My Best Day", 10000)); tipmenu.enchantedCustomTable = new menusection("Main"); /** * Print the help messages for tipmenu * @param message Requesting message */ function help(message) { notice.add("/menu --Get the entire tipmenu"); notice.add(emblems.blank + "<Section>+ --Get only the specified sections"); notice.add(emblems.blank + "limit <Cost> --Get all items lesser or equal to the specified cost"); if (permissions.isAtLeastTrusted(message)) { notice.add(emblems.blank + "set (<Flag> <Level>)+ --Set each specified flag to level, modifying the tipmenu"); } notice.post(message.user); } tipmenu.help = help; /** * Attempt to match the tip to an item in the menu * @param tip Tip to match */ function match(tip) { cb.log("match()"); for (var _i = 0, _a = tipmenu.specials.list(); _i < _a.length; _i++) { var item = _a[_i]; if (tip.amount === item.cost) return item; } if (tipmenu.customSelector) { cb.log("custom menu"); if (teams.isMemberOf(tip, "enchanted") || teams.isMemberOf(tip, "mods")) { cb.log("discounted"); for (var _b = 0, _c = tipmenu.enchantedCustomTable.list(); _b < _c.length; _b++) { var item = _c[_b]; if (tip.amount === item.cost) { cb.log("matched item: " + item.name); return item; } } } else { for (var _d = 0, _e = tipmenu.customTable.list(); _d < _e.length; _d++) { var item = _e[_d]; if (tip.amount === item.cost) { cb.log("matched item: " + item.name); return item; } } } } else { cb.log("normal menu"); if (teams.isMemberOf(tip, "enchanted") || teams.isMemberOf(tip, "mods")) { cb.log("discounted"); for (var _f = 0, _g = tipmenu.enchantedTable.list(); _f < _g.length; _f++) { var item = _g[_f]; cb.log("item: " + item.cost + " " + item.name); if (tip.amount === item.cost) { cb.log("matched item: " + item.name); return item; } } } else { for (var _h = 0, _j = tipmenu.normalTable.list(); _h < _j.length; _h++) { var item = _j[_h]; if (tip.amount === item.cost) { cb.log("item: " + item.cost + " " + item.name); cb.log("matched item: " + item.name); return item; } } } } return null; } tipmenu.match = match; /** * Print the tipmenu to chat * @param message Requesting message */ function print(message, limit, flags) { if (limit === void 0) { limit = null; } if (flags === void 0) { flags = [true, true]; } if (flags[0]) tipmenu.specials.print(message, limit); if (flags[1]) { if (tipmenu.customSelector) { if (teams.isMemberOf(message, "enchanted") || teams.isMemberOf(message, "mods")) { tipmenu.enchantedCustomTable.print(message, limit); } else { tipmenu.customTable.print(message, limit); } } else { if (teams.isMemberOf(message, "enchanted") || teams.isMemberOf(message, "mods")) { tipmenu.enchantedTable.print(message, limit); } else { tipmenu.normalTable.print(message, limit); } } } } tipmenu.print = print; /** * Try to parse a tipmenu command, returning true if a valid command is found * @param message Requesting message */ function tryParse(message) { var m = message.m.split(" "); if (m.length === 0) return false; var command = m.shift().toLowerCase(); switch (command) { case "/menu": case "/tipmenu": if (m.length === 0) { print(message); return true; } else { // Generally, this assumes it's parsing a list of sections to print. However, it does a check if a flag setter is being used. var sections = [false, false]; var word = void 0; while (m.length !== 0) { word = m.shift().toLowerCase(); switch (word) { case "help": tipmenu.help(message); return true; case "limit": if (m.length === 0) return false; var limit = m.shift(); if (isNaN(Number(limit))) return false; print(message, Number(limit)); return true; case "main": sections[1] = true; break; case "special": case "specials": sections[0] = true; break; } } print(message, null, sections); for (var _i = 0, sections_1 = sections; _i < sections_1.length; _i++) { var section = sections_1[_i]; if (section) return true; } return false; } break; default: return false; } } tipmenu.tryParse = tryParse; })(tipmenu || (tipmenu = {})); /** * Initialization Code */ { notice.color = "#094E94"; permissions.entrust("_atze_"); teams.addTeam(new team("models", " :enchanted16 ")); if (teams.lookup("models") !== null) { teams.lookup("models").adds("lola03"); } timers.start(); rotater.start(); if (cb.settings.rotater0 !== "") { rotater.add(cb.settings.rotater0); } if (cb.settings.rotater1 !== "") { rotater.add(cb.settings.rotater1); } if (cb.settings.rotater2 !== "") { rotater.add(cb.settings.rotater2); } if (cb.settings.rotater3 !== "") { rotater.add(cb.settings.rotater3); } if (cb.settings.rotater4 !== "") { rotater.add(cb.settings.rotater4); } if (cb.settings.rotater5 !== "") { rotater.add(cb.settings.rotater5); } if (cb.settings.rotater6 !== "") { rotater.add(cb.settings.rotater6); } if (cb.settings.rotater7 !== "") { rotater.add(cb.settings.rotater7); } if (cb.settings.rotater8 !== "") { rotater.add(cb.settings.rotater8); } var split = void 0; var cost = void 0; var name_1; if (cb.settings.custTipmenu0 !== undefined && cb.settings.custTipmenu0 !== "") { tipmenu.customSelector = true; split = cb.settings.custTipmenu0.split(' '); cost = split.shift(); name_1 = split.join(' '); tipmenu.customTable.add(name_1, Number(cost)); tipmenu.enchantedCustomTable.add(name_1, Math.floor(Number(cost) * 0.9)); } if (cb.settings.custTipmenu1 !== undefined && cb.settings.custTipmenu1 !== "") { tipmenu.customSelector = true; split = cb.settings.custTipmenu1.split(' '); cost = split.shift(); name_1 = split.join(' '); tipmenu.customTable.add(name_1, Number(cost)); tipmenu.enchantedCustomTable.add(name_1, Math.floor(Number(cost) * 0.9)); } if (cb.settings.custTipmenu2 !== undefined && cb.settings.custTipmenu2 !== "") { tipmenu.customSelector = true; split = cb.settings.custTipmenu2.split(' '); cost = split.shift(); name_1 = split.join(' '); tipmenu.customTable.add(name_1, Number(cost)); tipmenu.enchantedCustomTable.add(name_1, Math.floor(Number(cost) * 0.9)); } if (cb.settings.custTipmenu3 !== undefined && cb.settings.custTipmenu3 !== "") { tipmenu.customSelector = true; split = cb.settings.custTipmenu3.split(' '); cost = split.shift(); name_1 = split.join(' '); tipmenu.customTable.add(name_1, Number(cost)); tipmenu.enchantedCustomTable.add(name_1, Math.floor(Number(cost) * 0.9)); } if (cb.settings.custTipmenu4 !== undefined && cb.settings.custTipmenu4 !== "") { tipmenu.customSelector = true; split = cb.settings.custTipmenu4.split(' '); cost = split.shift(); name_1 = split.join(' '); tipmenu.customTable.add(name_1, Number(cost)); tipmenu.enchantedCustomTable.add(name_1, Math.floor(Number(cost) * 0.9)); } if (cb.settings.custTipmenu5 !== undefined && cb.settings.custTipmenu5 !== "") { tipmenu.customSelector = true; split = cb.settings.custTipmenu5.split(' '); cost = split.shift(); name_1 = split.join(' '); tipmenu.customTable.add(name_1, Number(cost)); tipmenu.enchantedCustomTable.add(name_1, Math.floor(Number(cost) * 0.9)); } if (cb.settings.custTipmenu6 !== undefined && cb.settings.custTipmenu6 !== "") { tipmenu.customSelector = true; split = cb.settings.custTipmenu6.split(' '); cost = split.shift(); name_1 = split.join(' '); tipmenu.customTable.add(name_1, Number(cost)); tipmenu.enchantedCustomTable.add(name_1, Math.floor(Number(cost) * 0.9)); } if (cb.settings.custTipmenu7 !== undefined && cb.settings.custTipmenu7 !== "") { tipmenu.customSelector = true; split = cb.settings.custTipmenu7.split(' '); cost = split.shift(); name_1 = split.join(' '); tipmenu.customTable.add(name_1, Number(cost)); tipmenu.enchantedCustomTable.add(name_1, Math.floor(Number(cost) * 0.9)); } if (cb.settings.custTipmenu8 !== undefined && cb.settings.custTipmenu8 !== "") { tipmenu.customSelector = true; split = cb.settings.custTipmenu8.split(' '); cost = split.shift(); name_1 = split.join(' '); tipmenu.customTable.add(name_1, Number(cost)); tipmenu.enchantedCustomTable.add(name_1, Math.floor(Number(cost) * 0.9)); } if (cb.settings.custTipmenu9 !== undefined && cb.settings.custTipmenu9 !== "") { tipmenu.customSelector = true; split = cb.settings.custTipmenu9.split(' '); cost = split.shift(); name_1 = split.join(' '); tipmenu.customTable.add(name_1, Number(cost)); tipmenu.enchantedCustomTable.add(name_1, Math.floor(Number(cost) * 0.9)); } if (cb.settings.custTipmenu10 !== undefined && cb.settings.custTipmenu10 !== "") { tipmenu.customSelector = true; split = cb.settings.custTipmenu10.split(' '); cost = split.shift(); name_1 = split.join(' '); tipmenu.customTable.add(name_1, Number(cost)); tipmenu.enchantedCustomTable.add(name_1, Math.floor(Number(cost) * 0.9)); } if (cb.settings.custTipmenu11 !== undefined && cb.settings.custTipmenu11 !== "") { tipmenu.customSelector = true; split = cb.settings.custTipmenu11.split(' '); cost = split.shift(); name_1 = split.join(' '); tipmenu.customTable.add(name_1, Number(cost)); tipmenu.enchantedCustomTable.add(name_1, Math.floor(Number(cost) * 0.9)); } if (cb.settings.custTipmenu12 !== undefined && cb.settings.custTipmenu12 !== "") { tipmenu.customSelector = true; split = cb.settings.custTipmenu12.split(' '); cost = split.shift(); name_1 = split.join(' '); tipmenu.customTable.add(name_1, Number(cost)); tipmenu.enchantedCustomTable.add(name_1, Math.floor(Number(cost) * 0.9)); } if (cb.settings.custTipmenu13 !== undefined && cb.settings.custTipmenu13 !== "") { tipmenu.customSelector = true; split = cb.settings.custTipmenu13.split(' '); cost = split.shift(); name_1 = split.join(' '); tipmenu.customTable.add(name_1, Number(cost)); tipmenu.enchantedCustomTable.add(name_1, Math.floor(Number(cost) * 0.9)); } if (cb.settings.custTipmenu14 !== undefined && cb.settings.custTipmenu14 !== "") { tipmenu.customSelector = true; split = cb.settings.custTipmenu14.split(' '); cost = split.shift(); name_1 = split.join(' '); tipmenu.customTable.add(name_1, Number(cost)); tipmenu.enchantedCustomTable.add(name_1, Math.floor(Number(cost) * 0.9)); } teams.addTeam(new modteam("mods", " :enchanted13 ", 0.10)); teams.addTeam(new team("enchanted", " :enchanted12 ", 0.10)); if (cb.settings.enchanted !== undefined) { for (var _i = 0, _a = cb.settings.enchanted.split(" "); _i < _a.length; _i++) { var member = _a[_i]; teams.addToTeam(member, "enchanted"); } } if (cb.settings.trusted !== undefined) { for (var _b = 0, _c = cb.settings.trusted.split(" "); _b < _c.length; _b++) { var member = _c[_b]; permissions.entrust(member); } } } /** * Manages the high tipper */ var hightip; (function (hightip) { "use strict"; /** * The actual tipper */ var slot; /** * Compare the tip against the highest tip, replacing it if greater * This is single tip only, so no tipper lookup should ever occur * @param tip Tip to compare */ function compare(tip) { if (slot == null || tip.amount > slot.tipped) { slot = new tipper(tip.from_user, tip.amount); } } hightip.compare = compare; /** * Print the help menu for hightip * @param message Requesting message */ function help(message) { notice.add("/hightip --Get the highest single tipper"); notice.post(message.user); } hightip.help = help; /** * Load the state string * @param state State string */ function load(state) { var tipped = state.split(" ")[0]; var name = state.split(" ")[1]; slot = new tipper(name, Number(tipped)); } hightip.load = load; /** * Get the name of the high tipper */ function name() { return slot == null ? null : slot.name; } hightip.name = name; /** * rotate high tipper notice */ function rotate() { notice.send(emblems.crown + "The king tip is " + slot.tipped + emblems.token); cb.setTimeout(rotate, 60 * 1000); } hightip.rotate = rotate; /** * Get the amount tipped during this show */ function tipped() { return slot == null ? null : slot.tipped; } hightip.tipped = tipped; /** * Try to parse a valid command, returning true if a valid command is found * @param message Requesting message */ function tryParse(message) { var m = message.m.split(" "); if (m.length === 0) return false; var command = m.shift().toLowerCase(); switch (command) { case "/hightip": notice.send(slot.tipped + " " + slot.name, message.user); return true; default: return false; } } hightip.tryParse = tryParse; })(hightip || (hightip = {})); /** * Handles the leaderboard */ var leaderboard; (function (leaderboard) { "use strict"; /** * Number, in minutes, between rotations */ leaderboard.lapse = 10; /** * Default size of the leaderboard */ leaderboard.size = 5; /** * Prints the help for the leaderboard * @param message Requesting message */ function help(message) { notice.add("/leaderboard --Print the leaderboard"); notice.post(message.user); message['X-Spam'] = true; } leaderboard.help = help; /** * Is the tipper in the leaderboard position? * This function technically will work beyond the leaderboard, but why would you bother? * @param pos Leaderboard position * @param tipper Tipper to check */ function isPos(pos, tipper) { return tippers.top(pos)[pos - 1] === tipper; } leaderboard.isPos = isPos; /** * Print the leaderboard to chat * @param slots Amount of slots to print * @param sendTo User to send to */ function print(slots, sendTo) { if (slots === void 0) { slots = leaderboard.size; } if (sendTo === void 0) { sendTo = ""; } var top = tippers.top(slots); if (top != null && top.length != 0) notice.add("===== Leaderboard ====="); if (top[0] != null && top[0].tipped != 0) notice.add(emblems.goldmedal + top[0].name + " " + top[0].tipped); if (top[1] != null && top[1].tipped != 0) notice.add(emblems.silvermedal + top[1].name + " " + top[1].tipped); if (top[2] != null && top[2].tipped != 0) notice.add(emblems.bronzemedal + top[2].name + " " + top[2].tipped); if (top[3] != null && top[3].tipped != 0) notice.add(emblems.tinmedal + top[3].name + " " + top[3].tipped); if (top[4] != null && top[4].tipped != 0) notice.add(emblems.coppermedal + top[4].name + " " + top[4].tipped); notice.post(sendTo); } /** * Rotate the leaderboard * @param slots Amount of slots to print */ function rotate(slots) { if (slots === void 0) { slots = leaderboard.size; } print(slots); cb.setTimeout(rotate, leaderboard.lapse * 60 * 1000); } function start() { cb.setTimeout(rotate, rotater.lapse * 60 * 1000); } leaderboard.rotate = rotate; rotater.start = start; /** * Try to parse a leaderboard command, returning true if a valid command is found * @param message Requesting message */ function tryParse(message) { var m = message.m.split(" "); if (m.length === 0) return false; var command = m.shift().toLowerCase(); switch (command) { case "/leaderboard": print(leaderboard.size, message.user); return true; default: return false; } } leaderboard.tryParse = tryParse; })(leaderboard || (leaderboard = {})); leaderboard.rotate(3); //TLG code: log.level = log.DEBUG; log.debug("Initial user db: " + log.format(seen)); cmdHelp();///TLG code end //bouncer-code// (cb || (cb = {})); var filter; (function (filter) { /** * Manages the bot filter * This implementation will change to coincide with whatever easily caught bots are currently plaguing CB. More sophisticated bots should be caught with the same heuristics for general chat; improve those instead. */ var bot; (function (bot) { /** * Check a message for chatbot language * @param message Message to check */ function check(message) { if (message.user === cb.room_slug) return; if (cb.settings.modexception == "on" && message.is_mod) return; if (cb.settings.fcexception == "on" && message.in_fanclub) return; var m = message.m.split(" "); for (var _i = 0, m_13 = m; _i < m_13.length; _i++) { var candidate = m_13[_i]; if (candidate.match(/m.*a.*y.*b.*e.*s.*e.*x/i)) { message['X-Spam'] = true; break; } if (candidate.match(/m(.|\s)*a(.|\s)*y(.|\s)*b(.|\s)*e(.|\s)*p(.|\s)*r(.|\s)*i(.|\s)*v(.|\s)*a(.|\s)*t(.|\s)*e/i)) { message['X-Spam'] = true; break; } if (candidate.match(/token/i) && candidate.match(/generator/i)) { message['X-Spam'] = true; break; } if (candidate.match(/use\s+that\s+site\s+too/i)) { message['X-Spam'] = true; break; } } if (message['X-Spam']) { if (cb.settings.bcdetails == "on") { notice.send(emblems.gavel + message.user + ": '" + message.m + "' has been filtered for likely being a bot", cb.room_slug); } else { notice.send(emblems.gavel + message.user + " has been filtered for likely being a bot", cb.room_slug); } if (cb.settings.moddetails == "on") { notice.sendGroup(emblems.gavel + message.user + ": '" + message.m + "' has been filtered for likely being a bot", "red"); } else { notice.sendGroup(emblems.gavel + message.user + " has been filtered for likely being a bot", "red"); } } } bot.check = check; })(bot = filter.bot || (filter.bot = {})); })(filter || (filter = {})); /** * Provides "the dozer"; chat cleanup */ var dozer; /** * Provides "the dozer"; chat cleanup */ (function (dozer) { "use strict"; /** * Prints the help for dozer * @param message Requesting message */ function help(message) { if (permissions.isAtLeastModerator(message)) { notice.add("/doze,dozer --Clear the chat"); notice.post(message.user); message['X-Spam'] = true; } } dozer.help = help; /** * Try to parse a dozer command, returning true if a valid command is found * @param message Requesting message */ function tryParse(message) { if (permissions.isAtLeastModerator(message)) { var m = message.m.split(" "); if (m.length === 0) return false; var command = m.shift().toLowerCase(); switch (command) { case "/doze": case "/dozer": doze(); return true; default: return false; } } return false; } dozer.tryParse = tryParse; /** * Run the dozer */ function doze() { notice.adds("\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n"); notice.post("", "#FFFFFF"); } })(dozer || (dozer = {})); //REMINDER TO RATE IF TIPPED OVER 25 var RATE_FROM = 25, RATE_MESSAGE = ":b-vote3", RATE_MESSAGE_DELAY = 1500, user_total_tips = {}, user_last_tip_time = {}; function handleTip(amount, user) { if (amount <= 0) return; var before = user_total_tips[user] || 0, after = user_total_tips[user] = before + amount; user_last_tip_time[user] = new Date().valueOf(); if ((before < RATE_FROM) && (after >= RATE_FROM)){ cb.setTimeout(function(){ cb.chatNotice(RATE_MESSAGE, '', '#FFF0DE', '#2D72B7', 'normal'); }, RATE_MESSAGE_DELAY); } }
© Copyright Chaturbate 2011- 2024. All Rights Reserved.