Bots Home
|
Create an App
Dorothy's Token Poll
Author:
dorothy
Description
Source Code
Launch Bot
Current Users
Created by:
Dorothy
/** Name: Dorothy's Ultra Fembot Author: chelsea2950 Created: 11/29/2018 See Change Log on bot description page for revision history This ultrabot is intended to provide more experienced broadcasters and moderators with a single tool to provide most common bot functions, primarily around chat control and personalization. I've borrowed some existing features from many places/bots including 18yearold, allinone and ultrabot for most, so credit to those who have gone before for all your hard work (britney and justin, alice and shaggy, lund, and I'm sure many others). Special recognition to 4science for the Tip Menu and Token Polls (which were built off work by badbadbubba and NotThatFrank). This bot is also intended to be transparent and not automatically add people to your modlist or ticket show lists or give other special rights without permission. **/ // prototype functions { String.prototype.capitalize = function() { return this.charAt(0).toUpperCase() + this.slice(1); } } {cb.settings_choices = [ {name: 'dummy0', label: '******************* Introduction ******************** Latest Updt: 12/2/2019 (version 3.3) See Change Log. **************************************************** Welcome to Dorothy\'s Ultra Fembot, if this is your first time using the bot, you can accept all of the defaults and it will just turn on the minimum set of features such as messaging and tip tracking/leaderboard. Other features such as tip menu, token poll, notifiers, and more can be set up in future shows or turned on during the show by you or your moderator. Moderators are given significant privileges by this bot, so please make sure you assign moderators you can trust. I\'ve also setup a default tip menu, token poll, positions menu, and lush menu using prices that I find to be common, but please update these per your preference, the defaults are only suggestions! Also, you can see the full list of commands for the bot by typing "/fbhelp" in the chat (no quotes), and then also see more detailed help by section. Please enjoy using the ultrabot and feel free to say hello if you see me around, or DM me on twitter @thechelsea2950 if you have questions. Thank you! - chelsea', type: 'choice',required: false}, {name: 'enableTokenPoll', label: '1. Enable on Start? -- Start the Token Poll at start of show? If not starting at the beginning, you can also turn the token poll on later during the show using the "/startpoll" command.', type: 'choice', choice1: 'Yes', choice2: 'No', defaultValue: 'Yes'}, {name: 'pollTitle', label: '2. Poll Title -- What will people be voting for?',type: 'str',required: false,minLength: 1,maxLength: 255}, {name: 'pollInterval', label: '3. Display Interval -- Interval used for displaying the current voting summary (in minutes)',type: 'int',required: false,minValue: 1,maxValue: 15,defaultValue: 2}, {name: 'pollMode', label: '4. End Voting Options -- Voting can be ended and the poll closed using one four methods: manually by the broadcaster or a moderator, using a timer, after a certain number of total votes, or after a number of votes for any one choice',type: 'choice',choice1: 'Ends by Mod/Broadcaster command',choice2: 'Ends after X minutes',choice3: 'Ends after X votes',choice4: 'Ends when one option reaches X votes',defaultValue: 'Ends by Mod/Broadcaster command'}, {name: 'pollCount', label: '5. End Voting Amount -- For the above choices for Poll End Options, if ending after a time period or number of votes, choose the value for X (in minutes or votes) ',type: 'int',required: false,minValue: 1,defaultValue: 10}, {name: 'pollMinimum', label: '6. Minimum votes -- If you would like to set a minimum number of total votes required to make the poll valid, set the minimum here. A setting of 0 disables this feature',type: 'int',minValue: 0,maxValue: 50,defaultValue: 0}, {name: 'pollTxtColor', label: '7. Poll Notice text color',type: 'choice',choice1: 'White/No Color',choice2: 'Black',choice3: 'Dark Grey',choice4: 'Dark Red',choice5: 'Dark Orange',choice6: 'Dark Green',choice7: 'Dark Aqua',choice8: 'Dark Blue',choice9: 'Dark Purple',choice10: 'Dark Pink',choice11: 'Custom',defaultValue: 'Dark Green'}, {name: 'pollCustTxtColor', label: '8. Custom Text Color -- If you picked a custom text color in the previous setting, enter the hex color (6 character hex color codes plus the # prefix)',type: 'str',minLength: 1,maxLength: 7,required: false}, {name: 'pollBgColor', label: '9. Poll Notice background color',type: 'choice', choice1: 'White/No Color',choice2: 'Light Yellow',choice3: 'Light Blue',choice4: 'Light Pink',choice5: 'Light Red',choice6: 'Light Green',choice7: 'Light Purple',choice8: 'Light Orange',choice9: 'Light Grey',choice10: 'Light Aqua',choice11: 'Custom',defaultValue: 'Light Green'}, {name: 'pollCustBgColor', label: '10. Custom Background Color -- If you picked a custom background highlight color in the previous setting, enter the hex color (6 character hex color codes plus the # prefix)',type: 'str',minLength: 1,maxLength: 7,required: false}, {name: 'pollKeepalive', label: '12. Keep Poll Alive? -- When using a Poll Timer, when the timer remaining drops below 30 seconds, keep the poll alive by adding 30 more seconds if people are tipping?',type: 'choice',choice1: 'Yes',choice2: 'No',defaultValue: 'No'}, {name: 'pollModAdd', label: '13. Allow a moderator to add or remove votes?',type: 'choice',choice1: 'Yes',choice2: 'No',defaultValue: 'Yes'}, {name: 'stealPollAmount', label: '14. Allow Steal Poll? -- If you want to allow people to "hijack" or "steal" the poll by tipping a very large amount in a single tip, set the amount here, otherwise set it to zero. Note that this has the potential to anger people who have been voting, but use it at your own discretion.',type: 'int',required: false,minValue: 0,maxValue: 99999,defaultValue: 0,}, {name: 'bctext', label: '15. Personalized Messaging - Replace the general term "broadcaster" and in some cases the room name with the name of your choosing (the name you would like to be called, couples name, etc) wherever it appears in chat notices. Leave blank to just use "The Broadcaster".', type: 'str',required: false, minLength: 1, maxLength: 50}, {name: 'minMsgForNotice', label: '16. Minimum number of messages required to display the next iteration of the chat notice. This helps reduce the frequency with which the recurring notices is posted if there is not a lot of chat. Set to 0 to not impose a minimum number of messages. Values of 10-25 are commonly used but may be set lower if the chat is really slow, or higher if the chat is busy, although if the chat is busy, the normal time interval is usually fine and will not be restricted by this setting.',type: 'int',minValue: 0,maxValue: 1000,defaultValue: 0}, {name: 'dummy1', label: 'You can configure up to 8 Poll Options below by setting the description of the option and the associated price to vote for that option. If you want to handicap certain options, you can also set a starting amount that will be credited to that option at the beginning of the voting (to encourage voting when there are other obvious crowd favorites). Please ensure the prices do not overlap with other menu options, ticket show prices, etc. You must set up at least two poll options with both a description and a price. You can put a dash / minus sign (-) in front of the price for certain options to make them negative numbers and temporarily prevent them from being used in the poll (such as if certain poll options are available at certain times of the month, or during certain types of shows.', type: 'choice',required: false}, {name: 'pollOptLabel1', label: 'Option 1',type: 'str',minLength: 1,maxLength: 50,defaultValue: 'Facial'}, {name: 'pollOptTokens1', label: 'Option 1 tip amount',type: 'int',minValue: -99999,maxValue: 99999,defaultValue: 11}, {name: 'pollOptStart1', label: 'Option 1 "handicap" already tipped amount',type: 'int',minValue: 0,maxValue: 99999,defaultValue: 0}, {name: 'pollOptLabel2', label: 'Option 2',type: 'str',minLength: 1,maxLength: 50,defaultValue: 'Creampie'}, {name: 'pollOptTokens2', label: 'Option 2 tip amount',type: 'int',minValue: -99999,maxValue: 99999,defaultValue: 12}, {name: 'pollOptStart2', label: 'Option 2 "handicap" already tipped amount',type: 'int',minValue: 0,maxValue: 99999,defaultValue: 0}, {name: 'pollOptLabel3', label: 'Option 3',type: 'str',minLength: 1,maxLength: 50,required: false}, {name: 'pollOptTokens3', label: 'Option 3 tip amount',type: 'int',minValue: -99999,maxValue: 99999,required: false}, {name: 'pollOptStart3', label: 'Option 3 "handicap" already tipped amount',type: 'int',minValue: 0,maxValue: 99999,required: false}, {name: 'pollOptLabel4', label: 'Option 4',type: 'str',minLength: 1,maxLength: 50,required: false}, {name: 'pollOptTokens4', label: 'Option 4 tip amount',type: 'int',minValue: -99999,maxValue: 99999,required: false}, {name: 'pollOptStart4', label: 'Option 4 "handicap" already tipped amount',type: 'int',minValue: 0,maxValue: 99999,required: false}, {name: 'pollOptLabel5', label: 'Option 5',type: 'str',minLength: 1,maxLength: 50,required: false}, {name: 'pollOptTokens5', label: 'Option 5 tip amount',type: 'int',minValue: -99999,maxValue: 99999,required: false}, {name: 'pollOptStart5', label: 'Option 5 "handicap" already tipped amount',type: 'int',minValue: 0,maxValue: 99999,required: false}, {name: 'pollOptLabel6', label: 'Option 6',type: 'str',minLength: 1,maxLength: 50,required: false}, {name: 'pollOptTokens6', label: 'Option 6 tip amount',type: 'int',minValue: -99999,maxValue: 99999,required: false}, {name: 'pollOptStart6', label: 'Option 6 "handicap" already tipped amount',type: 'int',minValue: 0,maxValue: 99999,required: false}, {name: 'pollOptLabel7', label: 'Option 7',type: 'str',minLength: 1,maxLength: 50,required: false}, {name: 'pollOptTokens7', label: 'Option 7 tip amount',type: 'int',minValue: -99999,maxValue: 99999,required: false}, {name: 'pollOptStart7', label: 'Option 7 "handicap" already tipped amount',type: 'int',minValue: 0,maxValue: 99999,required: false}, {name: 'pollOptLabel8', label: 'Option 8',type: 'str',minLength: 1,maxLength: 50,required: false}, {name: 'pollOptTokens8', label: 'Option 8 tip amount',type: 'int',minValue: -99999,maxValue: 99999,required: false}, {name: 'pollOptStart8', label: 'Option 8 "handicap" already tipped amount',type: 'int',minValue: 0,maxValue: 99999,required: false} ]; } { // *********************************** Variables and Arrays ************************************** var initialize = 0; var caps = /[A-Z][A-Z]+/; var appNoticeColor = '#a2dfac'; // Used for general messaging from fembot (green) var appWarningColor = '#f4d599'; // Used for general messaging from fembot (yellow) var appAlertColor = '#f4c1bc'; // Used for general messaging from fembot (red) var yellow = '#f4d599'; // Used for clock countdown var red = '#f4c1bc'; // Used for last 2 minutes of clock countdown var dashLine60 = new Array(60).join('-'); var dashLine70 = new Array(70).join('-'); var dashLine80 = new Array(80).join('-'); var dashLine90 = new Array(90).join('-'); var minMessagesForNotice = cb.settings.minMsgForNotice; var msgCounterTokenPoll = 0; var tokenPollToggle = 0; var pollwarnLight = '#FF0000'; var pollwarnDark = '#FFFFFF'; var pollType; var fanDouble = (cb.settings.pollFanClubDouble === 'Yes'); var pollModAdd = (cb.settings.pollModAdd === 'Yes'); var pollStartTime; var pollStopTime; var pollMinsRemain = cb.settings.pollCount; var pollSecsRemain = 60; var votesRemain = cb.settings.pollCount; var stealPollAmount = cb.settings.stealPollAmount; var pollRunning = false; var aliveWarned = false; var nline = 0; var pollOptLabel1 = cb.settings.pollOptLabel1; var pollOptLabel2 = cb.settings.pollOptLabel2; var pollOptLabel3 = cb.settings.pollOptLabel3; var pollOptLabel4 = cb.settings.pollOptLabel4; var pollOptLabel5 = cb.settings.pollOptLabel5; var pollOptLabel6 = cb.settings.pollOptLabel6; var pollOptLabel7 = cb.settings.pollOptLabel7; var pollOptLabel8 = cb.settings.pollOptLabel8; var pollOptTokens1 = cb.settings.pollOptTokens1; var pollOptTokens2 = cb.settings.pollOptTokens2; var pollOptTokens3 = cb.settings.pollOptTokens3; var pollOptTokens4 = cb.settings.pollOptTokens4; var pollOptTokens5 = cb.settings.pollOptTokens5; var pollOptTokens6 = cb.settings.pollOptTokens6; var pollOptTokens7 = cb.settings.pollOptTokens7; var pollOptTokens8 = cb.settings.pollOptTokens8; var pollOptStart1 = cb.settings.pollOptStart1; var pollOptStart2 = cb.settings.pollOptStart2; var pollOptStart3 = cb.settings.pollOptStart3; var pollOptStart4 = cb.settings.pollOptStart4; var pollOptStart5 = cb.settings.pollOptStart5; var pollOptStart6 = cb.settings.pollOptStart6; var pollOptStart7 = cb.settings.pollOptStart7; var pollOptStart8 = cb.settings.pollOptStart8; var pollArrayAmount = []; var pollArrayLabel = []; var pollArrayVotes = []; var pollMinimum = cb.settings.pollMinimum; var totalPollVotes = 0; var pollTitle = cb.settings.pollTitle; // ************ Variables for On-demand Token Poll var odpollType; var odpollModAdd = 'Yes'; var odpollMinsRemain = 0; var odpollSecsRemain = 0; var onDemandPollRunning = false; var onDemandPollEnabled = false; var odpollTitle = 'Poll Topic'; var tempODPollLabels = []; var tempODPollAmounts = []; var odpollArrayAmount = []; var odpollArrayLabel = []; var odpollArrayVotes = []; var nlineOD = 0; } { // *********************************** Functions ************************************** { // Generic functions to set the color or separator characters function checkTextColor(color) { switch (color) { case 'White/No Color': return '#FFFFFF'; case 'Black': return '#000000'; case 'Dark Blue': return '#0629AC'; case 'Dark Pink': return '#FF6680'; case 'Dark Green': return '#006600'; case 'Dark Red': return '#cc0000'; case 'Dark Purple': return '#3d003d'; case 'Dark Grey': return '#737373'; case 'Dark Orange': return '#e77400'; case 'Dark Aqua': return '#006767'; default: if (/^#[0-9A-F]{6}$/i.test(color)) { return color; } else if (/^[0-9A-F]{6}$/i.test(color)) { return ('#' + color); } else { return ('default'); } } } function checkBgColor(color) { switch (color) { case 'White/No Color': return '#FFFFFF'; case 'Light Aqua': return '#adeaea'; case 'Light Pink': return '#FFE6EA'; case 'Light Green': return '#94e594'; case 'Light Red': return '#ff9a9a'; case 'Light Purple': return '#f2cdff'; case 'Light Orange': return '#ffd9b3'; case 'Light Grey': return '#e6e6e6'; case 'Light Blue': return '#d1eaee'; case 'Light Yellow': return '#ffff94' case 'Cream': return '#f9f6ed' default: if (/^#[0-9A-F]{6}$/i.test(color)) { return color; } else if (/^[0-9A-F]{6}$/i.test(color)) { return ('#' + color); } else { return ('default'); } } } // *************************** Token Poll Functions ************************ function setTokenPollToggle(mode, calledby) { setPollColors(); if (mode == 'on') { if(tokenPollToggle == 1) { cb.sendNotice('The Token Poll is already enabled.', calledby, appNoticeColor); } else { tokenPollToggle = 1; initTokenPoll(calledby); cb.sendNotice(calledby + ' has enabled the Token Poll feature. You can now vote in the poll.', '', pollbackground, pollforeground, 'bold'); } } else if (mode == 'off') { if(tokenPollToggle == 0) { cb.sendNotice('The Token Poll is already disabled.', calledby, appNoticeColor); } else { tokenPollToggle = 0; pollArrayAmount = []; pollArrayLabel = []; pollArrayVotes = []; cb.sendNotice(calledby + ' has disabled the Token Poll feature. Voting will no longer be tracked.', '', pollbackground, pollforeground, 'bold'); pollRunning = false; } } else if (mode != null) { cb.sendNotice(mode + ' is not a valid option for /usepoll, valid values are "on" or "off".', calledby, appNoticeColor); } else if (mode == null) { cb.sendNotice('You did not enter a valid option for /usepoll, valid values are "on" or "off".', calledby, appNoticeColor); } } function initTokenPoll(calledby) { switch (cb.settings.pollMode) { case 'Ends by Mod/Broadcaster command': pollType = 'Never'; break; case 'Ends after X minutes': pollType = 'Timer'; break; case 'Ends after X votes': pollType = 'Vote'; break; case 'Ends when one option reaches X votes': pollType = 'Goal'; break; default: cb.sendNotice('Error in determining the poll type', calledby, appNoticeColor); } pollRunning = true; nline = 0; buildPollBoard(calledby); showBoard('timer'); initPollTimer(); cb.setTimeout(displayPoll, 30000); totalPollVotes = 0; } function setPollColors() { if (cb.settings.pollTxtColor == 'Custom') { pollforeground = checkTextColor(cb.settings.pollCustTxtColor); if (pollforeground === 'default') { cb.sendNotice('Token Poll - Error while setting the font color. It has to be in a HEX format. Using default value.', cb.room_slug, '#FFFFFF', '#FF0000', 'bold'); pollforeground = '#FFFFFF'; } } else { pollforeground = checkTextColor(cb.settings.pollTxtColor); } if (cb.settings.pollBgColor == 'Custom') { pollbackground = checkBgColor(cb.settings.pollCustBgColor); if (pollbackground === 'default') { cb.sendNotice('Token Poll - Error while setting the background color. It has to be in a HEX format. Using default value.', cb.room_slug, '#FFFFFF', '#FF0000', 'bold'); pollbackground = '#0629AC'; } } else { pollbackground = checkBgColor(cb.settings.pollBgColor); } } function buildPollBoard(calledby) { for (let i = 1; i <= 8; i++) { var oktoadd = 1; if (this['pollOptTokens'+i] != '' && this['pollOptTokens'+i] != null && this['pollOptTokens'+i] > 0) { if (this['pollOptLabel'+i] != '' && this['pollOptLabel'+i] != null) { for (let j = 0; j < i-1; j++) { if (pollArrayAmount[j] === this['pollOptTokens'+i]) { cb.sendNotice('Tip Price Amount for option ' + i + ' is not unique, it is not added to the board.', calledby, appNoticeColor); oktoadd = 0; break; } else if (pollArrayLabel[j] === this['pollOptLabel'+i]) { cb.sendNotice('Label for option ' + i + ' is not unique, it is not added to the board.', calledby, appNoticeColor); oktoadd = 0; break; } } if (this['pollOptStart'+i] > 0) { startvotes = this['pollOptStart'+i]; } else { startvotes = 0; } if(oktoadd == 1) { populatePollArray(this['pollOptLabel'+i],this['pollOptTokens'+i],startvotes,calledby); } } else { cb.sendNotice('Label for option ' + i + ' is blank or null, not added to board.', calledby, appNoticeColor); } } } } function populatePollArray(label, amount, votes, calledby) { if (!cbjs.arrayContains(pollArrayAmount, amount) && !cbjs.arrayContains(pollArrayLabel, label)) { var pollindex = pollArrayAmount.length; pollArrayLabel[pollindex] = label; pollArrayAmount[pollindex] = amount; pollArrayVotes[pollindex] = votes; } else { cb.sendNotice('Tip Price Amount or Label for option ' + label + ' is not unique, it is not added to the board.', calledby, appNoticeColor); return; } } function showBoard(reqby) { if (reqby === undefined) { reqby = 'timer'; } if (tokenPollToggle == 1) { if (reqby == 'bc' || reqby == 'timer' ) { var pollboard1 = 'Sent to ALL:'; } else { var pollboard1 = 'Sent to you:'; } if (pollRunning) { pollboard1 += '\n \u25B7 \u25B7 \u25B7 \u25B7 \u25B7 \u25B7 ' + bctext + '\'s Token Poll Board \u25C1 \u25C1 \u25C1 \u25C1 \u25C1 \u25C1'; } else { pollboard1 += '\n \u25B7 \u25B7 \u25B7 \u25B7 \u25B7 \u25B7 Poll Results! \u25C1 \u25C1 \u25C1 \u25C1 \u25C1 \u25C1'; } var pollboard2 = '\n \u25c7 \u25c7 \u25c7 \u25c7 \u25c7 \u25c7 ' + pollTitle + ' \u25c7 \u25c7 \u25c7 \u25c7 \u25c7 \u25c7'; let ids = []; for (let i = 0; i < pollArrayAmount.length; i++) { ids.push({ 'votes': pollArrayVotes[i], 'id': i }); } ids.sort(function(a, b) { return b.votes - a.votes; }); for (let j = 0; j < ids.length; j++) { if (0 != pollArrayAmount[ids[j].id]) { pollboard2 += '\n \u23E9 ' + pollArrayLabel[ids[j].id] + ' (Price = ' + pollArrayAmount[ids[j].id] + ' tokens): ' + pollArrayVotes[ids[j].id] + ' vote' + (pollArrayVotes[ids[j].id] != 1 ? 's' : ''); } } if (stealPollAmount > 0) { pollboard2 += '\n *** ' + bctext + ' has enabled hijacking of the poll. If a user tips ' + stealPollAmount + ' tokens in a single tip, they will "hijack" the poll and be able to choose the poll winner regardless of current voting.'; } let pollboard3 = ''; if (pollRunning) { switch (pollType) { case 'Timer': break; case 'Vote': pollboard3 = votesRemain + ' vote' + (votesRemain > 1 ? 's' : '') + ' remaining before poll closes\n'; break; case 'Goal': pollboard3 = 'First option to ' + cb.settings.pollCount + ' votes wins!\n'; break; } pollboard3 += 'Simply tip the shown token amounts to vote for your choice. Type "/poll" at any time to see the poll board.'; if (pollMinimum > 0) { if (totalPollVotes >= pollMinimum) { pollboard3 += '\nThe minimum total number of votes has been met! The poll result is valid.'; } else { votesNeeded = pollMinimum - totalPollVotes; pollboard3 += '\nThe minimum total number of votes to make the poll valid is ' + pollMinimum + ' and has not yet been met. ' + votesNeeded + ' more vote' + (votesNeeded != 1 ? 's' : '') + ' needed!'; } } } else { pollboard3 += '\nThe poll has been closed, no more voting!'; } sendto = reqby; if (reqby == 'timer') { sendto = ''; if (pollRunning) { cb.setTimeout(showBoard, cb.settings.pollInterval * 60000); } } else if (reqby == 'bc') { sendto = ''; } cb.sendNotice(pollboard1 + pollboard2, sendto, pollbackground, pollforeground, 'bold'); cb.sendNotice(pollboard3, sendto, pollbackground, pollforeground, 'bold'); } } function pollTip(tipAmount,voteAmount,tippedby) { for (let i = 0; i < pollArrayAmount.length; i++) { if (tipAmount == pollArrayAmount[i]) { pollArrayVotes[i] += voteAmount; totalPollVotes += voteAmount; if (voteAmount == 1) { cb.sendNotice(tippedby + ' voted for ' + pollArrayLabel[i], '', pollbackground, pollforeground, 'bold'); } else { cb.sendNotice(tippedby + ' voted ' + voteAmount + ' time' + (voteAmount == 1 ? '' : 's') + ' for ' + pollArrayLabel[i], '', pollbackground, pollforeground, 'bold'); } if (pollType == 'Vote') { votesRemain -= voteAmount; } if (pollType == 'Timer' && cb.settings.pollKeepalive == 'Yes' && pollSecsRemain < 30 && pollMinsRemain < 1) { pollStopTime = new Date(pollStopTime.getTime() + 30000); pollSecsRemain = pollSecsRemain + 30; cb.sendNotice('The token poll timer is set to keep alive with continued voting, 30 seconds have been added to the timer. Now ' + pollTimeLeft(), '', pollbackground, pollforeground, 'bold'); if (!aliveWarned) { aliveWarning(); } } if (pollType != 'Timer') { checkPollEnd(); } } } } function stealPoll(tippedby) { if (tokenPollToggle == 1) { cb.sendNotice(' :siren1 ' + tippedby + ' has HIJACKED the poll and will get to choose the winner! :siren1 \nVoting is ended, and no more votes will be counted.', '', pollbackground, pollforeground, 'bold'); if (pollRunning) { pollRunning = false; } } } function aliveWarning() { if (!pollRunning || pollType != 'Timer') { return; } cb.sendNotice('Since you have enabled the setting to keep the poll alive if users are still voting, the poll might be kept alive indefinitely by tipping, however, you can use /endpoll to stop it.', cb.room_slug, appNoticeColor); cb.sendNotice('Since ' + bctext + ' has enabled the setting to keep the poll alive if users are still voting, the poll might be kept alive indefinitely by tipping, however, you can use /endpoll to stop it.', '', appNoticeColor,'','','red'); if (pollMinsRemain < 2 && pollRunning) { cb.setTimeout(aliveWarning, 60000); } aliveWarned = true; } function checkPollEnd() { if (pollType == 'Vote') { if (votesRemain < 1) { pollRunning = false; showWinner(''); } } else if (pollType == 'Goal') { for (let i = 0; i < pollArrayAmount.length; i++) { if (pollArrayVotes[i] >= cb.settings.pollCount) { pollRunning = false; showWinner(''); } } } } function showWinner(u) { let options = []; for (let i = 0; i < pollArrayAmount.length; i++) { options[i] = i; } options.sort(function(a, b) { return pollArrayVotes[b] - pollArrayVotes[a]; }); let win_count = 1; for (let j = 1; j < pollArrayAmount.length; j++) { if (pollArrayVotes[options[j]] != pollArrayVotes[options[0]]) { break; } if (0 != pollArrayAmount[options[j]]) { win_count++; } } let pollwinner1 = '\u23f0 \u23f0 \u23f0 Token Poll has ended! \u23f0 \u23f0 \u23f0 \n'; let pollwinner2 = 'Winner' + (win_count > 1 ? 's (' + win_count + '-way tie)' : '') + ':'; for (let k = 0; k < win_count; k++) { if (pollArrayAmount[options[k]] != 0) { pollwinner2 += '\n \u23E9 ' + pollArrayLabel[options[k]] + ': ' + pollArrayVotes[options[k]] + ' votes'; } } cb.sendNotice(pollwinner1 + pollwinner2, u, pollbackground, pollforeground, 'bold'); } function showLead() { let options = []; let leadOpt = []; for (let i = 0; i < pollArrayAmount.length; i++) { options[i] = i; } options.sort(function(a, b) { return pollArrayVotes[b] - pollArrayVotes[a]; }); if (pollArrayVotes[options[0] ] > 0 ){ leadOpt.push(pollArrayLabel[options[0]]); for (let j = 1; j < pollArrayAmount.length; j++) { if (pollArrayVotes[options[j]] != pollArrayVotes[options[0]]) { break; } if (0 != pollArrayAmount[options[j]]) { leadOpt.push(pollArrayLabel[options[j]]); } } } let polllead; let leadCount = leadOpt.length; if (leadCount === 0){ polllead = 'No votes yet, be sure to vote for your favorite! Type /poll at any time to see all the options.'; } else if (leadCount === 1) { polllead = pollArrayLabel[options[0]] + ' is in the lead by ' + (pollArrayVotes[options[0]] - pollArrayVotes[options[1]]) + ' vote' + ((pollArrayVotes[options[0]] - pollArrayVotes[options[1]]) === 1 ? '' : 's') + '.'; } else { polllead = 'We have a ' + leadCount + '-way tie between ' + formatArray(leadOpt,'and') + '.'; } return polllead; } function formatArray(arr,andor){ let outStr = ''; if (arr.length === 1) { outStr = arr[0]; } else if (arr.length === 2) { outStr = arr.join(' '+andor+' '); } else if (arr.length > 2) { outStr = arr.slice(0, -1).join(', ') + ', '+andor+' ' + arr.slice(-1); } return outStr; } function timeCal() { pollStartTime = new Date(); return pollStopTime - pollStartTime.getTime(); } function pollTimeLeft() { var pollTimeLeft = timeCal(); var milliseconds = pollTimeLeft % 1000; var seconds = ((pollTimeLeft - milliseconds) % 60000); var minutes = ((pollTimeLeft - seconds - milliseconds) % 3600000); var hours = (pollTimeLeft - minutes - seconds - milliseconds); seconds = seconds / 1000; minutes = minutes / 60000; hours = hours / 3600000; if (hours > 0) { return hours + ' hour' + (hours > 1 ? 's' : '') + ' and ' + minutes + ' minute' + (minutes > 1 ? 's' : '') + ' remaining to vote.'; } else if (minutes > 0 && seconds === 0) { return minutes + ' minute' + (minutes > 1 ? 's' : '') + ' remaining to vote!'; } else if (minutes > 0) { return minutes + ' minute' + (minutes > 1 ? 's' : '') + ' and ' + seconds + ' second' + (seconds > 1 ? 's' : '') + ' remaining to vote!'; } else { return seconds + ' second' + (seconds > 1 ? 's' : '') + ' remaining to vote!!!'; } } function initPollTimer() { if (!pollRunning || pollType !== 'Timer') { return; } else { pollStartTime = new Date(); pollStopTime = new Date(pollStartTime.getTime() + cb.settings.pollCount * 60000); pollTimerMin(); } } function pollAddTime(polltimetoadd, u) { pollStopTime = new Date(pollStopTime.getTime() + polltimetoadd * 60000); timetoaddabs = Math.abs(polltimetoadd); if (polltimetoadd > 0) { cb.sendNotice(polltimetoadd + ' minute' + (polltimetoadd == 1 || polltimetoadd == -1 ? ' has' : 's have') + ' been added to the timer. Now ' + pollTimeLeft(), '', pollbackground, pollforeground, 'bold'); } else { cb.sendNotice(timetoaddabs + ' minute' + (timetoaddabs == 1 || timetoaddabs == -1 ? ' has' : 's have') + ' been subtracted from the timer. Now ' + pollTimeLeft(), '', pollbackground, pollforeground, 'bold'); } pollMinsRemain = pollMinsRemain + polltimetoadd; if (pollMinsRemain > 0) { pollDisplaySeconds = false; } else { pollDisplaySeconds = true; } } function pollSwitchToTimer(timetoadd, u) { pollType = 'Timer'; pollStartTime = new Date(); pollStopTime = new Date(pollStartTime.getTime() + timetoadd * 60000); cb.sendNotice('A token poll timer has been set for ' + timetoadd + ' minute' + (timetoadd === 1 || timetoadd === -1 ? '' : 's'), '', pollbackground, pollforeground, 'bold'); pollMinsRemain = timetoadd; pollTimerStopping = false; pollTimerMin(); return; } function pollTimerMin() { if(!pollTimerStopping) { if (!pollRunning || pollType !== 'Timer') { return; } switch (pollMinsRemain) { case 30: case 25: case 20: case 15: case 10: case 9: case 8: case 7: case 6: case 5: case 4: case 3: case 2: cb.sendNotice('\u231A \u231A \u231A ' + pollMinsRemain + ' minutes left to vote!!! \u231A \u231A \u231A', '', pollbackground, pollforeground, 'bold'); break; case 1: cb.sendNotice('\u231A \u231A \u231A There is 1 minute left to vote!!! \u231A \u231A \u231A', '', red, '', 'bold'); break; } pollMinsRemain--; if (pollMinsRemain > 0) { pollDisplaySeconds = false; } else { pollDisplaySeconds = true; } pollSecsRemain = 60; pollTimerSec(); } } function pollTimerSec() { if(!pollTimerStopping) { if (!pollRunning || pollType !== 'Timer') { return; } if (pollDisplaySeconds) { switch (pollSecsRemain) { case 30: case 10: case 5: case 4: case 3: case 2: cb.sendNotice('\u231A \u231A \u231A There are ' + pollSecsRemain + ' seconds left to vote!!! \u231A \u231A \u231A', '', red, '', 'bold'); break; case 1: cb.sendNotice('\u231A \u231A \u231A There is 1 second left to vote!!! \u231A \u231A \u231A', '', red, '', 'bold'); break; } } if (pollSecsRemain < 1) { if (pollMinsRemain >= 1) { pollTimerMin(); } else { cb.sendNotice('\u23f0 \u23f0 \u23f0 Time is up! No more Votes!!! \u23f0 \u23f0 \u23f0', '', appWarningColor, '', 'bold'); showWinner(''); pollRunning = false; } } else { pollSecsRemain--; cb.setTimeout(pollTimerSec, 1000); } } } function pollStopTimer() { pollStopTime = new Date(); pollMinsRemain = 0; pollSecsRemain = 0; pollTimerStopping = true; } function displayPoll() { if (tokenPollToggle == 1 && pollRunning) { if (minMessagesForNotice > 0 && msgCounterPoll < minMessagesForNotice) { cb.setTimeout(displayPoll, 30000); } else { msgCounterPoll = 0; let pollNotice = ['A poll is currently running, type "/poll" to see the current votes and the amounts to tip for each choice.']; if (fanDouble) { pollNotice.push('Fan club members currently get two votes for the price of one!'); } pollNotice.push(showLead()); cb.sendNotice(pollNotice[nline], '', pollbackground, pollforeground, 'bold'); nline += 1; if (nline >= pollNotice.length) { nline = 0; } cb.setTimeout(displayPoll, 90000); } } } // *************************** On-demand Poll Functions ************************ function createOnDemandPoll(startedby) { odpollforeground = checkTextColor('Dark Purple'); odpollbackground = checkBgColor('Light Pink'); onDemandPollEnabled = true; onDemandPollRunning = false; odpollArrayAmount = []; odpollArrayLabel = []; odpollArrayVotes = []; tempODPollLabels = []; tempODPollAmounts = []; nlineOD = 0; odpollType = 'Never'; cb.sendNotice('You have enabled the On-demand Token Poll. Up to 8 poll options can be added using the /makepoll command. You can change the Poll Topic text in the header with the command /pollchgtitle.', startedby, appNoticeColor); cb.sendNotice(startedby + ' has enabled the On-demand Token Poll feature. Once the Poll is completely built, it will be displayed and you will be able to vote in the poll.', '', odpollbackground, odpollforeground, 'bold'); } function disableOnDemandPoll(endedby) { if (onDemandPollRunning) { if (endedby != 'hijack') { cb.sendNotice(endedby + ' has disabled the On-demand Token Poll feature. No more voting will be counted.', '', odpollbackground, odpollforeground, 'bold'); } onDemandPollRunning = false; odpollArrayAmount = []; odpollArrayLabel = []; odpollArrayVotes = []; } tempODPollLabels = []; tempODPollAmounts = []; onDemandPollEnabled = false; if (odpollMinsRemain >= 0 || odpollSecsRemain >= 0) { odpollStopTimer(); } if (endedby != 'hijack') { cb.sendNotice('You have disabled the On-demand Token Poll.', endedby, appNoticeColor); } } function addODTempOption(odlabel,odamount,addedby) { oktoadd = true; for (let i = 0; i <= tempODPollAmounts.length; i++) { if (odamount == tempODPollAmounts[i]) { cb.sendNotice('Option tip price amount for the new entry is not unique, it is not added to the poll board.',addedby, appNoticeColor); oktoadd = false; break; } else if (odlabel == tempODPollLabels[i]) { cb.sendNotice('Option name for the new entry is not unique, it is not added to the poll board.',addedby, appNoticeColor); oktoadd = false; break; } } if (oktoadd) { tempODPollAmounts.push(odamount); tempODPollLabels.push(odlabel); } } function startOnDemandPoll(startedby) { buildODPollBoard(startedby); onDemandPollRunning = true; cb.sendNotice('You have started the On-demand Token Poll, voting can begin! You can still add or remove options in the poll with the command /polloptadd or /polloptrmv.', startedby, appNoticeColor); cb.sendNotice(startedby + ' has started the On-demand Token Poll. You can now vote in the poll.', '', odpollbackground, odpollforeground, 'bold'); showODBoard('timer'); initODPollTimer(); cb.setTimeout(displayODPoll, 30000); } function displayODPoll() { if (onDemandPollRunning) { if (minMessagesForNotice > 0 && msgCounterPoll < minMessagesForNotice) { cb.setTimeout(displayODPoll, 30000); } else { msgCounterPoll = 0; let odpollNotice = ['On-Demand Poll - a poll is currently running, type "/poll" to see the current votes and tip amounts.']; if (fanDouble) { odpollNotice.push('Fan club members currently get two votes for the price of one!'); } odpollNotice.push(odshowLead()); cb.sendNotice(odpollNotice[nlineOD], '', odpollbackground, odpollforeground, 'bold'); nlineOD += 1; if (nlineOD >= odpollNotice.length) { nlineOD = 0; } cb.setTimeout(displayODPoll, 90000); } } } function odshowLead() { let odoptions = []; let odleadOpt = []; for (let i = 0; i < odpollArrayAmount.length; i++) { odoptions[i] = i; } odoptions.sort(function(a, b) { return odpollArrayVotes[b] - odpollArrayVotes[a]; }); if (odpollArrayVotes[odoptions[0] ] > 0 ){ odleadOpt.push(odpollArrayLabel[odoptions[0]]); for (let j = 1; j < odpollArrayAmount.length; j++) { if (odpollArrayVotes[odoptions[j]] != odpollArrayVotes[odoptions[0]]) { break; } if (0 != odpollArrayAmount[odoptions[j]]) { odleadOpt.push(odpollArrayLabel[odoptions[j]]); } } } let odleadCount = odleadOpt.length; if (odleadCount == 0) { odpolllead = 'No votes yet, be sure to vote for your favorite! Type "/poll" at any time to see all the options.'; } else if (odleadCount == 1) { odpolllead = odpollArrayLabel[odoptions[0]] + ' is in the lead by ' + (odpollArrayVotes[odoptions[0]] - odpollArrayVotes[odoptions[1]]) + ' vote' + ((odpollArrayVotes[odoptions[0]] - odpollArrayVotes[odoptions[1]]) === 1 ? '' : 's') + '.'; } else { odpolllead = 'We have a ' + odleadCount + '-way tie between ' + odformatArray(odleadOpt,'and') + '.'; } return odpolllead; } function buildODPollBoard(startedby) { for (let i = 0; i < tempODPollLabels.length; i++) { populateODPollArray(tempODPollLabels[i],tempODPollAmounts[i],0); } } function populateODPollArray(odlabel,odamount,odvotes) { if (!cbjs.arrayContains(odpollArrayAmount,odamount) && !cbjs.arrayContains(odpollArrayLabel,odlabel)) { odpollArrayLabel.push(odlabel); odpollArrayAmount.push(odamount); odpollArrayVotes.push(odvotes); } else { cb.sendNotice('Option tip price or option name for combo (' + odlabel + ',' + odamount + ') is not unique, it is not added to the poll board.',startedby, appNoticeColor); return; } } function showODBoard(odreqby) { if (odreqby === undefined) { odreqby = 'timer'; } if (odreqby == 'bc' || odreqby == 'timer' ) { var odpollboard1 = 'Sent to ALL:'; } else { var odpollboard1 = 'Sent to you:'; } if (onDemandPollRunning) { odpollboard1 += '\n \u25B7 \u25B7 \u25B7 \u25B7 \u25B7 \u25B7 On-Demand Poll \u25C1 \u25C1 \u25C1 \u25C1 \u25C1 \u25C1'; } else { odpollboard1 += '\n \u25B7 \u25B7 \u25B7 \u25B7 \u25B7 \u25B7 Poll Results! \u25C1 \u25C1 \u25C1 \u25C1 \u25C1 \u25C1'; } var odpollboard2 = '\n \u25c7 \u25c7 \u25c7 \u25c7 \u25c7 \u25c7 ' + odpollTitle + ' \u25c7 \u25c7 \u25c7 \u25c7 \u25c7 \u25c7'; let odSortedPollVotes = []; for (let i = 0; i < odpollArrayAmount.length; i++) { odSortedPollVotes.push({ 'odvotes': odpollArrayVotes[i], 'odid': i }); } odSortedPollVotes.sort(function(a, b) { return b.odvotes - a.odvotes; }); for (let j = 0; j < odSortedPollVotes.length; j++) { if (0 != odpollArrayAmount[odSortedPollVotes[j].odid]) { odpollboard2 += '\n \u23E9 ' + odpollArrayLabel[odSortedPollVotes[j].odid] + ' (Price = ' + odpollArrayAmount[odSortedPollVotes[j].odid] + ' tokens): ' + odpollArrayVotes[odSortedPollVotes[j].odid] + ' vote' + (odpollArrayVotes[odSortedPollVotes[j].odid] != 1 ? 's' : ''); } } if (stealPollAmount > 0) { odpollboard2 += '\n *** ' + bctext + ' has enabled hijacking of the poll. If a user tips ' + stealPollAmount + ' tokens in a single tip, they will "hijack" the poll and be able to choose the poll winner regardless of current voting.'; } if (onDemandPollRunning) { odpollboard3 = 'Simply tip the shown token amounts to register your vote. Type "/poll" at any time to see the poll board.'; } else { odpollboard3 = 'The poll has been closed, no more voting!'; } odsendto = odreqby; if (odreqby == 'timer') { odsendto = ''; if (onDemandPollRunning) { cb.setTimeout(showODBoard, cb.settings.pollInterval * 60000); } } else if (odreqby == 'bc') { odsendto = ''; } cb.sendNotice(odpollboard1 + odpollboard2, odsendto, odpollbackground, odpollforeground, 'bold'); cb.sendNotice(odpollboard3, odsendto, odpollbackground, odpollforeground, 'bold'); } function odpollTip(tipAmount,voteAmount,tippedby) { pollindex = odpollArrayAmount.indexOf(tipAmount); odpollArrayVotes[pollindex] += voteAmount; votedfor = odpollArrayLabel[pollindex]; if (voteAmount == 1) { cb.sendNotice(tippedby + ' voted for ' + votedfor + '.', '', odpollbackground, odpollforeground, 'bold'); } else { cb.sendNotice('Fanclub member ' + tippedby + ' voted twice for ' + votedfor + '.', '', odpollbackground, odpollforeground, 'bold'); } } function odshowWinner(u) { let odoptions = []; for (let i = 0; i < odpollArrayAmount.length; i++) { odoptions[i] = i; } odoptions.sort(function(a, b) { return odpollArrayVotes[b] - odpollArrayVotes[a]; }); let win_count = 1; for (let j = 1; j < odpollArrayAmount.length; j++) { if (odpollArrayVotes[odoptions[j]] != odpollArrayVotes[odoptions[0]]) { break; } if (0 != odpollArrayAmount[odoptions[j]]) { win_count++; } } let odpollwinner1 = '\u23f0 \u23f0 \u23f0 Token Poll has ended! \u23f0 \u23f0 \u23f0 \n'; let odpollwinner2 = 'Winner' + (win_count > 1 ? 's (' + win_count + '-way tie)' : '') + ':'; for (let k = 0; k < win_count; k++) { if (odpollArrayAmount[odoptions[k]] != 0) { odpollwinner2 += '\n \u23E9 ' + odpollArrayLabel[odoptions[k]] + ': ' + odpollArrayVotes[odoptions[k]] + ' votes'; } } cb.sendNotice(odpollwinner1 + odpollwinner2, u, odpollbackground, odpollforeground, 'bold'); } function stealODPoll(tippedby) { if (onDemandPollRunning) { cb.sendNotice(' :siren1 ' + tippedby + ' has HIJACKED the poll and will get to choose the winner! :siren1 \nVoting is ended, and no more votes will be counted.', '', odpollbackground, odpollforeground, 'bold'); disableOnDemandPoll('hijack'); } } function odformatArray(arr,andor){ let odoutStr = ''; if (arr.length === 1) { odoutStr = arr[0]; } else if (arr.length === 2) { odoutStr = arr.join(' '+andor+' '); } else if (arr.length > 2) { odoutStr = arr.slice(0, -1).join(', ') + ', '+andor+' ' + arr.slice(-1); } return odoutStr; } function odtimeCal() { odpollStartTime = new Date(); return odpollStopTime - odpollStartTime.getTime(); } function odpollTimeLeft() { var odpollTimeLeft = odtimeCal(); var milliseconds = odpollTimeLeft % 1000; var seconds = ((odpollTimeLeft - milliseconds) % 60000); var minutes = ((odpollTimeLeft - seconds - milliseconds) % 3600000); var hours = (odpollTimeLeft - minutes - seconds - milliseconds); seconds = seconds / 1000; minutes = minutes / 60000; hours = hours / 3600000; if (hours > 0) { return hours + ' hour' + (hours > 1 ? 's' : '') + ' and ' + minutes + ' minute' + (minutes > 1 ? 's' : '') + ' remaining to vote.'; } else if (minutes > 0 && seconds === 0) { return minutes + ' minute' + (minutes > 1 ? 's' : '') + ' remaining to vote!'; } else if (minutes > 0) { return minutes + ' minute' + (minutes > 1 ? 's' : '') + ' and ' + seconds + ' second' + (seconds > 1 ? 's' : '') + ' remaining to vote!'; } else { return seconds + ' second' + (seconds > 1 ? 's' : '') + ' remaining to vote!!!'; } } function initODPollTimer() { if (!onDemandPollRunning || odpollType != 'Timer') { return; } else { odpollStartTime = new Date(); odpollStopTime = new Date(odpollStartTime.getTime() + cb.settings.pollCount * 60000); odpollTimerMin(); } } function odpollAddTime(polltimetoadd, u) { odpollStopTime = new Date(odpollStopTime.getTime() + polltimetoadd * 60000); timetoaddabs = Math.abs(polltimetoadd); if (polltimetoadd > 0) { cb.sendNotice(polltimetoadd + ' minute' + (polltimetoadd == 1 || polltimetoadd == -1 ? ' has' : 's have') + ' been added to the timer. Now ' + odpollTimeLeft(), '', pollbackground, pollforeground, 'bold'); } else { cb.sendNotice(timetoaddabs + ' minute' + (timetoaddabs == 1 || timetoaddabs == -1 ? ' has' : 's have') + ' been subtracted from the timer. Now ' + odpollTimeLeft(), '', pollbackground, pollforeground, 'bold'); } odpollMinsRemain = odpollMinsRemain + polltimetoadd; if (odpollMinsRemain > 0) { odpollDisplaySeconds = false; } else { odpollDisplaySeconds = true; } } function odpollSwitchToTimer(timetoadd, u) { odpollType = 'Timer'; odpollStartTime = new Date(); odpollStopTime = new Date(odpollStartTime.getTime() + timetoadd * 60000); cb.sendNotice('A token poll timer has been set for ' + timetoadd + ' minute' + (timetoadd === 1 || timetoadd === -1 ? '' : 's'), '', odpollbackground, odpollforeground, 'bold'); odpollMinsRemain = timetoadd; odpollTimerStopping = false; odpollTimerMin(); return; } function odpollTimerMin() { if(!odpollTimerStopping) { if (!onDemandPollRunning || odpollType !== 'Timer') { return; } switch (odpollMinsRemain) { case 30: case 25: case 20: case 15: case 10: case 9: case 8: case 7: case 6: case 5: case 4: case 3: case 2: cb.sendNotice('\u231A \u231A \u231A ' + odpollMinsRemain + ' minutes left to vote!!! \u231A \u231A \u231A', '', odpollbackground, odpollforeground, 'bold'); break; case 1: cb.sendNotice('\u231A \u231A \u231A There is 1 minute left to vote!!! \u231A \u231A \u231A', '', red, '', 'bold'); break; } odpollMinsRemain--; if (odpollMinsRemain > 0) { odpollDisplaySeconds = false; } else { odpollDisplaySeconds = true; } odpollSecsRemain = 60; odpollTimerSec(); } } function odpollTimerSec() { if(!odpollTimerStopping) { if (!onDemandPollRunning || odpollType !== 'Timer') { return; } if (odpollDisplaySeconds) { switch (odpollSecsRemain) { case 30: case 10: case 5: case 4: case 3: case 2: cb.sendNotice('\u231A \u231A \u231A There are ' + odpollSecsRemain + ' seconds left to vote!!! \u231A \u231A \u231A', '', red, '', 'bold'); break; case 1: cb.sendNotice('\u231A \u231A \u231A There is 1 second left to vote!!! \u231A \u231A \u231A', '', red, '', 'bold'); break; } } if (odpollSecsRemain < 1) { if (odpollMinsRemain >= 1) { odpollTimerMin(); } else { cb.sendNotice('\u23f0 \u23f0 \u23f0 Time is up! No more Votes!!! \u23f0 \u23f0 \u23f0', '', appWarningColor, '', 'bold'); odshowWinner(''); onDemandPollRunning = false; } } else { odpollSecsRemain--; cb.setTimeout(odpollTimerSec, 1000); } } } function odpollStopTimer() { odpollStopTime = new Date(); odpollMinsRemain = 0; odpollSecsRemain = 0; odpollTimerStopping = true; } // *********************************** Help Function ************************************** function helpModBC(from) { cb.sendNotice('Ultra Fembot help for Token Poll Commands:',from,appNoticeColor); cb.sendNotice( '/poll: (all users) Display the current poll results board in the chat for the requesting user. Displayed to all when requested by moderators.' + '\n/usepoll [on/off]: (mods/bc only) Toggle the setting for whether the Token Poll is "on" or "off". Overrides the initial setting to turn the Token Poll on or off during the show.' + '\n/endpoll: (mods/bc only) When running under manual control, end the poll and display the winner.' + '\n/restartpoll: (mods/bc only) If the poll is accidentally ended, or suspended, it can be restarted using this command.' + '\n/addvote X Y: (mods/bc only) Add or remove "Y" number of votes to the poll item with a price of "X". If "Y" is not specified, defaults to one vote added or removed. Number can be shown as negative (-2) to remove votes. Moderators have to be enabled to use this command.' + '\n/polloptadd X Y: (mods/bc only) Add an item named "Y" with a price of "X" tokens to the poll.' + '\n/polloptrmv X: (mods/bc only) Will remove any item with a price of "X" from the token poll.' + '\n/pollstarttimer X: (mods/bc only) Starts a timer for "X" minutes for the poll when run under timed mode. Poll will automatically end when time runs out.' + '\n/polladdtime X: (mods/bc only) Adds "X" minutes to the poll timer if a timer is running.' + '\n/pollstoptimer: (mods/bc only) Ends the timer if running under timed mode.' + '\n/pollchgtitle [new title]: (mods/bc only) Update the text of the token poll title to [new title].' + '\n/polllead (or /pl): (all users) Display only the notice for the current leader of the poll. When requested by mods or broadcaster, the notice is sent to all.' + '\n/hijackprice [newprice]: (mods/bc only) Update the price for hijacking the poll. Note that updating it to 0 will disable the hijack feature.' + '\nON DEMAND POLL:' + '\n/makepoll X Y: (mods/bc only) Adds a new option to the on-demand poll with a price of X and decription/name of Y. Note that the options are not part of the actual poll (viewers cannot see them, they do not show up with the "/poll" command) until you use the command /odstart to start the poll.' + '\n/odstart: (mods/bc only) Start the on-demand poll, viewers can now see the optionsand vote.' + '\n/odoff: (mods/bc only) Disables the on-demand poll so that the pre-configured poll can be used (or a new on-demand poll can be started).' ,from); cb.sendNotice('',from,appNoticeColor); } } } // ******************************* Upon user entry of a Message ************************************** { cb.onMessage(function (msg) { var message = msg['m'].split(' '); var cmd = 0; var listRegExp = /[,\s]+/; var listRegExpSpc = /[,]+/; var m = msg.m; var u = msg.user; var isMod = msg.is_mod; var isBC = (u === cb.room_slug); var BC = cb.room_slug; if (msg['X-Spam'] != true && minMessagesForNotice > 0) { msgCounterTokenPoll++; } var command = message[0] var commandVar1 = parseInt(message[1]); var commandVar2 = parseInt(message[2]); if(message[0].charAt(0) == '/') { msg['X-Spam'] = true; //******** Chat Control Commands *********** switch(command) { case '/pollhelp': { if (isMod || isBC) { helpModBC(u) } else { cb.sendNotice('Only moderators and broadcasters are able to use that command. All others can use the /poll command to see the current poll.',u,appNoticeColor); } break; } case '/startpoll': { if (isMod || isBC) { if (onDemandPollEnabled) { cb.sendNotice('The On-Demand Token Poll is enabled, the Pre-configured Fembot Token Poll cannot be started at the same time, please turn off the On-Demand Poll with /odoff.', u, appNoticeColor); } else { setTokenPollToggle('on', u) } } else { cb.sendNotice('Only moderators and broadcasters are able to use that command.',u,appNoticeColor); } break; } case '/poll': { sendto = u; if (isMod || isBC) { sendto = 'bc'; } if (tokenPollToggle == 1) { showBoard(sendto); } else if (onDemandPollRunning) { showODBoard(sendto); } else { cb.sendNotice('The Token Poll is disabled.', u, appNoticeColor); } break; } case '/endpoll': { if (isMod || isBC) { if (tokenPollToggle == 1) { cb.sendNotice(u + ' has ended the poll. No more votes will be counted.', '', pollbackground, pollforeground, 'bold'); if (pollRunning) { pollRunning = false; } showWinner(''); } else if (onDemandPollRunning) { cb.sendNotice(u + ' has ended the poll. No more votes will be counted.', '', odpollbackground, odpollforeground, 'bold'); onDemandPollRunning = false; odshowWinner(''); } else { cb.sendNotice('The Token Poll is disabled.', u, appNoticeColor); } } else { cb.sendNotice('Only moderators and broadcasters are able to use that command.',u,appNoticeColor); } break; } case '/restartpoll': { if (isMod || isBC) { if (tokenPollToggle == 1) { cb.sendNotice(u + ' has restarted the poll, voting has resumed.', '', pollbackground, pollforeground, 'bold'); if (!pollRunning) { pollRunning = true; pollType = 'Never'; } } else if (onDemandPollEnabled) { cb.sendNotice(u + ' has restarted the poll, voting has resumed.', '', odpollbackground, odpollforeground, 'bold'); if (!onDemandPollRunning) { onDemandPollRunning = true; } } else { cb.sendNotice('The Token Poll is disabled.', u, appNoticeColor); } } else { cb.sendNotice('Only moderators and broadcasters are able to use that command.',u,appNoticeColor); } break; } case '/resetpoll': { if (isMod || isBC) { if (tokenPollToggle == 1) { pollArrayVotes.fill(0); totalPollVotes = 0; cb.sendNotice(u + ' has reset the poll vote counts, voting is now starting over.', '', pollbackground, pollforeground, 'bold'); if (!pollRunning) { pollRunning = true; pollType = 'Never'; } } else if (onDemandPollEnabled) { if (onDemandPollRunning) { odpollArrayVotes.fill(0); cb.sendNotice(u + ' has reset the On-demand poll vote counts, voting is now starting over.', '', odpollbackground, odpollforeground, 'bold'); } else { cb.sendNotice('The The current On-demand Poll is in the process of being defined and has not yet been started. Use the /odstart command to begin using the current poll options.', u, appNoticeColor); } } else { cb.sendNotice('The Token Poll is disabled, there is no poll currently running to reset. You can use the command "/usepoll on" to start using the pre-configured poll.', u, appNoticeColor); } } else { cb.sendNotice('Only moderators and broadcasters are able to use that command.',u,appNoticeColor); } break; } case '/addvote': { if (isMod || isBC) { if (isMod && !pollModAdd) { cb.sendNotice('The broadcaster has disabled the abaility to add votes for moderators.', u, appNoticeColor); } else { if (tokenPollToggle == 1) { var amount; var voteFail = true; if (commandVar1 === 0 || commandVar2 === 0) { cb.sendNotice('Invalid Entry - The tip price amount and added vote amount cannot be zero. \n ex: "/addvote 10 1" will add 1 vote for the poll option with a price of 10', u, appNoticeColor); break; } if (!commandVar1) { cb.sendNotice('Invalid Entry - A tip price amount must be specified to add votes to. \n ex: "/addvote 10 1" will add 1 vote for the poll option with a price of 10', u, appNoticeColor); break; } if (!commandVar2) { amount = 1; } else { amount = commandVar2; } for (let i = 0; i < pollArrayAmount.length; i++) { if (commandVar1 === pollArrayAmount[i]) { cb.sendNotice(u + ' has ' + (amount > 0 ? 'added' : 'removed') + ' ' + (amount < 0 ? -amount : amount) + ' vote' + (amount === 1 || amount === -1 ? '' : 's') + ' for poll option "' + pollArrayLabel[i] + '".', '', pollbackground, pollforeground, 'bold'); pollArrayVotes[i] += amount; totalPollVotes += amount; voteFail = false; if (pollType === 'Vote') { votesRemain -= amount; } checkPollEnd(); break; } } if (voteFail) { cb.sendNotice('Invalid Entry - That tip price amount is not currently in the poll. \n The first variable needs to match a tip amount on the poll, the second variable is the number of votes to add.\n ex: "/addvote 10 1" will add 1 vote for the poll option with a price of 10', u, appNoticeColor); break; } } else if (onDemandPollRunning) { var voteFail = true; if (commandVar1 === 0 || commandVar2 === 0) { cb.sendNotice('Invalid Entry - The tip price amount and added vote amount cannot be zero. \n ex: "/addvote 10 1" will add 1 vote for the poll option with a price of 10', u, appNoticeColor); break; } if (!commandVar1) { cb.sendNotice('Invalid Entry - A tip price amount must be specified to add votes to. \n ex: "/addvote 10 1" will add 1 vote for the poll option with a price of 10', u, appNoticeColor); break; } if (!commandVar2) { amount = 1; } else { amount = commandVar2; } for (let i = 0; i < odpollArrayAmount.length; i++) { if (commandVar1 == odpollArrayAmount[i]) { cb.sendNotice(u + ' has ' + (amount > 0 ? 'added' : 'removed') + ' ' + (amount < 0 ? -amount : amount) + ' vote' + (amount === 1 || amount === -1 ? '' : 's') + ' for poll option "' + odpollArrayLabel[i] + '".', '', odpollbackground, odpollforeground, 'bold'); odpollArrayVotes[i] += amount; voteFail = false; break; } } if (voteFail) { cb.sendNotice('Invalid Entry - That tip price amount is not currently in the poll. \n The first variable needs to match a tip amount on the poll, the second variable is the number of votes to add.\n ex: "/addvote 10 1" will add 1 vote for the poll option with a price of 10', u, appNoticeColor); break; } } else { cb.sendNotice('The Token Poll is disabled.', u, appNoticeColor); } } } else { cb.sendNotice('Only moderators and broadcasters are able to use that command.',u,appNoticeColor); } break; } case '/polloptadd': { if (isMod || isBC) { if (tokenPollToggle == 1) { var label; var oktoadd = 1; if (commandVar1 <= 0 || isNaN(commandVar1)) { cb.sendNotice('The first variable has be be a number greater than 0. This is the amount the viewers will tip to vote for this selection.', u, appNoticeColor); var oktoadd = 0; break; } if (!message[2]) { cb.sendNotice('You must include a label for this voting selection in the second variable.', u, appNoticeColor); var oktoadd = 0; break; } if (pollArrayAmount.length >= 8) { cb.sendNotice('There are already 8 entries in the poll, no more can be added.', u, appNoticeColor); var oktoadd = 0; break; } for (let j = 0; j < pollArrayAmount.length; j++) { if (pollArrayAmount[j] === commandVar1) { cb.sendNotice('Tip Price Amount specified is already used in the poll, and will not be added to the board. Please try again with a unique tip amount.', u, appNoticeColor); var oktoadd = 0; break; } } for (let i = 2; i < message.length; i++) { if (i === 2) { label = message[i]; } else { label += ' ' + message[i]; } } for (let j = 0; j < pollArrayLabel.length; j++) { if (pollArrayLabel[j] === label) { cb.sendNotice('The Poll Option Label specified is already used in the poll, and will not be added to the board. Please try again with a unique label value.', u, appNoticeColor); var oktoadd = 0; break; } } if(oktoadd == 1) { populatePollArray(label,commandVar1,0,u); cb.sendNotice(u + ' added the option "' + label + '" to the poll.', '', pollbackground, pollforeground, 'bold'); } } else if (onDemandPollEnabled && !onDemandPollRunning) { cb.sendNotice('The On-demand Token Poll is still being built, please use the /makepoll command.', u, appNoticeColor); } else if (onDemandPollRunning) { var label; var oktoadd = 1; if (commandVar1 <= 0 || isNaN(commandVar1)) { cb.sendNotice('The first variable has be be a number greater than 0. This is the amount the viewers will tip to vote for this selection.', u, appNoticeColor); var oktoadd = 0; break; } if (!message[2]) { cb.sendNotice('You must include a label for this voting selection in the second variable.', u, appNoticeColor); var oktoadd = 0; break; } if (odpollArrayAmount.length >= 8) { cb.sendNotice('There are already 8 entries in the poll, no more can be added.', u, appNoticeColor); var oktoadd = 0; break; } for (let j = 0; j < odpollArrayAmount.length; j++) { if (odpollArrayAmount[j] == commandVar1) { cb.sendNotice('Tip Price Amount specified is already used in the poll, and will not be added to the board. Please try again with a unique tip amount.', u, appNoticeColor); var oktoadd = 0; break; } } for (let i = 2; i < message.length; i++) { if (i == 2) { label = message[i]; } else { label += ' ' + message[i]; } } for (let j = 0; j < odpollArrayLabel.length; j++) { if (odpollArrayLabel[j] == label) { cb.sendNotice('The Poll Option Label specified is already used in the poll, and will not be added to the board. Please try again with a unique label value.', u, appNoticeColor); var oktoadd = 0; break; } } if (oktoadd == 1) { populateODPollArray(label,commandVar1,0); cb.sendNotice(u + ' added the option "' + label + '" to the poll.', '', odpollbackground, odpollforeground, 'bold'); } } else { cb.sendNotice('The Token Poll is disabled.', u, appNoticeColor); } } else { cb.sendNotice('Only moderators and broadcasters are able to use that command.', u, appNoticeColor); } break; } case '/polloptrmv': { if (isMod || isBC) { if (tokenPollToggle == 1) { if (commandVar1 <= 0 || isNaN(commandVar1)) { cb.sendNotice('The first variable has be be a number greater than 0. This value is used to select the poll item that will be removed based on the price.', u, appNoticeColor); break; } if (pollArrayAmount.length <= 2) { cb.sendNotice('There are only 2 entries in the poll, no more can be removed.', u, appNoticeColor); break; } if (cbjs.arrayContains(pollArrayAmount,commandVar1)) { pollindex = pollArrayAmount.indexOf(commandVar1); cb.sendNotice(u + ' removed the option "' + pollArrayLabel[pollindex] + '" from the poll.', '', pollbackground, pollforeground, 'bold'); pollArrayAmount.splice(pollindex,1); pollArrayLabel.splice(pollindex,1); pollArrayVotes.splice(pollindex,1); } else { cb.sendNotice('The specified poll option amount is not in the poll, please try again.', u, appNoticeColor); } } else if (onDemandPollEnabled && !onDemandPollRunning) { cb.sendNotice('The On-demand Token Poll is still being built, please finish the poll using the /makepoll command and /odstart command, and then options can be removed.', u, appNoticeColor); } else if (onDemandPollRunning) { if (commandVar1 <= 0 || isNaN(commandVar1)) { cb.sendNotice('The first variable has be be a number greater than 0. This value is used to select the poll item that will be removed based on the price.', u, appNoticeColor); break; } if (odpollArrayAmount.length <= 2) { cb.sendNotice('There are only 2 entries in the poll, no more can be removed.', u, appNoticeColor); break; } if (cbjs.arrayContains(odpollArrayAmount,commandVar1)) { pollindex = odpollArrayAmount.indexOf(commandVar1); cb.sendNotice(u + ' removed the option "' + odpollArrayLabel[pollindex] + '" from the poll.', '', odpollbackground, odpollforeground, 'bold'); odpollArrayAmount.splice(pollindex,1); odpollArrayLabel.splice(pollindex,1); odpollArrayVotes.splice(pollindex,1); } else { cb.sendNotice('The specified poll option amount is not in the poll, please try again.', u, appNoticeColor); } } else { cb.sendNotice('The Token Poll is disabled.', u, appNoticeColor); } } else { cb.sendNotice('This command is only available for broadcasters and moderators.', u, appNoticeColor); } break; } case '/pst': case '/pollstarttimer': { if (isMod || isBC) { if (tokenPollToggle == 1) { if (!pollRunning) { cb.sendNotice('The poll is not running, cannot to start a timer.', u, appNoticeColor); break; } if (pollType == 'Timer' && (pollMinsRemain >= 1 || pollSecsRemain >= 1)) { cb.sendNotice('A timer is already running, please use "/polladdtime [X]" to add time to timer.', u, appNoticeColor); break; } if (!commandVar1) { cb.sendNotice('Invalid command, you need to specify the starting point for the timer in minutes. Example: use "/pollstarttimer 10" to start a 10 minute timer.', u, appNoticeColor); break; } if (commandVar1 > 60) { cb.sendNotice('The time specified is greater than 60 minutes, please use a smaller value.', u, appNoticeColor); break; } commandVar1 = parseInt(commandVar1) if (isNaN (commandVar1)) { cb.sendNotice('Invalid value, the time entered must be a numeric value in minutes. Example: use "/pollstarttimer 10" to start a 10 minute timer.', u, appNoticeColor); break; } if (pollType !== 'Timer') { pollTimerStopping = false; pollSwitchToTimer(commandVar1, u); break; } } else if (onDemandPollEnabled && !onDemandPollRunning) { cb.sendNotice('An on-demand poll has been created but not started. You can add more poll options or use the command /odstart when ready to start the poll', u, appNoticeColor); } else if (onDemandPollRunning) { if (odpollType == 'Timer' && (odpollMinsRemain >= 1 || odpollSecsRemain >= 1)) { cb.sendNotice('A timer is already running, please use "/polladdtime [X]" to add time to timer.', u, appNoticeColor); break; } if (!commandVar1) { cb.sendNotice('Invalid command, you must specify the time to use for the countdown in minutes. Example: use "/pollstarttimer 10" to start a 10 minute timer.', u, appNoticeColor); break; } if (commandVar1 > 60) { cb.sendNotice('The time specified is greater than 60 minutes, please use a smaller value.', u, appNoticeColor); break; } commandVar1 = parseInt(commandVar1) if (isNaN (commandVar1)) { cb.sendNotice('Invalid value, the time entered must be a numeric value in minutes. Example: use "/pollstarttimer 10" to start a 10 minute timer', u, appNoticeColor); break; } if (odpollType !== 'Timer') { odpollTimerStopping = false; odpollSwitchToTimer(commandVar1, u); break; } } else { cb.sendNotice('The Token Poll is disabled.', u, appNoticeColor); } } else { cb.sendNotice('This command is only available for broadcasters and moderators.', u, appNoticeColor); } break; } case '/polltimeleft': { if (tokenPollToggle == 1) { if (pollType == 'Timer') { cb.sendNotice(pollTimeLeft(), u, pollbackground, pollforeground, 'bold'); break; } else { cb.sendNotice('Timer is not running.', u, appNoticeColor); } } else if (onDemandPollRunning) { if (odpollType == 'Timer') { cb.sendNotice(odpollTimeLeft(), u, odpollbackground, odpollforeground, 'bold'); } else { cb.sendNotice('Timer is not running.', u, appNoticeColor); } } else { cb.sendNotice('A Token Poll is not running.', u, appNoticeColor); } break; } case '/polladdtime': { if (isMod || isBC) { if (tokenPollToggle == 1) { if (!pollRunning) { cb.sendNotice('The poll is not running, no need to add time.', u, appNoticeColor); } else if (!commandVar1) { cb.sendNotice('Invalid command, you need to specify the amount of time to add to the timer in minutes. Example: use "/polladdtime 3" to add 3 minutes to the timer', u, appNoticeColor); } else if (pollType !== 'Timer') { cb.sendNotice('The poll is currently configured for vote count or manual end, a timer is not valid in this mode.', u, appNoticeColor); } else if (pollMinsRemain + commandVar1 <= 0) { cb.sendNotice('The value is over the amount of time left. You can use "/endpoll" to stop the poll and pick the winner.', u, appNoticeColor); } else if (pollMinsRemain + commandVar1 > 60) { cb.sendNotice('The added time will increase the timer to greater than 60 minutes, please use a smaller value.', u, appNoticeColor); } else { pollAddTime(commandVar1, u); } } else if (onDemandPollRunning) { if (!commandVar1) { cb.sendNotice('Invalid command, you need to specify the amount of time to add to the timer in minutes. Example: use "/polladdtime 3" to add 3 minutes to the timer', u, appNoticeColor); } else if (odpollType !== 'Timer') { cb.sendNotice('The poll is currently configured for vote count or manual end, a timer is not valid in this mode.', u, appNoticeColor); } else if (odpollMinsRemain + commandVar1 <= 0) { cb.sendNotice('The value is over the amount of time left. You can use "/endpoll" to stop the poll and pick the winner.', u, appNoticeColor); } else if (odpollMinsRemain + commandVar1 > 60) { cb.sendNotice('The added time will increase the timer to greater than 60 minutes, please use a smaller value.', u, appNoticeColor); } else { odpollAddTime(commandVar1, u); } } else { cb.sendNotice('The Token Poll is disabled.', u, appNoticeColor); } } else { cb.sendNotice('This command is only available for broadcasters and moderators.', u, appNoticeColor); } break; } case '/pollstoptimer': { if (isMod || isBC) { if (tokenPollToggle == 1) { if (!pollRunning) { cb.sendNotice('The poll is not running.', u, appNoticeColor); } else if (pollType != 'Timer' || pollMinsRemain <= 0 || pollSecsRemain <= 0) { cb.sendNotice('A timer is not in use, ignoring command.', u, appNoticeColor); } else if (pollType == 'Timer') { pollType = 'Never'; pollStopTimer(); cb.sendNotice('The timer has been canceled, switching modes to manual end. The poll will go on until stopped by the ' + bctext + ' or a moderator.', '', pollbackground, pollforeground, 'bold'); } } else if (onDemandPollRunning) { if (odpollType != 'Timer' || odpollMinsRemain <= 0 || odpollSecsRemain <= 0) { cb.sendNotice('A timer is not in use, ignoring command.', u, appNoticeColor); } else if (odpollMinsRemain >= 0 || odpollSecsRemain >= 0) { odpollType = 'Never'; odpollStopTimer(); cb.sendNotice('The timer has been canceled, switching modes to manual end. The poll will go on until stopped by the ' + bctext + ' or a moderator.', '', odpollbackground, odpollforeground, 'bold'); } } else { cb.sendNotice('The Token Poll is disabled.', u, appNoticeColor); } } else { cb.sendNotice('This command is only available for broadcasters and moderators.', u, appNoticeColor); } break; } case '/pollchgtitle': { if (isMod || isBC) { if (tokenPollToggle == 1) { newtitle = msg['m'].substring(14).trim() if (newtitle) { pollTitle = newtitle; cb.sendNotice('You have updated the poll title to "' + newtitle + '".', u, appNoticeColor); } else { cb.sendNotice('A new title was not specified, please try the command again in the format "/pollchgtitle [new title]".', u, appNoticeColor); } } else if (onDemandPollEnabled) { newtitle = msg['m'].substring(14).trim() if (newtitle) { odpollTitle = newtitle; cb.sendNotice('You have updated the poll title to "' + newtitle + '".', u, appNoticeColor); } else { cb.sendNotice('A new title was not specified, please try the command again in the format "/pollchgtitle [new title]".', u, appNoticeColor); } } else { cb.sendNotice('The Token Poll is disabled.', u, appNoticeColor); } } else { cb.sendNotice('This command is only available for broadcasters and moderators.', u, appNoticeColor); } break; } case '/pl': case '/polllead': { sendto = u; if (isMod || isBC) { sendto = ''; } if (tokenPollToggle == 1) { cb.sendNotice((sendto == '' ? 'Sent to ALL: ' : 'Sent to YOU: ') + showLead(), sendto, pollbackground, pollforeground, 'bold'); } else if (onDemandPollRunning) { cb.sendNotice((sendto == '' ? 'Sent to ALL: ' : 'Sent to YOU: ') + odshowLead(), sendto, odpollbackground, odpollforeground, 'bold'); } else { cb.sendNotice('The Token Poll is disabled.', u, appNoticeColor); } break; } case '/hijackprice': { if (isMod || isBC) { if (tokenPollToggle == 1 || onDemandPollRunning) { numprice = parseInt(message[1]) if (isNaN(numprice)) { cb.sendNotice('The value entered for the new "hijack" price is not numeric, please try again.', u, appNoticeColor); break; } else if (numprice < 0 || numprice > 99999) { cb.sendNotice('The value entered for new "hijack" price is outside allowable values from 0 to 99999, please try again. Note that a value of 0 will disable the hijack feature.', u, appNoticeColor); } else { stealPollAmount = numprice; if (stealPollAmount == 0) { if (tokenPollToggle == 1) { cb.sendNotice('The "hijacking" of the poll has been disabled.', u, pollbackground, pollforeground, 'bold'); } else if (onDemandPollRunning) { cb.sendNotice('The "hijacking" of the poll has been disabled.', u, odpollbackground, odpollforeground, 'bold'); } } else { if (tokenPollToggle == 1) { cb.sendNotice('The price to "hijack" the poll has been set to ' + numprice + ' tokens.', u, pollbackground, pollforeground, 'bold'); } else if (onDemandPollRunning) { cb.sendNotice('The price to "hijack" the poll has been set to ' + numprice + ' tokens.', u, odpollbackground, odpollforeground, 'bold'); } } } } else { cb.sendNotice('The Token Poll is disabled.', u, appNoticeColor); } } else { cb.sendNotice('Only moderators and broadcasters are able to use that command.', u, appNoticeColor); } break; } //********* On-demand Poll Commands case '/makepoll': { if (isMod || isBC) { if (tokenPollToggle == 1) { cb.sendNotice('The Pre-configured Token Poll is enabled, an on-demand poll cannot be started at the same time. You can disable the pre-configured Fembot poll with the command "/usepoll off".', u, appNoticeColor); } else if (onDemandPollRunning) { cb.sendNotice('The on-demand poll is already running, please use the "/polloptadd" command to add another item to the poll.', u, appNoticeColor); } else { oktoadd = true; if (commandVar1 <= 0 || isNaN(commandVar1)) { cb.sendNotice('The first variable is the poll option price and must be a number greater than 0. This is the amount the viewers will tip to vote for this selection. Sample command format: "/makepoll 13 Take off shirt" to add this option for 13 tokens.', u, appNoticeColor); oktoadd = false; break; } if (!message[2]) { cb.sendNotice('The second parameter is the tip option name and must be entered. It can be a word or phrase, spaces are ok. Sample command format: "/makepoll 13 Take off shirt" to add this option for 13 tokens.', u, appNoticeColor); oktoadd = false; break; } if (tempODPollAmounts.length >= 8) { cb.sendNotice('There are already 8 entries in the poll, no more can be added.', u, appNoticeColor); oktoadd = false; break; } for (let j = 0; j < tempODPollAmounts.length; j++) { if (tempODPollAmounts[j] == commandVar1) { cb.sendNotice('Tip Price Amount specified is already used in the poll, and will not be added to the board. Please try again with a unique tip amount.', u, appNoticeColor); oktoadd = false; break; } } for (let i = 2; i < message.length; i++) { if (i == 2) { label = message[i]; } else { label += ' ' + message[i]; } } for (let j = 0; j < tempODPollLabels.length; j++) { if (tempODPollLabels[j] == label) { cb.sendNotice('The Poll Option Label specified is already used in the poll, and will not be added to the board. Please try again with a unique label value.', u, appNoticeColor); oktoadd = false; break; } } if (oktoadd) { if (!onDemandPollEnabled) { createOnDemandPoll(u); } addODTempOption(label,commandVar1,u); cb.sendNotice('You have added the option "' + label + '" to the poll. You can add more poll options or use the command "/odstart" when ready to start running the poll.', u, appNoticeColor); } } } else { cb.sendNotice('Only moderators and broadcasters are able to use that command.', u, appNoticeColor); } break; } case '/odpollstart': case '/odstart': { if (isMod || isBC) { if (tokenPollToggle == 1) { cb.sendNotice('The Pre-configured Token Poll is enabled, an on-demand poll cannot be started at the same time.', u, appNoticeColor); } else if (!onDemandPollEnabled) { cb.sendNotice('An on-demand poll has not been created, you can use the command "/makepoll" to add each option, then start the poll.', u, appNoticeColor); } else if (onDemandPollRunning) { cb.sendNotice('The on-demand poll is already running.', u, appNoticeColor); } else if (tempODPollLabels.length < 2) { cb.sendNotice('At least two options are required in the poll, you can use the command "/makepoll" to add each option, then start the poll.', u, appNoticeColor); } else { startOnDemandPoll(u); } } else { cb.sendNotice('Only moderators and broadcasters are able to use that command.', u, appNoticeColor); } break; } case '/odoff': { if (isMod || isBC) { if (!onDemandPollEnabled) { cb.sendNotice('An on-demand poll has not been created or started.', u, appNoticeColor); } else { disableOnDemandPoll(u) } } else { cb.sendNotice('Only moderators and broadcasters are able to use that command.', u, appNoticeColor); } break; } case '/pollsettings': { if (isMod || isBC) { cb.sendNotice( 'Dump of all current settings for token poll:' + '\n******************** Token Poll ***********************' + '\nenableTokenPoll : ' + cb.settings.enableTokenPoll + '\npollTitle : ' + cb.settings.pollTitle + '\npollInterval : ' + cb.settings.pollInterval + '\npollMode : ' + cb.settings.pollMode + '\npollCount : ' + cb.settings.pollCount + '\npollMinimum : ' + cb.settings.pollMinimum + '\npollTxtColor : ' + cb.settings.pollTxtColor + '\npollCustTxtColor : ' + cb.settings.pollCustTxtColor + '\npollBgColor : ' + cb.settings.pollBgColor + '\npollCustBgColor : ' + cb.settings.pollCustBgColor + '\npollKeepalive : ' + cb.settings.pollKeepalive + '\npollModAdd : ' + cb.settings.pollModAdd + '\nstealPollAmount : ' + cb.settings.stealPollAmount + '\nbctext : ' + cb.settings.bctext + '\nminMsgForNotice : ' + cb.settings.minMsgForNotice + '\npollOptLabel1 : ' + cb.settings.pollOptLabel1 + '\npollOptTokens1 : ' + cb.settings.pollOptTokens1 + '\npollOptStart1 : ' + cb.settings.pollOptStart1 + '\npollOptLabel2 : ' + cb.settings.pollOptLabel2 + '\npollOptTokens2 : ' + cb.settings.pollOptTokens2 + '\npollOptStart2 : ' + cb.settings.pollOptStart2 + '\npollOptLabel3 : ' + cb.settings.pollOptLabel3 + '\npollOptTokens3 : ' + cb.settings.pollOptTokens3 + '\npollOptStart3 : ' + cb.settings.pollOptStart3 + '\npollOptLabel4 : ' + cb.settings.pollOptLabel4 + '\npollOptTokens4 : ' + cb.settings.pollOptTokens4 + '\npollOptStart4 : ' + cb.settings.pollOptStart4 + '\npollOptLabel5 : ' + cb.settings.pollOptLabel5 + '\npollOptTokens5 : ' + cb.settings.pollOptTokens5 + '\npollOptStart5 : ' + cb.settings.pollOptStart5 + '\npollOptLabel6 : ' + cb.settings.pollOptLabel6 + '\npollOptTokens6 : ' + cb.settings.pollOptTokens6 + '\npollOptStart6 : ' + cb.settings.pollOptStart6 + '\npollOptLabel7 : ' + cb.settings.pollOptLabel7 + '\npollOptTokens7 : ' + cb.settings.pollOptTokens7 + '\npollOptStart7 : ' + cb.settings.pollOptStart7 + '\npollOptLabel8 : ' + cb.settings.pollOptLabel8 + '\npollOptTokens8 : ' + cb.settings.pollOptTokens8 + '\npollOptStart8 : ' + cb.settings.pollOptStart8,u); } else { cb.sendNotice('Only moderators and broadcasters are able to use that command.', u, appNoticeColor); } break; } } } return msg; }); } // *********************************** Actions on user entering ************************************** { cb.onEnter(function(user) { // Variables var enterUser = user.user; var isModEnter = user.is_mod; // **** General Entry Message if (cb.settings.enableEntryMessage == 'Yes') { if (tokenPollToggle == 1) { var entryMessage = ''; entryMessage += '\n \u21E8 A Token Poll is running, you can tip to vote for your favorite in the poll. You can also type "/poll" to see the current poll choices and votes.'; if (isModEnter) { entryMessage += '\n \u21E8 Moderators: Type "/pollhelp" to see all of the poll related commands.'; } temptextcolor = checkTextColor('Dark Green'); tempbgcolor = checkBgColor('Cream'); cb.sendNotice(entryMessage, enterUser, tempbgcolor, temptextcolor, 'bold'); } } }); } // *********************************** Actions upon leaving ************************************** { cb.onLeave(function(user) { }); } // *********************************** Actions upon tipping ************************************** { cb.onTip(function (tip) { var tipAmount = Number.parseInt(tip.amount, 10); var tipUser = tip.from_user if (tokenPollToggle == 1 && pollRunning) { if (tipAmount == stealPollAmount) { stealPoll(tipUser); } else if (cbjs.arrayContains(pollArrayAmount,tipAmount)) { pollTip(tipAmount,1,tipUser); } } else if (onDemandPollRunning) { if (tipAmount == stealPollAmount) { stealODPoll(tipUser); } else if (cbjs.arrayContains(odpollArrayAmount,tipAmount)) { odpollTip(tipAmount,1,tipUser); } } }); } // *********************************** Initialize ************************************** { if (initialize == 0) { intromessage = '** Dorothy\'s Token Poll Version 1.0 was released on 12/4/2019.'; intromessage += '\nYou can type "/pollhelp" to display the command list summary.'; cb.sendNotice(intromessage, cb.room_slug, red); if (cb.settings.bctext != '' && cb.settings.bctext != null) { bctext = cb.settings.bctext; } else { bctext = 'The Broadcaster'; } if (cb.settings.enableTokenPoll == 'Yes') { setTokenPollToggle('on',cb.room_slug); } initialize = 1; } }
© Copyright Chaturbate 2011- 2024. All Rights Reserved.