Bots Home
|
Create an App
The Gift of Voice
Author:
noddie82
Description
Source Code
Launch Bot
Current Users
Created by:
Noddie82
/* Author: Noddie82 Title: The Gift of Voice and Color Description: Silences all grays, except those that you decide should be allowed to talk. Moderators and people with tokens have voice by default, but can loose it. Change Log: v1.13 2015-10-14 Bug in togglevoice command v1.12 2015-10-12 Bug in the color command v1.11 2015-10-11 Quick commands to change notification style and also interval for the notification messages v1.10 2015-10-11 Added option for a countdown Quick commands for a lot of the options that would normally require an app restart v1.9 2015-10-09 Added tip Leaderboard Added king visualizer Added tipped amount indicator Added room greeting option (telling people welcome in the room) Added tip notice option - allows you to set a message for tippers Fixed that help message was partially spamming to everyone v1.8.1 2015-08-27 Remember that people still write tipnotes even if they don't want colors - dont mess with the colors in those cases v1.8 2015-08-26 Allow people to see tip king with /seeking v1.7 2015-08-24 Bugfix - When someone tips but does not say a color, don't reset their text color. In fact, don't muck about with colors at all when not needed v1.6 2015-08-20 Alert a user that he is now tip king, allow king to turn off the color highlight if wanted with /nothanks Secret feature to change the font color as well as the background - just add font color in hex after background Secret feature allows an easy way to see amount of tokens tipped by a user with /seetips <usr> v1.5 2015-08-18 Secret option to change notification without restarting the bot /setnotification Message;Message2 etc v1.4 2015-08-15 Added option to run off "tip for color notice" Added option to silence blues and mods in super intense rooms Added option to name mods instead of relying on room mod status Added support for dark blue and purple nicks so that people with 0 tokens behave as blues and not grays Added option to add several notifications in addition to the tip for color Added a simple tip king highlight Fixed so it actually works to remove a color from someone now v1.3 2013-05-06 Tell people they can tip for color every 120 seconds Really fix color through tipping v1.2.1-2013-05-04: Bugfix for color through tipping v1.2 - 2013-04-21: Added option screen to enable/disable voice control Added option to throttle gray talk to 1 message per X seconds Added option to allow users to tip for a color Added option to type /voicehelp to list available commands Added option to choose wheter or not moderators can use the slash-commands v1.1 - 2013-04-10: Added option to grant users special background-colors Added option to reset all background-colors Added toggle to disable/reenable voice control v1.0 - 2013-04-09: Initial Release. */ var voiceControlGrays = cb.settings.grays_can_talk == 'Yes' ? false : true; var voiceControlBlues = cb.settings.blues_can_talk == 'Yes' ? false : true; var voiceControlReds = cb.settings.reds_can_talk == 'Yes' ? false : true; var broadcaster = cb.room_slug; var mods = cb.settings.named_mods == null ? [] : cb.settings.named_mods.length == 0 ? [] : cb.settings.named_mods.split(","); var voicedUsers = []; var coloredUsers = []; var coloredFontUsers = []; var throttledUsers = []; var colors = []; colors.red = "FFCCCC"; colors.orange = "FFE0CC"; colors.yellow = 'F8FACD'; colors.lightgreen = "D2FACD"; colors.teal = "C4F0F4"; colors.blue = "C4DAFC"; colors.purple = "E1C4F4"; colors.pink = "F6C6E6"; colors.gray = "d6cdc8"; colors.white = "ffffff"; colors.green = "90EE90"; colors.aqua = "00FFFF"; colors.violet = "EE82EE"; colors.tan = "D2B48C"; colors.sky = "87CEEB"; colors.gold = "FFD700"; //these colors might hurt tryingto read with the black font //colors.trueteal = "00FFFF"; //colors.trueyellow = "FFFF00"; //colors.truepurple = "FF00FF"; //colors.forest = "228B22"; //colors.crimson = "DC143C"; //- add more color choices here var tipKingAmount = cb.settings.tip_king_min -1; var tipKingName = null; var topTipperAmount = cb.settings.tip_king_min -1; var topTipperName = null; var highlightTipKing = true; var tipperStats= []; var tipKingTitle = (typeof(cb.settings.tip_king_title) == 'undefined' || cb.settings.tip_king_title == null || cb.settings.tip_king_title == '') ? "Tip King!" : cb.settings.tip_king_title; var slashCommands = [ new slashCommand("voicehelp", false, false, viewHelpMessage), new slashCommand("nothanks", false, false, function(usr,isMod,parameters) { if(tipKingName == usr) { sendMsg("*** Your messages will no longer be highlighted! ***",usr); highlightTipKing = false; } } ), new slashCommand("seeking", false, false, showKingStats), new slashCommand("listvoices", true, false, listVoices), new slashCommand("voice", true, false, addVoice), new slashCommand("unvoice", true, false, removeVoice), new slashCommand("color", true, false, setColor), new slashCommand("colour", true, false, setColor), //for those fancy pants british users new slashCommand("resetcolors", true, false, resetColors), new slashCommand("resetcolors", true, false, resetColors), new slashCommand("resetvoicecontrol", true, false, resetVoiceControl), new slashCommand("togglevoice", true, false, toggleVoiceGray), new slashCommand("toggelvoiceblue", true, false, toggleVoiceBlue), new slashCommand("togglevoicered", true, true, toggleVoiceRed), new slashCommand("togglevoicegray", true, false, toggleVoiceGray), new slashCommand("togglevoicegrays", true, false, toggleVoiceGray), new slashCommand("toggelvoiceblues", true, false, toggleVoiceBlue), new slashCommand("togglevoicereds", true, true, toggleVoiceRed), new slashCommand("addmod", true, true, addModerator), new slashCommand("removemod", true, true, removeModerator), new slashCommand("seetip", true, false, seeTips), new slashCommand("seetips", true, false, seeTips), new slashCommand("showtip", true, false, seeTips), new slashCommand("showtips", true, false, seeTips), new slashCommand("voiceking", true, false, kingOptions), new slashCommand("voiceleaderboard",true,false, leaderboardOptions), new slashCommand("voicejoinnotice",true,false,enterNoticeOptions), new slashCommand("voicetipnotice",true,false,tipNoticeOptions), new slashCommand("voicetimer",true,false,voiceTimerOptions), new slashCommand("voicenotification",true,false,notificationOptions), new slashCommand("timeleft",false,false,voiceTimeLeft), new slashCommand("voicetiplabels",true,false,voiceTipLabelToggle), new slashCommand("voicetiplabel",true,false,voiceTipLabelToggle), ]; cb.settings_choices = [ { name: 'mod_admins',type: 'choice',defaultValue: 'Yes' ,label: "Allow moderators to use administrative commands",choice1 : 'No',choice2: 'Yes'}, { name: 'grays_can_talk',type: 'choice',defaultValue: 'No',label: "Allow grays to talk",choice1: 'No',choice2: 'Yes'}, {name: 'blues_can_talk',type: 'choice',defaultValue: 'Yes',label: 'Allow blues to talk',choice1: 'No',choice2: 'Yes'}, { name: 'reds_can_talk', type: 'choice',defaultValue: 'Yes',label: 'Allow mods to talk',choice1: 'No',choice2: 'Yes'}, { name: 'grays_throttle',type: 'int',minValue: 0,maxValue: 600,defaultValue: 120,label: "Number of seconds between each time a gray can talk"}, { name: 'color_by_tip', type: 'int', defaultValue: 1, label: 'Minimum tip to get a color of choice (0 = disabled)'}, { name: 'color_by_tip_notify', type: 'int', defaultValue: 2, required: false, label: 'Interval for notifications (0 = disable)' }, { name: 'notification_messages', type: 'str', defaultValue: '', required: false, label: 'Custom Notifications. Just separate with ; for more than 1' }, { name: 'notification_color', type: 'str', defaultValue: 'Blue', label: "Notification background" }, { name: 'notification_style', type: 'choice', choice1: 'Normal', choice2: 'Bold', choice3: 'Bolder', defaultValue: 'Normal', label: "Notification style" }, { name: 'named_mods', type: 'str', defaultValue: '', required: false, label: 'List of users that will have mod access no matter what'}, { name: 'tip_labels', label: 'Show tip amount labels in chat', type: 'choice', choice1: 'Yes', choice2: 'No', defaultValue: 'Yes'}, { name: 'tip_king', label: 'Use tip king', type: 'choice', choice1: 'Yes', choice2: 'No', defaultValue: 'Yes'}, { name: 'tip_king_mode', label: 'Tip king mode', type: 'choice', choice1: 'Highest SINGLE tip', choice2: 'Highest TOTAL tips', defaultValue: 'Highest SINGLE tip'}, { name: 'tip_king_color',type: 'str',defaultValue: '#9F9',required: false,label: 'Highlight color for tip king. Empty for no color' }, { name: 'tip_king_nag', type: 'choice', defaultValue: 'Yes', choice1: 'Yes', choice2: 'No', label: 'Periodically announce the tip required to become king' }, { name: 'tip_king_title', type: 'str', defaultValue: 'Tip King', label: 'Tip King title'}, { name: 'tip_king_min', label: 'Minimum tip for a user to become King:', type: 'int', minValue: 1, maxValue: 1000000, defaultValue: 25}, { name: 'tip_king_timer', label: 'Interval in minutes for tip king notice:', type: 'int', minValue: 1, maxValue: 60, defaultValue: 5}, { name: 'leaderboard', label: 'Show a tip leaderboard', type: 'choice', choice1: 'Yes', choice2: 'No', defaultValue: 'Yes'}, { name: 'leaderboard_nag', label: 'Announce the top tippers?', type: 'choice', choice1: 'Yes', choice2: 'No', defaultValue: 'Yes'}, { name: 'leaderboard_number', label: 'Number of tippers on the leaderboard:', type: 'int', minValue: 1, maxValue: 10, defaultValue: 5}, { name: 'leaderboard_timer', label: 'Interval in minutes for tip leaderboard:', type: 'int', minValue: 1, maxValue: 60, defaultValue: 7}, { name: 'notify_on_enter', label: 'Display a message when users join the room', type: 'choice', choice1: 'Yes', choice2: 'No', defaultValue: 'No'}, { name: 'notify_on_enter_message', label: 'Message for new users', type: 'str', minLength: 1, maxLength: 1000, defaultValue: 'Welcome to my room!'}, { name: 'notify_on_tip', label: 'Display a message when a user tips', type: 'choice', choice1: 'Yes', choice2: 'No', defaultValue: 'No'}, { name: 'notify_on_tip_message', label: 'Message to tippers.', type: 'str', minLength: 1, maxLength: 1000, defaultValue: 'Thank you!'}, { name: 'notify_on_tip_minimum', label: 'Minimum tip to trigger the tip message', type: 'int', minValue: 1, maxValue: 1000000, defaultValue: 10} ]; function viewHelpMessage(usr,isMod) { if(!isMod && cb.settings.color_by_tip == 0) { return; } if(!isMod) { cb.sendNotice("Tip a minimium of " + cb.settings.color_by_tip + " tokens to choose a special background colorr!",usr); } cb.sendNotice("- Possible colors: red, orange, yellow, green, teal, blue, purple, pink, gray. No color specified will reset the background",usr); cb.sendNotice("Type /seeking to see who is the current tip king",usr); cb.sendNotice("Type /timeleft - See how many minutes is left on a countdown",usr); if(isMod) { cb.sendNotice("/voice USER - Give voice to someone",usr); cb.sendNotice("/unvoice USER - Take voice away to someone",usr); cb.sendNotice("/listvoices - List who has voice",usr); cb.sendNotice("/seetips USER - Show how many tokens a given user has tipped this session",usr); cb.sendNotice("/color USER COLOR - Make a user have a special background-color",usr); cb.sendNotice("/color USER BACKGROUNDCOLOR FONTCOLOR - Make a user have a special background color and font color. font color must be in hex",usr); cb.sendNotice("/togglevoice - Toggle the voice control on or off.\n\t\tYou can specify on or off if you just want to make sure it is in a specific mode. ie /togglevoice on",usr); cb.sendNotice("/togglevoiceblue - Toggle the voice control for BLUE users. WARNING - this will silence all unvoiced blues!",usr); if(usr == broadcaster) { cb.sendNotice("/togglevoicered - Toggle the voice control for MODS. WARNING - this will silence all your unvoiced moderators!",usr); } cb.sendNotice("/resetvoicecontrol - Reset voice control for everyone, letting everyone talk again",usr); cb.sendNotice("/resetcolors - Reset all custom colors",usr); cb.sendNotice("/voicetimer - See options for countdown timer",usr); cb.sendNotice("/voiceking - See options for tip king",usr); cb.sendNotice("/voiceleaderboard - See options for leaderboard",usr); cb.sendNotice("/voicejoinnotice - See options for notice on join",usr); cb.sendNotice("/voicetipnotice - See options for notice on tip",usr); cb.sendNotice("/voicenotification - See options for notificatoins",usr); cb.sendNotice("/voicetiplabels OFF or /voicetiplabels OFF - turn tip labels on or off",usr); } } function sendKingNag() { var kingIsSingle = cb.settings.tip_king_mode == 'Highest SINGLE tip'; var tipForKing = kingIsSingle ? tipKingAmount : topTipperAmount; tipForKing++; if(tipForKing < cb.settings.tip_king_min) { tipForKing = cb.settings.tip_king_min; } sendMsg("*** Tip " + tipForKing + " or more to become " + tipKingTitle,""); kingInterval = cb.settings.tip_king_timer; } function showKingStats(usr,isMod) { var kingIsSingle = cb.settings.tip_king_mode == 'Highest SINGLE tip'; if(kingIsSingle ? (tipKingName == null || tipKingName == "") : (topTipperName == null || topTipperName == "") ) { sendMsg("*** Nobody is " + tipKingTitle,usr); return; } sendMsg("*** " + tipKingName + " is " + tipKingTitle + " with a tip of " + (kingIsSingle ? tipKingAmount : topTipperAmount) + "!",usr); } function setBackgroundColor(theUser,theColor,theColorer,allowSpecial,theFontColor) { var resetColor = false; if(!theColor || theColor.length == 0 || theColor.trim() == "") { resetColor = true; } var resetFontColor = false; if(!theFontColor || theFontColor.length == 0 || theFontColor.trim() =="") { resetFontColor = true; } if(allowSpecial && resetColor) { sendMsg("The Gift of Color has been reset for " + theUser,theColorer); coloredUsers[theUser] = null; return; } var theColorLowerCase = theColor.toLowerCase(); if(allowSpecial) { if(resetFontColor) { coloredFontUsers[theUser] = null; } var theFontColorLowerCase = resetFontColor ? "" : theFontColor.toLowerCase(); var isFontHexColor = resetFontColor ? false : /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(theFontColor); if(isFontHexColor) { coloredFontUsers[theUser] = theFontColorLowerCase.substring(1,theFontColorLowerCase.length);; } else { theFontColorLowerCase = ""; } } if(colors[theColorLowerCase] ) { cb.sendNotice("The Gift of the Color '" + theColorLowerCase + "' has been granted to '" + theUser + "'!","","#" + colors[theColorLowerCase],theFontColorLowerCase); coloredUsers[theUser] = colors[theColorLowerCase]; if(!allowSpecial) { coloredFontUsers[theUser] = null; } } else if(allowSpecial) { if(theColor.substring(0,1) != '#' && (theColor.length == 6 || theColor.length == 3) ) { theColor = '#' + theColor; } var isHexColor = /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(theColor); if(isHexColor) { coloredUsers[theUser] = theColor.substring(1,theColor.length); cb.sendNotice("The Gift of the Color '" + theColor + "' has been granted to '" + theUser + "'!","",theColor,theFontColorLowerCase); } else { sendError("Unknown color or color not in hex format #rrggbb - Possible colors: red, orange, yellow, green, teal, blue, purple, pink, gray.",theColorer); } } } cb.onTip(function (tip) { if(cb.settings.color_by_tip > 0) { var x = parseInt(tip['amount']); if(x >= cb.settings.color_by_tip && tip['message'].trim().length > 1 ) { setBackgroundColor(tip['from_user'],tip['message'].trim(),tip['from_user'],false); } } updateTipStats(tip); //if enabled, send a thank you in chat if(cb.settings.notify_on_tip == 'Yes' && parseInt(tip['amount']) >= cb.settings.notify_on_tip_minimum) { sendMsg(cb.settings.notify_on_tip_message,''); } }); cb.onEnter(function(user) { if(cb.settings.notify_on_enter == "Yes" && cb.settings.notify_on_enter_message != '' ) { sendMsg(cb.settings.notify_on_enter_message,user['user']); } }); function slashCommand(trigger,mustBeMod,mustBeBroadcaster,command) { this.trigger = trigger; this.mustBeMod = mustBeMod; this.mustBeBroadcaster = mustBeBroadcaster; this.command = command; this.isForUser = function(isMod,isBroadcaster) { if(isBroadcaster) { return true; } if(this.mustBeBroadcaster) { return false; } if(isMod) { return true; } if(this.mustBeMod) { return false; } return true; } } var currentCountdownTimer = null; function voiceTimeLeft(usr,isMode,msgParameters) { if(currentCountdownTimer == null) { sendMsg("*** There is no countdown running",usr); return; } currentCountdownTimer.announceCountdown(usr); } function voiceTipLabelToggle(usr,IsMod,msgParameters) { var command = null; if(msgParameters.length >= 2) { command = msgParameters[1].toLowerCase(); } switch(command) { case "on": cb.settings.tip_labels = 'Yes'; sendMsg("*** Tip labels are now turned on",usr); break; case "off": cb.settings.tip_labels= 'No'; sendMsg("*** Tip labels are now turned off",usr); break; default: if(cb.settings.tip_labels == 'Yes') { cb.settings.tip_labels = 'No'; sendMsg("*** Tip labels are now turned off",usr); } else { cb.settings.tip_labels = 'Yes'; sendMsg("*** Tip labels are now turned on",usr); } break; } } function notificationOptions(usr,IsMod,msgParameters,msg) { var command = null; if(msgParameters.length >= 2) { command = msgParameters[1].toLowerCase(); } switch(command) { case "msg": if(msgParameters.length < 3) { sendError("*** You must enter at least 1 message for the notification! Example: /voicenotification MSG hello mom",usr); return; } var newMsg = msgParameters[2]; for(var i=3;i<msgParameters.length;i++) { newMsg += " " + msgParameters[i]; } notifications = newMsg.split(";"); cb.settings.notification_messages = newMsg; lastShownNotification == -1; sendMsg("New notifications are set:",usr); for(var i=0;i<notifications.length;i++) { sendMsg("Message " + (i+1) + ": " + notifications[i],usr); } break; case "background": if(msgParameters.length < 3) { sendError("*** You must enter at background color for the notification!\nYou can use any of the named coors\nor a hex color (#ff7f00 etc) Example: /voicenotification BACKGROUND blue",usr); return; } notificationColor = parseColor(msgParameters[2]); sendMsg("*** Notifications will now look like this",usr,notificationColor,notificationFontColor,notificationStyle); break; case "style": if(msgParameters.length < 3) { sendError("*** You must enter at new notification style!\nThere's three types: normal, bold and bolder Example: /voicenotification STYLE bold",usr); return; } var newStyle = msgParameters[2].toLowerCase(); if(newStyle == 'normal') { notificationStyle = 'Normal'; sendMsg("*** Notifications will now look like this",usr,notificationColor,notificationFontColor,notificationStyle); } else if(newStyle == 'bold') { notificationStyle = 'Bold'; sendMsg("*** Notifications will now look like this",usr,notificationColor,notificationFontColor,notificationStyle); } else if(newStyle == 'bolder') { notificationStyle = 'Bolder'; sendMsg("*** Notifications will now look like this",usr,notificationColor,notificationFontColor,notificationStyle); } else { sendError("*** You entered an unkown style!",usr); } break; case "timer": if(msgParameters.length < 3) { sendError("*** You must enter a value for the new notification interval! example: /voicenotification TIMER [0-10]",usr); return; } var value = msgParameters[2]; var numbers = /^[0-9]+$/; if(!value.match(numbers)) { sendError("*** You must enter a number for the timer: /voicenotification TIMER [0-10]",usr); return; } value = parseInt(value); cb.settings.color_by_tip_notify = value; if(value < notificationInterval ) { notificationInterval = value; } if(value > 0) { sendMsg("*** Will now send chat notices every " + value + " minute(s)",usr); } else { sendMsg("*** Chat notices are now turned off",usr); } break; case "fontcolor": if(msgParameters.length < 3) { sendError("*** You must enter at font color for the notification!\nYou can use any of the named coors\nor a hex color (#ff7f00 etc) Example: /voicenotification FONTCOLOR blue",usr); return; } notificationFontColor = parseColor(msgParameters[2]); sendMsg("*** Notifications will now look like this",usr,notificationColor,notificationFontColor,notificationStyle); break; default: sendMsg("Usage:\n/voicenotification MSG Message 1;Message 2;...;Message N\n/voicenotification BACKGROUND [color]\n/voicenotification STYLE [Normal|Bold|Bolder\n/voicenotification FONTCOLOR [color]\n/voicenotification TIMER [0-10]",usr); break; } } function voiceTimerOptions(usr,isMod,msgParameters) { var command = null; if(msgParameters.length >= 2) { command = msgParameters[1].toLowerCase(); } switch(command) { case "countdown": if(currentCountdownTimer != null) { sendError("*** There is a countdown running already, stop it before making a new: /voicetimer STOP",usr); return; } if(msgParameters.length < 3) { sendError("*** You must enter a value to count down to! example: /voicetimer COUNTDOWN 5 Rocket launch Time!",usr); return; } var value = msgParameters[2]; var numbers = /^[0-9]+$/; if(!value.match(numbers)) { sendError("*** You must enter a number for the countdown: /voicetimer COUNTDOWN 5 Rocket launch Time!",usr); return; } value = parseInt(value); var timerCountdownMessage = ""; if(msgParameters.length > 4) { var newMsg = msgParameters[3]; for(var i=4;i<msgParameters.length;i++) { newMsg += " " + msgParameters[i]; } timerCountdownMessage = newMsg; } sendMsg("*** Countdown is started for " + value + " " + timerCountdownMessage,usr); currentCountdownTimer = new countdownHelper(value,timerCountdownMessage); currentCountdownTimer.announceCountdown(); break; case "msg": if(currentCountdownTimer == null) { sendMsg("*** There's no countdown running!",usr); return; } if(msgParameters.length < 3) { sendError("*** You must enter a message for the countdown! Example: /voicetimer MSG hello mom",usr); return; } var newMsg = msgParameters[2]; for(var i=3;i<msgParameters.length;i++) { newMsg += " " + msgParameters[i]; } currentCountdownTimer.timerCountdownMessage = newMsg; sendMsg("*** New countdown message is now '" + newMsg + "'",usr); currentCountdownTimer.announceCountdown(); break; case "add": if(currentCountdownTimer == null) { sendMsg("*** There is no timer running!",usr); return; } if(msgParameters.length < 3) { sendError("*** You must enter a value to add to the countdown! Example: /voicetimer ADD 5",usr); return; } var value = msgParameters[2]; var numbers = /^[-+]?[0-9]+$/; if(!value.match(numbers)) { sendMsg("*** You must enter a number to add to the timer! Use negative numbers to remove values: /voicetimer ADD -3",usr); return; } value = parseInt(value); currentCountdownTimer.timerCountdownValue += value; if(currentCountdownTimer.timerCountdownValue < 0) { currentCountdownTimer.timerCountdownValue = 1; } sendMsg("*** Added " + value + " to the countdown",usr); currentCountdownTimer.announceCountdown(); break; case "status": if( currentCountdownTimer != null) { currentCountdownTimer.announceCountdown(usr); } else { sendMsg("*** No countdown is running",usr); } break; case "stop": if(currentCountdownTimer != null) { sendMsg("*** The countdown timer has been stopped!"); } else { sendMsg("*** No countdown is running",usr); } currentCountdownTimer = null; break; default: sendMsg("*** Usage:\n/voicetimer COUNTDOWN [minutes] (optional message) \n/voicetimer ADD [minutes] \n/voicetimer MSG [countdown message] \n/voicetimer STATUS \n/voicetimer STOP \n",usr); break; } } function tipNoticeOptions(usr,isMod,msgParameters) { var command = null; if(msgParameters.length >= 2) { command = msgParameters[1].toLowerCase(); } switch(command) { case "mintip": if(msgParameters.length < 3) { sendError("*** You must enter a new minimum tip for a tip notice: /voicetipnotice MINTIP [0-100000]",usr); return; } var value = msgParameters[2]; var numbers = /^[0-9]+$/; if(!value.match(numbers)) { sendError("*** You must enter a number for min tip before a tip notice: /voicetipnotice MINTIP [0-10000]",usr); return; } value = parseInt(value); sendMsg("*** Min tip to show a tip notice is now " + value,usr); cb.settings.notify_on_tip_minimum = value; break; case 'msg': if(msgParameters.length < 3) { sendError("*** You must enter a new messagge to display on when a user tips: Usage: /voicetipnotice MSG 'Thanks for tipping!'",usr); return; } var newMsg = msgParameters[2]; for(var i=3;i<msgParameters.length;i++) { newMsg += " " + msgParameters[i]; } cb.settings.notify_on_tip_message = newMsg; sendMsg("*** New Message for tippers is saved",usr); break; case "off": cb.settings.notify_on_tip = 'No'; sendMsg("*** Notice on user tip feature is now turned off",usr); break; case "on": cb.settings.notify_on_tip = 'Yes'; sendMsg("*** Notice on user tip feature is now turned on",usr); break; default: sendMsg("*** Usage: \n/voicetipnotice OFF \n/voicetipnotice ON \n/voicetipnotice MSG 'new message' \n/voicetipnotice MINTIP [0-10000]",usr); break; } } function enterNoticeOptions(usr,isMod,msgParameters) { var command = null; if(msgParameters.length >= 2) { command = msgParameters[1].toLowerCase(); } switch(command) { case 'msg': if(msgParameters.length < 3) { sendError("*** You must enter a new messagge to display on when a user joins: Usage: /voicejoinnotice MSG 'Welcome in the room'",usr); return; } var newMsg = msgParameters[2]; for(var i=3;i<msgParameters.length;i++) { newMsg += " " + msgParameters[i]; } cb.settings.notify_on_enter_message = newMsg; sendMsg("*** New message for new users in the room is saved",usr); break; case "off": cb.settings.notify_on_enter = 'No'; sendMsg("*** Notice on user join feature is now turned off",usr); break; case "on": cb.settings.notify_on_enter = 'Yes'; sendMsg("*** Notice on user join feature is now turned on",usr); break; default: sendMsg("*** Usage: \n/voicejoinnotice OFF \n/voicejoinnotice ON \n/voicejoinnotice MSG 'new message'",usr); break; } } function leaderboardOptions(usr,isMod,msgParameters) { var command = null; if(msgParameters.length >= 2) { command = msgParameters[1].toLowerCase(); } switch(command) { case "timer": if(msgParameters.length < 3) { sendMsg("*** You must enter a new timer for leaderboard nagging: /voiceleaderboard TIMER [0-10]",usr); return; } var value = msgParameters[2]; var numbers = /^[0-9]+$/; if(!value.match(numbers)) { sendError("*** You must enter a new timer for leaderboard nagging: /voiceleaderboard TIMER [0-10]",usr); return; } value = parseInt(value); if(value == 0) { cb.settings.leaderboard_nag = 'No'; sendMsg("*** Leaderboard is disabled",usr); } else { cb.settings.leaderboard_nag = 'Yes'; cb.settings.leaderboard_timer = value; if(value < leaderboardInterval) { leaderboardInterval = value; } sendMsg("*** Will now nag about leaderboard every " + value + " minutes",usr); } break; case "off": cb.settings.leaderboard_nag = 'No'; sendMsg("*** Leaderboard feature is now turned off",usr); break; case "on": cb.settings.leaderboard_nag = 'Yes'; sendMsg("*** Leaderboard feature is now turned on",usr); break; default: sendMsg("*** Usage: \n/voiceleaderboard OFF \n/voiceleaderboard ON \n/voiceleaderboard TIMER [0-20]",usr); break; } } function kingOptions(usr,isMod,msgParameters,msg) { var command = null; if(msgParameters.length >= 2) { command = msgParameters[1].toLowerCase(); } switch(command) { case "timer": if(msgParameters.length < 3) { sendError("*** You must enter a new timer for tip king nagging: /voiceking TIMER [0-10]",usr); return; } var value = msgParameters[2]; var numbers = /^[0-9]+$/; if(!value.match(numbers)) { sendError("*** You must enter a new timer for tip king nagging: /voiceking TIMER [0-10]",usr); return; } value = parseInt(value); if(value == 0) { cb.settings.tip_king_nag = 'No'; sendMsg("*** Nagging about Tip King is disabled",usr); } else { cb.settings.tip_king_nag = 'Yes'; cb.settings.tip_king_timer = value; if(kingInterval > value) { kingInterval = value; } sendMsg("*** Will now nag about tip king every " + value + " minutes",usr); } break; case "mintip": if(msgParameters.length < 3) { sendError("*** You must enter a new minimum tip for the tip king: /voiceking MINTIP [0-100000]",usr); return; } var value = msgParameters[2]; var numbers = /^[0-9]+$/; if(!value.match(numbers)) { sendError("*** You must enter a number for min tip for the tip king: /voiceking MINTIP [0-10000]",usr); return; } value = parseInt(value); sendMsg("*** Min tip to become king is now " + value,usr); cb.settings.tip_king_min = value; var kingIsSingle = cb.settings.tip_king_mode == 'Highest SINGLE tip'; if(kingIsSingle && value > tipKingAmount) { sendMsg("*** Min tip is now higher, Tip King has been reset",usr); tipKingAmount = cb.settings.tip_king_min -1; tipKingName = null; } if(!kingIsSingle && value > topTipperAmount) { sendMsg("*** Min tip is now higher, Tip King has been reset",usr); topTipperAmount = cb.settings.tip_king_min -1; topTipperName = null; } break; case "off": cb.settings.tip_king = 'No'; sendMsg("*** Tip king feature is now turned off",usr); tipKingAmount = cb.settings.tip_king_min -1; tipKingName = null; topTipperAmount = cb.settings.tip_king_min -1; topTipperName = null; break; case "on": cb.settings.tip_king = 'Yes'; sendMsg("*** Tip king feature is now turned on",usr); break; case "mode": if(msgParameters.length < 3) { sendError("*** You must enter a new mode for the tip king! Single Highest or Total tipped!: /voiceking MODE SINGLE|TOTAL",usr); return; } if(msgParameters[2].toLowerCase() == 'single') { sendMsg("*** " + tipKingTitle + " is now in Single Highest Tip mode. The highest single tip counts!"); cb.settings.tip_king_mode = 'Highest SINGLE tip' } else if(msgParameters[2].toLowerCase() == 'total') { sendMsg("*** " + tipKingTitle + " is now in Total tips mode. The highest total tips counts!"); cb.settings.tip_king_mode = 'Highest TOTAL tips'; } else { sendError("*** You must enter either SINGLE or TOTAL for the tip king mode.\nEither Single highest tip\nOr Total tips tipped\n/voiceking MODE SINGLE|TOTAL",usr); } break; case "reset": tipKingAmount = cb.settings.tip_king_min -1; tipKingName = null; topTipperAmount = cb.settings.tip_king_min -1; topTipperName = null; sendMsg("*** Reset Tip King",usr); break; case "title": if(msgParameters.length < 3) { sendError("*** You must enter a new title for tip king: Usage: /voiceking TITLE 'Tip Baron'",usr); return; } var newTitle = msgParameters[2]; for(var i=3;i<msgParameters.length;i++) { newTitle += " " + msgParameters[i]; } tipKingTitle = newTitle; sendMsg("*** Tip king is now called " + newTitle,usr); break; default: sendMsg("*** Usage: \n/voiceking OFF \n/voiceking ON \n/voiceking RESET \n/voiceking TIMER [0-20] \n/voiceking TITLE 'Tip Baron' \n/voiceking MINTIP [0-10000]",usr); break; } } function listVoices(usr) { sendMsg("*** Voiced people ***",usr); for (var i in voicedUsers) { if(i && voicedUsers[i]) { sendMsg(i,usr); } } } function addVoice(usr,isMod,msgParameters) { if(msgParameters.length > 1) { voicedUsers[msgParameters[1].trim()] = true; sendMsg("The Gift of Voice has been granted to '" + msgParameters[1].trim() + "'!"); } else { sendMsg("Usage: /voice USER",usr); } } function removeVoice(usr,isMod,msgParameters) { if(msgParameters.length > 1) { voicedUsers[msgParameters[1].trim()] = false; sendMsg("The Gift of Voice has been removed from '" + msgParameters[1].trim() + "'!"); } else { sendMsg("Usage: /unvoice USER",usr); } } function setColor(usr,isMod,msgParameters) { if(msgParameters.length == 1) { sendMsg("Usage /color USER color",usr); sendMsg("- Possible colors: red, orange, yellow, green, teal, blue, purple, pink, gray. You can also enter a hex color. No color specified will reset the background",usr); } else if(msgParameters.length > 1) { var theColor = null; var theFontColor = null; var theUser = msgParameters[1].trim(); if(msgParameters.length > 2) { theColor = msgParameters[2].trim(); } if(msgParameters.length > 3) { theFontColor = msgParameters[3].trim(); } setBackgroundColor(theUser,theColor,usr,true,theFontColor); } } function resetColors() { sendMsg("=== All colors have been reset! ==="); coloredUsers = []; coloredFontUsers = []; } function resetVoiceControl() { voiceControlGrays = false; voiceControlBlues = false; voiceControlReds = false; sendMsg('=== Everyone can talk, chat restrictions lifted! ==='); } function toggleVoiceGray(usr,isMod,msgParameters) { voiceControlGrays = toggleVoiceAny(usr,voiceControlGrays,"Grays",msgParameters); } function toggleVoiceBlue(usr,isMod,msgParameters) { voiceControlBlues = toggleVoiceAny(usr,voiceControlBlues,"Blues",msgParameters); } function toggleVoiceRed(usr,isMod,msgParameters) { voiceControlReds = toggleVoiceAny(usr,voiceControlReds,"Mods",msgParameters); } function addModerator(usr,isMod,msgParameters) { if(msgParameters.length == 1) { sendMsg('You gotta say who to add as moderator',usr); } else { if(!cbjs.arrayContains(mods,msgParameters[1]) ) { mods.push(msgParameters[1]); } sendMsg(msgParameters[1] + " has been added as a Gift of Voice moderator!",usr); sendMsg("you have been added as a Gift of Voice moderator!",msgParameters[1] ); } } function removeModerator(usr,isMod,msgParameters) { if(msgParameters.length == 1) { sendMsg('You gotta say who to remove as moderator',usr); } else { mods = cbjs.arrayRemove(mods,msgParameters[1]); sendMsg(msgParameters[1] + " has been removed as a Gift of Voice moderator!",usr); sendMsg("you have been removed as a Gift of Voice moderator!",msgParameters[1] ); } } function seeTips(usr,isMod,msgParameters) { if(msgParameters.length > 1) { var who = msgParameters[1]; showTipStats(who,usr); } else { sendMsg("You need to say who you want to see Tips for. Use all for everyone: example: " + msgParameters[0] + " " + usr,usr); } } cb.onMessage(function (msg) { var usr = msg['user']; var isMod = usr == cb.room_slug || msg['is_mod']; var isGray = msg['has_tokens'] == false && msg['in_fanclub'] == false && msg['tipped_recently'] == false && msg['tipped_alot_recently'] == false && msg['tipped_tons_recently'] == false; var hasVoice = voicedUsers[usr] && true; if(isMod) { if(!voiceControlReds || usr == cb.room_slug) { //mods have voice as long as broadcaster doesn't decide to put on control hasVoice = true; } } else if(msg['has_tokens'] || msg['in_fanclub'] ) { if(voicedUsers[usr] == null) { //if a user has tokens or is in fanclub, they must explicitly loose voice to be silenced //unless voiceControll is on for blues if(!voiceControlBlues || msg['in_fanclub'] ) { hasVoice = true; } } else { hasVoice = voicedUsers[usr]; } } if(!voiceControlGrays && isGray && !hasVoice && cb.settings.grays_throttle > 0 ) { //voice control is off, check if throttling of grays are on var last = throttledUsers[usr]; if(!last) { throttledUsers[usr] = new Date().getTime(); } else { var since = new Date().getTime() - last; if(since < cb.settings.grays_throttle * 1000) { //message is too soon, stop it msg['X-Spam'] = true; sendMsg("*** Only Voiced users can talk more often than '" + cb.settings.grays_throttle + "' seconds!",usr); } else { throttledUsers[usr] = null; //null it for quicker fail check } } } if(!hasVoice) { //only stop message if voice is toggled on if( (isGray && voiceControlGrays) || (!isMod && !isGray && voiceControlBlues) || (isMod && voiceControlReds) ) { msg['X-Spam'] = true; //tell the user his message cannot be read by anyone else sendError("*** Your message was not delivered because you don't have voice ***",usr); return msg; } } var isBroadcaster = usr == cb.room_slug; isMod = isBroadcaster || (cb.settings.mod_admins == 'Yes' ? msg['is_mod'] : false); //rerun the isMod, but this time only mod Mods if setting is on if(!isMod) { for(var i=0;i<mods.length;i++) { if(usr == mods[i].trim() ) { isMod = true; break; } } } var isCmd = false; if(msg['m'].charAt(0) == '/') { //handle everything that starts with / as if it is a command //- that means no changing of the text message in case some other mod might be the receiver of this message isCmd = true; var msgParameters = msg['m'].split(" "); var cmd = msgParameters[0].toLowerCase(); for(var i=0;i<slashCommands.length;i++) { //strategy: fail quick - // it's much quicker to check if a command is even available to the user than check if the user typed this // so let's check that first, then check if the command is the one the user typed after //skip this command if the user can't access it if(!slashCommands[i].isForUser(isMod,isBroadcaster) ) { continue; } if( ("/" + slashCommands[i].trigger) == cmd) { slashCommands[i].command(usr,isMod,msgParameters); msg['X-Spam'] = true; return msg; //lets assume there's only 1 command that will ever match at most - otherwise something's wrong } } } else if(msg['m'].charAt(0) == '!') { isCmd = true; } var kingIsSingle = cb.settings.tip_king_mode == 'Highest SINGLE tip'; if(kingIsSingle && tipKingName == usr && highlightTipKing) { msg['background'] = cb.settings.tip_king_color; } if(!kingIsSingle && topTipperName == usr && highlightTipKing) { msg['background'] = cb.settings.tip_king_color; } if(coloredUsers[usr]) { //grant the gift of cool background colors msg['background'] = '#' + coloredUsers[usr]; } if(coloredFontUsers[usr]) { //grant the gift of cool font colors! msg['c'] = '#' + coloredFontUsers[usr]; } if(!isCmd && cb.settings.tip_labels == 'Yes' && tipperStats[usr] ) { msg['m'] = '|' + tipperStats[usr] + '| ' + msg['m']; } return msg; }); function toggleVoiceAny(usr,incommingValue,voiceColor,msgParameters) { var toggleOn = false; var toggleOff = false; if(msgParameters.length > 1) { if(msgParameters[1].trim().toLowerCase() == 'on') { toggleOn = true; } else if(msgParameters[1].trim().toLowerCase() == 'off') { toggleOff = true; } } return toggleVoiceControl(voiceColor,toggleOn,toggleOff,incommingValue,usr); } function toggleVoiceControl(toggleFor,toggleOn,toggleOff,incommingValue,usr) { var retValue = incommingValue; if(toggleOn) { if(!retValue) { sendMsg("Voice control enabled, " + toggleFor + " can no longer talk!"); retValue = true; } else { sendMsg(toggleFor + " are already silenced",usr); } } else if(toggleOff) { if(retValue) { retValue = false; sendMsg("Voice control disabled, " + toggleFor + " can talk!"); } else { sendMsg(toggleFor + " can already talk",usr); } } else if(retValue) { retValue = false; sendMsg("Voice control disabled, " + toggleFor + " can talk!"); } else { sendMsg("Voice control enabled, " + toggleFor + " can no longer talk!"); retValue = true; } return retValue; } function updateTipStats(tip) { var thisTip = tip['amount']; var tipper = tip['from_user']; if(!tipperStats[tipper]) { tipperStats[tipper] = thisTip; } else { tipperStats[tipper] = tipperStats[tipper] + thisTip; } var kingIsSingle = cb.settings.tip_king_mode == 'Highest SINGLE tip'; if(thisTip > tipKingAmount && cb.settings.tip_king == 'Yes') { tipKingAmount = thisTip; if(tipKingName != tipper) { tipKingName = tipper; if(kingIsSingle) { highlightTipKing = true; sendMsg(":crown01 " + tipper +" is now the " + tipKingTitle + " with " + thisTip + " tokens!",""); sendError("*** PS: If you don't want to be highlighted in chat, write /nothanks in chat",tipper); } } } if(tipperStats[tipper] > topTipperAmount && cb.settings.tip_king == 'Yes') { topTipperAmount = tipperStats[tipper]; if(topTipperName != tipper) { topTipperName = tipper; if(!kingIsSingle) { highlightTipKing = true; sendMsg(":crown01 " + tipper +" is now the " + tipKingTitle + " with " +topTipperAmount + " tokens!",""); sendError("*** PS: If you don't want to be highlighted in chat, write /nothanks in chat",tipper); } } } if(cb.settings.leaderboard == 'Yes') { //is the user already on the leaderboard? var onLeaderboard = -1; for(var i=0;i<leaderboard.length;i++) { if(tipper == leaderboard[i][0]) { onLeaderboard = i; break; } } if(onLeaderboard == -1) { if(leaderboard.length == 0) { leaderboard.push( [ tipper , tipperStats[tipper] ] ); } else { //find out where on the leaderboard if at all, start at the bottom and move up var newcommerPosition = -1; for(var i=0;i<leaderboard.length;i++) { if(tipperStats[tipper] > leaderboard[i][1]) { newcommerPosition = i; break; } } if(newcommerPosition != -1) { leaderboard.splice(newcommerPosition,0, [ tipper , tipperStats[tipper] ] ); if(leaderboard.length > cb.settings.leaderboard_number) { leaderboard.pop(); } } else if(leaderboard.length < cb.settings.leaderboard_number) { //tipper didnt overtake anyone, but there's room for more on the list leaderboard.push( [ tipper , tipperStats[tipper] ] ); } } } else { //we are on the leaderboard already, but are we moving up down? lets sort //update stats leaderboard[i][1] = tipperStats[tipper]; //sort it leaderboard = leaderboard.sort( function(a,b) { return b[1] - a[1]; }); } } } function showTipStats(who,modName) { if(who.toLowerCase() == 'all') { for(usr in tipperStats) { sendMsg(usr + " tipped " + tipperStats[usr],modName ); } } else { if(tipperStats[who]) { sendMsg(who + " tipped " + tipperStats[who],modName ); } else { sendMsg(who + " has not tipped yet",modName); } } } function sendNotificationToChat() { lastShownNotification++; if(lastShownNotification > notifications.length-1) { lastShownNotification = -1; } if(lastShownNotification == -1) { if(cb.settings.color_by_tip > 0) { sendMsg("Tip a minimum of " + cb.settings.color_by_tip + " tokens to get your custom background color! Name your color in tip note",""); } else { lastShownNotification++; } } if(lastShownNotification != -1) { if(notifications[lastShownNotification] != '') { sendMsg(notifications[lastShownNotification],""); } } notificationInterval = cb.settings.color_by_tip_notify; } var notificationInterval = cb.settings.color_by_tip_notify; var kingInterval = cb.settings.tip_king_timer; var leaderboardInterval = cb.settings.leaderboard_timer; function noticeController() { notificationInterval--; if(notificationInterval <= 0 && cb.settings.color_by_tip_notify > 0) { sendNotificationToChat(); } if(cb.settings.tip_king == "Yes" && cb.settings.tip_king_nag == 'Yes') { kingInterval--; if(kingInterval <= 0) { sendKingNag(); } } if(cb.settings.leaderboard_nag == 'Yes') { leaderboardInterval--; if(leaderboardInterval <= 0) { sendLeaderboardNag(); } } cb.setTimeout(noticeController, 60000); } function countdownHelper(countdown,message) { this.timerCountdownValue = countdown; this.timerCountdownMessage = message; this.started = new Date().getTime(); this.announceCountdown = function(usr) { if(this.timerCountdownValue > -1) { var message = "**** COUNTDOWN ***\n**\n** "; if(this.timerCountdownValue == 0) { message += "TIME IS UP!"; if(usr == null ) { currentCountdownTimer = null; } } else { message += this.timerCountdownValue + " mins remaining"; } if(this.timerCountdownMessage != "") { message += "\n**\n** Message: " + this.timerCountdownMessage; } sendMsg(message,usr == null ? "" : usr); } } cb.setTimeout(timerFunc,60000); cb.log("started countdown for " + this.timerCountdownValue); } //This functino should have been inside the countdown object, //but because cb-s timeout function doesnt seem to scope the objects correct we must put it outside and do some trixing function timerFunc() { //if the timer callback comes on a canceled timer, don't throw a fit if(currentCountdownTimer == null) { return; } //if the time passed since the object was created untill now is less than 59 seconds, assume that the callback is from an old timer that was stopped var now = new Date().getTime(); if(now - currentCountdownTimer.started < 59000) { cb.log("timer must have been restarted, abort! " + (now - currentCountdownTimer.started) ); return; } currentCountdownTimer.timerCountdownValue--; //announce only every 5 mins then at 3, 1 and on timeout if(currentCountdownTimer.timerCountdownValue % 5 == 0 || currentCountdownTimer.timerCountdownValue == 3 || currentCountdownTimer.timerCountdownValue == 1) { currentCountdownTimer.announceCountdown(); } if(currentCountdownTimer.timerCountdownValue > 0) { cb.setTimeout(timerFunc ,60000); } } function sendLeaderboardNag() { var leaderboardText = ""; var first = true; for(var i=0;i<leaderboard.length;i++) { if(first) { first = false; } else { leaderboardText += "\n"; } leaderboardText += leaderboard[i][0] + " : " + leaderboard[i][1]; } if(!first) { sendMsg('Leaderboard:',""); sendMsg(leaderboardText,""); sendMsg('**',""); } leaderboardInterval = cb.settings.leaderboard_timer;; } var notificationStyle = (typeof(cb.settings.notification_style) == undefined || cb.settings.notification_style == null || cb.settings.notification_style == '') ? "Normal" : cb.settings.notification_style.toLowerCase(); var notificationColor = parseColor(cb.settings.notification_color); var notificationFontColor = ""; function parseColor(colorString) { if(colorString == null || colorString == '' || colorString == "Normal") { returnColor = ""; return returnColor; } else if(colorString == 'Cb orange') { returnColor = "#DC5500"; return returnColor; } else if(colorString == 'Blue') { returnColor = "#94D4E9"; return returnColor; } var colorToTest = colorString; if(colorToTest.charAt(0) != '#') { if(!colors[colorToTest.toLowerCase()] ) { colorToTest = '#' + colorToTest; } else { returnColor = '#' + colors[colorToTest.toLowerCase()]; return returnColor; } } colorToTest = colorToTest.toUpperCase(); var isHexColor = /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(colorToTest); if(isHexColor) { returnColor = colorToTest; } else { returnColor = ""; } return returnColor; } function sendError(msg,usr) { if(!usr) { usr = ""; } cb.sendNotice(msg,usr,'#FF0000','#FFFFFF',notificationStyle); } function sendMsg(msg,usr) { cb.sendNotice(msg,usr,notificationColor,notificationFontColor,notificationStyle); } var lastShownNotification = -2; var notifications = (cb.settings.notification_messages == null || cb.settings.notification_messages.trim() == "") ? [] : cb.settings.notification_messages.split(";"); var leaderboard = []; cb.setTimeout(noticeController, 30000); sendMsg("The Gift of Voice and Color activated"); sendMsg("Write /voicehelp to show available commands"); viewHelpMessage(broadcaster,true);
© Copyright Chaturbate 2011- 2026. All Rights Reserved.