Apps Home
|
Create an App
GoalApp
Author:
entomy
Description
Source Code
Launch App
Current Users
Created by:
Entomy
/** * Provides aliases for emblem emotes */ var emblems; /** * Provides aliases for emblem emotes */ (function (emblems) { "use strict"; emblems.arrow = " :arrow16 "; emblems.ballot = " :ballot16 "; emblems.bb8 = " :miniBB-8 "; /** * Blank "emblem", used to indent since CB eats HT's. */ emblems.blank = " :blank16 "; emblems.bronzemedal = " :bronzemedal16c "; emblems.coppermedal = " :coppermedal16 "; emblems.crown = " :crown16 "; emblems.gavel = " :gavel16 "; emblems.goldmedal = " :goldmedal16 "; emblems.hitachi = " :hitachi16 "; emblems.notice = " :notice16 "; emblems.silvermedal = " :silvermedal16 "; emblems.song = " :song16 "; emblems.timer = " :timer16 "; emblems.tinmedal = " :tinmedal16 "; emblems.tipmenu = " :tipmenu16 "; emblems.token = " :token12 "; emblems.trusted = " :trusted16 "; emblems.whisper = " :whisper16 "; emblems.whispermod = " :whispermod16 "; })(emblems || (emblems = {})); /** * 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 the room subject */ var subject; /** * Manages the room subject */ (function (subject) { "use strict"; /** * Revert back to default room title */ function revert() { cb.changeRoomSubject(subject.defaultTitle + " " + subject.hashtags); } subject.revert = revert; /** * Sets the room title * @param title New room title */ function set(title) { cb.changeRoomSubject(title + " " + subject.hashtags); } subject.set = set; })(subject || (subject = {})); /** * Represents a ticker */ var ticker = /** @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 ticker(name, onTick) { cb.log("new ticker(" + name + ")"); this.name = name; cb.log("name: " + this.name); this.onTick = onTick; } /** * Perform one tick, calling the event if there is one * This also initializes the ticker, such that it calls itself again every interval */ ticker.prototype.tick = function () { cb.log(this.name + ".tick()"); this.onTick; cb.setTimeout(this.tick, 1000); }; /** * Start the ticker */ ticker.prototype.start = function () { cb.log(this.name + ".start()"); this.onTick; cb.setTimeout(this.start, 1000); }; return ticker; }()); cb.onDrawPanel(function () { if (goals.current() == null) { return { 'template': '3_rows_11_22_32', 'row1_label': 'No Goal', 'row2_label': 'Tipped', 'row2_value': goals.accumulator, }; } else if (goals.current().type == goaltype.drain) { return { 'template': '3_rows_11_22_32', 'row1_label': 'Jar', 'row2_label': 'Have', 'row2_value': goals.accumulator, 'row3_label': 'Drain Rate', 'row3_value': goals.current().target + "tokens/second", }; } else { return { 'template': '3_rows_11_22_32', 'row1_label': 'Goal', 'row2_label': 'Required', 'row2_value': goals.current().target, 'row3_label': 'Remaining', 'row3_value': goals.current().target - goals.accumulator, }; } }); 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 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 = permissions.tryParse(message); if (!validCommand) validCommand = goals.tryParse(message); return message; }); cb.onTip(function (tip) { goals.apply(tip); }); /** Type of goal */ var goaltype; /** Type of goal */ (function (goaltype) { goaltype[goaltype["single"] = 0] = "single"; goaltype[goaltype["repeating"] = 1] = "repeating"; goaltype[goaltype["drain"] = 2] = "drain"; })(goaltype || (goaltype = {})); ; /** * Represents a goal */ var goal = /** @class */ (function () { function goal(title, target, type) { if (type === void 0) { type = goaltype.single; } this.title = title; this.target = target; this.type = type; } return goal; }()); /** * Manager for goals */ var goals; /** * Manager for goals */ (function (goals) { /** * Queue of goals to reach */ var queue = []; var drainer = new ticker("drainer", function () { if (goals.accumulator > 0) goals.accumulator -= 0.1; cb.log("accumulator: " + goals.accumulator); }); /** * Accumulates tokens tipped during the show * Goal's reached remove tokens from this */ goals.accumulator = 0; /** * Add the goal to the queue * @param title Title of the goal * @param target Amount required to reach goal * @param type Type of the goal */ function add(title, target, type) { if (type === void 0) { type = goaltype.single; } queue[queue.length] = new goal(title, target, type); if (queue.length === 1) { subject.set("Goal: " + title); cb.drawPanel(); } else { notice.send("Goal '" + title + "' has been queued"); } } goals.add = add; /** * Add the tip to the accumulator * This also looks to see if the accumulator has enough to clear a goal, then clears goals until no longer able to * @param tip Tip to apply */ function apply(tip) { goals.accumulator += tip.amount; if (queue[0] !== null && queue[0].type !== goaltype.drain) { while (goals.accumulator >= queue[0].target) { goals.accumulator -= queue[0].target; if (queue[0].type === goaltype.repeating) { notice.send("Goal '" + queue[0].title + "' reached"); continue; } queue.shift(); if (queue.length === 0) { subject.revert(); break; } subject.set("Goal: " + queue[0].title); } } cb.drawPanel(); } goals.apply = apply; /** * Clear all goals */ function clear() { queue = []; notice.send("All goals have been cleared"); } goals.clear = clear; /** * Get the current goal */ function current() { return queue[0]; } goals.current = current; /** * Print the help messages for goal * @param message Requesting message */ function help(message) { if (permissions.isAtLeastTrusted(message)) { notice.add("/goal,goals"); notice.add(emblems.blank + "add <target> <title> --Add the goal to the queue"); notice.add(emblems.blank + emblems.blank + "drain,jar <rate> <title> --Add the draining goal to the queue"); notice.add(emblems.blank + emblems.blank + "repeat,repeats,repeating <target> <title> --Add the repeating goal to the queue"); notice.add(emblems.blank + "clear --Clear the queue"); notice.add(emblems.blank + "next --Move to the next goal, regardless of completion"); notice.add(emblems.blank + "set <target> <title> --Set the current goal"); notice.add(emblems.blank + emblems.blank + "drain,jar <rate> <title> --Set the current draining goal"); notice.add(emblems.blank + emblems.blank + "repeat,repeating <target> <title> --Set the current repeating goal"); notice.post(message.user); } } goals.help = help; /** * Move to the next goal, regardless of completion of current */ function next() { queue.shift(); if (queue.length === 0) { subject.revert(); } else { subject.set(queue[0].title); } cb.drawPanel(); } goals.next = next; /** * Set the current goal * This only changes the current goal, not the rest of the queue * @param title Title of the goal * @param target Amount required to reach goal * @param type What type of goal */ function set(title, target, type) { if (type === void 0) { type = goaltype.single; } queue[0] = new goal(title, target, type); subject.set("Goal: " + title); cb.drawPanel(); } goals.set = set; /** * Start everything the goal system needs */ function start() { cb.log("goals.start()"); drainer.start(); } goals.start = start; /** * Try to parse a goal 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 "/goal": case "/goals": if (m.length === 0) return false; var operation = m.shift().toLowerCase(); var title = void 0; // This is assigned while parsing operations var target = void 0; // This is assigned while parsing operations var type = void 0; // This is assigned while parsing operations switch (operation) { case "help": help(message); permissions.help(message); return true; case "add": if (!permissions.isAtLeastTrusted(message)) return false; type = m.shift(); switch (type.toLowerCase()) { case "drain": case "jar": case "repeat": case "repeats": case "repeating": break; default: m.unshift(type); type = null; break; } target = m.shift(); if (isNaN(Number(target))) { // Target wasn't at the beginning, try finding it at the end m.unshift(); target = m.pop(); if (isNaN(Number(target))) return false; // No target found, not a valid command } // We've found the target, the rest is the title title = m.join(" "); if (type === null) type = ""; switch (type.toLowerCase()) { case "drain": case "jar": goals.add(title, Number(target), goaltype.drain); break; case "repeat": case "repeats": case "repeating": goals.add(title, Number(target), goaltype.repeating); break; default: goals.add(title, Number(target)); break; } return true; case "clr": case "clear": if (!permissions.isAtLeastTrusted(message)) return false; goals.clear(); return true; case "next": if (!permissions.isAtLeastTrusted(message)) return false; goals.next(); return true; case "set": if (!permissions.isAtLeastTrusted(message)) return false; type = m.shift(); switch (type.toLowerCase()) { case "drain": case "jar": case "repeat": case "repeats": case "repeating": break; default: m.unshift(type); type = null; break; } target = m.shift(); if (isNaN(Number(target))) { // Target wasn't at the beginning, try finding it at the end m.unshift(); target = m.pop(); if (isNaN(Number(target))) return false; // No target found, not a valid command } // We've found the target, the rest is the title title = m.join(" "); if (type === null) type = ""; switch (type.toLowerCase()) { case "drain": case "jar": goals.set(title, Number(target), goaltype.drain); break; case "repeat": case "repeats": case "repeating": goals.set(title, Number(target), goaltype.repeating); break; default: goals.set(title, Number(target)); break; } return true; default: return false; } default: return false; } } goals.tryParse = tryParse; })(goals || (goals = {})); var cb; (function (cb) { cb.settings_choices = [ { name: "defaultTitle", label: "Default Title", type: "str", required: true, }, { name: "hashtags", label: "Room Hashtags", type: "str", required: false, }, { name: "trusted", label: "Trusted Users", type: "str", required: false, }, { name: "foreground", label: "Text Color", type: "str", defaultValue: "#000000", required: true, } ]; })(cb || (cb = {})); /** * Initialization code */ { notice.color = cb.settings.foreground; subject.defaultTitle = cb.settings.defaultTitle; subject.hashtags = cb.settings.hashtags; goals.start(); if (cb.settings.trusted !== undefined) { for (var _i = 0, _a = cb.settings.trusted.split(" "); _i < _a.length; _i++) { var member = _a[_i]; permissions.entrust(member); } } cb.changeRoomSubject(cb.settings.defaultTitle + " " + cb.settings.hashtags); }
© Copyright Chaturbate 2011- 2025. All Rights Reserved.