Bots Home
|
Create an App
Olivia's Friends with Benefits
Author:
oliviaoncam
Description
Source Code
Launch Bot
Current Users
Created by:
Oliviaoncam
"use strict"; const isMessageByHuman = (function(trustTippers) { function randomInteger(min, max) { return min + Math.floor(Math.random() * (max - min + 1)); } class Challenge { constructor(description, expectedResponse) { this.description = description; this.expectedResponse = String(expectedResponse).trim(); } isValidResponse(response) { return String(response).trim() == this.expectedResponse; } toString() { return this.description; } } class MathChallenge extends Challenge { static createRandomAddition() { const a = randomInteger(1, 20), b = randomInteger(1, 20), aPlusB = a + b; return new MathChallenge(`${a} + ${b} = ?`, aPlusB); } static createRandomSubtraction() { const a = randomInteger(1, 20), b = randomInteger(1, 20), aPlusB = a + b; return new MathChallenge(`${aPlusB} - ${b} = ?`, a); } constructor(description, expectedResponse) { super(description, parseInt(expectedResponse, 10)); } isValidResponse(response) { return super.isValidResponse(parseInt(response, 10)); } } const challengeFactories = [ MathChallenge.createRandomAddition, MathChallenge.createRandomSubtraction ]; function createRandomChallenge() { return challengeFactories[Math.floor(Math.random() * challengeFactories.length)].call(null); } const whitelist = new Set([ cb.room_slug ]); // add the broadcaster to whitelist right away const userChallenges = new Map(); function addToWhitelist(username) { whitelist.add(username); userChallenges.delete(username); return true; } return function(message) { if (whitelist.has(message.user)) { return true; } else if (message.in_fanclub || message.is_mod) { return addToWhitelist(message.user); } else if (trustTippers && (message.tipped_recently || message.tipped_alot_recently || message.tipped_tons_recently)) { return addToWhitelist(message.user); } else { let challenge = userChallenges.get(message.user); if (challenge && challenge.isValidResponse(message.m)) { addToWhitelist(message.user); message['X-Spam'] = true; message.m = ' :reddotsm Thank you, you can now join the conversation! :whisper '; return false; } else { if (!challenge) userChallenges.set(message.user, challenge = createRandomChallenge()); message['X-Spam'] = true; message.m = ' :reddotsm Wait! Remember that first notice that showed up in the chat when you entered the room? It warned you about this! If you are new to the room, reading the <About Me> section under the video can give you a good idea of what you can expect to find here. Olivia does not get naked and she does not take requests. :reddotsm Please type the answer to the following equation, to be able to join chat! :arrow_right ' + challenge.toString().replace(/ /g, '\u00A0'); return false; } } }; })(cb.settings.trustTippers == 'true'); // Declare prefixes Object (user->text). var prefixes = new Object(); // Declare claims Object (user->nickname). var claims = new Object(); // Declare tippers Object (user->total_amount). var tippers = new Object(); // CSS colors. // Specific user variables that will be used for cb.settings. var specific_users = [ "user_1", "user_2", "user_3", "user_4", "user_5", "user_6", "user_7", "user_8", "user_9", "user_10", "user_11", "user_12", "user_13", "user_14", "user_15", "user_16", "user_17", "user_18", "user_19", "user_20" ]; // Tracks which users have been seen var seen = {}; // Logging var log = {}; log.DEBUG = 0; log.INFO = 1; log.WARN = 2; log.ERR = 3; log.level = log.WARN; // Default log level // Silencing var. var silenced = false; var userArray = []; // Rotating Notifier vars var i = 0; var triggered; var MAXITEMS = 10; // tipMenu Vars var lastTipper = "--"; var lastTipAmount = 0; var tipCounter = 0; var lastItem = "--"; var tempLastItem = []; var lastItemText = "--"; var FWBRequests = []; // Bot settings. cb.settings_choices = [ { name: 'trustTippers', type: 'choice', label: 'Free pass for users with tokens?', required: true, choice1: 'true', choice2: 'false', defaultChoice: 'true' }, { name: specific_users[0], type: "str", required: false, label: "Initial prefix for specific user [username prefix]" }, { name: specific_users[1], type: "str", required: false, label: "Initial prefix for specific user [username prefix]" }, { name: specific_users[2], type: "str", required: false, label: "Initial prefix for specific user [username prefix]" }, { name: specific_users[3], type: "str", required: false, label: "Initial prefix for specific user [username prefix]" }, { name: specific_users[4], type: "str", required: false, label: "Initial prefix for specific user [username prefix]" }, { name: specific_users[5], type: "str", required: false, label: "Initial prefix for specific user [username prefix]" }, { name: specific_users[6], type: "str", required: false, label: "Initial prefix for specific user [username prefix]" }, { name: specific_users[7], type: "str", required: false, label: "Initial prefix for specific user [username prefix]" }, { name: specific_users[8], type: "str", required: false, label: "Initial prefix for specific user [username prefix]" }, { name: specific_users[9], type: "str", required: false, label: "Initial prefix for specific user [username prefix]" }, { name: specific_users[10], type: "str", required: false, label: "Initial prefix for specific user [username prefix]" }, { name: specific_users[11], type: "str", required: false, label: "Initial prefix for specific user [username prefix]" }, { name: specific_users[12], type: "str", required: false, label: "Initial prefix for specific user [username prefix]" }, { name: specific_users[13], type: "str", required: false, label: "Initial prefix for specific user [username prefix]" }, { name: specific_users[14], type: "str", required: false, label: "Initial prefix for specific user [username prefix]" }, { name: specific_users[15], type: "str", required: false, label: "Initial prefix for specific user [username prefix]" }, { name: specific_users[16], type: "str", required: false, label: "Initial prefix for specific user [username prefix]" }, { name: specific_users[17], type: "str", required: false, label: "Initial prefix for specific user [username prefix]" }, { name: specific_users[18], type: "str", required: false, label: "Initial prefix for specific user [username prefix]" }, { name: specific_users[19], type: "str", required: false, label: "Initial prefix for specific user [username prefix]" }, { name: "notice_color", type: "str", required: true, label: "Global notices color (e.g. #FFF6FB)" }, { name: "notice_background_color", type: "str", required: true, label: "Global notices background color (e.g. #FFF6FB)" }, { name: "tipMenu_notice_color", type: "str", required: true, label: "Tip menu notices color (e.g. #FFF6FB)" }, { name: "tipMenu_notice_background_color", type: "str", required: true, label: "Tip menu notices background color (e.g. #FFF6FB)" }, { name: "tipMenuItem_notice_color", type: "str", required: true, label: "Tip menu item notices color (e.g. #FFF6FB)" }, { name: "tipMenuItem_notice_background_color", type: "str", required: true, label: "Tip menu item notices background color (e.g. #FFF6FB)" }, { name: "fwbRequests_notice_color", type: "str", required: true, label: "FWB request notices color (e.g. #FFF6FB)" }, { name: "fwbRequests_notice_background_color", type: "str", required: true, label: "FWB request notices background color (e.g. #FFF6FB)" }, { name: "fwbMenu_notice_color", type: "str", required: true, label: "FWB menu notices color (e.g. #FFF6FB)" }, { name: "fwbMenu_notice_background_color", type: "str", required: true, label: "FWB menu notices background color (e.g. #FFF6FB)" }, { name: "fwbWhisperPUBLIC_notice_color", type: "str", required: true, label: "FWB whisper notices PUBLIC color (e.g. #FFF6FB)" }, { name: "fwbWhisperPUBLIC_notice_background_color", type: "str", required: true, label: "FWB whisper notices PUBLIC background color (e.g. #FFF6FB)" }, { name: "fwbWhisper_public_text", type: "str", required: true, label: "Text that public chat sees when someone whispers you" }, { name: "fwbWhisper_notice_color", type: "str", required: true, label: "FWB whisper notices color (e.g. #FFF6FB)" }, { name: "fwbWhisper_notice_background_color", type: "str", required: true, label: "FWB whisper notices background color (e.g. #FFF6FB)" }, { name: "Olivias_notice_color", type: "str", required: true, label: "Olivias notices color (e.g. #FFF6FB)" }, { name: "Olivias_notice_background_color", type: "str", required: true, label: "Olivias notices background color (e.g. #FFF6FB)" }, { name: "SpeakNote_notice_color", type: "str", required: true, label: "Speak Tipnote notices color (e.g. #FFF6FB)" }, { name: "SpeakNote_notice_background_color", type: "str", required: true, label: "Speak Tipnote notices background color (e.g. #FFF6FB)" }, { name: "msgonentry", type: "choice", choice1: "yes", choice2: "no", defaultValue: "yes", label: "Display a message privately on entry" }, { name: "entryMSG", type: "str", label: "Entry message (if enabled)", defaultValue: "Hello!" }, { name: "msg1", type: "str", required: true, label: "Message 1" }, { name: "msg2", type: "str", required: false, label: "Message 2" }, { name: "msg3", type: "str", required: false, label: "Message 3" }, { name: "msg4", type: "str", required: false, label: "Message 4" }, { name: "msg5", type: "str", required: false, label: "Message 5" }, { name: "msg6", type: "str", required: false, label: "Message 6" }, { name: "msg7", type: "str", required: false, label: "Message 7" }, { name: "msg8", type: "str", required: false, label: "Message 8" }, { name: "msg9", type: "str", required: false, label: "Message 9" }, { name: "msg10", type: "str", required: false, label: "Message 10" }, { name: "msgcolor", type: "str", label: "Notice color (html code default dark red #000000)", defaultValue: "#000000" }, { name: "chat_ad", type: "int", minValue: 1, maxValue: 999, defaultValue: 2, label: "Delay in minutes between notices being displayed (minimum 1)" }, { name: "tipmenu", type: "choice", choice1: "yes", choice2: "no", defaultValue: "yes", label: "Display Tip Menu when /list is typed." }, { name: "item_1", type: "str", label: "Item #1", defaultValue: "show ass" }, { name: "item_1_price", type: "int", label: "Price for item #1", defaultValue: 25 }, { name: "item_1_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #1 in tip menu when /list is typed." }, { name: "item_2", type: "str", label: "Item #2 (optional)", defaultValue: "all fours" }, { name: "item_2_price", type: "int", label: "Price for item #2", defaultValue: 35 }, { name: "item_2_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #2 in tip menu when /list is typed." }, { name: "item_3", type: "str", label: "Item #3 (optional)", defaultValue: "show feet" }, { name: "item_3_price", type: "int", label: "Price for item #3", defaultValue: 45 }, { name: "item_3_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #3 in tip menu when /list is typed." }, { name: "item_4", type: "str", label: "Item #4 (optional)", defaultValue: "spread cheeks" }, { name: "item_4_price", type: "int", label: "Price for item #4", defaultValue: 50 }, { name: "item_4_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #4 in tip menu when /list is typed." }, { name: "item_5", type: "str", label: "Item #5 (optional)", defaultValue: "finger hole" }, { name: "item_5_price", type: "int", label: "Price for item #5", defaultValue: 100 }, { name: "item_5_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #5 in tip menu when /list is typed." }, { name: "item_6", type: "str", label: "Item #6 (optional)", defaultValue: "", required: false }, { name: "item_6_price", type: "int", label: "Price for item #6", defaultValue: 75 }, { name: "item_6_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #6 in tip menu when /list is typed." }, { name: "item_7", type: "str", label: "Item #7 (optional)", defaultValue: "", required: false }, { name: "item_7_price", type: "int", label: "Price for item #7", defaultValue: 85 }, { name: "item_7_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #7 in tip menu when /list is typed." }, { name: "item_8", type: "str", label: "Item #8 (optional)", defaultValue: "", required: false }, { name: "item_8_price", type: "int", label: "Price for item #8", defaultValue: 95 }, { name: "item_8_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #8 in tip menu when /list is typed." }, { name: "item_9", type: "str", label: "Item #9 (optional)", defaultValue: "", required: false }, { name: "item_9_price", type: "int", label: "Price for item #9", defaultValue: 100 }, { name: "item_9_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #9 in tip menu when /list is typed." }, { name: "item_10", type: "str", label: "Item #10 (optional)", defaultValue: "", required: false }, { name: "item_10_price", type: "int", label: "Price for item #10", defaultValue: 125 }, { name: "item_10_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #10 in tip menu when /list is typed." }, { name: "item_11", type: "str", label: "Item #11 (optional)", defaultValue: "", required: false }, { name: "item_11_price", type: "int", label: "Price for item #11", defaultValue: 96 }, { name: "item_11_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #11 in tip menu when /list is typed." }, { name: "item_12", type: "str", label: "Item #12 (optional)", defaultValue: "", required: false }, { name: "item_12_price", type: "int", label: "Price for item #12", defaultValue: 97 }, { name: "item_12_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #12 in tip menu when /list is typed." }, { name: "item_13", type: "str", label: "Item #13 (optional)", defaultValue: "", required: false }, { name: "item_13_price", type: "int", label: "Price for item #13", defaultValue: 98 }, { name: "item_13_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #13 in tip menu when /list is typed." }, { name: "item_14", type: "str", label: "Item #14 (optional)", defaultValue: "", required: false }, { name: "item_14_price", type: "int", label: "Price for item #14", defaultValue: 99 }, { name: "item_14_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #14 in tip menu when /list is typed." }, { name: "item_15", type: "str", label: "Item #15 (optional)", defaultValue: "", required: false }, { name: "item_15_price", type: "int", label: "Price for item #15", defaultValue: 101 }, { name: "item_15_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #15 in tip menu when /list is typed." }, { name: "item_16", type: "str", label: "Item #16 (optional)", defaultValue: "", required: false }, { name: "item_16_price", type: "int", label: "Price for item #16", defaultValue: 905 }, { name: "item_16_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #16 in tip menu when /list is typed." }, { name: "item_17", type: "str", label: "Item #17 (optional)", defaultValue: "", required: false }, { name: "item_17_price", type: "int", label: "Price for item #17", defaultValue: 915 }, { name: "item_17_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #17 in tip menu when /list is typed." }, { name: "item_18", type: "str", label: "Item #18 (optional)", defaultValue: "", required: false }, { name: "item_18_price", type: "int", label: "Price for item #18", defaultValue: 925 }, { name: "item_18_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #18 in tip menu when /list is typed." }, { name: "item_19", type: "str", label: "Item #19 (optional)", defaultValue: "", required: false }, { name: "item_19_price", type: "int", label: "Price for item #19", defaultValue: 935 }, { name: "item_19_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #19 in tip menu when /list is typed." }, { name: "item_20", type: "str", label: "Item #20 (optional)", defaultValue: "", required: false }, { name: "item_20_price", type: "int", label: "Price for item #20", defaultValue: 945 }, { name: "item_20_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #20 in tip menu when /list is typed." }, { name: "item_21", type: "str", label: "Item #21 (optional)", defaultValue: "", required: false }, { name: "item_21_price", type: "int", label: "Price for item #21", defaultValue: 955 }, { name: "item_21_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #21 in tip menu when /list is typed." }, { name: "item_22", type: "str", label: "Item #22 (optional)", defaultValue: "", required: false }, { name: "item_22_price", type: "int", label: "Price for item #22", defaultValue: 965 }, { name: "item_22_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #22 in tip menu when /list is typed." }, { name: "item_23", type: "str", label: "Item #23 (optional)", defaultValue: "", required: false }, { name: "item_23_price", type: "int", label: "Price for item #23", defaultValue: 975 }, { name: "item_23_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #23 in tip menu when /list is typed." }, { name: "item_24", type: "str", label: "Item #24 (optional)", defaultValue: "", required: false }, { name: "item_24_price", type: "int", label: "Price for item #24", defaultValue: 985 }, { name: "item_24_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #24 in tip menu when /list is typed." }, { name: "item_25", type: "str", label: "Item #25 (optional)", defaultValue: "", required: false }, { name: "item_25_price", type: "int", label: "Price for item #25", defaultValue: 995 }, { name: "item_25_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #25 in tip menu when /list is typed." }, { name: "item_26", type: "str", label: "Item #26 (optional)", defaultValue: "", required: false }, { name: "item_26_price", type: "int", label: "Price for item #26", defaultValue: 996 }, { name: "item_26_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #26 in tip menu when /list is typed." }, { name: "item_27", type: "str", label: "Item #27 (optional)", defaultValue: "", required: false }, { name: "item_27_price", type: "int", label: "Price for item #27", defaultValue: 997 }, { name: "item_27_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #27 in tip menu when /list is typed." }, { name: "item_28", type: "str", label: "Item #28 (optional)", defaultValue: "", required: false }, { name: "item_28_price", type: "int", label: "Price for item #28", defaultValue: 998 }, { name: "item_28_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #28 in tip menu when /list is typed." }, { name: "item_29", type: "str", label: "Item #29 (optional)", defaultValue: "", required: false }, { name: "item_29_price", type: "int", label: "Price for item #29", defaultValue: 996 }, { name: "item_29_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #29 in tip menu when /list is typed." }, { name: "item_30", type: "str", label: "Item #30 (optional)", defaultValue: "", required: false }, { name: "item_30_price", type: "int", label: "Price for item #30", defaultValue: 996 }, { name: "item_30_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #30 in tip menu when /list is typed." }, { name: "item_30", type: "str", label: "Item #30 (optional)", defaultValue: "", required: false }, { name: "item_30_price", type: "int", label: "Price for item #30", defaultValue: 125 }, { name: "item_30_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #30 in tip menu when /list is typed." }, { name: "item_31", type: "str", label: "Item #31 (optional)", defaultValue: "", required: false }, { name: "item_31_price", type: "int", label: "Price for item #31", defaultValue: 96 }, { name: "item_31_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #31 in tip menu when /list is typed." }, { name: "item_32", type: "str", label: "Item #32 (optional)", defaultValue: "", required: false }, { name: "item_32_price", type: "int", label: "Price for item #32", defaultValue: 97 }, { name: "item_32_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #32 in tip menu when /list is typed." }, { name: "item_33", type: "str", label: "Item #33 (optional)", defaultValue: "", required: false }, { name: "item_33_price", type: "int", label: "Price for item #33", defaultValue: 98 }, { name: "item_33_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #33 in tip menu when /list is typed." }, { name: "item_34", type: "str", label: "Item #34 (optional)", defaultValue: "", required: false }, { name: "item_34_price", type: "int", label: "Price for item #34", defaultValue: 99 }, { name: "item_34_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #34 in tip menu when /list is typed." }, { name: "item_35", type: "str", label: "Item #35 (optional)", defaultValue: "", required: false }, { name: "item_35_price", type: "int", label: "Price for item #35", defaultValue: 101 }, { name: "item_35_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #35 in tip menu when /list is typed." }, { name: "item_36", type: "str", label: "Item #36 (optional)", defaultValue: "", required: false }, { name: "item_36_price", type: "int", label: "Price for item #36", defaultValue: 905 }, { name: "item_36_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #36 in tip menu when /list is typed." }, { name: "item_37", type: "str", label: "Item #37 (optional)", defaultValue: "", required: false }, { name: "item_37_price", type: "int", label: "Price for item #37", defaultValue: 915 }, { name: "item_37_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #37 in tip menu when /list is typed." }, { name: "item_38", type: "str", label: "Item #38 (optional)", defaultValue: "", required: false }, { name: "item_38_price", type: "int", label: "Price for item #38", defaultValue: 925 }, { name: "item_38_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #38 in tip menu when /list is typed." }, { name: "item_39", type: "str", label: "Item #39 (optional)", defaultValue: "", required: false }, { name: "item_39_price", type: "int", label: "Price for item #39", defaultValue: 935 }, { name: "item_39_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #39 in tip menu when /list is typed." }, { name: "item_40", type: "str", label: "Item #40 (optional)", defaultValue: "", required: false }, { name: "item_40_price", type: "int", label: "Price for item #40", defaultValue: 125 }, { name: "item_40_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #40 in tip menu when /list is typed." }, { name: "item_41", type: "str", label: "Item #41 (optional)", defaultValue: "", required: false }, { name: "item_41_price", type: "int", label: "Price for item #41", defaultValue: 96 }, { name: "item_41_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #41 in tip menu when /list is typed." }, { name: "item_42", type: "str", label: "Item #42 (optional)", defaultValue: "", required: false }, { name: "item_42_price", type: "int", label: "Price for item #42", defaultValue: 97 }, { name: "item_42_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #42 in tip menu when /list is typed." }, { name: "item_43", type: "str", label: "Item #43 (optional)", defaultValue: "", required: false }, { name: "item_43_price", type: "int", label: "Price for item #43", defaultValue: 98 }, { name: "item_43_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #43 in tip menu when /list is typed." }, { name: "item_44", type: "str", label: "Item #44 (optional)", defaultValue: "", required: false }, { name: "item_44_price", type: "int", label: "Price for item #44", defaultValue: 99 }, { name: "item_44_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #44 in tip menu when /list is typed." }, { name: "item_45", type: "str", label: "Item #45 (optional)", defaultValue: "", required: false }, { name: "item_45_price", type: "int", label: "Price for item #45", defaultValue: 101 }, { name: "item_45_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #45 in tip menu when /list is typed." }, { name: "item_46", type: "str", label: "Item #46 (optional)", defaultValue: "", required: false }, { name: "item_46_price", type: "int", label: "Price for item #46", defaultValue: 905 }, { name: "item_46_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #46 in tip menu when /list is typed." }, { name: "item_47", type: "str", label: "Item #47 (optional)", defaultValue: "", required: false }, { name: "item_47_price", type: "int", label: "Price for item #47", defaultValue: 915 }, { name: "item_47_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #47 in tip menu when /list is typed." }, { name: "item_48", type: "str", label: "Item #48 (optional)", defaultValue: "", required: false }, { name: "item_48_price", type: "int", label: "Price for item #48", defaultValue: 925 }, { name: "item_48_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #48 in tip menu when /list is typed." }, { name: "item_49", type: "str", label: "Item #49 (optional)", defaultValue: "", required: false }, { name: "item_49_price", type: "int", label: "Price for item #49", defaultValue: 935 }, { name: "item_49_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #49 in tip menu when /list is typed." }, { name: "item_50", type: "str", label: "Item #50 (optional)", defaultValue: "", required: false }, { name: "item_50_price", type: "int", label: "Price for item #50", defaultValue: 945 }, { name: "item_50_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #50 in tip menu when /list is typed." }, { name: "item_51", type: "str", label: "Item #51 (optional)", defaultValue: "", required: false }, { name: "item_51_price", type: "int", label: "Price for item #51", defaultValue: 955 }, { name: "item_51_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #51 in tip menu when /list is typed." }, { name: "item_52", type: "str", label: "Item #52 (optional)", defaultValue: "", required: false }, { name: "item_52_price", type: "int", label: "Price for item #52", defaultValue: 965 }, { name: "item_52_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #52 in tip menu when /list is typed." }, { name: "item_53", type: "str", label: "Item #53 (optional)", defaultValue: "", required: false }, { name: "item_53_price", type: "int", label: "Price for item #53", defaultValue: 975 }, { name: "item_53_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #53 in tip menu when /list is typed." }, { name: "item_54", type: "str", label: "Item #54 (optional)", defaultValue: "", required: false }, { name: "item_54_price", type: "int", label: "Price for item #54", defaultValue: 985 }, { name: "item_54_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #54 in tip menu when /list is typed." }, { name: "item_55", type: "str", label: "Item #55 (optional)", defaultValue: "", required: false }, { name: "item_55_price", type: "int", label: "Price for item #55", defaultValue: 995 }, { name: "item_55_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #55 in tip menu when /list is typed." }, { name: "item_56", type: "str", label: "Item #56 (optional)", defaultValue: "", required: false }, { name: "item_56_price", type: "int", label: "Price for item #56", defaultValue: 996 }, { name: "item_56_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #56 in tip menu when /list is typed." }, { name: "item_57", type: "str", label: "Item #57 (optional)", defaultValue: "", required: false }, { name: "item_57_price", type: "int", label: "Price for item #57", defaultValue: 997 }, { name: "item_57_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #57 in tip menu when /list is typed." }, { name: "item_58", type: "str", label: "Item #58 (optional)", defaultValue: "", required: false }, { name: "item_58_price", type: "int", label: "Price for item #58", defaultValue: 998 }, { name: "item_58_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #58 in tip menu when /list is typed." }, { name: "item_59", type: "str", label: "Item #59 (optional)", defaultValue: "", required: false }, { name: "item_59_price", type: "int", label: "Price for item #59", defaultValue: 996 }, { name: "item_59_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #59 in tip menu when /list is typed." }, { name: "item_60", type: "str", label: "Item #60 (optional)", defaultValue: "", required: false }, { name: "item_60_price", type: "int", label: "Price for item #60", defaultValue: 996 }, { name: "item_60_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display #60 in tip menu when /list is typed." }, { name: "item_61", type: "str", label: "Read the tipnote description.", defaultValue: "Read out your tipnote as a notice", required: true }, { name: "item_61_price", type: "int", label: "Price for 'Read out my tipnote'", defaultValue: 6 }, { name: "item_61_menu", type: "choice", choice1: "yes", choice2: "no", choice3: "hidden", defaultValue: "yes", label: "Display Price for 'Read out my tipnote' in tip menu when /list is typed." }, { name: "timelock_duration", type: "int", minValue: 1, maxValue: 99, defaultValue: 5, label: "Timelock duration in minutes" }, { name: "greys_off", type: "choice", choice1: "False", choice2: "True", defaultValue: "False", label: "Turn greys off entirely" }, { name: "messages_header", required: false, type: "str", minLength: 1, maxLength: 255, defaultValue: "{0} will become the number of minutes", label: "Below are messages for customization/translation (Optional)" }, { name: "msg_welcome", type: "str", minLength: 1, maxLength: 255, defaultValue: "Please sit back and enjoy the show! You are timelocked and will be able to chat {0} minutes after joining.", label: "Welcome message for greys (timelock active)" }, { name: "msg_welcome_greys_off", type: "str", minLength: 1, maxLength: 255, defaultValue: "Welcome! Grey chat has been disabled so please sit back and enjoy the show!", label: "Welcome message for greys (greys off)" }, { name: "msg_locked", type: "str", minLength: 1, maxLength: 255, defaultValue: "You are timelocked and cannot chat for another {0} minutes. You may skip the wait by purchasing tokens.", label: "Message for chatting while timelocked" }, { name: "msg_cantchat", type: "str", minLength: 1, maxLength: 255, defaultValue: "Grey chat has been disabled. You must purchase some tokens before you will be allowed to chat.", label: "Message for chatting while grey chat is off" }, { name: "msg_greyson", type: "str", minLength: 1, maxLength: 255, defaultValue: "Grey chat has been enabled.", label: "Greys on announcement" }, { name: "msg_greysoff", type: "str", minLength: 1, maxLength: 255, defaultValue: "Grey chat has been disabled.", label: "Greys off announcement" }, { name: "fwb_msg", type: "str", label: "FWB command text.", defaultValue: "" }, { name: "fwb_list", type: "str", label: "List of people who can use /fwb", defaultValue: "" }, { name: "fwb_entry_msg", type: "str", label: "Entry message to people who can use /fwb", defaultValue: "" } ]; // Fill mods and fans arrays. if (cb.settings.fwb_list !== undefined) { userArray = cb.settings.fwb_list.split(" "); } // Add the specific user defaults to the prefixes object. for (var o = 0; o < specific_users.length; o++) { var element = specific_users[o]; if (cb.settings[element] !== undefined) { var input = cb.settings[element].split(" "); // Explode input to an array. if (input.length >= 2) { var target_user = input[0]; input.splice(0, 1); // Remove target_user from array. var text = input.join(" "); // Implode remains of array to string. prefix(cb.room_slug, target_user, text); } } } // Send welcome message. cb.onEnter(function(user) { if (cb.settings["msgonentry"] == "yes") { var notices = "Hi " + user["user"] + "! "; cb.sendNotice( notices, user["user"], cb.settings["notice_background_color"], cb.settings["notice_color"], "bold" ); cb.sendNotice( cb.settings["entryMSG"], user["user"], cb.settings["notice_background_color"], cb.settings["notice_color"], "bold" ); var present = 0; for (var j = 0; j < userArray.length; j++) { if (userArray[j] == user["user"]) { present = 1; } } if(present == 1) { var FWBEntrymessage = cb.settings["fwb_entry_msg"].split("\\n"); // Explode message to an array. var FWBEntrymsg = FWBEntrymessage.join("\n"); cb.sendNotice( FWBEntrymsg, user["user"], cb.settings["notice_background_color"], cb.settings["notice_color"], "bold" ); } } var username = user.user; // If new, start tracking if (isNew(username)) { log.info("New user entered: " + username); log.debug(user); addUser(user); // Track enter time } else { log.info("User re-entered: " + username); log.debug(user); } // Send appropriate welcome message to greys if (isGrey(user)) { if (greysOff()) { var msg = cb.settings.msg_welcome_greys_off; tellUser(msg, username); } else { welcomeUser(username); // Send welcome msg } } }); // Rotating Notifier function function chatAd() { var msg; if (triggered != 1) { i = 0; triggered = 1; } while (cb.settings["msg" + (i + 1)] == 0) { //skip empty messages i++; i %= MAXITEMS; } msg = cb.settings["msg" + (i + 1)]; i++; i %= MAXITEMS; cb.sendNotice( msg, "", cb.settings["notice_background_color"], cb.settings["notice_color"], "bold" ); cb.setTimeout(chatAd, cb.settings.chat_ad * 60000); } cb.setTimeout(chatAd, cb.settings.chat_ad * 60000); // Act upon chat messages. cb.onMessage(function(msg) { if (!isMessageByHuman(msg)) { // stop processing the message return msg; } var message = msg["m"].split(" "); // Explode message to an array. var user = msg["user"]; var has_access = user == cb.room_slug || msg["is_mod"]; var commands = [ "/prefix", "/no_prefix", "/notice", "/private", "/tippers" ]; // Commands that can be called. var sGuser = msg; // Msg includes user info, so we can treat it as such var sGusername = msg.user; var sGtxt = msg.m; log.debug("Message received:"); log.debug(msg); log.debug("User is grey? " + isGrey(user)); // Check if we should hide this message if (greysOff() && isGrey(sGuser)) { msg["X-Spam"] = true; // Set flag to hide chat from room tellsGuser(cb.settings.msg_cantchat, sGusername); log.info("Silenced message from " + sGusername + " (greys are off)"); } else if (!canSpeak(sGuser)) { var left = timeLeft(sGusername); msg["X-Spam"] = true; // Set flag to hide chat from room tellUser(cb.settings.msg_locked.format(left), sGusername); log.info("Silenced message from " + sGusername); } // If looks like a command, hide it and try running it if (isCmd(sGtxt)) { msg["X-Spam"] = true; // Set flag to hide chat from room runCmd(msg); } // Check if a command is called. if (cbjs.arrayContains(commands, message[0])) { msg["X-Spam"] = true; // Hide command from chat by marking it as spam. var command = message[0]; var errorMessages = new Array(); // Do some checks. if (!has_access) { errorMessages.push("you are not allowed to execute this command."); } // if (message.length < 2) {errorMessages.push("this command needs an extra parameter, please try again: " + command + " [parameter]");} if (errorMessages.length == 0) { // No errors, execute! var target_user = message[1]; message.splice(0, 2); // Remove command and target_user from array. var text = message.join(" "); // Implode remains of array to string. switch (command) { case commands[0]: prefix(user, target_user, text); break; case commands[1]: removePrefix(user, target_user); break; case commands[2]: cb.sendNotice( msg["m"] .split(" ") .slice(1) .join(" "), "", cb.settings["notice_background_color"], cb.settings["notice_color"], "bold" ); break; case commands[3]: var private_text = "[" + user + "] " + msg["m"] .split(" ") .slice(1) .join(" "); cb.sendNotice(private_text, cb.room_slug, "#FFF6FB", "", "bold"); cb.sendNotice(private_text, "", "#FFF6FB", "", "bold", "red"); break; case commands[4]: getTipperList(); break; } } else { //Errors found, display them to the user! cb.sendNotice(errorMessages.join("\n"), user); } } else if (msg["m"].match(/\/listoff/i)) { var is_mod = cb.room_slug == msg["user"] || msg["is_mod"]; msg["X-Spam"] = true; if (is_mod) { cb.settings["tipmenu"] = "no"; } } else if (msg["m"].match(/\/liston/i)) { var is_mod = cb.room_slug == msg["user"] || msg["is_mod"]; msg["X-Spam"] = true; if (is_mod) { cb.settings["tipmenu"] = "yes"; } } else if (msg["m"].match(/\/list/i) && cb.settings["tipmenu"] == "yes") { cb.sendNotice( user + " requested the tip menu.", cb.room_slug, cb.settings["Olivias_notice_background_color"], cb.settings["Olivias_notice_color"], "bold" ); msg["X-Spam"] = true; var notices = " :lovey Say it with a tip :lovey "; for (var k = 1; k <= 100; k++) { if ( cb.settings.get("item_" + k) && parseInt(cb.settings["item_" + k + "_price"]) > 0 && cb.settings.get("item_" + k + "_menu") == "yes" ) { if (parseInt(cb.settings["item_" + k + "_price"]) == 696969) { notices += "\n " + cb.settings["item_" + k]; } else { notices += "\n " + cb.settings["item_" + k + "_price"] + "tk: " + cb.settings["item_" + k]; } } } var is_mod = cb.room_slug == msg["user"] || msg["is_mod"]; if (!is_mod) { cb.sendNotice( notices, msg["user"], cb.settings["tipMenu_notice_background_color"], cb.settings["tipMenu_notice_color"], "bold" ); } else { cb.sendNotice( notices, "", cb.settings["tipMenu_notice_background_color"], cb.settings["tipMenu_notice_color"], "bold" ); } } else if (msg["m"].match(/\/list/i) && cb.settings["tipmenu"] == "no") { cb.sendNotice( user + " tried to request the tip menu.", cb.room_slug, cb.settings["Olivias_notice_background_color"], cb.settings["Olivias_notice_color"], "bold" ); msg["X-Spam"] = true; cb.sendNotice( "I'm sorry, the tip menu is currently disabled.", msg["user"], cb.settings["tipMenu_notice_background_color"], cb.settings["tipMenu_notice_color"], "bold" ); } else if (msg["m"].match(/\/request/i)) { var Request = msg["user"] + " requested: " + msg["m"].split(" ").slice(1).join(" "); var present = 0; for (var j = 0; j < userArray.length; j++) { if (userArray[j] == msg["user"]) { present = 1; } } if (present == 1) { FWBRequests.push(Request); cb.sendNotice( user + " used the request command." + "\n" + Request, "", cb.settings["Olivias_notice_background_color"], cb.settings["Olivias_notice_color"], "bold" ); cb.sendNotice( "Your request has been registered.", msg["user"], cb.settings["fwbRequests_notice_background_color"], cb.settings["fwbRequests_notice_color"], "bold" ); } else { cb.sendNotice( "You do not have permission to use this command.", msg["user"], cb.settings["fwbRequests_notice_background_color"], cb.settings["fwbRequests_notice_color"], "bold" ); cb.sendNotice( user + " tried to use the fwb command but was denied.", cb.room_slug, cb.settings["Olivias_notice_background_color"], cb.settings["Olivias_notice_color"], "bold" ); } msg["X-Spam"] = true; } else if (msg["m"].match(/\/showfwbrequests/i)) { if (cb.room_slug == msg["user"]){ cb.sendNotice( FWBRequests.join("\n"), cb.room_slug, cb.settings["Olivias_notice_background_color"], cb.settings["Olivias_notice_color"], "bold" ); } msg["X-Spam"] = true; } else if (msg["m"].match(/\/whisper/i)) { var WhisperString = msg["m"].split(" ") var Whisper = msg["user"] + " whispered: " + msg["m"].split(" ").slice(1).join(" "); var present = 0; for (var j = 0; j < userArray.length; j++) { if (userArray[j] == msg["user"]) { present = 1; } } if (present == 1) { cb.sendNotice( Whisper, cb.room_slug, cb.settings["fwbWhisper_notice_background_color"], cb.settings["fwbWhisper_notice_color"], "bold" ); cb.sendNotice( msg["user"] + " " + cb.settings["fwbWhisper_public_text"], "", cb.settings["fwbWhisperPUBLIC_notice_background_color"], cb.settings["fwbWhisperPUBLIC_notice_color"], "bold" ); msg["m"] = "*** Message Sent ***"; } msg["X-Spam"] = true; } else if (msg["m"].match(/\/fwb/i)) { var present = 0; for (var j = 0; j < userArray.length; j++) { if (userArray[j] == msg["user"]) { present = 1; } } if (present == 1) { var FWBmessage = cb.settings["fwb_msg"].split("\\n"); // Explode message to an array. var FWBmsg = FWBmessage.join("\n"); cb.sendNotice( FWBmsg, msg["user"], cb.settings["fwbMenu_notice_background_color"], cb.settings["fwbMenu_notice_color"], "bold" ); cb.sendNotice( user + " used the fwb command.", cb.room_slug, cb.settings["Olivias_notice_background_color"], cb.settings["Olivias_notice_color"], "bold" ); } else { cb.sendNotice( "You do not have permission to use this command.", msg["user"], cb.settings["fwbMenu_notice_background_color"], cb.settings["fwbMenu_notice_color"], "bold" ); cb.sendNotice( user + " tried to use the fwb command but was denied.", cb.room_slug, cb.settings["Olivias_notice_background_color"], cb.settings["Olivias_notice_color"], "bold" ); } msg["X-Spam"] = true; } else { // No command. if (msg["m"][0] != "/") { alterNormalMessage(msg); // Alter the message with prefix and/or claim. } } return msg; }); // used by tip menu function getItem(tokens) { for (var l = 1; l <= 100; l++) { if (parseInt(cb.settings["item_" + l + "_price"]) == parseInt(tokens)) { return cb.settings["item_" + l]; } } } // used by tip menu function getItemActive(tokens) { for (var m = 1; m <= 100; m++) { if (parseInt(cb.settings["item_" + m + "_price"]) == parseInt(tokens)) { return cb.settings["item_" + m + "_menu"]; } } } // Act upon tips. cb.onTip(function(tip) { var user = tip["from_user"]; var amount = parseInt(tip["amount"]); if (user in tippers) { tippers[user] += amount; } else { tippers[user] = amount; } //new stuff by SIMON tipCounter += parseInt(tip["amount"]); lastTipAmount = parseInt(tip["amount"]); lastTipper = tip["from_user"]; lastItem = getItem(tip["amount"]); if (lastItem){ tempLastItem = lastItem.split("\\n"); // Explode message to an array. lastItemText = tempLastItem.join("\n"); var itemActive = getItemActive(tip["amount"]); if (cb.settings["tipmenu"] == "yes" && itemActive != "no" && lastItem == cb.settings["item_61"]) { cb.sendNotice( tip["from_user"] + " :heart2 says: " + tip["message"], "", cb.settings["SpeakNote_notice_background_color"], cb.settings["SpeakNote_notice_color"], "bold" ); } else if (cb.settings["tipmenu"] == "yes" && itemActive != "no") { cb.sendNotice( tip["from_user"] + " " + lastItemText, "", cb.settings["tipMenuItem_notice_background_color"], cb.settings["tipMenuItem_notice_color"], "bold" ); } } cb.drawPanel(); }); // Add prefix entry. function prefix(user, target_user, text) { if (text.length > 0) { prefixes[target_user] = text; cb.sendNotice( target_user + "'s messages will be prefixed with: " + text, user ); } else { cb.sendNotice( "you forgot to supply a prefix, please try again: /prefix [username] [prefix text]", user ); } } // Remove prefix entry. function removePrefix(user, target_user) { if (target_user in prefixes) { delete prefixes[target_user]; cb.sendNotice( target_user + "'s messages will no longer be prefixed.", user, cb.settings["notice_background_color"], cb.settings["notice_color"], "bold" ); } else { cb.sendNotice( "no prefix for " + target_user + " found to remove.", user, cb.settings["notice_background_color"], cb.settings["notice_color"], "bold" ); } } // Alter message with prefix and/or claim. function alterNormalMessage(msg) { var user = msg["user"]; // Prefix text of current user if applicable. if (user in prefixes) { msg["m"] = prefixes[user] + " " + msg["m"]; } // Claim user if applicable. if (user in claims) { msg["m"] = claims[user] + " " + msg["m"]; } } // Generate the tippers list. function getTipperList() { var output = "Generating tippers list.\n------------------------------------------------"; var output2 = "Generating tipper string.\n------------------------------------------------\n"; if (Object.keys(tippers).length === 0) { output += "\nNo tippers found in current session."; output2 += "No tippers found in current session."; } else { var keysSorted = Object.keys(tippers).sort(function(a, b) { return tippers[b] - tippers[a]; }); for (n = 0; n < keysSorted.length; n++) { var user = keysSorted[n]; var amount = tippers[user]; output += "\n" + user + " | " + amount + " tokens"; output2 += user + " "; } } output += "\n------------------------------------------------"; output2 += "\n------------------------------------------------"; output += "\n" + output2; cb.sendNotice(output, cb.room_slug); cb.sendNotice(output2, "", "", "", "", "red"); cb.sendNotice("List of FWB requests\n" + FWBRequests.join("\n"), cb.room_slug, cb.settings["Olivias_notice_background_color"], cb.settings["Olivias_notice_color"], "bold"); } // Helper function to get possesive pronoun. function getPossesive(gender) { var possesive; switch (gender) { case "m": possesive = "his"; break; case "f": possesive = "her"; break; case "s": possesive = "its"; break; case "c": possesive = "their"; break; } return possesive; } // Log to debug level log.debug = function(msg) { if (log.level > log.DEBUG) return; //cb.log("Debug: " + msg); tellOwner("Debug: " + log.format(msg)); }; // Log to info level log.info = function(msg) { if (log.level > log.INFO) return; tellOwner("Info: " + log.format(msg)); }; // Log to warning level log.warn = function(msg) { if (log.level > log.WARN) return; tellOwner("Warning: " + log.format(msg)); }; // Log to info level log.err = function(msg) { if (log.level > log.ERR) return; tellOwner("Error: " + log.format(msg)); }; // Format as string, using JSON to pretty print structures log.format = function(msg) { if (typeof msg === "string") return msg; else return JSON.stringify(msg, null, 4); }; String.prototype.format = function() { var args = arguments; return this.replace(/\{(\d+)\}/g, function($0, $1) { return args[$1] !== void 0 ? args[$1] : $0; }); }; // Have we seen this user before? function isNew(username) { return !seen.hasOwnProperty(username); } // Do we always allow this type of user to speak? function isPermaSpeaker(user) { var username = user.user; // Broadcaster can always speak if (username == cb.room_slug) return true; // Test user is always grey if (user.user == "loremipsumbacongrey") return false; // If blue, green or red they can always speak if (user.has_tokens || user.in_fanclub || user.is_mod) return true; else return false; } // If a user is grey. // Split out to allow isPermaSpeaker to change if needed at some point. function isGrey(user) { return !isPermaSpeaker(user); } // Can the user use admin commands? function isAdmin(user) { var username = user.user; // Broadcasters and mods can run admin commands if (username == cb.room_slug || user.is_mod) return true; else return false; } // Is the user allowed to chat function canSpeak(user) { var username = user.user; // If we haven't seen the user before, add them if (isNew(username)) { addUser(user); if (username != cb.room_slug) log.info("Note: Pre-existing user added (no join seen): " + username); } // If they've been marked as canSpeak, yes if (seen[username].canSpeak) return true; // If the timelock has expired, yes if (expired(seen[username].entered)) { setSpeaker(username); return true; } return false; } // Set a user function setSpeaker(username) { seen[username].canSpeak = true; } // Check if a timelock has expired function expired(date) { return elapsed(date) > cb.settings.timelock_duration; } // Get elapsed time since a date, in minutes function elapsed(date) { var now = Date.now(); var minutes = Math.floor((now - date) / (1000 * 60)); return minutes; } // Give user the welcome message function welcomeUser(username) { var msg = cb.settings.msg_welcome; var duration = cb.settings.timelock_duration; tellUser(msg.format(duration), username); } // Start tracking the user function addUser(user) { var username = user.user; var u = {}; // User info u.entered = Date.now(); u.canSpeak = isPermaSpeaker(user); seen[username] = u; log.info("Added user: " + username + " with values: "); log.info(u); log.debug("DB state:"); log.debug(seen); } // Send text to everyone function tellAll(msg) { cb.sendNotice(msg); } // Send text to a given user function tellUser(msg, username) { cb.sendNotice(msg, username); } // Send text to the broadcaster function tellOwner(msg) { tellUser(msg, cb.room_slug); } // How many minutes until a user can speak function timeLeft(username) { var ERR = -1; if (isNew(username)) { log.err("timeLeft called on invalid username: " + username); return ERR; } var entered = seen[username].entered; return cb.settings.timelock_duration - elapsed(entered); } // Does the text look like a command? function isCmd(txt) { if (txt.charAt(0) === "/") return true; else return false; } // Check if greys are off function greysOff() { return cb.settings.greys_off == "True"; } // Commands // Execute command function runCmd(msg) { var username = msg.user; var user = msg; // Msg includes user info, so we can treat it as such // Only admins can run commands if (!isAdmin(user)) { return false; } // Check for the tlg prefix, otherwise command is likely meant for another app if (msg.m.search("/tlg") !== 0) return false; // Extract the command name and any parameters var regex = /^\/tlg\s*(\S*)\s*(\S*.*)/i; var cmdSplit = msg.m.match(regex); log.debug("Command split:"); log.debug(cmdSplit); // No command found if (typeof cmdSplit === 'undefined' || cmdSplit === null) { log.err("Invalid command: " + msg.m); return false; } // Command name var cmd = cmdSplit[1]; // Command parameters var args; if (cmdSplit.length > 1) args = cmdSplit[2]; // If no command is provided just display the help if (typeof cmd === "undefined" || cmd === "") { cmdHelp(username); return false; } // Execute the command switch (cmd.toLowerCase()) { case "resetall": cmdResetAll(); break; case "resetuser": cmdResetUser(args); break; case "greysoff": cmdGreysOff(msg, args); break; case "help": cmdHelp(); break; default: tellUser("Unknown command: " + cmd, username); return false; } return true; } // Show commands function cmdHelp(username) { log.debug("Running cmdHelp"); // If msg is null (such as upon init) assume it's the broadcaster if (typeof username === "undefined") { username = cb.room_slug; } tellUser("", username); tellUser("TimeLockGreys", username); tellUser("=============", username); tellUser("", username); tellUser("/tlg greysoff - Toggle silencing greys on/off", username); tellUser("/tlg resetuser <user> - Force user to restart the timelock", username); tellUser("/tlg resetall - Force all users to restart the timelock", username); tellUser("/tlg help - Display this help message", username); tellUser("", username); } // Reset all seen data, as if starting fresh function cmdResetAll() { seen = {}; tellOwner("Reset all user info. Note: Timelocks for existing users will only start when they rejoin or attempt to speak."); } // Reset data for a specific user function cmdResetUser(username) { if (!isNew(username)) { delete seen[username]; tellOwner("Reset user info for {0}. Note: Timelocks for existing users will only start when they rejoin or attempt to speak.".format(username)); } else { tellOwner("Unknown user {0}.".format(username)); } } // Toggle the ability of greys to speak function cmdGreysOff() { if (cb.settings.greys_off === "True") { cb.settings.greys_off = "False"; tellAll(cb.settings.msg_greyson); } else { cb.settings.greys_off = "True"; tellAll(cb.settings.msg_greysoff); } } // Script startup function init() { //log.level = log.DEBUG; log.debug("Initial user db: " + log.format(seen)); cmdHelp(); } init();
© Copyright Chaturbate 2011- 2024. All Rights Reserved.