Bots Home
|
Create an App
ScarletsRoom
Author:
entomy
Description
Source Code
Launch Bot
Current Users
Created by:
Entomy
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 "; 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; } cb.log("print()"); var price; for (var _i = 0, _a = this.items; _i < _a.length; _i++) { var item = _a[_i]; cb.log("item: " + item.name); // Discount the item's price if appropriate price = discountMethod != null ? discountMethod(item, user) : item.cost; cb.log("price: " + price); // 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 = "#000000"; /** * 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 = {})); /** * 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; /** * 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 */ (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 = {})); /** * 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 = {})); 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); } 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, onTick) { if (delay === void 0) { delay = 0; } this.name = name; this.duration = duration; this.remaining = duration; this.delay = delay; this.onStart = onStart; this.onStop = onStop; this.onTick = onTick; } /** * 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) { if (this.onTick != null) this.onTick(); 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, onTick) { if (delay === void 0) { delay = 0; } pool[pool.length] = new timer(name, duration, delay, onStart, onStop, onTick); 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, "#802080", "bolder"); else if (permissions.isModerator(message)) notice.send(emblems.whisper + message.user + ": " + m, cb.room_slug, "#802020", "bolder"); else if (permissions.isInFanclub(message)) notice.send(emblems.whisper + message.user + ": " + m, cb.room_slug, "#208020"); else if (permissions.hasTokens(message)) notice.send(emblems.whisper + message.user + ": " + m, cb.room_slug, "#808080"); } /** * 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, "#802020", "bolder", false); notice.postGroup("red", "#802020", "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, "#804020"); } else { notice.send(emblems.whisper + message.user + ": " + m.join(" "), target, "#808080", "normal"); } notice.send(emblems.whisper + "Sent to: " + target, message.user); return true; } } whisper.tryParse = tryParse; })(whisper || (whisper = {})); cb.onEnter(function (user) { notice.adds(cb.settings.welcomeMessage, "To see available commands, enter /roomhelp in chat", "Check out the tip menu with /tipmenu"); notice.apply(emblems.notice); notice.post(user.user); viewers.enter(user); if (user.is_mod) { teams.addToTeam(user, "mods"); } }); cb.onLeave(function (user) { viewers.leave(user); }); cb.onMessage(function (message) { // 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 = 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 (message['X-Spam'] || validCommand) return message; // Apply Emblems 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; } // Return the message return message; }); cb.onTip(function (tip) { tippers.add(tip); var match = tipmenu.match(tip); if (match != null) { notice.send(emblems.tipmenu + tip.from_user + " has tipped for " + match.name); match.handle(tip); } }); var handlers; (function (handlers) { function addFairy(tip) { teams.addToTeam(tip, "fairies"); } handlers.addFairy = addFairy; function mute(_tip, amount) { var timer = timers.lookup("Mute"); if (timer != null) { timer.extend(amount * 60); } else { timers.add("Mute", 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 case "/roomhelp": help(message); return true; } return false; } room.tryParse = tryParse; })(room || (room = {})); var cb; (function (cb) { cb.settings_choices = [ { name: "welcomeMessage", label: "Welcome Message", type: "str", required: true }, { name: "rotater0", label: "Rotating Notice", type: "str", required: false }, { name: "rotater1", label: "Rotating Notice", type: "str", required: false }, { name: "rotater2", label: "Rotating Notice", type: "str", required: false }, { name: "rotater3", label: "Rotating Notice", type: "str", required: false }, { name: "rotater4", label: "Rotating Notice", type: "str", required: false }, { name: "custTipmenu0", label: "Custom Tipmenu Item", type: "str", required: false, }, { name: "custTipmenu1", label: "Custom Tipmenu Item", type: "str", required: false, }, { name: "custTipmenu2", label: "Custom Tipmenu Item", type: "str", required: false, }, { name: "custTipmenu3", label: "Custom Tipmenu Item", type: "str", required: false, }, { name: "custTipmenu4", label: "Custom Tipmenu Item", type: "str", required: false, }, { name: "custTipmenu5", label: "Custom Tipmenu Item", type: "str", required: false, }, { name: "custTipmenu6", label: "Custom Tipmenu Item", type: "str", required: false, }, { name: "custTipmenu7", label: "Custom Tipmenu Item", type: "str", required: false, }, { name: "custTipmenu8", label: "Custom Tipmenu Item", type: "str", required: false, }, { name: "custTipmenu9", label: "Custom Tipmenu Item", type: "str", required: false, }, { name: "custTipmenu10", label: "Custom Tipmenu Item", type: "str", required: false, }, { name: "custTipmenu11", label: "Custom Tipmenu Item", type: "str", required: false, }, { name: "custTipmenu12", label: "Custom Tipmenu Item", type: "str", required: false, }, { name: "custTipmenu13", label: "Custom Tipmenu Item", type: "str", required: false, }, { name: "custTipmenu14", label: "Custom Tipmenu Item", type: "str", required: false, }, { name: "fairies", label: "Fairies (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("Friend Zone Tax", 10), new menuitem("5 Hand Spanks", 30), new menuitem("5 Paddle Spanks", 35), new menuitem("Booty", 38), new menuitem("Boobs", 39), new menuitem("Feet", 41), new menuitem("Ash Does a Trick", 42), new menuitem("Skip Song", 43), new menuitem("Song Request", 44), new menuitem("5 Wood Paddle Spanks", 51), new menuitem("Show Off Flexibility", 65), new menuitem("Tell a Secret", 89), new menuitem("Dance Tease", 90), new menuitem("Dildo Blow Job", 98), new menuitem("Show Vegana", 99), new menuitem("5 Minute Nipple Clamps", 120, handlers.nippleClamps, 5), new menuitem("5 Minute Mute", 130, handlers.mute, 5), new menuitem("5 Minute Ballgag", 135, handlers.ballgag, 5), new menuitem("Play Ukulele", 150), new menuitem("Hula Hoop Rave", 305), new menuitem("C2C", 200), new menuitem("Butt Plug", 300), new menuitem("Snapchat", 333), new menuitem("Join Fairies", 444, handlers.addFairy), new menuitem("30 Minute Mute", 650, handlers.mute, 30), new menuitem("Nudity Ban", 3999), new menuitem("Instant Cum", 4999)); tipmenu.customTable = new menusection("Main"); tipmenu.fairiesTable = new menusection("Main", new menuitem("Friend Zone Tax (fairy discount)", 9), new menuitem("5 Hand Spanks (fairy discount)", 27), new menuitem("5 Paddle Spanks (fairy discount)", 31), new menuitem("Booty (fairy discount)", 34), new menuitem("Boobs (fairy discount)", 35), new menuitem("Feet (fairy discount)", 36), new menuitem("Ash Does a Trick (fairy discount)", 37), new menuitem("Skip Song (fairy discount)", 38), new menuitem("Song Request (fairy discount)", 39), new menuitem("5 Wood Paddle Spanks (fairy discount)", 45), new menuitem("Show Off Flexibility (fairy discount)", 58), new menuitem("Tell a Secret (fairy discount)", 80), new menuitem("Dance Tease (fairy discount)", 81), new menuitem("Dildo Blow Job (fairy discount)", 88), new menuitem("Show Vegana (fairy discount)", 89), new menuitem("5 Minute Nipple Clamps (fairy discount)", 108, handlers.nippleClamps, 5), new menuitem("5 Minute Mute (fairy discount)", 117, handlers.mute, 5), new menuitem("5 Minute Ballgag (fairy discount)", 121, handlers.ballgag, 5), new menuitem("Play Ukulele (fairy discount)", 135), new menuitem("Hula Hoop Rave (fairy discount)", 274), new menuitem("C2C (fairy discount)", 180), new menuitem("Butt Plug (fairy discount)", 270), new menuitem("Snapchat (fairy discount)", 299), new menuitem("30 Minute Mute (fairy discount)", 585, handlers.mute, 30), new menuitem("Nudity Ban (fairy discount)", 3599), new menuitem("Instant Cum (fairy discount)", 4499)); tipmenu.fairiesCustomTable = new menusection("Main"); /** * Print the help messages for tipmenu * @param message Requesting message */ function help(message) { notice.add("/tipmenu --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, "fairies") || teams.isMemberOf(tip, "mods")) { cb.log("discounted"); for (var _b = 0, _c = tipmenu.fairiesCustomTable.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, "fairies") || teams.isMemberOf(tip, "mods")) { cb.log("discounted"); for (var _f = 0, _g = tipmenu.fairiesTable.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, "fairies") || teams.isMemberOf(message, "mods")) { tipmenu.fairiesCustomTable.print(message, limit); } else { tipmenu.customTable.print(message, limit); } } else { if (teams.isMemberOf(message, "fairies") || teams.isMemberOf(message, "mods")) { tipmenu.fairiesTable.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; } default: return false; } } tipmenu.tryParse = tryParse; })(tipmenu || (tipmenu = {})); /** * Initialization Code */ { notice.color = "#7F5F1F"; permissions.entrust(); 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); } 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.fairiesCustomTable.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.fairiesCustomTable.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.fairiesCustomTable.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.fairiesCustomTable.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.fairiesCustomTable.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.fairiesCustomTable.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.fairiesCustomTable.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.fairiesCustomTable.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.fairiesCustomTable.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.fairiesCustomTable.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.fairiesCustomTable.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.fairiesCustomTable.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.fairiesCustomTable.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.fairiesCustomTable.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.fairiesCustomTable.add(name_1, Math.floor(Number(cost) * 0.9)); } teams.addTeam(new modteam("mods", " :taelscarletmod ", 0.10)); teams.addTeam(new team("fairies", " :scarletfairysmall ", 0.10)); if (cb.settings.fairies !== undefined) { for (var _i = 0, _a = cb.settings.fairies.split(" "); _i < _a.length; _i++) { var member = _a[_i]; teams.addToTeam(member, "fairies"); } } 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); } } }
© Copyright Chaturbate 2011- 2024. All Rights Reserved.