Bots Home
|
Create an App
TomysRoom
Author:
entomy
Description
Source Code
Launch Bot
Current Users
Created by:
Entomy
/** * Manages and applies discounts */ var discount; /** * Manages and applies discounts */ (function (discount) { "use strict"; /** * Fanclub discount percentage * This should be within 0~1 */ discount.fanclub = 0; /** * Moderator discount percentage * This should be within 0~1 */ discount.moderator = 0; /** * Apply the appropriate discount to the specified item, returning the discounted cost * @param item Item to discount * @param user User information for calculating discount */ function apply(item, user) { // CB uses different property names for the same thing on different types; this is confusing // These two values are assigned from whatever is approriate, to make the actual code easier to read var in_fanclub = user.hasOwnProperty("from_user_in_fanclub") ? user.from_user_in_fanclub : user.in_fanclub; var is_mod = user.hasOwnProperty("from_user_is_mod") ? user.from_user_is_mod : user.is_mod; // If user has no applicable discount, don't bother calculating it if (!in_fanclub && !is_mod) return item.cost; // Calculate the user discount based on whatever discount is appropriate and higher if (discount.fanclub >= discount.moderator) { if (in_fanclub) return Math.floor(item.cost * (1 - discount.fanclub)); else if (is_mod) return Math.floor(item.cost * (1 - discount.moderator)); } else if (discount.moderator > discount.fanclub) { if (is_mod) return Math.floor(item.cost * (1 - discount.moderator)); else if (in_fanclub) return Math.floor(item.cost * (1 - discount.fanclub)); } return item.cost; } discount.apply = apply; })(discount || (discount = {})); /** * 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 = " :bronzemedal16 "; 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.tipmenu = " :tipmenu16 "; emblems.token = " :token12 "; emblems.trusted = " :trusted16 "; emblems.whisper = " :whisper16 "; emblems.whispermod = " :whispermod16 "; })(emblems || (emblems = {})); /** * Manages and applies discounts */ var hightip; /** * Manages and applies discounts */ (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; /** * Get the name of the high tipper */ function name() { return slot == null ? null : slot.name; } hightip.name = name; /** * Get the amount tipped during this show */ function tipped() { return slot == null ? null : slot.tipped; } hightip.tipped = tipped; })(hightip || (hightip = {})); /** * Manages the leaderboard */ var leaderboard; /** * Manages the leaderboard */ (function (leaderboard) { "use strict"; /** * First place */ leaderboard.first = null; /** * Second place */ leaderboard.second = null; /** * Apply any relevant medal to the users message * @param message Message to check and apply */ function applyMedal(message) { if (leaderboard.first != null && leaderboard.first.name === message.user) { message.m = emblems.goldmedal + message.m; } if (leaderboard.second != null && leaderboard.second.name === message.user) { message.m = emblems.silvermedal + message.m; } } leaderboard.applyMedal = applyMedal; /** * Lookup the user in the leaderboard * @param name Username to look up */ function lookup(name) { if (leaderboard.first != null && leaderboard.first.name === name) return leaderboard.first; if (leaderboard.second != null && leaderboard.second.name === name) return leaderboard.second; return null; } leaderboard.lookup = lookup; /** * Place the tipper into the leaderboard if necessary * @param tip Tip from the tipper to place */ function place(tip) { var tipper = tippers.lookup(tip.from_user); if (lookup(tip.from_user) != null) { // The tipper is not already on the leaderboard, so attempt to insert the tipper if (leaderboard.first != null && leaderboard.first.tipped < tipper.tipped) { leaderboard.second = leaderboard.first; leaderboard.first = tipper; } else { if (leaderboard.first == null) leaderboard.first = tipper; if (leaderboard.second == null) leaderboard.second = tipper; } } else { // The tipper is already on the leaderboard, so adjust accordingly switch (position(tipper.name)) { case 1: // They are already highest, so nothing to do return; case 2: if (leaderboard.first.tipped < tipper.tipped) { leaderboard.second = leaderboard.first; leaderboard.first = tipper; } return; } } } leaderboard.place = place; function position(name) { if (leaderboard.first != null && leaderboard.first.name === name) return 1; if (leaderboard.second != null && leaderboard.second.name === name) return 2; return null; } leaderboard.position = position; })(leaderboard || (leaderboard = {})); /** * Represents a tipmenu item */ var menuitem = (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 () { if (this.handler != null) this.handler(this.params); }; return menuitem; }()); /** * Represents a tipmenu section */ var menusection = (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 handler Handler for when the item is tipped for */ 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; }; /** * Print this section to chat */ menusection.prototype.print = function (user, discounted) { if (discounted === void 0) { discounted = false; } notice.add("=====" + this.name + "====="); var price; for (var _i = 0, _a = this.items; _i < _a.length; _i++) { var item = _a[_i]; price = discounted ? discount.apply(item, user) : item.cost; 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); clear(); } } 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 "/note": case "notice": 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 "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] + "' has been removed from rotation"); pool = cbjs.arrayRemove(pool, pool[message]); } } 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 (Number(pos) === NaN) { // 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 "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"; /** * 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) { queue[queue.length] = new songrequest(user, song); notice.send(emblems.song + "'" + song + "' queued"); } 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 "next": if (permissions.isBroadcaster(message)) { var request = get(); if (request == null) { notice.send(emblems.song + "No songs in queue"); } else { notice.send(emblems.song + request.user + ": " + request.song); } return true; } return false; default: return false; } } songqueue.tryParse = tryParse; })(songqueue || (songqueue = {})); /** * Represents a song request */ var songrequest = (function () { function songrequest(user, song) { this.user = user; this.song = song; } 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; 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"; /** * Prints the help for dozer * @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 out all calculated stats * @param message Requesting message */ function print(message) { var duration = timers.showDuration(); notice.add("Show Duration: " + duration[0] + ":" + duration[1] + ":" + duration[2]); notice.add("Tokens Total: " + tippers.tipped()); notice.post(message.user); notice.clear(); } stats.print = print; /** * 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 = {})); /** * 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 team */ var team = (function () { function team(emblem) { var members = []; for (var _i = 1; _i < arguments.length; _i++) { members[_i - 1] = arguments[_i]; } /** Members of the team */ this.members = []; this.emblem = ""; this.members = members; this.emblem = emblem; } /** * 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) { this.members[this.members.length] = user; }; /** * Apply the team emblem to a message if a member * @param message Message to apply emblem */ team.prototype.apply = function (message) { if (this.isMember(message.user)) { return this.emblem + message.m; } else { return message.m; } }; /** * Is the user a member of this team? * @param user User to check */ team.prototype.isMember = function (user) { return cbjs.arrayContains(this.members, user); }; return team; }()); /** * Represents a timer */ var timer = (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, effectively 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) { notice.add("/timer,timers"); if (permissions.isAtLeastModerator(message)) { 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_2 = pool; _i < pool_2.length; _i++) { var timer_1 = pool_2[_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") { if (lookup(timer) != null) lookup(timer).remaining = 0; } } timers.stop = stop; /** * Count down one interval */ function tick() { var keep = []; showtime += 1; for (var _i = 0, pool_3 = pool; _i < pool_3.length; _i++) { var timer_2 = pool_3[_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": 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": timers.clear(); return true; case "del": case "delete": 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": 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 "list": case "print": var i = 0; for (var _i = 0, pool_4 = pool; _i < pool_4.length; _i++) { var timer_3 = pool_4[_i]; notice.add(++i + ") '" + timer_3.name + "' with " + timer_3.remaining + "s"); } notice.apply(emblems.timer); notice.post(message.user); return true; case "stop": pos = m.shift(); if (isNaN(Number(pos))) { // pos isn't actually a position, so put it back m.unshift(); 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 = (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; /** * Lookup the user, null if not found * @param user User to look up */ function lookup(user) { for (var _i = 0, pool_5 = pool; _i < pool_5.length; _i++) { var tipper_1 = pool_5[_i]; if (tipper_1.name === user) return tipper_1; } return null; } tippers.lookup = lookup; /** * Get the total amount tipped */ function tipped() { var total = 0; for (var _i = 0, pool_6 = pool; _i < pool_6.length; _i++) { var tipper_2 = pool_6[_i]; total += tipper_2.tipped; } return total; } tippers.tipped = tipped; })(tippers || (tippers = {})); /** * Manages votes and ballots */ var votes; /** * Manages votes and ballots */ (function (votes) { "use strict"; /** * The cast votes */ var casts = []; /** * The current ballot */ var ballot = []; /** * Cast or change a vote, validating it in the process * @param username Username of the voter * @param choice Choice voting for */ function cast(username, choice) { for (var _i = 0, ballot_1 = ballot; _i < ballot_1.length; _i++) { var ch = ballot_1[_i]; if (ch.toLowerCase() === choice.toLowerCase()) { casts[casts.length] = [username, choice]; notice.send(emblems.ballot + "Vote cast"); } } notice.send(emblems.ballot + "Your vote for '" + choice + "' was not recognized among the valid options", username); } votes.cast = cast; /** * Lookup a vote cast by the user, null if not found * @param username Username to look for */ function lookup(username) { for (var _i = 0, casts_1 = casts; _i < casts_1.length; _i++) { var cast_1 = casts_1[_i]; if (cast_1[0] === username) return cast_1; } return null; } votes.lookup = lookup; /** * Start a ballot with the specified choices * @param choices Ballot choices */ function start() { var choices = []; for (var _i = 0; _i < arguments.length; _i++) { choices[_i] = arguments[_i]; } ballot = choices; notice.add("A ballot has started between the following:"); for (var choice in ballot) { notice.add(choice); } notice.apply(emblems.ballot); notice.post(); notice.clear(); } votes.start = start; /** * Stop voting, count the votes, and report the winner */ function stop() { if (casts == null || casts === []) { notice.send(emblems.ballot + "No votes have been cast"); return; } for (var _i = 0, casts_2 = casts; _i < casts_2.length; _i++) { var cast_2 = casts_2[_i]; tallier.add(cast_2[1]); } var highest = tallier.highest(); tallier.clear(); notice.send(emblems.ballot + "'" + highest[0] + "'"); } votes.stop = stop; })(votes || (votes = {})); /** * 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 specials 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 "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 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.add("Welcome to my room!"); notice.add("To see available commands, enter /roomhelp in chat"); notice.add("Check out the tipmenu with /tipmenu"); notice.apply(emblems.notice); notice.post(user.user); notice.clear(); }); 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); } }); cb.onMessage(function (message) { // Mark 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 */ 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 = songqueue.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) return message; // One of these was a command, so return // Apply emblems if (permissions.isTrusted(message)) { message.m = " :trusted16 " + message.m; } else if (permissions.isInFanclub(message)) { message.m = " :chogan16 " + message.m; } if (hightip.name() === message.user) { message.m = emblems.crown + message.m; } // Apply tip amount if (tippers.lookup(message.user) !== null) message.m = "[" + tippers.lookup(message.user).tipped + "] " + message.m; // Return the message return message; }); cb.onTip(function (tip) { tippers.add(tip); hightip.compare(tip); var match = tipmenu.match(tip); if (match != null) { notice.send(emblems.tipmenu + tip.from_user + " has tipped for " + match.name); match.handle(); } }); var handlers; (function (handlers) { function flash() { timers.add("Flash", 30, 5); } handlers.flash = flash; })(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); rotater.help(message); songqueue.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: "anal", label: "Anal Items", type: "choice", choice1: "dildo", choice2: "plug", choice3: "off", defaultValue: "off", }, { name: "fitness", label: "Fitness Items", type: "choice", choice1: "on", choice2: "off", defaultValue: "off", }, ]; })(cb || (cb = {})); var tipmenu; (function (tipmenu) { /** * Flags which control what is active in the tipmenu */ var flags; (function (flags) { var analLevel; (function (analLevel) { analLevel[analLevel["off"] = 0] = "off"; analLevel[analLevel["plug"] = 1] = "plug"; analLevel[analLevel["dildo"] = 2] = "dildo"; })(analLevel = flags.analLevel || (flags.analLevel = {})); ; flags.anal = analLevel.off; var fitnessLevel; (function (fitnessLevel) { fitnessLevel[fitnessLevel["off"] = 0] = "off"; fitnessLevel[fitnessLevel["on"] = 1] = "on"; })(fitnessLevel = flags.fitnessLevel || (flags.fitnessLevel = {})); ; flags.fitness = fitnessLevel.off; })(flags = tipmenu.flags || (tipmenu.flags = {})); tipmenu.general = new menusection("General"); tipmenu.fitness = new menusection("Fitness"); tipmenu.merchandise = new menusection("Merchandise", new menuitem("Digital Pictures", 100), new menuitem("Custom Video (Short)", 200), new menuitem("Custom Video (Long)", 400), new menuitem("Steam Friend", 500)); /** * Build the tipmenu with whatever is assigned in flags */ function build() { tipmenu.general.clear(); // Build General Section tipmenu.general.add("Never Have I Ever", 8); tipmenu.general.add("Song Request", 18); tipmenu.general.add("Flash (Specify)", 20, handlers.flash); tipmenu.general.add("Lotion Bodypart (Specify)", 30); tipmenu.general.add("Ice Bodypart (Specify)", 45); tipmenu.general.add("Clothing Change", 50); tipmenu.general.add("Tease Until Hard", 80); if (flags.anal === flags.analLevel.plug) { tipmenu.general.add("Buttplug (Small)", 200); tipmenu.general.add("Buttplug (Medium)", 400); } // Build Fitness Section if (flags.fitness === flags.fitnessLevel.on) { tipmenu.fitness.add("Crunches (per each)", 6); tipmenu.fitness.add("Pushups (per each)", 9); tipmenu.fitness.add("Lunges (per each)", 11); tipmenu.fitness.add("Band Curl (per each)", 14); } } tipmenu.build = build; /** * Print the help messages for tipmenu * @param message Requesting message */ function help(message) { notice.add("tipmenu --Get the entire tipmenu"); notice.post(message.user); notice.clear(); } tipmenu.help = help; /** * Attempt to match the tip to an item in the menu * @param tip Tip to match */ function match(tip) { var price; for (var _i = 0, _a = tipmenu.specials.list(); _i < _a.length; _i++) { var item = _a[_i]; price = item.cost; if (tip.amount === price) return item; } for (var _b = 0, _c = tipmenu.general.list(); _b < _c.length; _b++) { var item = _c[_b]; price = discount.apply(item, tip); if (tip.amount === price) return item; } for (var _d = 0, _e = tipmenu.fitness.list(); _d < _e.length; _d++) { var item = _e[_d]; price = discount.apply(item, tip); if (tip.amount === price) return item; } for (var _f = 0, _g = tipmenu.merchandise.list(); _f < _g.length; _f++) { var item = _g[_f]; price = discount.apply(item, tip); if (tip.amount === price) return item; } return null; } tipmenu.match = match; /** * Print the tipmenu to chat * @param message Requesting message */ function print(message) { tipmenu.specials.print(message); tipmenu.general.print(message, true); tipmenu.fitness.print(message, true); tipmenu.merchandise.print(message); } 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 "/tipmenu": print(message); return true; } return false; } tipmenu.tryParse = tryParse; })(tipmenu || (tipmenu = {})); /** * Initialization code */ { notice.color = "#608020"; discount.fanclub = 0.10; discount.moderator = 0.10; timers.start(); rotater.add("Follow me on twitter: @EntomyCB"); rotater.add("Check me out on ManyVids: EntomyCB.ManyVids.com"); rotater.add("Check out the tipmenu with: /tipmenu"); rotater.add("Join the fanclub to receive a discount of: " + discount.fanclub * 100 + "%"); rotater.start(); switch (cb.settings.anal) { case "dildo": tipmenu.flags.anal = tipmenu.flags.analLevel.dildo; break; case "plug": tipmenu.flags.anal = tipmenu.flags.analLevel.plug; break; case "off": tipmenu.flags.anal = tipmenu.flags.analLevel.off; break; } switch (cb.settings.fitness) { case "on": tipmenu.flags.fitness = tipmenu.flags.fitnessLevel.on; break; case "off": tipmenu.flags.fitness = tipmenu.flags.fitnessLevel.off; break; } tipmenu.build(); }
© Copyright Chaturbate 2011- 2024. All Rights Reserved.